Amidakuji (阿 弥陀 籤) simplification


10

Si vous avez déjà été exposé à la culture japonaise ou asiatique, vous aurez sûrement rencontré le jeu Amidakuji:

entrez la description de l'image ici

Comme l'explique Wikipedia , il s'agit d'un type de loterie dessiné sur papier et utilisé pour sélectionner aléatoirement une permutation de N éléments.

Par exemple, il peut être utilisé pour attribuer au hasard une séquence de départ à N personnes, ou N prix à N personnes, et ainsi de suite.

L'astuce pour comprendre pourquoi le jeu représente une permutation est de réaliser que chaque coup horizontal (appelé "jambe") échange ses deux éléments en place.

La même page Wikipédia explique également que chaque permutation P de N éléments correspond à un nombre infini de diagrammes d'Amidakuji. Celui (s) avec le moins de coups horizontaux (jambes) sont appelés les "nombres premiers" de cette permutation particulière P.

Votre tâche consiste à recevoir un diagramme Amidakuji avec 2 lignes verticales ou plus (dans cet exemple, elles sont 6) dans ce format (moins les lettres):

A B C D E F
| | | | | |
|-| |-| |-|
| |-| |-| |
| | | | |-|
| |-| |-| |
| | |-| |-|
| | |-| | |
|-| | |-| |
|-| |-| | |
| |-| | |-|
| | | | | |
B C A D F E

Et produisez l'un de ses nombres premiers (encore une fois, moins les lettres):

A B C D E F
| | | | | |
|-| | | |-|
| |-| | | |
| | | | | |
B C A D F E

Les première et dernière lignes avec les lettres ne font pas partie du format. Je les ai ajoutés ici pour montrer la permutation. Il n'est pas non plus nécessaire que la première ou la dernière ligne ne contienne pas de segments |-|, ni que la sortie soit aussi compacte que possible.

Cet exemple d'entrée particulier est l'une des représentations ASCII (infinies) du diagramme d'Amidakuji en haut de la page Wikipedia.

Il existe une règle non évidente concernant ces diagrammes ASCII: les tronçons adjacents sont interdits.

|-|-|  <-  NO, this does not represent a single swap!

Wikipedia explique une procédure standard pour obtenir un nombre premier à partir d'un diagramme, appelé "bubblisation", qui consiste à appliquer les simplifications suivantes encore et encore:

1) Fourche droite à fourche gauche:

| |-|      |-| |
|-| |  ->  | |-|
| |-|      |-| |

2) Élimination des doubles:

|-|        | |
|-|   ->   | |

Je ne sais pas si cette explication est sans ambiguïté. Votre code peut utiliser cette technique ou tout autre algorithme qui produit les nombres premiers requis.

Le code le plus court gagne.

Des règles et des allocations standard s'appliquent. (Si l'entrée n'est pas valide, votre programme peut prendre feu. Les formats d'entrée / sortie peuvent être stdin / stdout, argument chaîne, liste de lignes, matrice de caractères, tout ce qui vous convient le mieux, etc.)

entrez la description de l'image ici


3
C'est un défi très intéressant. Je pourrais prendre un certain temps à produire une solution non golfée, heh.
JosiahRyanW

La sortie doit-elle être aussi compacte que possible ou une quantité d'espace vertical est-elle autorisée tant que le nombre de jambes est minimal?
Laikoni

@Laikoni toute quantité d'espace vertical est autorisée.
Tobia

La bubblisation et la bubblisation inverse atteignent-elles le même résultat Amidakuji?
l4m2

@ l4m2 qu'est-ce que la barbotisation inverse?
Tobia

Réponses:


4

Python 2 , 322 240 octets

def f(X):
 X=[[c>' 'for c in s.split('|')]for s in X.split('\n')];h=L=len(X[0])-1;p=range(L)
 for x in X:p=[a-x[a]+x[a+1]for a in p]
 while h:h=i=0;exec"if p[i]>p[i+1]:print'|'+i*' |'+'-|'+(L-i-2)*' |';h=p[i],p[i+1]=p[i+1],p[i]\ni+=1\n"*~-L

Essayez-le en ligne!

Une fonction qui prend la chaîne sous la forme spécifiée et imprime également l'Amidakuji réduit sous cette forme.

L'idée de base ici est de convertir d'abord l'entrée en une permutation (dans la for x in Xboucle); puis dans la whileboucle, effectuez une sorte de bulle de cette permutation, car comme le note l'article de wikipedia, cela se traduit par un Amidakuji «premier».


Sensationnel. Je viens de passer beaucoup de temps à créer une version Python 3, mais c'est 526 octets, hein.
JosiahRyanW

Je viens de fournir des centaines de diagrammes aléatoires à votre code et je peux confirmer qu'il génère des nombres premiers corrects!
Tobia

3

Haskell , 288 octets

p x(_:[])=x
p(x:y:z)(_:b:c)|b=='-'=y:p(x:z)c|0<1=x:p(y:z)c
c 0='-'
c _=' '
_#1="|"
m#n='|':c m:(m-1)#(n-1)
p?q=(p:fst q,snd q)
f%b|b==f b=b|0<1=f%f b
f l=reverse$snd$(g 0)%(foldl p[1..n]l,[])where n=1+div(length$l!!0)2;g b((x:y:z),a)|x>y=y?g(b+1)(x:z,a++[b#n])|0<1=x?g(b+1)(y:z,a);g _ x=x

Essayez-le en ligne!

Explication

-- the function p performs the permutation of a list
-- according to a single line from amidakuji board
p x (_:[]) = x
p (x:y:z) (_:b:c)
    | b == '-' = y : p (x : z) c
    | otherwise = x : p (y : z) c

-- helper to select either leg '-' or empty cell
c 0 = '-'
c _ = ' '

-- the # operator generates an amidakuji line containing one leg
-- which corresponds to one swap during bubble sort

-- terminal case, just one edge left
_ # 1 = "|"
-- each cell contains an edge '|' and either space or a '-' for the "active" cell
m # n = '|' : c m : (m - 1) # (n - 1)

-- helper to find the limit value of a function iteration
f % b
    | b == f b = b  -- return the value if it is unchanged by the function application 
    | otherwise = f % f b -- otherwise repeat

-- helper to appropriately combine q which is the result of invocation of 
-- the function g (see below), and a character p
p ? q = (p : fst q, snd q)

-- the function that does the work
f l = reverse $ snd $ (g 0) % (foldl p [1..n] l, []) where
    -- number of lines on the board
    n = 1 + div (length $ l !! 0) 2
    -- apply one iteration of bubble sort yielding (X, Y)
    -- where X is partially sorted list and Y is the output amidakuji
    g b ((x:y:z), a)
        -- if we need to swap two elements, do it and add a line to our board
        | x > y = y ? g (b + 1) (x:z, a ++ [b # n])
        -- if we don't need to, just proceed further
        | otherwise = x ? g (b + 1) (y:z, a)
    -- terminal case when there is only one element in the list
    g _ x = x

Bon travail! J'ai fourni des milliers de diagrammes aléatoires à votre code et il les a tous résolus.
Tobia

(_:[])peut être juste [_]et p?q=(p:fst q,snd q)peut être p?(f,s)=(p:f,s). Au lieu de définir c 0='-';c _=' ';puis d'utiliser c m, " -"!!(0^abs m)devrait fonctionner.
Laikoni

(g 0)n'a pas besoin de supports et un letdans une garde est plus court que where. Au total 274 octets: essayez-le en ligne!
Laikoni

Votre fonction de point fixe %peut être intégrée à until(\x->g 0 x==x)(g 0).
Laikoni du

2

Retina 0.8.2 , 105 octets

$
¶$%`
r`.?.\G
 1$.'$*
+r-1=`\|(-?.?[- 1]*¶.*)(1+)
$2$1
-
 
1G`
;{`\b(1+) \1
$1-$1
*`1+
|
(1+)-(1+)
$2 $1

Essayez-le en ligne! Explication:

$
¶$%`

Dupliquez la dernière ligne.

r`.?.\G
 1$.'$*

Numérotez les colonnes de la dernière ligne.

+r-1=`\|(-?.?[- 1]*¶.*)(1+)
$2$1

Déplacez les chiffres vers le haut jusqu'à ce qu'ils atteignent la première ligne. À chaque itération, seul le nombre le plus à droite -1=est déplacé. Il est déplacé vers la droite, à |moins qu'il ne soit précédé d'un, -auquel cas il est déplacé vers le précédent |. (Le rindique que l'expression régulière est traitée comme s'il s'agissait d'un lookbehind, ce qui facilite légèrement la correspondance avec ce cas.) Ceci calcule la permutation que l'Amidakuji transforme en ordre trié.

-
 
1G`

Gardez juste la liste des nombres, en supprimant les -s et n'importe quoi après la première ligne.

;{`

Le reste du programme est ensuite répété, puis trie la liste dans l'ordre, mais la liste finale n'est pas imprimée, mais comme il faut une itération pour que Retina 0.8.2 remarque que la liste est en ordre, une ligne sans jambes est généré à la fin, ce qui, je pense, est acceptable.

\b(1+) \1
$1-$1

Marquez toutes les paires disponibles de numéros adjacents non triés avec -s pour les jambes.

*`1+
|

Imprimez les jambes mais avec les numéros remplacés par |s.

(1+)-(1+)
$2 $1

Effectuez en fait les swaps.


Avez-vous des conseils sur la façon d'exécuter votre code avec Retina.exe ? Je pense avoir la bonne source (105 octets) mais elle ne produit rien. J'ai essayé le Hello World à partir des exemples Retina et cela fonctionne. Pouvez-vous télécharger la source quelque part, ou Base64 l'encoder et la mettre dans une boîte à pâte, au cas où j'aurais mal encodé?
Tobia

@Tobia Désolé, mais je ne me souviens pas comment utiliser Retina.exe; Je pense que je pourrais l'avoir utilisé une ou deux fois, mais ces jours-ci, j'utilise simplement Try It Online.
Neil

LOL, je suis stupide! J'utilisais une version de pointe au lieu de 0.8.2. Maintenant, j'ai obtenu mon harnais pour alimenter des centaines de diagrammes aléatoires dans votre code et je peux confirmer qu'il génère toujours les nombres premiers corrects. Bon travail!
Tobia

@Tobia Merci pour les tests! Ajustements nécessaires pour Retina 1: $**; -1=0; 1_; ;.(à peu près); **\.
Neil

1

Python 3 , 524 488 486 octets

-38 octets grâce aux ovs!

from numpy import*
A=array;E=array_equal
K=[0]
def r(a,m,n):
	X=len(m);Y=len(m[0]);W,H=a.shape
	for x in range(W-X+1):
		for y in range(H-Y+1):
			if E(a[x:x+X,y:y+Y],A(m)):a[x:x+X,y:y+Y]=A(n)
	return a
def p(a):
	b=A([[j>" "for j in i]for i in[i.split("|")for i in a.split("\n")]])
	while E(a,b)<1:a=b;Z=K*3;O=[0,1,0];T=[K+O,O+K]*2;D=[O,O],[Z,Z];P=[Z,O],[O,Z];*R,_=T;_,*L=T;b=r(r(r(r(r(r(a[any(a,1)],R,L),*D),*P),L,R),*D),*P)
	for i in a:print("",*[" -"[j]for j in i[1:-1]],"",sep="|")

Essayez-le en ligne!

Cela convertit l'Amidakuji en un tableau binaire 2D et le réduit directement à l'aide des règles.


Je suis curieux de connaître votre approche; Je regarderai! En attendant, vous pouvez économiser quelques octets en remplaçant " "+i.replace("|","")+" "par i.split("|")in. la première ligne de votre pfonction ...
Chas Brown

Quelques ajustements de golf en python plus standard pour atteindre 479 octets .
Chas Brown


Yah, je ne sais pas pourquoi cela se produit ...
Chas Brown

Pas toujours ... parfois, la fourche droite à la fourche gauche n'est pas faisable, mais la fourche gauche à la fourche droite l'est. Dans ce cas précis, il s'agit simplement de faire le contraire. Peut-être que je dois faire les deux?
JosiahRyanW

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.