Rulo Zindanlar ve Ejderhalar zar


20

Zindanlar ve Ejderhalar oynamak istiyorum, ama zarım yok! Senin meydan okuma bazı D & D zar atmak için.

Backus-Naur formundaki girdi biçimi belirtimi :

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

'Den önceki isteğe bağlı tam dsayı, döndürülecek zar sayısıdır; en azından olmalı 1ve sağlanmazsa varsayılan olarak 1ayarlanmalıdır.

Hemen ardından gereken tamsayı dher kalıbın sahip olduğu kenar sayısıdır; en azından olmalı 1. Her kalıbın yanları, başlangıçta başlayan ardışık pozitif tamsayılardır 1.

İsteğe bağlı değiştirici olabilir +0ve +0belirtilmezse varsayılan olarak ayarlanır.

Örneğin, giriş için 2d10+5, 1'den 10'a dahil olmak üzere iki rastgele sayı üretir, bunları toplar ve 5 eklersiniz. Sonra sonucu çıkarırsınız.

Eğer geçersiz giriş gibi alırsanız 2d, d20+, 0d4, 2d5+1+2, 2+2, siz "çıktı gerekir bu biçimi uymuyor başka, ya da bir şey Invalid input". Aksi takdirde, girişe göre ağırlıklı tek bir rastgele tamsayı çıkarmalısınız. Örneğin, 3d6daha fazla üretmelidir 10daha s 4s .

Test senaryoları

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

Bu , bu yüzden bayt içindeki en kısa kod kazanacak!


1
02d05+073geçerli bir girdi?
MT0

2
Bu sorunun zor kısmı girdiyi doğrulamaktır, ancak doğrulama kurallarını açıklayan paragraf kendi kendine çelişkilidir. İsteğe bağlı olarak nve pisteğe bağlı olarak tanımlanır , ancak bunları ( d20+) geçersiz olarak eklememeyi seçen girdi .
Peter Taylor

1
@PeterTaylor: İşaretin +yalnızca değiştirici psağlandığında eklenmesi gerektiğini düşünüyorum .
ProgramFOX

4
@Doorknob, Eh, çünkü d13 ve d17 D & D'de zar kullanılmıyor. D&D d4, d6, d8, d10, d12 ve d20 kullanır. Ayrıca, bir rulonun farklı zar türlerini (örneğin, 1d4+1d6bir hançere saldıran bir Rogue sinsi için) veya negatif p(örneğin, 1d20-1rütbeleri / eğitimi olmayan bir yetenek kontrolü ve olumsuz bir yetenek değiştirici için) içereceği durumlar da vardır .
Brian S

2
Kullanmadan dnd oynayacak mısın 2d8 + 1d6 + 4? Kötü bir zaman
geçireceksiniz

Yanıtlar:


12

Perl, 109 95 93 96 89 bayt

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

Gerektirir -pİki bayttan anahtarı . Ideone'da çevrimiçi deneyin .

Nasıl çalışır

  • Nedeniyle -pAnahtar STDIN'den bir satır okunur ve içinde saklanır $_.

  • Komut s/^d/1d/bir başa ekler 1 için$_ , bir d ile başlıyorsa , yani zar sayısı belirtilmemişse .

  • Normal ifade /^(\d+)d(\d+)(\+\d+)?/, satırın bir sayıdan, bir değişmez değerden oluşup oluşmadığını kontrol eder d , başka bir sayı ve isteğe bağlı olarak önünde + işareti bulunan üçüncü .

    Bir eşleşme varsa, sayılar $1 , $2ve$3 .

    Bu durumda, giriş geçerli olacak ancak ve ancak $1ve$2 her ikisi de pozitifse .

  • $d += 1 + rand $2 | 0 1'den belirtilen sayıda tarafa sözde rastgele seçilen tam sayı ekler $d (başlangıçta sıfır olarak muamele edilir) .

  • for 1 .. $1 1 ile zar sayısı arasındaki her tam sayı için yukarıdakini bir kez yapar.

  • Komut $_ = $1 * $2 ? $d + $3 : 'Invalid input'aşağıdakileri yapar:

    • Eğer $1 * $2sıfırdır, bu ayarlar $_için geçersiz girdi .

    • Aksi takdirde, giriş geçerlidir ve $_zar rulolarının ve değiştiricinin toplamına ayarlanır .

  • -pAnahtar nedeniyle Perl,$_ .

  • Başka giriş satırı olmadığından komut dosyası çıkar.


1
Genel olarak, ekstra komut satırı parametrelerinin her bir bayt değerinde olduğu düşünülür, ancak kısa çizgi ücretsizdir. Bu durumda, -psadece bir tanesine mal olur, bu da 108 baytlık bir çözümdür.
undergroundmonorail

2
96 karakter yapılabilir/^([1-9]\d*)?d([1-9]\d*)(\+\d+)?$/||die"Invalid input$/";$a+=1+int rand$2for(1..$1||1);$_=$a+$3
Hasturkun

1
@undergroundmonorail: İnsanların tek bir komut satırı anahtarını bir, iki ve hatta üç (boşluk sayarak) bayt olarak saydığını gördüm. Bir olarak saymayı tercih ederim, ama iki bayt bana adil geliyor.
Dennis

1
@Vynce İkinizin de olmadığını varsayıyorum. Ben |0int için döküm kullanın, çünkü randsahte rasgele seçilen bir float döndürür .
Dennis

1
@Vynce Soruya bir kalıcı bağlantı ekledim ( ideone.com/gLJfhO ). -etek tırnakları çift tırnaklarla değiştirmediğiniz sürece burada sorun çıkarır.
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;

Örtülü yazmayı kötüye kullanma ( i-ntümü tamsayıdır, diğer her şey gerçektir). Küçük uyarı: giriş boşlukla ayrılmalıdır, bu 2d10+5nedenle olarak girilmelidir 2 d 10 + 5, aksi takdirde bir alırsınız input conversion error.


4

Ruby, 116

Alternatif Ruby sürümü. Düzenli ifadeler olmadan bunu yapmanın bir yolunu bulmaya çalışıyordum, ancak yapmanız gereken doğrulama onlarsız çok daha zor.

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

Bu, Dennis'in akıllı Perl algoritmasını kullanan 112'dir:

$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 Teşekkürler! Neden> 0 olması gerektiğini düşündüğümü bilmiyorum.
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)}

Bundan daha iyi golf olamaz. İşe geri dönme zamanı.


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)yalnızca 137 bayta sahiptir.
Dennis

2
Sorudaki yorumlara göre, bu yanlış bir cevaptır, çünkü girişi reddetmektedir 02d05+073.
Peter Taylor

3

GolfScript ( 120 106 bayt)

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

Bu sadece ilk versiyondan daha kısa değil, aynı zamanda daha zariftir. Gerçekten kalıp haddeleme yapan kısmı

\{rand)+}+@*

Geri kalanı temel olarak giriş doğrulaması ve ayrıştırma için birkaç karakterdir.

# 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

Test çerçeveli çevrimiçi demo


Neden kullanmadığınızı merak ediyorum n./? Belki 10,n*bir karakter daha az.
Howard

@Howard, birincisi, çünkü bazı test senaryolarını geçmek son dakika hack oldu ve ben golf hakkında düşünmedim. İkincisi, bu bazı geçersiz girişleri kabul eder.
Peter Taylor

2

J - 130 (45?) Karakter

Bu zorluk, özellikle geçersiz girdiyi ayırt etmek zorunda kalmakla birlikte, düzenli ifadelere biraz önyargılı görünüyor. J'nin bir POSIX normal ifade kütüphanesi var, bu yüzden o kadar da kötü değil, ancak Perl ile olduğu gibi entegre değil, bu yüzden J diğer dillerden daha iyi değil.

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

Python / PHP çözümleri gibi geçerli ifadeler için mantığı uyguluyorsanız, daha makul 45 karakterdir:

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

Dikkate değer bitler:

  • 1!:1]1girdi ve (rxmatch rxfrom])alt ifade eşleşmelerini döndüren mantıktır.

  • Girdinin yasal olup olmadığı normal ifade eşleşmesi tarafından işlenir, bu nedenle n ve p için varsayılanları ayarlayabiliriz 0 1 1>.. Geriye doğru bakar (n varsayılan olarak 1'dir ve p 0'dır) çünkü |.listeyi daha önce tersine çevirmek zorunda kaldık ( ), böylece sondaki mantık doğru sırada yürütülür.

  • @.olan Ajanda birlikte, esas olarak, bir J-ish anahtar ifadesi. Eşleşmeler boşsa (0 $ hape'nin bir e.lementi ise 0 e.$), hata mesajını yayarız , aksi takdirde zar atmaktan geçeriz : #~zarları yerleştirmek, 1+?yuvarlamak ve +/@,değiştirici p'yi eklemek için ve toplam.


Bu işe yarıyor 01d01+01mu?
Cees Timmerman

@CeesTimmerman Kötüüm. Şimdi öyle.
algorithmmshark

2

MinikMUSH , 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)

İlk dört satır, "d" nin, mevcut olmadığında yerleşik bir hata mesajıyla evrensel "aşağı" çıkış için bir takma ad olduğu gerçeğiyle ilgilidir; çıkışlar kullanıcı tanımlı komutlardan önce taranır. Kalan satırlar, yerleşik die () işlevini kullanarak kullanıcı tanımlı bir komutla bir nesne oluşturur.


2

PHP, 129

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

Daha sonra PHP'nin değerlendirdiği bir ifade oluşturmak için bir normal ifade kullanır. Girdi url:? 0 = argüman ile besleniyor . + Kodunu% 2b olarak kodladığınızdan emin olun. Daha okunabilir bir biçimde şöyle görünür:

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

Kullanarak dizeleri bitsel olarak ters çevirme ~ yalnızca bir karakteri kaydetmekle kalmaz, çünkü tırnaklara (PHP'nin dizeler olduğunu varsayar) değil, aynı zamanda karakterleri de kaydeder, çünkü normal ifadedeki ters eğik çizgilerden kaçmak zorunda kalmazsınız.

?:Operatör üçlü operatörün özel bir şeklidir. $foo = $a ? $a : $bile aynıdır $foo = $a ?: $b.


1

Java, 378

Sadece Java ile en iyi çözümden uzak bir çözüm denemek istedim. Ama hey: Java her durumda golf dili değildir!

Girişi komut satırından alır. İlk parametre args[0]giriş değeridir.

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

Biliyor muydunuz decode, daha kısa valueOfmı?


1

Python 3, 184 bayt

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)

Tüm testleri geçer. Sıfır zar izin verilirse, dışarıda bırakılarak 6 bayt daha kısa olacaktır (or q).


Yine de BNF'yi yanlış anladım. Bu sayfa yardımcı olur.
Cees Timmerman

Normal ifadenin neden bir uca tutturulduğunu merak ediyor, ancak diğerine değil re.match. Bunu yapan başka bir regex kütüphanesinin farkında değilim.
Peter Taylor

1
Başlatarak küçük bir tasarruf var t=int(c or 0); ve cevabınızı mevcut Python ile birleştirerek (daha az boşluk kullanan) birkaç tane daha tasarruf edebilirsiniz.
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')

Bu
Snack'in

Peki benzerlikler var, bu aynı dil / algoritma ... Ama benim kod (ve regex) farklı bir cevap göndermek için yeterli farklılıklar olduğunu düşündüm.
Michael

Sorudaki yorumlara göre, bu yanlış bir cevaptır, çünkü girişi reddetmektedir 02d05+073.
Peter Taylor

0

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

Tüm işi yapmak için bir normal ifade kullanır. Kullandığımdan beri \d+, geçersiz girdiyi kontrol etmem gereken tek şey, ne bir eşleşme olduğunu, ne nde ne molduğunu 0ve bir m. Bunlardan herhangi biri bulunursa, bir mesajla ( 'Invalid input') iptal edilir . Daha sonra sonucu yazdırır, çünkü giriş geçersizse şimdiye kadar iptal edilirdi.

Sonuç baskısı o kadar ilginç değil, ama ...

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

Daha sonra değişti .inject(:+)etmek eval(...*?+), ama fikir aynıdır.


0

Python3, 204B

Mine gerekli hata işleme ekleyerek ve okuyarak mevcut Python cevabı yener d20olarak 1d20yerine 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 yazım hatalarını düzeltmek için düzenlendi: I(x) => I(c),Invalid Input => Invalid input

regex düzeltmek için düzenlendi: \+?(\d*) => (\+\d+)?


Açıkça sorulan soruya göre, bu girişi yanlış kabul ettiği için yanlış bir cevaptır 3d20+.
Peter Taylor

İyi bir nokta! #filler
alexander-brett

Ve değil 01d01+01.
Cees Timmerman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.