ทอยลูกเต๋าและดันเจี้ยนมังกร


20

ฉันต้องการเล่น Dungeons and Dragons แต่ฉันไม่มีลูกเต๋า! ความท้าทายของคุณคือหมุนลูกเต๋า 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จะเป็นจำนวนของลูกเต๋าที่จะม้วน; อย่างน้อยจะต้องเป็น1ค่าเริ่มต้น1หากไม่ได้ระบุไว้

จำนวนเต็มที่ต้องการทันทีหลังจากdคือจำนวนของแต่ละด้านที่มี 1มันจะต้องเป็นอย่างน้อย 1ด้านข้างของแต่ละคนตายมีความแตกต่างจำนวนเต็มบวกติดต่อกันเริ่มต้นที่

ตัวเลือกเสริมอาจเป็น+0และจะมีค่าเริ่มต้น+0หากไม่ได้ระบุไว้

ตัวอย่างเช่นสำหรับอินพุต2d10+5คุณสร้างตัวเลขสุ่มสองหมายเลขจาก 1 ถึง 10 รวมเพิ่มเข้าด้วยกันและเพิ่ม 5 จากนั้นคุณจะแสดงผลลัพธ์

ถ้าคุณได้รับการป้อนข้อมูลที่ไม่ถูกต้องเช่น2d, d20+, 0d4, 2d5+1+2, 2+2หรือสิ่งอื่นที่ไม่พอดีกับรูปแบบนี้คุณต้องเอาท์พุท " Invalid input" มิฉะนั้นคุณจะต้องแสดงผลเป็นจำนวนเต็มแบบสุ่มเดียวเท่านั้นซึ่งมีน้ำหนักตามอินพุต ยกตัวอย่างเช่น3d6ควรผลิตมากขึ้น10s กว่า4 s

กรณีทดสอบ

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

2
ส่วนที่ยากเกี่ยวกับคำถามนี้คือการตรวจสอบความถูกต้องของอินพุต แต่ย่อหน้าที่อธิบายถึงกฎการตรวจสอบความถูกต้องนั้นขัดแย้งกับตัวเอง มันอธิบายnและpเป็นตัวเลือก แต่การป้อนข้อมูลที่เลือกที่จะไม่รวมพวกเขา ( d20+) ว่าไม่ถูกต้อง
Peter Taylor

1
@PeterTaylor: ฉันคิดว่า+ควรจะเพิ่มสัญญาณเมื่อมีการแก้ไขpเท่านั้น
ProgramFOX

4
@Doorknob ก็เพราะว่า d13 และ d17 ไม่ใช่ลูกเต๋าที่ใช้ใน D&D D&D ใช้ d4, d6, d8, d10, d12 และ d20 นอกจากนี้ยังมีบางกรณีที่การหมุนจะรวมถึงลูกเต๋าชนิดต่าง ๆ (เช่น1d4+1d6สำหรับ Rogue แอบโจมตีกริช) หรือมีการลบp(เช่น1d20-1สำหรับการตรวจสอบทักษะโดยไม่มีอันดับ / การฝึกอบรมและการปรับปรุงความสามารถเชิงลบ)
Brian S

2
คุณจะเล่น dnd โดยไม่ต้องใช้ usecase 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'

ต้องใช้-pสวิตช์ซึ่งคิดเป็นสองไบต์ ลองมันออนไลน์บนIdeone

มันทำงานอย่างไร

  • เพราะ-pสวิทช์บรรทัดถูกอ่านจาก STDIN $_และเก็บไว้ใน

  • คำสั่งจะs/^d/1d/เพิ่ม1ถึง$_ถ้าเริ่มต้นด้วยdเช่นหากไม่ระบุจำนวนของลูกเต๋า

  • นิพจน์ทั่วไป/^(\d+)d(\d+)(\+\d+)?/ตรวจสอบว่าบรรทัดประกอบด้วยตัวเลขตัวอักษรdตัวเลขอื่นหรือไม่หรือเป็นตัวเลขที่สามนำหน้าด้วยเครื่องหมาย+

    หากมีการแข่งขันตัวเลขจะถูกบันทึกไว้ใน$1, และ$2$3

    ในกรณีนี้การป้อนข้อมูลจะถูกต้องหากและถ้า$1และ$2ทั้งบวก

  • $d += 1 + rand $2 | 0เพิ่มจำนวนเต็มหลอกแบบสุ่มจาก 1 เป็นจำนวนด้านที่ระบุไป$d(เริ่มแรกถือว่าเป็นศูนย์)

  • for 1 .. $1 ทำข้างต้นหนึ่งครั้งสำหรับทุกจำนวนเต็มตั้งแต่ 1 ถึงจำนวนลูกเต๋า

  • คำสั่ง$_ = $1 * $2 ? $d + $3 : 'Invalid input'ทำสิ่งต่อไปนี้:

    • ถ้า$1 * $2เป็นศูนย์มันจะตั้งค่า$_การป้อนข้อมูลที่ไม่ถูกต้อง

    • มิฉะนั้นการป้อนข้อมูลที่ถูกต้องและมันจะตั้งค่า $_เป็นผลรวมของลูกเต๋าม้วนและตัวปรับเปลี่ยน

  • เนื่องจากว่า -pสวิทช์, Perl $_พิมพ์เนื้อหาของ

  • เนื่องจากไม่มีบรรทัดอินพุตเพิ่มเติมสคริปต์จึงออก


1
ฉันเชื่อว่าโดยทั่วไปพารามิเตอร์บรรทัดคำสั่งพิเศษจะถือว่ามีค่าเป็นไบต์ละ แต่ยัติภังค์ฟรี ในกรณีนี้คุณ-pจะเสียค่าใช้จ่ายเพียงอย่างเดียวทำให้เป็นโซลูชั่น 108 ไบต์
undergroundmonorail

2
สามารถทำ 96 ตัวอักษร/^([1-9]\d*)?d([1-9]\d*)(\+\d+)?$/||die"Invalid input$/";$a+=1+int rand$2for(1..$1||1);$_=$a+$3
Hasturkun

1
@undergroundmonorail: ฉันเห็นคนนับสวิตช์บรรทัดคำสั่งเดียวเป็นไบต์หนึ่งสองและสาม (นับช่องว่าง) ไบต์ ฉันควรนับว่าเป็นหนึ่งเดียว แต่สองไบต์ดูเหมือนจะยุติธรรมสำหรับฉัน
เดนนิส

1
@Vynce ฉันคิดว่าคุณไม่ได้อย่างใดอย่างหนึ่ง ผมใช้|0การโยน int เนื่องจากrandผลตอบแทนที่ได้รับการแต่งตั้งหลอกสุ่มลอย
Dennis

1
@Vynce ฉันได้เพิ่ม Permalink ให้กับคำถาม ( ideone.com/gLJfhO ) -eจะเป็นปัญหาที่นี่เว้นแต่คุณจะแทนที่เครื่องหมายคำพูดเดี่ยวด้วยเครื่องหมายคำพูดคู่
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;

การใช้งานที่ไม่เหมาะสมโดยนัย ( i-nเป็นจำนวนเต็มทุกอย่างเป็นของจริง) ไมเนอร์ข้อแม้: การป้อนข้อมูลจะต้องเป็นพื้นที่ที่แยกออกจากกันดังนั้น2d10+5จะต้องป้อนเป็นมิฉะนั้นคุณจะได้รับ2 d 10 + 5input conversion error


4

ทับทิม, 116

ทางเลือกรุ่นทับทิม ฉันพยายามหาวิธีที่จะทำได้โดยไม่ต้องมีการแสดงออกปกติ แต่การตรวจสอบที่คุณต้องทำคือยากมากโดยไม่มีพวกเขา

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

ไม่สามารถเล่นกอล์ฟได้ดีไปกว่านี้ ได้เวลากลับไปทำงานแล้ว


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ตามความคิดเห็นในคำถามนี้เป็นคำตอบที่ไม่ถูกต้องเพราะมันปฏิเสธการป้อนข้อมูล
Peter Taylor

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*น้อยกว่าหนึ่งตัวอักษร
โฮเวิร์ด

@Howard ถึงครั้งแรกเพราะมันเป็นนาทีสุดท้ายที่แฮ็คจะผ่านการทดสอบบางกรณีและฉันไม่ได้คิดถึงการเล่นกอล์ฟ ประการที่สองนั่นจะทำให้ยอมรับการป้อนข้อมูลที่ไม่ถูกต้อง
Peter Taylor

2

J - 130 (45?) ตัวอักษร

ความท้าทายนี้ดูเหมือนจะมีอคติเล็กน้อยต่อการแสดงออกปกติโดยเฉพาะอย่างยิ่งเมื่อต้องแยกแยะอินพุตที่ไม่ถูกต้อง J มีไลบรารี POSIX regex ดังนั้นมันก็ไม่ได้แย่ขนาดนั้น แต่มันไม่ได้รวมเข้ากับ 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])เป็นตรรกะที่ส่งคืน subexpression ที่ตรงกัน

  • หรือไม่ว่าการป้อนข้อมูลที่ถูกกฎหมายจะถูกจัดการโดยการจับคู่ regex เพื่อให้เราสามารถตั้งค่าเริ่มต้นสำหรับ n p 0 1 1>.และมี ดูย้อนหลัง (n คือ 1 โดยค่าเริ่มต้นและ p คือ 0) เพราะเราต้องย้อนกลับ ( |.) รายการก่อนหน้านี้เพื่อให้ตรรกะที่ส่วนท้ายดำเนินการตามลำดับที่ถูกต้อง

  • @.คือการรวมวาระการประชุมเป็นหลักคำสั่ง J-ish เปลี่ยน หากการแข่งขันว่างเปล่า (ถ้า 0 คือ e.lement of $ hape:) 0 e.$เราปล่อยข้อความแสดงข้อผิดพลาดไม่เช่นนั้นเราจะผ่านการทอยลูกเต๋า: #~เพื่อกำหนดลูกเต๋า1+?กลิ้งและ+/@,เพิ่มตัวปรับ p และผลรวม


ใช้งานได้01d01+01หรือไม่
Cees Timmerman

@CeesTimmerman ฉันไม่ดี มันทำตอนนี้
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)

สี่บรรทัดแรกจัดการกับความจริงที่ว่า "d" เป็นนามแฝงสำหรับทางออก "ลง" สากลพร้อมกับข้อความแสดงความล้มเหลวในตัวเมื่อไม่มี ออกจากการสแกนก่อนคำสั่งที่ผู้ใช้กำหนด บรรทัดที่เหลือสร้างวัตถุที่มีคำสั่งที่ผู้ใช้กำหนดโดยใช้ฟังก์ชั่น die () ในตัว


2

PHP, 129

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

ใช้ regex เพื่อสร้างนิพจน์ที่ PHP ประเมินค่า การป้อนข้อมูลจะถูกป้อนผ่าน url: 0 = โต้แย้ง ตรวจสอบให้แน่ใจว่าคุณได้ urlencode + ถึง% 2b นี่คือสิ่งที่ดูเหมือนในรูปแบบที่อ่านง่ายขึ้น:

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 สลับการใช้สตริง ~ไม่เพียงบันทึกอักขระเนื่องจากคุณไม่ต้องการอัญประกาศ (PHP ถือว่าเป็นสตริง) แต่ยังบันทึกอักขระเนื่องจากคุณไม่ต้องใช้เครื่องหมายแบคสแลชในนิพจน์ทั่วไป

?:ประกอบเป็นรูปแบบพิเศษของผู้ประกอบการ ternary เป็นเช่นเดียวกับ$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 แม้ว่า หน้านี้ช่วย
Cees Timmerman

เพื่อประโยชน์ของผู้อื่นที่สงสัยว่าเหตุใดจึงมีการยึดที่ปลายด้านหนึ่งของ regex แต่ไม่ใช่ที่อื่น ๆ : Python re.matchยึดจุดเริ่มต้นโดยปริยาย แต่ไม่สิ้นสุด ฉันไม่ทราบว่าไลบรารี regex อื่นใดที่ทำเช่นนั้น
Peter Taylor

1
มีขนาดเล็กประหยัดโดยเริ่มต้นt=int(c or 0); และอาจเป็นไปได้ที่จะรวมคำตอบของคุณกับ Python ที่มีอยู่ (ซึ่งใช้พื้นที่น้อยกว่า) เพื่อประหยัดอีกสองสามข้อ
Peter Taylor

0

จาวาสคริปต์ 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')

นี้คล้ายกับคำตอบของ Snack
user12205

มีความคล้ายคลึงกันนี่เป็นภาษา / อัลกอริทึมเดียวกัน ... แต่ฉันคิดว่ามีความแตกต่างในโค้ดของฉัน (และ regex) มากพอที่จะโพสต์คำตอบที่ต่างออกไป
Michael M.

02d05+073ตามความคิดเห็นในคำถามนี้เป็นคำตอบที่ไม่ถูกต้องเพราะมันปฏิเสธการป้อนข้อมูล
Peter Taylor

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

ใช้ regexp เพื่อทำงานทั้งหมด ตั้งแต่ฉันใช้\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

Mine จะตอบคำถาม 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

แก้ไขเพื่อแก้ไข regex: \+?(\d*) => (\+\d+)?


3d20+ตามที่ชี้แจงคำถามนี้เป็นคำตอบที่ไม่ถูกต้องเพราะมันยอมรับการป้อนข้อมูล
Peter Taylor

จุดดี! #filler
alexander-brett

01d01+01และไม่
Cees Timmerman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.