Скроллинг Шатер


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среду. Если другая среда окажется полезной, будут сравниваться только похожие среды, и для каждого из них может быть объявлен отдельный победитель.

Приложение (25 апреля 2012 г.)

Чтобы решить некоторые возникающие проблемы, я делаю решение. Ваше количество символов должно включать код, необходимый для:

  1. Флеш STDOUT (смотрит на тебя, Руби)
  2. Реализация sleepс задержкой <1с (смотря на вас, Perl)

Это может быть сделано, когда командная строка переключается на интерпретатор, но эти символы учитываются в общем количестве (без пробелов).


Я немного обеспокоен клеммное поведение для такого рода вещи ... xterm, vt102, ...?
dmckee --- котенок экс-модератора

Я предполагаю, что xterm, но я не думаю, что это имеет большое значение. Возможно, я не понимаю вашу озабоченность?
Джоэл Бергер

Эти трюки обычно создаются на основе того, как различные терминалы обрабатывают некоторые непечатаемые символы, и терминалы различались по тому, что они могли делать, и какие последовательности давали эффекты. Для воспроизводимости было бы хорошо иметь указанную терминальную среду.
dmckee --- котенок экс-модератора

1
Будет правильно, если кто-то отправит действительно короткий ответ, который зависит от неясного терминала, для которого у вас нет эмулятора, но все в порядке.
dmckee --- котенок экс-модератора

хорошо, я думаю, что у меня есть это сейчас. Спасибо за мысли :-)
Джоэл Бергер

Ответы:


5

питон 2 - 146 символов

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

Используя bash (по крайней мере, в недавней установке MacOSX и CentOS), команда оболочки, используемая для очистки экрана терминала, должна быть «clear», а не «cls».
Паоло

«cls» для Windows, «clear» для сборок OSX / Linux, я думаю
Blazer

Полезно было бы посоветовать, как запустить программу для тех, кто не имеет дело с питоном ежедневно. Запустите питон. вставить код, звонок 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 есть $|++. Это дополнительные 17 символов, но все еще намного ниже моего. Ну, я не могу позволить Руби победить Perl! Собираюсь работать. Хороший.
Джоэл Бергер

Если я звоню, ruby1.8 "Hello World"я получаю, не совсем к моему удивлению, сообщение об ошибке:ruby1.8: No such file or directory -- Hello World (LoadError)
пользователь неизвестен

@userunknown, может быть, вы тоже должны указать путь к исходному файлу: ruby foo.rb args;-)
Patrick Oscity

@padde: Да, я должен. К сожалению, Говард отредактировал свой пост, не сообщая мне о его изменении. Взгляните на историю, чтобы понять мой вопрос.
пользователь неизвестен

3

С 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**tна int*t. Работает нормально в 32-битной ( int**tбудет поддерживать 64-битную).

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 - 431 416 знаков

Уважает стандарт в высокой степени. Использует ncurses, поэтому он должен быть в значительной степени независимым от терминала. Когда текст попадает на бок, происходит небольшое заикание из-за некоторой хитрости, сыгранной для сохранения предполагаемого пробела в строке.

Используемая строка должна быть передана в качестве первого аргумента в командной строке (и ее следует экранировать, если она содержит пробелы, особенно если она содержит a, !как это 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: Да, и я забыл заменить ' 's числовыми эквивалентами.
dmckee --- котенок экс-модератора

Еще несколько хитростей: Замените x==32на x-32(меняет значение, поэтому измените если-либо) или на x<33(при условии, что 0..31 никогда не использовалось). Инициализируйте значениями, которые у вас есть ( for(curs_set(c=0);...). *(s+1)-> s[1]. Удалите ненужные скобки (замена ;с ,поможет).
Угорен

2

Perl 5.13.2, 96

$_=join$;x4,$;x46,split//,pop;print substr(s/$;/ /gr,0,50)." \r"while$|=s/$;//+select'','','',.1

Кража много из ответа @ Кевина Рейда , особенно/r уловка, доступная в более новых Perls.

Perl, 115

Как и ответ @ Joel Berger , это могло бы стать намного короче, если бы я мог использовать sleep 1и был медленным, или передавал -MTime::HiRes=sleepкомандную строку для включения 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}

да, я укусил себя за это! Я не понимал, что в других langs будет встроенный сон. О, хорошо.
Джоэл Бергер

Некоторые предложения, вы можете удалить пробел после каждого 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 Привет мир имеет 4 пробела между каждой буквой, когда h является первым символом, эти пробелы удаляются. Это демо медленнее jsfiddle.net/fYvg7/1
ajax333221

Это близко, но вы должны удалить каждый пробел по отдельности.
Джоэл Бергер

@JoelBerger Исправлено
ajax333221

Ну, я не хочу быть ворчливым, но есть еще одна проблема: ваша начинается со всех букв, а не вводится по одному справа.
Джоэл Бергер

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.
  • Замена на NUL для сохранения пробелов однозначна, поскольку POSIX argv не является чистым 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"

ungolfed:

#!/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

Perl : 144 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}

Для того, чтобы выспаться <1 с, вам нужно запустить как:

perl -MTime::HiRes=sleep scriptname 'string to print'

Поскольку я не буду объявлять себя победителем, я не буду спорить о том, что там важно или нет (но я действительно не могу, чтобы Руби выиграла это ;-))


Еще 4, и это помещается на твит: D
ajax333221

4 символа прямо здесь: s/' '/$"/gиs/shift/pop/
эпифим

да, я включил их вместе с удалением pushзаявления. Я просто еще не опубликовал это.
Джоэл Бергер

0

Вопрос, 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];}

Требуется два аргумента: строка ввода и скорость прокрутки

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, а затем выбрасывает его. Это занимает около трети секунды на моей машине, это вызывает задержку.
  • ((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

PowerShell , 129 байт

for($x=' '*52+(($args|% t*y)-join' '*4);$x-match'  '){write-host "`r$(-join($x=$x-replace'(?<!  .*)  ')[0..50])  "-n
sleep -m 99}

Попробуйте онлайн!

Этот сценарий не удаляет пробелы в аргументах в отличие от сценария Джои .

TIOне отображает вывод правильно. С консолью Powershell вы получаете прокрутку.


0

05AB1E , 42 байта

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

Попробуйте онлайн (без сна).ПРИМЕЧАНИЕ: у меня не установлен 05AB1E локально, поэтому я не уверен на 100%, работает ли \rтрюк (однако теоретически он должен работать). В TIO \rони интерпретируются как переводы строк. Кроме того, TIO использует унаследованную версию, поскольку .eона отключена в новой версии 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)чтобы начать.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.