代码高尔夫:波

挑战

按字符计数的最短代码从inputstring中生成一个波形。

通过提升(line-1)较高的字符和降低(line + 1)较低的字符来生成wave。 相同的字符保持在同一行(不提升或降级)。

input仅由小写字母和数字组成,字母被认为高于数字。

testing用例:

Input: 1234567890qwertyuiopasdfghjklzxcvbnm Output: z lxvn kcbm j h g ypsf tuoad wri 9 qe 8 0 7 6 5 4 3 2 1 Input: 31415926535897932384626433832795028841971693993751058209749445923078164062862 Output: 9 9 8 6 6 9 6 8 7 3 3 4 2 4 8 9 88 3 4 5 2 5 5 2 33 3 7 5 2 4 9 9 99 7 1 1 3 2 0 1 7 6 3 3 5 8 8 6 1 1 5 2 9 9 3 7 1 4 6 8 0 0 7 9 5 2 0 0 2 6 4 44 2 

代码计数包括input/​​输出(即完整程序)。

x86机器代码(37字节)

进制打印:

 6800B807BF8007BE8200B40EAC3C0D741338D8740A720481EF400181C7A000AB86C3EBE8C3 

使用50行控制台在MS-DOS中运行,input从命令行中获取。

例如

 wave.com 1234567890qwertyuiopasdfghjklzxcvbnm 

在这里下载二进制

更新:谢谢jrandomhacker三个字节

Ĵ

54个字符,如果你让解释器处理input/输出。

 e=:|:@((#&' '@],[)"0[:(-<./)0,[:+/\[:(}:(>-<)}.)ai]) 

65显式读取标准input并写入标准输出。

 (|:((#&' '@],[)"0[:(-<./)0,[:+/\[:(}:(>-<)}.)a.&i.)~1!:1[3)1!:2[4 
 e'1234567890qwertyuiopasdfghjklzxcvbnm'
                              ž
                             lxvn
                            kcbm
                           Ĵ
                          H
                         G
                ypsf
               tuoad
            WRI
         9 qe
        8 0
       7
      6
    五
    4
   3
  2
 1
 e'31415926535897932384626433832795028841971693993751058209749445923078164062862'
             9 9 8 6 6
      9 6 8 7 3 3 4 2 4 8 9 88
 3 4 5 2 5 5 2 33 3 7 5 2 4 9 9 99 7
  1 1 3 2 0 1 7 6 3 3 5 8 8 6
                                         1 1 5 2 9 9 3 7 1 4 6 8
                                                   0 0 7 9 5 2 0 0 2 6
                                                          4 44 2


    NB。  查找ASCII码
 ord =:ai] 
     ord'p4ssw0rd'
 112 52 115 115 119 48 114 100

    NB。  往上走?
 up =:}:<}。 
     up ord'p4ssw0rd'
 0 1 0 1 0 1 0

    NB。  下降?
 down =:}:>}。 
     down ord'p4ssw0rd'
 1 0 0 0 1 0 1

    NB。  合并得到±1
 updown =:}:(>  -  <)}。 
     updown ord'p4ssw0rd'
 1 _1 0 _1 1 _1 1

    NB。  从0开始,跟进部分款项
 sum =:0,+ / \ 
     sum updown ord'p4ssw0rd'
 0 1 0 0 _1 0 _1 0

    NB。  减去最小值得到基数为0的序列
 修复=: -  <./ 
     修复总结updown ord'p4ssw0rd'
 1 2 1 1 0 1 0 1

    NB。  为了方便起见,命名这个函数链
 d =:[:fix [:sum [:updown ord
    NB。  在字符之前留出空格
 push =:(#&''@],[)“0 d 
     推'p4ssw0rd'
  p
   4
 小号
 小号
 w ^
  0
 [R
  d

    NB。  打开它的一面
 |:推'p4ssw0rd'
     WR
 p ss 0 d
  4

    NB。  结合成一个命名的function...
 e =:|:@ push
    NB。  ...并内联一切
 e =:|:@((#&''@],[)“0 [:( -  <./)0,[:+ / \ [:(}:(>  -  <)}。)ai])

字符计数的最短代码从inputstring打印“波”。

Console.WriteLine(“来自inputstring的一个'波'”);

Perl(94个字符)

144个字符原始由barnaba:

chop($_=<>);$l=length;push(@a," "x$l)for(1..$l*2);$l+=(ord $p<=>ord $_),substr($a[$l],$r++,1)=$p=$_ for(split //);/^\s+$/||print "$_\n" for(@a)

Chris Lutz优化的121个字符:

$_=<>;chop;$a[@a]=" "x$l for 1..($l=length)*2;$l+=$p cmp$_,substr($a[$l],$r++,1)=$p=$_ for split//;/\S/&&print"$_\n"for@a

进一步优化94个字符:

$_=<>;@a=($"x($l=y///c).$/)x(2*$l);s/./substr$a[$l+=$"cmp$&],"@-",1,$"=$&/ge;/\S/&&print for@a

请注意,在传统的Perl高尔夫球中,通常会增加开关的数量和代码的长度(这可以通过几个笔划来获得帮助),但是这里我们使用了不带开关的独立程序。

C VT100terminal(76个字符)

这在我对FreeSBIE的testing中起作用:

 o;main(c){for(;(c=getchar())-10;o=c)printf("\33[1%c%c",c<o?66:c>o?65:71,c);} 

但是为了清楚地看到输出结果,你必须运行这样的东西:

clear ; printf "\n\n\n\n\n" ; echo the quick brown fox jumps over the lazy dog | ./a.out ; printf "\n\n\n\n\n"

这算什么?

Python(161个字符)

 v,s="",raw_input() m=n=len(s) r=[' ']*n q=[r[:]for i in range(2*n)] for j,i in enumerate(s): m+=(i<v)-(i>v) q[m][j],v=i,i for i in q: if i!=r:print''.join(i) 

尽pipe如此,我还没有做太多的压缩。 现在把它移植到一个飞船运营商的东西。

Ruby:99字节

 r,a,q,i=[],"",99,0 gets.chars{|x|t=r[q+=a<=>x]||="" a=x r[q]+=" "*(it.size)+x i+=1} puts r.compact 

未压缩:

 r,a,q,i = [],"",99,0 gets.chars { |x| t = r[q+=a<=>x] ||= "" a = x r[q] += " "*(it.size)+x i += 1 } puts r.compact 

PHP(138个字符)

 <?for($lc=$i=$h=0;"\n"!=$c=fgetc(STDIN);$o[$h]=sprintf("%- {$i}s%s",@$o[$h],$lc=$c),$i++)$h+=$c<$lc?-1:$c>$lc;krsort($o);echo join($c,$o); 

“可读”版本:

 <? for ( $last_ch = $i = $level = 0; "\n" != $ch = fgetc(STDIN); $out[$level] = sprintf("%- {$i}s%s", @$out[$level], $last_ch = $ch), $i++ ) $level += $ch < $last_ch ? -1 : $ch > $last_ch; krsort($out); echo join($ch,$out); 

Python 2.x,现在下降到156个字符:

 s=raw_input() R=range(len(s)) m=[0] for i in R[1:]:m+=[m[-1]-cmp(s[i],s[i-1])] for x in range(min(m),max(m)+1):print''.join(m[i]==x and s[i]or' 'for i in R) 

哈斯克尔,215个字符。 我发布这个,因为我根本不喜欢Khoth的版本。 仅仅通过写作一个合理的function风格,我结束了一个大大缩短和IMO更可读的程序。 我实际上并没有试图使它与variables名和间距分开。 破坏性地更新数组可能会使其比复制空格更短。

 import Char import List main=getLine>>=(putStr.p) ps=unlines$transpose[z++(y:x)|(m,y)<-zip ns,let(x,z)=splitAt m$replicate(maximum n)' '] where o=map ord s n=scanl(+)0$map signum$zipWith(-)(tail o)o 

C89(151个字符)

 l[999][999];p;v=500;r;main(c){for(;(c=getchar())>0; )l[v+=c>p,v-=c<p][++r]=*l[v]=p=c;for(v=999;v--;)for (c=0;c++<=r;)*l[v]&&putchar(c<=r?32|l[v][c]:10);} 

C#:

 using System; static class A { static void Main(string[] a) { var s=a[0];var r=""; int i=1,h=0,d=0,c=0,n=s.Length; var m=new int[n]; m[0]=0; for(;i<n;i++) { c+=Math.Sign(s[i]-s[i-1]); h=(c>h)?c:h; d=(c<d)?c:d; m[i]=c; } for(;h>=d;h--) { for (c=0;c<n;c++) r+=(m[c]==h)?s[c]:' '; r+="\n"; } Console.Write(r); } } 

重287压缩。

Perl,85个字符与开关,96没有

-F// -an开关调用

 $q=$"x($n=@F);$,=$/;for(@F){/ /&&print@O;substr($O[$n+=$*cmp$_]|=$q,$i++,1)=$_;$*=$_} 

第二个和第三个斜杠之间有一个换行符。 没有开关,你可以做

 $q=$"x($n=@C=split//,<>);$,=$/;for(@C){/ /&&print@O;substr($O[$n+=$*cmp$_]|=$q,$i++,1)=$_;$*=$_} 

Haskell(285个字符):

 heightDiff xy | x == y = 0 | x < y = -1 | True = 1 heights h (x:y:z)= (x,h):(heights (h+(heightDiff xy) ) (y:z)) heights h [y] = [(y,h)] makech ((x,h):xs) i = (if i==h then x else ' '):makech xs i makech [] _ = [] printAll xs = mapM_ (putStrLn . (makech xs)) [(minimum $ map snd xs)..(maximum $ map snd xs)] main = getLine >>= (printAll . heights 0) 

一些压缩(260个字符):

 axy|x==y=0 |x<y= -1 |True=1 ch (x:y:z)=(x,h):(c(h+(axy))(y:z)) ch [y]=[(y,h)] d ((x,h):xs)i=(if i==h then x else ' '):d xs i d [] _=[] p xs = mapM_ (putStrLn .(d xs)) [(minimum $ map snd xs)..(maximum $ map snd xs)] main = getLine >>= (p . c 0) 

Perl,88个字符

现在,编辑为88个字符:

 $_=<>; s/.(?=(.))/($"x40).$&.$"x(39+($1cmp$&))/ge; @_=/.{80}/g; {say map{chop||die}@_;redo} 

是:

 $_=<>; s/.(?=(.))/$&.$"x(79+($1cmp$&))/ge; s/^.{40}|.{80}/$&\n/g; print $& while /.$/gm || s/.$//gm * /\n/; 

97个字符(省略空格)。 这并不是那么简短,但是我想知道是否有更多PERL经验的人可以进一步缩短。 还发现任何错误。 第二行使用空格来创build一个垂直落下的波浪,而不是水平的,在一个宽度为80的包裹屏幕上。 第三行插入换行符。 最后一行翻转X / Y轴。

我最初想知道最后两行可能是交错(s /。{80} / g),其中交错交错string数组。 但似乎没有这个function,我希望。 (或者在图书馆里?)

在C#中的第一个呼喊。 input必须作为第一个命令linie参数提供。

 using System; using C = System.Console; static class P { static void Main(string[] a) { var b = a[0]; var l = b.Length; int y = 0, z = 0; for (int i = 0; i < l - 1; i++) { y += Math.Sign(b[i] - b[i + 1]); z = Math.Min(y, z); } y = 0; for (int i = 0; i < l - 1; i++) { C.SetCursorPosition(i, y - z); C.Write(b[i]); y += Math.Sign(b[i] - b[i + 1]); } } } 

这从压缩产生280个字节。

using System;using C=System.Console;static class P{static void Main(string[]a){var b=a[0];var l=b.Length;int y=0,z=0;for(int i=0;i<l-1;i++){y+=Math.Sign(b[i]-b[i+1]);z=Math.Min(y,z);}y=0;for(int i=0;i<l-1;i++){C.SetCursorPosition(i,yz);C.Write(b[i]);y+=Math.Sign(b[i]-b[i+1]);}}}

用不同的方法尝试第二个。

 using System; using System.Collections.Generic; static class P { static void Main(string[] a) { var b = a[0] + "$"; var l = new List<string>(); var y = -1; for (int i = 0; i < b.Length - 1; i++) { if ((y == -1) || (y == l.Count)) { y = y < 0 ? 0 : y; l.Insert(y, b.Substring(i, 1).PadLeft(i + 1)); } else { l[y] = l[y].PadRight(i) + b[i]; } y += Math.Sign(b[i] - b[i + 1]); } foreach (var q in l) Console.WriteLine(q); } } 

循环可以进一步重写为使用try / catch块。

 for (int i = 0; i < b.Length - 1; i++) { try { l[y] = l[y].PadRight(i) + b[i]; } catch { y = y < 0 ? 0 : y; l.Insert(y, b.Substring(i, 1).PadLeft(i + 1)); } y += Math.Sign(b[i] - b[i + 1]); } 

这产生稍微修改和压缩的321字节 – 多一点,然后第一次尝试,但很多robuster。

using System;static class P{static void Main(string[]a){var b=a[0]+"$";var r=new System.Collections.Generic.List<string>();var y=-1;for(int i=0;i<b.Length-1;i++){try{r[y]=r[y].PadRight(i)+b[i];}catch{y=y<0?0:y;r.Insert(y,b[i].ToString().PadLeft(i+1));}y+=Math.Sign(b[i]-b[i+1]);}foreach(var l in r)Console.WriteLine(l);}}

电源shell

当然,如果有人想编辑这些代码,那么可以用更less的代码来完成。 我留下它可读。

 $v = (Read-Host).ToCharArray() $r = @(0) for($i = 1; $i -lt $v.length; $i++) { $p = $i - 1 $r += $r[$p] + [System.Math]::Sign($v[$i] - $v[$p]) $t = [System.Math]::Max($t, $r[$i]) $b = [System.Math]::Min($b, $r[$i]) } for($i = $t; $i -ge $b; $i--) { for($x = 0; $x -lt $r.length; $x ++) { if($r[$x] -eq $i) { $o += $v[$x] } else { $o += " " } } $o += "`n" } $o 

F#,242个字符:

 let F(s:string)=(fun L->let a=Array.init(L*3)(fun _->Array.create L ' ')in Seq.fold(fun(r,p,c)n->let r=r+sign(int p-int n)in a.[r].[c]<-n;r,n,c+1)(L,s.[0],0)s;for r in a do if Array.exists((<>)' ')r then printfn"%s"(new string(r)))s.Length 

随着空白添加更容易阅读,这是

 let F(s:string) = (fun L-> let a = Array.init (L*3) (fun _ -> Array.create L ' ') in Seq.fold (fun (r,p,c) n -> let r = r + sign(int p-int n) in a.[r].[c]<-n; r, n, c+1) (L, s.[0], 0) s; for r in a do if Array.exists ((<>) ' ') r then printfn "%s" (new string(r)) ) s.Length 

C(157个字符)

我暂时被困在那里。 我不认为C会在这一个上击败J. 尽pipe如此,感谢strager帮助修剪了8个字符。

 char*p,a[999][80];w,x,y=500;main(c){for(gets(memset(p=*a,32,79920));*p; a[y][x++]=c=*p++)y+=*p<c,y-=*p>c;for(;++w<998;strspn(p," ")-79&&puts(p)) 79[p=a[w]]=0;} 

格式:

 char *p, /* pointer to current character (1st) or line (2nd) */ a[999][80]; /* up to 998 lines of up to 79 characters */ w, x, y = 500; /* three int variables. y initialized to middle of array */ main(c){ for(gets(memset(p=*a, 32, 79920)); /* 999 * 80 = 79920, so the entire array is filled with space characters. * memset() returns the value of its first parameter, so the above is * a shortcut for: * * p = *a; * memset(p, 32, 79920); * gets(p); * * Incidentally, this is why I say "up to 998 lines", since the first * row in the array is used for the input string. * * **** WARNING: Input string must not be more than 79 characters! **** */ *p;a[y][x++] = c = *p++) /* read from input string until end; * put this char in line buffer and in prev */ y += *p < c, /* if this char < prev char, y++ */ y -= *p > c; /* the use of commas saves from using { } */ for(;++w < 998; /* will iterate from 1 to 998 */ strspn(p, " ") - 79 && /* strspn returns the index of the first char in its first parameter * that's NOT in its second parameter, so this gets the first non- * space character in the string. If this is the NULL at the end of * the string (index 79), then we won't print this line (since it's blank). */ puts(p)) /* write the line out to the screen (followed by '\n') */ 79[p = a[w]] = 0; /* same as "(p = a[y])[79] = 0", * or "p = a[y], p[79] = 0", but shorter. * Puts terminating null at the end of each line */ } 

我没有支持超过79个字符的input,因为这会导致大多数terminal上的混淆。

一个Java解决scheme,没有特别压缩(现在修改为从标准input读取)。

 public class W { public static void main(String[] x) { String s = new java.util.Scanner(System.in).nextLine(); int i,j; int t = s.length(); char[] b = s.toCharArray(); char[][] p = new char[2*t][t]; int q = t; char v = b[0]; for (i=0; i<2*t; i++) { for (j=0; j<t; j++) { p[i][j] = ' '; } } p[q][0] = v; String z = new String(p[0]); for (i=1; i<t; i++) { char c = b[i]; int d = (c == v) ? 0 : (c > v ? -1 : 1); q += d; p[q][i] = c; v = c; } for (i=0; i<2*t; i++) { String n = new String(p[i]); if (!n.equals(z)) { System.out.println(n); } } } } 

C# (564个字符的代码)

 using System; class Program { static void Main(string[] args) { var input = args[0]; int min = 0, max = 0; var heights = new int[input.Length]; for (var i = 1; i < input.Length; i++) { heights[i] = heights[i-1] + (input[i] > input[i-1] ? 1 : (input[i] < input[i-1] ? -1 : 0)); min = Math.Min(min, heights[i]); max = Math.Max(max, heights[i]); } for (var row = max; row >= min; row--, Console.WriteLine()) for (var col = 0; col < input.Length; col++) Console.Write(heights[col] == row ? input[col] : ' '); } } 

压缩:(324个字符的代码)

 using System;class A{static void Main(string[] args){var I=args[0];int M=0,X=0;var H=new int[I.Length];for(var i=1;i<I.Length;i++){H[i]=H[i-1]+(I[i]>I[i-1]?1:(I[i]<I[i-1]?-1:0));M=Math.Min(M,H[i]);X=Math.Max(X,H[i]);}for(var r=X;r>=M;r--,Console.WriteLine())for(var c=0;c<I.Length;c++)Console.Write(H[c]==r?I[c]:' ');}} 

使用评论(283个字符)的技巧:

 using System;class A{static void Main(string[] a){var I=a[0];int M=0,X=0,i=1,r,h,c=0,l=I.Length;var H=new int[l];for(;i<l;i++){h=H[i-1]+(I[i]>I[i-1]?1:(I[i]<I[i-1]?-1:0));H[i]=h;M=M<h?M:h;X=x>h?X:h;}for(r=X;r>=M;r--,Console.Write('\n'))for(;c<l;c++)Console.Write(H[c]==r?I[c]:' ');}} 

Perl 5.10

159个字符,最“人性化”版本:

 perl -nE'chop;@l=split//;$l{$_}=$l{$_-1}+($l[$_]cmp$l[$_-1])for 0..$#l;%e=();for$x(sort{$b<=>$a}grep{!$e{$_}++}values%l){say map{$l{$_}==$x?$l[$_]:" "}0..$#l}' 

以下版本为153个字符,但只能input一行。 要input多个,您必须重新启动程序。 规则不清楚是否允许这样做,但我认为无论如何,最好同时发布两个版本:

 perl -nE'chop;@l=split//;$l{$_}=$l{$_-1}+($l[$_]cmp$l[$_-1])for 0..$#l;for$x(sort{$b<=>$a}grep{!$e{$_}++}values%l){say map{$l{$_}==$x?$l[$_]:" "}0..$#l}' 

这里是一个149个字符的版本 – 这个是一个脚本而不是一个shell的内容,也只适用于一行input,但不会在第一行之后继续接受input,这可能是一件好事:

 $_=<>;chop;@l=split//;$l{$_}=$l{$_-1}+($l[$_]cmp$l[$_-1])for 0..$#l;for$x(sort{$b<=>$a}grep{!$e{$_}++}values%l){say map{$l{$_}==$x?$l[$_]:" "}0..$#l} 

这些都不像已经发布的Perl解决scheme那么短,但是它们似乎击败了Python和Ruby。 此外,还有更多的方法来做到这一点。

F#,235个字符

与我的另一个解决scheme相比,完全不同的策略节省了一些字符。

 let F(s:string)=(fun L->let _,_,h=Seq.fold(fun(p,h,l)n->let r=h-sign(int n-int p)in n,r,r::l)(s.[0],0,[0])s in for r in Seq.min h..Seq.max h do printfn"%s"(new string(Array.init L (fun c->if r=h.[L-1-c]then s.[c]else ' '))))s.Length 

用空格:

 let F(s:string) = (fun L-> let _,_,h = Seq.fold (fun (p,h,l) n -> let r = h - sign(int n-int p) in n,r,r::l) (s.[0],0,[0]) s in for r in Seq.min h..Seq.max h do printfn "%s" (new string(Array.init L (fun c -> if r=h.[L-1-c] then s.[c] else ' '))) ) s.Length 

C# 545字节未压缩

 using System; using System.Linq; class Program{ static void Main(string[] b){ var s = b[0]; var t = new System.Collections.Generic.Dictionary<int, string>(); int y=0, p=0; for (int i = 0; i < s.Length; i++){ y += Math.Sign(s[i] - p); p = s[i]; if (!t.ContainsKey(y)) t.Add(y, ""); t[y] = t[y].PadRight(i) + s[i]; } foreach (var v in t.OrderBy(a => -a.Key)) Console.WriteLine(v.Value); } } 

ruby:109字节,计算换行字符!

 s=gets r,a,q,i=[],s[0,1],99,0 s.chars{|x|q+=a<=>x a=x t=r[q]||="" r[q]+=" "*(it.size)+x i+=1} puts r.compact 

未压缩:

 s = gets r,a,q,i = [],s[0,1],99,0 s.chars { |x| q += a<=>x a = x t = r[q] ||= "" r[q] += " "*(it.size)+x i += 1 } puts r.compact 

Groovy(195个字符)

testing

 s="1234567890qwertyuiopasdfghjklzxcvbnm" 

 =(s=~/./).collect{(char)it} e=' ';x=0;l=[];u=[] w.eachWithIndex({it,n-> if(l.size()>x){l[x]+=e*(nu[x]-1)+it;u[x]=n}else{l+=e*n+it;u+=n} if(w[n+1]>it)x++else x--;}) l.reverse().each({println it}) 

PHP:108个字符

 <?while(-1<$a=fgetc(STDIN)){$d+=$a<$b^-($a>$b);$r[$d].=' ';$r[$d][$k++]=$b=$a;}ksort($r);echo join("\n",$r); 

可读版本:

 <? while(-1<$a=fgetc(STDIN)){ $d+=$a<$b^-($a>$b); $r[$d].=' '; $r[$d][$k++]=$b=$a; } ksort($r); echo join("\n",$r); 

Golfscript – 65字符

 ' ': :c;1/:a,.+,{:N;a,a{:@c<+c@:c<-.N=[ c]\=}%.[n+'']\$-1= ==\;}% 

逐行生成波形

 {:N;a,a{:@c<+c@:c<-.N=[ c]\=}% 

滤除空白行

 .[n+'']\$-1= ==\ 

ASL:73

 args1[,;{ch},1_]@1]o o>:><-0 0a:/+,/&-;{()@:'{" "`}}@;{};;{(){`}#`}" ":|P 

我只是将J解决scheme翻译成ASL。

XQuery的

(257字节)

 declare variable$i external;let$c:=string-to-codepoints($i),$h:= for$x at$p in$c return sum(for$x in 1 to$p let$d:=$c[$x]-$c[$x -1]return(-1[$d>0],1[$d<0]))return codepoints-to-string(for$p in min($h)to max($h),$x at$q in($c,10)return(32[$h[$q]!=$p],$x)[1]) 

由于XQuery纯粹是声明式的,所以我不得不将input伪装成一个外部variables。 这是用XQSharp运行这个命令行:

 xquery wave.xq !method=text i='1234567890qwertyuiopasdfghjklzxcvbnm' 

如果string作为上下文项传入,那么可以进一步减less该string,但是将上下文项设置为非节点值并不是所有的XQuery实现(而不是XQSharp命令行工具)都支持:

 let$c:=string-to-codepoints(.),$h:= for$x at$p in$c return sum(for$x in 1 to$p let$d:=$c[$x]-$c[$x -1]return(-1[$d>0],1[$d<0]))return codepoints-to-string(for$p in min($h)to max($h),$x at$q in($c,10)return(32[$h[$q]!=$p],$x)[1]) 

只有228个字节。