Đơn giản hóa Amidakuji (阿 弥陀 籤)


10

Nếu bạn đã từng tiếp xúc với văn hóa Nhật Bản hoặc Đông Á, bạn chắc chắn sẽ bắt gặp trò chơi Amidakuji:

nhập mô tả hình ảnh ở đây

Như Wikipedia giải thích , đây là một loại xổ số được vẽ trên giấy và được sử dụng để chọn ngẫu nhiên một hoán vị của N vật phẩm.

Ví dụ: nó có thể được sử dụng để gán ngẫu nhiên một chuỗi bắt đầu cho N người hoặc N giải thưởng cho N người, v.v.

Mẹo để hiểu lý do tại sao trò chơi đại diện cho một hoán vị là nhận ra rằng mọi nét ngang (được gọi là "chân") đều hoán đổi hai vật phẩm của nó tại chỗ.

Trang Wikipedia tương tự cũng giải thích rằng mỗi P hoán vị của N mục tương ứng với vô số sơ đồ Amidakuji. (Các) số có ít nhất các nét ngang (chân) được gọi là "số nguyên tố" của hoán vị cụ thể P.

Nhiệm vụ của bạn là nhận một sơ đồ Amidakuji có 2 hoặc nhiều dòng dọc (trong ví dụ này là 6) theo định dạng này (trừ các chữ cái):

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

Và tạo một trong các số nguyên tố của nó (một lần nữa, trừ các chữ cái):

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

Các dòng đầu tiên và cuối cùng với các chữ cái không phải là một phần của định dạng. Tôi đã thêm chúng ở đây để hiển thị hoán vị. Cũng không yêu cầu các dòng đầu tiên hoặc cuối cùng không chứa chân |-|, cũng như đầu ra càng nhỏ gọn càng tốt.

Ví dụ đầu vào cụ thể này là một trong những biểu diễn ASCII (vô hạn) của sơ đồ Amidakuji ở đầu trang Wikipedia.

Có một quy tắc không rõ ràng về các sơ đồ ASCII này: các chân liền kề bị cấm.

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

Wikipedia giải thích một quy trình chuẩn để có được một số nguyên tố từ một sơ đồ, được gọi là "bong bóng", bao gồm việc áp dụng các đơn giản hóa sau và hơn:

1) Nĩa phải sang ngã ba trái:

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

2) Loại bỏ nhân đôi:

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

Tôi không chắc liệu lời giải thích đó có rõ ràng không. Mã của bạn có thể sử dụng kỹ thuật đó hoặc bất kỳ thuật toán nào khác tạo ra các số nguyên tố cần thiết.

Mã ngắn nhất sẽ thắng.

Quy tắc tiêu chuẩn và phụ cấp tiêu chuẩn được áp dụng. (Nếu đầu vào không hợp lệ, chương trình của bạn có thể bắt lửa. Các định dạng đầu vào / đầu ra có thể là stdin / stdout, đối số chuỗi, danh sách các dòng, ma trận ký tự, bất cứ điều gì phù hợp nhất với bạn, v.v.)

nhập mô tả hình ảnh ở đây


3
Đây là một thử thách rất thú vị. Tôi có thể mất một lúc để tạo ra một giải pháp vô căn cứ, heh.
JosiahRyanW

Là đầu ra cần phải nhỏ gọn nhất có thể hoặc bất kỳ số lượng không gian dọc cho phép miễn là số lượng chân là tối thiểu?
Laikoni

@Laikoni bất kỳ số lượng không gian dọc được cho phép.
Tobia

Liệu bong bóng và bong bóng ngược có đạt được mọi kết quả Amidakuji không?
l4m2

@ l4m2 bong bóng nghịch đảo là gì?
Tobia

Câu trả lời:


4

Python 2 , 322 240 byte

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

Hãy thử trực tuyến!

Một hàm lấy chuỗi ở dạng đã chỉ định và cũng in ra Amidakuji đã giảm ở dạng đó.

Ý tưởng cơ bản ở đây là trước tiên chuyển đổi đầu vào thành một hoán vị (trong for x in Xvòng lặp); và sau đó trong whilevòng lặp, thực hiện một loại bong bóng của hoán vị đó, vì như bài viết trên wikipedia, điều này dẫn đến một Amidakuji 'nguyên tố'.


Ồ Tôi mới dành một thời gian dài để tạo phiên bản Python 3, nhưng đó là 526 byte, heh.
JosiahRyanW

Tôi chỉ cung cấp hàng trăm sơ đồ ngẫu nhiên cho mã của bạn và tôi có thể xác nhận rằng nó đưa ra các số nguyên tố chính xác!
Tobia

3

Haskell , 288 byte

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

Hãy thử trực tuyến!

Giải trình

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

Làm tốt lắm! Tôi đã cung cấp 1000 sơ đồ ngẫu nhiên cho mã của bạn và nó đã giải quyết tất cả.
Tobia

(_:[])có thể vừa [_]p?q=(p:fst q,snd q)có thể p?(f,s)=(p:f,s). Thay vì xác định c 0='-';c _=' ';và sau đó sử dụng c m, " -"!!(0^abs m)nên làm việc.
Laikoni

(g 0)không cần dấu ngoặc và lettrong một bảo vệ ngắn hơn where. Tất cả cùng nhau 274 byte: Hãy thử trực tuyến!
Laikoni

Chức năng fixpoint của bạn %có thể được nội tuyến với until(\x->g 0 x==x)(g 0).
Laikoni

2

Võng mạc 0.8.2 , 105 byte

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

Hãy thử trực tuyến! Giải trình:

$
¶$%`

Nhân đôi dòng cuối cùng.

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

Đánh số các cột trong dòng cuối cùng.

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

Di chuyển các số lên cho đến khi chúng đến dòng đầu tiên. Ở mỗi lần lặp, chỉ có số ngoài cùng bên phải -1=được di chuyển. Nó được di chuyển đến ngoài cùng bên phải |trừ khi nó được đi trước bởi -trong trường hợp nó được chuyển sang trước đó |. (Cácr chỉ ra rằng regex được xử lý như thể nó là một lookbehind, mà làm cho nó nhẹ dễ dàng hơn để phù hợp với trường hợp này). Điều này tính toán hoán vị rằng biến đổi Amidakuji vào thứ tự sắp xếp.

-
 
1G`

Chỉ giữ danh sách các số, xóa -s và bất cứ thứ gì sau dòng đầu tiên.

;{`

Phần còn lại của chương trình sau đó được lặp lại sắp xếp danh sách theo thứ tự, nhưng danh sách cuối cùng không được in, tuy nhiên, phải mất một lần lặp cho Retina 0.8.2 để nhận thấy rằng danh sách theo thứ tự, một dòng không có chân là tạo ra ở cuối, mà tôi tin là chấp nhận được.

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

Đánh dấu tất cả các cặp số chưa sắp xếp liền kề bằng -s cho chân.

*`1+
|

In chân nhưng với số được thay thế bằng |s.

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

Thực tế thực hiện các giao dịch hoán đổi.


Bạn có lời khuyên nào về cách chạy mã của bạn với Retina.exe không? Tôi nghĩ rằng tôi có nguồn chính xác (105 byte) nhưng nó không cho ra kết quả gì. Tôi đã thử Hello World từ các ví dụ Retina và nó hoạt động. Bạn có thể tải lên nguồn ở đâu đó, hoặc Base64 mã hóa nó và đặt nó vào một pastebin, trong trường hợp tôi nhận được mã hóa sai?
Tobia

@Tobia Xin lỗi, nhưng tôi không thể nhớ cách sử dụng Retina.exe; Tôi nghĩ rằng tôi có thể đã sử dụng nó một hoặc hai lần nhưng những ngày này tôi chỉ sử dụng Dùng thử trực tuyến.
Neil

LOL tôi thật ngốc! Tôi đã sử dụng một số phiên bản tiên tiến thay vì 0.8.2. Bây giờ tôi đã khai thác để cung cấp hàng trăm sơ đồ ngẫu nhiên cho mã của bạn và tôi có thể xác nhận rằng nó luôn đưa ra các số nguyên tố chính xác. Làm tốt lắm!
Tobia

@Tobia Cảm ơn bạn đã thử nghiệm! Tinh chỉnh cần thiết cho Retina 1: $**; -1=0; 1_; ;.(đại khái); **\.
Neil

1

Python 3 , 524 488 486 byte

-38 byte nhờ vào lò nướng!

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

Hãy thử trực tuyến!

Điều này chuyển đổi Amidakuji thành một mảng nhị phân 2D và trực tiếp giảm nó bằng cách sử dụng các quy tắc.


Tôi tò mò về cách tiếp cận của bạn; Tôi sẽ xem qua một chút! Trong khi đó, bạn có thể lưu một số byte bằng cách thay thế " "+i.replace("|","")+" "bằng i.split("|")in. dòng đầu tiên của pchức năng của bạn ...
Chas Brown

Một vài điều chỉnh golf python tiêu chuẩn để có được nó tới 479 byte .
Chas Brown


Yah, không chắc tại sao điều đó xảy ra ...
Chas Brown

Không phải lúc nào ... đôi khi rẽ phải sang ngã ba trái là không thể thực hiện được, nhưng rẽ trái sang ngã ba phải là. Trong trường hợp cụ thể đó, đó chỉ là vấn đề làm ngược lại ở đó. Có lẽ tôi cần phải làm cả hai?
JosiahRyanW

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.