Code Golf: Jouer à Tesortings

Les bases:

Considérez les tetrominoes suivants et le terrain de jeu vide:

                                             0123456789
     IOZTLSJ []
                                            []
     # ## ## ### # ## # []
     # ## ## # # ## # []
     # ## ## []
     # []
                                            [==========]

Les dimensions du terrain de jeu sont fixes. Les chiffres en haut sont juste ici pour indiquer le numéro de la colonne (voir aussi input).

Consortingbution:

1 . On vous donne un terrain de jeu spécifique (basé sur ce qui précède) qui peut déjà être rempli en partie avec des tétromino (cela peut être dans un fichier séparé ou fourni via stdin).

Échantillon d’entrée:

 []
 []
 []
 []
 [# # #]
 [## ######]
 [==========]

2 . Vous recevez une chaîne qui décrit (séparés par des espaces) quel tétromino insérer (et dérouler) à quelle colonne. Les tétrominoïdes n’ont pas besoin d’être pivotés. L’entrée peut être lue à partir de stdin.

Échantillon d’entrée:

T2 Z6 I0 T7 

Vous pouvez supposer que l’entrée est «bien formée» (ou qu’elle produit un comportement indéfini lorsque ce n’est pas le cas).

Sortie

Rendre le champ résultant (les lignes «complètes» doivent disparaître) et imprimer le nombre de points (chaque ligne supprimée compte pour 10 points).

Exemple de sortie basé sur l’échantillon ci-dessus:

 []
 []
 []
 [# ###]
 [# ###]
 [##### ####]
 [==========]
 dix

Gagnant:

Solution la plus courte (par nombre de caractères de code). Les exemples d’utilisation sont sympas. Amusez-vous au golf!

Edit : ajouté une réputation de +500 pour attirer davantage l’attention sur les efforts déjà déployés (et éventuellement de nouvelles solutions à cette question) …

GolfScript – 181 caractères

Les nouvelles lignes ne sont pas nécessaires. La sortie est en sortie standard, bien que certaines erreurs soient présentes dans stderr.
\10 doit être remplacé par le caractère ASCII correspondant pour que le programme comporte 181 caractères.

 {):X!-{2B{" #"=}%X" ":f*+-1%}%:P;:>.{\!:F;>P{\(@{3&\(@.2$&F|:F;|}%\+}%\+F![f]P+:P ;}do;{"= "&},.,7^.R+:R;[>0="#"/f*]*\+}0"R@1(XBc_""~\10"{base}:B/3/~4*"nIOZTLSJR " ";:"*~;n%)n*~ 10R*+n* 

Echantillon E / S:

 $ cat inp [ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] T2 Z6 I0 T7 $ cat inp|golfscript tesortings.gs 2>/dev/null [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10 

Tetromino compression:
Les pièces sont stockées sous forme de trois chiffres de base 8. C’est une représentation binary simple, par exemple T=[7,2,0], S=[6,3,0], J=[2,2,3] . [1] est utilisé pour le morceau I en compression, mais celui-ci est défini explicitement à [1,1,1,1] plus tard (le 4* dans le code). Tous ces tableaux sont concaténés en un seul tableau, qui est converti en un entier, puis en une chaîne (base 126 pour minimiser les caractères non imprimables, la longueur et ne pas rencontrer utf8). Cette chaîne est très courte: "R@1(XBc_" .

La décompression est alors simple. Nous faisons d’abord une conversion en base 126 suivie d’une conversion en base 8 ( "~\10"{base}/ , c’est-à-dire en parcourant "~\10" et en effectuant une conversion de base pour chaque élément). Le tableau résultant est divisé en groupes de 3, le tableau pour I est fixe ( 3/~4* ). Nous convertissons ensuite chaque élément en base 2 et (après suppression des zéros), nous remplaçons chaque chiffre binary par le caractère de cet index dans la chaîne " #" ( 2base{" #"=}%...-1% – notez que nous avons besoin inverser le tableau sinon 2 deviendrait "# " au lieu de " #" ).

Format de carte / pièce, laisser tomber
Le tableau est simplement un tableau de chaînes, une pour chaque ligne. Aucun travail n’est initialement effectué sur ce sujet, nous pouvons donc le générer avec n/( sur l’entrée. Les pièces sont également des tableaux de chaînes, remplis d’espaces à gauche pour leur position X, mais sans espaces de fin. le tableau, et tester continuellement s’il y a une collision.

Les tests de collision se font en parcourant tous les personnages de la pièce et en les comparant au caractère de la même position sur le tableau. Nous voulons considérer # + = et # + # comme des collisions, nous testons donc si ((piecechar & 3) & boardchar) est différent de zéro. Lors de cette itération, nous mettons également à jour (une copie de) le tableau avec ((piecechar & 3) | boardchar), qui définit correctement la valeur pour les paires # + , + # , + [ . Nous utilisons cette carte mise à jour en cas de collision après avoir déplacé la pièce sur une autre ligne.

Supprimer les lignes remplies est assez simple. Nous supprimons toutes les lignes pour lesquelles "= "& return false. Une rangée remplie n’aura ni = ni , la conjonction sera donc une chaîne vide, ce qui équivaut à false. Ensuite, nous comptons le nombre de lignes supprimées, ajoutons le nombre à la partition et ajoutons le nombre de lignes "[ ... ]" . Nous générons cela de manière compacte en prenant la première ligne de la grid et en remplaçant # par .

Prime
Puisque nous calculons à quoi ressemblerait le tableau dans chaque position du morceau, nous pouvons les conserver sur la stack au lieu de les supprimer! Pour un total de trois caractères de plus, nous pouvons afficher toutes ces positions (ou deux caractères si les états de la carte sont à interligne simple).

 {):X!-{2B{" #"=}%X" ":f*+-1%}%:P;:>.{>[f]P+:P(!:F;{\(@{3&\(@.2$&F|:F;|}%\+}%\+F!} do;{"= "&},.,7^.R+:R;[>0="#"/f*]*\+}0"R@1(XBc_""~\10"{base}:B/3/~4*"nIOZTLSJR " ";:"*~;n%)n*~ ]{n*n.}/10R* 

Perl, 586 523 483 472 427 407 404 386 387 356 353 caractères

(Nécessite Perl 5.10 pour l’opérateur défini ou // ).

Prend toutes les entrées de stdin. Encore du golf sérieux.
Notez que ^ Q représente ASCII 17 (DC1 / XON), ^ C représente ASCII 3 et ^ @ représente ASCII 0 (NUL).

 while(<>){push@A,[split//]if/]/;while(/\w/g){for$i(0..6){for($f=0,$j=4;$j--;){$c=0;map{if($_){$i--,$f=$j=3,redo if$A[$k=$i+$j][$C=$c+$'+1]ne$";$A[$k][$C]="#"if$f}$c++}split//,unpack"b*",chr vec"3^@'^@c^@^Q^C6^@\"^C^Q^Q",index(OTZLSJI,$&)*4+$j,4;$s+=10,@A[0..$k]=@A[$k,0..$k-1],map{s/#/ /}@{$A[0]},$i++if 9 

Version commentée:

 while(<>){ # store the playfield as an AoA of chars push@A,[split//]if/]/; # while we're getting pieces while(/\w/g){ # for each line of playfield for$i(0..6){ # for each line of current piece for($f=0,$j=4;$j--;){ # for each column of current piece $c=0; map{ if($_){ # if there's a collision, restart loop over piece lines # with a mark set and playfield line decremented $i--,$f=$j=3,redo if$A[$k=$i+$j][$C=$c+$'+1]ne$"; # if we already found a collision, draw piece $A[$k][$C]="#"if$f } $c++ # pieces are stored as a bit vector, 16 bits (4x4) per piece, # expand into array of 1's and 0's }split//,unpack"b*",chr vec"3^@'^@c^@^Q^C6^@\"^C^Q^Q",index(OTZLSJI,$&)*4+$j,4; # if this playfield line is full, remove it. Done by array slicing # and substituting all "#"'s in line 0 with " "'s $s+=10,@A[0..$k]=@A[$k,0..$k-1],map{s/#/ /}@{$A[0]},$i++if 9 

Edit 1: du golf sérieux, correction du bogue de sortie.
Edit 2: certains inlining, fusionné deux boucles en une pour une sauvegarde nette de (roulement de batterie ...) 3 chars, divers golf.
Edit 3: une élimination commune des sous-expressions, une fusion un peu constante et un regex modifié.
Edit 4: modification de la représentation des tetrominoes en un vecteur de bit compacté, misc golfing.
Edit 5: traduction plus directe de la lettre tetromino à l'index du tableau, utilisez des caractères non imprimables, divers golf.
Edit 6: correction du bug de la ligne supérieure, introduite dans r3 (edit 2), repérée par Nakilon. Utilisez plus de caractères non imprimables.
Edit 7: utilisez vec pour obtenir des données tetromino. Profitez du fait que le terrain de jeu a des dimensions fixes. if déclaration => if modificateur, la fusion des boucles de l'édition 2 commence à porter ses fruits. Utilisez // pour le cas 0-score.
Edit 8: correction d'un autre bug, introduit dans r6 (edit 5), repéré par Nakilon.
Edit 9: ne créez pas de nouvelles références lorsque vous effacez des lignes, déplacez simplement les références via le découpage de tableau. Fusionner deux map en une. Regex plus intelligent. "Plus intelligent" for . Golfs divers.
Edit 10: tableau tetromino en ligne, version commentée ajoutée.

Rubis – 427 408 398 369 359

 t=[*$< ] o=0 u=->f{f.transpose} a=u[t.reverse.join.scan /#{'( |#)'*10}/] t.pop.split.map{|w|m=(g='I4O22Z0121T01201L31S1201J13'[/#{w[0]}\d+/].scan(/0?\d/).zip a.drop w[1].to_i).map{|r,b|(b.rindex ?#or-1)-r.size+1}.max g.map{|r,b|b.fill ?#,m+r.size,r.to_i} v=u[a] v.reject!{|i|i-[?#]==[]&&(o+=10;v)< <[' ']*10} a=u[v]} puts u[a].reverse.map{|i|?[+i*''+?]},t[-1],o 

Script shell Bash ( 301 304 caractères)

UPDATE: Correction d’un bug impliquant des pièces qui se prolongent dans la rangée supérieure. En outre, la sortie est maintenant envoyée à la sortie standard, et en bonus, il est possible de relancer le script pour continuer à jouer à un jeu (auquel cas vous devez additionner le score total).

Cela inclut les caractères non imprimables, donc j’ai fourni un vidage hexadécimal. Enregistrez-le sous tesortings.txt :

 0000000: 7461 696c 202d 3120 245f 7c7a 6361 743e tail -1 $_|zcat> 0000010: 753b 2e20 750a 1f8b 0800 35b0 b34c 0203 u;. u.....5..L.. 0000020: 5590 516b 8330 10c7 dff3 296e 4c88 ae64 U.Qk.0....)nL..d 0000030: a863 0c4a f57d 63b0 07f7 b452 88d1 b4da .cJ}c....R.... 0000040: 1a5d 5369 91a6 df7d 899a d05d 5e72 bfbb .]Si...}...]^r.. 0000050: fbff 2fe1 45d5 0196 7cff 6cce f272 7c10 ../.E...|.l..r|. 0000060: 387d 477c c4b1 e695 855f 77d0 b29f 99bd 8}G|....._w..... 0000070: 98c6 c8d2 ef99 8eaa b1a5 9f33 6d8c 40ec ...........3m.@. 0000080: 6433 8bc7 eeca b57f a06d 27a1 4765 07e6 d3.......m'.Ge.. 0000090: 3240 dd02 3df1 2344 f04a 0d1d c748 0bde 2@..=.#DJ..H.. 00000a0: 75b8 ed0f 9eef 7bd7 7e19 dd16 5110 34aa u.....{.~...Q.4. 00000b0: c87b 2060 48a8 993a d7c0 d210 ed24 ff85 .{ `H..:.....$.. 00000c0: c405 8834 548a 499e 1fd0 1a68 2f81 1425 ...4T.I....h/..% 00000d0: e047 bc62 ea52 e884 42f2 0f0b 8b37 764c .GbR.B....7vL 00000e0: 17f9 544a 5bbd 54cb 9171 6e53 3679 91b3 ..TJ[.T..qnS6y.. 00000f0: 2eba c07a 0981 f4a6 d922 89c2 279f 1ab5 ...z....."..'... 0000100: 0656 c028 7177 4183 2040 033f 015e 838b .V.(qwA. @.?.^.. 0000110: 0d56 15cf 4b20 6ff3 d384 eaf3 bad1 b9b6 .V..K o......... 0000120: 72be 6cfa 4b2f fb03 45fc cd51 d601 0000 rlK/..E..Q.... 

Ensuite, à l’invite de commande bash, de préférence avec elvis plutôt que vim installé en tant que vi :

 $ xxd -r tesortings.txt tesortings.sh $ chmod +x tesortings.sh $ cat < < EOF > b > [ ] > [ ] > [ ] > [ ] > [ # # #] > [ ## ######] > [==========] > EOF $ ./tesortings.sh T2 Z6 I0 T7 2>/dev/null -- removed stuff that is not in standard out -- [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10 

Comment ça marche

Le code s’auto-extrait de la même manière que les programmes exécutables compressés à l’aide du script gzexe . Les pièces Tetromino sont représentées par des séquences de commandes de l’éditeur vi. Le comptage de caractères est utilisé pour détecter les collisions et le comptage de lignes est utilisé pour calculer le score.

Le code décompressé:

 echo 'rej.jj:wq!m'>I echo '2rejh.:wq!m'>O echo '2rej.:wq!m'>Z echo '3rejh1.:wq!m'>T echo 'rej.j2.:wq!m'>L echo 'l2rej2h.:wq!m'>S echo 'lrej.jh2.:wq!m'>J for t do for y in `seq 1 5` do echo -n ${y}jk$((${t:1}+1))l|cat - ${t:0:1}|vi b>0 grep ========== m>0||break [ `tr -cd '#'n done cat n>b grep -v '##########' b>m $((S+=10*(`wc -l < b`-`wc -l < m`))) yes '[ ]'|head -7|cat - m|tail -7>b done cat b echo $S 

Le code original avant de jouer au golf:

 #!/bin/bash mkpieces() { pieces=('r@jjj' '2r@jh.' '2r@j.' '3r@jh1.' 'r@j.j2.' 'l2r@j2h.' 'lr@j.jh2.') letters=(IOZTLSJ) for j in `seq 0 9`; do for i in `seq 0 6`; do echo "jk$(($j+1))l${pieces[$i]}:wq! temp" > ${letters[$i]}$j done done } counthashes() { tr -cd '#' < $1 | wc -c } droppiece() { for y in `seq 1 5`; do echo -n $y | cat - $1 | vi board > /dev/null egrep '={10}' temp > /dev/null || break [ `counthashes board` -eq `counthashes temp` ] || break tr @ "#" < temp > newboard done cp newboard board } removelines() { egrep -v '#{10}' board > temp SCORE=$(($SCORE + 10 * (`wc -l < board` - `wc -l < temp`))) yes '[ ]' | head -7 | cat - temp | tail -7 > board } SCORE=0 mkpieces for piece; do droppiece $piece removelines done cat board echo $SCORE 

Python: 504 519 caractères

(Solution Python 3) Nécessite actuellement de définir l’entrée dans le format indiqué en haut (le code d’entrée n’est pas comptabilisé). Je vais développer pour lire depuis un fichier ou stdin plus tard. Maintenant, fonctionne avec une invite, il suffit de coller l’entrée dans (8 lignes au total).

 R=range f,p=[input()[1:11]for i in R(7)],p for(a,b)in input().split(): t=[' '*int(b)+r+' '*9for r in{'I':'#,#,#,#','O':'##,##','Z':'##, ##','T':'###, # ','L':'#,#,##','S':' ##,##','J':' #, #,##'}[a].split(',')] for r in R(6-len(t),0,-1): for i in R(len(t)): if any(a==b=='#'for(a,b)in zip(t[i],f[r+i])):break else: for i in R(0,len(t)): f[r+i]=''.join(a if b!='#'else b for(a,b)in zip(t[i],f[r+i])) if f[r+i]=='#'*10:del f[r+i];f[0:0]=[' '*10];p+=10 break print('\n'.join('['+r+']'for r in f[:7]),p,sep='\n') 

Je ne sais pas si je peux économiser beaucoup plus là-bas. Beaucoup de caractères sont perdus lors de la transformation en champs de bits, mais cela permet d’économiser beaucoup plus de caractères que de travailler avec les chaînes. Aussi, je ne suis pas sûr de pouvoir supprimer plus de blancs, mais je vais essayer plus tard.
Ne sera pas en mesure de le réduire beaucoup plus; Après avoir eu la solution basée sur les champs de bits, je suis revenu aux chaînes, car j’ai trouvé un moyen de le compresser davantage (sauvegarde de 8 caractères sur le champ de bits!). Mais étant donné que j’ai oublié d’inclure le L et que j’avais une erreur avec les points à l’intérieur, mon compte de personnages ne fait que grimper… Peut-être que je trouverai quelque chose plus tard pour le compresser un peu plus, mais Pour le code original et commenté, voir ci-dessous:

Version originale:

 field = [ input()[1:11] for i in range(7) ] + [ 0, input() ] # harcoded tetrominoes tetrominoes = {'I':('#','#','#','#'),'O':('##','##'),'Z':('##',' ##'),'T':('###',' # '),'L':('#','#','##'),'S':(' ##','##'),'J':(' #',' #','##')} for ( f, c ) in field[8].split(): # shift tetromino to the correct column tetromino = [ ' ' * int(c) + r + ' ' * 9 for r in tetrominoes[f] ] # find the correct row to insert for r in range( 6 - len( tetromino ), 0, -1 ): for i in range( len( tetromino ) ): if any( a == b == '#' for (a,b) in zip( tetromino[i], field[r+i] ) ): # skip the row if some pieces overlap break else: # didn't break, insert the tetromino for i in range( 0, len( tetromino ) ): # merge the tetromino with the field field[r+i] = ''.join( a if b != '#' else b for (a,b) in zip( tetromino[i], field[r+i] ) ) # check for completely filled rows if field[r+i] == '#' * 10: # remove current row del field[r+i] # add new row field[0:0] = [' '*10] field[7] += 10 # we found the row, so abort here break # print it in the requested format print( '\n'.join( '[' + r + ']' for r in field[:7] ) ) # and add the points = 10 * the number of redundant lines at the end print( str( field[7] ) ) 

Ruby 1.9, 357 355 353 339 330 310 309 caractères

 d=0 e=[*$< ] e.pop.split.map{|f|f="L\003\003\007J\005\005\007O\007\007Z\007\013S\013\007I\003\003\003\003T\017\005"[/#{f[j=0]}(\W*)/,1].bytes.map{|z|?\0+?\0*f[1].hex+z.to_s(2).tr("01"," #")[1,9]} k,f,i=i,[p]+f,e.zip(f).map{|l,m|l.bytes.zip(m.to_s.bytes).map{|n,o|j|=n&3&q=o||0;(n|q).chr}*""}until j>0 e=[] e+=k.reject{|r|r.sum==544&&e<  

Notez que les \000 échappements (y compris les octets nuls sur la troisième ligne) doivent être remplacés par leur équivalent non imprimable.

Échantillon d'entrée:

 [ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] T2 Z6 I0 T7 

Usage:

 ruby1.9 tesortings.rb < input 

ou

 ruby1.9 tesortings.rb input 

C, 727 […] 596 581 556 517 496 471 461 457 caractères

C’est mon premier golf de code, je pense que le nombre de personnages peut être beaucoup plus bas, ce serait bien si les golfeurs expérimentés pouvaient me donner des conseils.

La version actuelle peut également gérer des zones de jeu de différentes dimensions. L’entrée peut avoir des sauts de ligne au format DOS / Windows et Unix.

Le code était assez simple avant l’optimisation, les tetrominoes sont stockés dans 4 entiers qui sont interprétés comme un tableau (7 * 3) x4 bits, le playfield est stocké tel quel, les tuiles sont supprimées et les lignes complètes sont supprimées au début et après chaque chute de tuile.

Je n’étais pas sûr de savoir comment compter les caractères, alors j’ai utilisé la taille de fichier du code avec tous les sauts de ligne inutiles supprimés.

EDIT 596 => 581: Grâce à KitsuneYMG, tout a fonctionné parfaitement, à l’exception de la suggestion %ls . De plus, j’ai remarqué que putch au lieu de putchar peut être utilisé ( getch ne fonctionne pas) et a supprimé toutes les parenthèses de #define G

EDIT 581 => 556: N’était pas satisfait des boucles F restantes et nestedes, donc il y avait des fusions, des modifications et des suppressions de boucles, assez déroutantes mais qui en valaient vraiment la peine.

EDIT 556 => 517: Finalement, nous avons trouvé un moyen de créer a tableau int. Un peu de N; fusionné avec c , plus de break .

EDIT 496 => 471: La largeur et la hauteur du terrain de jeu sont maintenant fixées.

EDIT 471 => 461: modifications mineures, putchar utilisé à nouveau comme putch n’est pas une fonction standard.

EDIT: Correction de bugs, les lignes complètes ont été supprimées avant que les tuiles ne tombent au lieu d’ après , donc des lignes complètes pourraient être laissées à la fin. Le correctif ne change pas le nombre de caractères.

 #define N (c=getchar()) #define GT[j%4]&1< w){t=C[c];x=N-86; W(c){F(j,12)if(G&&X>1?a[X]-32:0)c=0; F(j,12)if(G&&X>w&&!c)a[Xw]=35;x+=w;}N; F(i,6){A=0;t=i*w;F(x,w)A|=(a[t+x]==32); if(!A){s++;F(j,t)a[t+wj]=a[tj]; x=1;W(a[x]-93)a[x++]=32;}}} F(i,91)putchar(a[i]);printf("%i0",s);} 

Python 2.6+ – 334 322 316 caractères

397 368 366 caractères non compressés

 #coding:l1 exec'xÚEPMO!½ï¯ i,P*Ýlš%ì‰=‰Ö–*†þz©‰:‡—Lò¾fÜ”bžAù,MVi™.ÐlǃwÁ„eQL&•uÏÔ‹¿1O6ǘ.€LSLÓ'¼›î”3òšL¸tŠv[ѵl»h;ÁºŽñÝ0Àë»Ç‡ÛûH.ª€¼âBNjr}¹„V5¾3Dë@¼¡•gO. ¾ô6 çÊsÃЮürÃ1&›ßVˆùZ`Ü€ÿžcx±ˆ‹sCàŽ êüRô{U¯ZÕDüE+³ŽFA÷{CjùYö„÷¦¯Î[0þøõ…(Îd®_›â»E#–Y%'›”ëýÒ·X‹d¼.ß9‡kD'.decode('zip') 

La nouvelle ligne unique est requirejse et je l’ai comptée comme un seul personnage.

La page de code du navigateur mumbo jumbo peut empêcher le copier-coller de ce code, vous pouvez donc générer le fichier à partir de ce code:

 s = """ 23 63 6F 64 69 6E 67 3A 6C 31 0A 65 78 65 63 27 78 DA 45 50 4D 4F 03 21 10 BD EF AF 20 69 2C 50 2A 02 DD 6C 9A 25 EC AD 07 8D 89 07 3D 89 1C D6 96 2A 86 05 02 1B AD FE 7A A9 89 3A 87 97 4C F2 BE 66 DC 94 62 9E 41 F9 2C 4D 56 15 69 99 0F 2E D0 6C C7 83 77 C1 16 84 65 51 4C 26 95 75 CF 8D 1C 15 D4 8B BF 31 4F 01 36 C7 98 81 07 2E 80 4C 53 4C 08 D3 92 BC 9B 11 EE 1B 10 94 0B 33 F2 9A 1B 4C B8 74 8A 9D 76 5B D1 B5 6C BB 13 9D 68 3B C1 BA 8E F1 DD 30 C0 EB BB C7 87 DB FB 1B 48 8F 2E 1C AA 80 19 BC E2 42 4E 6A 72 01 7D B9 84 56 35 BE 33 44 8F 06 EB 40 BC A1 95 67 4F 08 2E 20 BE F4 36 A0 E7 CA 73 C3 D0 AE FC 72 C3 31 26 9B DF 56 88 AD F9 5A 60 DC 80 FF 9E 63 78 B1 88 8B 73 43 E0 8E A0 EA FC 52 F4 7B 55 8D AF 5A 19 D5 44 FC 45 2B B3 8E 46 9D 41 F7 7B 43 6A 12 F9 59 F6 84 F7 A6 01 1F AF CE 5B 30 FE F8 F5 85 28 CE 64 AE 5F 9B E2 BB 45 23 96 59 25 92 9B 94 EB FD 10 D2 B7 58 8B 64 BC 2E DF 39 87 6B 44 27 2E 64 65 63 6F 64 65 28 27 7A 69 70 27 29 """ with open('golfsortings.py', 'wb') as f: f.write(''.join(chr(int(i, 16)) for i in s.split())) 

Essai

intesortings

 []
 []
 []
 []
 [# # #]
 [## ######]
 [==========]
 T2 Z6 I0 T7

Les nouvelles lignes doivent être de type Unix (saut de ligne uniquement). Une nouvelle ligne à la dernière ligne est facultative.

Tester:

 > python golfsortings.py 

Ce code décompresse le code d' origine et l'exécute avec exec . Ce code décompressé pèse 366 caractères et ressemble à ceci:

 import sys r=sys.stdin.readlines();s=0;p=r[:1];a='[##########]\n' for l in r.pop().split(): n=int(l[1])+1;i=0xE826408E26246206601E>>'IOZTLSJ'.find(l[0])*12;m=min(zip(*r[:6]+[a])[n+l].index('#')-len(bin(i>>4*l&31))+3for l in(0,1,2)) for l in range(12): if i>>l&2:c=n+l/4;o=m+l%4;r[o]=r[o][:c]+'#'+r[o][c+1:] while a in r:s+=10;r.remove(a);r=p+r print''.join(r),s 

Les nouvelles lignes sont obligatoires et ont un caractère chacune.

N'essayez pas de lire ce code. Les noms de variables sont littéralement choisis au hasard à la recherche de la compression la plus élevée (avec des noms de variables différents, j'ai vu jusqu'à 342 caractères après la compression). Une version plus compréhensible suit:

 import sys board = sys.stdin.readlines() score = 0 blank = board[:1] # notice that I rely on the first line being blank full = '[##########]\n' for piece in board.pop().split(): column = int(piece[1]) + 1 # "+ 1" to skip the '[' at the start of the line # explanation of these three lines after the code bits = 0xE826408E26246206601E >> 'IOZTLSJ'.find(piece[0]) * 12 drop = min(zip(*board[:6]+[full])[column + x].index('#') - len(bin(bits >> 4 * x & 31)) + 3 for x in (0, 1, 2)) for i in range(12): if bits >> i & 2: # if the current cell should be a '#' x = column + i / 4 y = drop + i % 4 board[y] = board[y][:x] + '#' + board[y][x + 1:] while full in board: # if there is a full line, score += 10 # score it, board.remove(full) # remove it, board = blank + board # and replace it with a blank line at top print ''.join(board), score 

Le nœud est dans les trois lignes cryptiques que j'ai dit que j'expliquerais.

La forme des tetrominoes est encodée dans le nombre hexadécimal. Chaque tetronimo est considéré comme occupant une grid de cellules 3x4, où chaque cellule est vide (un espace) ou complète (un signe numérique). Chaque pièce est ensuite codée avec 3 chiffres hexadécimaux, chaque chiffre décrivant une colonne à 4 cellules. Les chiffres les moins significatifs décrivent les colonnes les plus à gauche et le bit le moins significatif de chaque chiffre décrit la cellule la plus haute de chaque colonne. Si un bit est 0, alors cette cellule est vide, sinon c'est un "#". Par exemple, le I tetronimo est codé comme 00F , avec les quatre bits du chiffre le moins significatif pour coder les quatre signes numériques dans la colonne la plus à gauche et le T est 131 , le bit supérieur étant placé à gauche. et le droit, et les deux premiers bits au milieu.

Le nombre hexadécimal entier est alors décalé d'un bit vers la gauche (multiplié par deux). Cela nous permettra d'ignorer le bit le plus bas. Je vais vous expliquer pourquoi dans une minute.

Donc, étant donné le morceau actuel de l'entrée, nous trouvons l'index dans ce nombre hexadécimal où commencent les 12 bits décrivant sa forme, puis le décalent pour que les bits 1–12 (saut du bit 0) de la variable bits décrivent le morceau actuel.

L'affectation à drop détermine combien de lignes du haut de la grid la pièce tombera avant d'atterrir sur d'autres fragments de pièces. La première ligne indique combien de cellules vides se trouvent en haut de chaque colonne du terrain de jeu, tandis que la seconde trouve la cellule occupée la plus basse dans chaque colonne du morceau. La fonction zip renvoie une liste de n-uplets, où chaque n-uplet comprend la n- ème cellule de chaque élément de la liste d’entrée. Ainsi, en utilisant le tableau d’échantillons d’échantillons, zip(board[:6] + [full]) renverra:

 [ ('[', '[', '[', '[', '[', '[', '['), (' ', ' ', ' ', ' ', ' ', ' ', '#'), (' ', ' ', ' ', ' ', '#', '#', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', ' ', ' ', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', '#', '#', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', '#', '#', '#'), (']', ']', ']', ']', ']', ']', ']') ] 

Nous sélectionnons le tuple de cette liste correspondant à la colonne appropriée et trouvons l'index du premier '#' dans la colonne. C'est pourquoi nous avons ajouté une ligne "complète" avant d'appeler zip , de sorte que l' index aura un retour sensible (au lieu de générer une exception) lorsque la colonne est vide.

Ensuite, pour trouver le '#' le plus bas dans chaque colonne de la pièce, nous décalons et masquons les quatre bits qui décrivent cette colonne, puis nous utilisons la fonction bin pour en faire une chaîne de uns et de zéros. La fonction bin ne renvoie que les bits significatifs, il suffit donc de calculer la longueur de cette chaîne pour trouver la cellule occupée la plus basse (bit le plus significatif). La fonction bin ajoute également '0b' , nous devons donc soustraire cela. Nous ignorons également le bit le moins significatif. C'est pourquoi le nombre hexadécimal est décalé d'un bit vers la gauche. Ceci est à prendre en compte pour les colonnes vides, dont les représentations de chaîne auront la même longueur qu'une colonne avec seulement la cellule supérieure pleine (telle que la pièce T ).

Par exemple, les colonnes de I tetromino, comme mentionné précédemment, sont F , 0 et 0 . bin(0xF) est '0b1111' . Après avoir ignoré le '0b' , nous avons une longueur de 4, ce qui est correct. Mais bin(0x0) est 0b0 . Après avoir ignoré le '0b' , nous avons toujours une longueur de '1, ce qui est incorrect. Pour en tenir compte, nous avons ajouté un bit supplémentaire à la fin, afin que nous puissions ignorer ce bit insignifiant. Par conséquent, le +3 dans le code est là pour tenir compte de la longueur supplémentaire prise par le '0b' au début et du bit non significatif à la fin.

Tout cela se produit dans une expression de générateur pour trois colonnes ( (0,1,2) ), et nous prenons le résultat min pour trouver le nombre maximal de lignes que le morceau peut déposer avant de toucher l'une des trois colonnes.

Le rest devrait être assez facile à comprendre en lisant le code, mais la boucle for suit ces affectations ajoute la pièce au tableau. Après cela, la boucle while supprime les lignes entières, les remplaçant par des lignes vides en haut, et calcule le score. A la fin, le tableau et le score sont imprimés sur la sortie.

Python, 298 caractères

Bat toutes les solutions de langage non ésotériques jusqu’à présent (Perl, Ruby, C, bash …)


… et n’utilise même pas la chicanerie à compression de code.

 import os r=os.read b='[%11c\n'%']'*99+r(0,91) for k,v in r(0,99).split(): t=map(ord,' -:G!.:; -:; !-.!"-. !". !./')['IJLOSTZ'.find(k)*4:][:4];v=int(v)-31 while'!'>max(b[v+j+13]for j in t):v+=13 for j in t:b=b[:v+j]+'#'+b[v+j+1:] b=b.replace('[##########]\n','') print b[-91:],1060-10*len(b)/13 

Sur l’exemple de test

 [ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] T2 Z6 I0 T7 

il produit

 [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10 

PS Correction d’un bug signalé par Nakilon au prix de +5

Golfscript 260 caractères

Je suis sûr que cela pourrait être amélioré, je suis un peu nouveau pour Golfscript.

 [39 26.2/0:$14{.(}:?~1?15?1?14 2??27?13.!14?2?27?14 1]4/:t;n/)\n*:|;' '/-1%.,:c;~{)18+:&;'XIOZTLSJX'\%~;,1-t\={{.&+.90>{;.}*|\=32=!{&13-:&;}*}%}6*{&+}/|{\.@< '#'+\)|>+}4*{'['\10*']'++}: ;n/0\~n+:|;0\{.'#' ={;)}{n+|+:|;}if\.}do;' ' n+\.@*|+\$+:$;.,1-<: |;}c*|n?$* 

La fin des lignes est pertinente (il ne devrait pas y en avoir une à la fin). Quoi qu’il en soit, voici quelques cas de test que j’ai utilisés:

 > cat init.txt 
 []
 []
 []
 []
 [# # #]
 [## ######]
 [==========]
 T2 Z6 I0 T7> cat init.txt |  ruby golfscript.rb tesortings.gsc
 []
 []
 []
 [# ###]
 [# ###]
 [##### ####]
 [==========]
 dix

 > cat init.txt
 []
 []
 []
 []
 [# # #]
 [## #####]
 [==========]
 I0 O7 Z1 S4> cat init.txt |  ruby golfscript.rb tesortings.gsc
 []
 []
 []
 [#]
 [### ####]
 [### #####]
 [==========]
 dix

> cat init.txt
[ ]
[ ]
[ ]
[ ## ### ]
[ # # ]
[ ## ######]
[==========]
T7 I0 I3> cat init.txt | ruby golfscript.rb tesortings.gsc
[ ]
[ ]
[ ]
[ ]
[# # ]
[## # # # ]
[==========]
 20

Note that there is no end of line in the input file, an end of line would break the script as is.

O’Caml 809 782 Chars

 open Ssortingng let w=length let cs=let x=ref 0in iter(fun k->if k='#'then incr x)s;!x open List let(@),g,s,p,q=nth,ref[],ref 0,(0,1),(0,2)let l=length let u=Printf.printf let rec oxij=let a=map(fun s->copy s)!g in if snd(fold_left(fun(r,k)(p,l)->let z=c(a@r)in blit(make l '#')0(a@r)(i+p)l;if c(a@r)=z+l then r+1,k else r,false)(jl x+1,true)x)then g:=a else oxi(j-1)and fx=let s=read_line()in if s.[1]='='then g:=rev x else f(sub s 1 10::x)let z=f [];read_line();;for i=0to wz/3 do o(assoc z.[i*3]['I',[p;p;p;p];'O',[q;q];'Z',[q;1,2];'T',[0,3;1,1];'L',[p;p;q];'S',[1,2;q];'J',[1,1;1,1;q]])(Char.code z.[i*3+1]-48)(l!g-1);let h=l!g in g:=filter(fun s->c s<>ws)!g;for i=1to h-(l!g)do incr s;g:=make 10' '::!g done;done;iter(fun r->u"[%s]\n"r)!g;u"[==========]\n";u"%d\n"(!s*10) 

Common Lisp 667 657 645 Chars

My first attempt at code golf, so there are probably many sortingcks that I don’t know yet. I left some newlines there to keep some residual “readability” (I counted newlines as 2 bytes, so removing 6 unnecessary newlines gains 12 more characters).

In input, first put the shapes then the field.

 (let(b(s 0)m(e'(0 1 2 3 4 5 6 7 8 9))) (labels((o(pi)(mapcar(lambda(j)(+ ij))p))(w(pr)(op(* 13 r)))(f(i)(find ib)) (a(&aux(i(position(read-char)"IOZTLSJ")))(when i(push(o(nth i'((0 13 26 39)(0 1 13 14)(0 1 14 15)(0 1 2 14)(0 13 26 27)(1 2 13 14)(1 14 26 27)))(read))m)(a)))) (a)(dotimes(i 90)(if(find(read-char)"#=")(push ib)))(dolist(p(reverse m)) (setf b`(,@b,@(wp(1-(position-if(lambda(i)(some #'f(wpi)))e))))) (dotimes(i 6)(when(every #'f(wei))(setf s(1+ s)b(mapcar(lambda(k)(+(if(>(* 13 i)k)13(if(< =(* 13(1+ i))k)0 78))k))b))))) (dotimes(i 6)(format t"[~{~:[ ~;#~]~}] "(mapcar #'f(wei))))(format t"[==========] ~a0"s))) 

Essai

 T2 Z6 I0 T7 [ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10 NIL 

Ruby 505 479 474 442 439 426 chars

A first attempt. Have done it with IronRuby. I’m sure it can be improved, but I really should get some work done today!

 p,q,r,s=(0..9),(0..2),(0..6),0 t=[*$< ] f=p.map{|a|g=0;r.map{|b|g+=2**b if t[6-b][a+1]==?#};g} t.pop.split.map{|x|w,y=[15,51,306,562,23,561,113]["IOZTLSJ"=~/#{x[0]}/],x[1].to_i l=q.map{|d|r.inject{|b,c|f[d+y]&(w>>(d*4)&15-c+1)>0?c:b}}.max q.map{|b|f[b+y]|=w>>(b*4)&15-l} r.map{i=f.inject{|a,b|a&b};f.map!{|a|b=i^(i-1);a=((a&~b)>>1)+(a&(b>>1))};s+=i>0?10:0}} p.map{|a|r.map{|b|t[6-b][a+1]=f[a]&2**b>0??#:' '}} puts t,s 

Essai

 cat test.txt | ruby tesortings.rb [ ] [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10 

Edit Now using normal ruby. Got the walls output..

Another one in Ruby, 573 546 characters

:**

 Z={I:?#*4,J:'#,###',L:'###,#',O:'##,##',S:'#,##, #',Z:' #,##,#',T:' #,##, #'} t=[*$< ] R=->s{s.reverse} T=->m{m.transpose} a = T[R[t].join.scan /.#{'(\D)'*10}.$/] t.pop.split.each{|z| t,o=Z[z[0].to_sym].split(',').map{|x|x.split //},z[1].to_i r=0..t.size-1 y=r.map{|u|1+a[o+u].rindex(?#).to_i-t[u].count(' ')}.max (0..3).each{|i|r.each{|j|t[j][i]==?#&&a[o+j][y+i]=t[j][i]}}} s=0 a.each{|x|s=a.max_by(&:size).size;x[s-=1]||=' 'while s>0} a=R[T[a].reject{|x|x*''=~/[#]{10}/&&s+=10}.map{|x|?[+x*''+?]}[0..6]] puts (0..8-a.size).map{?[+' '*10+?]},a,s 

Essai:

 cat test.txt | ruby 3858384_tesortings.rb [ ] [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10