Simulez l'automate cellulaire Wireworld

24

Wireworld est un automate cellulaire qui a été conçu pour ressembler à des électrons traversant des fils. Sa mécanique simple permet la construction de circuits numériques. Il a même permis la construction d'un ordinateur entier .

Votre mission est de créer l'implémentation Wireworld la plus courte dans la langue de votre choix.

Chaque cellule de la grille a un état sur quatre. Les quatre états sont "vierge", "cuivre", "tête d'électron" ou "queue d'électron".

  • Une cellule vide restera toujours une cellule vide
  • Une tête d'électrons deviendra toujours une queue d'électrons
  • Une queue d'électrons deviendra toujours du cuivre
  • Une cellule en cuivre deviendra une tête d'électron si exactement un ou deux de ses huit voisins sont des têtes d'électrons, sinon elle restera en cuivre

Cette compétition aura un style similaire à la compétition Shortest Game of Life , mais avec quelques changements.

  • La grille doit être d'au moins 40 par 40 cellules
  • Les bords de la grille ne doivent PAS s'enrouler (pas un tore). Traitez les cellules en dehors du champ comme étant constamment "blanches".
  • Les utilisateurs doivent pouvoir saisir leur propre configuration de démarrage.
  • Regarder des écrans vierges n'est pas amusant. Le programme doit afficher visuellement la simulation pendant son exécution.

C'est le golf de code, le moins d'octets gagne.

PhiNotPi
la source

Réponses:

6

APL, Dyalog (131)

{h t c←1↓⍵∘=¨F←' htc'⋄⎕SM∘←1 1,⍨⊂N←F[1+⊃+/H h(t∨c≠H←c∧S↑1 1↓1 2∊⍨⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂¯1⌽¯1⊖h↑⍨2+S←25 79)ר⍳3]⋄∇N⊣⎕DL÷4}↑{79↑⍞}¨⍳25

La sortie s'affiche dans la ⎕SMfenêtre. La simulation s'exécute sans fin. La grille est de 79x25 car c'est la taille par défaut de la ⎕SMfenêtre. La tête d'électrons esth , la queue est t, le cuivre estc . Le programme lit la configuration de départ du clavier sur 25 lignes.

Explication:

  • ↑{79↑⍞}¨⍳25: lire la grille 79x25
  • h t c←1↓⍵∘=¨F←' htc': obtenez trois matrices, une avec les têtes, une avec les queues et une avec le cuivre. Définissez également F sur la chaîne' htc' .

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]: La partie "..." est un vecteur de longueur trois, où les éléments sont des matrices montrant respectivement les nouvelles têtes, queues et cuivre. Les têtes sont multipliées par 1, les queues par 2 et le cuivre par 3, puis nous additionnons ces matrices et en ajoutons une, donnant une matrice d'indices dans F. Ndevient le nouvel état, dans le même format que l'entrée, et il est affiché sur l' ⎕SMécran à partir du coin supérieur gauche.

  • ¯1⌽¯1⊖h↑⍨2+S←25 79: Ajoutez une bordure de blancs à hen l'agrandissant de deux lignes et colonnes, puis en la faisant pivoter d'une droite et d'une vers le bas.

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂: Faites pivoter la matrice dans les huit directions, puis additionnez les matrices résultantes ensemble, en donnant le nombre de voisins qui sont des têtes sur chaque position.

  • 1 2∊⍨: Définissez uniquement les positions sur 1 qui ont 1 ou 2 voisins.

  • S↑1 1↓: Supprimez la bordure que nous avons ajoutée précédemment.

  • H←c∧: Les nouvelles têtes sont toutes ces cellules en cuivre qui ont 1 ou 2 têtes voisines.

  • t∨c≠H: Les nouvelles cellules de cuivre sont toutes de vieilles queues et toutes les anciennes cellules de cuivre qui ne sont pas devenues des têtes.

  • H h(... ): Les nouvelles têtes sontH comme calculé ci-dessus, les nouvelles queues sont les anciennes têtes, et les nouvelles cellules de cuivre sont comme calculé ci-dessus.

  • ∇N⊣⎕DL÷4: Attendez 1/4 de seconde, puis exécutez à nouveau la fonction N.

marinus
la source
Je pense que ce serait mieux s'il pouvait contenir une grille de 40 par 40.
mbomb007
6

ALPACA, 82 caractères

ALPACA est un langage spécialement conçu pour les automates cellulaires.

o n'est rien; c est conducteur; e est électron; t est la queue d'électrons.

state o " ";
state c "c" to e when 1 e or 2 e;
state e "e" to t;
state t "t" to c.
DanTheMan
la source
Quand cette langue a-t-elle été publiée? Existe-t-il des liens vers la langue?
Optimizer
@Optimizer C'est parti ! Je n'ai pas fait la langue.
DanTheMan
4
Cool. La bonne langue pour le bon défi ..
Optimizer
4

GolfScript ( 125 120 105 100 caractères)

n%{.,,{1${.0=,:w[1,*]\+2*>3<}:^~`{zip^''+.4=5%'`X '@{+}*(7&1>'iX'>+=}+w,%}%"\033[H\033[J"@n*+puts 6.?.?}do

Notez que je compte \033chacun comme un caractère, car ils peuvent être remplacés par un ESCcaractère littéral . Cela utilise des codes de contrôle ANSI, repose donc sur un tty compatible. Notez également que les cadres sont imprimés en commençant par la grille d'entrée.

Il y a un certain chevauchement avec Générer une grille de sommes , qui utilise également le voisinage de Moore.

Encodage: espace vide => ; tête d'électrons => i; queue d'électrons => `; cuivre =>X .

La pause entre les itérations est le temps nécessaire pour calculer 46656 46656 . Le passage 6.?.?à une autre expression vous permet de contrôler la vitesse; le suivant le plus lent pour le même nombre de caractères est 7.?.?, ce qui est beaucoup plus lent (la sortie est 22 fois plus grande et ce n'est pas un calcul de complexité linéaire).

Pour un cas de test, j'utilise

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

du défi Rosetta Code Wireworld .

Peter Taylor
la source
3

Python 371 341 caractères

Ouais, ce n'est pas si court, mais il a un GUI interactif!

import matplotlib.pylab as l,scipy.ndimage as i
r=round
w=l.zeros((40,40),int)-1
p=l.matshow(w,vmax=2)
c=p.figure.canvas
def h(e):
 try:w[r(e.ydata),r(e.xdata)]=[0,2,-1][e.button-1]
 except:x=i.convolve(w==2,l.ones((3,3)),int,'constant');w[:]=w/2+((w==0)&(x>0)&(x<3))*2
 p.set_data(w);c.draw()
c.mpl_connect('button_press_event',h)
l.show()

Instructions:

Cliquez avec le bouton gauche de la souris pour placer le fil

Cliquez avec le bouton droit de la souris pour effacer

Cliquez avec le bouton central de la souris pour placer la tête d'électrons

Cliquez en dehors des axes pour faire avancer l'automate

Geoff Reedy
la source
(x>0)&(x<3)-> (0<x<3). :)
beary605
3

Python ( 243214 )

J'ai essayé de faire un croisement entre la convivialité et les personnages. La grille est de 40x40. L'entrée est donnée sur stdin. Une tête d'électrons est h, la queue d'électrons est t, le cuivre est c, tout le reste est vide.

import os
f=raw_input()
while 1:f=''.join('h'if(i=='c')&(0<sum(1 for i in[-1,1,-39,-40,-41,39,40,41]if f[e+i:e+i+1]=='h')<3)else't'if i=='h'else'c'if i=='t'else f[e]for e,i in enumerate(f));os.system('cls');print f

La boucle while (ligne 3) non compressée (ne fonctionnera pas si elle est placée dans le code):

while 1:
 for e,i in enumerate(f):
  if(i=='c')&(0<sum(1 for i in[-1,1,-39,-40,-41,39,40,41]if f[e+i:e+i+1]=='h')<3):f[e]='h'
  elif i=='h':f[e]='t'
  elif i=='t':f[e]='c'
  else:f[e]=f[e]  #redundant, but Python needs this to run
 os.system('cls') #cls is shorter than clear, so I used that
 print f
beary605
la source
Je pense que vous pouvez remplacer les lignes 5-7 avec une seule expression: g[e]='h'if(t=='c')&...else't'if i=='h'else'c'if i=='t'else i. Je ne sais pas si cela fonctionne exactement tel
quel
2

C, 355 347 300 294 car.

Edit: réalisé que je n'ai pas besoin feof()

Edit: sauvé 47 caractères! Suppression du sommeil, suppression de presque toutes les orthèses, combinaison de nombreuses opérations.

Edit: Le dernier aujourd'hui, depuis que j'ai cassé 300 caractères. Changé printfen puts, trouvé une petite optimisation mignonne avec la première comparaison.

C ne se prête pas bien à ce genre de problème, mais bon, jouer au golf est amusant. C'est une implémentation assez brutale, mais je voulais voir jusqu'où je pouvais jouer.

L'entrée est un fichier texte nommé i. Il contient une représentation de l'état de départ, avec *pour le cuivre, +pour la tête d'électrons, -pour la queue d'électrons, des espaces pour les cellules vides. J'utilise la porte XOR de la page wiki pour les tests.

   ****-+**
  +        ******
   -*******      *
                ****
                *  *****
                ****
   ********      *
  +        ******
   -****+-*

char*p,t[42][42],s[42][42];
main(i,r,c,n,j)
{
  for(p=fopen("i","r");fgets(s[i++]+1,40,p););

  for(;;getch(),memcpy(s,t,1764))
    for(j=1;j<41;puts(s[j++]+1))
      for(i=1;i<41;)
      {
        p=t[j]+i;
        r=s[j][i++];
        *p=r==43?45:r;
        if(r==45)
          *p=42;
        if(r==42)
          for(r=-1,n=0;r<2;++r,*p=n&&n<3?43:42)
            for(c=-2;c<1;)
              n+=s[j+r][i+c++]==43;
      }
}
JoeFish
la source
Pourrait cond?43:42être écrit 42+(cond)? Et je suis sûr que cela r=s[j][i++];*p=r==43?45:r;if(r==45)*p=42;peut être réduit à r=s[j][i++];*p=r==43?45:r==45?42:r;sinonr=s[j][i++]-43;*p=!r?45:r==2?42:r;
Peter Taylor
1

Python, 234 218 caractères

import time
I=input
C=I()
H=I()
T=I()
R=range(40)
while 1:
 for y in R:print''.join(' CHT'[(C+H+2*T).count(x+y*1j)]for x in R)
 H,T=[c for c in C if 0<sum(1 for h in H if abs(c-h)<2)<3and c not in H+T],H;time.sleep(.1)

Vous entrez le tableau sous la forme de trois listes de nombres complexes représentant les coordonnées des cellules de cuivre (qui doivent inclure les listes de têtes et de queues), de têtes et de queues. Voici un exemple:

[3+2j+x for x in range(8)] + [3+4j+x for x in range(8)] + [11+3j+x for x in range(6)] + [2+3j]
[3+2j]
[2+3j]

Notez que nous avons evall'entrée, vous pouvez donc utiliser des expressions arbitrairement complexes pour les listes de nombres complexes.

Keith Randall
la source
1

QBasic, 309 octets

Attention: la version golfée n'est pas conviviale: elle a une méthode de saisie bizarre, fonctionne comme une boucle infinie, et n'a pas de retard (donc, tourne trop vite sur certains systèmes). Exécutez-le uniquement si vous savez comment terminer un programme dans votre environnement QBasic. La version non golfée est recommandée (voir ci-dessous).

INPUT w,h
SCREEN 9
FOR y=1TO h
FOR x=1TO w
PSET(x,y),VAL(INPUT$(1))
NEXT
NEXT
DO
FOR y=1TO h
FOR x=1TO w
SCREEN,,0
c=POINT(x,y)
d=c
IF c=7THEN d=1
IF c=1THEN d=6
IF c=6THEN
n=0
FOR v=y-1TO y+1
FOR u=x-1TO x+1
n=n-(POINT(u,v)=7)
NEXT
NEXT
d=7+(n=0OR n>2)
END IF
SCREEN,,1,0
PSET(x,y),d
NEXT
NEXT
PCOPY 1,0
LOOP

Pour exécuter, spécifiez à l'invite de saisie la largeur wet la hauteur de votre configuration h.1 saisissez Puis w*hcodes à un seul chiffre pour les cellules ( se déplaçant de gauche à droite, puis de haut en bas), avec

  • 0 = vide
  • 6 = fil
  • 7 = tête de signal
  • 1 = queue de signal

Une fois que vous avez entré toutes les cellules, la simulation commencera (et se poursuivra indéfiniment, jusqu'à ce que vous tuiez le programme).

Non golfé

Une version plus conviviale. Pour modifier la mise en page, modifiez les DATAinstructions à la fin.

Le code tire parti de la POINTfonction, qui lit la valeur de couleur d'un pixel à l'écran. Cela signifie que nous n'avons pas à stocker les cellules séparément sous forme de tableau. Pour nous assurer que toutes les cellules sont mises à jour simultanément, nous effectuons les mises à jour sur une deuxième "page". Nous pouvons basculer la page active à l'aide d'une version de l' SCREENinstruction et copier le contenu d'une page dans une autre à l'aide de l' PCOPYinstruction.

SCREEN 9

EMPTY = 0 ' Black
HEAD = 7  ' Light gray
TAIL = 1  ' Blue
WIRE = 6  ' Brown/orange

' First two data values are the width and height
READ w, h
' The rest are the initial configuration, row by row
' Read them and plot the appropriately colored pixels
FOR y = 1 TO h
  FOR x = 1 TO w
    READ state$
    IF state$ = "" THEN value = EMPTY
    IF state$ = "H" THEN value = HEAD
    IF state$ = "T" THEN value = TAIL
    IF state$ = "W" THEN value = WIRE
    PSET (x, y), value
  NEXT x
NEXT y

' Loop the simulation until user presses a key
DO UNTIL INKEY$ <> ""
  ' Store current time for delay purposes
  t# = TIMER

  FOR y = 1 TO h
    FOR x = 1 TO w
      ' Active page = display page = 0
      SCREEN , , 0
      ' Get the color value of the pixel at x,y
      oldVal = POINT(x, y)
      IF oldVal = EMPTY THEN
        newVal = EMPTY
      ELSEIF oldVal = HEAD THEN
        newVal = TAIL
      ELSEIF oldVal = TAIL THEN
        newVal = WIRE
      ELSEIF oldVal = WIRE THEN
        neighbors = 0
        FOR ny = y - 1 TO y + 1
          FOR nx = x - 1 TO x + 1
            IF POINT(nx, ny) = HEAD THEN neighbors = neighbors + 1
          NEXT nx
        NEXT ny
        IF neighbors = 1 OR neighbors = 2 THEN
          newVal = HEAD
        ELSE
          newVal = WIRE
        END IF
      END IF
      ' Active page = 1, display page = 0
      SCREEN , , 1, 0
      ' Plot the new value on page 1
      PSET (x, y), newVal
    NEXT x
  NEXT y

  ' Copy page 1 to page 0
  PCOPY 1, 0

  ' Delay
  WHILE TIMER >= t# AND t# + 0.2 > TIMER
  WEND
LOOP

DATA 8,5
DATA T,H,W,W,W,W,W,W
DATA W, , , ,W, , , 
DATA  , , ,W,W,W, , 
DATA W, , , ,W, , , 
DATA H,T,W,W, ,W,W,W

1 Les valeurs maximales de largeur et de hauteur dépendent du mode d'écran utilisé. Dans SCREEN 9, la largeur peut aller jusqu'à 638 et la hauteur jusqu'à 348.SCREEN 7 a une résolution plus petite (taille de configuration maximale 318 par 198), mais les pixels sont plus grands et donc plus faciles à voir (sur DOS QBasic ou l'émulateur DOSBox - malheureusement QB64 juste donne une fenêtre plus petite).

Exemple d'exécution

Version non golfée sur archive.org , avec le mode écran 7:

Wireworld dans QBasic

DLosc
la source