J , 16 11 byte
(+$:)^:=1+?
Cobalah online!
Penjelasan
TL; DR 1+?
melakukan die roll, (+$:)^:=
hanya mengulangi ketika sama dengan input.
Fungsi ini adalah kereta dari 4 kata kerja:
┌─ +
┌───┴─ $:
┌─ ^: ─┴─ =
│
──┤ ┌─ 1
└──────┼─ +
└─ ?
Kereta adalah ketika 2 atau lebih kata kerja disatukan. Di sini, jawabannya adalah dalam bentuk f g h j
:
(+$:)^:= 1 + ?
f g h j
Apa yang disebut "kereta 4" diurai sebagai kait dan garpu:
f g h j ⇔ f (g h j)
Dengan demikian, jawabannya setara dengan:
(+$:)^:= (1 + ?)
Hooks: (f g) x
danx (f g) y
Hook monadic (satu argumen) dari dua kata kerja, diberikan argumen x
, persamaan berikut berlaku:
(f g) x ⇔ x f (g x)
Misalnya, (* -) 5
mengevaluasi ke 5 * (- 5)
, yang mengevaluasi ke _25
.
Ini berarti bahwa 4 kereta kami, sebuah kait dari f
dan (g h j)
, setara dengan:
(f (g h j)) x ⇔ x f ((g h j) x)
Tetapi apa yang f
dilakukan di sini? (+$:)^:=
adalah konjungsi dari dua kata kerja menggunakan konjungsi Daya^:
: hook lain ( (+$:)
) dan kata kerja ( =
). Perhatikan di sini bahwa f
ini adalah diadik — ada dua argumen ( x
dan (g h j) x
). Jadi kita harus melihat bagaimana ^:
berperilaku. Konjungsi daya f^:o
mengambil kata kerja f
dan kata kerja atau kata benda o
(kata benda hanya sepotong data) dan berlaku f
o
kali. Sebagai contoh, ambil o = 3
. Persamaan berikut berlaku:
(f^:3) x ⇔ f (f (f x))
x (f^:3) y ⇔ x f (x f (x f y))
Jika o
adalah kata kerja, konjungsi daya hanya akan mengevaluasi o
argumen dan menggunakan hasil kata benda sebagai hitungan ulang.
Untuk kata kerja kami, o
adalah =
, kata kerja kesetaraan. Ini mengevaluasi 0
untuk argumen yang berbeda dan 1
untuk argumen yang sama. Kami mengulangi hook (+$:)
sekali untuk argumen yang sama dan tidak ada waktu untuk yang berbeda. Untuk kemudahan notasi penjelasannya, mari y ⇔ ((g h j) x)
. Ingat bahwa kait awal kami setara dengan ini:
x (+$:)^:= ((g h j) x)
x (+$:)^:= y
Memperluas konjungsi, ini menjadi:
x ((+$:)^:(x = y)) y
Jika x
dan y
sama, ini menjadi:
x (+$:)^:1 y ⇔ x (+$:) y
Kalau tidak, ini menjadi:
x (+$:)^:0 y ⇔ y
Sekarang, kita telah melihat garpu monadik. Di sini, kami memiliki garpu diad:
x (f g) y ⇔ x f (g y)
Jadi, kapan x
dan y
sama, kita mendapatkan:
x (+$:) y ⇔ x + ($: y)
Apa $:
? Ini merujuk ke seluruh kata kerja itu sendiri dan memungkinkan untuk rekursi. Ini berarti bahwa, ketika x
dan y are the same, we apply the verb to
y and add
x` untuk itu.
Garpu: (g h j) x
Sekarang, apa yang dilakukan garpu dalam? Ini adalah y
contoh terakhir kami. Untuk fork monadik dengan tiga kata kerja, diberikan argumen x
, persamaan kesetaraan berikut:
(g h j) x ⇔ (g x) h (j x)
Sebagai contoh berikut ini, misalkan kita telah verba bernama SUM
, DIVIDE
, dan LENGTH
, yang melakukan apa yang Anda kira mereka mungkin. Jika kami menggabungkan ketiganya menjadi garpu, kami mendapatkan:
(SUM DIVIDE LENGTH) x ⇔ (SUM x) DIVIDE (LENGTH x)
Garpu ini mengevaluasi ke rata-rata x
(dengan asumsi x
adalah daftar angka). Di J, kami akan menulis ini sebagai contoh +/ % #
.
Satu hal lagi tentang garpu. Ketika "tine" paling kiri (dalam kasus simbolis kami di atas, g
) adalah kata benda, itu diperlakukan sebagai fungsi konstan mengembalikan nilai itu.
Dengan semua ini, kita sekarang dapat memahami garpu di atas:
(1 + ?) x ⇔ (1 x) + (? x)
⇔ 1 + (? x)
?
di sini memberikan bilangan bulat acak dalam kisaran [ 0 , x ), jadi kita perlu mengubah rentang untuk mewakili dadu; incrementing menghasilkan rentang[ 1 , x ].
Menyatukan semuanya
Dengan semua hal ini, kata kerja kami setara dengan:
((+$:)^:=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
Ini mengekspresikan fungsi yang diinginkan.