using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; // see http://www.carlopescio.com/2011/06/cut-red-wire.html for details namespace Yahtzee { class DiceGroup { public DiceGroup(int f, int c) { Face = f; Count = c; } public int Face { get; private set; } public int Count { get; private set; } public int Score() { return Face * Count; } } class Roll : IEnumerable { public Roll(int[] dice) { diceByFace = dice.GroupBy(x => x).Select(g => new DiceGroup(g.First(), g.Count())); } public Roll(IEnumerable dice) { diceByFace = dice; } public int Score() { return diceByFace.Sum(g => g.Score()); } public IEnumerator GetEnumerator() { return diceByFace.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return diceByFace.GetEnumerator(); } public static Roll Empty() { return empty; } private IEnumerable diceByFace; private static int[] emptyArray = new int[0]; private static Roll empty = new Roll(emptyArray); } static class RollLanguage { public static Roll TopByFace(this Roll groups, int minCount) { if( groups.Count() < minCount ) return Roll.Empty(); else return groups.OrderByDescending(g => g.Face).Take(minCount).AsRoll(); } public static Roll TrimCountTo(this Roll groups, int minCount) { return groups.Where(g => g.Count >= minCount).Select(g => new DiceGroup(g.Face, minCount)).AsRoll(); } public static Roll TrimFaceTo(this Roll groups, int face) { return groups.Where(g => g.Face == face).AsRoll(); } public static Roll AsRoll(this IEnumerable r) { return new Roll(r); } } class Yahtzee { public int ScoreOnePair(Roll r) { return r.TrimCountTo(2).TopByFace(1).Score(); } public int ScoreTwoPairs(Roll r) { return r.TrimCountTo(2).TopByFace(2).Score(); } public int ScoreThreeOfAKind(Roll r) { return r.TrimCountTo(3).Score(); } public int ScoreFourOfAKind(Roll r) { return r.TrimCountTo(4).Score(); } public int ScoreYahtzee(Roll r) { return r.TrimCountTo(5).Score(); } public int ScoreChance(Roll r) { return r.Score(); } public int ScoreOnes(Roll r) { return r.TrimFaceTo(1).Score(); } } class Program { static void Main(string[] args) { Yahtzee y = new Yahtzee(); int[] dice = { 1, 1, 4, 3, 4 }; Roll roll = new Roll(dice); int n = y.ScoreTwoPairs(roll); Debug.Assert(n == 10); n = y.ScoreOnePair(roll); Debug.Assert(n == 8); n = y.ScoreThreeOfAKind(roll); Debug.Assert(n == 0); n = y.ScoreFourOfAKind(roll); Debug.Assert(n == 0); n = y.ScoreYahtzee(roll); Debug.Assert(n == 0); n = y.ScoreChance(roll); Debug.Assert(n == 13); n = y.ScoreOnes(roll); Debug.Assert(n == 2); dice = new int[] { 3, 3, 2, 3, 2 }; roll = new Roll(dice); n = y.ScoreTwoPairs(roll); Debug.Assert(n == 10); n = y.ScoreOnePair(roll); Debug.Assert(n == 6); n = y.ScoreThreeOfAKind(roll); Debug.Assert(n == 9); n = y.ScoreFourOfAKind(roll); Debug.Assert(n == 0); n = y.ScoreYahtzee(roll); Debug.Assert(n == 0); n = y.ScoreChance(roll); Debug.Assert(n == 13); n = y.ScoreOnes(roll); Debug.Assert(n == 0); dice = new int[] { 1, 2, 4, 3, 4 }; roll = new Roll(dice); n = y.ScoreTwoPairs(roll); Debug.Assert( n == 0 ); n = y.ScoreOnePair(roll); Debug.Assert(n == 8); n = y.ScoreThreeOfAKind(roll); Debug.Assert(n == 0); n = y.ScoreFourOfAKind(roll); Debug.Assert(n == 0); n = y.ScoreYahtzee(roll); Debug.Assert(n == 0); n = y.ScoreChance(roll); Debug.Assert(n == 14); dice = new int[] { 1, 2, 5, 3, 4 }; roll = new Roll(dice); n = y.ScoreTwoPairs(roll); Debug.Assert(n == 0); n = y.ScoreOnePair(roll); Debug.Assert(n == 0); n = y.ScoreThreeOfAKind(roll); Debug.Assert(n == 0); n = y.ScoreFourOfAKind(roll); Debug.Assert(n == 0); n = y.ScoreYahtzee(roll); Debug.Assert(n == 0); n = y.ScoreChance(roll); Debug.Assert(n == 15); dice = new int[] { 1, 2, 2, 2, 2 }; roll = new Roll(dice); n = y.ScoreTwoPairs(roll); Debug.Assert( n == 0 ); n = y.ScoreOnePair(roll); Debug.Assert(n == 4); n = y.ScoreThreeOfAKind(roll); Debug.Assert(n == 6); n = y.ScoreFourOfAKind(roll); Debug.Assert(n == 8); n = y.ScoreYahtzee(roll); Debug.Assert(n == 0); n = y.ScoreChance(roll); Debug.Assert(n == 9); dice = new int[] { 2, 2, 2, 2, 2 }; roll = new Roll(dice); n = y.ScoreTwoPairs(roll); Debug.Assert(n == 0); n = y.ScoreOnePair(roll); Debug.Assert(n == 4); n = y.ScoreThreeOfAKind(roll); Debug.Assert(n == 6); n = y.ScoreFourOfAKind(roll); Debug.Assert(n == 8); n = y.ScoreYahtzee(roll); Debug.Assert(n == 10); n = y.ScoreChance(roll); Debug.Assert(n == 10); } } }