Penyederhanaan Amidakuji (阿 弥陀 籤)


10

Jika Anda pernah memiliki paparan budaya Jepang atau Asia Timur, Anda pasti akan menemukan permainan Amidakuji:

masukkan deskripsi gambar di sini

Seperti yang dijelaskan Wikipedia , ini adalah jenis lotre yang digambar di atas kertas dan digunakan untuk memilih permutasi item N secara acak.

Misalnya, ini dapat digunakan untuk menetapkan urutan awal secara acak untuk N orang, atau N hadiah untuk N orang, dan seterusnya.

Trik untuk memahami mengapa permainan merepresentasikan permutasi adalah dengan menyadari bahwa setiap goresan horizontal (disebut "leg") menukar kedua item di tempatnya.

Halaman Wikipedia yang sama juga menjelaskan bahwa setiap permutasi item P sesuai dengan jumlah diagram Amidakuji yang tak terbatas. Satu (s) dengan paling sedikit stroke horisontal (kaki) disebut "bilangan prima" dari permutasi P. tertentu

Tugas Anda adalah untuk menerima diagram Amidakuji dengan 2 atau lebih garis vertikal (dalam contoh ini 6) dalam format ini (minus huruf):

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

Dan menghasilkan salah satu bilangan prima (sekali lagi, minus huruf):

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

Baris pertama dan terakhir dengan huruf bukan bagian dari format. Saya telah menambahkan mereka di sini untuk menunjukkan permutasi. Juga tidak diharuskan bahwa baris pertama atau terakhir tidak mengandung tungkai |-|, atau bahwa output sekompleks mungkin.

Contoh input khusus ini adalah salah satu representasi ASCII (tak terbatas) dari diagram Amidakuji di bagian atas halaman Wikipedia.

Ada satu aturan yang tidak jelas tentang diagram ASCII ini: kaki yang berdekatan dilarang.

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

Wikipedia menjelaskan prosedur standar untuk mendapatkan yang utama dari diagram, yang disebut "penggelembungan", yang terdiri dari penerapan penyederhanaan berikut berulang-ulang:

1) Garpu kanan ke garpu kiri:

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

2) Menghilangkan ganda:

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

Saya tidak yakin apakah penjelasan itu tidak ambigu. Kode Anda dapat menggunakan teknik itu atau algoritma lainnya yang menghasilkan bilangan prima yang diperlukan.

Kode terpendek menang.

Aturan standar dan tunjangan standar berlaku. (Jika input tidak valid, program Anda mungkin terbakar. Format input / output mungkin stdin / stdout, argumen string, daftar garis, matriks karakter, apa pun yang paling cocok untuk Anda, dll.)

masukkan deskripsi gambar di sini


3
Ini adalah tantangan yang sangat menarik. Saya mungkin perlu waktu beberapa saat untuk menghasilkan solusi tanpa kulit, heh.
JosiahRyanW

Apakah output harus sekompak mungkin atau apakah ada jumlah ruang vertikal diizinkan selama jumlah kaki minimal?
Laikoni

@Laikoni ruang vertikal dalam jumlah berapa pun diperbolehkan.
Tobia

Apakah bubblisasi dan bubblisasi terbalik mencapai setiap hasil yang sama Amidakuji?
14m2

@ l4m2 apa itu pembalikan terbalik?
Tobia

Jawaban:


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

Cobalah online!

Sebuah fungsi yang mengambil string dalam bentuk yang ditentukan, dan mencetak Amidakuji yang berkurang dalam bentuk itu juga.

Ide dasar di sini adalah untuk pertama-tama mengubah input menjadi permutasi (dalam for x in Xloop); dan kemudian dalam whileloop, melakukan semacam gelembung permutasi itu, karena seperti yang ditulis dalam artikel wikipedia, ini menghasilkan Amidakuji 'prima'.


Wow. Saya baru saja menghabiskan waktu yang lama membuat versi Python 3, tapi ini 526 byte, heh.
JosiahRyanW

Saya baru saja memberi ratusan diagram acak ke kode Anda dan saya dapat mengonfirmasi bahwa itu menghasilkan bilangan prima yang benar!
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

Cobalah online!

Penjelasan

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

Kerja bagus! Saya memberi makan 1000 diagram acak ke kode Anda dan itu menyelesaikan semuanya.
Tobia

(_:[])bisa adil [_]dan p?q=(p:fst q,snd q)bisa p?(f,s)=(p:f,s). Alih-alih mendefinisikan c 0='-';c _=' ';dan kemudian menggunakan c m, " -"!!(0^abs m)harus bekerja.
Laikoni

(g 0)tidak membutuhkan tanda kurung dan letdi penjaga lebih pendek dari where. Secara keseluruhan 274 byte: Cobalah secara online!
Laikoni

Fungsi fixpoint Anda %dapat digarisbawahi dengan until(\x->g 0 x==x)(g 0).
Laikoni

2

Retina 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

Cobalah online! Penjelasan:

$
¶$%`

Gandakan baris terakhir.

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

Beri nomor kolom pada baris terakhir.

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

Pindahkan angka ke atas sampai mencapai baris pertama. Pada setiap iterasi, hanya angka paling kanan -1=yang dipindahkan. Ini dipindahkan ke paling kanan |kecuali jika didahului oleh -dalam hal ini dipindahkan ke sebelumnya |. (Yang rmenunjukkan bahwa regex diproses seolah-olah itu terlihat di belakang, yang membuatnya sedikit lebih mudah untuk mencocokkan kasus ini.) Ini menghitung permutasi yang diubah oleh Amidakuji ke dalam urutan urutan.

-
 
1G`

Simpan saja daftar angka, hapus angka -s dan apa pun setelah baris pertama.

;{`

Sisa dari program ini kemudian diulangi mengurutkan daftar kembali ke dalam urutan, tetapi daftar akhir tidak dicetak, namun karena dibutuhkan iterasi untuk Retina 0.8.2 untuk melihat bahwa daftar tersebut dalam urutan, garis tanpa kaki adalah dihasilkan pada akhirnya, yang saya percaya dapat diterima.

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

Tandai semua pasangan yang tersedia dari nomor yang tidak disortir bersebelahan dengan -s untuk kaki.

*`1+
|

Cetak kaki tetapi dengan angka diganti dengan |s.

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

Sebenarnya melakukan swap.


Apakah Anda memiliki saran tentang cara menjalankan kode Anda dengan Retina.exe ? Saya pikir saya memiliki sumber yang benar (105 byte) tetapi tidak menghasilkan apa-apa. Saya mencoba Hello World dari contoh Retina dan berhasil. Bisakah Anda mengunggah sumbernya di suatu tempat, atau Base64 menyandikannya dan meletakkannya di pastebin, kalau-kalau saya salah mengartikannya?
Tobia

@Tobia Maaf, tapi saya tidak ingat cara menggunakan Retina.exe; Saya pikir saya mungkin telah menggunakannya sekali atau dua kali tetapi hari ini saya hanya menggunakan Try It Online.
Neil

LOL saya bodoh! Saya menggunakan beberapa versi mutakhir, bukan 0.8.2. Sekarang saya mendapat harness saya untuk memberi makan ratusan diagram acak ke kode Anda dan saya bisa memastikan bahwa itu selalu menampilkan bilangan prima yang benar. Kerja bagus!
Tobia

@Tobia Terima kasih telah menguji! Tweaks yang diperlukan untuk Retina 1: $**; -1=0; 1_; ;.(kurang-lebih); **\.
Neil

1

Python 3 , 524 488 486 byte

-38 bytes terima kasih kepada 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="|")

Cobalah online!

Ini mengonversi Amidakuji ke array biner 2D, dan langsung menguranginya menggunakan aturan.


Saya ingin tahu tentang pendekatan Anda; Aku akan melihatnya! Sementara itu, Anda dapat menyimpan beberapa byte dengan mengganti " "+i.replace("|","")+" "dengan i.split("|"). baris pertama dari pfungsi Anda ...
Chas Brown

Beberapa tweak golf python standar lagi untuk mencapai 479 byte .
Chas Brown


Yah, tidak yakin mengapa itu terjadi ...
Chas Brown

Tidak selalu ... terkadang garpu kanan ke kiri tidak bisa dilakukan, tetapi garpu kiri ke kanan adalah garpu. Dalam kasus khusus itu, hanya masalah melakukan yang sebaliknya di sana. Mungkin saya perlu melakukan keduanya?
JosiahRyanW

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.