การทำให้เข้าใจง่าย Amidakuji (阿 simpl 籤)


10

หากคุณเคยสัมผัสวัฒนธรรมญี่ปุ่นหรือเอเชียตะวันออกคุณจะได้พบกับเกม Amidakuji:

ป้อนคำอธิบายรูปภาพที่นี่

ตามที่Wikipedia อธิบายมันเป็นลอตเตอรีประเภทหนึ่งที่วาดบนกระดาษและใช้ในการสุ่มเลือกการเรียงสับเปลี่ยนของรายการ N

ตัวอย่างเช่นอาจใช้เพื่อกำหนดลำดับการเริ่มต้นแบบสุ่มให้กับคน N หรือรางวัล N ให้กับคน N และอื่น ๆ

เคล็ดลับในการทำความเข้าใจว่าทำไมเกมถึงแสดงถึงการเปลี่ยนแปลงคือการตระหนักว่าทุกจังหวะในแนวนอน (เรียกว่า "ขา") สลับสองรายการเข้าที่

หน้า Wikipedia เดียวกันนี้ยังอธิบายว่าการเปลี่ยนแปลง P ของ N รายการแต่ละรายการสอดคล้องกับแผนภาพ Amidakuji จำนวนไม่ จำกัด (s) ที่มีจำนวนน้อยที่สุดในแนวนอน (ขา) เรียกว่า "ช่วงเวลา" ของการเปลี่ยนแปลงเฉพาะ p

งานของคุณคือการรับไดอะแกรม Amidakuji ที่มีเส้นแนวตั้งตั้งแต่ 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

บรรทัดแรกและบรรทัดสุดท้ายที่มีตัวอักษรไม่ได้เป็นส่วนหนึ่งของรูปแบบ ฉันได้เพิ่มพวกเขาที่นี่เพื่อแสดงการเปลี่ยนแปลง นอกจากนี้ยังไม่จำเป็นที่บรรทัดแรกหรือสุดท้ายประกอบด้วยไม่มีขา|-|, หรือว่าการส่งออกจะเป็นขนาดเล็กที่สุดเท่าที่ทำได้

ตัวอย่างอินพุตเฉพาะนี้เป็นหนึ่งในการแทน ASCII (ไม่ จำกัด ) ของแผนภาพ Amidakuji ที่ด้านบนของหน้า Wikipedia

มีกฎข้อหนึ่งที่ไม่ชัดเจนเกี่ยวกับไดอะแกรม ASCII เหล่านี้คือห้ามไม่ให้ใช้ขาข้างกัน

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

Wikipedia อธิบายขั้นตอนมาตรฐานเพื่อให้ได้ไพรม์จากไดอะแกรมที่เรียกว่า "bubblization" ซึ่งประกอบด้วยการประยุกต์ใช้การทำให้เรียบง่ายต่อไปนี้ซ้ำแล้วซ้ำอีก:

1) ทางขวาไปทางซ้ายของทางแยก:

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

2) กำจัดคู่:

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

ฉันไม่แน่ใจว่าคำอธิบายนั้นไม่คลุมเครือหรือไม่ รหัสของคุณอาจใช้เทคนิคนั้นหรืออัลกอริทึมอื่น ๆ ที่สร้างช่วงเวลาที่ต้องการ

รหัสที่สั้นที่สุดชนะ

ใช้กฎมาตรฐานและค่าเผื่อมาตรฐาน (หากอินพุตไม่ถูกต้องโปรแกรมของคุณอาจติดไฟรูปแบบอินพุต / เอาท์พุตอาจเป็น stdin / stdout อาร์กิวเมนต์ string รายชื่อบรรทัดเมทริกซ์ของตัวอักษรสิ่งใดก็ได้ที่ดีที่สุดสำหรับคุณ ฯลฯ )

ป้อนคำอธิบายรูปภาพที่นี่


3
นี่เป็นความท้าทายที่น่าสนใจมาก ฉันอาจใช้เวลาสักครู่ในการสร้างทางออกที่ไม่ดี
JosiahRyanW

เอาท์พุทจะต้องมีขนาดกะทัดรัดที่สุดเท่าที่จะเป็นไปได้หรือมีพื้นที่แนวตั้งจำนวนเท่าใดก็ได้ตราบใดที่จำนวนขาน้อยที่สุด?
Laikoni

@Laikoni อนุญาตให้มีพื้นที่แนวตั้งจำนวนเท่าใดก็ได้
เบีย

การทำฟองสบู่และการพองตัวผกผันไปถึงผลลัพธ์เดียวกันทุก Amidakuji?
l4m2

@ l4m2 bubblization ผกผันคืออะไร?
Tobia

คำตอบ:


4

Python 2 , 322 240 ไบต์

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

ลองออนไลน์!

ฟังก์ชั่นที่รับสายในรูปแบบที่ระบุและพิมพ์ Amidakuji ที่ลดลงในรูปแบบนั้นเช่นกัน

แนวคิดพื้นฐานที่นี่คือการแปลงอินพุตเป็นการเปลี่ยนแปลงครั้งแรก (ในfor x in Xลูป); และจากนั้นในwhileวงวนให้เรียงลำดับฟองสบู่ของการเปลี่ยนลำดับเนื่องจากในขณะที่บทความวิกิพีเดียจดบันทึกสิ่งนี้จะส่งผลให้เกิด 'Amidakuji' แบบ 'นายก'


ว้าว. ฉันใช้เวลานานในการสร้าง Python 3 แต่มันมีขนาด 526 ไบต์ใช่มั้ย
JosiahRyanW

ฉันเพิ่งป้อนไดอะแกรมสุ่มหลายร้อยตัวให้กับรหัสของคุณและฉันสามารถยืนยันได้ว่ามันจะให้ผลที่ถูกต้อง!
เบีย

3

Haskellขนาด 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

เยี่ยมมาก! ฉันป้อนไดอะแกรมสุ่ม 1,000 รายการให้กับรหัสของคุณและแก้ไขได้ทั้งหมด
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

ฟังก์ชั่น fixpoint ของคุณ%สามารถสอดแทรก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บ่งชี้ว่า regex ถูกประมวลผลราวกับว่ามันเป็น lookbehind ซึ่งทำให้ง่ายขึ้นเล็กน้อยตรงกับกรณีนี้) ซึ่งคำนวณการเปลี่ยนแปลงที่ Amidakuji เปลี่ยนเป็นการเรียงลำดับ

-
 
1G`

เก็บเฉพาะรายการตัวเลขการลบ-s และอะไรก็ได้หลังจากบรรทัดแรก

;{`

ส่วนที่เหลือของโปรแกรมนั้นจะเรียงลำดับรายการกลับไปตามลำดับ แต่รายการสุดท้ายจะไม่ถูกพิมพ์อย่างไรก็ตามเนื่องจากต้องใช้การวนซ้ำสำหรับ Retina 0.8.2 เพื่อแจ้งให้ทราบว่ารายการอยู่ในลำดับบรรทัดที่ไม่มีขาอยู่ สร้างขึ้นในตอนท้ายซึ่งฉันเชื่อว่าเป็นที่ยอมรับ

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

ทำเครื่องหมายคู่ของตัวเลขที่ไม่ได้เรียงติดกันทั้งหมดด้วย-s สำหรับขา

*`1+
|

พิมพ์ขา แต่มีตัวเลขแทนที่ด้วย|s

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

ดำเนินการแลกเปลี่ยนจริง


คุณมีคำแนะนำในการรันโค้ดด้วยRetina.exeหรือไม่? ฉันคิดว่าฉันมีแหล่งข้อมูลที่ถูกต้อง (105 ไบต์) แต่ไม่มีผลอะไร ฉันลอง Hello World จากตัวอย่าง Retinaและใช้งานได้ คุณสามารถอัปโหลดที่มาที่อื่นหรือเข้ารหัส Base64 แล้ววางลงใน Pastebin ในกรณีที่ฉันเข้ารหัสผิด
เบีย

@Tobia ขออภัย แต่ฉันจำไม่ได้ว่าจะใช้ Retina.exe อย่างไร ฉันคิดว่าฉันอาจจะใช้มันครั้งหรือสองครั้ง แต่วันนี้ฉันแค่ใช้ลองออนไลน์
Neil

ฮ่า ๆ ฉันเป็นใบ้! ฉันใช้เวอร์ชั่นที่ทันสมัยแทน 0.8.2 ตอนนี้ฉันได้สายบังเหียนของฉันให้ส่งไดอะแกรมสุ่มหลายร้อยตัวให้กับรหัสของคุณแล้วและฉันสามารถยืนยันได้ว่ามันจะแสดงช่วงเวลาที่ถูกต้องเสมอ เยี่ยมมาก!
เบีย

@Tobia ขอบคุณสำหรับการทดสอบ! ต้องการ Tweaks สำหรับ Retina 1: $**; -1=0; 1_; ;.(ประมาณ) →* *\
Neil

1

Python 3 , 524 488 486 ไบต์

-38 ไบต์ขอบคุณ 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="|")

ลองออนไลน์!

สิ่งนี้จะแปลง Amidakuji ไปเป็นอาร์เรย์ไบนารีแบบ 2 มิติและลดลงโดยตรงโดยใช้กฎ


ฉันอยากรู้เกี่ยวกับวิธีการของคุณ; ฉันจะดู! ในขณะเดียวกันคุณสามารถบันทึกไบต์บางส่วนโดยการแทนที่" "+i.replace("|","")+" "ด้วยi.split("|")ใน บรรทัดแรกของpฟังก์ชั่นของคุณ...
Chas Brown

ไม่กี่ปรับแต่งหลามกอล์ฟมาตรฐานมากขึ้นที่จะได้ไป479 ไบต์
Chas Brown


ย่ะไม่แน่ใจว่าทำไมมันถึงเกิดขึ้น ...
Chas Brown

ไม่เสมอไป ... บางครั้งการแยกจากขวาไปซ้ายไม่สามารถทำได้ ในกรณีเฉพาะนั้นมันเป็นเพียงเรื่องของการทำตรงข้ามที่นั่น บางทีฉันต้องทำทั้งสองอย่าง?
JosiahRyanW

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.