# Score a game of Yahtzee

For each of the 13 rows of a Yahtzee scoresheet you are given (from stdin) a space separated list of 5 numbers (dice). Your task is to calculate the score for each line and output the Grand Total of the game.

## Example

Input and how to interpret it:

Input       Box              Score
6 1 4 1 3   Aces              2
3 2 2 1 2   Twos              6
6 3 2 3 3   Threes            9
4 2 3 6 5   Fours             4
6 3 5 5 1   Fives            10
1 5 6 5 6   Sixes            12
Bonus             -
4 2 4 4 1   3 of a kind      15
2 2 3 2 4   4 of a kind       -
3 2 2 2 3   Full house       25
1 3 1 6 1   Small straight    -
2 5 4 6 3   Large straight   40
2 2 2 2 2   Yahtzee          50
5 5 4 5 2   Chance           21
Grand Total     194


We will disregard the Yahtzee Bonus and Joker rules, and only sum up the scores from the Upper and Lower Section and the Bonus in the Upper Section. If in doubt, refer to these rules.

May the shortest code win!

• For the benefit of those who don't speak Norwegian, could you list the scoring rules you want people to implement directly in the question? Sep 26, 2012 at 17:08
• Heh heh ;) The rules are the same, it's only some of the blocks that have changed positions, and the addition of 1 and 2 pair. The first code-block is the rough translation (without "Sum" and "Bonus") so just refer to that one. The Norwegian link was just to justify the order of the blocks for people who may be used to other setups. I think the rules are clear, and that the "pair" blocks are pretty self-explanatory. The rest of the rules should be explained on the English wiki link I provided. Sep 26, 2012 at 17:18
• Oh, I just realized, the rules are different. I will use the official, "international" rules then: yahtzeerules.com/yahtzee-scoring.htm (I like the Norwegian ones better, it has more variations in possible scores) -- I'll change the question in a moment. Sep 26, 2012 at 17:39
• You are actually going to match the input cards to the scoring line? Shouldn't we have to figure out which line is most appropriate for any given hand? Sep 27, 2012 at 2:51
• @Matt Based after skimming through some top results from a certain search engine, I'll say 'yes'. Sep 27, 2012 at 13:53

## R - 264

S=sum;
P=prod;
T=function(i)table(x[i,]);
Z=function(i,...)any(sapply(list(...),function(y)all(y%in%x[i,])))
S((x[1:6,]==(R=row(x[1:6,])))*R)+ # Upper section
S(x[7,])*any(T(7)>2)+             # 3 of a kind
S(x[8,])*any(T(8)>3)+             # 4 of a kind
25*(P(T(9))%in%5:6)+              # Full house
30*Z(10,1:4,2:5,3:6)+             # Small straight
40*Z(11,1:5,2:6)+                 # Large straight
50*(P(T(12))==5)+                 # Yahtzee
S(x[13,])                         # Chance


(264 characters when excluding the comments)

With the input

x <- as.matrix(read.table("http://pastebin.com/raw.php?i=ZRMC9B4x"))


Output

[1] 194

• Nice to see that someone manages to get the right output :D I'll update the example. Sep 27, 2012 at 9:58
• I think your program incorrectly handles full house. I tested dice 2 2 2 2 2 and I believe your program treats that as a full house and awards the 25 points.
– Matt
Sep 27, 2012 at 12:21
• I think there is also a problem with the large and small straights. If all dice are the same (I again tested 2 2 2 2 2) I get a result of numeric(0) instead of a score.
– Matt
Sep 27, 2012 at 12:26
• @Matt, where I come from (my rules or everyone's?) you can score a yahtzee (e.g. 2 2 2 2 2) under "Full house". I think you are correct about the straights, thanks; I will update my code with a shorter version I thought about. Sep 27, 2012 at 12:54

## APL (124)

S←{⍺∊+⌿⍵∘.=⍵}⋄+/(+/⎕)(50×∧/,A∘.=A←⎕)(+/10×{⍵×∨/(⍳⍵)⍷1+A-⊃A←A[⍋A←⎕]}¨N)(25×∧/S∘⎕¨2 3)(+/{(+/A)×⍵S⊢A←⎕}¨N←3 4)(+/{+/⍵×⍵=⎕}¨⍳6)

• I swear this looks identical to something I read on the side of an alien spaceship. Oct 11, 2012 at 1:45
• I have no idea if this program works or not, but surely it's the shortest :D Oct 26, 2012 at 15:00

# Python 364

S=sum;R=range;D=[map(int,raw_input().split())for i in R(13)];s=S(x for i in R(6)for x in D[i]if x==i+1)
for i in R(2):d=D[6+i];s+=[0,S(d)][max(map(d.count,d))>2+i];d=sorted(set(D[9+i]));s+=[0,30+i*10]['1, 1, 1'+', 1'*i in[d[x+1]-d[x]for x in R(len(d)-1)]]
e=D[8];a=map(e.count,e);d=D[11];print s+S(D[12])+[0,50][d.count(d[0])==5]+[0,25][2in a and 3in a or 5in a]


As requested, input is on stdin:

$yScore.py < dice.txt 194  If the data could be preloaded into a list, as some other solutions have done, I could remove 62 characters to get to 302. # Mathematica 359 y = IntegerDigits@ImportString[x, "Table"][[1]]; l = Length; g = Gather; r = Range; b = SortBy; h = l@b[g[y[[#]]], l][[-1]] &; Tr@Flatten@{# Count[y[[#]], #] & /@ r@6, If[h@7 == 3, 15, 0], If[h@8 == 4, 20, 0], If[(l /@ b[g[y[[9]]], l]) == {2, 3}, 25, 0], If[MatchQ[Sort@y[[10]], {___, n_, m_, o_, q_, ___} /; m == n + 1 && o == m + 1 && q == o + 1], 30, 0], If[Sort[y[[11]]] == r[y[[11, 1]], y[[11, 1]] + 4], 40, 0], If[l@g[y[[12]]] == 1, 50, 0], y[[13]]}  There must be a more efficient way to check for the short straight. ### GolfScript 180 n/{~]}%6,{)['{''=},,''*']*}%[{.{+}*\{..|{'{'\'=},,'++1$\~}%$\;}:g~)\;2>*}{.{+}*\g)\;3>*}{g[2 3]=25*}{$:§;3,{).4+,\>§-}%1?)!!30*}{.$(\;.5+,\>\-!40*}{g)\;5=50*}{{+}*}]+]zip{~~}%{+}*  You can test the program here Annotated program: n/ # split input by newline {~]}% # parse an int array from each line 6,{)['{''=},,''*']*}% # create {X=},,X* code blocks, # where X goes from 1 to 6 # (needed for processing the first # half of the board) [ # create an array of code blocks, for scoring: # three of a kind: {.{+}*\{..|{'{'\'=},,'++1$\~}%$\;}:g~)\;2>*} # four of a kind: {.{+}*\g)\;3>*} # full house: {g[2 3]=25*} # small straight: {$:§;3,{).4+,\>§-!}%1?)!!30*}

# straight:
{.$(\;.5+,\>\-!40*} # yahtzee: {g)\;5=50*} #chance: {{+}*} ]+ # concatenate the 1-6 code block array with this one ]zip # distribute each line in the input # to the corresponding scoring rule (code block) {~~}% # evaluate each input/code pair # and get an array with score for each hand {+}* # sum up the partial scores.  # Perl 527 characters while(<>){$l++;$q=$c=0;$q=1if(($_=~/1/&&$_=~/2/&&$_=~/3/&&$_=~/4/)||($_=~/5/&&$_=~/2/&&$_=~/3/&&$_=~/4/)||($_=~/5/&&$_=~/6/&&$_=~/3/&&$_=~/4/));@a=split//;for(@a){$c++if/$l/;}$s+=$l*($c)if$l<7;$s+=35if$s>=63&&$l==6;for$i(1...6){$t=0;$f+=$c if($l==9&&($c==2||$c==3));$c=0if!($l==11&&$c>1);for(@a){$t+=$_;$c++if/$i/;}$s+=$t if($c>=3&&$l==7);$s+=$t if($c>=4&&$l==8);$s+=50if($c==5&&$l==12);$s+=$t if($l==13&&$i==6);}$s+=25if($f==5&&$l==9);$s+=30if($q==1&&$l==10);$s+=40if($c<2&&($t==15||$t==20)&&$l==11);exit(print $s)if($l==13);}