Wirf Dungeons und Dragons Würfel

20

Ich möchte Dungeons and Dragons spielen, aber ich habe keine Würfel! Ihre Herausforderung besteht darin, einige D & D-Würfel zu werfen.

Die Eingabeformatspezifikation in Backus-Naur-Form lautet:

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

Die optionale Ganzzahl vor dem dist die Anzahl der Würfel, die gewürfelt werden sollen. Dies muss mindestens der Fall sein 1, und der Standardwert ist, 1wenn er nicht angegeben wird.

Die erforderliche Ganzzahl unmittelbar nach dem dist die Anzahl der Seiten, die jeder Würfel hat; es muss zumindest sein 1. Die Seiten jedes Würfels sind verschiedene aufeinanderfolgende positive ganze Zahlen, beginnend mit 1.

Der optionale Modifikator kann sein +0und ist standardmäßig +0nicht angegeben.

Für die Eingabe 2d10+5generieren Sie beispielsweise zwei Zufallszahlen von 1 bis einschließlich 10, addieren diese und addieren 5. Anschließend geben Sie das Ergebnis aus.

Wenn Sie erhalten ungültige Eingaben, wie zum Beispiel 2d, d20+, 0d4, 2d5+1+2, 2+2, oder irgendetwas anderes , das dieses Format nicht paßt, müssen Sie Ausgang „ Invalid input“. Andernfalls müssen Sie nur eine einzelne zufällige Ganzzahl ausgeben, die entsprechend der Eingabe gewichtet ist. Zum Beispiel 3d6sollte mehr 10s als 4s produzieren .

Testfälle

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

Das ist , also gewinnt der kürzeste Code in Bytes!

Türknauf
quelle
1
Ist 02d05+073eine gültige Eingabe?
MT0
2
Der schwierige Teil dieser Frage ist die Validierung der Eingabe, aber der Absatz, in dem die Validierungsregeln beschrieben werden, ist widersprüchlich. Es beschreibt nund pals optional, aber Eingaben, die sie nicht enthalten möchten ( d20+) als ungültig.
Peter Taylor
1
@ PeterTaylor: Ich denke, das +Zeichen sollte nur hinzugefügt werden, wenn der Modifikator pbereitgestellt wird.
ProgramFOX
4
@Doorknob, gut, weil d13 und d17 keine Würfel sind, die in D & D verwendet werden. D & D verwendet d4, d6, d8, d10, d12 und d20. Es gibt sicherlich auch Fälle, in denen ein Wurf verschiedene Arten von Würfeln enthält (z. B. 1d4+1d6für einen Schurken, der mit einem Dolch angreift) oder negativ ist p(z. B. 1d20-1für eine Fähigkeitsüberprüfung ohne Ränge / Training und einen negativen Fähigkeitsmodifikator).
Brian S
2
Du spielst dnd ohne das usecase von 2d8 + 1d6 + 4? Du wirst eine schlechte Zeit haben
corsiKa

Antworten:

12

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'

Erfordert den -pSchalter, der zwei der Bytes ausmacht. Probieren Sie es online auf Ideone .

Wie es funktioniert

  • Aufgrund des -pSchalters wird eine Zeile aus STDIN gelesen und in gespeichert $_.

  • Der Befehl s/^d/1d/stellt eine 1 voran , $_wenn er mit einem d beginnt , dh wenn die Anzahl der Würfel nicht angegeben wurde.

  • Der reguläre Ausdruck /^(\d+)d(\d+)(\+\d+)?/prüft, ob die Zeile aus einer Zahl, einem Literal d , einer anderen Zahl und optional einer dritten Zahl mit vorangestelltem + besteht .

    Wenn es eine Übereinstimmung gibt, werden die Nummern gespeichert in $1, $2und $3.

    In diesem Fall wird die Eingabe gültig , wenn und nur wenn $1und $2beide positiv.

  • $d += 1 + rand $2 | 0Fügt eine pseudozufällig gewählte Ganzzahl von 1 zu der angegebenen Anzahl von Seiten hinzu $d(anfänglich als Null behandelt).

  • for 1 .. $1 macht das obige einmal für jede ganze Zahl zwischen 1 und der Anzahl der Würfel.

  • Der Befehl $_ = $1 * $2 ? $d + $3 : 'Invalid input'führt Folgendes aus:

    • Wenn $1 * $2Null ist, wird $_die Eingabe auf Ungültig gesetzt .

    • Ansonsten ist die Eingabe gültig und setzt $_sich aus der Summe der Würfelwürfe und dem Modifikator zusammen.

  • Aufgrund des -pSchalters druckt Perl den Inhalt von $_.

  • Da es keine weiteren Eingabezeilen gibt, wird das Skript beendet.

Dennis
quelle
1
Ich glaube, dass im Allgemeinen zusätzliche Befehlszeilenparameter jeweils ein Byte wert sind, der Bindestrich jedoch frei ist. In diesem Fall -pwürde es nur einen kosten, was eine 108-Byte-Lösung ergibt.
U-
2
Kann 96 Zeichen gemacht werden,/^([1-9]\d*)?d([1-9]\d*)(\+\d+)?$/||die"Invalid input$/";$a+=1+int rand$2for(1..$1||1);$_=$a+$3
Hasturkun
1
@undergroundmonorail: Ich habe gesehen, wie Leute einen einzelnen Befehlszeilenschalter als ein, zwei und sogar drei (das Leerzeichen zählend) Bytes gezählt haben. Ich würde es lieber als eins zählen, aber zwei Bytes scheinen mir fair zu sein.
Dennis
1
@ Vynce Ich nehme an, du hast es auch nicht. Ich benutze |0das Casting auf int, da es randeinen pseudozufällig ausgewählten float zurückgibt .
Dennis
1
@Vynce Ich habe der Frage einen Permalink hinzugefügt ( ideone.com/gLJfhO ). -ewäre hier problematisch, sofern Sie nicht die einfachen Anführungszeichen durch doppelte Anführungszeichen ersetzen.
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;

Missbrauch implizite Typisierung ( i-nsind alle ganzen Zahlen, alles andere eine echte). Kleine Einschränkung: Die Eingabe muss durch Leerzeichen getrennt sein, 2d10+5muss also als eingegeben werden 2 d 10 + 5, sonst erhalten Sie eine input conversion error.

Kyle Kanos
quelle
4

Rubin, 116

Alternative Ruby-Version. Ich habe versucht, einen Weg zu finden, dies ohne die regulären Ausdrücke zu tun, aber die Validierung, die Sie durchführen müssen, ist ohne sie viel schwieriger.

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

Dieser ist 112 und verwendet Dennis 'cleveren Perl-Algorithmus:

$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
quelle
@ m.buettner Danke! Ich weiß nicht, warum ich dachte, es müsste> 0 sein.
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)}

Besser kann man nicht golfen. Es ist Zeit, wieder an die Arbeit zu gehen.

Snack
quelle
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)hat nur 137 Bytes.
Dennis
2
Laut den Kommentaren zu der Frage ist dies eine falsche Antwort, da die Eingabe abgelehnt wird 02d05+073.
Peter Taylor
3

GolfScript ( 120 106 Bytes)

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

Dies ist nicht nur kürzer als die erste Version, sondern auch eleganter. Der Teil, der das Würfeln tatsächlich macht, ist

\{rand)+}+@*

Der Rest besteht hauptsächlich aus der Eingabeüberprüfung und ein paar Zeichen zum Parsen.

# 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

Online Demo mit Test Framework

Peter Taylor
quelle
Ich frage mich, warum Sie nicht verwenden n./? Vielleicht auch 10,n*für ein Zeichen weniger.
Howard
@Howard, zum ersten, denn es war ein Last-Minute-Hack, um einige Testfälle zu bestehen, und ich habe nicht daran gedacht, Golf zu spielen. Auf die Sekunde genau würde dies dazu führen, dass ungültige Eingaben akzeptiert werden.
Peter Taylor
2

J - 130 (45?) Char

Diese Herausforderung scheint ein wenig voreingenommen gegenüber regulären Ausdrücken zu sein, insbesondere wenn ungültige Eingaben unterschieden werden müssen. J hat eine POSIX-Regex-Bibliothek, es ist also nicht so schlimm, aber nicht wie in Perl integriert, sodass J nicht besser abschneidet als andere Sprachen.

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

Wenn Sie nur die Logik für gültige Ausdrücke implementieren, wie es die Python / PHP-Lösungen scheinen, sind es die vernünftigeren 45 Zeichen:

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

Bemerkenswerte Bits:

  • 1!:1]1ist die Eingabe und (rxmatch rxfrom])die Logik, die die Unterausdrucksübereinstimmungen zurückgibt.

  • Ob die Eingabe zulässig war oder nicht, wird vom Regex-Matching behandelt, sodass wir die Standardwerte für n und p mit festlegen können 0 1 1>.. Es sieht rückwärts aus (n ist standardmäßig 1 und p ist 0), weil wir |.die Liste früher umkehren mussten ( ), damit die Logik am Ende in der richtigen Reihenfolge ausgeführt wird.

  • @.ist die Agenda- Konjunktion, im Wesentlichen eine J-ish switch-Anweisung. Wenn die Übereinstimmungen leer sind (wenn 0 ein Element von $ hape ist:) 0 e.$, geben wir die Fehlermeldung aus, ansonsten würfeln wir: #~um die Würfel auszurichten, 1+?zu würfeln und +/@,den Modifikator p hinzuzufügen und Summe.

algorithmshark
quelle
Funktioniert das für 01d01+01?
Cees Timmerman
@ CeesTimmerman Mein schlechtes. Das tut es jetzt.
Algorithmushai
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)

Die ersten vier Zeilen befassen sich mit der Tatsache, dass "d" ein Alias ​​für den universellen "down" -Exit mit einer integrierten Fehlermeldung ist, wenn diese nicht vorhanden ist. Exits werden vor benutzerdefinierten Befehlen gescannt. Die verbleibenden Zeilen erstellen ein Objekt mit einem benutzerdefinierten Befehl, der die integrierte Funktion die () verwendet.

Muqo
quelle
2

PHP, 129

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

Verwendet einen regulären Ausdruck, um einen Ausdruck zu erstellen, den PHP dann auswertet. Die Eingabe erfolgt über URL:? 0 = Argument . Stellen Sie sicher, dass Sie das + mit% 2b urlenkodieren. So sieht es in besser lesbarer Form aus:

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

Durch bitweises Invertieren der Zeichenfolgen wird ~nicht nur ein Zeichen gespeichert, weil Sie keine Anführungszeichen benötigen (PHP geht davon aus, dass es sich um Zeichenfolgen handelt), sondern auch Zeichen, weil Sie die umgekehrten Schrägstriche im regulären Ausdruck nicht umgehen müssen.

Der ?:Operator ist eine Sonderform des ternären Operators. $foo = $a ? $a : $bist das gleiche wie $foo = $a ?: $b.

Tryth
quelle
1

Java, 378

Ich wollte nur eine Lösung mit Java ausprobieren, die weit von der besten Lösung entfernt ist. Aber hey: Java ist auf keinen Fall eine Golfsprache!

Es erhält die Eingabe von der Kommandozeile. Erster Parameter args[0]ist der Eingabewert.

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

Wussten Sie, dass decodeist kürzer als valueOf?

Bobbel
quelle
1

Python 3, 184 Bytes

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)

Besteht alle Tests. Wenn null Würfel erlaubt wären, wären es 6 Bytes kürzer, wenn man sie weglässt (or q).

Cees Timmerman
quelle
Ich habe die BNF jedoch falsch verstanden. Diese Seite hilft.
Cees Timmerman
Zum Wohle aller anderen, die sich fragen, warum der Regex an einem Ende verankert ist, aber nicht am anderen: Python re.matchverankert sich implizit am Anfang, aber nicht am Ende. Mir ist keine andere Regex-Bibliothek bekannt, die das tut.
Peter Taylor
1
Es gibt eine kleine Ersparnis beim Initialisieren t=int(c or 0); und es könnte möglich sein, Ihre Antwort mit der vorhandenen Python-Antwort (die weniger Leerzeichen verwendet) zu kombinieren, um ein paar mehr zu sparen.
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.
quelle
Dies ist so ähnlich wie die Antwort
user12205
Nun, es gibt Ähnlichkeiten, das ist die gleiche Sprache / der gleiche Algorithmus ... Aber ich dachte, es gibt genug Unterschiede in meinem Code (und der Regex), um eine andere Antwort zu posten.
Michael M.
Laut den Kommentaren zu der Frage ist dies eine falsche Antwort, da die Eingabe abgelehnt wird 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

Verwendet einen regulären Ausdruck, um die ganze Arbeit zu erledigen. Da ich verwende \d+, muss ich nur prüfen, ob eine ungültige Eingabe vorliegt, weder eine nnoch eine Übereinstimmungm waren 0, und dass es eine war m. Wenn eines dieser Elemente gefunden wird, wird es mit einer Meldung ( 'Invalid input') abgebrochen . Dann gibt es nur das Ergebnis aus, da es inzwischen abgebrochen worden wäre, wenn die Eingabe ungültig gewesen wäre.

Das Ergebnis-Drucken ist nicht so interessant, aber ...

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

Ich später geändert .inject(:+)zu eval(...*?+), aber die Idee ist das gleiche.

Türknauf
quelle
0

Python3, 204B

Meins schlägt die bestehende Python-Antwort durch Hinzufügen der erforderlichen Fehlerbehandlung und Lesen d20als 1d20statt 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)

bearbeiten 2 Tippfehler zu beheben: I(x) => I(c),Invalid Input => Invalid input

bearbeitet, um Regex zu reparieren: \+?(\d*) => (\+\d+)?

Alexander-Brett
quelle
Laut der geklärten Frage ist dies eine falsche Antwort, da die Eingabe akzeptiert wird 3d20+.
Peter Taylor
Guter Punkt! #Filler
Alexander-Brett
Und nicht 01d01+01.
Cees Timmerman