Анімальна драбина Якоба ASCII


23

Можливо, ви бачили Сходи Якова в дитячих музеях науки. Якщо ви не знайомі з тим, як вони виглядають, на Вікісховищі є кілька зображень та відеоприкладів . Завдання сьогодні - створити анімовану версію електричного гаджета ASCII. Зрештою, це має виглядати приблизно так:

СходиGIFEПриклад


Будівництво сходів

Ось основна форма сходів висотою ( Н ) 6:

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

Цифри зліва просто вказують номер рядка для цього прикладу і не повинні включатися у висновок. Ми будемо посилатися на даний рядок за його номером ( R ). Рядок 0 - це нижня частина ¯¯. Кожен рядок від 1 до Н складається з чотирьох частин:

  • Пробіл (U + 0020), повторений ( H - R ) разів
  • Задня косою рисою \(U + 005C)
  • Пробіл (U + 0020), повторений (2 * R ) разів
  • Передня косою рисою /(U + 002F)

Рядок 0 ідентичний, за винятком того, що обидві ¯косої риски замінені макроном (U + 00AF). Кінцевий пробіл в кінці кожного рядка або нижче сходів нормально. Провідні пробіли - ні.


Дугове будівництво

Після того як сходи побудовані, ви можете створити дуги між лівою та правою стороною. Одна дуга знаходиться повністю в ряду і замінює проміжки між провідним \і кінцевим /. Отже, рядок 2 матиме 4 символи у своїй дузі, у рядку 3 - 6 тощо. Кожна дуга складається за такими правилами:

  • Єдиними допустимими символами є _/¯\(U + 005F, U + 002F, U + 00AF, U + 005C)
  • Щоб забезпечити гладкий зовнішній вигляд, будь-який ¯або /повинен дотримуватися а ¯або\
  • Щоб забезпечити гладкий зовнішній вигляд, будь-який _або \повинен дотримуватися а _або/
  • Два вищезазначених правила застосовуються і до країв сходів
  • Три вищезазначені правила фактично означають, що перший символ у дузі повинен бути _або, /а останній символ повинен бути _або \( \¯\_//недійсний на обох кінцях, але \_/¯\/це нормально)
  • У кожному допустимому символі має бути ненульовий шанс виникнути в заданій точці
  • Кожна дуга незалежна від кожної іншої дуги

Анімація

Життя однієї дуги створюється, починаючи її в рядку 1 і "переміщуючи" її вгору по одному ряду, поки вона не досягне вершини. IE, спочатку генеруйте дугу в рядку 1, потім встановіть її назад у пробіли та генеруйте дугу в рядку 2 тощо. З огляду на кількість дуг ( N ), покажіть повний термін служби багатьох дуг одна за одною, використовуючи наступні вказівки:

  • Тільки одна дуга повинна бути "живою" в будь-який час. Наступна дуга не може початися, поки поточна не досягне вершини, а потім погасне.
  • Кожен ряд життя дуги повинен бути показаний рівно на один кадр
  • Перед початком нової дуги повинен бути один каркас просто основної драбини (без дуг) (необов'язково перед першою дугою)
  • Анімація повинна показувати повне життя N дуг. Якщо N = 0, він повинен анімувати випадкові дуги назавжди до зупинки.
  • Якщо N > 0, ви все одно можете назавжди циклічити анімацію, але вона повинна бути петлею однієї і тієї ж дуги. (Приклад GIF у верхній частині цієї публікації має H = 6 і N = 3, але він циклічно назавжди.)
  • Анімація повинна відбуватися на місці. Тобто кожен кадр повинен повністю перезаписати наступний кадр і знаходитися в одному місці.
  • Довжина кожного кадру може бути будь-якою, яку ви хочете, але зробіть його людиною спостережливою (IE, використовуйте здоровий глузд: 0.01s / кадр і 30s / frame є неприйнятними.)

Введення-виведення

  • Введення та вихід можуть бути у будь-якому стандартному форматі
  • Ви можете експортувати GIF, писати текст на екран, виводити один файл для кожного кадру чи будь-які інші розумні засоби
  • Стандартні лазівки заборонені
  • Висота сходів Н буде цілим числом
  • Кількість дуг для показу N буде невід'ємним цілим числом
  • І H і N приймаються як вхідні дані в будь-якому обраному вами порядку (будь-ласка, включіть порядок у свою відповідь)

Умова виграшу

Це тому найкоротший код виграє.

Пісочниця


1
Чи може дуга генеруватися симетрично її центром? Я не бачу обмежень до цього в правилах
Dead Possum

Чи можу я друкувати один кадр один за одним на консолі?
TFeld

@DeadPossum Я думав, що ти маєш рацію, незважаючи на те, що це виглядатиме не дуже блискавично, але насправді це заборонено поєднанням двох правил: 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

Python 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 + 002D) замість макронів (U + 00AF). Я не думаю, що це збільшить кількість байтів, щоб виправити це. Також, як зазначав @wastl, між дугами немає порожнього каркаса сходів.
Інженер Тост

У нижньому рядку використовуються макрони, але дуги цього немає
Engineer Toast

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.


Можна зменшити його до 242, визначивши A=x=>[...Array(x)].map;на початку та замінивши обидва звички.
Bary12

@ 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 працює лише дійсно ... багато емуляторів терміналів просто не підтримують збереження / відновлення позиції.
LambdaBeta

Нижній рядок - це рядок 0 і містить лише два макрона. Це не так \--/. Це, мабуть, легке виправлення. Чи можете ви зафіксувати та опублікувати GIF цього файлу, що працює в Xterm?
Інженер Тост

На жаль, мені не вистачає інструментів для цього (просто граючи в часи збірки на роботі). Я оновлю правильний рядок 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
        }
    }
}

Це невелика річ, але нижній ряд - це дефіси замість макронів. Це зміна нуля байтів$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 також можуть бути цікавими для прочитання.
Кевін Кройсейсен

1
sleep 1економить трохи (він за замовчуванням до -секунди), але досить повільний, але все-таки розумний-ish, sleep -m 99досить швидкий, але також розумний. Економить 5/1 байт залежно від того, що вам подобається. Не перевірив спробу Кевіна, але functionтакож filterце безкоштовний байт.
Веська

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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.