滚动字幕


13

在进入混淆的Hello World之后,我认为共享基础代码可能会很有趣。但是为什么只显示代码,也让它成为高尔夫!

挑战

编写一个脚本,该脚本在终端上从右向左滚动字符串,并在左侧停留。

输入值

将字符串作为参数。

结果

将滚动字幕打印到STDOUT。最大宽度约50个字符。从显示0或1个字符开始。滚动时字母之间的一些空间。解决后停止(单词字符之间没有多余的空格)。慢速滚动,但不要太慢(每次迭代<1秒)。

使用arg运行脚本 'Hello World'

                                                   H

后来

                H    e    l    l    o         W    o

后来

H    e    l    l    o          W    o    r    l    d

后来

Hell    o         W    o    r    l    d

最后

Hello World

对于运行示例,请尝试“挑战世界”挑战中的代码。最终,我将发布我的信息。目前在Perl中为202个字符。现在有一些竞争对手,我已经在答案中发布了我的答案。

优胜者

我不希望这些限制是绝对的,这就是为什么我对它们有些含糊的原因。遵循我原著精神的最短脚本将获胜。

笔记

该游戏假设xterm环境。如果证明另一个环境有用,则将仅比较类似的环境,并且可以为每个环境声明一个独立的获胜者。

附录(2012年4月25日)

为了解决一些新出现的问题,我正在做出裁决。您的字符数必须包含以下代码:

  1. Flush STDOUT(看着您,Ruby)
  2. 实施sleep时延小于1秒(看着您的Perl)

可以在命令行切换到解释器时执行此操作,但是这些字符计入总数(无空白)。


我很担心终端行为的这种事情......一点点xtermvt102...?
dmckee ---前主持人小猫,

我假设使用xterm,但我认为这不太重要。也许我不明白您的担心?
乔尔·伯杰

这些技巧通常是依靠各种终端处理某些非打印字符的方式来产生的,并且终端在执行功能和产生效果的顺序方面有所不同。为了重现性,最好具有指定的终端环境。
dmckee ---前主持人小猫,

1
它会为你的权利是人的职位一个真正依赖一个不起眼的终端上,你没有一个模拟器,但OK简短的回答。
dmckee ---前主持人小猫,

好吧,我想我现在拥有了。感谢您的想法:-)
Joel Berger 2012年

Answers:


5

Python 2-146个字符

编辑:使其成为函数,而不是通过stdin输入。第一个参数是字符串,第二个参数是您想要的长度。因此调用将是f('Hello World', 50)。我也使它更加流畅。当每个角色“着陆”时,都会有一个尴尬的停顿

import os,time
def f(x,n):
 y=' '*n+'  '.join(x);z=0
 while y:w=y[0]==x[z];y=y[1+w:];z+=w;os.system('cls');print((x[:z]+y)[:n]);time.sleep(0.1)

旧的158个字符:

import os,time,sys
x=' '.join(sys.argv[1:])
y=' '*50+'  '.join(x)
z=0
while y:z+=y[0]==x[z];y=y[1:];os.system('cls');print((x[:z]+y)[:50]);time.sleep(0.1)

使用bash(至少在最近安装的MacOSX和CentOS中),用于清除终端屏幕的shell命令应为“ clear”而不是“ cls”。
Paolo

“CLS”的窗口,“清除”的OSX / Linux的版本,我想
开拓者

建议如何为每天不使用python的人启动程序,将有所帮助。启动python。粘贴代码,致电f("Hello World, 40)对我有用。
用户未知,

@用户我嗯。我确实在那儿放了电话吗?
开拓者2012年

4

Ruby,93 91 89个字符

u="\1";s=u*50+[*$*[0].chars]*(u*3);$><<s.tr(u," ")[0,50]+" \r"while s.sub!u,""*sleep(0.1)

要显示的文本必须作为命令行参数给出,例如

ruby marquee.rb "Hello World"

对于上面显示的示例。不幸的是,我无法在此处显示动画,因此您必须自己尝试代码。

先前版本:

s=" "*67+[*$*[0].chars]*"   ";(s.size*3/4).times{|j|s[j/3]='';$><<s[16,50]+" \r";sleep 0.1}

令人印象深刻的大小。但是,它不是很平稳,是我(目前正在使用一台低功耗机器)还是代码是如何工作的?
乔尔·伯杰

想通了,我必须进行设置STDOUT.sync=true;以使其自动溢出。Perl等价于$|++。多数民众赞成在一个额外的17个字符,但仍然远远低于我的。好吧,我不能让Ruby击败Perl!哈夫塔要去工作。好一个。
乔尔·伯杰

如果我打电话给ruby1.8 "Hello World"我,我并不惊讶,这是一个错误,它说:ruby1.8: No such file or directory -- Hello World (LoadError)
用户未知

@userunknown也许您也应该在其中放置源文件的路径:ruby foo.rb args;-)
Patrick Oscity 2012年

@padde:是的,我应该。不幸的是,霍华德编辑了他的帖子,但没有通知我他的更改。看看历史了解我的问题。
用户未知

3

C,94 83 80 173个字符

编辑:添加了大量代码,现在实现所有请求的功能。1e8可以调整常数以控制速度。在我的机器上,速度非常快。
某些字符肯定可以保存在这里。l可以是静态的(保存初始化),c可以成为指针(替换b+c)。

char b[99],c=1;
main(a,t,w,i,l)char**t;{
    for(l=0;b[l++]=*t[1]++;b[l++]=32);
    for(w=80;i--||
        printf("\033[F\033[K%*.*s\n",w-=l<a,a++,b,i=1e8)>l+6||
        b[++c]&&memmove(b+c-1,b+c,l););
}

旧版本(80个字符),具有部分功能:
通过更换保存几个字符的char**tint*t。在32位上正常工作(int**t将支持64位)。

main(i,t,w)
    int*t;
{
    for(w=80;i--||printf("\033[F\033[K%*s\n",w,t[1],i=1e8)*--w;);
}

2

K&R C- 431416个字符

高度尊重标准。使用ncurses,因此它在很大程度上应独立于终端。由于为保留字符串中的预期空白而进行了一些欺骗性操作,因此当文本碰到侧面时会有些口吃。

要使用的字符串应作为命令行的第一个参数传递(如果包含空格,则应将其转义,如果!如我的测试字符串(Hello, World!)那样包含,则应转义)。

#include <ncurses.h>
#include <unistd.h>
#define T usleep(1e5),S(l)
#define U mvprintw(23,0,"%s",l),refresh()
char l[63],*p,*q,r;
S(char*s){r=0;if(*s==32)q=s++;else{for(;*s-32||*(s+1)-32;s++); 
for(q=s;*s==32;s++);(s-q)&1?s--:usleep(1e5);}
for(r=0;*s;*q++=*s++){*s-32?r=1:0;}return r;}
main(int c,char**v){initscr();curs_set(0);for(c=0;c<62;l[c++]=32);
for(p=*++v;*p;){l[52]=*p++;U;T;U;T;U;T;}for(;T;U);getch();endwin();}

以更具可读性和评论性的形式:

#include <ncurses.h>
#include <unistd.h>

char l[63] /* take advantage of 0 initialization */,
  *p,*q, r;

/* Remove the first unwanted space. Unwanted means at the begining of
 * the line, all of even length blocks between non-spaces, and
 * all-bu-one of odd length blocks between non-spaces.
 *
 * Return true if the removed space occurs before a non-space character.
 */
S/*lide marquee*/(char*s){
  r=0; /* initialize the return value */
  if(*s==' '){
    q=s++;
  } else {
    /* Find the start of first block of contiguous spaces */
    for(;*s-' '||*(s+1)-' ';s++); 
    for(q=s;*s==' ';s++); /* q holds the start, s finds it's end */
    /* if this block is even length remove all, if odd, all but one */
    if( (s-q)%2 )s--; else usleep(1e5);
  }
  /* copy from s to q all the way to the end */
  for(r=0;*s;*q++=*s++){ 
    if(*s-' ')r=1; /* note if we pass a non-space */
  } 
  return r;
}

main(int c,char**v){
  initscr();curs_set(0); /* setup ncurses with invisible cursor */
  for(c=0;c<62;l[c++]=' '); /* initialize l */
  for(p=*++v;*p;){ /* load the message into the marque, skipping space */
    l[52]=*p++;
    mvprintw(23,0,"%s",l),
    refresh();
    usleep(1e5),
    S(l);
    usleep(1e5),
    S(l);
    usleep(1e5),
    S(l);
  }
  for(;usleep(1e5),S(l);mvprintw(23,0,"%s",l),refresh()); /* keeping sliding until we're done. */
  getch();
  endwin();
}

缩短的潜力很大,尤其是可以用if运算符代替。例如-- if((s-q)%2)s--;else usleep(1e5);> s-q&1?s--:usleep(1e5);(或s-=s-q&1||usleep(1e5);
ugoren 2012年

@ugoren:是的,我忘了' '用数值等效项代替。
dmckee ---前主持人小猫,2012年

一些更多的招数:替换x==32x-32(反转的意思,所以反向的if-else),或x<33(假设从来没有使用过0..31)。用您拥有的值(for(curs_set(c=0);...)进行初始化。*(s+1)-> s[1]。取下不需要的牙套(替换;,会有所帮助)。
ugoren

2

Perl 5.13.2、96

$_=join$;x4,$;x46,split//,pop;print substr(s/$;/ /gr,0,50)." \r"while$|=s/$;//+select'','','',.1

从@ Kevin Reid的答案中窃取了很多东西,尤其是/r更新的Perls中可用的技巧。

Perl,115岁

就像@ Joel Berger的答案一样,如果我可以使用它sleep 1并且变慢,或者通过-MTime::HiRes=sleep命令行启用enable ,它将变得更短sleep.1。否则,唯一的短暂睡眠的内置方法select'','','',.1就是相当长的时间。

$|=@_=(($")x45,map{($")x4,$_}split//,pop);for(0..$#_){print@_," \r";splice@_,($_-=45)<0?0:$_/4,1;select'','','',.1}

Perl,128个

$_=$"x9 .pop;s/./    $&/g;$.=-46;$\=" \r";while($|=/./g){print substr($_,0,50);pos=++$.<0?0:$./4;s/\G.//;select'','','',.1}print

Perl,133

$|=@_=split//,pop;for$i(reverse-$#_..50){for(@_){print$"x($j||$i),$_;($i+=$j=($i++>0)*4)>50&&last}print"    \r";$j=select'','','',.1}

是的,我在那条规则上咬我自己!我没有意识到其他的lang内置了一个usleep。
Joel Berger

一些建议,您可以在每个空格之后删除空格xmap并将其节省一些。
Joel Berger 2012年

1

的JavaScript 180 218个字符

生产版本:

function f(){i--&&(i>50?h=h.substr(1):h=h.replace(" ",i==16?"&nbsp;":""),document.body.innerHTML="<pre>"+h.substr(0,50)+"</pre>",setTimeout(f,99))}h=(new Array(50)).join(" ")+"HelloWorld".split("").join("   "),i=80,f()

非高尔夫版本:

h=new Array(50).join(" ")+("HelloWorld".split("").join("   "));
i=80;

function f(){
        if(i--){
            if(i>50){
                h=h.substr(1);
            }else{
                h=h.replace(" ",(i==16)?"&nbsp;":"");
            }
            document.body.innerHTML="<pre>"+h.substr(0,50)+"</pre>";
            setTimeout(f,99);
        }
}
f();​

这是一个jsFiddle演示

注意:如果您尝试重现它,请确保代码在主体下方


我无法从演示中看出来,它是“堆叠”在左侧,还是简单地放在左侧然后显示最终字符串?如果不确定,霍华德绝对可以工作。
乔尔·伯杰

@ JoelBerger,hello world在每个字母之间有4个空格,当h是第一个字符时,将删除这些空格。这个演示速度较慢jsfiddle.net/fYvg7/1
ajax333221 2012年

快结束了,但是您应该单独删除每个空格。
乔尔·伯杰

@JoelBerger固定
ajax333221 2012年

好吧,我讨厌a,但是还有另一个问题:您的字母以所有字母开头,而不是在右边一一输入。
Joel Berger 2012年

1

Perl 5.13.2,115个字符

$_=$"x9 .pop=~y/ /\0/r;s/./    $&/g;print(y/\0/ /r=~/(.{50})/,"\r"),select$.,$.,$.,.02while$|=s/ (\S)/$1 /g;print$/
  • 警告干净。
  • 可以通过减少字符之间的间距或初始空格来进行压缩。
  • 由于使用,需要Perl 5.13.2或更高版本/r
  • 因为POSIX argv不是NUL干净的,所以用NUL替换保留空间是明确的。但是,循环替换将把其他任何空格都变成空(最终)。

学分:


我喜欢r国旗,这是自该语言以来的最佳补充state
乔尔·伯格

1

打击234

w=$1
p(){
i=$1
s=$2
p=$((50+s*3-i))
((p<s+1)) && p=$((s+1));
((p<50)) && echo -en "[20;"${p}H$3"  ";
}
clear
for i in {0..99}
do
for s in $(seq 0 ${#w})
do
p $i $s ${w:s:1} 
done
sleep .1
echo -en "[20;1H  "
done
echo -en "\b\b$w\n"

用法:

./marquee.sh "Hello, fine marquee world"

松开

#!/bin/bash
w=$1
p(){
    #si String index
    it=$1
    #it=iteration
    si=$2
    pos=$((50+(si*3)-it))
    ((pos<si+1 )) && pos=$((si+1));
    ((pos<50)) && echo -en "[20;"${pos}H$3"  ";
}
clear
for it in {0..99}
do
    for si in $(seq 0 ${#w})
    do
        p $it $si ${w:si:1} 
    done
    sleep .1
    echo -en "[20;1H   "
done
echo -en "[22;1H"

1

R,319个字符

遵循@Blazer示例的原理(d是秒数的延迟):

f=function(x,n=50,d=0.2){
    s=strsplit(x,"")[[1]];i=1;l=length
    while (i<(n+l(s)-1)){
        if(i<=l(s))cat(rep(" ", n-i),s[1:i])
        else if((i<=n)&&(i>l(s)))cat(rep(" ", n-i),s[1:l(s)])
        else cat(paste(s[1:(i-n+1)],collapse=""),s[(i-n+2):l(s)])
        Sys.sleep(d);system("clear");i=i+1
    }
    cat(paste(s[1:l(s)],collapse=""))
}

用法:

f("Hello World",n=20,d=0.2)

1

Perl的144 133

$|=@s=(($")x50,map{$_,($")x4}@i=split//,pop);{$n=0;$s[$n]ne$_?last:$n++for@i;splice@s,$n,1;print"\r",@s[0..50];sleep.1;$n!=@i&&redo}

为了获得<1s的睡眠,尽管您需要以以下方式运行:

perl -MTime::HiRes=sleep scriptname 'string to print'

因为我不会宣布自己是赢家,所以我不会就是否有价值而争论自己(但我真的不能让Ruby赢得胜利;-))


还有4个并且适合推文:D
ajax333221 2012年

4个字符就在这里:s/' '/$"/gs/shift/pop/
ephemient

是的,我已经删除了这些内容,并包括了这些内容push。我只是还没有发布。
乔尔·伯杰

0

145

不能完全满足要求,因为最后一行将删除原始输入字符串中的所有空格。

{c:2_'((!)(#)a)_'a:((l:3*(#)x)#" "),\(1_(,/)b,'x,'b:" ");{(-1 x;);system"sleep ",($)y}'[-1_c,(l-1)$d(!:)[d]except\(&)(^)d:((!)(#)q)!q:last c;y];}

它需要两个参数,输入字符串和滚动速度

q){c:2_'((!)(#)a)_'a:((l:3*(#)x)#" "),\(1_(,/)b,'x,'b:" ");{(-1 x;);system"sleep ",($)y}'[-1_c,(l-1)$d(!:)[d]except\(&)(^)d:((!)(#)q)!q:last c;y];}["hello";0.05]
             h
            h
           h
          h  e
         h  e
        h  e
       h  e  l
      h  e  l
     h  e  l
    h  e  l  l
   h  e  l  l
  h  e  l  l
 h  e  l  l  o
h  e  l  l  o
h e  l  l  o
he  l  l  o
he l  l  o
hel  l  o
hel l  o
hell  o
hell o
hello

不幸的是,这很重要。我知道,没有它,Perl脚本可能会变得很小。
Joel Berger 2012年

0

PowerShell,135

不太打高尔夫,可能是一个可怕的方法,但我生病了,无法真正思考...

for($x="`r"+' '*50;$y-ne$x){$y=$x
write-host($x=$x-replace' ([^ ])','$1 ')-n
if(!($t++%5)){$x=$x-replace'.$',"$args"[$i++]}sleep -m 99}

0

J(116)

s(echo@((50#LF)&,)@([[i.@]&2e7)@(50&{.)@;@:(([,~#&' '@])&.>))"1([-=&0@/:@\:@:~:&0)^:(i.>:+/k)k=.50,3#~<:#s=.>2{ARGV

在命令行上获取输入字符串,即 jconsole marquee.ijs 'Hello, world!'

如果不需要清除屏幕,即输出如下:

H  e  l  l  o
H e  l  l  o
He  l  l  o
He l  l  o
...

允许,它将短12个字符。

说明:

  • s.=>2{ARGV:从命令行获取字符串
  • k.=50,3#~<:#s:每个字符前添加的空白起始数量,第一个字符前50个,其他所有字符前的3个。(给出一个数组,“ 50 3 3 3 ...”)
  • ([-=&0@/:@\:@~:&0):给定一个数组,递减数组中的第一个非零项
  • ^:(i.>:+/k):此函数应用了N次,其中N为0直至所添加空白的总和。(给出一个矩阵:50 3 3 3; 49 3 3 3; 48 3 3 3; ... 0 0 0 1; 0 0 0 0)
  • "1:在矩阵的每一行上运行以下函数
  • ;@:(([,~#&' '@])@.>):在字符串中的每个字符之前添加给定数量的空格
  • (50&{.):采用字符串的前50个字符
  • ([[i.@]&2e7):一个函数,它生成从0到2 * 10 ^ 7的列表,然后将其丢弃。这大约需要我机器上三分之一的时间,这会导致延迟。
  • ((50#LF)&,):在字符串前添加50行换行符,以清除屏幕
  • echo:输出字符串
  • s (...):将字符串作为函数的左参数

0

APL(70)

{⎕SM∘←1,⍨1,⍨,/D{⍺,⍨⍵⍴⍕⍬}¨P←⍵-{⍵×~×⍺}\×⍵⊣⎕DL÷8⋄0∨.≠P:∇P}1↓⎕SD,1↓3⍴⍨⍴D←⍞

从键盘获取输入,输出在⎕SM窗口中(如果您有基于文本的APL,它将是终端)。如果您确实希望将窗口大小设为50,则会自动检测到窗口大小,将更1↓⎕SD改为50

说明:

  • 1↓⎕SD,1↓3⍴⍨⍴D←⍞:读取字符串并存储在中D。生成一个向量,该向量描述每个字符之前要添加多少空格,即第一个字符(1↓⎕SD)之前的屏幕宽度,其他字符()之前的3 1↓3⍴⍨⍴D

  • ⎕DL÷8:等待1/8秒

  • P←⍵-{⍵×~×⍺}\×⍵:在右参数的向量中,从最左边的非零项中减去1,然后将新向量存储在P中。
  • ,/D{⍺,⍨⍵⍴⍕⍬}¨P:对于D中的每个字符,请在P中给定空白量。
  • ⎕SM∘←1,⍨1,⍨:显示在屏幕上的第一行的最左列
  • 0∨.≠P:∇P:如果P中存在一个非零元素,请重复P。

0

PowerShell 129字节

for($x=' '*52+(($args|% t*y)-join' '*4);$x-match'  '){write-host "`r$(-join($x=$x-replace'(?<!  .*)  ')[0..50])  "-n
sleep -m 99}

在线尝试!

Joey的脚本相比,此脚本不会从参数中删除空格。

TIO无法正确显示输出。使用Powershell控制台,您可以获得滚动字幕。


0

05AB1E,42 个字节

ð¶:S3úJ46ú[D50£¶ð:D?IQ#ðõ.;“…¢('\r')“.eт.W

在线尝试(不睡觉)。注意:我没有在本地安装05AB1E,所以我不能100%确定该\r技巧是否有效(但是理论上应该可行)。在TIO中,\r它们被解释为换行符。同样,TIO使用旧版本,因为.e在新TIO版本中已禁用(但是旧版本和05AB1E的程序都相同)。

说明:

ð¶:            # Replace all spaces in the (implicit) input-string with newlines
   S           # Split the string to a list of characters
    3ú         # Pad each character with 3 leading spaces
      J        # Join the characters together again
       46ú     # And pad the entire string with an additional 46 leading spaces
[              # Now start an infinite loop:
 D             #  Duplicate the string
  50£          #  And leave only the first 50 characters of this copy as substring
     ¶ð:       #  Replace the newlines back to spaces
        D?     #  Duplicate the string, and print it without trailing newline
 IQ            #  If the current string is equal to the input:
   #           #   Stop the infinite loop
 ðõ.;          #  Replace the first space with an empty string to remove it
 “…¢('\r')“    #  Push dictionary string "print('\r')"
           .e  #  Evaluate it as Python code
 т.W           #  Sleep for 100 ms

见我这个05AB1E尖端(部分如何使用字典?理解为什么“…¢('\r')“"print('\r')"


0

Python,139个字节

import os;P='\n'
def f(x,w):
 v=k=P*w+P.join(x);o=str.replace
 while v!=x:os.system('sleep 1;clear');k=o(k,P,'',1);v=o(k,P,' ');print v[:w]

必须致电f('Hello World', 50)才能开始。

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.