Chemins aléatoires de plomberie


23

Écrivez un programme ou une fonction qui accepte trois entiers, une largeur w, une hauteur het un nombre de pas s. Vous allez dessiner une marche aléatoire non auto-entrecroisée slongue sur une image 5*wpar 5*hpixel où chaque cellule de 5 x 5 pixels est vide (beige pur) ou l'un de ces douze "tuyaux" simples:

tuyaux agrandis

L'image ci-dessus est agrandie pour montrer les détails. Voici les tuyaux à taille réelle:

tuyaux

(Les lignes grises sont juste pour séparer les types de tuyaux.)

La marche aléatoire sera un chemin de tuyau continu unique qui commence à un point d'extrémité de tuyau (l'un des quatre types de tuyaux inférieurs) et se termine à un autre point d'extrémité de tuyau.

Commencez par un vide wpar hgrille et choisir au hasard une cellule pour être le point de départ. Ensuite, choisissez au hasard l'une des quatre directions pour commencer et dessinez l'extrémité du tuyau correspondant. Cette cellule de départ marque la première étape de votre promenade et chaque fois que vous dessinez une nouvelle cellule ou écrasez une cellule existante, elle compte comme une autre étape.

Maintenant, à plusieurs reprises, choisissez au hasard d'aller à droite, à gauche ou à droite, en dessinant la cellule de tuyau appropriée si la direction choisie est valide. Revenez en arrière et choisissez à nouveau si une direction n'est pas valide jusqu'à ce que le schemin d'étape complet soit formé. Le chemin doit se terminer par un point d'extrémité de tuyau, qui peut se trouver n'importe où sur la grille, en fonction du parcours suivi.

Il est très important de noter que seules les deux cellules de tuyau droites peuvent être écrasées, et uniquement par la cellule de tuyau droite de l'orientation opposée, le résultat étant une cellule d'intersection. Sinon, tous les tuyaux doivent être placés dans des cellules vides.

Lorsqu'une intersection est dessinée, la partie du chemin la plus éloignée de la cellule de départ doit être dessinée en haut.

C'est à vous de décider si la grille a ou non des conditions aux limites périodiques (PBC), c'est-à-dire si une conduite sortant d'un côté de la grille sortira de l'autre côté. Sans PBC, la limite de la grille compte comme une barrière que vous pouvez rencontrer comme les autres tuyaux.

Cas spéciaux

  • Lorsque la valeur sest 0, aucun tuyau ne doit être tracé et la sortie doit être un blanc 5*wpar 5*himage (c'est-à-dire tout beige).
  • Quand sest 1 un bout de tuyau simple

    bout de tuyau agrandi(Taille réelle: bout de tuyau)

    doit être tracé dans la cellule de départ choisie au hasard.

Autres détails

  • Vous pouvez supposer que sc'est tout au plus w*hdonc un chemin sera toujours possible. (Bien que des chemins plus longs soient possibles en raison des intersections.)
  • wet hsera toujours positif.
  • Tous les choix aléatoires doivent être uniformément aléatoires. Par exemple, vous ne devez pas éviter de créer des intersections quand elles sont possibles même si cela facilite le problème. Les générateurs de nombres pseudo-aléatoires sont autorisés.
  • Trois couleurs visuellement distinctes peuvent être utilisées à la place du noir, du bleu et du beige.
  • Vos images de sortie peuvent être agrandies de sorte qu'elles soient vraiment 5*w*ken 5*h*kpixels où kest un entier positif. (Il est conseillé d'agrandir tous les exemples que vous publiez, même si vous en avez k1.)
  • N'importe quel format de fichier d'image sans perte commun peut être utilisé et l'image peut être enregistrée dans un fichier, affichée ou crue sur stdout.

Le code le plus court en octets gagne.

Exemples

(Le tout agrandi de 500%.)

Si l'entrée est w=2, h=1, s=0alors la sortie sera toujours:

Si l'entrée est w=2, h=1, s=1alors la sortie sera l'une de ces images avec une chance égale:

Si l'entrée est w=2, h=1, s=2alors la sortie sera

ou peut-être

si le réseau est supposé avoir du PBC.

(Notez que démarrer le chemin comme le rendrait impossible une deuxième étape.)


Voici quelques sorties possibles pour w=3, h=2, s=6, en supposant PBC:


Voici une sortie possible pour w=3, h=3, s=9, en supposant PBC:

Notez que le chemin n'a pas eu besoin de couvrir toutes les cellules car l'intersection compte pour deux étapes. De plus, nous pouvons en déduire que le point d'extrémité d'angle était la cellule de départ car le passage supérieur d'intersection doit avoir été tracé par la suite. Ainsi, nous pouvons déduire la séquence de choix aléatoires qui ont été faits:

start at top left, facing east
go straight
go right
go right
go right
go straight
go left
go right
end

Enfin, voici des exemples de w=4, h=5, s=20et w=4, h=5, s=16:


1
L'idée n'est qu'une marche aléatoire, non?
Akangka

Ligne 2: You will be drawing a non-self-intersecting random walk... est-elle auto-intersectée ou non?
edc65

@ChristianIrwan Eh bien pas vraiment. Les promenades aléatoires peuvent généralement se replier sur elles-mêmes ou ne pas s'entrecroiser. C'est un cas unique car des intersections sont faites mais elles ne comptent pas comme retraçant le même sol. Et oui, cela pourrait être dans un format ascii-art ou quelque chose mais j'aime l'idée de faire de belles images.
Calvin's Hobbies

2
@ChristianIrwan J'ai déjà répondu que quand j'ai dit "Et oui, cela pourrait être dans un format ascii-art ou quelque chose mais j'aime l'idée de faire de belles images." Je choisis de ne pas impliquer l'ascii-art.
Calvin's Hobbies

1
Les "nœuds" sont-ils autorisés?
aditsu

Réponses:


4

CJam, 274

q~:K;:B;:A;{0aA*aB*:M5*5f*:I;K{[Bmr:QAmr:P]5f*:R;3Ym*{R.+:)2{1$0=I=2$W=@tI@0=@t:I;}:F~}/R2f+1FK({MQ=P=:EY4mr:D#&1{{MQMQ=PE2D#+tt:M;}:G~7,1>[W0_1_0_W]2/D=:Off*{[QP]5f*2f+.+_:H1F_OW%.+2FOW%.m2F}/H2FO~P+:P;Q+:Q;MQ=P=:E_5YD2%-*=!JK2-=+*1{D2+4%:D;G}?}?}fJ]}0?}g'P2NA5*SI,N2NI:+N*

Essayez-le en ligne

Utilise PBC, sorties au format PGM. Vous pouvez supprimer la :+fin pour obtenir une sortie visuelle plus agréable dans le navigateur.

C'est très lent pour une entrée plus importante, surtout si le nombre de pas est proche de la zone.

Exemple de résultat pour l'entrée 4 3 10(mise à l'échelle 500%):

Exemple

Brève explication:

L'approche générale est la suivante:

  • répétez toutes les étapes suivantes jusqu'à la réussite:
  • initialiser 2 matrices: une pour enregistrer les côtés utilisés dans chaque cellule et une pour l'image
  • si s = 0, nous avons terminé, sinon:
  • choisissez une cellule aléatoire et dessinez un carré, puis effectuez les s-1 fois suivantes:
  • choisissez une direction aléatoire; si ce côté est déjà utilisé, échouez et recommencez
  • marquez le côté comme utilisé et dessinez le tuyau réel dans l'image (en dessinant 3 lignes adjacentes de longueur 6, en commençant juste "après" le pixel central de la cellule actuelle, puis en ajoutant un point pour coiffer l'extrémité du tuyau)
  • mettre à jour la position actuelle (passer à la cellule suivante)
  • vérifiez si la cellule est vide ou s'il s'agit d'un croisement valide; sinon, échouer et recommencer
  • marquez le côté dans la direction opposée comme utilisé dans cette cellule, puis continuez la boucle

1

QBasic, 517 516 octets

RANDOMIZE TIMER
SCREEN 9
INPUT w,h,s
1CLS
IF s=0GOTO 9
x=5*INT(RND*w)
y=5*INT(RND*h)
GOSUB 7
FOR k=1TO s-1
r=INT(RND*4)+1
a=x+5*((r=2)-(r=4))
b=y+5*((r=1)-(r=3))
c=(POINT(a,b+2)*POINT(a+4,b+2)+POINT(a+2,b)*POINT(a+2,b+4))*(0=POINT((a+x)\2+2,(b+y)\2+2))
IF((0=POINT(a+2,b+2))+c)*(a>=0)*(b>=0)*(a<5*w)*(b<5*h)=0GOTO 1
x=a
y=b
GOSUB 7
o=1AND r
p=x-2+3*o-5*(r=2)
q=y+1-3*o-5*(r=1)
u=p+3-o
v=q+2+o
LINE(p,q)-(u,v),7,B
LINE(p+o,q+1-o)-(u-o,v-1+o),1
NEXT
9IF c GOTO 1
END
7LINE(x+1,y+1)-(x+3,y+3),7,B
PSET(x+2,y+2),1
RETURN
  • Prend w, het à spartir de l'entrée utilisateur, séparé par des virgules.
  • La sortie est dessinée à l'écran. Pendant que le programme recherche une solution, vous pouvez voir des solutions partielles clignoter.
  • N'utilise pas de conditions aux limites périodiques. J'ai trouvé plus facile de dessiner et de tester les tuyaux de raccordement sans avoir à se soucier de la moitié du tuyau se trouvant d'un côté de la grille et de l'autre de l'autre.

L'approche ici consiste à essayer une direction aléatoire à chaque étape et à recommencer depuis le début si elle entraîne un mouvement invalide. Nous dessinons les tuyaux au fur et à mesure que les directions sont décidées et utilisons POINTpour tester des points sur l'écran pour nos conditions de validité. Un mouvement est valide s'il ne sort pas des limites de la grille et:

  1. La cellule déplacée est vide; ou
  2. Tous les deux
    1. La cellule déplacée contient un tuyau passant directement, horizontalement ou verticalement, et
    2. La nouvelle section de tuyau ne double pas une section de tuyau existante

Comme la réponse CJam d'Aditsu , ce code est très lent et peut être incroyablement lent s'il sreprésente une fraction importante de w*h. Sur ma configuration QB64, il fournit une réponse 5,5,19assez rapidement, mais prend plus de temps que je ne le souhaitais 5,5,20.

Si vous souhaitez exécuter des exemples plus volumineux / plus denses, voici mon approche originale en utilisant une recherche en profondeur d'abord . C'est beaucoup plus efficace, au prix d'un énorme 300 octets supplémentaires.

RANDOMIZE TIMER
SCREEN 9
INPUT w,h,s
DIM t(s),m(s)
0
FOR z=1TO s
t(z)=-1
NEXT
i=5*INT(RND*w)
j=5*INT(RND*h)
k=1
1CLS
IF s=0GOTO 9
x=i
y=j
GOSUB 7
FOR z=1TO k-1
r=m(z)
GOSUB 6
x=a
y=b
GOSUB 7
o=1AND r
p=x-2+3*o-5*(r=2)
q=y+1-3*o-5*(r=1)
u=p+3-o
v=q+2+o
LINE(p,q)-(u,v),7,B
LINE(p+o,q+1-o)-(u-o,v-1+o),1
NEXT
IF c*(k=s)THEN k=k-1:GOTO 1 ELSE IF k=s GOTO 9
IF k<1GOTO 0
IF t(k)>=0GOTO 4
t(k)=0
f=30
WHILE f
r=INT(RND*4)+1
IF f AND 2^r THEN t(k)=t(k)*5+r:f=f-2^r
WEND
4r=t(k)MOD 5
m(k)=r
t(k)=t(k)\5
GOSUB 6
c=(POINT(a,b+2)*POINT(a+4,b+2)+POINT(a+2,b)*POINT(a+2,b+4))*(0=POINT((a+x)\2+2,(b+y)\2+2))
IF((0=POINT(a+2,b+2))+c)*(a>=0)*(b>=0)*(a<5*w)*(b<5*h)THEN k=k+1 ELSE IF t(k)>0GOTO 4 ELSE t(k)=-1:k=k-1
GOTO 1
6a=x+5*((r=2)-(r=4))
b=y+5*((r=1)-(r=3))
RETURN
7LINE(x+1,y+1)-(x+3,y+3),7,B
PSET(x+2,y+2),1
RETURN
9

Exemple de sortie pour les entrées 10, 10, 100, taille réelle:Plomberie aléatoire 10x10

Une version encore plus sophistiquée peut être trouvée dans cet essentiel . En plus d'être non golfé et complètement commenté, il augmente la sortie d'un facteur constant et permet un délai défini entre les étapes, vous permettant de regarder l'algorithme DFS au travail. Voici un exemple d'exécution:

plumbing.bas de luxe en action

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.