J , 16 11 байт
(+$:)^:=1+?
Попробуйте онлайн!
объяснение
TL; DR 1+?
выполняет бросок кубика, (+$:)^:=
повторяется только тогда, когда он равен входу.
Функция представляет собой череду из 4 глаголов:
┌─ +
┌───┴─ $:
┌─ ^: ─┴─ =
│
──┤ ┌─ 1
└──────┼─ +
└─ ?
Поезд - это когда два или более глаголов соединяются. Здесь ответ имеет вид f g h j
:
(+$:)^:= 1 + ?
f g h j
Так называемый «4-поезд» разбирается как крюк и вилка:
f g h j ⇔ f (g h j)
Таким образом, ответ эквивалентен:
(+$:)^:= (1 + ?)
Крючки: (f g) x
иx (f g) y
Монадический (с одним аргументом) хук из двух глаголов, если задан аргумент x
, имеет место следующая эквивалентность:
(f g) x ⇔ x f (g x)
Например, (* -) 5
оценивает до 5 * (- 5)
, что оценивает до _25
.
Это означает, что наш 4-поезд, крюк f
и (g h j)
, эквивалентен:
(f (g h j)) x ⇔ x f ((g h j) x)
Но что f
здесь делать? (+$:)^:=
это соединение двух глаголов с использованием питания конъюнкции ^:
: другой крюк ( (+$:)
) и глагол ( =
). Обратите внимание, что f
это двоично - у него есть два аргумента ( x
и (g h j) x
). Поэтому мы должны посмотреть, как ^:
ведет себя. Силовое соединение f^:o
принимает глагол f
и глагол или существительное o
(существительное - просто часть данных) и применяет f
o
времена. Например, взять o = 3
. Имеются следующие эквивалентности:
(f^:3) x ⇔ f (f (f x))
x (f^:3) y ⇔ x f (x f (x f y))
Если o
это глагол, степенное соединение просто оценивает o
аргументы и использует результат существительного в качестве числа повторений.
Для нашего глагола, o
это =
глагол равенства. Он оценивает 0
для различных аргументов и 1
для равных аргументов. Мы повторяем хук (+$:)
один раз для одинаковых аргументов, а не раз для разных. Для удобства обозначения для объяснения, позвольте y ⇔ ((g h j) x)
. Помните, что наш начальный хук эквивалентен этому:
x (+$:)^:= ((g h j) x)
x (+$:)^:= y
Расширяя соединение, это становится:
x ((+$:)^:(x = y)) y
Если x
и y
совпадают, это становится:
x (+$:)^:1 y ⇔ x (+$:) y
В противном случае это становится:
x (+$:)^:0 y ⇔ y
Теперь мы видели монадические вилки. Здесь у нас есть диадическая вилка:
x (f g) y ⇔ x f (g y)
Итак, когда x
и y
совпадают, мы получаем:
x (+$:) y ⇔ x + ($: y)
Что такое $:
? Это относится ко всему самому глаголу и допускает рекурсию. Это означает, что, когда x
и y are the same, we apply the verb to
y and add
x` к нему.
вилы: (g h j) x
Теперь, что делает внутренняя вилка? Это было y
в нашем последнем примере. Для монадической вилки из трех глаголов с заданным аргументом имеет x
место следующая эквивалентность:
(g h j) x ⇔ (g x) h (j x)
Для следующего примера предположим, что мы глаголы с именем SUM
, DIVIDE
и LENGTH
, что делать то , что вы думаете , что они могли бы. Если мы объединяем три в форк, мы получаем:
(SUM DIVIDE LENGTH) x ⇔ (SUM x) DIVIDE (LENGTH x)
Эта разветвленность оценивается как среднее x
(предположим, x
что это список чисел). В J мы бы написали это как пример как +/ % #
.
Еще одна вещь о вилках. Когда крайний левый «зубец» (в нашем символическом случае выше g
) является существительным, он обрабатывается как постоянная функция, возвращающая это значение.
Имея все это на своем месте, теперь мы можем понять вышеупомянутый форк:
(1 + ?) x ⇔ (1 x) + (? x)
⇔ 1 + (? x)
?
[ 0 , х )[ 1 , х ]
Собираем все вместе
Учитывая все эти вещи, наш глагол эквивалентен:
((+$:)^:=1+?) x ⇔ ((+$:)^:= 1 + ?) x
⇔ ((+$:)^:= (1 + ?)) x
⇔ x ((+$:)^:=) (1 + ?) x
⇔ x ((+$:)^:=) (1 + (? x))
⇔ x (+$:)^:(x = (1 + (? x))
(let y = 1 + (? x))
if x = y ⇒ x + $: y
otherwise ⇒ y
Это выражает желаемую функциональность.