J , 16 11 bajtów
(+$:)^:=1+?
Wypróbuj online!
Wyjaśnienie
TL; DR 1+?
wykonuje rzut matrycą, (+$:)^:=
powtarza tylko wtedy, gdy równa się wejściowi.
Funkcja to ciąg 4 czasowników:
┌─ +
┌───┴─ $:
┌─ ^: ─┴─ =
│
──┤ ┌─ 1
└──────┼─ +
└─ ?
Pociąg ma miejsce, gdy 2 lub więcej czasowników jest połączonych. Tutaj odpowiedź ma postać f g h j
:
(+$:)^:= 1 + ?
f g h j
Tak zwany „4-pociąg” jest analizowany jako hak i widelec:
f g h j ⇔ f (g h j)
Zatem odpowiedź jest równoważna z:
(+$:)^:= (1 + ?)
Haki: (f g) x
ix (f g) y
Monadyczny (jeden argument) hak dwóch czasowników, biorąc pod uwagę argument x
, obowiązuje następująca równoważność:
(f g) x ⇔ x f (g x)
Na przykład (* -) 5
ocenia do 5 * (- 5)
, który ocenia _25
.
Oznacza to, że nasz 4-pociągowy hak f
i (g h j)
jest równoważny z:
(f (g h j)) x ⇔ x f ((g h j) x)
Ale co f
tu robi? (+$:)^:=
jest koniunkcją dwóch czasowników używających koniunkcji Mocy^:
: innym hookiem ( (+$:)
) i czasownikiem ( =
). Zauważ tutaj, że f
jest drastyczny - ma dwa argumenty ( x
i (g h j) x
). Musimy więc sprawdzić, jak się ^:
zachowuje. Koniunkcja potęgi f^:o
przyjmuje czasownik f
i czasownik lub rzeczownik o
(rzeczownik jest tylko fragmentem danych) i stosuje f
o
czasy. Na przykład weź o = 3
. Obowiązują następujące równoważności:
(f^:3) x ⇔ f (f (f x))
x (f^:3) y ⇔ x f (x f (x f y))
Jeśli o
jest czasownikiem, koniunkcja potęgi po prostu oceni o
argumenty i użyje wyniku rzeczownika jako liczby powtórzeń.
Dla naszego czasownika o
jest =
to czasownik równości. Ocenia się 0
dla różnych argumentów i 1
dla równych argumentów. Powtarzamy hak (+$:)
raz dla równych argumentów, a nie dla różnych. Dla ułatwienia notacji wyjaśnienia, pozwól y ⇔ ((g h j) x)
. Pamiętaj, że nasz początkowy hak jest równoważny z tym:
x (+$:)^:= ((g h j) x)
x (+$:)^:= y
Po rozwinięciu koniunkcji staje się to:
x ((+$:)^:(x = y)) y
Jeśli x
i y
są takie same, staje się to:
x (+$:)^:1 y ⇔ x (+$:) y
W przeciwnym razie staje się to:
x (+$:)^:0 y ⇔ y
Teraz widzieliśmy monadyczne widelce. Tutaj mamy dyadyczny widelec:
x (f g) y ⇔ x f (g y)
Tak więc, kiedy x
i y
są takie same, otrzymujemy:
x (+$:) y ⇔ x + ($: y)
Co to jest $:
? Odnosi się do całego czasownika i pozwala na rekursję. Oznacza to, że kiedy x
i y are the same, we apply the verb to
yand add
x` do tego.
Widły: (g h j) x
Co robi wewnętrzny widelec? To był y
nasz ostatni przykład. W przypadku monadycznego rozwidlenia trzech czasowników, z podaniem argumentu x
, obowiązuje następująca równoważność:
(g h j) x ⇔ (g x) h (j x)
W następnym przykładzie załóżmy, że mamy czasowniki o nazwach SUM
i DIVIDE
, i LENGTH
które, jak przypuszczasz, mogą mieć. Jeśli połączymy trójkę w rozwidlenie, otrzymamy:
(SUM DIVIDE LENGTH) x ⇔ (SUM x) DIVIDE (LENGTH x)
Ten widelec ocenia się na średnią x
(zakładając, że x
jest to lista liczb). W J napisalibyśmy to jako przykład jako+/ % #
.
Ostatnia rzecz dotycząca widelców. Gdy skrajnie lewy „ząb” (w naszym symbolicznym przypadku powyżej,g
) jest rzeczownikiem, jest traktowany jako stała funkcja zwracająca tę wartość.
Po tym wszystkim możemy teraz zrozumieć powyższy widelec:
(1 + ?) x ⇔ (1 x) + (? x)
⇔ 1 + (? x)
?
[ 0 , x )[ 1 , x ].
Kładąc wszystko razem
Biorąc pod uwagę wszystkie te rzeczy, nasz czasownik jest równoważny z:
((+$:)^:=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
To wyraża pożądaną funkcjonalność.