让我成为滚动字幕


15

介绍

还记得咆哮的80年代吗?我的意思是,就像30年前一样?没有手机,没有互联网,没有自动取款机,没有荧光的衣服(那是什么?!),还有滚动的马其布的!不不不!带LED灯的不是在线的,而是真实的。

滚动字幕

由于我怀旧,我希望您创建一个滚动字幕。

挑战

创建一个程序,您可以在其中输入一个单行字符串。您的程序需要创建一个80个字符的滚动字幕,并在必要时重复该文本。

规则

  • 用户必须能够在程序中输入字符串作为输入。该字符串可以是命令行参数,也可以是运行程序时输入的字符串。
  • 您的程序必须连续打印正好80个(可见)字符的字符串。
  • 字符串必须每0.1秒更新一次(或多或少;我不会定时),每次迭代时将字符向左移动一个位置。
  • 字符串“旋转”。在用户提供的字符串的末尾,必须显示该字符串的另一个实例。
  • 您的程序必须在一行中打印输出,没有换行(使用'\ r'而不是'\ n')
  • 您的程序必须无限运行,直到用户中断。
  • 这是一个代码高尔夫,因此以字节为单位的最短代码获胜。
  • 有10%的奖金(四舍五入到下一个整数),用于在红色印刷在黑色的背景。
  • 有标准漏洞。

Python 2.7中的参考实现

该程序不是高尔夫运动,但它提供了参考实现(因此提供了大小上限)。

import time,sys
s=raw_input()*99
while 1:
    for i in range(80):
        print s[i:i+80]+'\r',
        sys.stdout.flush()
        time.sleep(0.1)

@ mbomb007类似,但不相同。同样这个问题看起来像它(好灵感),但它是在几个方面有所不同,我想。另外,我发现分数(代码长度)也很令人失望。我真的认为我们可以做得更好!
agtoever

也许作为代码高尔夫+人气竞赛?
SuperJedi224

我们是否必须精确地等待100毫秒?
丹尼斯

1
@丹尼斯,或多或少。如果将其设置为99可以保存一个字符,可以。假设其他指令的执行将花费0.01秒。:-)
agtoever 2015年

1
如果输入字符串超过80个字符,该怎么办?您的参考实现,我的回答,得到S [80:160],然后跳回S [0 ..]他们从来不打印长字符串的结尾,例如输入1 2 3 4 5 6 7 8 9 10 11 ... 300切断后约56
TessellatingHeckler

Answers:


4

CJam,31个字节

l80*{Dco_80<o(+es99+{es1$<}g;}h

恰好等待100毫秒。

这仅适用于官方Java解释器,因为在线解释器仅在退出程序后显示输出。

黑色背景上的红色文本可能以40(或39)字节为单位,得分为36:

0000000: 6c 38 30 2a 7b 22 0d 1b 5b 33 31 3b 34 30 6d 22 6f 5f  l80*{"..[31;40m"o_
0000012: 38 30 3c 6f 28 2b 65 73 39 39 2b 7b 65 73 31 24 3c 7d  80<o(+es99+{es1$<}
0000024: 67 3b 7d 68                                            g;}h

怎么运行的

l80*                             Read a line and repeat it 80 times.
    {                        }h  Do:
     Dco                           Print the character with code point 13.
        _80<o                      Print the first 80 characters of the string.
             (+                    Rotate the string one charcter to the left.
               es99+               Push the current time (ms) plus 99.
                    {     }g       Do:
                     es1$<           Compare the current time with the sum.
                                     Repeat the loop if 99 or less ms have passed.
                            ;      Discard the time stamp.
                                 Repeat the loop.

我怀疑他们不会比这短。恭喜你!
2015年

似乎tlike将;在解释错位
法师

@Ven固定,谢谢!
丹尼斯,

9

PowerShell,11811311210810210199 96-10%= 86

$s=(Read-Host)*180;for(){Write-Host($s.substring(($i=++$i%80),80)+"`r")-N -F R -B 0;sleep -m 99}

需要注意的是,它现在从第二个字符开始第一个循环。规则不必说它必须从字符串的开头开始,并且第一个包含在整个字符串中,所以我觉得很好。我将以某种方式将其获取到100个字符-编辑:感谢@ConnorLSW进行的编辑,以使其低于100个字符。

使用说明

  1. 运行PowerShell(普通控制台,在PowerShell ISE中不起作用)
  2. 将单行版本粘贴到PoSH中,按Enter
  3. 输入消息,然后按Enter
  4. Ctrl-C中断

输出量

PowerShell marquee example output

笔记

更具可读性的版本,其中的变量名和参数有点填充:

$test = (Read-Host) * 180
for () {
    Write-Host ($text.substring(($i=++$i%80), 80)+"`r") -NoNewLine -ForegroundColor Red -BackgroundColor Black
    sleep -Miliseconds 99
}
  • 参数只需要足够长就可以唯一,因此-F R例如可以设置Red ForegroundColor足够唯一。
  • 与“蓝色”相比,“黑色”必须为“黑色”才能唯一,但-B 0将其设置为颜色Enum值0(解释为黑色)。

另一种,更“正确”的字幕:

该参考代码不能很好地处理超过80个字符的字符串,跳过消息中超过160个字符的任何内容,并且每隔99 * len(string)个字符就会发生故障复位。例如,如果符号宽度为5个字符长,它将执行以下操作:

   here is my long test input
 0 |here |            
 1  |ere i|          ^^^^ never shown
 2   |re is|
 3    |e is |
 4     | is m|
 0 |here |
 1  |ere i|
    ...

该版本以文本长度而不是符号宽度为模数索引,因此它贯穿整个字符串。106-10%= 95个字符。

$l=($s=Read-Host).Length;for(){Write-Host(($s*160).substring(($i=++$i%$l),80)+"`r")-N -F R -B 0;sleep -m 99}

替代方案:像问题中的.gif那样循环签名,即10-10%= 106

因为看起来更好。

$s=' '*80+(read-host)+' '*80;for(){write-host($s.Substring(($i=++$i%($s.length-80)),80)+"`r")-N -F R -B 0;sleep -m 99}

Alternative sign example animation


1
我知道这个答案很老,但是这个问题现在在首页上- Bla0- Write-Host会将数字解释为颜色。
colsw

@ConnorLSW谢谢,您的价格低于100个字符!我不知道为什么我在一年前错过了您的评论(!),有人刚刚投票支持我,然后我回来看看它是什么。
TessellatingHeckler

不用担心,我想你也可以改变while(1),以for()节省一些字节:)
colsw

@ConnorLSW,所以您也可以这样做。(我可能在大多数高尔夫比赛中都能做到这一点,这不是我通常认为的事情)。
TessellatingHeckler

使用时for(),您可以再保存一个字节,$s=(Read-Host)*180;for(){以将其更改为for($s=(Read-Host)*180){
Clijsters

6

Matlab,76个字节

我认为这很不错,您可以将向量作为数组索引。这将返回对应数组条目的向量,这使得与长度无关地附加给定字符串非常容易。

a=input('');k=1:80;while 1;pause(.1);clc;k=mod(k+1,nnz(a));disp(a(k+1));end

结果:

enter image description here


不错的把戏clc。你忘了添加's'input
路易斯Mendo

你是什​​么意思 正如我在(R2010b)所获得的Matlab版本中一样,它工作得很好。
瑕疵

1
现在,您需要输入带引号的字符串。要直接输入字符串内容(无qoutes),您需要a=input('','s')
Luis

现在,我知道该功能了。由于规范不需要这样做,因此我认为可以要求使用'分隔字符串作为输入。许多语言都需要字符串定界符,否则它们会以句子(用空格分隔的单词)的形式将命令行参数解释为多个参数。
瑕疵

4

QBasic中,116个 113字节- 10(%)= 105 102

INPUT s$
COLOR 4
1CLS
FOR i=a TO a+79
?MID$(s$,i MOD LEN(s$)+1,1);
NEXT
?
a=a+1
t=TIMER+.1
2ON(TIMER<t)+2GOTO 2,1

Marquee demonstration

这是带有一些注释的格式化版本:

INPUT s$
COLOR 4   ' 4 is the color code for red (the background's already black)

1 CLS   ' CLear Screen (and mark this as line number 1)

' The variable a represents an offset from the beginning of the string
' As a numeric variable, it is 0 at the beginning of the program
FOR i = a TO a + 79
    ' Print i'th character mod string length (+ 1 because QBasic strings
    ' are 1-indexed)
    PRINT MID$(s$, i MOD LEN(s$) + 1, 1);
NEXT i
PRINT
a = a + 1

' Do a busy-wait for .1 seconds
' (Unfortunately, QBasic's SLEEP command only takes integer values)
' Set t to the time we want to stop waiting, .1 seconds in the future
t = TIMER + .1
' We want to stay on line number 2 while TIMER < t; once that condition is
' no longer true, we want to goto the top of the outer loop (line number 1)
' Since true is -1 and false is 0 in QBasic, adding 2 to the conditional
' gives 1 for true and 2 for false; we can pass these values to the
' ON ... GOTO statement to branch conditionally
2 ON (TIMER < t) + 2 GOTO 2, 1

一些注意事项:

  • 我不知道为什么PRINT在后FOR循环是必要的。CLS应该每次将光标重置到左上角。但是,至少在QB64上,如果我不添加其他功能PRINT,则选框最终出现在第二行而不是第一行。如果有人在DosBox上设置了QBasic或类似的东西,我很想知道那里是否发生了相同的事情,或者它是否是QB64错误。
  • 该代码有一个小故障,因为它依赖于TIMER(自午夜以来的秒数)延迟。如果代码在午夜运行,则选框将被卡住,因为TIMER它将重置为0并且始终小t于此时间。

我的母语!IIRC无论如何在QB 4.5中,在打印字符串的末尾使用分号表示PRINT语句不打印回车符。
bgStack15 '16

@ bgStack15我也是。:^ D这个问题不是真正的问题,PRINT而是CLS--after CLS,无论之前打印什么,下一条PRINT语句的输出应该为1,1; 但是相反,我遇到了输出为2,1的情况。
DLosc

4

Perl,99 98个字节(-10%= 89)

$|=@_=split('',pop);printf("\e[31m\r%.80s",join('',@_)x80)while select($a,$a,$a,.1)|push@_,shift@_

从命令行参数获取其输入。

perl marquee.pl "Welcome to Programming Puzzles & Code Golf "

3

,⌈(216 + 3)*0.9⌉= 198

+3个字节的解释器标记 d=1

c^w[Y=-1]{w[B!0]{>}t[X]<[X-79]w[X!0]{t[T-1]w[T=-1]{t[0]}<}vw[T=0]{^w[B!0]{t[B]^b[T]>v}<[X]^w[B!0]{t[B]vw[B!0]{>}b[T]<[X]^w[B=0]{>}b[0]>}v}}^w[1=1]{<[X-80]w[X!0]{<t[B]vb[T]^}w[B!0]{t[B]<b[T]>>}<[X]<t[B]w[B!0]{>}<b[T]}

这是一个非常可怕的成绩,但是考虑到用这种语言做任何事情有多困难,情况可能会更糟。这个答案的比例(用于获取红色文本的字节)与(具有红色文本的奖励)的比例非常好,整个输出变成红色,只有c在开始时!

两次滴答之间的时间取决于输入字符串的长度,但大约为0.1秒。

顺便说一句,由于解释器很糟糕,该程序的输出看起来像是垃圾。每毫秒,它将清除终端并重新绘制所有内容,因此它会变得非常闪烁。

有评论:

c           # Change paint colour to red

^w[Y=-1]{   # While Y=-1 (arbitrary condition we can break later)

    w[B!0]{>}   # Go to end of input

    t[X]        # Save length of input in T

    # SET T TO MAX(T-79, 0)

    <[X-79]     # Go to (79, -1)

    w[X!0]{     # While X is not 0
        t[T-1]      # Subtract 1 from T
        w[T=-1]{    # If T is now negative
            t[0]        # Set it back to 0
        }
        <         # Move left (position doesn't matter except to end the loop eventually)
    }

    # DONE SETTING T TO MAX(T-79, 0)
    # If T == 0, the string needs to be doubled. Otherwise this part of the program is done

    v           # Move down to break the loop unless this is specifically undone
    w[T=0]{     # While T == 0
        ^w[B!0]{    # For each byte of input
            t[B]^b[T] # Copy it up 1 place
            >v        # Go to the next byte
        }
        <[X]^     # First byte of the copy
        w[B!0]{   # For each byte of the copy
            t[B]      # Save the byte's value
            vw[B!0]{>}# Go to the first empty spot after the original
            b[T]      # Write the saved value
            <[X]^w[B=0]{>} # Go back to the first byte of the copy
            b[0]>     # Erase it and go to the next one
        }
        v       # Back to Y=-1 to reset the loop from the very beginning
    }

}

# After ALL OF THAT nonsense, we're now at (0, 0) and the input string is guaranteed to be
# at least 80 characters long

^
w[1=1]{       # While 1=1 (should hold true until mathematics itself breaks down)
    <[X-80]        # Go to the 81st character
    w[X!0]{        # While X!=0
        <t[B]vb[T]^    # Go left and copy that character down
    }

    w[B!0]{      # For each byte in the string
        t[B]<b[T]>>  # Copy that byte left
    }

    <[X]<t[B]    # Go get the first value (copied to (-1, -1))
    w[B!0]{>}<b[T]# Bring it to the end of the string
}

3

Perl-120个字节(-10%= 108)

$|=1;$_=<>;chomp;for(;;){print "\e[31m",substr(" "x80 .$_,$p++,80)," \r";select($z,$z,$z,0.1);if($p>length()+80){$p=0}}

Perl marquee


2

Matlab,⌈188*.9⌉= 170

在Matlab R2014b或更高版本中有效。结果显示在图形窗口中。

h=text(.1,.1,repmat(' ',1,80),'fontn','courier','ba','k','co','r');set(1,'pos',[90 90 990 90]);axis off
s=input('','s');n=0;while 1
n=n+1;pause(.1)
h.String=s(mod((0:79)+n,numel(s))+1);end

在下面的示例中,以黑体字键入文本以实现更好的可视化(上面的代码未完成,因为它花费了一些字节)。还要注意,GIF动画的速度与所需的0.1秒暂停不对应,但是在运行程序所示的实际图中,时间是正确的。

enter image description here


2

SpecBAS,130字节(-10%= 117)

将原始字符串乘以使其等于或大于80个字符,然后将其精确地切成80。

TEXT 是SpecBAS中的命令,其工作方式与 PRINT(在此示例中)相同,但保存一个字符。

SCALE命令在代码中添加了一些额外的字符,但是使它看起来更像是字幕。

该程序一直运行,直到您按Esc键为止。

1 INPUT s$: LET s$=s$*CEIL(80/LEN s$)
2 TEXT PAPER 0;INK 2;SCALE 1,2;AT 1,1;s$( TO 80)
3 LET s$=s$(2 TO)+s$(1): PAUSE 5: GO TO 2

enter image description here


2

Perl,63岁(70个字符-奖金的10%)

与其他解决方案相比,这并不是一个完全不同的解决方案,但是我浪费了时间,所以我想我也应该发布它!

$_=<>;s/
/ /;print"\x0d\x1b[91m",substr"$_"x80,$z++%y///c,80 until`sleep .1`

依靠Unix兼容的终端来进行ANSI代码和对coreutils'的调用sleep。上面的两个\x..字符实际上是一个文本换行符,并按照此十六进制转储符进行转义:

0000000: 245f 3d3c 3e3b 732f 0a2f 202f 3b70 7269  $_=<>;s/./ /;pri
0000010: 6e74 220d 1b5b 3931 6d22 2c73 7562 7374  nt"..[91m",subst
0000020: 7222 245f 2278 3830 2c24 7a2b 2b25 792f  r"$_"x80,$z++%y/
0000030: 2f2f 632c 3830 2075 6e74 696c 6073 6c65  //c,80 until`sle
0000040: 6570 202e 3160                           ep .1`

2

Ruby,79 76 75字节

t,i=gets.chop*81,0
loop{system'cls'
$><<t[(i=(i+1)%80)..i+79]
sleep 0.1}

我仍然不是红宝石专家,可能会打高尔夫球。

红色和黑色得分相同:

t,i=gets.chop*81,0
loop{system'cls&color 4'
$><<t[(i=(i+1)%80)..i+79]
sleep 0.1}

2

Perl,84个字节(-10%= 76)

$_=' 'x80 .pop;$|=print"\b \r\e[31m".substr$_,++$p% length,80until select$z,$z,$z,.1

这需要一个命令行参数,它是字幕中的文本。

说明:

  1. 在文本前添加80个空格并存储在 $_
  2. 打印退格键(\b)和空格()。这将从上一个打印中删除最后一个字符。然后打印回车和颜色。
  3. 从位置打印文本的80个字符 $p
  4. $p = ($p+1) % length of text
  5. 睡眠0.1秒

2

bash,121个字节

A=$(printf ' %.s' {1..80})$1
while :; do
printf "%s \r" "${A:((P++)):80}"
if [ $P == ${#A} ];then
 P=0
fi
sleep 0.1
done

1

Python 3,96个字节

import time;s=input()*80
while 1:print("\033[2J",end=s[:80],flush=1);s=s[1:]+s[0];time.sleep(.1)

这仅适用于支持ANSI转义序列的终端。如果您使用Windows,请尝试ansicon

flushPython 3中的关键字加油,所以我们不必打个昂贵的sys.stdout.flush()电话。


1

C,293个 269字节

(增加了换行符以提高可读性)

这从EOF终止的标准输入中获取输入。因此最好输入一个字符串,一个换行符,然后输入EOF(例如Ctrl ^ D)。

#include<stdio.h>
#include<string.h>
#define Z '\0'
main(){int i=0,j;char m[80],o[80],n[2];
while(~(j=getchar())&&i<80)j-'\n'?m[i++]=j:0;m[i]=Z;
while(1){for(i=0;m[i]-Z;++i){strcpy(o,&m[i]);
for(j=0;j<i;)*n=m[j++],n[1]=Z,strcat(o,n);
printf("\x1b[40;31m%s\x1b[0m\r",o);}}}

取消高尔夫:

#include <stdio.h>
#include <string.h>
#define ANSI_COLOR_SET "\x1b[40;31m"
#define ANSI_COLOR_RESET "\x1b[0m"

int main(void)
{
  int i, j, c;
  char msg[80], out[80], next[2];

  for (i = 0; (c = getchar()) != EOF && i < 80; ++i) {
    if (c != '\n') {
      msg[i] = c;
    }
  }
  msg[i - 1] = '\0';

  while (1) {
    for (i = 0; msg[i] != '\0'; ++i) {
      strcpy(out, &msg[i]);
      for (j = 0; j < i; ++j) {
        next[0] = msg[j];
        next[1] = '\0';
        strcat(out, next);
      }
      printf(ANSI_COLOR_SET "%s\r" ANSI_COLOR_RESET, out);
    }
  }
  return(0);
}

1

SmileBASIC BIG,79个字节

COLOR 3INPUT S$@L
CLS
FOR I=0TO 79?S$[(I+O)MOD LEN(S$)];
NEXT
WAIT 6O=O+1GOTO@L

当我意识到它必须一次滚动1个完整字符时,我几乎完成了一个不错的图形解决方案。


1

果冻20 19 18字节

  • -1通过替换的第一字节80(= 256),因为它必须通过相乘至少 80
  • 通过将无限循环更改为Çß(from Ç1¿)-1个字节。

ẋ⁹ḣ80ṙ1;”ÆṄœS.1
Çß

@Dennis在这里回答的一些技巧。果冻比挑战更新颖,但并非专门针对挑战而量身定制。欢迎提出改进建议!如果您的控制台是utf-8,请运行export LC_ALL=en_US或尝试类似操作。

https://gyazo.com/f3594391a6b4d459a9d30bd47cf598b1

说明

ẋ⁹ḣ80ṙ1;”ÆṄœS.1         Monadic helper link - Argument: s
ẋ⁹                      Repeat s 256 times.
  ḣ80                   Head. Set {output} to first 80 characters from repeated s.
     ṙ1                 Rotate. Rotates {output} one character to the left.
       ;Ӯ              Concatenate character 0D, the carriage return, to {output}.
          Ṅ             Print and return {output}.
           œS.1         Wait 0.1 seconds before returning {output} from the
                        helper link.

Çß                      Monadic main link - Argument: s
Ç                       Execute helper link with argument s. Replace s by
                        result of helper link.
 ß                      Execute this link with argument s (while true).

0

LOVE2D Lua,197-10%= 178字节

f=io.open("t.t"):read().."  "love.graphics.setColor(255,0,0)love.window.setMode(640,14)function love.draw()s=""for i=1,80 do n=i+os.clock()s=s..f:sub(n%#f,n%#f) end love.graphics.print(s,0,0)end

要求输入位于根目录中名为“ tt”的文件中,因此将3个额外字节添加到了乐谱中。

功能上真正的基础,只是在80次迭代的for循环中,将字符附加到i的索引处加上当前时间(以秒为单位),该时间由当前字符串的长度调制,从而得到重复的80个字符长的输入字符串,该字符串向左移动随着时间的推移。

我用LOVE2D来发笑。


0

Sinclair ZX81 / Timex TS1000 / 1500 BASIC, 110字节 182字节(用于列表)

1 LET A$="I LIKE TO SCROLL IT... HELLO MUM, BY DONKEYSOFT... THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG... STILL SCROLLING... "
2 PRINT AT 0,0;A$(1 TO 80)
3 LET A$=A$(2 TO )+A$(1)
4 GOTO 3

它的工作方式是在第二行的屏幕位置0,0 打印该字符串的前32个 80个字符A$,然后从位置2到第3行的字符串结尾处处理该字符串(Sinclair ZX81 BASIC将从1而不是从0索引字符串) ),因此将第一个字符添加到末尾并将其传递回A$变量;然后有一个无条件循环回到第2行。


0

准将64,434字节

0 A$="I LIKE TO SCROLL IT... SAMPLE SCROLLY ROUTINE FOR CODE-GOLF MADE BY DONKEYS
1 A$=A$+"OFT MMXVII... HELLO MUM... SCROLLING IS FUN, INNIT? GREETZ TO ALL...
2 POKE53280,6:PRINT"{CLEAR}";
3 PRINTLEFT$(A$,40)"{HOME}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}"MID$(A$,41,40)"{HOME}";
4 FORI=0TO99:NEXT:A$=RIGHT$(A$,142)+LEFT$(A$,1):GOTO3

因为这需要显示80个字符,而C64默认情况下只有40个字符,所以滚动区域的40个字符被打印在屏幕区域的顶行,而其他40个字符则被打印在屏幕底部附近。

为了弄清楚the {HOME}和其他符号转换为PETSCII的含义,这是我的模拟器截取的屏幕截图:

Commodore 64 scrolly over two lines

当我安装了CBM PRG Studio时(或当我不在工作时间吃午饭时),我将进行完整的高尔夫版本。


0

Ruby,79 77个字符

->(s){t=0;loop{system("clear");puts (s*80)[t..(80+t)];t=(t+1)%80;sleep(0.1)}}

0

PHP,136字节

<?php
$s="\e[0;31;40m".substr(str_repeat($argv[1],160),0,160);
while(true){for($i=0;$i<=80;$i++){usleep(100000);echo substr($s,$i)."\r";}}die;
  • 调用它php -f marquee.php hello\ world以选框“ hello world”字符串。
  • 由于某种原因,我必须为初始字符串输入160个字符,否则输出将类似于hello worlddddddddddddddddddddddddddddddddddddddd,但它只能循环显示80个字符-我希望这仍然有用。

https://gyazo.com/4c433abf04d71ca7ebb63a0889ca705d

这是漫长的一天,可能我可以做些改进


0

PHP,85字节

for(;;usleep(1e5))echo substr(str_repeat($s=$argv[1],80),$i=++$i%strlen($s),80),"\r";

从第一个命令行参数获取输入;与-nr

开始滚动第二个字符。添加一个字节的第一个字符开始:
替换=++$i%%=;;;;$i++,

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.