Le code le plus court par caractère compte pour générer une onde à partir de la chaîne d’entrée.
Une onde est générée en élevant (ligne 1) un caractère plus élevé et en dégradant (ligne + 1) un caractère inférieur. Les caractères égaux sont conservés sur la même ligne (pas d’élévation ni de dégradation).
La saisie est faite de caractères minuscules et de chiffres uniquement, les lettres sont considérées comme supérieures aux nombres.
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
Le nombre de codes comprend les entrées / sorties (c.-à-d. Le programme complet).
Hdddump:
6800B807BF8007BE8200B40EAC3C0D741338D8740A720481EF400181C7A000AB86C3EBE8C3
Exécuter dans MS-DOS avec console de 50 lignes, l’entrée est prise à partir de la ligne de commande.
Par exemple
wave.com 1234567890qwertyuiopasdfghjklzxcvbnm
Téléchargez le binary ici
Mise à jour: effacé trois octets grâce à jrandomhacker
54 caractères, si vous laissez l’interpréteur gérer les entrées / sorties.
e=:|:@((#&' '@],[)"0[:(-<./)0,[:+/\[:(}:(>-<)}.)ai])
65 pour lire explicitement de stdin et écrire sur stdout.
(|:((#&' '@],[)"0[:(-<./)0,[:+/\[:(}:(>-<)}.)a.&i.)~1!:1[3)1!:2[4
e '1234567890qwertyuiopasdfghjklzxcvbnm' z lxvn kcbm j h g ypsf tuoad wri 9 qe 8 0 7 6 5 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 Recherchez les codes ASCII ord =: ai] ord 'p4ssw0rd' 112 52 115 115 119 48 114 100 NB Monter? up =:}: <}. up ord 'p4ssw0rd' 0 1 0 1 0 1 0 NB Descente? down =:}:>}. vers le bas 'p4ssw0rd' 1 0 0 0 1 0 1 NB Combiner pour obtenir ± 1 updown =:}: (> - <)}. updown ord 'p4ssw0rd' 1 _1 0 _1 1 _1 1 NB Commence avec 0, suivi avec des sums partielles sum =: 0, + / \ sum updown ord 'p4ssw0rd' 0 1 0 0 _1 0 _1 0 NB Soustrayez le minimum pour obtenir la séquence avec la base à 0 fix =: - <./ sum de sum updown ord 'p4ssw0rd' 1 2 1 1 0 1 0 1 NB Pour plus de commodité, nommez cette chaîne de fonctions d =: [: fix [: sum [: updown ord
NB Faire des espaces avant les caractères push =: (# & '' @], [) "0 d poussez 'p4ssw0rd' p 4 s s w 0 r ré NB Tournez-le sur le côté |: poussez 'p4ssw0rd' wr p ss 0 d 4 NB Combinez en une fonction nommée… e =: |: @ push NB … Et tout incorporer e =: |: @ ((# & '' @], [) "0 [: (- <./) 0, [: + / \ [: (}: (> - <)}.) ai])
Le code le plus court par caractère compte pour imprimer une «vague» à partir de la chaîne d’entrée.
Console.WriteLine (“une” vague “de la chaîne d’entrée.”);
144 caractères à l’origine par 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)
121 personnages de l’optimisation par Chris Lutz:
$_=<>;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 caractères d’optimisation supplémentaire:
$_=<>;@a=($"x($l=y///c).$/)x(2*$l);s/./substr$a[$l+=$"cmp$&],"@-",1,$"=$&/ge;/\S/&&print for@a
Notez que dans le golf Perl traditionnel, on ajoute généralement le nombre de commutateurs et la longueur du code (ce qui aiderait ici par quelques coups), mais ici nous utilisons des programmes autonomes sans commutateur.
Cela fonctionne dans mon test sur FreeSBIE:
o;main(c){for(;(c=getchar())-10;o=c)printf("\33[1%c%c",co?65:71,c);}
Mais pour voir clairement le résultat, vous devez le lancer avec quelque chose comme ceci:
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"
Est-ce que ça compte?
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+=(iv) q[m][j],v=i,i for i in q: if i!=r:print''.join(i)
Je n’ai cependant pas fait grand chose pour le compresser. Portant à quelque chose avec un opérateur de vaisseau spatial maintenant.
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
Non compressé:
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
$lc;krsort($o);echo join($c,$o);
Version ‘lisible’ :
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, maintenant réduit à 156 caractères:
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)
Haskell, 215 caractères. Je poste ceci parce que je n’aime pas du tout la version de Khoth. En écrivant dans un style raisonnablement fonctionnel, je me suis retrouvé avec un programme beaucoup plus court et plus lisible par l’OMI. Je n’ai pas vraiment essayé de le faire en dehors des noms de variables et de l’espacement. La mise à jour destructive d’un tableau peut le rendre plus court que la réplication d’espaces.
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
l[999][999];p;v=500;r;main(c){for(;(c=getchar())>0; )l[v+=c>p,v-=c
C #:
using System; static class A { static void Main(ssortingng[] 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(;ih)?c:h; d=(c=d;h--) { for (c=0;c
Pesé à 287 comprimés.
Invoquer avec -F// -an
commutateurs
$q=$"x($n=@F);$,=$/;for(@F){/ /&&print@O;substr($O[$n+=$*cmp$_]|=$q,$i++,1)=$_;$*=$_}
Il y a une nouvelle ligne entre le 2ème et le 3ème slash. Sans interrupteurs, vous pouvez faire
$q=$"x($n=@C=split//,<>);$,=$/;for(@C){/ /&&print@O;substr($O[$n+=$*cmp$_]|=$q,$i++,1)=$_;$*=$_}
Haskell (285 caractères):
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)
Quelques compression (260 caractères):
axy|x==y=0 |x>= (p . c 0)
Perl, 88 caractères
Maintenant, édité à 88 caractères:
$_=<>; s/.(?=(.))/($"x40).$&.$"x(39+($1cmp$&))/ge; @_=/.{80}/g; {say map{chop||die}@_;redo}
Était:
$_=<>; s/.(?=(.))/$&.$"x(79+($1cmp$&))/ge; s/^.{40}|.{80}/$&\n/g; print $& while /.$/gm || s/.$//gm * /\n/;
97 caractères (espaces omis). Ce n’est pas si court, mais je me demande si une personne ayant plus d’expérience avec PERL pourrait être en mesure de la raccourcir davantage. Et aussi repérer les bugs. La deuxième ligne utilise des espaces pour créer une onde qui tombe verticalement plutôt qu’horizontalement, sur un écran enveloppant de 80 largeurs. La troisième ligne insère des sauts de ligne. La dernière ligne fait basculer les axes X / Y.
Je me suis d’abord demandé si les deux dernières lignes pouvaient être quelque chose comme un entrelacement (s /. {80} / g) où l’interligne entrelace un tableau de chaînes. Mais il ne semble pas y avoir cette fonction que j’espérais. (Ou y a-t-il dans une bibliothèque?)
Un premier cri en C #. L’entrée doit être fournie comme premier argument de ligne de commande.
using System; using C = System.Console; static class P { static void Main(ssortingng[] 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]); } } }
Cela donne 280 octets compressés à partir de.
using System;using C=System.Console;static class P{static void Main(ssortingng[]a){var b=a[0];var l=b.Length;int y=0,z=0;for(int i=0;i
Tentative numéro deux avec une approche différente.
using System; using System.Collections.Generic; static class P { static void Main(ssortingng[] a) { var b = a[0] + "$"; var l = new List(); 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); } }
La boucle peut être réécrite pour utiliser un bloc 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]); }
Cela donne 321 octets légèrement modifiés et compressés - un peu plus que la première tentative, mais beaucoup plus volumineux.
using System;static class P{static void Main(ssortingng[]a){var b=a[0]+"$";var r=new System.Collections.Generic.List
Je suis sûr que cela peut être fait avec beaucoup moins de code, si quelqu’un veut le modifier, ce serait excellent. Je le laisse lisible.
$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
let F(s:ssortingng)=(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 ssortingng(r)))s.Length
Avec les espaces ajoutés pour faciliter la lecture,
let F(s:ssortingng) = (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 ssortingng(r)) ) s.Length
Je suis coincé là pour le moment. Je ne pense pas que C battra J sur celui-ci. Merci à strager pour aider à couper 8 caractères, cependant.
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+=*pc;for(;++w<998;strspn(p," ")-79&&puts(p)) 79[p=a[w]]=0;}
Formaté:
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 ssortingng. * * **** WARNING: Input ssortingng must not be more than 79 characters! **** */ *p;a[y][x++] = c = *p++) /* read from input ssortingng 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 */ }
Je n'ai pas pris la peine de supporter une entrée de plus de 79 caractères, car cela causerait une confusion sur la plupart des terminaux.
Une solution Java, pas particulièrement compressée (maintenant modifiée pour lire à partir de stdin).
public class W { public static void main(Ssortingng[] x) { Ssortingng 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 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 caractères de code)
using System; class Program { static void Main(ssortingng[] 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] : ' '); } }
Compacté: (324 caractères de code)
using System;class A{static void Main(ssortingng[] args){var I=args[0];int M=0,X=0;var H=new int[I.Length];for(var i=1;iI[i-1]?1:(I[i]=M;r--,Console.WriteLine())for(var c=0;c
Utiliser les astuces des commentaires (283 caractères):
using System;class A{static void Main(ssortingng[] 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(;iI[i-1]?1:(I[i]h?X:h;}for(r=X;r>=M;r--,Console.Write('\n'))for(;c
159 caractères, la version la plus “conviviale”:
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}'
La version suivante est 153 caractères, mais vous ne pouvez entrer qu’une seule ligne. Pour en entrer plus d’un, vous devez redémarrer le programme. Les règles ne sont pas claires quant à savoir si cela est autorisé ou non, mais j’ai pensé qu’il serait préférable de publier les deux versions quand même:
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}'
Et voici une version de 149 caractères – celle-ci est un script plutôt qu’un shell simple, et fonctionne également pour une seule ligne d’entrée, mais ne continue pas à accepter les entrées après cette première ligne, ce qui est probablement une bonne chose :
$_=<>;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}
Aucun d’entre eux n’est aussi court que la solution Perl déjà publiée, mais ils semblent certainement battre Python et Ruby. Et d’ailleurs, il y a plus d’une façon de le faire.
Une stratégie complètement différente a permis d’économiser quelques caractères par rapport à l’autre solution.
let F(s:ssortingng)=(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 ssortingng(Array.init L (fun c->if r=h.[L-1-c]then s.[c]else ' '))))s.Length
Avec des espaces:
let F(s:ssortingng) = (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 ssortingng(Array.init L (fun c -> if r=h.[L-1-c] then s.[c] else ' '))) ) s.Length
C # 545 octet non compressé
using System; using System.Linq; class Program{ static void Main(ssortingng[] b){ var s = b[0]; var t = new System.Collections.Generic.Dictionary(); 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); } }
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
Non compressé:
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
tester
s="1234567890qwertyuiopasdfghjklzxcvbnm"
court
=(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})
$b);$r[$d].=' ';$r[$d][$k++]=$b=$a;}ksort($r);echo join("\n",$r);
Version lisible:
while(-1<$a=fgetc(STDIN)){ $d+=$a<$b^-($a>$b); $r[$d].=' '; $r[$d][$k++]=$b=$a; } ksort($r); echo join("\n",$r);
' ': :c;1/:a,.+,{:N;a,a{:@c<+c@:c<-.N=[ c]\=}%.[n+'']\$-1= ==\;}%
Générer l'onde ligne par ligne
{:N;a,a{:@c<+c@:c<-.N=[ c]\=}%
Filtrer les lignes vides
.[n+'']\$-1= ==\
args1[,;{ch},1_]@1]o o>:><-0 0a:/+,/&-;{()@:'{" "`}}@;{};;{(){`}#`}" ":|P
Je viens de traduire la solution J en ASL.
XQuery
(257 octets)
declare variable$i external;let$c:=ssortingng-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])
Puisque XQuery est purement déclaratif, j'ai dû simuler l'entrée comme étant passée dans une variable externe. Voici la ligne de commande pour l'exécuter avec XQSharp:
xquery wave.xq !method=text i='1234567890qwertyuiopasdfghjklzxcvbnm'
Si la chaîne a été transmise en tant qu'élément de contexte, cela peut être réduit davantage, mais la définition de l'élément de contexte sur une valeur autre qu'un nœud n'est pas prise en charge avec toutes les implémentations XQuery (et non par l'outil de ligne de commande XQSharp):
let$c:=ssortingng-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])
Juste 228 octets.