Tugas Anda adalah membuat program yang menggunakan bilangan bulat n > 1
, dan mengeluarkan gulungan n
dadu satu sisi. Namun, dadu ini mengikuti aturan untuk meledak dadu .
Saat Anda menggulung dadu, periksa nilai apa yang Anda gulir. Jika Anda mendapatkan jumlah maksimum untuk jenis die (pada d4 standar yang akan menjadi 4, atau 6 pada d6, dll.), Gulung lagi dan tambahkan gulungan baru ke total itu. Setiap gulungan terus menambahkan ke total, sampai Anda tidak menggulung angka maks lagi. Angka terakhir itu masih ditambahkan.
Program Anda harus mengambil satu bilangan bulat n
, dan menggulung n
dadu sisi yang meledak . Berikut adalah contoh distribusi untuk menunjukkan seperti apa tampilannya n=4
. Perhatikan bahwa Anda seharusnya tidak pernah menghasilkan kelipatan n
, karena mereka akan selalu meledak.
Anda dapat mengasumsikan ukuran tumpukan untuk setiap rekursi yang Anda lakukan tidak terbatas, dan fungsi acak Anda harus memenuhi standar kami untuk keacakan (generator acak bawaan atau waktu / tanggal ). Fungsi acak Anda juga harus seseragam mungkin, vs. sesuatu seperti distribusi geometris, karena ini adalah dadu yang sedang kita bicarakan.
Jawaban:
x86 Machine Code (untuk Intel Ivy Bridge dan yang lebih baru), 17 byte
Byte kode di atas mendefinisikan fungsi yang mensimulasikan mati meledak. Dibutuhkan satu input, diteruskan dalam
ESI
register, menunjukkan jumlah maksimum die. Ini mengembalikan nilai tunggal diECX
register, yang merupakan hasil dari gulungan.Secara internal, menggunakan para
RDRAND
instruksi untuk menghasilkan nomor acak. Ini menggunakan generator angka acak (RNG) yang dibangun ke dalam perangkat keras pada prosesor Intel Ivy Bridge dan yang lebih baru (beberapa CPU AMD juga mendukung instruksi ini).Logika fungsi ini sebaliknya cukup mudah. Angka acak yang dihasilkan diskalakan agar berada dalam kisaran yang diinginkan menggunakan teknik standar (
(rand % dieSize) + 1
), dan kemudian diperiksa untuk melihat apakah harus menyebabkan ledakan. Hasil akhir disimpan dalam register akumulator.Berikut adalah versi beranotasi yang menunjukkan mnemonik bahasa assembly:
Saya sedikit curang . Semua konvensi panggilan x86 standar mengembalikan hasil fungsi dalam
EAX
register. Tetapi, dalam kode mesin yang sebenarnya, tidak ada konvensi pemanggilan. Anda dapat menggunakan register yang Anda inginkan untuk input / output. MenggunakanECX
untuk register keluaran menyelamatkan saya 1 byte. Jika Anda ingin menggunakanEAX
, masukkanXCHG eax, ecx
instruksi 1-byte segera sebelumret
instruksi. Ini menukar nilaiEAX
danECX
register, secara efektif menyalin hasil dariECX
keEAX
, dan merusakECX
dengan nilai lama dariEAX
.Cobalah online!
Berikut fungsi setara ditranskripsikan dalam C, menggunakan yang
__builtin_ia32_rdrand32_step
intrinsik didukung oleh GCC, dentang, dan ICC untuk menghasilkanRDRAND
instruksi:Menariknya, GCC dengan
-Os
flag mengubah ini menjadi kode mesin yang hampir persis sama . Dibutuhkan inputEDI
bukannyaESI
, yang sepenuhnya sewenang-wenang dan tidak mengubah substansi tentang kode. Ini harus mengembalikan hasilnyaEAX
, seperti yang saya sebutkan sebelumnya, dan menggunakanMOV
instruksi yang lebih efisien (tetapi lebih besar) untuk melakukan ini segera sebelumRET
. Jika tidak, sama. Itu selalu menyenangkan ketika proses sepenuhnya reversibel: tulis kode dalam rakitan, transkrip ke dalam C, jalankan melalui kompiler C, dan dapatkan kembali rakitan asli Anda!sumber
Python 2 ,
666461 byte-3 byte terima kasih kepada xnor
Cobalah online!
Gulungan sebelumnya disimpan di
c
, memungkinkan kita untuk mengaksesnya berkali-kali tanpa harus menyimpannya ke variabel, yang tidak dapat dilakukan dalam Python lambda. Setiap rekursi, kami memeriksa apakah kami melempar dadu yang meledak.c
diinisialisasi ke nol, begituc%n
pula falsey di sana. Dalam iterasi berikutnya, itu hanya akan menjadi falsey jika dadu meledak digulung.Python 2 , 55 byte
Cobalah online!
Jawaban saya yang lain tampaknya agak terlalu direkayasa, karena ini tampaknya bekerja juga ... Saya tetap akan membiarkannya.
sumber
c*(c<n)
bisac%n
.R , 39 byte
Cobalah online!
Penjelasan: solusi ini menghindari rekursi / loop sementara dengan langsung menghitung distribusi jumlah ledakan yang akan terjadi. Biarkann menjadi jumlah sisi pada dadu. Jika Anda menunjukkan kesuksesan sebagai bergulir sebuah n dan kegagalan sebagai bergulir hal lain, maka Anda memiliki probabilitas 1n sukses. Jumlah total ledakan adalah jumlah keberhasilan sebelum kegagalan pertama. Ini sesuai denganGeometric(1−1n) distribusi (lihathalaman wikipedia, yang mendefinisikan keberhasilan dan kegagalan sebaliknya). Setiap ledakan membawan ke total. Gulungan terakhir mengikutidistribusiUniform(1,2,…,n−1) yang kami tambahkan ke total.
sumber
sample
memenuhi standar untuk keacakan, mengingat biasnya ?sample
mengarah pada kurangnya keseragaman yang memberikan rasio probabilitas maks ke minimum setinggi 1,03 ... Mengejutkan, bukan ?!sample
dengan ? ;-)Perl 6 , 26 byte
Cobalah online!
Penjelasan
sumber
{sum roll(*,1..$_)...$_>*}
J ,
1611 byteCobalah online!
Penjelasan
TL; DR
1+?
melakukan die roll,(+$:)^:=
hanya mengulangi ketika sama dengan input.Fungsi ini adalah kereta dari 4 kata kerja:
Kereta adalah ketika 2 atau lebih kata kerja disatukan. Di sini, jawabannya adalah dalam bentuk
f g h j
:Apa yang disebut "kereta 4" diurai sebagai kait dan garpu:
Dengan demikian, jawabannya setara dengan:
Hooks:
(f g) x
danx (f g) y
Hook monadic (satu argumen) dari dua kata kerja, diberikan argumen
x
, persamaan berikut berlaku:Misalnya,
(* -) 5
mengevaluasi ke5 * (- 5)
, yang mengevaluasi ke_25
.Ini berarti bahwa 4 kereta kami, sebuah kait dari
f
dan(g h j)
, setara dengan:Tetapi apa yang
f
dilakukan di sini?(+$:)^:=
adalah konjungsi dari dua kata kerja menggunakan konjungsi Daya^:
: hook lain ((+$:)
) dan kata kerja (=
). Perhatikan di sini bahwaf
ini adalah diadik — ada dua argumen (x
dan(g h j) x
). Jadi kita harus melihat bagaimana^:
berperilaku. Konjungsi dayaf^:o
mengambil kata kerjaf
dan kata kerja atau kata bendao
(kata benda hanya sepotong data) dan berlakuf
o
kali. Sebagai contoh, ambilo = 3
. Persamaan berikut berlaku:Jika
o
adalah kata kerja, konjungsi daya hanya akan mengevaluasio
argumen dan menggunakan hasil kata benda sebagai hitungan ulang.Untuk kata kerja kami,
o
adalah=
, kata kerja kesetaraan. Ini mengevaluasi0
untuk argumen yang berbeda dan1
untuk argumen yang sama. Kami mengulangi hook(+$:)
sekali untuk argumen yang sama dan tidak ada waktu untuk yang berbeda. Untuk kemudahan notasi penjelasannya, mariy ⇔ ((g h j) x)
. Ingat bahwa kait awal kami setara dengan ini:Memperluas konjungsi, ini menjadi:
Jika
x
dany
sama, ini menjadi:Kalau tidak, ini menjadi:
Sekarang, kita telah melihat garpu monadik. Di sini, kami memiliki garpu diad:
Jadi, kapan
x
dany
sama, kita mendapatkan:Apa
$:
? Ini merujuk ke seluruh kata kerja itu sendiri dan memungkinkan untuk rekursi. Ini berarti bahwa, ketikax
dan yare the same, we apply the verb to
yand 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 argumenx
, persamaan kesetaraan berikut:Sebagai contoh berikut ini, misalkan kita telah verba bernama
SUM
,DIVIDE
, danLENGTH
, yang melakukan apa yang Anda kira mereka mungkin. Jika kami menggabungkan ketiganya menjadi garpu, kami mendapatkan:Garpu ini mengevaluasi ke rata-rata
x
(dengan asumsix
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:
?
di sini memberikan bilangan bulat acak dalam kisaranMenyatukan semuanya
Dengan semua hal ini, kata kerja kami setara dengan:
Ini mengekspresikan fungsi yang diinginkan.
sumber
(+$:)^:=1+?
Jelly , 7 byte
Cobalah online!
Gunakan rekursi. Jalankan lagi program (
ß
) dan tambahkan (+
) jika (¡
) angka acak (X
) sama dengan (=
) ke input program.}
membuatß
tindakan pada input program dan¥
bergabung+ß}
menjadi satu tautan untuk¡
dikonsumsi.Di sini distribusi 1000 output untuk n = 6 yang saya kumpulkan menggunakan program ini . Diplot dengan python / matplotlib.
Berikut adalah 5000 titik data dari n = 3 pada plot semilog yang menunjukkan distribusi eksponensial (kurang lebih?).
sumber
Pyth -
1211 byteMenggunakan fungsional sementara. Saya merasa harus ada jawaban yang lebih cerdas yang hanya mensimulasikan distribusi.
Cobalah online .
sumber
Python 3 , 80 byte
Cobalah online!
sumber
r.random()
mengembalikan 0.1-r.random()
harus bekerja.import ... as _
terpendek!05AB1E , 10 byte
Cobalah online atau verifikasi daftar .
Alternatif 10 byte:
Cobalah online atau verifikasi daftar .
Meskipun saya suka yang teratas lagi karena mendapat 'kata'
DIÊ
di dalamnya, yang sesuai dengan tantangan.Penjelasan:
sumber
.Γ
atau sesuatu.Bahasa Wolfram (Mathematica) , 50 byte
Cobalah online!
sumber
R ,
4742 byteCobalah online!
Credit to ArBo's approach.
Still a byte longer than Robin Ryder's, go upvote his!
sumber
if
for 46 bytes, but ended up getting a 52 on one roll which shouldn't be possible with n=4, so I don't know if there's a weird low recursion limit thing happening, but I think it may be buggy. Try it online!Ruby , 35 byte
Cobalah online!
sumber
x
variabel: Cobalah online!APL (Dyalog Unicode) ,
1514 byteCobalah online!
sumber
Haskell ,
7776 byteCobalah online!
Terima kasih untuk killmous selama satu byte.
Jika
<|>
berada di awal, kita bisa melakukan yang lebih baik denganMonadComprehensions
:Haskell , tidak bersaing, 66 byte
Cobalah online!
sumber
Python 2, 53 bytes
Try it online!
Menggunakan
or
ide hubungan pendek dari jawaban Arbo . Ekspresirandom()*n//1
menghasilkan angka dari0
ken-1
, dengan0
menggantikan gulungann
. Theor
mengambil nomor yang, kecuali jika itu nol (Falsey) terus ken+f(n)
.sumber
Japt , 13 byte
Cobalah
Jawaban Port of Arnauld . Menemukan cara melakukan panggilan rekursif;)
JS yang dialihkan:
sumber
N.g(f)
:) yang sangat bagusU
. Melompati garis sepertinya juga berhasil. Itu trik yang bagus :)Japt , 12 byte
Ini mungkin lebih pendek daripada solusi dana, tetapi jauh lebih buruk dari itu. Saya hanya mempostingnya karena sepertinya selamanya karena kami memiliki solusi Japt yang dimulai dengan baris kosong.
Cobalah
sumber
PowerShell , 49 byte
Cobalah online!
Metode berulang. Atur input
$args
ke$a
dan$l
roll ast (selesai maka kita memasuki loop setidaknya sekali). Kemudian, selama gulungan terakhir-eq
ual ke input, kami terus bergulir. Di dalam loop kami terakumulasi ke$o
dalam gulungan terakhir, yang diperbarui dengan membuat rentang mulai dari1
input$a
dan memilihRandom
elemennya. (Jujur, saya sedikit terkejut itu$o+=$l=
bekerja.) Setelah kita keluar dari loop, kita pergi$o
pada jalur pipa dan output tersirat.sumber
Keempat (gforth) , 72 byte
Cobalah online!
Penjelasan Kode
sumber
Batch, 70 byte
Mengambil input
n
sebagai parameter baris perintah%1
.d
adalah gulungan saat ini,t
total kumulatif. Cukup terus bergulir sampaid
tidak sama dengann
.sumber
Jelly , 9 byte
Cobalah online!
Tautan monadik yang mengambil n sebagai argumennya dan mengembalikan angka yang dihasilkan oleh d-sisi mati yang meledak. Ini menghasilkan 256 angka dari 1 ke n dan mengembalikan jumlah kumulatif pertama yang bukan kelipatan n. Secara teori ini bisa mengembalikan 256n, tetapi bahkan untuk dadu 2 sisi ini hanya akan terjadi satu setiap2256 waktu.
Alternatif yang tidak memiliki batasan ini adalah:
Jelly , 10 byte
Cobalah online!
Perhatikan bahwa kedua tautan TIO menghasilkan 400 angka untuk menunjukkan distribusi.
sumber
Python 3 ,
8172 byteCobalah online!
-9 byte terima kasih kepada ArBo
Penjelasan
sumber
from random import*
sebagai gantinya.TI-BASIC,
2823 byte-5 byte berkat postingan meta ini !
Input di
Ans
.Keluaran dalam
Ans
dan dicetak secara implisit.Contoh:
Penjelasan:
Catatan:
sumber
startTmr
tidak diperlukan lagi, pengiriman ini sekarang akan berfungsi untuk versi TI-BASIC lebih awal dari TI-84 +SmileBASIC 3, 49 byte
Fungsi
D N OUT R
mengimplementasikan gulungan dadu yang meledak secara rekursif.Tidak disatukan
Perhatikan bahwa dalam SmileBASIC, fungsi dapat memiliki beberapa nilai balik. Jika suatu fungsi memiliki satu nilai balik maka
fun in OUT var
danvar = fun(in)
persis sama, itulah sebabnya kita dapat mendefinisikan fungsi dalamOUT
bentuk dan juga memanggilnya dalam ekspresi di tubuh fungsi itu sendiri. Jika saya telah mendefinisikan fungsi karenaDEF D(N)
saya harus secara eksplisit menyatakanRETURN R
dalam tubuh fungsi; mencampur kedua sintaks menyelamatkan saya byte.sumber
PowerShell , 43 byte (metode berulang)
Cobalah online!
PowerShell , 48 byte (metode rekursif)
Cobalah online!
sumber
Jelly , 7 byte
Tautan monadik yang menerima bilangan bulat
n
,, yang menghasilkan bilangan bulat.Cobalah online! Atau lihat hitungan105 berjalan
Bagaimana?
sumber
SmileBASIC, 41 byte
Setelah membaca:
Saya menyadari bahwa alih-alih memeriksa apakah gulungan dadu itu
n
, Anda bisa mengulanginya sementara jumlahnya adalah kelipatann
.sumber
AnyDice , 36 byte
Hampir built-in dalam bahasa:
Agar ini benar, saya harus menyalahgunakan asumsi kedalaman rekursi tak terbatas. AnyDice membatasi kedalaman rekursi dengan kedalaman fungsi maksimum properti global. meledak namun menggunakan itu sendiri; kedalaman ledakan - yang standarnya adalah 2.
Akan menambah 25 byte; dan tidak akan benar-benar cocok dengan persyaratan karena secara teori dimungkinkan dadu meledak lebih dari 99 kali.
Output dari fungsi adalah mati, yaitu. tipe bawaan AnyDice yang merupakan pengupas hasil dan probabilitas untuk hasilnya.
sumber
CJam , 19 byte
Penjelasan:
Atau dalam pseudocode:
Sebagai diagram alur:
Cobalah online!
sumber
Excel VBA, 46 byte
Terima kasih kepada @TaylorScott
Dieksekusi di jendela perintah.
Sebagai fungsi yang ditentukan pengguna.
Excel VBA,
10867 bytesumber
do
..loop while
, dan mengubah fungsi menjadi fungsi jendela langsung. -Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t
- 46 Bytes