スクロールマーキー


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

実行例については、「Hello World」チャレンジのコードを試してください。最終的に私は私のものを投稿します。現在、Perlでは202文字です。競合他社がいくつかあるので、回答に私の投稿を掲載しました。

勝者

制限を絶対にしたくないので、少しあいまいにしておきました。私のオリジナルの精神に従う最短のスクリプトが勝ちます。

ノート

このゲームは xterm環境をます。別の環境が有用であることが判明した場合、同様の環境のみが比較され、それぞれに対して個別の勝者が宣言される場合があります。

補遺(2012年4月25日)

いくつかの新進の問題に対処するために、私は裁定を下しています。文字数には、以下に必要なコードを含める必要があります。

  1. STDOUTのフラッシュ(Rubyを見る)
  2. sleep1秒未満の遅延で実装します(Perlを見てください)

これは、コマンドラインがインタープリターに切り替わるときに実行できますが、これらの文字は合計に含まれます(空白を囲む文字は含まれません)。


私は...この種のもののために、端末の行動を懸念少しですかxtermvt102...?
dmckee ---元モデレーター子猫

私はxtermを想定していますが、それほど重要ではないと思います。おそらく私はあなたの懸念を理解していませんか?
ジョエルバーガー

これらのトリックは、通常、さまざまな端末が非印刷文字の一部を処理する方法に依存することによって生成され、端末は何ができるか、どのシーケンスがエフェクトを生成するかが異なります。再現性を確保するために、指定された端末環境を用意することをお勧めします。
dmckee ---元モデレーター子猫

1
誰かがエミュレーターを持っていないあいまいな端末に依存する本当に短い答えを投稿することはあなたに正しいサービスを提供しますが、OKです。
dmckee ---元モデレーター子猫

わかった 考えてくれてありがとう:
ジョエルベルガー

回答:


5

Python 2-146文字

編集:標準入力を介した入力の代わりに関数にしました。最初の引数は文字列で、2番目の引数は必要な長さです。したがって、呼び出しはになります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)

(少なくとも最近のMacOSXおよびCentOSのインストールでは)bashを使用して、ターミナル画面をクリアするために使用されるシェルコマンドは「cls」ではなく「clear」である必要があります。
パオロ

Windowsの場合は「cls」、OSX / Linuxビルドの場合は「clear」
ブレイザー

毎日Pythonを扱っていない人のためにプログラムを開始する方法についてのアドバイスが役立ちます。Pythonを起動します。コードを貼り付けて、電話f("Hello World, 40)をかけてください。
ユーザー不明

@ユーザー 私はそこに呼び出しを入れましたか?
ブレザー

4

ルビー、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 equivは$|++です。それは追加の17文字ですが、それでも私のものよりかなり下です。さて、RubyがPerlを打ち負かすことはできません!仕事をするつもりだ。良いですね。
ジョエルバーガー

私が呼び出す場合ruby1.8 "Hello World"、私はない正確に私の驚きに、取得、エラーが言って:ruby1.8: No such file or directory -- Hello World (LoadError)
ユーザー不明

@userunknown多分あなたも、そこにあるソースファイルへのパスを置く必要がありますruby foo.rb args;-)
パトリックOscity

@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**t64ビットをサポートします)。

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

@ugoren:うん、私は' 'sを同等の数値に置き換えるのを忘れていました。
dmckee ---元モデレーター子猫

さらにいくつかのトリック:交換するx==32x-32(あれば、そうでないので、逆に、意味が反転)、またはで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新しいPerlで利用できるトリックから多くを盗みます。

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}

ええ、私は自分自身のルールで自分自身を噛みました!他の言語にはusleepが組み込まれていることに気づきませんでした。
ジョエルバーガー

いくつかの提案は、それぞれの後にスペースを削除することができx、ブロック形式はmapいくつかを節約します。
ジョエルバーガー

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

これは近いですが、各スペースを個別に削除する必要があります。
ジョエルバーガー

@JoelBerger修正
-ajax333221

さて、私は口うるさいのは嫌いですが、もう1つの問題があります。あなたの問題は、右側に1つずつ入力するのではなく、すべての文字が表示されることから始まります。
ジョエルバーガー

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

Perl144 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

ここの4文字:s/' '/$"/gおよびs/shift/pop/
-ephemient

ええ、私はそれらを含め、push声明を削除しました。まだ投稿していません。
ジョエルバーガー

0

Q、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];}

入力文字列とスクロール速度の2つの引数を取ります

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スクリプトは、それなしでは非常に小さくなります。
ジョエルバーガー

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までのリストを生成し、それを破棄する関数。これは私のマシンで約3分の1秒かかり、これが遅延の原因となります。
  • ((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

05AB1E、42 バイト

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

オンラインで(スリープなしで)試してください。注:05AB1Eをローカルにインストールしていないため、\rトリックが機能するかどうかは100%わかりません(ただし、理論上は機能するはずです)。TIO \rでは、代わりに改行として解釈されます。また、.e新しいTIOバージョンでは無効になっているため、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)開始するには呼び出す必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.