ジェイコブのASCIIラダーをアニメートする


23

子供の科学博物館でジェイコブのはしごを見たことがあるかもしれません。外観がよくわからない場合は、ウィキメディアコモンズにいくつかの画像とビデオの例があります。今日の課題は、電気機器のアニメーション化されたASCIIバージョンを作成することです。最終的には、次のようになります。

はしごGIF


ラダー構造

以下は、高さ(H)が6のはしごの基本形状です。

6   \            /
5    \          /
4     \        /
3      \      /
2       \    /
1        \  /
0         ¯¯

左側の数字は、この例の行番号を示しているだけであり、出力に含めるべきではありません。特定の行を番号(R)で参照します。行0が一番下¯¯です。行1からHはそれぞれ4つの部分で構成されています。

  • スペース(U + 0020)が(H - R)回繰り返された
  • バックスラッシュ\(U + 005C)
  • スペース(U + 0020)が(2 * R)回繰り返された
  • スラッシュ/(U + 002F)

行0は、両方のスラッシュがマクロン¯(U + 00AF)に置き換えられることを除いて同一です。各行の末尾またはラダーの下の末尾の空白は問題ありません。先頭の空白はそうではありません。


アーク建設

はしごを作成したら、左側と右側の間に円弧を作成できます。1つの円弧は完全に行内にあり、先頭\と末尾の間のスペースを置き換えます/。したがって、行2のアークには4文字、行3には6というように続きます。各アークは、次のルールを使用して構成されます。

  • 使用できる文字は_/¯\(U + 005F、U + 002F、U + 00AF、U + 005C)のみです
  • 滑らかな外観を確保するために、いずれ¯かまたは/後には、¯または\
  • 滑らかな外観を確保するために、いずれ_かまたは\後には、_または/
  • 上記の2つのルールは、ラダーのエッジにも適用されます
  • 上記の3つのルールは、アークの最初の文字が_orで/あり、最後の文字が_orでなければならないことを意味します\\¯\_//両端で無効\_/¯\/ですが、OKです)
  • 特定のポイントで発生する可能性のある文字ごとに、ゼロ以外のチャンスがなければなりません
  • 各アークは他のすべてのアークから独立しています

アニメーション

単一のアークの寿命は、行1で開始し、頂点に達するまで一度に1行ずつ「移動」することによって作成されます。IEでは、最初に行1でアークを生成し、次にスペースに戻し、行2でアークを生成します。表示するアークの数(N)を考慮して、次のガイドラインを使用して、その多くのアークの完全な寿命を一度に1つずつ表示します。

  • 一度に「生きている」アークは1つだけです。次のアークは、現在のアークがトップに到達してから消えるまで開始できません。
  • アークの寿命の各行は、正確に1つのフレームに対して表示される必要があります
  • 新しいアークを開始する前に、基本的なはしご(アークなし)だけのフレームが1つ必要です(最初のアークの前にオプション)
  • アニメーションは、N個のアークの寿命全体を表示する必要があります。N = 0の場合、停止するまでランダムアークを永久にアニメーション化する必要があります。
  • N > 0の場合、アニメーションを永久にループできますが、繰り返し同じ円弧のループである必要があります。(この投稿の上部にあるGIFの例はH = 6とN = 3ですが、永久にループします。)
  • アニメーションはインプレースで発生するはずです。つまり、各フレームは次のフレームを完全に上書きし、同じ場所にある必要があります。
  • 各フレームの長さは自由に設定できますが、人間が見ることができるようにします(つまり、常識に従ってください:0.01s / frameと30s / frameはどちらも受け入れられません)。

入出力

  • 入力および出力は、任意の標準形式にすることができます
  • GIFのエクスポート、画面へのテキストの書き込み、フレームごとに1つのファイルの出力、またはその他の妥当な手段
  • 標準的な抜け穴は禁止されています
  • はしごの高さHは正の整数になります
  • Nを示す弧の数は負でない整数になります
  • どちらもHNは、あなたが選択した任意の順序で入力(あなたの答えで順序を記載してください)として採用されています

勝利条件

これはので、最短のコードが優先されます。

サンドボックス


1
アークは中心で対称的に生成できますか?私はルールでそれに対する制限を見ることができません
デッドポッサム

コンソールに各フレームを順番に印刷できますか?
TFeld

@DeadPossum私はあなたが正しいと思っていましたが、それは非常に稲妻のようには見えませんが、実際には2つのルールの組み合わせによって許可されていません:the first character in the arc must be _ or / and the last character must be _ or \ There must be a non-zero chance for each allowable character to occur at a given point。対称にするためには、最初と最後の両方の文字が_毎回である必要があります/。つまり、どちらかまたは「\」が発生する可能性はゼロです。
エンジニアトースト

@TFeld各フレームが画面上の同じ場所に表示される限り、はい。これは、毎回コンソールをクリアする必要があることを意味します(または、可能であれば下にスクロールする必要があります)。
エンジニアトースト

2
マクロン要件は、QBasicが競合できないことを意味しますか?コードポイントがあるCP437を使用します。0xAF»
DLosc

回答:


5

パイソン2287の 271 270 276 275バイト

import time,random
r,n=input()
c=n*-~r or-r
while c:
 c-=1;L=[list(' '*i+'\\'+'  '*(r-i)+'/')for i in range(r)];x=c%-~r;time.sleep(1);y=x+1;exec"L[x][y]=random.choice('\xaf/\_'[L[x][y-1]in'\_'::2][y==2*r-x:]);y+=1;"*2*(r-x)
 for l in['']*99+L+[' '*r+'\xaf'*2]:print''.join(l)

オンラインでお試しください!

TIOの画面をクリアしませんが、コンソールで機能します。

実行中のGif:

ここに画像の説明を入力してください


少し卑劣ですが、print'\n'*99代わりに使用しos.system('cls')osインポートを失う可能性があります。TIOでは動作しませんが、WindowsとLinuxコンソールの両方で動作します。
エルペドロ

1
新しいアークが開始する前に、最初のアークのない基本的なはしご(アークのない)の1つのフレームがあるはずです(最初のアークの前にオプション)
wastl

5
マクロン(U + 00AF)の代わりにハイフン(U + 002D)を使用していると思います。修正するためにバイト数が増えるとは思わない。また、@ wastlが指摘したように、アーク間に空のラダーフレームはありません。
エンジニアトースト

下の行はmacronsを使用するが、アークはない
エンジニアトースト

1
@EngineerToastが修正されました:)
TFeld

4

JavaScript(ES6)、245バイト

f=(o,h,n,i=0)=>(o.innerText=[...Array(h+1)].map((_,j)=>` `.repeat(j)+(j<h?`\\${[...Array(w--*2)].map((_,k)=>h+~j-i?` `:k>w*2|Math.random()<.5?s[s=t,1]:s[s=`¯\\`,0],s=t=`/_`).join``}/`:`¯¯`),w=h).join`
`,(++i<h||--n)&&setTimeout(f,250,o,h,n,i%h))
Height: <input type=number min=1 value=6 id=h><br>Arcs: <input type=number min=0 value=3 id=n><br><input type=button value=Go! onclick=f(o,+h.value,+n.value)><pre id=o></pre>

バイトカウントはISO-8859-1エンコードを前提としています。


最初に定義A=x=>[...Array(x)].map;して両方の使用法を置き換えることにより、242に減らすことができます。
バリー

@ Bary12を返すことはできません。これはmap単なるプロパティでArray.prototypeあり、単独では使用できません。動作するバージョンを試してみましたが、それらはすべて245バイトより長く出てきました。
ニール

3

C(gcc)、406バイト

#define p(X) printf(X),usleep(999)
#define x(X) do{s[X]=0;p(s);s[X]=' ';}while(0)
char c[2][2]={95,47,92,'¯'};R;i;j;k;a(){char s[2]={92,0};for(j=0;j<2*R-1;++j,p(s))*s=c[*s<50][rand()%2];*s=c[*s<50][0];p(s);}f(H,N){char s[99];for(i=0;i<99;++i)s[i]=' ';p("\e[s");for(i=0;;++i){i%=(N?N:i+1);srand(i^H^N);for(k=1;k<H;++k){for(R=H;--R;){x(H-R+1);p("\\");if(R==k)a();else x(2*R);p("/\n");}x(H);p(" ¯¯\n\e[u");}}}

オンラインでお試しください!

説明:

#define p(X) printf(X),usleep(999)              // Define p to printf(p) + delay
#define x(X) do{s[X]=0;p(s);s[X]=' ';}while(0)  // Define x(X) to print X spaces
                                                // This uses a string s full of
                                                // spaces and adds the null
                                                // terminator where approrpiate
char c[2][2]={95,47,92,'¯'};                    // 2d array of 'next arc' options
R;i;j;k;                                        // Variables
a(){                                            // a() -> print arc for row R
    char s[2]={92,0};                           // s is a string of next char
                                                // initialize to backslash
    for(j=0;j<2*R-1;++j                         // loop over each character
            ,p(s))                              // printing s each time
        *s=c[*s<50][rand()%2];                  // set s to the next arc char
    *s=c[*s<50][0];                             // set s to the 'first' arc char
                                                // note that in definition of c
                                                // first means appropriate as
                                                // final character before /
    p(s);}                                      // print the last character
f(H,N){                                         // f(H,N) -> print jacob ladder
    char s[99];for(i=0;i<99;++i)s[i]=' ';       // this is the space string for x
    p("\e[s");                                  // ANSI terminal save position
    for(i=0;;++i){i%=(N?N:i+1);                 // loop i->N (or i->INT_MAX if N=0)
        srand(i^H^N);                           // seed random with i XOR H XOR N
        for(k=1;k<H;++k){                       // for each row (bottom to top)
            for(R=H;--R;){                      // for each row (top to bottom)
                x(H-R+1);p("\\");               // print left "    \"
                if(R==k)                        // if on the arc row
                    a();                        // print the arc
                else x(2*R);                    // otherwise print spaces
                p("/\n");}                      // finish off the row
            x(H);p(" ¯¯\n\e[u");}}}             // print bottom line and move back

注:Xtermでのみ実際に動作します...多くの端末エミュレーターは、位置の保存/復元をサポートしていません。
ラムダベータ

一番下の行は行0で、2つのマクロンのみがあります。そうではありません\--/。それはおそらく簡単な修正です。Xtermで動作するGIFをキャプチャして投稿できますか?
エンジニアトースト

悲しいことに、それを行うためのツールがありません(職場でのビルド時に遊んでいるだけです)。正しい行0で更新しますが、簡単に修正できます。
ラムダベータ

無効:新しいアークが開始する前に、最初のアークのない基本的なはしご(アークのない)の1つのフレームがあります(最初のアークの前にオプション)
wastl

k = 1をk = 0に変更すると、... 0バイトのコストが修正されます。間もなく更新されます。
ラムダベータ

2

PowerShell347 319バイト

filter c{Param($h,$n)if($n-eq0){$n=-1}for($x=0;$x++-ne$n;){($h..1)|%{$l=(($h..1)|%{"$(" "*($h-$_))\$(" "*$_*2)/"})+"$(" "*$h)¯¯"
$r="Get-Random"
$i=0
$z=-join((0..(($h-$_)*2))|%{$i=switch($i%3){0{&$r 0,1}default{&$r 2,3}}"_/¯\"[$i]})+"_\\_"[$i]
$l[$_-1]=($l[$_-1]).Substring(0,$_)+"$z/"
cls
$l
Sleep -m 250}}}

オンラインでお試しください!うまく$argsプレイできなかったため、コンソールをクリアせずにリンクが関数を呼び出します。

非ゴルフ

filter c{
    Param($h,$n)
    if($n -eq 0){$n=-1} # inelegant swap to allow for an infinite loop. 
                        # Curse you zero-indexing!
    for($x=0;$x++-ne$n;)
    {
        ($h..1) | % {         
            $l=(($h..1)|%{ # (( double paren is needed to induce each line 
                           # as a new array element
                "$(" "*($h-$_))\$(" "*$_*2)/" # offset by total height. 
                                              # N spaces + rung + N*2 spaces + rung
            })+"$(" "*$h)¯¯" # last line is the floor of the ladder

            $r="Get-Random" # shorter to declare once and execute with & operator

            $i=0 # initialize $i so we choose only _ or / for the first char

            $z=-join( # build an electric ZAP!
                (0..(($h-$_)*2))|%{                    
                    $i = switch($i%3) { # choose next char based on previous selection
                        0{&$r 0,1}
                        default{&$r 2,3}
                    }    
                    "_/¯\"[$i]
                }
            )+"_\\_"[$i] # final char is \ or _ to rejoin the ladder        
            $l[$_-1]=($l[$_-1]).Substring(0,$_)+"$z/" # select one rung of the ladder 
                                                      # append an electric ZAP!                
            cls # clear the console
            $l  # display the ladder
            Sleep -m 250
        }
    }
}

小さなことですが、一番下の行はマクロンではなくハイフンです。それはゼロバイトの変更です$l=(($h..1)|%{"$(" "*($h-$_))\$(" "*$_*2)/"})+"$(" "*$h)¯¯"
エンジニアトースト

1
¯\(°_o)/¯おっと!マクロンに交換:p
ピーターヴァンディヴィエ

1
PowerShellの知識はあまりありませんが、ほとんどの改行は削除できます。さらにfor($x=0;$x-ne$n;$x++)することができますfor($x=0;$x++-ne$n;)。そうすると、324バイト(321文字)になりました。<すべての言語>でゴルフのヒントPowerShellでゴルフのヒントにも一読しても面白いかもしれません。
ケビンCruijssen

1
sleep 1少し節約します(デフォルトは-secondsです)が、かなり遅いですが、それでも妥当sleep -m 99なようです。かなり速いですが、妥当です。好みに応じて5/1バイトを節約します。Kevinの試みをチェックしませんでしfunctionfilterが、これもフリーバイトです。
ベスカ

1

ルビー、293バイト

m={}
"   __/\\_/¯¯\\/¯\\".chars.each_slice(3){|e|u,*v=e;m[u]=v}
a=->l,c{l<1?"/":(d=m[c].sample;c+a[l-1,d])}
n=gets.to_i
h=gets.to_i
o=0
while o<n||n<1
h.times{|i|puts (0...h).map{|j|" "*j+"\\"+a[2*(h-j),i==h-j-1?["_","/"].sample: " "]}*"\n";puts" "*h+"¯¯";sleep(0.3);puts"\n"*99}
o+=1
end

オンラインでお試しください!

私はWindows上にいるので、コンソールをクリアするために多くの「\ n」を印刷するだけです。2つの引数nを取りh、stdinの2行として受け取ります。

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