아미 다쿠지 (阿 弥陀 籤) 단순화


10

일본이나 동아시아 문화에 노출 된 적이 있다면 반드시 아미 다쿠지 게임을 보게 될 것입니다.

여기에 이미지 설명을 입력하십시오

위키 백과 설명 , 그것은 복권의 유형 종이에 그려진 무작위 N 항목의 순열을 선택하는 데 사용입니다.

예를 들어, 시작 순서를 N 명에게 무작위로 할당하거나 N 상을 N 명에게 무작위로 할당하는 데 사용될 수 있습니다.

게임이 순열을 나타내는 이유를 이해하는 데 트릭은 (는 "다리"라고 함) 모든 수평 스트로크를 실현하는 것입니다 스왑 장소에 두 개의 항목을.

같은 Wikipedia 페이지에서는 N 항목의 각 순열 P가 무한한 수의 아미 다쿠지 다이어그램에 해당한다고 설명합니다. 가장 적은 수의 수평 스트로크 (다리)를 가진 것을 특정 순열 P의 "프라임"이라고합니다.

당신의 임무는이 형식 (문자 제외)에서 2 개 이상의 수직선 (이 예에서는 6 개)이있는 아미 다쿠지 다이어그램을받는 것입니다.

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

그리고 그 소수 중 하나를 생성하십시오 (다시, 문자를 뺀 것).

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

문자가있는 첫 번째 및 마지막 줄 은 형식의 일부 가 아닙니다 . 순열을 보여주기 위해 여기에 추가했습니다. 또한되어 있지 첫 번째 또는 마지막 줄이 더 다리를 포함하지 않는 것을 요구 |-|, 출력이 가능한 소형으로 할 수있다.

이 특정 입력 예제는 Wikipedia 페이지 맨 위에있는 Amidakuji 다이어그램의 (무한한) ASCII 표현 중 하나입니다.

이 ASCII 다이어그램에 대한 명백한 규칙이 하나 있습니다. 인접한 다리는 금지됩니다.

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

Wikipedia는 "거품"이라는 다이어그램에서 소수를 얻는 표준 절차를 설명합니다.이 절차는 다음과 같은 단순화를 반복해서 적용합니다.

1) 오른쪽 포크에서 왼쪽 포크로 :

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

2) 복식 제거 :

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

그 설명이 모호하지 않은지 잘 모르겠습니다. 코드는 해당 기술 또는 필요한 소수를 생성하는 다른 알고리즘을 사용할 수 있습니다.

가장 짧은 코드가 승리합니다.

표준 규칙 및 표준 허용량이 적용됩니다. (입력이 유효하지 않으면 프로그램에서 불이 붙을 수 있습니다. 입력 / 출력 형식은 stdin / stdout, 문자열 인수, 행 목록, 문자 매트릭스 등 가장 적합한 방법 등일 수 있습니다.)

여기에 이미지 설명을 입력하십시오


3
이것은 매우 흥미로운 도전입니다. 언 골프 솔루션을 만드는 데 시간이 걸릴 수 있습니다.
JosiahRyanW

출력이 가능한 한 콤팩트해야합니까? 또는 레그 수가 최소 인 한 허용되는 수직 공간이 있습니까?
Laikoni

@Laikoni 모든 수직 공간이 허용됩니다.
Tobia

기 포화와 역 기포 화가 동일한 결과에 도달합니까?
l4m2

@ l4m2 역 버블 링이란 무엇입니까?
Tobia

답변:


4

파이썬 2 , 322240 바이트

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

온라인으로 사용해보십시오!

문자열을 지정된 형식으로 가져 가서 축소 된 아미 다쿠지를 해당 형식으로 인쇄하는 기능입니다.

여기서 기본 아이디어는 먼저 입력을 순열 ( for x in X루프에서) 로 변환하는 것입니다 . 다음에 while루프, 이후 위키 피 디아 문서 노트는 '프라임'Amidakuji이 결과로, 그 순열의 버블 정렬을 수행합니다.


와. 방금 파이썬 3 버전을 만드는 데 오랜 시간을 보냈지 만 526 바이트입니다.
JosiahRyanW

방금 수백 개의 임의 다이어그램을 코드에 공급했으며 올바른 소수를 출력하는지 확인할 수 있습니다!
Tobia

3

하스켈 , 288 바이트

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

온라인으로 사용해보십시오!

설명

-- 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

잘 했어! 나는 당신의 코드에 1000 개의 임의의 다이어그램을 공급했으며 그것들을 모두 해결했습니다.
Tobia

(_:[])단지 수 있습니다 [_]p?q=(p:fst q,snd q)수 있습니다 p?(f,s)=(p:f,s). 대신 정의하는 c 0='-';c _=' ';사용 후와 c m, " -"!!(0^abs m)작동합니다.
Laikoni

(g 0)괄호가 필요하지 않으며 let가드가보다 짧습니다 where. 모두 함께 274 바이트 : 온라인으로 사용해보십시오!
Laikoni

픽스 포인트 함수 %는로 인라인 될 수 있습니다 until(\x->g 0 x==x)(g 0).
Laikoni

2

레티 나 0.8.2 , 105 바이트

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

온라인으로 사용해보십시오! 설명:

$
¶$%`

마지막 줄을 복제하십시오.

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

마지막 줄의 열 번호를 지정하십시오.

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

숫자가 첫 번째 줄에 올 때까지 위로 이동하십시오. 각 반복에서 가장 오른쪽의 숫자 만 -1=이동됩니다. |앞에 오는 경우가 아니면 가장 오른쪽으로 이동하며, -이 경우 이전으로 이동합니다 |. (이것은 r정규 표현식이 룩백처럼 처리 되어이 경우와 거의 일치하지 않음을 나타냅니다.) 이것은 Amidakuji가 정렬 된 순서로 변환되는 순열을 계산합니다.

-
 
1G`

숫자 목록 만 유지 -하고 첫 번째 줄 뒤의 s 및 기타 항목을 삭제하십시오 .

;{`

그런 다음 나머지 프로그램은 반복하여 목록을 순서대로 정렬하지만 최종 목록은 인쇄되지 않지만 Retina 0.8.2에서 목록이 순서대로 있음을 알기 위해 반복하지 않으므로 다리가없는 행은 다음과 같습니다. 마지막에 생성되었으므로 허용됩니다.

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

-다리에 사용할 수있는 인접 정렬되지 않은 숫자 쌍을 모두 s로 표시하십시오.

*`1+
|

다리를 인쇄하되 숫자를 |s 로 바꿉니다.

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

실제로 스왑을 수행하십시오.


Retina.exe로 코드를 실행하는 방법에 대한 조언이 있습니까? 올바른 소스 (105 바이트)가 있다고 생각하지만 아무것도 출력하지 않습니다. Retina 예제 에서 Hello World를 사용해 보았습니다 . 인코딩이 잘못 된 경우 소스를 어딘가에 업로드하거나 Base64로 인코딩하여 pastebin에 넣을 수 있습니까?
Tobia

@Tobia 죄송하지만 Retina.exe 사용 방법을 기억할 수 없습니다. 한두 번 사용했을 수도 있지만 요즘에는 온라인으로 사용해보십시오.
Neil

LOL 난 바보 야! 0.8.2 대신 최신 버전을 사용하고있었습니다. 이제 코드에 수백 개의 임의 다이어그램을 제공 할 수있는 하네스를 얻었으며 항상 올바른 소수를 출력 함을 확인할 수 있습니다. 잘 했어!
Tobia

@Tobia 테스트 해 주셔서 감사합니다! 망막 1에 필요한 조정 : $**; -1=0; 1_; ;.(대략); **\.
Neil

1

파이썬 3 , 524 4486 486 바이트

ovs 덕분에 -38 바이트!

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="|")

온라인으로 사용해보십시오!

이것은 Amidakuji를 2D 이진 배열로 변환하고 규칙을 사용하여 직접 줄입니다.


당신의 접근 방식이 궁금합니다. 내가 볼게요! 한편, 당신은 대체하여 몇 바이트를 저장할 수 있습니다 " "+i.replace("|","")+" "으로 i.split("|")한다. p함수 의 첫 번째 줄 ...
Chas Brown

좀 더 표준 python golfing이 479 바이트로 조정되었습니다 .
Chas Brown


Yah, 왜 그런 일이 일어나고 있는지 잘 모르겠습니다.
Chas Brown

항상 그렇지는 않습니다. 때때로 오른쪽 포크에서 왼쪽 포크는 할 수 없지만 왼쪽 포크에서 오른쪽 포크는 가능합니다. 이 특정한 경우에, 그것은 반대의 일의 문제 일뿐입니다. 아마도 둘 다해야합니까?
JosiahRyanW

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.