ロールダンジョンとドラゴンのサイコロ


20

ダンジョンとドラゴンをプレイしたいのですが、サイコロがありません!あなたの挑戦は、いくつかのD&Dサイコロを振ることです。

Backus-Naur形式の入力形式の仕様は次のとおりです。

<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>

の前のオプションの整数dは、振るサイコロの数です。少なくともである必要があり、指定さ11ていない場合のデフォルトになります。

直後に必要な整数dは、各ダイが持つ辺の数です。少なくともでなければなりません1。各ダイの側面は、から始まる明確な連続した正の整数1です。

オプションの修飾子はである場合があり+0+0指定されていない場合はデフォルトになります。

たとえば、入力では2d10+5、1〜10の2つの乱数を生成し、それらを加算して5を加算します。次に、結果を出力します。

次のような無効な入力を、受信した場合は2dd20+0d42d5+1+22+2それはこの形式に適合しない、または何か他には、「出力しなければなりませんInvalid input」。それ以外の場合は、入力に従って重み付けされた単一のランダム整数のみを出力する必要があります。例えば、3d6より多く生産する必要がある10よりもS 4

テストケース

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

これはなので、バイト単位の最短コードが勝ちます!


1
ある02d05+073有効な入力?
MT0 14

2
この質問に関する難しい部分は入力を検証することですが、検証ルールを説明する段落は矛盾しています。オプションとして説明npますが、それらd20+を無効として含めないことを選択する入力()。
ピーターテイラー14

1
@PeterTaylor:+修飾子pが提供されている場合にのみ記号を追加すべきだと思います。
ProgramFOX 14

4
@Doorknob、まあ、d13とd17はD&Dで使用されるダイスではないからです。D&Dはd4、d6、d8、d10、d12、およびd20を使用します。また、ロールにさまざまな種類のサイコロが含まれる場合(例:1d4+1d6短剣でローグがこっそり攻撃する場合)またはネガティブになる場合p(例:1d20-1ランク/トレーニングなしのスキルチェックおよびネガティブアビリティモディファイア)が含まれる場合があります。
ブライアンS 14

2
のユースケースなしでdndをプレイし2d8 + 1d6 + 4ますか?あなたは悪い時間を持っているつもりだ
corsiKa

回答:


12

Perl、109 95 93 96 89バイト

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

-p2バイトを占めるスイッチが必要です。Ideoneでオンラインでお試しください。

使い方

  • -pスイッチのため、行はSTDINから読み取られ、に保存され$_ます。

  • dで始まる場合、つまり、サイコロの数が指定されていない場合、コマンドs/^d/1d/1を先頭に追加します。$_

  • 正規表現/^(\d+)d(\d+)(\+\d+)?/は、行が数字、リテラルd、別の数字、およびオプションで+記号が前に付いた3番目の数字で構成されているかどうかをチェックします。

    一致する場合、番号は$1$2およびに保存され$3ます。

    この場合、入力は、場合にのみ有効になります$1し、$2両方とも正です。

  • $d += 1 + rand $2 | 0擬似ランダムに選択された整数を1から指定された数の辺に追加します$d(最初はゼロとして扱われます)。

  • for 1 .. $1 1からサイコロの数までの整数ごとに上記を1回行います。

  • このコマンド$_ = $1 * $2 ? $d + $3 : 'Invalid input'は次のことを行います。

    • 場合は$1 * $2ゼロである、それがセット$_無効な入力

    • それ以外の場合、入力は有効であり$_、サイコロの出目と修正の合計に設定されます。

  • -pスイッチのため、Perlはの内容を出力します$_

  • これ以上入力行がないため、スクリプトは終了します。


1
一般に、追加のコマンドラインパラメーターはそれぞれ1バイトの価値があると見なされますが、ハイフンは無料です。この場合、-pコストは1つだけで、108バイトのソリューションになります。
地下

2
96文字にすることができます/^([1-9]\d*)?d([1-9]\d*)(\+\d+)?$/||die"Invalid input$/";$a+=1+int rand$2for(1..$1||1);$_=$a+$3
Hasturkun 14

1
@undergroundmonorail:単一のコマンドラインスイッチを1、2、さらには3(空白をカウント)バイトとしてカウントする人を見てきました。私はむしろそれを1と数えたいが、2バイトは私にとって公平に思えます。
デニス14

1
@Vynce私はあなたもそうではないと思います。擬似ランダムに選択されたfloatを返すため、|0intにキャストするために使用しrandます。
デニス

1
@Vynce質問にパーマリンクを追加しました(ideone.com/gLJfhO)。-eここでは、単一引用符を二重引用符に置き換えない限り、問題があります。
デニス

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;

暗黙的な型指定を乱用します(i-nすべて整数で、その他はすべて実数です)。軽微な注意:入力はスペースで区切る必要があるため、2d10+5として入力する必要があります。2 d 10 + 5そうでない場合はが表示されますinput conversion error


4

ルビー、116

代替Rubyバージョン。私は正規表現なしでそれを行う方法を見つけようとしましたが、あなたがしなければならない検証は、それらなしでははるかに困難です。

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

これは112で、デニスの巧妙なPerlアルゴリズムを使用しています。

$p='(\d*[1-9]\d*)'
puts~/^#$p?d#$p(\+\d+)?$/?eval("r=#{$3||0};#{$1||1}.times{r+=rand(#$2)+1};r"):'Invalid input'

@ m.buettnerありがとう!なぜ> 0でなければならないと思ったのかはわかりません。
ポール・プレスティッジ14

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)}

これ以上ゴルフはできません。仕事に戻る時が来ました。


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)137バイトのみです。
デニス

2
質問に対するコメントによると、これは入力を拒否するため、誤った回答02d05+073です。
ピーターテイラー14

3

GolfScript(120 106バイト)

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

これは最初のバージョンよりも短いだけでなく、よりエレガントです。実際にダイスローリングを行う部分は

\{rand)+}+@*

残りは主に入力の検証と、解析のためのいくつかの文字です。

# 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

テストフレームワークを使用したオンラインデモ


なぜあなたは使用しないのだろうかn./?たぶん10,n*1文字も少ないです。
ハワード14

@Howard、最初に、いくつかのテストケースに合格するのは土壇場のハックであり、ゴルフをすることは考えなかったからです。第二に、それはいくつかの無効な入力を受け入れるようになります。
ピーターテイラー14

2

J-130(45?)文字

この課題は、特に無効な入力を区別する必要があるため、正規表現に少し偏っているようです。JにはPOSIX正規表現ライブラリがあるため、それほど悪くはありませんが、Perlのように統合されていないため、Jは他の言語と比べてあまり良くありません。

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

Python / PHPソリューションのように、有効な式のロジックを実装しているだけであれば、より妥当な45文字になります。

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

注目すべきビット:

  • 1!:1]1は入力であり(rxmatch rxfrom])、部分式の一致を返すロジックです。

  • 入力が正当であったかどうかは、正規表現のマッチングによって処理されるため、nおよびpのデフォルトをで設定でき0 1 1>.ます。|.リストを前に反転()しなければならず、最後のロジックが正しい順序で実行されるため、後方に見えます(デフォルトではnは1、pは0)。

  • @.あるアジェンダ基本的に連携し、J-っぽいswitch文。マッチが空の場合(0が$ hape:のe.lementである場合0 e.$)、エラーメッセージを出力します。それ以外の場合は、サイコロを転がします:サイコロ#~を設定し、1+?転がし、+/@,修飾子pを追加しますそして合計。


それはうまくいきます01d01+01か?
シーズティマーマン14

@CeesTimmerman私の悪い。今はそうです。
algorithmshark 14

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)

最初の4行は、「d」が、存在しない場合は組み込みの失敗メッセージを伴うユニバーサル「down」出口のエイリアスであるという事実を扱っています。出口は、ユーザー定義コマンドの前にスキャンされます。残りの行は、組み込みのdie()関数を使用して、ユーザー定義のコマンドでオブジェクトを作成します。


2

PHP、129

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

正規表現を使用して、PHPが評価する式を作成します。入力はurl:?0 = argumentを介して入力されます。必ず+を%2bにurlencodeしてください。より読みやすい形式では、次のようになります。

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";');

を使用して文字列をビット単位で反転すると、~引用符が不要なため(PHPは文字列であると見なされるため)文字が保存されるだけでなく、正規表現でバックスラッシュをエスケープする必要がないため文字も保存されます。

?:オペレータは、三項演算子の特殊な形式です。$foo = $a ? $a : $bはと同じ$foo = $a ?: $bです。


1

Java、378

最良のソリューションとはほど遠いJavaでのソリューションを試してみたかっただけです。しかし、ちょっと:Javaは、いずれにしてもゴルフ言語ではありません!

コマンドラインから入力を取得します。最初のパラメーターargs[0]は入力値です。

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;}}

あなたは知っていました、それdecodeはより短いですvalueOfか?


1

Python 3、184バイト

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)

すべてのテストに合格します。ゼロのサイコロが許可されている場合は、省略することで6バイト短くなります(or q)


しかし、私はBNFを誤解していました。このページは役立ちます。
シーズティマーマン14

なぜ正規表現が一方の端に固定され、もう一方の端には固定されていないのか疑問に思う他の人のために:Pythonのre.match暗黙的なアンカーは開始であるが終了ではない 私はそれを行う他の正規表現ライブラリを知りません。
ピーターテイラー14

1
初期化による小さな節約がありますt=int(c or 0); また、回答を既存のPythonの回答(空白の使用量が少ない)と組み合わせて、さらに節約することもできます。
ピーターテイラー14

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')

これは、と非常に似ているスナックの答え
user12205

よく似ていますが、これは同じ言語/アルゴリズムです...しかし、別の答えを投稿するには、コード(および正規表現)に十分な違いがあると思いました。
マイケルM. 14

質問に対するコメントによると、これは入力を拒否するため、誤った回答02d05+073です。
ピーターテイラー14

0

ルビー、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

正規表現を使用してすべての作業を行います。を使用しているので\d+、無効な入力をチェックする必要があるのは、一致があったこと、どちらnもなかっmたこと0、およびがあったことだけmです。それらのいずれかが見つかった場合、メッセージ('Invalid input')で中止します。次に、入力が無効だった場合は中止されるため、結果を出力するだけです。

結果の印刷はそれほど興味深いものではありませんが、...

([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)

後でに変更.inject(:+)しましたeval(...*?+)が、考え方は同じです。


0

Python3、204B

鉱山は、必要なエラー処理に追加して読み込むことで、既存のPythonの回答を打つd20ように1d20するのではなく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)

2つのタイプミスを修正するために編集:I(x) => I(c)Invalid Input => Invalid input

正規表現を修正するために編集: \+?(\d*) => (\+\d+)?


明確な質問によると、これは入力を受け入れるため、これは間違った答え3d20+です。
ピーターテイラー14

いい視点ね!#filler-
アレクサンダー

そしてそうではありません01d01+01
シーズティマーマン14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.