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
Mı 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.