代码高尔夫:莫里斯序列

挑战

按字符计数的最短代码将输出莫里斯数列 。 莫里斯数字序列Morris Number Sequence) ,也被称为Look-and-say序列,是一个数字序列,开头如下:

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

您可以无限地生成序列(即,您不必生成特定的数字)。

I / O期望

该程序不需要任何input(但接受input的奖励点,从而提供从任意起点或数字开始的选项)。 至less你的程序必须从1开始。

产出至less是期望的顺序:

 1 11 21 1211 111221 312211 ... 

额外的信用

如果你要额外的信贷,你需要做这样的事情:

 $ morris 1 1 11 21 1211 111221 312211 ... $ morris 3 3 13 1113 3113 132113 ... 

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 

什么?
获取序列中下一个数字的过程:将当前数字转换为string,追加一个换行符并遍历字符。 对于每个数字,如果前面的数字P相同,则递增计数器c 。 否则,将cP添加到下一个数字中,然后更新这些variables。 我们附加的换行符允许将最后一组数字添加到下一个数字。

详细的细节可以通过检查GolfScript文档来获得。 (注意|用作variables。)

哈斯克尔: 115 88 85

 import List mx=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] fx=putStrLn x>>f(group x>>=m) main=f"1" 

Perl(46个字符)

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

额外学分(52个字符)

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

Perl,46个字符

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

额外的信贷,51个字符:

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

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--)} 

允许中断序列(通过单击“取消”),所以我们不locking用户代理并挂钩CPU。 它也允许从任何正整数(额外的信用)开始。

现场示例: http : //jsbin.com/izeqo/2

Mathematica – 62 53 50个字符 – 包括额外的功劳

编辑:40个字符…但从右到左:(

奇怪的是,如果我们读到从左到右的顺序(即1,11,12,1121,..),40个字符就足够了

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

那是因为Tally生成一个列表{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} 🙂

这里是我的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 ... 

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 

例如:

 $ python morris.py | head 1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 

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) 

这里是我的实现(在Prolog中):

序言与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->(MTO=0-[N|R]-_,N);MTO=1-RN)},!,m(M,O,R). 

简单的香草序言,代码更加readeable(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]). 

输出Morris序列:m(D)。 其中D是“起始”数字。

ruby – 52

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

任务太简单了,太单纯了…

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",cb,*b))for(b=c;*++c==*b;);} 

如果只包含数字1-3,则调用一个string“Morris-ish”,并且不包含任何超过三位的数字。 如果初始string是Morris-ish,那么从它迭代产生的所有string也将是Morris-ish。 同样,如果初始string不是Morris-ish,那么没有生成的string将是Morris-ish,除非数字大于十的数字被视为数字的组合(例如,如果11111111111被视为折叠成三个,而不是“十一”一个)。

鉴于这种观察,每一次从Morris-ish种子开始的迭代都可以按以下查找/replace操作顺序完成:

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

请注意,序列是上述replace之前的Morris-ish,每个生成的对的第二个字符将与前后两个对的第二个字符不同; 因此不可能有多于三个相同的字符顺序。

我不知道有多less不相交的Morris-ish序列?

Perl(额外信贷),47个字符

 $_=pop.$/;{print;s/(.)\1*/$&=~y

c.$1/ge;redo}

Java的

我在“代码高尔夫”上的第一次尝试,就是在我的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; } 

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 

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); } } 

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个字节 (并按原样编译)。

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) 

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)) 

这是我第一次尝试编码高尔夫球,所以请不要对我太苛刻!

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初始化为一个string,但是我花了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(额外的信用),与打开和closures标签ungolfed

 <?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; } } } ?> 

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; } } 

Python – 117

我的python不强,所以我做了很多的search。 🙂

 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]时使用内部理解插入空格,join将结果列表转换为一个string,然后在空格上进行拆分,在这个拆分表上使用另一个理解来replace每个元素的运行长度和第一个字符,最后连接到下一个值。

C w /额外信贷,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);}} 

如果你省略了include,你可以保存另外60个字符,gcc仍然会编译警告。

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

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; } } 

Common Lisp – 124 122 115 Chars

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

使用格式:

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

F# – 135

 let rec ml=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 ml= 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] 

仍然有希望,我可以find一个更好的方式来打印列表或使用string/ bigint。

PHP 72字节

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

这个脚本可能会进一步优化。 但是因为我们已经在PHPGolf({http://www.phpgolf.org/?p=challenges&challenge_id=28})完全一样的顺序,所以我保持这种方式。

Python – 92个字符

98额外的信贷

无限输出。 我build议将输出redirect到一个文件,并快速按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 

对于额外的信用版本,请replace

 x=`1` 

 x=`input()` 

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;);} 

换行是为了可读性的缘故。

当它发生段错误(在至less15次迭代之后)时停止。 如果您的C库使用缓冲I / O,那么在segfault之前可能看不到任何输出。 如果是这样,用这个代码testing:

 #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

Ungolfed,它看起来像这样:

 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;);}