Roll Dungeons and Dragons dice
Perl, 109 95 93 96 89 bytes
s/^d/1d/;/^(\d+)d(\d+)(\+\d+)?$/;$d+=1+rand$2|0for
1..$1;$_=$1*$2?$d+$3:'Invalid input'
Requires the -p
switch, which accounts for two of the bytes. Try it online on Ideone.
How it works
Because of the
-p
switch, a line is read from STDIN and stored in$_
.The command
s/^d/1d/
prepends a 1 to$_
if it begins with a d, i. e., if the number of dice has not been specified.The regular expression
/^(\d+)d(\d+)(\+\d+)?/
checks if the line consists of a number, a literal d, another number and, optionally, a third number preceded by a + sign.If there is a match, the numbers will be saved in
$1
,$2
and$3
.In this case, the input will be valid if and only if
$1
and$2
are both positive.$d += 1 + rand $2 | 0
adds a pseudo-randomly chosen integer from 1 to the specified number of sides to$d
(initially treated as zero).for 1 .. $1
does the above once for every integer between 1 and the number of dice.The command
$_ = $1 * $2 ? $d + $3 : 'Invalid input'
does the following:If
$1 * $2
is zero, it sets$_
to Invalid input.Otherwise, the input is valid and it sets
$_
to the sum of the dice rolls and the modifier.
Because of the
-p
switch, Perl prints the contents of$_
.Since there a no further input lines, the script exits.
Ruby, 116
Alternative Ruby version. I was trying to find a way to do it without the regular expressions, but the validation you have to do is a lot harder without them.
gets=~/^(\d+)?d(\d+)(\+\d+)?$/
a=$1||?1
puts$~&&a>?0?eval("r=#{$3||0};#{a}.times{r+=rand(#$2)+1};r"):'Invalid input'
This one is 112, using Dennis' clever Perl algorithm:
$p='(\d*[1-9]\d*)'
puts~/^#$p?d#$p(\+\d+)?$/?eval("r=#{$3||0};#{$1||1}.times{r+=rand(#$2)+1};r"):'Invalid input'
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;
Abuses implicit typing (i-n
are all integers, everything else a real). Minor caveat: input must be space separated, so 2d10+5
must be entered as 2 d 10 + 5
, otherwise you'll get an input conversion error
.