Упрощение Амидакудзи (阿 弥陀 籤)


10

Если вы когда-либо знакомились с культурой Японии или Восточной Азии, вы наверняка столкнулись с игрой Amidakuji:

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

Как объясняет Википедия , это тип лотереи, нарисованный на бумаге и используемый для случайного выбора перестановки из N предметов.

Например, его можно использовать для случайного назначения стартовой последовательности для N человек или для N призов для N человек и так далее.

Хитрость в понимании того, почему игра представляет собой перестановку, состоит в том, чтобы понять, что каждый горизонтальный удар (называемый «ногой») меняет свои два элемента на месте.

На той же странице Википедии также объясняется, что каждая перестановка P из N элементов соответствует бесконечному числу диаграмм Амидакудзи. Один (ие) с наименьшим количеством горизонтальных штрихов (ножек) называются «простыми числами» этой конкретной перестановки 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

Первая и последняя строки с буквами не являются частью формата. Я добавил их сюда, чтобы показать перестановку. Он также не требуется, чтобы первые или последние строки не содержат ни ног |-|, ни о том , что выход будет как можно более компактным.

Этот конкретный пример ввода является одним из (бесконечных) ASCII-представлений диаграммы Амидакудзи в верхней части страницы Википедии.

Есть одно неочевидное правило об этих диаграммах ASCII: смежные ноги запрещены.

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

Википедия объясняет стандартную процедуру получения простого числа из диаграммы, называемую «пузырением», которая состоит в применении следующих упрощений снова и снова:

1) Правая вилка на левую вилку:

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

2) Устранение двойников:

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

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

Самый короткий код выигрывает.

Применяются стандартные правила и стандартные надбавки. (Если ввод недопустим, ваша программа может загореться. Форматы ввода / вывода могут быть stdin / stdout, строковый аргумент, список строк, матрица символов, все, что вам подходит, и т. Д.)

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


3
Это очень интересный вызов. Я мог бы потратить некоторое время на то, чтобы найти решение, не нужное, хех.
JosiahRyanW

Выходной сигнал должен быть как можно более компактным или допускается какое-либо количество вертикального пространства при минимальном количестве ветвей?
Лайкони

@ Laikoni допускается любое количество вертикального пространства.
Tobia

Достигают ли пузыри и обратные пузыри одинакового результата Амидакудзи?
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

Отличная работа! Я добавил в ваш код тысячи случайных диаграмм, и он решил их все.
Тобиа

(_:[])может быть справедливым [_]и 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Указывает, что регулярное выражение обрабатывается так, как если бы оно было задним числом, что немного облегчает сопоставление с этим случаем.) Это вычисляет перестановку, которую 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 закодировать его и поместить в каталог, на случай, если я ошибся в кодировке?
Тобиа

@Tobia Извините, но я не могу вспомнить, как использовать Retina.exe; Я думаю, что я мог бы использовать его один или два раза, но сейчас я просто использую Try It Online.
Нил

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("|")in. первая строка вашей pфункции ...
Час Браун

Еще несколько стандартных настроек игры в python golfing, чтобы получить его до 479 байтов .
Час Браун


Да, не уверен, почему это происходит ...
Час Браун

Не всегда ... иногда с правой стороны на левую вилку невозможно, но с левой стороны на правую вилку. В этом конкретном случае, это просто вопрос противоположного действия. Возможно, мне нужно сделать оба?
JosiahRyanW

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.