Gulung Dungeons and Dragons dadu

20

Saya ingin bermain Dungeons and Dragons, tapi saya tidak punya dadu! Tantangan Anda adalah melempar beberapa dadu D & D.

Spesifikasi format input dalam formulir Backus-Naur adalah:

<valid-input>  ::= <opt-integer> "d" <integer> <opt-modifier>
<opt-integer>  ::= | <integer>
<opt-modifier> ::= | "+" <integer>
<integer>      ::= "0" | "1" | "2" | "3" | "4" | "5" |
                   "6" | "7" | "8" | "9" | <integer> <integer>

Bilangan bulat opsional sebelum dadalah jumlah dadu untuk digulung; itu harus setidaknya 1, dan default ke 1jika tidak disediakan.

Bilangan bulat yang diperlukan segera setelah djumlah sisi yang dimiliki masing-masing die; setidaknya harus 1. Sisi setiap dadu adalah bilangan bulat positif berurutan yang berbeda mulai dari 1.

Pengubah opsional mungkin +0, dan standarnya adalah +0jika tidak ditentukan.

Misalnya, untuk input 2d10+5, Anda menghasilkan dua angka acak dari 1 hingga 10 inklusif, tambahkan bersama-sama, dan tambahkan 5. Kemudian Anda akan menampilkan hasilnya.

Jika Anda menerima input tidak valid, seperti 2d, d20+, 0d4, 2d5+1+2, 2+2, atau apa pun yang tidak sesuai format ini, Anda harus output " Invalid input". Jika tidak, Anda harus mengeluarkan hanya satu bilangan bulat acak, yang dibobot menurut input. Misalnya, 3d6harus menghasilkan lebih 10dari 4s .

Uji kasus

Input      Minimum possible output    Maximum possible output
d1         1                          1
d6         1                          6
d1+3       4                          4
d20+3      4                          23
2d1        2                          2
2d6+2      4                          14
d01        1                          1
d01+0      1                          1
01d01+01   2                          2
3d20+10    13                         70

d          Invalid input
d0         Invalid input
d+0        Invalid input
d0+0       Invalid input
0d1        Invalid input
0d1+1      Invalid input
d1+        Invalid input
1d         Invalid input
1d1+       Invalid input
1d+1       Invalid input
2d+2d      Invalid input
d2+d2      Invalid input
d2+2+2     Invalid input
d2-1       Invalid input
-d2        Invalid input
-2d2       Invalid input
4*3        Invalid input
4*d2       Invalid input

Ini adalah , jadi kode terpendek dalam byte akan menang!

Gagang pintu
sumber
1
Apakah 02d05+073input yang valid?
MT0
2
Bagian yang sulit tentang pertanyaan ini adalah memvalidasi input, tetapi paragraf yang menjelaskan aturan validasi bertentangan sendiri. Ini menjelaskan ndan psebagai opsional, tetapi input yang memilih untuk tidak memasukkannya ( d20+) sebagai tidak valid.
Peter Taylor
1
@PeterTaylor: Saya pikir +tanda hanya akan ditambahkan jika pengubah pdisediakan.
ProgramFOX
4
@ Doorknob, Ya, karena d13 dan d17 tidak digunakan dalam D&D. D & D menggunakan d4, d6, d8, d10, d12, dan d20. Juga, tentu saja ada kasus-kasus di mana gulungan akan mencakup berbagai jenis dadu (misalnya, 1d4+1d6untuk penyamun licik menyerang dengan belati) atau memiliki negatif p(misalnya, 1d20-1untuk pemeriksaan keterampilan tanpa peringkat / pelatihan dan pengubah kemampuan negatif).
Brian S
2
Anda akan bermain dnd tanpa menggunakan dari 2d8 + 1d6 + 4? Anda akan memiliki waktu yang buruk
corsiKa

Jawaban:

12

Perl, 109 95 93 96 89 byte

s/^d/1d/;/^(\d+)d(\d+)(\+\d+)?$/;$d+=1+rand$2|0for
1..$1;$_=$1*$2?$d+$3:'Invalid input'

Membutuhkan -psakelar, yang menyumbang dua byte. Cobalah online di Ideone .

Bagaimana itu bekerja

  • Karena -psaklar, sebuah baris dibaca dari STDIN dan disimpan di $_.

  • Perintah s/^d/1d/menambahkan awal 1 ke $_jika dimulai dengan d , yaitu, jika jumlah dadu belum ditentukan.

  • Ekspresi reguler /^(\d+)d(\d+)(\+\d+)?/memeriksa apakah garis terdiri dari angka, d literal , angka lain dan, opsional, angka ketiga didahului dengan tanda + .

    Jika ada kecocokan, angkanya akan disimpan $1, $2dan $3.

    Dalam hal ini, input akan valid jika dan hanya jika $1dan $2keduanya positif.

  • $d += 1 + rand $2 | 0menambahkan bilangan bulat pseudo-acak yang dipilih dari 1 ke jumlah sisi yang ditentukan $d(awalnya diperlakukan sebagai nol).

  • for 1 .. $1 melakukan hal di atas satu kali untuk setiap bilangan bulat antara 1 dan jumlah dadu.

  • Perintah $_ = $1 * $2 ? $d + $3 : 'Invalid input'melakukan hal berikut:

    • Jika $1 * $2nol, ini ditetapkan $_ke input tidak valid .

    • Jika tidak, input tersebut valid dan set $_ke jumlah gulungan dadu dan pengubah.

  • Karena -pberalih, Perl mencetak konten $_.

  • Karena tidak ada lagi baris input, skrip keluar.

Dennis
sumber
1
Saya percaya bahwa, secara umum, parameter baris perintah tambahan dianggap bernilai byte masing-masing tetapi tanda hubung gratis. Dalam hal ini, -phanya akan dikenakan biaya satu, menjadikan ini solusi 108 byte.
undergroundmonorail
2
Dapat dibuat 96 karakter,/^([1-9]\d*)?d([1-9]\d*)(\+\d+)?$/||die"Invalid input$/";$a+=1+int rand$2for(1..$1||1);$_=$a+$3
Hasturkun
1
@undergroundmonorail: Saya telah melihat orang-orang yang menghitung satu saklar baris perintah sebagai satu, dua dan bahkan tiga (menghitung spasi) byte. Saya lebih suka menghitungnya sebagai satu, tetapi dua byte tampaknya adil bagi saya.
Dennis
1
@Vynce Saya menganggap Anda juga belum. Saya menggunakan |0cast ke int, karena randmengembalikan float yang dipilih secara acak semu .
Dennis
1
@Vynce Saya telah menambahkan permalink ke pertanyaan ( ideone.com/gLJfhO ). -eakan bermasalah di sini, kecuali jika Anda mengganti tanda kutip tunggal dengan tanda kutip ganda.
Dennis
4

Fortran: 145

character(1)a;read(*,*)s,a,j,a,k;n=0;if(k<0.or.a=="-")then;print*,"error k<0";stop;endif;do l=1,int(s);n=n+int(s*rand(0)+1);enddo;print*,n+k;end;

Kekerasan mengetik secara implisit ( i-nsemuanya bilangan bulat, yang lainnya nyata). Peringatan kecil: input harus dipisahkan dengan spasi, jadi 2d10+5harus dimasukkan sebagai 2 d 10 + 5, jika tidak, Anda akan mendapatkan input conversion error.

Kyle Kanos
sumber
4

Ruby, 116

Versi Ruby alternatif. Saya mencoba menemukan cara untuk melakukannya tanpa ekspresi reguler, tetapi validasi yang harus Anda lakukan jauh lebih sulit tanpa mereka.

gets=~/^(\d+)?d(\d+)(\+\d+)?$/
a=$1||?1
puts$~&&a>?0?eval("r=#{$3||0};#{a}.times{r+=rand(#$2)+1};r"):'Invalid input'

Yang ini 112, menggunakan algoritma Perl 'Dennis pintar:

$p='(\d*[1-9]\d*)'
puts~/^#$p?d#$p(\+\d+)?$/?eval("r=#{$3||0};#{$1||1}.times{r+=rand(#$2)+1};r"):'Invalid input'
Paul Prestidge
sumber
@ m.buettner Terima kasih! Saya tidak tahu mengapa saya pikir itu harus> 0.
Paul Prestidge
3

Javascipt, 158

m=prompt().match(/^([1-9]\d*)?d([1-9]\d*)(\+\d+)?$/);if(!m)alert("Invalid input");else{for(s=+m[3]|0,i=0;i<(+m[1]||1);i++)s+=Math.random()*+m[2]+1|0;alert(s)}

Tidak bisa bermain golf lebih baik dari ini. Sudah waktunya untuk kembali bekerja.

Camilan
sumber
1
s="Invalid input";if(m=prompt().match(/^([1-9]\d*)?d([1-9]\d*)(\+\d+)?$/))for(s=m[3]|0,i=0;i<(m[1]||1);i++)s+=Math.random()*m[2]+1|0;alert(s)hanya memiliki 137 byte.
Dennis
2
Menurut komentar pada pertanyaan, ini adalah jawaban yang salah karena menolak input 02d05+073.
Peter Taylor
3

GolfScript ( 120 106 byte)

.100?!1`*\+.43?)!'+0'*+.10,'d+':^*-!*.10,''*-^=*^1/{/n*}/~].,3=*3,or:x~;*{x~\{rand)+}+@*}'Invalid input'if

Ini tidak hanya lebih pendek dari versi pertama, tetapi juga lebih elegan. Bagian yang benar-benar melakukan rolling mati adalah

\{rand)+}+@*

Sisanya sebagian besar input validasi, dan beberapa karakter untuk parsing.

# Start by converting valid inputs into valid inputs with all optional bits.
# Prepend a '1' if the string starts with 'd'.
.100?!1`*\+
# Append '+0' if there's no '+' in the string.
.43?)!'+0'*+
# Now we start knocking out the invalid inputs.
# If it contains a character other than [0-9d+], replace the string with ''.
.10,'d+':^*-!*
# If it doesn't contain exactly one 'd', exactly one '+', and the 'd' before the '+',
# replace the string with ''.
.10,''*-^=*
# Now we either have a valid string, an empty string, or a string which is almost valid
# but has some empty substrings which should be integers, or a forbidden 0 integer value.
# Replace the 'd' and '+' with newlines, eval the result, and gather into an array.
^1/{/n*}/~]
# If we had any empty parts, we'll have fewer than 3 items on the stack.
# In that case, replace with integer values which will fail the final validation step.
.,3=*3,or
# Final validation: number of dice * number of sides per die != 0.
:x~;*
# If we pass, do the actual die rolling. Otherwise give the error message.
{x~\{rand)+}+@*}'Invalid input'if

Demo online dengan kerangka uji

Peter Taylor
sumber
Saya bertanya-tanya mengapa Anda tidak menggunakan n./? Mungkin juga 10,n*untuk satu karakter lebih sedikit.
Howard
@ Howard, ke yang pertama, karena ini adalah hack menit terakhir untuk melewati beberapa test case dan saya tidak berpikir tentang golf itu. Untuk yang kedua, itu akan membuatnya menerima beberapa input yang tidak valid.
Peter Taylor
2

J - 130 (45?) Char

Tantangan ini tampaknya sedikit bias terhadap ekspresi reguler, terutama dengan harus membedakan input yang tidak valid. J memiliki perpustakaan regex POSIX, jadi tidak seburuk itu, tetapi tidak terintegrasi seperti halnya dengan Perl, jadi J harganya tidak lebih baik daripada bahasa lain.

+/@,`(1+?@#~)/`('Invalid input'"_)@.(0 e.$)0 1 1>.".>|.}.((,'?d','(\+[0-9]+)?$',~}.)'^([0-9]*[1-9][0-9]*)')(rxmatch rxfrom])1!:1]1

Jika Anda hanya menerapkan logika untuk ekspresi yang valid, seperti yang tampak pada solusi Python / PHP, itu adalah 45 karakter yang lebih masuk akal:

+/,(1+[:?@#/1>.".;._2@,&'d')`".;._1'+',1!:1]1

Bit penting:

  • 1!:1]1adalah input, dan (rxmatch rxfrom])merupakan logika yang mengembalikan kecocokan subekspresi.

  • Apakah input legal atau tidak ditangani oleh pencocokan regex, sehingga kita dapat mengatur default untuk n dan p dengan 0 1 1>.. Itu terlihat mundur (n adalah 1 secara default dan p adalah 0) karena kami harus membalikkan ( |.) daftar sebelumnya, sehingga logika pada akhirnya dijalankan dalam urutan yang benar.

  • @.adalah Agenda konjungsi, pada dasarnya pernyataan switch J-ish. Jika kecocokan kosong (jika 0 adalah e.lement dari $ hape:) 0 e.$, kami memancarkan pesan kesalahan, jika tidak, kami melanjutkan dengan menggulirkan dadu: #~untuk mengatur dadu, 1+?untuk menggulung, dan +/@,menambahkan pengubah p dan jumlah.

algoritme hiu
sumber
Apakah itu berhasil 01d01+01?
Cees Timmerman
@CeesTimmerman Badaku. Itu sekarang.
algorithmshark
2

TinyMUSH , 239

@dig/t +
@op d=+
@lo d=d
@fail d=Invalid input
@cr .
@set .=com
&d .=$*:\ifelse(regmatch(%0,^(\\\\d+)?d(\\\\d+)(\\\\+\\\\d+)?$,0 1 2 3),ifzero(and(or(not(strlen(%q1)),%q1),%q2),Invalid input,add(die(usetrue(%q1,1),%q2),%q3)),Invalid input)

Empat baris pertama berurusan dengan fakta bahwa "d" adalah alias untuk keluar "turun" universal dengan pesan kegagalan bawaan ketika tidak ada; keluar dipindai sebelum perintah yang ditentukan pengguna. Baris yang tersisa membuat objek dengan perintah yang ditentukan pengguna dengan memanfaatkan fungsi die () bawaan.

Muqo
sumber
2

PHP, 129

<?eval(preg_filter(~Сף›ÔÖÀ›×£›Ö×£Ô£›ÔÖÀÛÐ,~ÛžÂÝÛÎÝÀÅÎÄ™×ÄÛ–ÔÔÃÛžÄیԞ‘›×ÎÓÛÍÖÖÄšœ—ÛŒÛÌÄ,$_GET[0])?:~šœ—ݶ‘‰ž“–›ß–‘Š‹ÝÄ);

Menggunakan regex untuk membuat ekspresi yang kemudian dievaluasi oleh PHP. Input dimasukkan melalui url:? 0 = argumen . Pastikan Anda memasukkan kode + ke% 2b. Begini tampilannya dalam bentuk yang lebih mudah dibaca:

eval(preg_filter('/^(\\d)?d(\\d)(\\+\\d)?$/','$a="$1"?:1;for(;$i++<$a;$s+=rand(1,$2));echo$s$3;',$_GET[0])?:'echo"Invalid input";');

Bitwise membalikkan string menggunakan ~tidak hanya menyimpan karakter karena Anda tidak perlu tanda kutip (PHP menganggap itu adalah string) tetapi juga menyimpan karakter karena Anda tidak harus melarikan diri dari garis miring terbalik dalam ekspresi reguler.

The ?:operator adalah bentuk khusus dari operator ternary. $foo = $a ? $a : $bsama dengan $foo = $a ?: $b.

Tryth
sumber
1

Jawa, 378

Hanya ingin mencoba solusi dengan Java jauh dari solusi terbaik. Tapi hei: Jawa bukan bahasa golf!

Ia mendapat input dari baris perintah. Parameter pertama args[0]adalah nilai input.

class A{public static void main(String[]s){System.out.print(s[0].matches(
"(0+\\d+|[1-9]\\d*|)d(0+\\d+|[1-9]\\d*)(\\+\\d+)?")?z(s[0]):"Invalid input");}static int
z(String s){String[]a=s.split("d");String[]b=a[1].split("\\+");int c=a[0].isEmpty()?1:Byte.
decode(a[0]);int d=b.length<2?0:Byte.decode(b[1]);while(c-->0)d+=new java.util.Random().
nextInt(Byte.decode(b[0]))+1;return d;}}

Tahukah Anda, itu decodelebih pendek dari valueOf?

bobbel
sumber
1

Python 3, 184 byte

import random,re
try:a,b,c=re.findall("^(\d*)d(\d+)(\+\d+)?$",input())[0];t=int(c or 0)+(sum(random.randint(1,int(b))for i in range(int(a or 1)))or q)
except:t="Invalid input"
print(t)

Lewati semua tes. Jika nol dadu diizinkan, itu akan menjadi 6 byte lebih pendek dengan meninggalkan (or q).

Cees Timmerman
sumber
Saya salah paham tentang BNF. Halaman ini membantu.
Cees Timmerman
Untuk kepentingan siapa pun yang bertanya-tanya mengapa regex berlabuh di satu ujung tetapi tidak di ujung lainnya: Python re.matchsecara implisit berlabuh di awal tetapi tidak di akhir. Saya tidak mengetahui ada perpustakaan regex lain yang melakukan itu.
Peter Taylor
1
Ada sedikit penghematan dengan menginisialisasi t=int(c or 0); dan mungkin untuk menggabungkan jawaban Anda dengan Python yang ada (yang menggunakan spasi lebih sedikit) untuk menghemat lebih banyak pasangan.
Peter Taylor
0

JavaScript 134

m=prompt().match(/^((?!0)\d*)d((?!0)\d+)(\+\d+)?$/);alert(m?eval('for(o=m[3]|0,i=m[1]||1;i--;)o+=m[2]*Math.random()+1|0'):'Invalid input')
Michael M.
sumber
Ini sangat mirip dengan jawaban Snack
user12205
Yah ada kesamaan, ini bahasa yang sama / algoritma ... Tapi saya pikir ada cukup banyak perbedaan dalam kode saya (dan regex) untuk mengirim jawaban yang berbeda.
Michael M.
Menurut komentar pada pertanyaan, ini adalah jawaban yang salah karena menolak input 02d05+073.
Peter Taylor
0

Ruby, 167 147

/^(\d+)?d(\d+)(\+\d+)?$/.match gets
abort'Invalid input'if !$~||$1==?0||!$2||$2==?0
p eval(([0]*($1||1).to_i).map{rand($2.to_i)+1}*?+)+($3||0).to_i

Menggunakan regexp untuk melakukan semua pekerjaan. Karena saya menggunakan \d+, satu-satunya hal yang saya perlu periksa untuk input yang tidak valid adalah bahwa ada kecocokan, tidak ada natau mtidak 0, dan ada m. Jika ada yang ditemukan, itu dibatalkan dengan pesan ( 'Invalid input'). Maka itu hanya mencetak hasilnya, karena itu akan dibatalkan sekarang jika input tidak valid.

Hasil-mencetak tidak begitu menarik, tapi ...

([0]*($1||1).to_i)    # create an array of n elements (1 if there is no n)
.map{rand($2.to_i)+1} # fill it up with random numbers, where the number x is 1 < x < m+1
.inject(:+)           # add them all up
+($3||0).to_i         # and finally add the modifier (0 if there is none)

Saya kemudian berubah .inject(:+)menjadi eval(...*?+), tetapi idenya sama.

Gagang pintu
sumber
0

Python3, 204B

Tambang mengalahkan jawaban Python yang ada dengan menambahkan dalam penanganan kesalahan yang diperlukan dan membaca d20sebagai 1d20bukan 0d20:)

import random,re
try:a,b,c=re.findall('^([1-9]\d*)?d(\d+)(\+\d+)?$',input())[0];I=int;R=sum(random.randrange(I(b))+1for x in[0]*(1if a==''else I(a)))+(0if c==''else I(c))
except:R='Invalid input'
print(R)

diedit untuk memperbaiki 2 kesalahan ketik: I(x) => I(c),Invalid Input => Invalid input

diedit untuk memperbaiki regex: \+?(\d*) => (\+\d+)?

alexander-brett
sumber
Menurut pertanyaan yang diklarifikasi, ini adalah jawaban yang salah karena menerima input 3d20+.
Peter Taylor
Poin bagus! #filler
alexander-brett
Dan tidak 01d01+01.
Cees Timmerman