야곱의 ASCII 사다리 애니메이션


23

어린이 과학 박물관에서 야곱의 사다리 를 보았을 것 입니다. 그들이 어떻게 생겼는지에 익숙하지 않다면 Wikimedia Commons 에 몇 가지 이미지와 비디오 예제가 있습니다. 오늘날 도전은 전기 가제트의 애니메이션 ASCII 버전을 만드는 것입니다. 결국 다음과 같이 보일 것입니다.

사다리 GIF 예


사다리 건설

다음은 높이 ( H )가 6 인 사다리의 기본 모양입니다 .

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

왼쪽의 숫자는이 예제의 행 번호를 나타내며 출력에 포함되지 않아야합니다. 주어진 행을 숫자 ( R )로 참조합니다. 행 0이 맨 아래 ¯¯입니다. 1 행부터 H 행 까지는 네 부분으로 구성됩니다.

  • 반복되는 공간 (U + 0020) ( H - R )
  • 백 슬래시 \(U + 005C)
  • 반복되는 공간 (U + 0020) (2 * R )
  • 슬래시 /(U + 002F)

슬래시가 모두 매크로 ¯(U + 00AF) 로 대체 된 것을 제외하고 행 0은 동일합니다 . 각 줄의 끝이나 사다리 아래의 후행 공백은 괜찮습니다. 선행 공백은 아닙니다.


아크 건설

래더가 구성되면 왼쪽과 오른쪽 사이에 호를 만들 수 있습니다. 하나의 호는 완전히 한 행 안에 있으며 선행 \과 후행 사이의 공간을 대체합니다 /. 따라서 2 행에는 호에 4 개의 문자가 있고 3 행에는 6 개의 문자가 있습니다. 각 호는 다음 규칙을 사용하여 구성됩니다.

  • 유일하게 허용되는 문자는 _/¯\(U + 005F, U + 002F, U + 00AF, U + 005C)입니다.
  • 매끄러운 외관을 보장하기 위해, 어떤 ¯이상이 /a로 따라야합니다 ¯또는\
  • 매끄러운 외관을 보장하기 위해, 어떤 _이상이 \a로 따라야합니다 _또는/
  • 위의 두 규칙은 사다리의 가장자리에도 적용됩니다
  • 위의 세 가지 규칙은 사실상 호의 첫 번째 문자는 _또는 이어야 /하고 마지막 문자는 _또는 이어야합니다 \( \¯\_//양쪽에서 유효하지 않지만 \_/¯\/괜찮음).
  • 주어진 지점에서 각각의 허용 가능한 캐릭터가 나타날 확률이 0이 아니어야합니다.
  • 각 호는 다른 모든 호와 독립적입니다.

생기

단일 호의 수명은 1 행에서 시작하여 상단에 도달 할 때까지 한 번에 한 행씩 "이동"하여 생성됩니다. IE의 경우 먼저 행 1에서 원호를 생성 한 다음 다시 스페이스로 설정하고 행 2에서 원호를 생성합니다. 표시 할 다수의 아크가있는 경우 ( N ) 다음 지침을 사용하여 한 번에 하나씩 많은 아크의 수명을 보여주십시오.

  • 한 번에 하나의 아크만 "작동"해야합니다. 다음 호는 현재 호가 맨 위에 도달 한 다음 꺼질 때까지 시작할 수 없습니다.
  • 호 수명의 각 행은 정확히 한 프레임 동안 표시되어야합니다.
  • 새로운 호가 시작되기 전에 (호가없는) 기본 사다리의 한 프레임이 있어야합니다 (첫 번째 호 전에 선택 사항)
  • 애니메이션에는 N 호의 전체 수명이 표시되어야합니다 . 경우 N은 0 = 중지 될 때까지 영원히 임의 호에 애니메이션을 적용해야한다.
  • 경우 N > 0, 당신은 영원히 루프 애니메이션을 여전히 수도 있지만, 반복해서 같은 아크의 루프해야합니다. (이 게시물의 상단에있는 예제 GIF는 H = 6이고 N = 3이지만 영원히 반복됩니다.)
  • 애니메이션이 제자리에 있어야합니다. 즉, 각 프레임은 다음 프레임을 완전히 덮어 쓰고 동일한 위치에 있어야합니다.
  • 각 프레임의 길이는 원하는대로 할 수 있지만 사람이 볼 수있게합니다 (IE, 상식을 사용하십시오 : 0.01s / frame과 30s / frame은 모두 허용되지 않습니다).

입출력

  • 입력 및 출력은 모든 표준 형식 일 수 있습니다
  • GIF를 내보내고, 화면에 텍스트를 쓰거나, 각 프레임마다 단일 파일을 출력하거나, 다른 합리적인 수단을 사용할 수 있습니다
  • 표준 허점 은 금지되어 있습니다
  • 사다리 H 의 높이는 양의 정수입니다.
  • N 을 나타내는 호의 수는 음이 아닌 정수입니다.
  • HN 은 모두 원하는 순서대로 입력으로 사용됩니다 (답에 주문을 포함하십시오)

승리 조건

이것은 이므로 가장 짧은 코드가 승리합니다.

모래 상자


1
중심에서 호를 대칭으로 생성 할 수 있습니까? 나는 규칙에 그 제한을 볼 수 없습니다
Dead Possum

각 프레임을 콘솔에 차례로 인쇄 할 수 있습니까?
TFeld

: @DeadPossum 나는 당신이 매우 번개-Y를 보이지 않아 사실에도 불구하고 옳았지만 실제로이 규칙의 조합에 의해 허용되지 않는 것 생각 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 2016 년

답변:


5

파이썬 2 , 287 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 콘솔 모두에서 작동합니다.
ElPedro

1
새 호가 시작되기 전에 (호가없는) 기본 사다리의 한 프레임이 있어야합니다 (첫 번째 호 전에 선택 사항)
wastl

5
매크로 (U + 00AF) 대신 하이픈 (U + 002D)을 사용하고 있다고 생각합니다. 바이트 수를 늘려서 고칠 것이라고 생각하지 않습니다. 또한 @wastl이 지적했듯이 호 사이에 빈 사다리 프레임이 없습니다.
엔지니어 토스트

맨 아래 줄은 마크로를 사용하지만 호는 사용하지 않습니다
Engineer Toast

1
@EngineerToast 수정 됨 :)
TFeld

4

자바 스크립트 (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

@ Bary12 당신은 반환 할 수 없습니다 map, 그것은 단지 속성이며 Array.prototype자체적으로 사용되지 않습니다. 작업 버전을 시도했지만 모두 245 바이트보다 길었습니다.
Neil

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에서만 작동합니다 ... 많은 터미널 에뮬레이터는 저장 / 복원 위치를 지원하지 않습니다.
LambdaBeta

맨 아래 행은 행 0이며 두 개의 매크로 만 있습니다. 아닙니다 \--/. 아마도 쉬운 해결책 일 것입니다. Xterm에서 작동하는 GIF를 캡처하고 게시 할 수 있습니까?
엔지니어 토스트

슬프게도 그렇게 할 수있는 도구가 부족합니다 (직장에서 빌드 시간 동안 놀아요). 올바른 행 0으로 업데이트하지만 쉽게 해결할 수 있습니다.
LambdaBeta

무효 : 새로운 호가 시작되기 전에 (호가없는) 기본 사다리의 한 프레임이 있어야합니다 (첫 번째 호 전에 선택 사항)
wastl

k = 1을 k = 0으로 변경하면 0 바이트 비용이 수정됩니다. 곧 업데이트됩니다.
LambdaBeta

2

PowerShell , 347 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
        }
    }
}

작은 일이지만 맨 아래 행은 매크로 대신 하이픈입니다. 바이트가 0으로 변경됨$l=(($h..1)|%{"$(" "*($h-$_))\$(" "*$_*2)/"})+"$(" "*$h)¯¯"
Engineer Toast

1
¯ \ (° _o) / ¯ 죄송합니다! 마크론으로 교체 : p
Peter Vandivier

1
PowerShell을 잘 모르지만 대부분의 줄 바꿈을 제거 할 수 있습니다. 또한 for($x=0;$x-ne$n;$x++)가능합니다 for($x=0;$x++-ne$n;). 나는 그것을 324 바이트 (321 자)로 줄였다 . <모든 언어>의 골프 팁PowerShell의 골프 팁도 읽어 보는 것이 흥미로울 수 있습니다.
Kevin Cruijssen

1
sleep 1비트를 저장하지만 (기본값은-초) 꽤 느리지 만 여전히 합리적 sleep -m 99이며 매우 빠르지 만 합리적입니다. 원하는 내용에 따라 5/1 바이트를 저장합니다. 케빈의 시도를 확인하지 않았지만 functionfilter무료 바이트는 물론이다.
Veskah

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

온라인으로 사용해보십시오!

나는 창에 있으므로 콘솔을 지우기 위해 많은 "\ n"을 인쇄합니다. stdin에서 두 개의 인수 nh두 개의 행을 취합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.