L'art ASCII de la fourmi de Langton.

22

Tracez le chemin de la fourmi de Langton .

La description

Les carrés d'un avion sont colorés de différentes manières, soit en noir soit en blanc. Nous identifions arbitrairement un carré comme la "fourmi". La fourmi peut voyager dans n'importe laquelle des quatre directions cardinales à chaque étape. La fourmi se déplace selon les règles ci-dessous:

  • Sur un carré blanc, tournez à 90 ° à droite, retournez la couleur du carré, avancez d'une unité
  • Sur un carré noir, tournez à 90 ° à gauche, retournez la couleur du carré, avancez d'une unité

Caractéristiques

  • Entrée: un entier N compris entre 0 et 725 (inclus).
  • Sortie: une grille de 17 x 17 représentant le "chemin" de la fourmi à l'étape N.

Règles

  • La fourmi commence à faire face à droite (3 heures).
  • La fourmi commence au centre de la grille.
  • À utiliser _#@pour les carrés blancs, les carrés noirs et la fourmi respectivement.
  • La grille est initialement complètement blanche.
  • Vous pouvez créer soit un programme complet soit une fonction sur un langage interprété.
  • Entrée par stdin ou argument.

Exemples

Mise à jour: la sortie N = 450 du boîtier était incorrecte.

N = 0

_________________
_________________
_________________
_________________
_________________
_________________
_________________
_________________
________@________
_________________
_________________
_________________
_________________
_________________
_________________
_________________
_________________

N = 1

_________________
_________________
_________________
_________________
_________________
_________________
_________________
_________________
________#________
________@________
_________________
_________________
_________________
_________________
_________________
_________________
_________________

N = 450

_________________
_________________
___________##____
____##______##___
___#__##___##_#__
__###_#@#__#__#__
__#_#_#_#__#_#___
_____###___#_____
_____#___________
_____#__###______
___#_#_#__#_#_#__
__#__#_#____###__
__#_##__##___#___
___##______##____
____##___________
_________________
_________________
Eelvex
la source
@Joey: oui "Programme ou fonction complète. Entrée par argument ou stdin.",
Style
@Joey: Désolé si ce n'était pas clair: vous pouvez soit faire une fonction sur un langage interprété ou un programme complet. Vous pouvez prendre l'entrée de stdin ou la fournir comme argument.
Eelvex
@Joey: Notez qu'à l'étape 1 la fourmi tourne d'abord à droite (maintenant face au nord) puis avance. Etes-vous sûr de prendre cela en compte?
Eelvex
@Joey: Oui, je voulais dire sud au commentaire précédent et vous avez raison, le dernier exemple était pour différents N: - / (Mise à jour de la section des exemples).
Eelvex

Réponses:

10

GolfScript - 67 caractères

~17.'_'*n+*\153:|;{|/()[124^.2/6+:6.1&17*)\2&(*|+:|;]@++}*|/();'@'@

La solution Python de hallvabo est la plus similaire à celle-ci, je ne décrirai donc que les principales différences.

La carte est stockée sous forme de chaîne au lieu d'un tableau. C'est ainsi que nous pouvons mettre à jour une valeur sur la carte avec moins de caractères (car les chaînes sont toujours plates), et donc obtenir le format de sortie souhaité est facile.

La position de la fourmi est incrémentée par la formule ((d&1)*17+1)*((d&2)-1)(c'est-à-dire .1&17*)\2&(*), où d est la direction. Nous utilisons la variable 6pour ignorer l'initialisation.

Nabb
la source
1
Awww, maintenant je me sens comme un noob GolfScript.
aaaaaaaaaaaa
:6- tellement hipster. Je détesterais déboguer votre code :-)
John Dvorak
9

Ruby 1.9, 104 caractères

f=->z{l=[*[r=1]*17,2]*17;c=152;z.times{c+=r=(r*r>1?r/18:-r*18)*l[c]*=-1};l[c]=0;l.map{|a|putc"@_
#"[a]}}

Entrée via l'argument de fonction.

  • (146 -> 142) Inline m
  • (142 -> 140) Vérifier au r*r>1lieu der.abs>1
  • (142 -> 128) Utilisez String#scanpour générer la sortie. Changé ==en>
  • (128 -> 125) Variable obsolète supprimée
  • (125 -> 122) Remplacer String#trpar un conditionnel
  • (122 -> 122) Génère désormais la même sortie que les exemples mis à jour
  • (122 -> 111) Utilisez des ints au lieu de caractères lors de la génération du chemin de la fourmi.
  • (111 -> 109) Réorganisez certaines expressions pour enregistrer les parenthèses
  • (109 -> 108) Le code est désormais une fonction
  • (108 -> 104) Imprimez chaque caractère individuellement
Ventero
la source
Les fonctions sont autorisées.
Eelvex
@Eelvex: la fonction doit-elle renvoyer une chaîne ou doit-elle la sortir?
Ventero
sortie.
Eelvex
6

Python, 123

n = entrée ()
d = x = 152
g = (17 * [95] + [10]) * 17
tandis que n: d + = g [x] / 2; g [x] ^ = 124; x + = (1, -18, -1,18) [d% 4]; n- = 1
g [x] = 64
imprimer "% c" * 306% tuple (g)

Juste une légère refonte de ma solution Python à partir de http://golf.shinh.org/p.rb?Langtons+Ant .

hallvabo
la source
5

GolfScript 96 94 89

Ma langue de haine préférée est de retour avec un autre tas de codes sorta semi-lisibles.

En version 89, j'ai finalement réussi à intégrer @ dans la boucle de sortie.

~289[0:c]*145:b;{.b>\b<)!..c++(4%:c[1 17-1-17]=b+:b;@++}@*{{(b(:b!.++'_#@@'1/=\}17*n\}17*

Version 94:

~306[0:c]*152:b;{.b<\b>(!..c++(4%:c[1 18-1-18]=b+:b;\++}@*{{('_#'1/=\}17*(;n\}17*].b<\b>(;'@'\

Commenté:

               #Initialization.
~                  #Parse input.
306[0:c]*          #Make array of 306 0s, set c to 0 in the middle of that operation.
152:b;             #Set b to 152, remove 152 from the stack.
                   #b is a value for the ant's position, c for its rotation.

               #Run the algorithm.
{                  #Start of block.
    .b<\b>(        #Split the array at index b into before, after and value at b.
    !..            #Not the value and make 2 copies of it.
    c++            #Add the 2 copies to c.
    (4%:c          #Subtract 1, modulus by 4 and save the result to c.
    [1 18-1-18]=   #Define an array and take element number c.
    b+:b;          #Add b to the value, save result to b, remove result from stack.
    \++            #Reform the array.
}@*                #Switch the input to the top of the stack and run the block input times.

               #Convert array of 1s and 0s to the correct characters.
{                  #Start of block.
    {              #Start of block.
        ('_#'1/=   #Take the first array element, convert it to either '_' or '#'.
        \          #Switch the array to the top of the stack.
    }17*           #Execute block 17 times.
    (;n\           #Discard the 18th element of the line, write a lineshift.
}17*               #Execute block 17 times.

               #Insert the @.
]                  #Put everything in an array.
.b<\b>(            #Split the array at index b into before, after and value at b.
;'@'\              #Ditch the value at b, write a @ and shift it into place.

Edit, je pourrais aussi bien en faire une grosse version, voici 59 * 59 et 10500 itérations:

~59:a.*[0:c]*1741:b;{.b>\b<)!..c++(4%:c[1 a-1-59]=b+:b;@++}@*{{(b(:b!.++'_#@@'1/=\}a*n\}a*

.

___________________________________________________________
___________________________________________________________
_________________________##__##____________________________
________________________#__@_###___________________________
_______________________###__#_#_#__________________________
_______________________#####_#__##_________________________
________________________#___##_##_#________________________
_________________________###___#__##_______________________
__________________________#___##_##_#______________________
___________________________###___#__##_____________________
____________________________#___##_##_#__##________________
_____________________________###___#__##__##_______________
______________________________#___##_##__##___#____________
________________________####___###___#___#__###____________
_______________________#____#___#___##_####___#____________
______________________###____#___#_#______#_##_#___________
______________________###____#_##_____#_##__#_##___________
_______________________#____#___##_#_#_____##______________
_______________________#_#______#_#####__#___#_____________
______________________#___#####__________##_######_________
______________________###__##__#_##_#_#_#___##_#_##________
____________________##__#_#######_#___#__###____##_#_______
___________________#__#__######_##___#__#_##___#___#_______
__________________#____#_#_##_#__######_#######___#________
__________________#_####_##_#_####____##__##_#_##_#________
___________________#____####___#__#_######_##____###_______
______________________#___#_##_#_###_#__##__##___###_______
_________________________#######____#__##_##_#_____#_______
_________________####__##_##__####_##_##_##__#_____#_______
________________#____#_#___###_##_###____#_####____#_______
_______________###_______###_#_#_#####____#_#______#_______
_______________#_#___###_####_##_#___##_###_##_____#_______
_____________________##_##__####____####_#_#_#_____#_______
________________#____#__##___###__###_____###______#_______
________________##___##_###_####__#______###___##__#_______
________________##_#_####_____#___#__#_##_###_##___#_______
_______________####_##___##_####__#_#__#__#__###___#_______
_______________#_##_###__#_#_##_#_#_____#_#_____#_#________
___________________#_#__#____##_##__#_#__###_##____________
___________________##_#____#__#####_#____#____#__#_#_______
__________________#_##_#__#____##_##_#__###______###_______
________________#_#___#__#__#__#__###___##__##____#________
_______________###_#_#####_######_###_#######_#_##_________
_______________#_#_#____#####___##__#####_#####____________
_________________#__##___#______#__#_##__###_###___________
______________####___#####_#########___#_#_________________
_________##____#__#_____###_#_#___#_###__###_______________
________#__#__####_##___###_##___###_##_____##_____________
_______###____#_##_#_#####___#____#__#__##_###_____________
_______#_#####_#_#___##__##_____#____#___#__#______________
___________######_####__##_#___#__##__#_#_##_______________
_________##______#_###_##__####___#___###__________________
__________#__#_#####__#___#_##___#__#__#___________________
__________##_###_#######_____#_____#_##____________________
_________#_#__##_##______#___##____#_______________________
________#__#_####________###__##__#________________________
________#_##_###____________##__##_________________________
_________##________________________________________________
__________##_______________________________________________
aaaaaaaaaaaa
la source
5

Windows PowerShell, 119 118

for($p,$n,$g=144,+"$args"+,1*289;$n--){$d+=$g[$p]*=-1
$p+='B0@R'[$d%4]-65}$g[$p]=0
-join'@_#'[$g]-replace'.{17}',"$&
"
Joey
la source
4

PHP, 350 309 307 312 174 161 166 159 151 149 147 147 144 143

<?$p=144;while($i=$argv[1]--){$g[$p]=$a=2-$g[$p];$d+=--$a;$p+=(1-($d&2))*(1+16*($d&1));}while($i++<288)echo$i%17?$i!=$p?$g[$i]?"#": _:"@":"\n";

Non golfé

$p = 144; // Set initial pointer

while($i = $argv[1]--){ // Ends at -1
    $g[$p] = $a = 2 - $g[$p]; // Either returns true (2) or false(0)

    $d += --$a; // Adds 1 (2-1) or removes 1 (0-1) from the direction

    $p += (1 - ($d & 2)) * (1 + 16 * ($d & 1));
}

while($i++ < 288)
    echo $i % 17? $i != $p? $g[$i]? "#" : @_ : "@" : "\n"; // Prints the correct character

350 -> 309: Diverses techniques de compression avec les boucles for (), également mises à jour pour afficher une sortie correcte.
309 -> 307: Conversion de la boucle principale for () en boucle while ().
307 -> 312: J'ai oublié de le changer pour utiliser argv.
312 -> 174: recodé sur la base d'une autre réponse.
174 -> 161: la valeur par défaut du tableau entier n'est plus par défaut.
161 -> 166: Argv gagne à nouveau.
166 -> 159: Pas besoin de redéfinir argv [1].
159 -> 151: Plus rien par défaut, PHP le fait automatiquement.
151 -> 149: Suppression d'un ensemble de parenthèses, l'ordre des opérations supprime le besoin.
149 -> 147: raccourci de la dernière boucle for (), accolades non nécessaires.
147 -> 144:La dernière boucle for () est maintenant une boucle while ().
144 -> 143: utilisé une variable temporaire pour enregistrer un caractère.

Kevin Brown
la source
Je vois que vous avez utilisé mes astuces de grille et de direction, et qu'il a supprimé 138 caractères de votre code, c'est bien!
PatrickvL
4

C, 166 162

Voici une traduction de mon approche Delphi du C, montrant à quel point le C peut être compact. J'ai emprunté l'astuce conditionnelle de nouvelle ligne à fR0DDY (merci mec!):

g[289]={0},a=144,d,i,N;main(){scanf("%d",&N);while(N--)g[a]=2-g[a],d+=g[a]-1,a+=(1-(d&2))*(1+d%2*16);for(g[a]=1;i<289;)printf("%s%c",i++%17?"":"\n","_@#"[g[i]]);}

La version en retrait et commentée ressemble à ceci:

g[289]={0}, // g: The grid is initially completely white. (size=17*17=289)
a=144, // a: Ant position starts at the center of the grid (=8*17+8=144)
d, // Assume 0=d: Ant start 'd'irection faces right (=0, see below)
i,
N;
main(){
  scanf("%d",&N);
  while(N--)
    // Flip the color of the square:
    g[a]=2-g[a],
    // Turn 90° right if at an '_' space, 90° left otherwise :
    d+=g[a]-1,
    // Move one unit forward;
    //   For this, determine the step size, using the two least significant bits of d.
    //   This gives the following relation :
    //     00 = 0 =  90° = right =   1
    //     01 = 1 = 180° = down  =  17
    //     10 = 2 = 270° = left  = - 1
    //     11 = 3 =   0° = up    = -17
    //   (d and 2) gives 0 or 2, translate that to 1 or -1
    //   (d and 1) gives 0 or 1, translate that to 1 or 17
    //   Multiply the two to get an offset 1, 17, -1 or -17 :
    a+=(1-(d&2))*(1+d%2*16);
  // Place the ant and print the grid :
  for(g[a]=1;i<289;)
    printf("%s%c",i++%17?"":"\n","_@#"[g[i]]); // 0 > '_', 1='@', 2 > '#'
}
PatrickvL
la source
+1. J'aime les astuces "_@#"[g[i]]eta+=(1-(d&2))*(1+(16*(d&1)))
fR0DDY
(1+d%2*16)enregistre quelques caractères.
Nabb
@Nabb: En effet, cela enregistre 4 caractères, merci pour la suggestion!
PatrickvL
4

Delphi, 217

var g,a:PByte;i,d,Word;begin g:=AllocMem(306);a:=g+153;Read(i);for n:=1to i do begin a^:=2-a^;d:=d-1+a^;a:=a+(1-2and d)*(1+17*(1and d))end;a^:=1;for n:=1to 306do if n mod 18=0then WriteLn else Write('_@#'[1+g[n]])end.

Le code en retrait et commenté se lit comme suit:

var
  g,a:PByte;
  i,d,n:Int32;
begin
  g:=AllocMem(306); // g: The grid is initially completely white. (size=18*17=306)
  // Assume 0=d: Ant start 'd'irection faces right (=0, see below)
  a:=g+153; // a: Ant position starts at the center of the grid (=8*18+9=153)
  Read(i);
  for n:=1to i do
  begin
    // Flip the color of the square;
    a^:=2-a^;
    // Turn 90° right if at an '_' space, 90° left otherwise;
    d:=d-1+a^;
    // Move one unit forward;
    //   For this, determine the step size, using the two least significant bits of d.
    //   This gives the following relation :
    //     00 = 0 =  90° = right =   1
    //     01 = 1 = 180° = down  =  18
    //     10 = 2 = 270° = left  = - 1
    //     11 = 3 =   0° = up    = -18
    //   (d and 2) gives 0 or 2, translate that to 1 or -1
    //   (d and 1) gives 0 or 1, translate that to 1 or 18
    //   Multiply the two to get an offset 1, 18, -1 or -18 :
    a:=a+(1-2and d)*(1+17*(1and d))
  end;
  // Place the ant and print the grid :
  a^:=1; // 0 > '_', 1='@', 2 > '#'
  for i:=1to 306do
    if i mod 18=0then // we insert & abuse column 0 for newlines only (saves a begin+end pair)
      WriteLn
    else
      Write('_@#'[1+g[i]])
end.

Contribution:

450

Sortie:

_________________
_________________
___________##____
____##______##___
___#__##___##_#__
__###_#@#__#__#__
__#_#_#_#__#_#___
_____###___#_____
_____#___________
_____#__###______
___#_#_#__#_#_#__
__#__#_#____###__
__#_##__##___#___
___##______##____
____##___________
_________________
_________________
PatrickvL
la source
@Patrick: l'exemple était incorrect, veuillez vérifier les mises à jour. (et il semble que vous ayez sorti l'étape 451 :)).
Eelvex
@Eelvex: Merci. J'ai corrigé le cas 'N = 0' au coût de 4 caractères ... maintenant je dois les reconquérir à nouveau! ;-)
PatrickvL
@Eelvex: PS: Pas de +1 pour avoir repéré votre erreur il y a 3 heures avec juste une humble remarque, cela pourrait être de ma faute? ;)
PatrickvL
@Patrick: J'attendais <200 mais ok ... :)
Eelvex
@Eelvex: LOL, y arriver ... (jusqu'à 238 déjà)
PatrickvL
3

C 195 caractères

x=144,T,p=1,i,N[289]={0},a[]={-17,1,17,-1};c(t){p=(p+t+4)%4;x+=a[p];}main(){scanf("%d",&T);while(T--)N[x]=(N[x]+1)%2,c(N[x]?1:-1);for(;i<289;i++)printf("%s%c",i%17?"":"\n",i-x?N[i]?'#':'_':'@');}

http://www.ideone.com/Dw3xW

Je reçois ceci pour 725.

_________________
_________________
___________##____
____##______##___
___#___##__##_#__
__###____#_#__#__
__#_#_#__#_#_#___
______###____#__@
_______###__#__#_
_____#_#____#___#
___#_#_#_##____#_
__#__#_#_#_#_###_
__#_##_#_____####
___##_#____#_####
____###___####_#_
_______#__#__##__
________####_____
fR0DDY
la source
Utiliser p+=t+4;x+=a[p%4];au lieu d' p=(p+t+4)%4;x+=a[p];enregistrer trois caractères.
Joey
3

sed, 481 caractères

#n
1{s/.*/_________________/;h;H;H;H;G;G;G;G;s/^\(.\{152\}\)_/\1@/;s/$/;r/;ta;};x;:a;/;r/br;/;d/bd;/;l/bl;/;u/bu;:w;y/rdlu/dlur/;bz;:b;y/rdlu/urdl/;bz;:r;s/@\(.\{17\}\)_/#\1@/;tw;s/@\(.\{17\}\)#/#\1!/;tw;s/_\(.\{17\}\)!/@\1_/;tb;s/#\(.\{17\}\)!/!\1_/;tb;:d;s/_@/@#/;tw;s/#@/!#/;tw;s/!_/_@/;tb;s/!#/_!/;tb;:l;s/_\(.\{17\}\)@/@\1#/;tw;s/#\(.\{17\}\)@/!\1#/;tw;s/!\(.\{17\}\)_/_\1@/;tb;s/!\(.\{17\}\)#/_\1!/;tb;:u;s/@_/#@/;tw;s/@#/#!/;tw;s/_!/@_/;tb;s/#!/!_/;tb;:z;h;${s/!/@/;s/;.//p}

Peut être réduit à 478 caractères en supprimant la première ligne et en exécutant avec -n

Nécessite N lignes pour l'entrée, par exemple. lorsqu'il est exécuté en tant que

seq 450 | sed -f ant.sed

les sorties:

_________________
_________________
___________##____
____##______##___
___#__##___##_#__
__###_#@#__#__#__
__#_#_#_#__#_#___
_____###___#_____
_____#___________
_____#__###______
___#_#_#__#_#_#__
__#__#_#____###__
__#_##__##___#___
___##______##____
____##___________
_________________
_________________
Hasturkun
la source
3

Perl, 110 caractères

$p=144;$p+=(1,-17,-1,17)[($d+=($f[$p]^=2)+1)%4]for 1..<>;$f[$p]=1;print$_%17?'':$/,qw(_ @ #)[$f[$_]]for 0..288

Le numéro est lu à partir de la première ligne de STDIN. Le reste de l'entrée est ignoré.

Un peu plus lisible:

$p=144;
$p += (1,-17,-1,17)[($d+=($f[$p]^=2)+1) % 4] for 1..<>;
$f[$p]=1;
print $_%17 ? '' : $/, qw(_ @ #)[$f[$_]] for 0..288

Modifications

  • (112 → 111) Pas besoin de mettre à jour $davec la valeur modulo-4.

  • (111 → 110) Peut maintenant $dincrémenter l' incrément

Addendum (109 caractères)

Nous pouvons avoir un caractère plus court si vous êtes content d'avoir le cas spécial d' N=0échec (il ne produit pas le @caractère pour la fourmi). Toutes les autres entrées fonctionnent correctement:

$p+=(1,-17,-1,17)[($d+=($f{$p+0}^=2)+1)%4]for 1..<>;$f{$p}=1;print$_%17-9?'':$/,qw(_ @ #)[$f{$_}]for-144..144

Les différences sont que nous utilisons maintenant %fau lieu de @fafin que nous puissions utiliser des indices négatifs, et nous itérons à partir de -144..144au lieu de 0..288. Cela évite d'avoir à initialiser $p.

Timwi
la source
1

Mathematica, 94 caractères

a@_=d=1;a@Nest[#+(d*=(a@#*=-1)I)&,9-9I,Input[]]=0;Grid@Array["@"[_,"#"][[a[#2-# I]]]&,17{1,1}]
alephalpha
la source
1

> <>, 122 octets

Au risque d'une petite nécromancie de fil, j'ai pensé qu'écrire une réponse en> <> serait un défi intéressant ...

1&f8r\
1-:?!\r:@@:@$:@@:@g:2*1+&+4%:&}1$-@p{:3$-5gaa*-$@+@5gaa*-+r
2}p70\~
a7+=?\:@@:@g4+5go$1+:
o053.>~1+:64*=?;a
dedc_#@

Ce programme s'attend à ce que le nombre d'étapes à calculer soit présent sur la pile avant l'exécution.

Sok
la source