Амідакуджі (阿 弥陀 籤) спрощення


10

Якщо ви коли-небудь стикалися з японською або східноазіатською культурою, ви напевно зіткнулися з грою Amidakuji:

введіть тут опис зображення

Як пояснює Вікіпедія , це тип лотереї, намальований на папері і використовується для випадкового вибору перестановки з N елементів.

Наприклад, він може бути використаний для випадкового присвоєння початкової послідовності N людям, або N призів N людям тощо.

Хитрість розуміння того, чому гра являє перестановку, полягає в тому, щоб усвідомити, що кожен горизонтальний хід (який називається "нога") поміняє свої два елементи на місце.

Ця ж сторінка Вікіпедії також пояснює, що кожна перестановка P з N елементів відповідає нескінченній кількості діаграм Амідакуджі. Один (и) з найменшою кількістю горизонтальних штрихів (ніг) називають "праймерами" саме цієї перестановки 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 діаграми Амідакуджі вгорі сторінки Вікіпедії.

Є одне неочевидне правило щодо цих діаграм ASCII: сусідні ноги заборонені.

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

Вікіпедія пояснює стандартну процедуру отримання простих частот із діаграми, що називається "бульбалізацією", яка складається із застосування наступних спрощень знову і знову:

1) Права вилка вліво:

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

2) Елімінація парних пар:

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

Я не впевнений, чи це пояснення однозначне. Ваш код може використовувати цю техніку або будь-який інший алгоритм, який створює необхідні праймери.

Найкоротший код виграє.

Діють стандартні правила та стандартні надбавки. (Якщо введення недійсне, програма може загорітися. Формати вводу / виводу можуть бути stdin / stdout, аргумент рядків, список рядків, матриця символів, що найкраще працює для вас тощо).

введіть тут опис зображення


3
Це дуже цікавий виклик. Я можу зайняти деякий час, виробляючи незворушене рішення, хе.
JosiahRyanW

Чи потрібно на виході бути максимально компактним або дозволено будь-який обсяг вертикального простору до тих пір, поки кількість ніжок буде мінімальною?
Лайконі

@Laikoni дозволено будь-яку кількість вертикального простору.
Тобія

Чи досягають бабблізація та зворотна бульбалізація кожного результату Амідакуджі?
l4m2

@ l4m2 що таке зворотна бульбалізація?
Тобіа

Відповіді:


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циклі виконайте подібну перестановку міхура, оскільки, як зазначає стаття у Вікіпедії, це призводить до «простого» Амідакуджі.


Ого. Я просто витратив тривалий час на створення 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

Хороша робота! Я подав у ваш код 1000 тисяч випадкових діаграм, і це все вирішило.
Тобія

(_:[])може бути справедливим [_]і p?q=(p:fst q,snd q)може бути p?(f,s)=(p:f,s). Замість того, щоб визначати, c 0='-';c _=' ';а потім використовувати c m, " -"!!(0^abs m)слід працювати.
Лайконі

(g 0)не потрібні дужки, а letу гвардії коротше, ніж where. Всього 274 байти: Спробуйте в Інтернеті!
Лайконі

Ваша функція фіксації %може бути позначена символом until(\x->g 0 x==x)(g 0).
Лайконі

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=переміщується лише найправіше число . Він переміщується в крайній правий край, |якщо йому не передує a, -в цьому випадку він переміщується до попереднього |. ( rВказує на те, що регулярний вираз обробляється так, ніби він виглядає позаду, що полегшує порівняння з цим випадком.) Це обчислює перестановку, яку Амідакуджі перетворює в відсортований порядок.

-
 
1G`

Зберігайте лише список номерів, видаляючи -s та що-небудь після першого рядка.

;{`

Потім решта програми повторюється сортування списку в порядку, але остаточний список не друкується, проте, оскільки для Retina 0.8.2 потрібна ітерація, щоб помітити, що список в порядку, рядок без ніг є створена в кінці, що я вважаю прийнятним.

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

Позначте всі наявні пари сусідніх несортованих чисел за допомогою - s для ніг.

*`1+
|

Надрукуйте ніжки, але з цифрами, заміненими на | s.

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

Фактично виконуйте свопи.


Чи є якісь поради щодо запуску коду за допомогою Retina.exe ? Я думаю, що у мене є правильне джерело (105 байт), але воно нічого не дає. Я спробував Hello World із прикладів сітківки, і це працює. Чи можете ви завантажити джерело кудись, або Base64 кодувати його і помістити в пастину, якщо я отримав кодування неправильно?
Тобія

@Tobia Вибачте, але я не можу згадати, як користуватися Retina.exe; Я думаю, що я міг би використати його один або два рази, але в наші дні я просто використовую "Спробуйте в Інтернеті".
Ніл

LOL Я німий! Я використовував деяку передову версію замість 0.8.2. Тепер я отримав запряжку, щоб подати сотні випадкових діаграм до вашого коду, і я можу підтвердити, що він завжди видає правильні праймери. Хороша робота!
Тобія

@Tobia Дякую за тестування! Налаштування, необхідні для Retina 1: $**; -1=0; 1_; ;.(приблизно); **\.
Ніл

1

Python 3 , 524 488 486 байт

-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 у двовимірний двійковий масив і безпосередньо зменшує його за допомогою правил.


Мені цікаво ваш підхід; Я погляну! У той же час, ви можете заощадити кілька байт, замінюючи " "+i.replace("|","")+" "з i.split("|")в. перший рядок вашої pфункції ...
Час Браун

Ще кілька стандартних налаштувань для гольфу на пітоні, щоб отримати його до 479 байт .
Час Браун


Так, не впевнений, чому це відбувається ...
Час Браун

Не завжди ... інколи праворуч до ліво-вилки не піддається виконанню, але ліво-форк-право-форк є. У цьому конкретному випадку, справа лише в тому, щоб робити навпаки. Можливо, мені потрібно зробити і те, і інше?
JosiahRyanW

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.