Код Гольф: последовательность Морриса

Соревнование

Самый короткий код по количеству символов, который выводит числовую последовательность Морриса. Числовая последовательность Морриса, также известная как Посмотри и скажи, - это последовательность чисел, которая начинается следующим образом:

1, 11, 21, 1211, 111221, 312211, ...

Вы можете генерировать последовательность бесконечно (т.е. вам не нужно создавать конкретное число).

Ожидания ввода-вывода

Программе не требуется вводить какие-либо данные (но есть бонусные баллы за принятие ввода и, таким образом, возможность начать с любой произвольной начальной точки или числа). По крайней мере, ваша программа должна начинаться с 1.

Как минимум ожидается, что на выходе будет последовательность:

1
11
21
1211
111221
312211
...

Дополнительный кредит

Если вы собираетесь получить дополнительный кредит, вам нужно будет сделать что-то вроде этого:

$ morris 1
1
11
21
1211
111221
312211
...

$ morris 3
3
13
1113
3113
132113
...

person Community    schedule 11.10.2010    source источник
comment
Каковы ожидаемые входные и выходные данные? Одно значение, один выход? Конкретное количество итераций?   -  person Mike Clark    schedule 11.10.2010
comment
@Mike: Что ж, я бы предположил, что для нестрогих (ленивых) языков или языков, поддерживающих генераторы, вы можете просто написать функцию для генерации всей (бесконечной) последовательности. Для языков с ограниченным доступом распечатывайте элементы до тех пор, пока их не прервет пользователь, или что-то в этом роде.   -  person Chris Jester-Young    schedule 11.10.2010
comment
@Mike Я заявил, что вы можете генерировать последовательность бесконечно :) Нет определенного количества итераций.   -  person Vivin Paliath    schedule 11.10.2010
comment
@whoever Если вы собираетесь голосовать за закрытие, скажите хотя бы почему.   -  person Vivin Paliath    schedule 11.10.2010
comment
Я думаю, будет более понятно, если вы замените неопределенно (неопределенно, неясно) бесконечно (бесконечно, без границ). Насчет доводчиков: привыкайте. code-golf вопросы - это серая зона в SO.   -  person BalusC    schedule 11.10.2010
comment
@BalusC спасибо! Я это перефразирую!   -  person Vivin Paliath    schedule 11.10.2010
comment
@Vivin, обычно я говорю, почему я голосую за закрытие, но в твоем исходном посте не было так много деталей, что мне просто не хотелось объяснять себя. См. Также meta.stackexchange.com/ questions / 24242 /, чтобы узнать о некоторых правилах правильных сообщений code-golf.   -  person Bart Kiers    schedule 11.10.2010
comment
Должен ли вывод быть [13,1113,3113 ...] или [3,13,1113,3113 ...]?   -  person Instantsoup    schedule 11.10.2010
comment
@ Барт, спасибо. IMO Я чувствовал, что проблема была достаточно простой (сгенерируйте эту последовательность), чтобы не требовать дополнительных объяснений. Спасибо за ссылку! @instantsoup мой плохой! я починил это   -  person Vivin Paliath    schedule 11.10.2010
comment
@Bart - мне нравится, когда на мой пост ссылаются! Рад видеть, что люди до сих пор помогают новичкам.   -  person Chris Lutz    schedule 12.10.2010
comment
Никто не любит шепелявить?   -  person Ricardo Marimon    schedule 13.10.2010
comment
-1 быть достаточно сложным, чтобы допускать более одного разумного способа его выполнения stackoverflow.com/tags/code-golf/info   -  person Nakilon    schedule 13.10.2010
comment
@Nakilon Я полагаю, что многочисленные способы сделать это (ниже) не означают, что существует более одного способа сделать это. Спасибо за ваше прекрасное понимание.   -  person Vivin Paliath    schedule 13.10.2010
comment
Этот вопрос кажется не по теме, потому что он касается Code Golf; сайт, у которого есть свои вопросы.   -  person George Stocker    schedule 22.05.2014


Ответы (41)


GolfScript - 41 (доп. Кредит: 40)

1{.p`n+0:c:P;{:|P=c{c`P|:P!}if):c;}%~1}do
{~.p`n+0:c:P;{:|P=c{c`P|:P!}if):c;}%1}do

Что?
Процедура получения следующего числа в последовательности: преобразовать текущее число в строку, добавить новую строку и перебрать символы. Для каждой цифры, если предыдущая цифра P такая же, увеличивайте счетчик c. В противном случае добавьте c и P к следующему числу, а затем обновите эти переменные. Добавляемая новая строка позволяет добавить последнюю группу цифр к следующему числу.

Точные подробности можно получить, изучив документацию GolfScript. (Обратите внимание, что | используется как переменная.)

person Community    schedule 12.10.2010
comment
Ах, похоже, еще одна перестрелка из сценария гольфа / J - person John La Rooy; 12.10.2010
comment
Не могли бы вы объяснить, что здесь происходит, для нас, новичков в гольф-скриптах? :-) - person Michael Foukarakis; 13.10.2010
comment
@Michael Я добавил краткое описание алгоритма, но вам придется обратиться к документации gs, если вы хотите понять, что именно происходит (к счастью, код состоит всего из 41 символа). - person Nabb; 13.10.2010
comment
Похоже, самый короткий пока :) Приму это завтра, если не увижу ничего короче! - person Vivin Paliath; 15.10.2010

Haskell: 115 88 85

import List
m x=do a:b<-group x;show(length b+1)++[a]
main=mapM putStrLn$iterate m"1"

Это бесконечная последовательность. Я знаю, что его можно значительно улучшить - я новичок в Haskell.

Немного короче, встраивая mapM и повторяйте:

import List
m(a:b)=show(length b+1)++[a]
f x=putStrLn x>>f(group x>>=m)
main=f"1"
person Community    schedule 11.10.2010
comment
Я добавил несколько хитростей: List vs Data.List; использовать нотацию вместо concatMap; использование итерации. - person Josh Lee; 12.10.2010
comment
Несколько незначительных улучшений для получения 85: m x=do a:b<-group x;show(length b+1)++[a] (сопоставление с образцом) и main=mapM putStrLn$iterate m"1" (main может быть IO a, а не IO (), а $ может исключить круглые скобки). - person Olathe; 12.10.2010

Perl (46 символов)

$_="1$/";s/(.)\1*/length($&).$1/eg while print

Дополнительный кредит (52 символа)

$_=(pop||1).$/;s/(.)\1*/length($&).$1/eg while print
person Community    schedule 11.10.2010
comment
Сделал это перед прочтением других решений. Воспользовавшись советом «повторить» в другом ответе на Perl, эти решения уменьшатся на 3 символа. - person Bizangles; 12.10.2010
comment
Я думаю, что -l обычно стоит трех символов. - person Nabb; 12.10.2010

Javascript 100 97

for(x=prompt();confirm(y=x);)for(x="";y;){for(c=0;y[c++]&&y[c]==y[0];);x+=c+y[0];y=y.substr(c--)}

Позволяет прервать последовательность (нажав «Отмена»), чтобы мы не блокировали пользовательский агент и не привязывали процессор. Это также позволяет начинать с любого положительного целого числа (дополнительный кредит).

Живой пример: http://jsbin.com/izeqo/2

person Community    schedule 11.10.2010
comment
substr() короче substring() и выполняет ту же работу, если вы передаете один аргумент. - person Harmen; 12.10.2010

Perl, 46 символов

$_=1;s/(.)\1*/$&=~y!!!c.$1/ge while print$_,$/

Дополнительный кредит, 51 символ:

$_=pop||1;s/(.)\1*/$&=~y!!!c.$1/ge while print$_,$/
person Community    schedule 11.10.2010
comment
Примечание для себя: изучите специальные переменные регулярных выражений. Однако я могу придумать несколько вещей, которые вы можете сделать. Один, while(1){...} можно сократить до {...;redo} (-3 символа). Во-вторых, последний оператор в блоке и сами блоки не нуждаются в точках с запятой (-2 символа). - person Platinum Azure; 11.10.2010
comment
Также стоит посмотреть: my$n вместо $n=""? Я считаю, что лексическая область видимости блока будет эффективно отменять его каждый раз (и, конечно же, использование оператора .= объединит его с пустой строкой, если переменная равна undef). Таким образом вы сохраняете один символ, но я не знаю, будет ли он семантически работать на 100%. Кроме того, вы можете изменить inline while с while(s///) на while s///, сохранив один символ. - person Platinum Azure; 11.10.2010
comment
Вы можете удалить две точки с запятой, использовать для (;;), и модификаторы предложения (в конце предложения) не нуждаются в скобках, так как это на 4 символа меньше. - person ninjalj; 11.10.2010
comment
@ninjalj: Согласно моим комментариям выше, вы можете просто использовать повтор в блоке для того же эффекта, сохранив еще два символа. :-) - person Platinum Azure; 11.10.2010
comment
Еще одного персонажа слишком много. Как сказано выше, модификаторы предложений не нуждаются в скобках. - person ninjalj; 12.10.2010
comment
Кроме того, привязка ^ не нужна, s /// запоминает последний проверенный символ. - person ninjalj; 12.10.2010
comment
Этот не печатает 1 (или входное значение) в первой строке вывода. - person Plutor; 12.10.2010
comment
Этот не печатает 1 (или входное значение) в первой строке вывода. Вы должны поменять местами печать и /// в это время. Кроме того, $ + [0] - $ - [0] длиннее, чем длина ($ &). - person Plutor; 12.10.2010

Mathematica - 62 53 50 символов - Включены дополнительные баллы

Изменить: 40 символов ... но справа налево :(

Любопытно, что если мы читаем последовательность справа налево (т.е. 1,11,12,1121, ..), 40 символов будет достаточно

NestList[Flatten[Tally /@ Split@#] &, #2, #] &

Это потому, что Талли генерирует список {elem, counter}!

Изменить: 50 символов

NestList[Flatten@Reverse[Tally /@ Split@#, 3] &, #2, #] &

Рассечение: (читайте комментарии вверху)

NestList[               // 5-Recursively get the first N iterations
    Flatten@            // 4-Convert to one big list
       Reverse          // 3-Reverse to get {counter,element}
          [Tally /@     // 2-Count each run (generates {element,counter})
               Split@#, // 1-Split list in runs of equal elements
                 3] &,
                     #2,// Input param: Starting Number 
                     #] // Input param: Number of iterations

Изменить: произведен рефакторинг

NestList[Flatten[{Length@#, #[[1]]} & /@ Split@#, 1] &, #2, #1] &

Конец редактирования ///

NestList[Flatten@Riffle[Length /@ (c = Split@#), First /@ c] &, #2, #1] &

Пробелы не нужны / добавлены для ясности

Вызов с помощью

%[NumberOfRuns,{Seed}]

Я впервые использую "Riffle", чтобы объединить {1,2,3} и {a, b, c} в {1, a, 2, b, 3, c} :)

person Community    schedule 12.10.2010

Вот моя попытка C # с использованием LINQ и первая попытка Code Golf:

C # - 205 194 211 198 байтов с дополнительным кредитом (включая шаблон C #)

using System.Linq;class C{static void Main(string[]a){var v=a[0];for(;;){var r="";while(v!=""){int i=v.TakeWhile(d=>d==v[0]).Count();r+=i;r+=v[0];v=v.Remove(0,i);}System.Console.WriteLine(r);v=r;}}}

Читаемая версия:

static void Main(string[] args)
{
    string value = args[0];
    for (;;)
    {
        string result = "";
        while (value != "")
        {
            int i = value.TakeWhile(d => d == value[0]).Count();
            result += i;
            result += value[0];
            value = value.Remove(0, i);
        }
        Console.WriteLine(result);
        value = result;
    }
}

Пример вывода:

11
21
1211
111221
312211
13112221
1113213211
...
person Community    schedule 12.10.2010
comment
Переименование параметра args сэкономит вам еще 6 символов. - person Dirk Vollmar; 12.10.2010
comment
Преобразование int i = value.TakeWhile (d = ›d == value [0]). Count (); в int я = 0; while (i ‹v.Length && v [i] == v [0]) i ++; позволит вам удалить Linq с помощью. - person MikeP; 14.10.2010
comment
@MikeP, я действительно хотел использовать LINQ для этого, просто в качестве упражнения. - person GeReV; 14.10.2010

Python, 97 102 115

Пробелами должны быть вкладки:

x='1'
while 1:
    print x;y=d=''
    for c in x+'_':
        if c!=d:
            if d:y+=`n`+d
            n,d=0,c
        n+=1
    x=y

E.g.:

$ python morris.py | head
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
person Community    schedule 11.10.2010
comment
Вырезайте символы, помещая операторы в одну строку, когда это возможно. Вы можете заменить несколько комбинаций новой строки / табуляции точкой с запятой. Это особенно полезно, если вы можете делать это в строках с глубоким отступом. - person Chris Lutz; 12.10.2010
comment
Табуляторы можно заменить пробелами. Просто сделайте один отступ на первом уровне, два на втором и т. Д. - person phkahler; 13.10.2010
comment
@phkahler Табуляция и пробелы состоят из одного символа. Однако чередование пробела / табуляции / пробела + табуляции позволит сэкономить несколько символов. - person Nabb; 13.10.2010

Perl, 67 символов

включая флаг -l.

sub f{$_=pop;print;my$n;$n.=$+[0].$1while(s/(.)\1*//);f($n)}f(1)

Perl, 72 символа с дополнительными баллами

sub f{$_=pop;print;my$n;$n.=$+[0].$1while(s/(.)\1*//);f($n)}f(pop||1)
person Community    schedule 11.10.2010

Вот моя реализация (на Прологе):

Пролог с DCG (174 символа):

m(D):-write(D),nl,m(1,write(D),T,[nl|T],_).
m(C,D,T)-->[D],{succ(C,N)},!,m(N,D,T).
m(C,D,[G,D|T])-->[N],{G=write(C),G,D,(N=nl->(M-T-O=0-[N|R]-_,N);M-T-O=1-R-N)},!,m(M,O,R).

Простой ванильный пролог, код гораздо более читабельный (225 символов):

m(D):-
  ((D=1->write(D),nl);true),
  m([], [1,D]).

m([], [C,D|M]):-
  write(C), write(D),nl,
  reverse([D,C|M],[N|X]),
  !,
  m([N|X],[0,N]).
m([D|T], [C,D|M]):-
  succ(C,N),
  !,
  m(T,[N,D|M]).
m([Y|T],[C,D|M]):-
  write(C), write(D),
  !,
  m(T,[1,Y,D,C|M]).

Чтобы вывести последовательность Морриса: m (D). где D - «начальная» цифра.

person Community    schedule 11.10.2010
comment
Я собирался проголосовать, но я так ненавижу пролог, что просто не мог этого сделать. - person rerun; 12.10.2010

Рубин - 52

s=?1;loop{puts s;s.gsub!(/(.)\1*/){"#{$&.size}"+$1}}

Задача слишком проста, и слишком жаль ...

person Community    schedule 12.10.2010

C, 128 символов

использует статический буфер, что гарантированно вызовет ошибку сегментации

main(){char*c,v[4096],*o,*b,d[4096]="1";for(;o=v,puts(d);strcpy(d,v))for(c=d;*c;o+=sprintf(o,"%d%c",c-b,*b))for(b=c;*++c==*b;);}
person Community    schedule 11.10.2010

Назовите строку «Моррис-иш», если она не содержит ничего, кроме цифр 1–3, и не содержит пробегов более трех цифр. Если исходная строка является моррисовской, все строки, итеративно сгенерированные из нее, также будут моррисовскими. Точно так же, если исходная строка не является моррисовской, тогда никакая сгенерированная строка не будет моррисской, если числа больше десяти не рассматриваются как комбинации цифр (например, если 11111111111 рассматривается как сворачивающаяся на три единицы, а не на «одиннадцать» и один).

Учитывая это наблюдение, каждая итерация, начинающаяся с начального числа Морриса, может быть выполнена в виде следующей последовательности операций поиска / замены:

111 -> CA
11 -> BA
1 -> AA
222 -> CB
22 -> BB
2 -> AB
333 -> CC
33 -> BC
3 -> AC
A -> 1
B -> 2
C -> 3

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

Интересно, сколько существует непересекающихся последовательностей в стиле Морриса?

person Community    schedule 11.10.2010
comment
Их бесконечно много. Пусть M будет набором строк в стиле Морриса, а f:M->M - функцией типа «говорите, что вы видите», которая итеративно генерирует последовательность Морриса. Обратите внимание: если m является элементом M, то f(m) имеет четную длину. Таким образом, строка 1212121...1, в которой есть n 1 и n-1 2 для некоторого неотрицательного n, является началом последовательности Морриса (это не f(m) для любого m). Это дает счетное бесконечное количество начальных точек для последовательностей Морриса; то, что последовательности не пересекаются, требует только f быть инъективным, что прямо верно. - person Hammerite; 12.10.2010
comment
@Hammerite: Хорошее доказательство. При работе с такими последовательностями аргументы четности могут показаться довольно мощными, учитывая наблюдение, что соседние пары должны заканчиваться разными символами. - person supercat; 12.10.2010

Perl (доп. Кредит), 47 символов

$_=pop.$/;{print;s/(.)\1*/$&=~y|||c.$1/ge;redo}
person Community    schedule 12.10.2010

Java

Моя первая попытка сыграть в Code-Golf, я просто скомбинировал это во время части моего класса IB CS:

238 в сжатом виде

Сжатый:

String a="1",b="1",z;int i,c;while(true){System.out.println(b);for(c=0,i=0,b="",z=a.substring(0,1);i<a.length();i++){if(z.equals(a.substring(i,i+1)))c++;else{b+=Integer.toString(c)+z;z=a.substring(i,i+1);c=1;}}b+=Integer.toString(c)+z;a=b;}

Правильно отформатирован:

    String a = "1", b = "1", z;
    int i, c;

    while (true) {      
      System.out.println(b);

      for (c = 0, i = 0, b = "", z = a.substring(0, 1); i < a.length(); i++) {
        if (z.equals(a.substring(i, i + 1))) c++;
        else {
          b += Integer.toString(c) + z;
          z = a.substring(i, i + 1);
          c = 1;
        }
      }

      b += Integer.toString(c) + z;
      a = b;
    }
person Community    schedule 11.10.2010
comment
Изучите другие темы с тегами code-golf, чтобы узнать, что они означают с code-golf. - person BalusC; 11.10.2010
comment
Блин, я бы хотел, чтобы в мою программу IB входил CS. - person Sam Dolan; 11.10.2010
comment
@sdolan это вариант в учебной программе уже более десяти лет (12+ лет назад, когда я получил свой диплом IB) - я полагаю, что он не был удален ни разу с тех пор - person Daniel DiPaolo; 12.10.2010
comment
@ Дэниел Не все школы это предлагают. - person ; 12.10.2010
comment
@ Дэниел: Я был в первом классе в моей средней школе (~ 5 лет назад). Единственным вариантом, который у нас был, был испанский против латыни для нашего требования FL. - person Sam Dolan; 12.10.2010
comment
Мне кажется, комментарий BalusC может быть немного резким: это решение неплохое (играть в гольф на Java сложно), хотя его, вероятно, можно было бы сделать короче ... - person ChristopheD; 14.10.2010
comment
@ChristopheD: ОП отредактировал ответ позже :) Проверьте историю редактирования для оригинальный ответ. Все переменные записываются полностью, а пробелы сохраняются. Каким был Гольфи? В любом случае, для более короткого решения см. мой ответ. - person BalusC; 14.10.2010
comment
@BalusC: а, ладно, это многое объясняет (первоначальная версия не выглядела такой уж интересной) ... - person ChristopheD; 14.10.2010

J, 44 символа с дополнительными баллами

(([:,#;.1@{:,.{:#{.)@(,:0<1,[:|2-/\]))^:(<9)

К сожалению, это генерирует только 9 итераций, но счетчик итераций <9 можно настроить на любое значение. Установка его на a: генерирует бесконечную последовательность, но, очевидно, ее нельзя распечатать.

Использование:

   (([:,#;.1@{:,.{:#{.)@(,:0<1,[:|2-/\]))^:(<9) 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0
2 1 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 1 0 0 0 0 0 0 0 0 0 0
1 1 1 2 2 1 0 0 0 0 0 0 0 0
3 1 2 2 1 1 0 0 0 0 0 0 0 0
1 3 1 1 2 2 2 1 0 0 0 0 0 0
1 1 1 3 2 1 3 2 1 1 0 0 0 0
3 1 1 3 1 2 1 1 1 3 1 2 2 1

   (([:,#;.1@{:,.{:#{.)@(,:0<1,[:|2-/\]))^:(<11) 4
4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 1 1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 3 2 1 1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 3 1 2 2 1 1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 1 1 3 1 1 2 2 2 1 1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 3 2 1 1 3 2 1 3 2 2 1 1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 3 1 2 2 1 1 3 1 2 1 1 1 3 2 2 2 1 1 4 0 0 0 0 0 0 0 0
3 1 1 3 1 1 2 2 2 1 1 3 1 1 1 2 3 1 1 3 3 2 2 1 1 4 0 0 0 0
1 3 2 1 1 3 2 1 3 2 2 1 1 3 3 1 1 2 1 3 2 1 2 3 2 2 2 1 1 4
person Community    schedule 12.10.2010
comment
Это самый длинный J-код, который я когда-либо видел! Блин, нельзя ли сделать этот язык более лаконичным? - person fbrereto; 13.10.2010

Delphi

Delphi - ужасный язык для игры в гольф, но все же:

var i,n:Int32;s,t,k:string;u:char;label l;begin s:='1';l:writeln(s);t:='';u:=s[1
];n:=1;for i:=2to length(s)do if s[i]=u then inc(n)else begin str(n,k);t:=t+k+u;
u:=s[i];n:=1;end;str(n,k);t:=t+k+u;s:=t;goto l;end.

Это 211 байт (и он компилируется как есть).

person Community    schedule 12.10.2010
comment
необъявленный идентификатор Int32 @ Delphi 2007 для win32 - person himself; 12.10.2010
comment
Также вместо среднего FOR вы можете сделать это, чтобы немного сэкономить: n: = 0; i: = 2; z: Inc (n); Inc (i); если s [i] = u, то goto z; str ( n, k); t: = t + k + u; u: = s [i]; n: = 0; goto z; - person himself; 12.10.2010
comment
повысил свой счет, проверьте это, у меня 164. - person himself; 12.10.2010
comment
@himself: В Delphi 2009 Int32 - это целое число. - person Andreas Rejbrand; 12.10.2010

PHP: 111

Моя первая попытка сыграть в гольф-код, результат меня вполне устраивает.

for($x=1;;){echo$y=$x,"\n";for($x="";$y;){for($c=0;$y[$c++]&&$y[$c]==$y[0];);$x.=$c.$y[0];$y=substr($y,$c--);}}

Дает:

> php htdocs/golf.php
1
11
21
... (endless loop)

PHP с дополнительным баллом: 118

for($x=$argv[1];;){echo$y=$x,"\n";for($x="";$y;){for($c=0;$y[$c++]&&$y[$c]==$y[0];);$x.=$c.$y[0];$y=substr($y,$c--);}}

Дает:

> php htdocs/golf.php 4
4
14
1114
3114
... (to infinity and beyond)
person Community    schedule 12.10.2010
comment
Получите +1 за мой ответ :) - person BoltClock; 12.10.2010

Python - 98 символов

from itertools import *
L='1'
while 1:print L;L=''.join('%s'%len(list(y))+x for x,y in groupby(L))

106 символов для бонуса

from itertools import *
L=raw_input()
while 1:print L;L=''.join('%s'%len(list(y))+x for x,y in groupby(L))
person Community    schedule 12.10.2010

Java - 167 символов (с кредитом)

(122 без шаблона класса / основного)


class M{public static void main(String[]a){for(String i=a[0],o="";;System.out.println(i=o),o="")for(String p:i.split("(?<=(.)(?!\\1))"))o+=p.length()+""+p.charAt(0);}}

С символами новой строки:

class M{
 public static void main(String[]a){
  for(String i=a[0],o="";;System.out.println(i=o),o="")
   for(String p:i.split("(?<=(.)(?!\\1))"))
    o+=p.length()+""+p.charAt(0);
 }
}
person Community    schedule 13.10.2010
comment
Сохраняет точки с запятой и фигурные скобки :) - person BalusC; 24.10.2010

Это моя самая первая попытка игры в гольф-код, поэтому, пожалуйста, не будьте со мной слишком суровы!

PHP, 128 122 112 байтов с открывающим тегом

122 116 106 байт без открывающего тега и ведущих пробелов.

<?php for($a="1";!$c="";print"$a\n",$a=$c)for($j=0,$x=1;$a[$j];++$j)$a[$j]==$a[$j+1]?$x++:($c.=$x.$a[$j])&&$x=1;

(Очень жаль, что мне пришлось инициализировать $a как строку, что стоило мне 2 дополнительных байта, иначе я не смогу использовать для нее индексную нотацию.)

Вывод

$ php morris.php
1
11
21
1211
111221
312211
...

PHP (дополнительный кредит), 133 127 117 байт с открывающим тегом

127 121 111 байтов без открытия тега <?php и начальных пробелов.

<?php for($a=$argv[1];!$c="";print"$a\n",$a=$c)for($j=0,$x=1;$a[$j];++$j)$a[$j]==$a[$j+1]?$x++:($c.=$x.$a[$j])&&$x=1;

Вывод

$ php morris.php 3
3
13
1113
3113
132113
1113122113
...
^C
$ php morris.php 614
614
161114
11163114
3116132114
1321161113122114
1113122116311311222114
...

PHP (дополнительный кредит), без открывающих и закрывающих тегов

<?php

for ($a = $argv[1]; !$c = ""; print "$a\n", $a = $c)
{
    for ($j = 0, $x = 1; $a[$j]; ++$j)
    {
        // NB: this was golfed using ternary and logical AND operators:
        // $a[$j] == $a[$j + 1] ? $x++ : ($c .= $x . $a[$j]) && $x = 1;
        if ($a[$j] == $a[$j + 1])
        {
            $x++;
        }
        else
        {
            $c .= $x . $a[$j];
            $x = 1;
        }
    }
}

?>
person Community    schedule 11.10.2010
comment
Coule вы объясните, что делает for(;;)? Пробовал поискать в Google, но это не самая простая вещь для поиска! - person chigley; 12.10.2010
comment
@chigley: это просто указывает на бесконечный цикл. Пустые выражения между точками с запятой указывают на то, что для управления циклом ничего не нужно делать - просто позвольте ему работать вечно. Это похоже на while(1), только на 1 символ короче :) - person BoltClock; 12.10.2010
comment
Ха! Я тебя опередил:]. Вы должны как-нибудь попробовать убрать двойной echo. Может быть, таким образом у вас получится лучшее решение. - person Harmen; 12.10.2010
comment
Вы можете написать оператор if-else немного короче: $a[$j]==$a[$j+1]?$x++:($c.=$x.$a[$j])&&$x=1;. Это экономит вам 6 символов - person Harmen; 12.10.2010
comment
@Harmen: Спасибо за это, как-то раньше я не мог разобраться, используя тернарный оператор :) - person BoltClock; 12.10.2010
comment
@Harmen: Я снова возился со своим кодом, и теперь у меня есть один оператор print вместо двух операторов echo. Я тоже тебя обыграл на этот раз: P - person BoltClock; 12.10.2010
comment
@BoltClock, милый D :, я бы хотел проголосовать дважды: P - почему бы не использовать короткий тег php? <? - person Harmen; 13.10.2010
comment
@Harmen: Я не хочу, чтобы ненавистники коротких открывающих тегов отказали мне в голосах: P - person BoltClock; 13.10.2010
comment
@BoltClock, я на Javascript портировал: всего 87 символов. - person Harmen; 13.10.2010

C ++, 310 символов.

#include <iostream>
#include <list>
using namespace std;
int main(){list<int> l(1,1);cout<<1<<endl;while(1){list<int> t;for(list<int>::iterator i=l.begin();i!=l.end();){list<int>::iterator p=i;++i;while((i!=l.end())&&(*i==*p)){++i;}int c=distance(p,i);cout<<c<<*p;t.push_back(c);t.push_back(*p);}cout<<'\n';l=t;}}

Правильный отступ:

#include <iostream>
#include <list>
using namespace std;

int main() {
    list <int> l(1,1);
    cout << 1 << endl;
    while(1) {
        list <int> t;
        for (list <int>::iterator i = l.begin(); i != l.end();) {
            const list <int>::iterator p = i;
            ++i;
            while ((i != l.end()) && (*i == *p)) {
                ++i;
            }
            int c = distance(p, i);
            cout << c << *p;
            t.push_back(c);
            t.push_back(*p);
        }
        cout << '\n';
        l = t;
    }
}
person Community    schedule 11.10.2010
comment
Я думаю, что вам нужно #include <algorithm> за distance. - person Matteo Italia; 12.10.2010
comment
Точно сказать не могу. Он компилируется с помощью gcc. - person Wok; 12.10.2010

Питон - 117

Мой питон-фу не силен, поэтому я много гуглил для этого. :)

a='1'
while 1:
 print a
 a=''.join([`len(s)`+s[0]for s in''.join([x+' '*(x!=y)for x,y in zip(a,(2*a)[1:])]).split()])

Идея состоит в том, чтобы использовать zip для создания списка пар (a [i], a [i + 1]), использовать внутреннее понимание для вставки пробела, когда a [i]! = A [i + 1], присоединиться к результирующий список в строку и разделение на пробелы, используйте другое понимание этого разделенного списка, чтобы заменить каждый элемент длиной выполнения элемента и первым символом, и, наконец, соединиться, чтобы получить следующее значение в последовательности.

person Community    schedule 11.10.2010

C с дополнительным баллом, 242 (или 184)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define s malloc(1<<20)
main(int z,char**v){char*j=s,*k=s;strcpy(k,*++v);for(;;){strcpy(j,k);z=1;*k=0;while(*j){if(*j-*++j)sprintf(k+strlen(k),"%d%c",z,*(j-1)),z=1;else++z;}puts(k);}}

Вы можете сохранить еще ~ 60 символов, если вы опустите include, gcc все равно будет компилироваться с предупреждениями.

$ ./a.out 11111111 | head
81
1811
111821
31181211
132118111221
1113122118312211
31131122211813112221
132113213221181113213211
111312211312111322211831131211131221
3113112221131112311332211813211311123113112211
person Community    schedule 11.10.2010

C #, 204 байта (256 с дополнительным кредитом)

Моя первая попытка код-гольфа

static void Main(){var v="1";for(;;){Console.Write(v + "\n");var r=v.Aggregate("", (x, y) => x.LastOrDefault()==y?x.Remove(0, x.Length-2)+(int.Parse(x[x.Length-2].ToString())+1).ToString()+y:x+="1"+y);v=r;}}

Читаемая версия, отличие от других в том, что я использую функцию Linq Aggregate

static void Main(){
    var value="1";
    for(;;)
    {
        Console.Write(value + "\n");
        var result = value.Aggregate("", (seed, character) => 
                        seed.LastOrDefault() == character ? 
                            seed.Remove(seed.Length-2) + (int.Parse(seed[seed.Length-2].ToString())+1).ToString() + character
                            : seed += "1" + character
                    );
        value = result;
    }
}
person Community    schedule 12.10.2010

Common Lisp - 124 122 115 символов

(do((l'(1)(do(a r)((not l)r)(setf a(1+(mismatch(cdr l)l))r(,@r,a,(car l))l(nthcdr a l)))))((format t"~{~s~}~%"l)))

С форматированием:

(do ((l '(1) (do (a r) ((not l) r) (setf a (1+ (mismatch (cdr l) l))
                                         r `(,@r ,a ,(car l)) l (nthcdr a l)))))
    ((format t "~{~s~}~%" l)))
person Community    schedule 14.10.2010

F# - 135

let rec m l=Seq.iter(printf "%i")l;printfn"";m(List.foldBack(fun x s->match s with|c::v::t when x=v->(c+1)::v::t|_->1::x::s)l [])
m[1]

Форматированный код

let rec m l=
    Seq.iter(printf "%i")l;printfn"";
    m (List.foldBack(fun x s->
        match s with
        |c::v::t when x=v->(c+1)::v::t
        |_->1::x::s) l [])
m[1]

Тем не менее надеюсь, что смогу найти лучший способ распечатать список или использовать вместо него строку / bigint.

person Community    schedule 23.10.2010

72 байта PHP

<?for(;;)echo$a=preg_filter('#(.)\1*#e','strlen("$0"). $1',$a)?:5554,~õ;

Этот сценарий может быть дополнительно оптимизирован. Но поскольку у нас в PHPGolf ({http://www.phpgolf.org/?p=challenges&challenge_id=28}) точно такая же последовательность, я сохраняю ее такой.

person Community    schedule 20.01.2011

Python - 92 символа

98 с дополнительным баллом

Выходы бесконечно. Я рекомендую перенаправить вывод в файл и быстро нажать Ctrl + C.

x=`1`;t=''
while 1:
 print x
 while x:c=x[0];n=len(x);x=x.lstrip(c);t+=`n-len(x)`+c
 x,t=t,x

Для версии с дополнительным кредитом замените

x=`1`

с участием

x=`input()`
person Community    schedule 14.10.2010

C - 120 знаков

129 с дополнительным кредитом

main(){char*p,*s,*r,x[99]="1",t[99];for(;r=t,puts(p=x);strcpy(x,t))
for(;*p;*r++=p-s+48,*r++=*s,*r=0)for(s=p;*++p==*s;);}

Новая строка используется только для удобства чтения.

Это останавливается, когда происходит сбой (после как минимум 15 итераций). Если ваши библиотеки C используют буферизованный ввод-вывод, вы можете не увидеть никаких выходных данных до segfault. Если да, проверьте с помощью этого кода:

#include<stdio.h>
main(){char*p,*s,*r,x[99]="1",t[99];for(;r=t,puts(p=x),fflush(stdout),1;
strcpy(x,t))for(;*p;*r++=p-s+48,*r++=*s,*r=0)for(s=p;*++p==*s;);}

Это добавляет fflush после каждого вывода.

Без гольфа это выглядело бы примерно так:

int main(){
    char *p, *start, *result, number[99] = "1", temp[99];

    while(1){ /* loop forever */
        puts(number);

        result = temp; /* we'll be incrementing this pointer as we write */
        p = number;    /* we'll be incrementing this pointer as we read */

        while(*p){ /* loop till end of string */
            start = p; /* keep track of where we started */

            while(*p == *start) /* find all occurrences of this character */
                p++;

            *result++ = '0' + p - start; /* write the count of characters, */
            *result++ = *start;          /* the character just counted, */
            *result   = 0;               /* and a terminating null */
        }

        strcpy(number, temp); /* copy the result back to our working buffer */
    }
}

Вы можете увидеть это в действии на ideone.

С дополнительным кредитом код выглядит так:

main(){char*p,*s,*r,x[99],t[99];for(scanf("%s",x);r=t,puts(p=x);strcpy(x,t))
for(;*p;*r++=p-s+48,*r++=*s,*r=0)for(s=p;*++p==*s;);}
person Community    schedule 14.10.2010

C++, 264

#include <iostream>
#include <sstream>
#include <string>
using namespace std;int main(){string l="1\n";for(;;){ostringstream o;int e=1;char m;cout<<l;for(int i=1;i<l.size();i++){m=l[i-1];if(l[i]==m)e++;else if(e){if(m!='\n')o<<e<<m;e=1;}}l=o.str()+'\n';}return 0;}

с правильным отступом:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main()
{
    string l="1\n";
    for(;;)
    {
        ostringstream o;
        int e=1;
        char m;
        cout<<l;
        for(int i=1; i<l.size(); i++)
        {
            m=l[i-1];
            if(l[i]==m)
                e++;
            else if(e)
            {
                if(m!='\n')
                    o<<e<<m;
                e=1;
            }
        }
        l=o.str()+'\n';
    }
    return 0;
}

Пример вывода:

matteo@teoubuntu:~/cpp$ g++ morris.cpp -O3 -o morris.x && ./morris.x | head1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

C ++, 276 (с доплатой)

#include <iostream>
#include <sstream>
#include <string>
using namespace std;int main(){string l;getline(cin,l);for(;;){ostringstream o;int e=1;char m;l+='\n';cout<<l;for(int i=1;i<l.size();i++){m=l[i-1];if(l[i]==m)e++;else if(e){if(m!='\n')o<<e<<m;e=1;}}l=o.str();}return 0;}

с правильным отступом:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main()
{
    string l;
    getline(cin,l);
    for(;;)
    {
        ostringstream o;
        int e=1;
        char m;
        l+='\n';
        cout<<l;
        for(int i=1; i<l.size(); i++)
        {
            m=l[i-1];
            if(l[i]==m)
                e++;
            else if(e)
            {
                if(m!='\n')
                    o<<e<<m;
                e=1;
            }
        }
        l=o.str();
    }
    return 0;
}

Пример вывода:

matteo@teoubuntu:~/cpp$ g++ morris.cpp -O3 -o morris.x && ./morris.x | head
7754 <-- notice: this was inserted manually
7754
271514
121711151114
1112111731153114
31123117132115132114
13211213211711131221151113122114
11131221121113122117311311222115311311222114
3113112221123113112221171321132132211513211321322114
132113213221121321132132211711131221131211132221151113122113121113222114
111312211312111322211211131221131211132221173113112221131112311332211531131122211311123113322114
person Community    schedule 11.10.2010

Delphi, 163 байта (166 с доп.)

Существенно переработанная версия Андреаса Рейбранда. Хорошо, что str () не проверяет тип параметра, иначе мне пришлось бы приводить integer (s) -integer (u).

var q,t,k:string;s,u:pchar;label l,z;begin t:='1';l:writeln(t);q:=t;s:=@q[1];
t:='';z:u:=s;while s^=u^do Inc(s);str(s-u,k);t:=t+k+u^;if s^=#0then goto l;
goto z;end.

Для дополнительной возможности измените t: = '1'; to t: = readln;

person Community    schedule 12.10.2010
comment
Поскольку 0 = 00, вы можете легко сохранить еще один символ. - person Andreas Rejbrand; 12.10.2010

Javascript: 87

Это вдохновлено кодом BoltClock и моими собственными попытками PHP.

for(a="1";!(c="");alert(a),a=c)for(j=0,x=1;a[j];j++)a[j]==a[j+1]?x++:(c+=x+a[j])&&(x=1)

Javascript с доп.: 92

for(a=prompt();!(c="");alert(a),a=c)for(j=0,x=1;a[j];j++)a[j]==a[j+1]?x++:(c+=x+a[j])&&(x=1)

Украсить:

// Start with a=1, an set c to "" every start of the loop
// alert a and set a=c at the end of a loop
for (a = "1"; !(c = ""); alert(a), a = c)

  // Set iterator j to 0, set counter x to 1 at the initialisation
  // detect if a[j] exists at the start of the loop and incremement j at the end
  for (j = 0, x = 1; a[j]; j++)

    // check if the jth and (j+1)th characters are equal
    // if so, increment x,
    // if not, the end of a row is found, add it to c and set x to 1 again
    a[j] == a[j + 1] ? x++ : (c += x + a[j]) && (x = 1)
person Community    schedule 12.10.2010

C #, 140 рабочих символов (177 171 с шаблоном)

class C{static void Main(){var x="1\n";for(;;){System.Console.Write(x);var y="";for(int n,i=0;i<x.Length-1;y+=n+""+x[i],i+=n)n=x[i+1]!=x[i]?1:x[i+2]!=x[i]?2:3;x=y+"\n";}}}

Наблюдение Конвея (IIRC) этого эксплойта о том, что в последовательности не может быть числа больше 3.

        var x = "1\n";
        for (; ; )
        {
            Console.Write(x);
            var y = "";
            var i = 0;
            while (i < x.Length - 1)
            {
                var n = x[i + 1] != x[i] ? 1 : x[i + 2] != x[i] ? 2 : 3;
                y += n + "" + x[i];
                i += n;
            }
            x = y + "\n";
        }
person Community    schedule 12.10.2010

Clojure 111 символов

(loop[a"1"](pr a)(let[x(reduce(fn[a b](str a(count(first b))(nth b 1)))(str)(re-seq #"(.)\1*" a))](recur x)))

Бонусные 119 символов

(loop[a(read-line)](pr a)(let[x(reduce(fn[a b](str a(count(first b))(nth b 1)))(str)(re-seq #"(.)\1*" a))](recur x)))
person Community    schedule 13.10.2010

С # 315 236 228

хорошо, сначала попробуй в гольф код


static void Main(string[]args)
    {string o,s="1";int l=11;while(l-- >0)
    {Console.WriteLine(s);o="";while(s!=""){var c=s.Substring(0,1);int i=Regex.Match(s,"("+c+"*)").Length;o+=i.ToString()+c;s=s.Substring(i);}s=o;}}

вот источник с пробелами разрыва строки> 8.9999999999


static void main( string[] args )
    {
        string sp = "1";
        string ou = "";
        int It = 11;
        while ( It-- > 0 )
        {

            Console.WriteLine(sp);
            ou = "";
            while ( sp != "" )
            {
                var c = sp.Substring(0, 1);
                int i = Regex.Match(sp, "(" + c + "*)").Length;
                ou += i.ToString() + c;
                sp = sp.Substring(i);

            }
            sp = ou;
        }
    }

Дополнительный кредит

static void Main(string[]a)
{string o,s=a[0];int l=11;while(l-- >0)
{Console.WriteLine(s);o="";while(s!=""){var c=s.Substring(0,1);int i=Regex.Match(s,"("+c+"*)").Length;o+=i.ToString()+c;s=s.Substring(i);}s=o;}}
person Community    schedule 11.10.2010

285 248 Chars - лучшее, что я могу сделать на C # (и это тоже без лишних слов!)

Изменить: это тоже мой первый гольф код .. Мне очень понравилось это делать: D

static void Main(){string s="1",x=s;for(;;){char[]c=x.ToCharArray();char d=c[0];x="";int a=0;for(inti=0;i<=c.Length;i++){char q;if(i!=c.Length)q=c[i];else q='0';if (d != q){x+=a.ToString();x+=d.ToString();d=q;a=1;}else a++;}Console.WriteLine(x);}}

Читаемый код:

using System;
class Program
{
    static void Main()
    {
        string startPoint = "1";
        string currentPoint = startPoint;
        while (true)
        {
            char[] currentPointAsCharArray = currentPoint.ToCharArray();
            char previousCharacter = currentPointAsCharArray[0];
            currentPoint = "";
            int countOfCharInGroup = 0;
            for(int i=0;i<=currentPointAsCharArray.Length;i++)
            {
                char c;
                if (i != currentPointAsCharArray.Length)
                    c = currentPointAsCharArray[i];
                else
                    c = '0';
                if (previousCharacter != c)
                {
                    currentPoint += countOfCharInGroup.ToString();
                    currentPoint += previousCharacter.ToString();
                    previousCharacter = c;
                    countOfCharInGroup = 1;
                }
                else
                    countOfCharInGroup++;
            }
            Console.Write(currentPoint + "\n");
        }
    }
}
person Community    schedule 13.10.2010

Scala - 97 символов

Сильно вдохновленный впечатляющим ответом @BalusC:

def m(s:String){println(s);m((""/:(s split"(?<=(.)(?!\\1))")){(a,s)=>a+s.size+s(0)})};m(args(0))
person Community    schedule 27.10.2010

J, 61 символ

J: las=: ,@((# , {.);.1~ 1 , 2 ~:/\ ])&.(10x&#.inv)@]^:(1+i.@[)

Пример:

10 las 1
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221

Обратите внимание, что результатом является фактическая числовая последовательность (см. Текстовые решения на других языках).

Источник здесь: http://rosettacode.org/wiki/Look-and-say_sequence#J < / а>

person Community    schedule 17.11.2010

Lua, 114 байт (с бонусом)

Сжатый:

x=arg[1]while 1 do print(x)i=1 y=''while i<=#x do a=x:sub(i,i)s,e=x:find(a..'+',i)y=y..e+1-s..a;i=e+1 end x=y end

Правильно оформленный:

x=arg[1]
for k=1,10 do
    print(x)
    i=1
    y=''
    while i <= #x do
        a=x:sub(i,i)
        s,e=x:find(a..'+',i)
        y=y..e+1-s ..a
        i=e+1
    end
    x=y
end
person Community    schedule 25.11.2010

Отличный (86 символов) с доплатой:

def f={m,n->n.times{println m;m=(m=~/(\d)\1*/).collect{it[0].size()+""+it[1]}.join()}}

Вызов с помощью: f(1,10)orf(x,n) для кредита.

person Community    schedule 22.05.2014