Оживленная лестница Джейкоба ASCII

23

Возможно, вы видели Лестницу Иакова в детских научных музеях. Если вы не знакомы с тем, как они выглядят, есть несколько изображений и видео примеров на сайте Wikimedia Commons . Задача сегодня - создать анимированную версию электрического гаджета в формате ASCII. В итоге все должно выглядеть примерно так:

LadderGIFExample


Лестница Строительство

Вот основная форма лестницы с высотой ( 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)

Строка 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,01 с / кадр и 30 с / кадр недопустимы).

Ввод, вывод

  • Ввод и вывод может быть в любом стандартном формате
  • Вы можете экспортировать GIF, записать текст на экран, вывести один файл для каждого кадра или любым другим разумным способом
  • Стандартные лазейки запрещены
  • Высота лестницы H будет положительным целым числом
  • Число дуг для отображения N будет неотрицательным целым числом
  • И H, и N принимаются в качестве входных данных в любом порядке, который вы выберете (пожалуйста, включите этот порядок в ваш ответ)

Условие победы

Это поэтому выигрывает самый короткий код.

песочница

Инженер Тост
источник
1
Может ли дуга быть симметричной по центру? Я не вижу ограничений в правилах
Мертвый Поссум
Могу ли я печатать каждый кадр за консолью за другим?
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 из этого работает:

введите описание изображения здесь

TFeld
источник
Немного подлый, но вы можете использовать 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
LambdaBeta
источник
Примечание: действительно работает только в 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нормально играть, поэтому ссылка вызывает функцию без очистки консоли.

Ungolfed

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)¯¯"
Engineer Toast
1
¯ \ (° _o) / ой! поменялись местами в макронах: p
Питер Вандивье
1
Я не очень хорошо знаю PowerShell, но вы можете удалить большинство новых строк. Кроме того for($x=0;$x-ne$n;$x++)может быть for($x=0;$x++-ne$n;). Я сделал это до 324 байтов (321 символов) при этом. Советы по игре в гольф на <все языки> и Советы по игре в гольф в PowerShell также могут быть интересными для чтения.
Кевин Круйссен
1
sleep 1немного экономит (по умолчанию-секунды), но довольно медленно, но все же разумно, 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.

crashoz
источник