trackler 2.0.6.11 → 2.0.6.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/CONTRIBUTING.md +6 -1
- data/common/exercises/difference-of-squares/metadata.yml +1 -1
- data/common/exercises/luhn/canonical-data.json +2 -2
- data/common/exercises/rectangles/canonical-data.json +25 -0
- data/common/exercises/rectangles/description.md +11 -3
- data/lib/trackler/version.rb +1 -1
- data/tracks/ceylon/config.json +9 -0
- data/tracks/ceylon/exercises/anagram/source/anagram/AnagramTest.ceylon +38 -39
- data/tracks/ceylon/exercises/bracket-push/source/bracketpush/BracketsTest.ceylon +28 -29
- data/tracks/ceylon/exercises/largest-series-product/example/Series.ceylon +13 -0
- data/tracks/ceylon/exercises/largest-series-product/source/largestseriesproduct/Series.ceylon +5 -0
- data/tracks/ceylon/exercises/largest-series-product/source/largestseriesproduct/SeriesTest.ceylon +30 -0
- data/tracks/ceylon/exercises/largest-series-product/source/largestseriesproduct/module.ceylon +3 -0
- data/tracks/csharp/config.json +41 -0
- data/tracks/csharp/exercises/alphametics/AlphameticsTest.cs +122 -0
- data/tracks/csharp/exercises/alphametics/Example.cs +139 -0
- data/tracks/csharp/exercises/dot-dsl/DotDslTest.cs +91 -0
- data/tracks/csharp/exercises/dot-dsl/Example.cs +90 -0
- data/tracks/csharp/exercises/dot-dsl/HINTS.md +2 -0
- data/tracks/csharp/exercises/error-handling/ErrorHandlingTest.cs +65 -0
- data/tracks/csharp/exercises/error-handling/Example.cs +34 -0
- data/tracks/csharp/exercises/exercises.csproj +1 -1
- data/tracks/csharp/exercises/hangman/Example.cs +85 -0
- data/tracks/csharp/exercises/hangman/HangmanTest.cs +140 -0
- data/tracks/csharp/exercises/ledger/Example.cs +106 -0
- data/tracks/csharp/exercises/ledger/Ledger.cs +166 -0
- data/tracks/csharp/exercises/ledger/LedgerTest.cs +168 -0
- data/tracks/elixir/exercises/allergies/allergies_test.exs +2 -2
- data/tracks/elixir/exercises/markdown/example.exs +3 -3
- data/tracks/elixir/exercises/phone-number/example.exs +0 -2
- data/tracks/elixir/exercises/queen-attack/example.exs +1 -1
- data/tracks/elixir/exercises/wordy/example.exs +6 -6
- data/tracks/elixir/exercises/zipper/zipper_test.exs +12 -12
- data/tracks/elixir/mix.exs +1 -1
- data/tracks/fsharp/config.json +8 -8
- data/tracks/fsharp/docs/ABOUT.md +4 -0
- data/tracks/fsharp/exercises/alphametics/AlphameticsTest.fs +33 -13
- data/tracks/fsharp/exercises/alphametics/Example.fs +29 -64
- data/tracks/fsharp/exercises/binary-search-tree/BinarySearchTreeTest.fs +14 -14
- data/tracks/fsharp/exercises/binary-search-tree/Example.fs +17 -14
- data/tracks/fsharp/exercises/triangle/TriangleTest.fs +0 -5
- data/tracks/go/README.md +3 -3
- data/tracks/go/config.json +10 -3
- data/tracks/go/exercises/acronym/acronym.go +5 -0
- data/tracks/go/exercises/bob/example_gen.go +1 -1
- data/tracks/go/exercises/clock/example_gen.go +1 -1
- data/tracks/go/exercises/connect/example_gen.go +1 -1
- data/tracks/go/exercises/custom-set/example_gen.go +1 -1
- data/tracks/go/exercises/gigasecond/example_gen.go +1 -1
- data/tracks/go/exercises/hamming/example_gen.go +1 -1
- data/tracks/go/exercises/largest-series-product/example_gen.go +1 -1
- data/tracks/go/exercises/leap/cases_test.go +5 -7
- data/tracks/go/exercises/leap/example.go +1 -1
- data/tracks/go/exercises/leap/example_gen.go +1 -1
- data/tracks/go/exercises/leap/leap.go +1 -1
- data/tracks/go/exercises/leap/leap_test.go +1 -1
- data/tracks/go/exercises/meetup/example_gen.go +1 -1
- data/tracks/go/exercises/nucleotide-count/nucleotide_count_test.go +0 -5
- data/tracks/go/exercises/pangram/pangram.go +5 -0
- data/tracks/go/exercises/raindrops/example_gen.go +1 -1
- data/tracks/go/exercises/rna-transcription/example_gen.go +1 -1
- data/tracks/go/exercises/roman-numerals/example_gen.go +1 -1
- data/tracks/go/exercises/word-count/example_gen.go +1 -1
- data/tracks/go/gen/gen.go +3 -2
- data/tracks/haskell/exercises/accumulate/src/Accumulate.hs +1 -1
- data/tracks/haskell/exercises/all-your-base/src/Base.hs +1 -1
- data/tracks/haskell/exercises/allergies/src/Allergies.hs +2 -2
- data/tracks/haskell/exercises/alphametics/src/Alphametics.hs +1 -1
- data/tracks/haskell/exercises/anagram/src/Anagram.hs +1 -1
- data/tracks/haskell/exercises/atbash-cipher/src/Atbash.hs +2 -2
- data/tracks/haskell/exercises/bank-account/src/BankAccount.hs +4 -4
- data/tracks/haskell/exercises/binary/src/Binary.hs +1 -1
- data/tracks/haskell/exercises/binary-search-tree/src/BST.hs +8 -8
- data/tracks/haskell/exercises/bob/src/Bob.hs +1 -1
- data/tracks/haskell/exercises/bowling/src/Bowling.hs +1 -1
- data/tracks/haskell/exercises/change/src/Change.hs +1 -1
- data/tracks/haskell/exercises/clock/src/Clock.hs +4 -4
- data/tracks/haskell/exercises/connect/src/Connect.hs +1 -1
- data/tracks/haskell/exercises/crypto-square/src/CryptoSquare.hs +1 -1
- data/tracks/haskell/exercises/custom-set/src/CustomSet.hs +13 -13
- data/tracks/haskell/exercises/difference-of-squares/src/Squares.hs +3 -3
- data/tracks/haskell/exercises/dominoes/src/Dominoes.hs +1 -1
- data/tracks/haskell/exercises/etl/src/ETL.hs +1 -1
- data/tracks/haskell/exercises/forth/src/Forth.hs +3 -3
- data/tracks/haskell/exercises/gigasecond/src/Gigasecond.hs +1 -1
- data/tracks/haskell/exercises/go-counting/src/Counting.hs +2 -2
- data/tracks/haskell/exercises/grade-school/src/School.hs +4 -4
- data/tracks/haskell/exercises/grains/src/Grains.hs +2 -2
- data/tracks/haskell/exercises/hamming/src/Hamming.hs +1 -1
- data/tracks/haskell/exercises/hexadecimal/src/Hexadecimal.hs +1 -1
- data/tracks/haskell/exercises/kindergarten-garden/src/Garden.hs +3 -3
- data/tracks/haskell/exercises/largest-series-product/src/Series.hs +1 -1
- data/tracks/haskell/exercises/leap/src/LeapYear.hs +1 -1
- data/tracks/haskell/exercises/lens-person/src/Person.hs +4 -4
- data/tracks/haskell/exercises/linked-list/src/Deque.hs +5 -5
- data/tracks/haskell/exercises/list-ops/src/ListOps.hs +8 -8
- data/tracks/haskell/exercises/luhn/src/Luhn.hs +5 -5
- data/tracks/haskell/exercises/matrix/src/Matrix.hs +10 -10
- data/tracks/haskell/exercises/meetup/src/Meetup.hs +1 -1
- data/tracks/haskell/exercises/minesweeper/src/Minesweeper.hs +1 -1
- data/tracks/haskell/exercises/nth-prime/src/Prime.hs +1 -1
- data/tracks/haskell/exercises/nucleotide-count/src/DNA.hs +2 -2
- data/tracks/haskell/exercises/ocr-numbers/src/OCR.hs +1 -1
- data/tracks/haskell/exercises/octal/src/Octal.hs +2 -2
- data/tracks/haskell/exercises/palindrome-products/src/Palindromes.hs +2 -2
- data/tracks/haskell/exercises/parallel-letter-frequency/src/Frequency.hs +1 -1
- data/tracks/haskell/exercises/pascals-triangle/src/Triangle.hs +1 -1
- data/tracks/haskell/exercises/phone-number/src/Phone.hs +3 -3
- data/tracks/haskell/exercises/pig-latin/src/PigLatin.hs +1 -1
- data/tracks/haskell/exercises/pov/src/POV.hs +2 -2
- data/tracks/haskell/exercises/prime-factors/src/PrimeFactors.hs +1 -1
- data/tracks/haskell/exercises/pythagorean-triplet/src/Triplet.hs +3 -3
- data/tracks/haskell/exercises/queen-attack/src/Queens.hs +2 -2
- data/tracks/haskell/exercises/raindrops/src/Raindrops.hs +1 -1
- data/tracks/haskell/exercises/rna-transcription/src/DNA.hs +1 -1
- data/tracks/haskell/exercises/robot-name/src/Robot.hs +3 -3
- data/tracks/haskell/exercises/robot-simulator/src/Robot.hs +6 -6
- data/tracks/haskell/exercises/roman-numerals/src/Roman.hs +1 -1
- data/tracks/haskell/exercises/run-length-encoding/src/RunLength.hs +2 -2
- data/tracks/haskell/exercises/saddle-points/src/Matrix.hs +1 -1
- data/tracks/haskell/exercises/say/src/Say.hs +1 -1
- data/tracks/haskell/exercises/scrabble-score/src/Scrabble.hs +2 -2
- data/tracks/haskell/exercises/secret-handshake/src/SecretHandshake.hs +1 -1
- data/tracks/haskell/exercises/series/src/Series.hs +1 -1
- data/tracks/haskell/exercises/sgf-parsing/src/Sgf.hs +1 -1
- data/tracks/haskell/exercises/sieve/src/Sieve.hs +1 -1
- data/tracks/haskell/exercises/simple-cipher/src/Cipher.hs +3 -3
- data/tracks/haskell/exercises/simple-linked-list/src/LinkedList.hs +8 -8
- data/tracks/haskell/exercises/space-age/src/SpaceAge.hs +1 -1
- data/tracks/haskell/exercises/strain/src/Strain.hs +2 -2
- data/tracks/haskell/exercises/sublist/src/Sublist.hs +1 -1
- data/tracks/haskell/exercises/sum-of-multiples/src/SumOfMultiples.hs +1 -1
- data/tracks/haskell/exercises/triangle/src/Triangle.hs +1 -1
- data/tracks/haskell/exercises/trinary/src/Trinary.hs +2 -2
- data/tracks/haskell/exercises/word-count/src/WordCount.hs +1 -1
- data/tracks/haskell/exercises/wordy/src/WordProblem.hs +1 -1
- data/tracks/haskell/exercises/zebra-puzzle/src/ZebraPuzzle.hs +1 -1
- data/tracks/haskell/exercises/zipper/src/Zipper.hs +9 -9
- data/tracks/java/docs/MAINTAINING.md +48 -0
- data/tracks/java/exercises/queen-attack/src/test/java/QueenAttackCalculatorTest.java +51 -51
- data/tracks/kotlin/exercises/etl/src/example/kotlin/ETL.kt +1 -1
- data/tracks/kotlin/exercises/etl/src/test/kotlin/ETLTest.kt +19 -19
- data/tracks/kotlin/exercises/pangram/src/test/kotlin/PangramTest.kt +5 -0
- data/tracks/lisp/docs/ABOUT.md +9 -0
- data/tracks/lua/exercises/transpose/example.lua +1 -1
- data/tracks/lua/exercises/transpose/transpose_spec.lua +16 -0
- data/tracks/pascal/config.json +36 -36
- data/tracks/pascal/exercises/bob/uBobTests.pas +0 -1
- data/tracks/pascal/exercises/hamming/uHammingTests.pas +0 -1
- data/tracks/pascal/exercises/leap/uLeapTests.pas +0 -1
- data/tracks/pascal/exercises/saddle-points/uSaddlePointsExample.pas +11 -0
- data/tracks/pascal/exercises/saddle-points/uSaddlePointsTests.pas +9 -1
- data/tracks/perl6/exercises/atbash-cipher/cipher.t +1 -1
- data/tracks/php/config.json +7 -0
- data/tracks/php/exercises/robot-simulator/example.php +148 -0
- data/tracks/php/exercises/robot-simulator/robot-simulator_test.php +168 -0
- data/tracks/pony/config.json +16 -7
- data/tracks/pony/exercises/roman-numerals/example.pony +35 -0
- data/tracks/pony/exercises/roman-numerals/test.pony +45 -0
- data/tracks/python/requirements-travis.txt +1 -1
- data/tracks/ruby/.rubocop.yml +1 -1
- data/tracks/ruby/bin/enable-executable +1 -1
- data/tracks/ruby/bin/executable-tests-check +1 -1
- data/tracks/ruby/exercises/acronym/example.tt +2 -3
- data/tracks/ruby/exercises/all-your-base/example.tt +2 -2
- data/tracks/ruby/exercises/alphametics/example.tt +2 -2
- data/tracks/ruby/exercises/anagram/example.tt +2 -3
- data/tracks/ruby/exercises/binary/example.tt +2 -3
- data/tracks/ruby/exercises/bowling/example.tt +2 -3
- data/tracks/ruby/exercises/bracket-push/example.tt +2 -3
- data/tracks/ruby/exercises/clock/example.tt +2 -3
- data/tracks/ruby/exercises/connect/example.rb +1 -1
- data/tracks/ruby/exercises/connect/example.tt +1 -1
- data/tracks/ruby/exercises/custom-set/example.tt +2 -3
- data/tracks/ruby/exercises/diamond/example.rb +1 -1
- data/tracks/ruby/exercises/difference-of-squares/example.tt +2 -3
- data/tracks/ruby/exercises/dominoes/example.tt +2 -2
- data/tracks/ruby/exercises/gigasecond/example.tt +2 -3
- data/tracks/ruby/exercises/grains/example.tt +2 -2
- data/tracks/ruby/exercises/hamming/example.tt +2 -3
- data/tracks/ruby/exercises/hello-world/example.tt +1 -2
- data/tracks/ruby/exercises/isogram/example.tt +2 -2
- data/tracks/ruby/exercises/largest-series-product/example.tt +2 -4
- data/tracks/ruby/exercises/leap/example.tt +2 -3
- data/tracks/ruby/exercises/nth-prime/example.tt +2 -4
- data/tracks/ruby/exercises/pangram/example.tt +2 -2
- data/tracks/ruby/exercises/queen-attack/example.tt +2 -3
- data/tracks/ruby/exercises/raindrops/example.tt +2 -3
- data/tracks/ruby/exercises/rna-transcription/example.tt +2 -3
- data/tracks/ruby/exercises/roman-numerals/example.tt +2 -3
- data/tracks/ruby/exercises/run-length-encoding/example.tt +2 -3
- data/tracks/ruby/exercises/sieve/example.tt +2 -4
- data/tracks/ruby/exercises/simple-linked-list/simple_linked_list_test.rb +6 -6
- data/tracks/ruby/exercises/tournament/example.tt +2 -3
- data/tracks/ruby/exercises/transpose/example.tt +2 -3
- data/tracks/ruby/exercises/triangle/example.tt +2 -3
- data/tracks/ruby/exercises/two-bucket/example.tt +2 -3
- data/tracks/ruby/exercises/word-count/example.tt +2 -3
- data/tracks/ruby/exercises/wordy/example.tt +2 -2
- data/tracks/ruby/lib/acronym_cases.rb +2 -0
- data/tracks/ruby/lib/all_your_base_cases.rb +3 -1
- data/tracks/ruby/lib/alphametics_cases.rb +6 -4
- data/tracks/ruby/lib/anagram_cases.rb +2 -0
- data/tracks/ruby/lib/binary_cases.rb +2 -0
- data/tracks/ruby/lib/bowling_cases.rb +2 -0
- data/tracks/ruby/lib/bracket_push_cases.rb +2 -0
- data/tracks/ruby/lib/clock_cases.rb +2 -0
- data/tracks/ruby/lib/connect_cases.rb +2 -0
- data/tracks/ruby/lib/custom_set_cases.rb +2 -0
- data/tracks/ruby/lib/difference_of_squares_cases.rb +2 -0
- data/tracks/ruby/lib/dominoes_cases.rb +2 -0
- data/tracks/ruby/lib/exercise_cases.rb +2 -0
- data/tracks/ruby/lib/generator/files/track_files.rb +3 -3
- data/tracks/ruby/lib/generator/files.rb +1 -1
- data/tracks/ruby/lib/generator/template_values.rb +5 -14
- data/tracks/ruby/lib/gigasecond_cases.rb +2 -0
- data/tracks/ruby/lib/grains_cases.rb +3 -1
- data/tracks/ruby/lib/hamming_cases.rb +2 -0
- data/tracks/ruby/lib/hello_world_cases.rb +2 -0
- data/tracks/ruby/lib/isogram_cases.rb +3 -1
- data/tracks/ruby/lib/largest_series_product_cases.rb +2 -0
- data/tracks/ruby/lib/leap_cases.rb +2 -0
- data/tracks/ruby/lib/nth_prime_cases.rb +2 -0
- data/tracks/ruby/lib/pangram_cases.rb +3 -1
- data/tracks/ruby/lib/queen_attack_cases.rb +2 -0
- data/tracks/ruby/lib/raindrops_cases.rb +2 -0
- data/tracks/ruby/lib/rna_transcription_cases.rb +2 -0
- data/tracks/ruby/lib/roman_numerals_cases.rb +2 -0
- data/tracks/ruby/lib/run_length_encoding_cases.rb +2 -0
- data/tracks/ruby/lib/sieve_cases.rb +2 -0
- data/tracks/ruby/lib/tournament_cases.rb +2 -0
- data/tracks/ruby/lib/transpose_cases.rb +2 -0
- data/tracks/ruby/lib/triangle_cases.rb +2 -0
- data/tracks/ruby/lib/two_bucket_cases.rb +2 -0
- data/tracks/ruby/lib/word_count_cases.rb +2 -0
- data/tracks/ruby/lib/wordy_cases.rb +2 -0
- data/tracks/ruby/test/fixtures/xruby/exercises/alpha/example.tt +2 -2
- data/tracks/ruby/test/fixtures/xruby/lib/alpha_cases.rb +1 -1
- data/tracks/ruby/test/generator/command_line_test.rb +1 -1
- data/tracks/ruby/test/generator/template_values_test.rb +7 -7
- data/tracks/rust/.travis.yml +4 -0
- data/tracks/rust/_test/check-exercises.sh +11 -2
- data/tracks/rust/config.json +9 -0
- data/tracks/rust/exercises/luhn/.gitignore +7 -0
- data/tracks/rust/exercises/luhn/Cargo.toml +3 -0
- data/tracks/rust/exercises/luhn/example.rs +13 -0
- data/tracks/rust/exercises/luhn/tests/luhn.rs +38 -0
- data/tracks/rust/exercises/parallel-letter-frequency/HINTS.md +32 -0
- data/tracks/rust/exercises/parallel-letter-frequency/benches/benchmark.rs +99 -0
- data/tracks/scala/config.json +57 -1
- data/tracks/scala/exercises/allergies/build.sbt +2 -2
- data/tracks/scala/exercises/atbash-cipher/build.sbt +2 -2
- data/tracks/scala/exercises/bank-account/build.sbt +3 -2
- data/tracks/scala/exercises/binary-search-tree/build.sbt +2 -2
- data/tracks/scala/exercises/clock/build.sbt +2 -2
- data/tracks/scala/exercises/crypto-square/build.sbt +2 -2
- data/tracks/scala/exercises/custom-set/build.sbt +3 -2
- data/tracks/scala/exercises/food-chain/build.sbt +3 -2
- data/tracks/scala/exercises/house/build.sbt +2 -2
- data/tracks/scala/exercises/kindergarten-garden/build.sbt +3 -2
- data/tracks/scala/exercises/largest-series-product/build.sbt +2 -2
- data/tracks/scala/exercises/linked-list/build.sbt +3 -2
- data/tracks/scala/exercises/matrix/build.sbt +2 -2
- data/tracks/scala/exercises/minesweeper/build.sbt +2 -2
- data/tracks/scala/exercises/nth-prime/build.sbt +2 -2
- data/tracks/scala/exercises/ocr-numbers/build.sbt +2 -2
- data/tracks/scala/exercises/palindrome-products/build.sbt +2 -2
- data/tracks/scala/exercises/prime-factors/build.sbt +3 -2
- data/tracks/scala/exercises/queen-attack/build.sbt +2 -2
- data/tracks/scala/exercises/raindrops/build.sbt +2 -2
- data/tracks/scala/exercises/robot-simulator/build.sbt +2 -2
- data/tracks/scala/exercises/triangle/build.sbt +2 -2
- data/tracks/scala/exercises/trinary/build.sbt +2 -2
- data/tracks/scala/exercises/wordy/build.sbt +3 -3
- metadata +33 -2
@@ -0,0 +1,139 @@
|
|
1
|
+
using Sprache;
|
2
|
+
using System.Collections.Generic;
|
3
|
+
using System.Linq;
|
4
|
+
using System;
|
5
|
+
|
6
|
+
public static class Alphametics
|
7
|
+
{
|
8
|
+
public static IDictionary<char, int> Solve(string equation)
|
9
|
+
{
|
10
|
+
var expression = ExpressionParser.Equation.Parse(equation);
|
11
|
+
|
12
|
+
var maps = GetValidMaps(expression.Chars, expression.StartChars);
|
13
|
+
return maps.First(map => expression.Solve(map) == 0);
|
14
|
+
}
|
15
|
+
|
16
|
+
private static IEnumerable<IDictionary<char, int>> GetValidMaps(HashSet<char> chars, HashSet<char> startChars)
|
17
|
+
=> GetMaps(chars, startChars).Where(map => IsValidMap(map, startChars));
|
18
|
+
|
19
|
+
private static IEnumerable<IDictionary<char, int>> GetMaps(HashSet<char> chars, HashSet<char> startChars)
|
20
|
+
=> GetDigitPermutations(chars.Count).Select(digits => GetMap(digits, chars));
|
21
|
+
|
22
|
+
private static IEnumerable<IEnumerable<int>> GetDigitPermutations(int length)
|
23
|
+
=> Enumerable.Range(0, 10).Permutations(length);
|
24
|
+
|
25
|
+
private static IDictionary<char, int> GetMap(IEnumerable<int> digits, IEnumerable<char> chars)
|
26
|
+
=> digits.Zip(chars, (i, c) => new KeyValuePair<char, int>(c, i)).ToDictionary(x => x.Key, x => x.Value);
|
27
|
+
|
28
|
+
private static bool IsValidMap(IDictionary<char, int> map, IEnumerable<char> startChars) =>
|
29
|
+
!startChars.Any(c => map[c] == 0);
|
30
|
+
}
|
31
|
+
|
32
|
+
public static class EnumerableExtensions
|
33
|
+
{
|
34
|
+
public static IEnumerable<IEnumerable<T>> Permutations<T>(this IEnumerable<T> input, int length)
|
35
|
+
{
|
36
|
+
if (length == 1)
|
37
|
+
return input.Select(t => new T[] { t });
|
38
|
+
|
39
|
+
return Permutations(input, length - 1)
|
40
|
+
.SelectMany(t => input.Where(o => !t.Contains(o)),
|
41
|
+
(t1, t2) => t1.Concat(new T[] { t2 }));
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
public enum ExpressionType
|
46
|
+
{
|
47
|
+
Add,
|
48
|
+
Equal
|
49
|
+
}
|
50
|
+
|
51
|
+
public abstract class Expression
|
52
|
+
{
|
53
|
+
public abstract HashSet<char> Chars { get; }
|
54
|
+
public abstract HashSet<char> StartChars { get; }
|
55
|
+
public abstract int Solve(IDictionary<char, int> mapping);
|
56
|
+
}
|
57
|
+
|
58
|
+
public class PlaceholderExpression : Expression
|
59
|
+
{
|
60
|
+
public PlaceholderExpression(string value)
|
61
|
+
{
|
62
|
+
Value = value;
|
63
|
+
Chars = new HashSet<char>(value);
|
64
|
+
StartChars = new HashSet<char> { value[0] };
|
65
|
+
}
|
66
|
+
|
67
|
+
public override HashSet<char> Chars { get; }
|
68
|
+
public override HashSet<char> StartChars { get; }
|
69
|
+
|
70
|
+
public string Value { get; }
|
71
|
+
|
72
|
+
public static PlaceholderExpression Create(string value) => new PlaceholderExpression(value);
|
73
|
+
|
74
|
+
public override int Solve(IDictionary<char, int> mapping) => Value.Aggregate(0, (acc, x) => acc * 10 + mapping[x]);
|
75
|
+
}
|
76
|
+
|
77
|
+
public abstract class BinaryExpression : Expression
|
78
|
+
{
|
79
|
+
public BinaryExpression(Expression left, Expression right)
|
80
|
+
{
|
81
|
+
Left = left;
|
82
|
+
Right = right;
|
83
|
+
|
84
|
+
Chars = new HashSet<char>(Left.Chars);
|
85
|
+
Chars.UnionWith(Right.Chars);
|
86
|
+
|
87
|
+
StartChars = new HashSet<char>(Left.StartChars);
|
88
|
+
StartChars.UnionWith(Right.StartChars);
|
89
|
+
}
|
90
|
+
|
91
|
+
public Expression Left { get; }
|
92
|
+
public Expression Right { get; }
|
93
|
+
|
94
|
+
public override HashSet<char> Chars { get; }
|
95
|
+
public override HashSet<char> StartChars { get; }
|
96
|
+
|
97
|
+
public static BinaryExpression Create(ExpressionType type, Expression left, Expression right)
|
98
|
+
{
|
99
|
+
switch (type)
|
100
|
+
{
|
101
|
+
case ExpressionType.Add:
|
102
|
+
return new AddExpression(left, right);
|
103
|
+
case ExpressionType.Equal:
|
104
|
+
return new EqualExpression(left, right);
|
105
|
+
default:
|
106
|
+
throw new InvalidOperationException("Invalid expression");
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
public class AddExpression : BinaryExpression
|
112
|
+
{
|
113
|
+
public AddExpression(Expression left, Expression right) : base(left, right)
|
114
|
+
{
|
115
|
+
}
|
116
|
+
|
117
|
+
public override int Solve(IDictionary<char, int> mapping) => Left.Solve(mapping) + Right.Solve(mapping);
|
118
|
+
}
|
119
|
+
|
120
|
+
public class EqualExpression : BinaryExpression
|
121
|
+
{
|
122
|
+
public EqualExpression(Expression left, Expression right) : base(left, right)
|
123
|
+
{
|
124
|
+
}
|
125
|
+
|
126
|
+
public override int Solve(IDictionary<char, int> mapping) => Left.Solve(mapping) - Right.Solve(mapping);
|
127
|
+
}
|
128
|
+
|
129
|
+
public static class ExpressionParser
|
130
|
+
{
|
131
|
+
public static Parser<ExpressionType> Operator(string op, ExpressionType operatorType)
|
132
|
+
=> Parse.String(op).Token().Return(operatorType);
|
133
|
+
|
134
|
+
public static readonly Parser<ExpressionType> Add = Operator("+", ExpressionType.Add);
|
135
|
+
public static readonly Parser<ExpressionType> Equality = Operator("==", ExpressionType.Equal);
|
136
|
+
public static readonly Parser<Expression> Operand = Parse.Upper.AtLeastOnce().Text().Select(PlaceholderExpression.Create);
|
137
|
+
public static readonly Parser<Expression> Expr = Parse.ChainOperator(Add, Operand, BinaryExpression.Create);
|
138
|
+
public static readonly Parser<Expression> Equation = Parse.ChainOperator(Equality, Expr, BinaryExpression.Create);
|
139
|
+
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
using NUnit.Framework;
|
2
|
+
|
3
|
+
public class DotDslTest
|
4
|
+
{
|
5
|
+
[Test]
|
6
|
+
public void Empty_graph()
|
7
|
+
{
|
8
|
+
var g = new Graph();
|
9
|
+
|
10
|
+
Assert.That(g.Nodes, Is.Empty);
|
11
|
+
Assert.That(g.Edges, Is.Empty);
|
12
|
+
Assert.That(g.Attrs, Is.Empty);
|
13
|
+
}
|
14
|
+
|
15
|
+
[Ignore("Remove to run test")]
|
16
|
+
[Test]
|
17
|
+
public void Graph_with_one_node()
|
18
|
+
{
|
19
|
+
var g = new Graph
|
20
|
+
{
|
21
|
+
new Node("a")
|
22
|
+
};
|
23
|
+
|
24
|
+
Assert.That(g.Nodes, Is.EquivalentTo(new[] { new Node("a") }));
|
25
|
+
Assert.That(g.Edges, Is.Empty);
|
26
|
+
Assert.That(g.Attrs, Is.Empty);
|
27
|
+
}
|
28
|
+
|
29
|
+
[Ignore("Remove to run test")]
|
30
|
+
[Test]
|
31
|
+
public void Graph_with_one_node_with_keywords()
|
32
|
+
{
|
33
|
+
var g = new Graph
|
34
|
+
{
|
35
|
+
new Node("a") { { "color", "green" } }
|
36
|
+
};
|
37
|
+
|
38
|
+
Assert.That(g.Nodes, Is.EquivalentTo(new[] { new Node("a") { { "color", "green" } } }));
|
39
|
+
Assert.That(g.Edges, Is.Empty);
|
40
|
+
Assert.That(g.Attrs, Is.Empty);
|
41
|
+
}
|
42
|
+
|
43
|
+
[Ignore("Remove to run test")]
|
44
|
+
[Test]
|
45
|
+
public void Graph_with_one_edge()
|
46
|
+
{
|
47
|
+
var g = new Graph
|
48
|
+
{
|
49
|
+
new Edge("a", "b")
|
50
|
+
};
|
51
|
+
|
52
|
+
Assert.That(g.Nodes, Is.Empty);
|
53
|
+
Assert.That(g.Edges, Is.EquivalentTo(new[] { new Edge("a", "b") }));
|
54
|
+
Assert.That(g.Attrs, Is.Empty);
|
55
|
+
}
|
56
|
+
|
57
|
+
[Ignore("Remove to run test")]
|
58
|
+
[Test]
|
59
|
+
public void Graph_with_one_attribute()
|
60
|
+
{
|
61
|
+
var g = new Graph
|
62
|
+
{
|
63
|
+
{ "foo", "1" }
|
64
|
+
};
|
65
|
+
|
66
|
+
Assert.That(g.Nodes, Is.Empty);
|
67
|
+
Assert.That(g.Edges, Is.Empty);
|
68
|
+
Assert.That(g.Attrs, Is.EquivalentTo(new[] { new Attr("foo", "1") }));
|
69
|
+
}
|
70
|
+
|
71
|
+
[Ignore("Remove to run test")]
|
72
|
+
[Test]
|
73
|
+
public void Graph_with_attributes()
|
74
|
+
{
|
75
|
+
var g = new Graph
|
76
|
+
{
|
77
|
+
{ "foo", "1" },
|
78
|
+
{ "title", "Testing Attrs" },
|
79
|
+
new Node("a") { { "color", "green" } },
|
80
|
+
new Node("c"),
|
81
|
+
new Node("b") { { "label", "Beta!" } },
|
82
|
+
new Edge("b", "c"),
|
83
|
+
new Edge("a", "b") { { "color", "blue" } },
|
84
|
+
{ "bar", "true" }
|
85
|
+
};
|
86
|
+
|
87
|
+
Assert.That(g.Nodes, Is.EquivalentTo(new[] { new Node("a") { { "color", "green" } }, new Node("b") { { "label", "Beta!" } }, new Node("c") }));
|
88
|
+
Assert.That(g.Edges, Is.EquivalentTo(new[] { new Edge("a", "b") { { "color", "blue" } }, new Edge("b", "c") }));
|
89
|
+
Assert.That(g.Attrs, Is.EquivalentTo(new[] { new Attr("bar", "true"), new Attr("foo", "1"), new Attr("title", "Testing Attrs") }));
|
90
|
+
}
|
91
|
+
}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
using System.Collections;
|
2
|
+
using System.Collections.Generic;
|
3
|
+
|
4
|
+
public class Node : Element
|
5
|
+
{
|
6
|
+
public Node(string name)
|
7
|
+
{
|
8
|
+
Name = name;
|
9
|
+
}
|
10
|
+
|
11
|
+
public string Name { get; }
|
12
|
+
|
13
|
+
public override bool Equals(object obj)
|
14
|
+
{
|
15
|
+
if (obj == null || GetType() != obj.GetType())
|
16
|
+
return false;
|
17
|
+
|
18
|
+
return ((Node)obj).Name == Name;
|
19
|
+
}
|
20
|
+
|
21
|
+
public override int GetHashCode() => Name.GetHashCode();
|
22
|
+
}
|
23
|
+
|
24
|
+
public class Edge : Element
|
25
|
+
{
|
26
|
+
public Edge(string node1, string node2)
|
27
|
+
{
|
28
|
+
Node1 = node1;
|
29
|
+
Node2 = node2;
|
30
|
+
}
|
31
|
+
|
32
|
+
public string Node1 { get; }
|
33
|
+
public string Node2 { get; }
|
34
|
+
|
35
|
+
public override bool Equals(object obj)
|
36
|
+
{
|
37
|
+
if (obj == null || GetType() != obj.GetType())
|
38
|
+
return false;
|
39
|
+
|
40
|
+
return ((Edge)obj).Node1 == Node1 && ((Edge)obj).Node2 == Node2;
|
41
|
+
}
|
42
|
+
|
43
|
+
public override int GetHashCode() => Node1.GetHashCode() ^ Node2.GetHashCode();
|
44
|
+
}
|
45
|
+
|
46
|
+
|
47
|
+
public class Attr
|
48
|
+
{
|
49
|
+
public Attr(string key, string value)
|
50
|
+
{
|
51
|
+
Key = key;
|
52
|
+
Value = value;
|
53
|
+
}
|
54
|
+
|
55
|
+
public string Key { get; }
|
56
|
+
public string Value { get; }
|
57
|
+
|
58
|
+
public override bool Equals(object obj)
|
59
|
+
{
|
60
|
+
if (obj == null || GetType() != obj.GetType())
|
61
|
+
return false;
|
62
|
+
|
63
|
+
return ((Attr)obj).Key == Key && ((Attr)obj).Value == Value;
|
64
|
+
}
|
65
|
+
|
66
|
+
public override int GetHashCode() => Key.GetHashCode() ^ Value.GetHashCode();
|
67
|
+
}
|
68
|
+
|
69
|
+
public class Graph : Element
|
70
|
+
{
|
71
|
+
private List<Node> nodes = new List<Node>();
|
72
|
+
private List<Edge> edges = new List<Edge>();
|
73
|
+
|
74
|
+
public IEnumerable<Node> Nodes => nodes;
|
75
|
+
public IEnumerable<Edge> Edges => edges;
|
76
|
+
public IEnumerable<Attr> Attrs => attrs;
|
77
|
+
|
78
|
+
public void Add(Node node) => nodes.Add(node);
|
79
|
+
public void Add(Edge edge) => edges.Add(edge);
|
80
|
+
}
|
81
|
+
|
82
|
+
public abstract class Element : IEnumerable<Attr>
|
83
|
+
{
|
84
|
+
protected List<Attr> attrs = new List<Attr>();
|
85
|
+
|
86
|
+
public void Add(string key, string value) => attrs.Add(new Attr(key, value));
|
87
|
+
|
88
|
+
public IEnumerator<Attr> GetEnumerator() => attrs.GetEnumerator();
|
89
|
+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
90
|
+
}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
using System;
|
2
|
+
using NUnit.Framework;
|
3
|
+
|
4
|
+
[TestFixture]
|
5
|
+
public class ErrorHandlingTest
|
6
|
+
{
|
7
|
+
// Read more about exception handling here:
|
8
|
+
// https://msdn.microsoft.com/en-us/library/ms173162.aspx?f=255&MSPPError=-2147217396
|
9
|
+
[TestCase]
|
10
|
+
public void ThrowException()
|
11
|
+
{
|
12
|
+
Assert.Throws<Exception>(ErrorHandling.HandleErrorByThrowingException);
|
13
|
+
}
|
14
|
+
|
15
|
+
// Read more about nullable types here:
|
16
|
+
// https://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx?f=255&MSPPError=-2147217396
|
17
|
+
[TestCase]
|
18
|
+
[Ignore("Remove to run test")]
|
19
|
+
public void ReturnNullableType()
|
20
|
+
{
|
21
|
+
var successfulResult = ErrorHandling.HandleErrorByReturningNullableType("1");
|
22
|
+
Assert.That(successfulResult, Is.EqualTo(1));
|
23
|
+
|
24
|
+
var failureResult = ErrorHandling.HandleErrorByReturningNullableType("a");
|
25
|
+
Assert.That(failureResult, Is.EqualTo(null));
|
26
|
+
}
|
27
|
+
|
28
|
+
// Read more about out parameters here:
|
29
|
+
// https://msdn.microsoft.com/en-us/library/t3c3bfhx.aspx?f=255&MSPPError=-2147217396
|
30
|
+
[TestCase]
|
31
|
+
[Ignore("Remove to run test")]
|
32
|
+
public void ReturnWithOutParameter()
|
33
|
+
{
|
34
|
+
int result;
|
35
|
+
var successfulResult = ErrorHandling.HandleErrorWithOutParam("1", out result);
|
36
|
+
Assert.That(successfulResult, Is.EqualTo(true));
|
37
|
+
Assert.That(result, Is.EqualTo(1));
|
38
|
+
|
39
|
+
var failureResult = ErrorHandling.HandleErrorWithOutParam("a", out result);
|
40
|
+
Assert.That(failureResult, Is.EqualTo(false));
|
41
|
+
// The value of result is meaningless here (it could be anything) so it shouldn't be used and it's not validated
|
42
|
+
}
|
43
|
+
|
44
|
+
private class DisposableResource : IDisposable
|
45
|
+
{
|
46
|
+
public bool IsDisposed { get; private set; }
|
47
|
+
|
48
|
+
public void Dispose()
|
49
|
+
{
|
50
|
+
IsDisposed = true;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
// Read more about IDisposable here:
|
55
|
+
// https://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx
|
56
|
+
[TestCase]
|
57
|
+
[Ignore("Remove to run test")]
|
58
|
+
public void DisposableObjectsAreDisposedWhenThrowingAnException()
|
59
|
+
{
|
60
|
+
var disposbaleResource = new DisposableResource();
|
61
|
+
|
62
|
+
Assert.Throws<Exception>(() => ErrorHandling.DisposableResourcesAreDisposedWhenExceptionIsThrown(disposbaleResource));
|
63
|
+
Assert.That(disposbaleResource.IsDisposed, Is.EqualTo(true));
|
64
|
+
}
|
65
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
using System;
|
2
|
+
|
3
|
+
public static class ErrorHandling
|
4
|
+
{
|
5
|
+
public static void HandleErrorByThrowingException()
|
6
|
+
{
|
7
|
+
throw new Exception("An error occured.");
|
8
|
+
}
|
9
|
+
|
10
|
+
public static int? HandleErrorByReturningNullableType(string input)
|
11
|
+
{
|
12
|
+
int result;
|
13
|
+
|
14
|
+
if (int.TryParse(input, out result))
|
15
|
+
{
|
16
|
+
return result;
|
17
|
+
}
|
18
|
+
|
19
|
+
return null;
|
20
|
+
}
|
21
|
+
|
22
|
+
public static bool HandleErrorWithOutParam(string input, out int result)
|
23
|
+
{
|
24
|
+
return int.TryParse(input, out result);
|
25
|
+
}
|
26
|
+
|
27
|
+
public static void DisposableResourcesAreDisposedWhenExceptionIsThrown(IDisposable disposableObject)
|
28
|
+
{
|
29
|
+
using (disposableObject)
|
30
|
+
{
|
31
|
+
throw new Exception("An error occured.");
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
@@ -38,7 +38,7 @@
|
|
38
38
|
<Reference Include="Microsoft.CSharp" />
|
39
39
|
</ItemGroup>
|
40
40
|
<ItemGroup>
|
41
|
-
<Compile Include="**\*.cs" Exclude="sgf-parsing\SgfParsing.cs;markdown\Markdown.cs;tree-building\TreeBuilding.cs" />
|
41
|
+
<Compile Include="**\*.cs" Exclude="sgf-parsing\SgfParsing.cs;markdown\Markdown.cs;tree-building\TreeBuilding.cs;ledger\Ledger.cs" />
|
42
42
|
</ItemGroup>
|
43
43
|
<ItemGroup>
|
44
44
|
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
@@ -0,0 +1,85 @@
|
|
1
|
+
using System.Collections.Generic;
|
2
|
+
using System.Linq;
|
3
|
+
|
4
|
+
public delegate void HangmanChangedEventHandler(object sender, HangmanState state);
|
5
|
+
|
6
|
+
public class HangmanState
|
7
|
+
{
|
8
|
+
public HangmanGame.Status Status { get; set; }
|
9
|
+
public int RemainingGuesses { get; set; }
|
10
|
+
public string MaskedWord { get; set; }
|
11
|
+
public HashSet<char> Guesses { get; set; }
|
12
|
+
}
|
13
|
+
|
14
|
+
public class HangmanGame
|
15
|
+
{
|
16
|
+
private const int NumberOfAllowedGuesses = 9;
|
17
|
+
private const char UnguessedCharacterPlaceHolder = '_';
|
18
|
+
|
19
|
+
private readonly string word;
|
20
|
+
private readonly HangmanState state;
|
21
|
+
|
22
|
+
public enum Status
|
23
|
+
{
|
24
|
+
Busy,
|
25
|
+
Win,
|
26
|
+
Lose
|
27
|
+
}
|
28
|
+
|
29
|
+
public HangmanGame(string word)
|
30
|
+
{
|
31
|
+
this.word = word;
|
32
|
+
|
33
|
+
state = new HangmanState
|
34
|
+
{
|
35
|
+
RemainingGuesses = NumberOfAllowedGuesses,
|
36
|
+
Guesses = new HashSet<char>()
|
37
|
+
};
|
38
|
+
|
39
|
+
UpdateMaskedWord();
|
40
|
+
UpdateStatus();
|
41
|
+
}
|
42
|
+
|
43
|
+
public event HangmanChangedEventHandler StateChanged;
|
44
|
+
|
45
|
+
public void Start()
|
46
|
+
{
|
47
|
+
StateChanged?.Invoke(this, state);
|
48
|
+
}
|
49
|
+
|
50
|
+
public void Guess(char c)
|
51
|
+
{
|
52
|
+
UpdateRemainingGuesses(c);
|
53
|
+
UpdateMaskedWord();
|
54
|
+
UpdateStatus();
|
55
|
+
|
56
|
+
StateChanged?.Invoke(this, state);
|
57
|
+
}
|
58
|
+
|
59
|
+
private void UpdateRemainingGuesses(char c)
|
60
|
+
{
|
61
|
+
if (UnknownCharacter(c) || CharacterAlreadyGuessed(c))
|
62
|
+
state.RemainingGuesses--;
|
63
|
+
|
64
|
+
state.Guesses.Add(c);
|
65
|
+
}
|
66
|
+
|
67
|
+
private bool UnknownCharacter(char c) => word.All(x => x != c);
|
68
|
+
|
69
|
+
private bool CharacterAlreadyGuessed(char c) => state.Guesses.Contains(c);
|
70
|
+
|
71
|
+
private void UpdateMaskedWord()
|
72
|
+
{
|
73
|
+
state.MaskedWord = new string(word.Select(c => state.Guesses.Contains(c) ? c : UnguessedCharacterPlaceHolder).ToArray());
|
74
|
+
}
|
75
|
+
|
76
|
+
private void UpdateStatus()
|
77
|
+
{
|
78
|
+
if (state.MaskedWord == word)
|
79
|
+
state.Status = Status.Win;
|
80
|
+
else if (state.RemainingGuesses < 0)
|
81
|
+
state.Status = Status.Lose;
|
82
|
+
else
|
83
|
+
state.Status = Status.Busy;
|
84
|
+
}
|
85
|
+
}
|
@@ -0,0 +1,140 @@
|
|
1
|
+
using NUnit.Framework;
|
2
|
+
|
3
|
+
public class HangmanTest
|
4
|
+
{
|
5
|
+
[Test]
|
6
|
+
public void Initially_9_failures_are_allowed()
|
7
|
+
{
|
8
|
+
var game = new HangmanGame("foo");
|
9
|
+
|
10
|
+
HangmanState lastState = null;
|
11
|
+
game.StateChanged += (sender, state) => lastState = state;
|
12
|
+
|
13
|
+
game.Start();
|
14
|
+
|
15
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
16
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(9));
|
17
|
+
}
|
18
|
+
|
19
|
+
[Ignore("Remove to run test")]
|
20
|
+
[Test]
|
21
|
+
public void Initially_no_letters_are_guessed()
|
22
|
+
{
|
23
|
+
var game = new HangmanGame("foo");
|
24
|
+
|
25
|
+
HangmanState lastState = null;
|
26
|
+
game.StateChanged += (sender, state) => lastState = state;
|
27
|
+
|
28
|
+
game.Start();
|
29
|
+
|
30
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("___"));
|
31
|
+
}
|
32
|
+
|
33
|
+
[Ignore("Remove to run test")]
|
34
|
+
[Test]
|
35
|
+
public void After_10_failures_the_game_is_over()
|
36
|
+
{
|
37
|
+
var game = new HangmanGame("foo");
|
38
|
+
|
39
|
+
HangmanState lastState = null;
|
40
|
+
game.StateChanged += (sender, state) => lastState = state;
|
41
|
+
|
42
|
+
game.Start();
|
43
|
+
|
44
|
+
for (var i = 0; i < 10; i++)
|
45
|
+
{
|
46
|
+
game.Guess('x');
|
47
|
+
}
|
48
|
+
|
49
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Lose));
|
50
|
+
}
|
51
|
+
|
52
|
+
[Ignore("Remove to run test")]
|
53
|
+
[Test]
|
54
|
+
public void Feeding_a_correct_letter_removes_underscores()
|
55
|
+
{
|
56
|
+
var game = new HangmanGame("foobar");
|
57
|
+
|
58
|
+
HangmanState lastState = null;
|
59
|
+
game.StateChanged += (sender, state) => lastState = state;
|
60
|
+
|
61
|
+
game.Start();
|
62
|
+
|
63
|
+
game.Guess('b');
|
64
|
+
|
65
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
66
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(9));
|
67
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("___b__"));
|
68
|
+
|
69
|
+
game.Guess('o');
|
70
|
+
|
71
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
72
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(9));
|
73
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("_oob__"));
|
74
|
+
}
|
75
|
+
|
76
|
+
[Ignore("Remove to run test")]
|
77
|
+
[Test]
|
78
|
+
public void Feeding_a_correct_letter_twice_counts_as_a_failure()
|
79
|
+
{
|
80
|
+
var game = new HangmanGame("foobar");
|
81
|
+
|
82
|
+
HangmanState lastState = null;
|
83
|
+
game.StateChanged += (sender, state) => lastState = state;
|
84
|
+
|
85
|
+
game.Start();
|
86
|
+
|
87
|
+
game.Guess('b');
|
88
|
+
|
89
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
90
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(9));
|
91
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("___b__"));
|
92
|
+
|
93
|
+
game.Guess('b');
|
94
|
+
|
95
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
96
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(8));
|
97
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("___b__"));
|
98
|
+
}
|
99
|
+
|
100
|
+
[Ignore("Remove to run test")]
|
101
|
+
[Test]
|
102
|
+
public void Getting_all_the_letters_right_makes_for_a_win()
|
103
|
+
{
|
104
|
+
var game = new HangmanGame("hello");
|
105
|
+
|
106
|
+
HangmanState lastState = null;
|
107
|
+
game.StateChanged += (sender, state) => lastState = state;
|
108
|
+
|
109
|
+
game.Start();
|
110
|
+
|
111
|
+
game.Guess('b');
|
112
|
+
|
113
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
114
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(8));
|
115
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("_____"));
|
116
|
+
|
117
|
+
game.Guess('e');
|
118
|
+
|
119
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
120
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(8));
|
121
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("_e___"));
|
122
|
+
|
123
|
+
game.Guess('l');
|
124
|
+
|
125
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
126
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(8));
|
127
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("_ell_"));
|
128
|
+
|
129
|
+
game.Guess('o');
|
130
|
+
|
131
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Busy));
|
132
|
+
Assert.That(lastState.RemainingGuesses, Is.EqualTo(8));
|
133
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("_ello"));
|
134
|
+
|
135
|
+
game.Guess('h');
|
136
|
+
|
137
|
+
Assert.That(lastState.Status, Is.EqualTo(HangmanGame.Status.Win));
|
138
|
+
Assert.That(lastState.MaskedWord, Is.EqualTo("hello"));
|
139
|
+
}
|
140
|
+
}
|