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.
Files changed (276) hide show
  1. checksums.yaml +4 -4
  2. data/common/CONTRIBUTING.md +6 -1
  3. data/common/exercises/difference-of-squares/metadata.yml +1 -1
  4. data/common/exercises/luhn/canonical-data.json +2 -2
  5. data/common/exercises/rectangles/canonical-data.json +25 -0
  6. data/common/exercises/rectangles/description.md +11 -3
  7. data/lib/trackler/version.rb +1 -1
  8. data/tracks/ceylon/config.json +9 -0
  9. data/tracks/ceylon/exercises/anagram/source/anagram/AnagramTest.ceylon +38 -39
  10. data/tracks/ceylon/exercises/bracket-push/source/bracketpush/BracketsTest.ceylon +28 -29
  11. data/tracks/ceylon/exercises/largest-series-product/example/Series.ceylon +13 -0
  12. data/tracks/ceylon/exercises/largest-series-product/source/largestseriesproduct/Series.ceylon +5 -0
  13. data/tracks/ceylon/exercises/largest-series-product/source/largestseriesproduct/SeriesTest.ceylon +30 -0
  14. data/tracks/ceylon/exercises/largest-series-product/source/largestseriesproduct/module.ceylon +3 -0
  15. data/tracks/csharp/config.json +41 -0
  16. data/tracks/csharp/exercises/alphametics/AlphameticsTest.cs +122 -0
  17. data/tracks/csharp/exercises/alphametics/Example.cs +139 -0
  18. data/tracks/csharp/exercises/dot-dsl/DotDslTest.cs +91 -0
  19. data/tracks/csharp/exercises/dot-dsl/Example.cs +90 -0
  20. data/tracks/csharp/exercises/dot-dsl/HINTS.md +2 -0
  21. data/tracks/csharp/exercises/error-handling/ErrorHandlingTest.cs +65 -0
  22. data/tracks/csharp/exercises/error-handling/Example.cs +34 -0
  23. data/tracks/csharp/exercises/exercises.csproj +1 -1
  24. data/tracks/csharp/exercises/hangman/Example.cs +85 -0
  25. data/tracks/csharp/exercises/hangman/HangmanTest.cs +140 -0
  26. data/tracks/csharp/exercises/ledger/Example.cs +106 -0
  27. data/tracks/csharp/exercises/ledger/Ledger.cs +166 -0
  28. data/tracks/csharp/exercises/ledger/LedgerTest.cs +168 -0
  29. data/tracks/elixir/exercises/allergies/allergies_test.exs +2 -2
  30. data/tracks/elixir/exercises/markdown/example.exs +3 -3
  31. data/tracks/elixir/exercises/phone-number/example.exs +0 -2
  32. data/tracks/elixir/exercises/queen-attack/example.exs +1 -1
  33. data/tracks/elixir/exercises/wordy/example.exs +6 -6
  34. data/tracks/elixir/exercises/zipper/zipper_test.exs +12 -12
  35. data/tracks/elixir/mix.exs +1 -1
  36. data/tracks/fsharp/config.json +8 -8
  37. data/tracks/fsharp/docs/ABOUT.md +4 -0
  38. data/tracks/fsharp/exercises/alphametics/AlphameticsTest.fs +33 -13
  39. data/tracks/fsharp/exercises/alphametics/Example.fs +29 -64
  40. data/tracks/fsharp/exercises/binary-search-tree/BinarySearchTreeTest.fs +14 -14
  41. data/tracks/fsharp/exercises/binary-search-tree/Example.fs +17 -14
  42. data/tracks/fsharp/exercises/triangle/TriangleTest.fs +0 -5
  43. data/tracks/go/README.md +3 -3
  44. data/tracks/go/config.json +10 -3
  45. data/tracks/go/exercises/acronym/acronym.go +5 -0
  46. data/tracks/go/exercises/bob/example_gen.go +1 -1
  47. data/tracks/go/exercises/clock/example_gen.go +1 -1
  48. data/tracks/go/exercises/connect/example_gen.go +1 -1
  49. data/tracks/go/exercises/custom-set/example_gen.go +1 -1
  50. data/tracks/go/exercises/gigasecond/example_gen.go +1 -1
  51. data/tracks/go/exercises/hamming/example_gen.go +1 -1
  52. data/tracks/go/exercises/largest-series-product/example_gen.go +1 -1
  53. data/tracks/go/exercises/leap/cases_test.go +5 -7
  54. data/tracks/go/exercises/leap/example.go +1 -1
  55. data/tracks/go/exercises/leap/example_gen.go +1 -1
  56. data/tracks/go/exercises/leap/leap.go +1 -1
  57. data/tracks/go/exercises/leap/leap_test.go +1 -1
  58. data/tracks/go/exercises/meetup/example_gen.go +1 -1
  59. data/tracks/go/exercises/nucleotide-count/nucleotide_count_test.go +0 -5
  60. data/tracks/go/exercises/pangram/pangram.go +5 -0
  61. data/tracks/go/exercises/raindrops/example_gen.go +1 -1
  62. data/tracks/go/exercises/rna-transcription/example_gen.go +1 -1
  63. data/tracks/go/exercises/roman-numerals/example_gen.go +1 -1
  64. data/tracks/go/exercises/word-count/example_gen.go +1 -1
  65. data/tracks/go/gen/gen.go +3 -2
  66. data/tracks/haskell/exercises/accumulate/src/Accumulate.hs +1 -1
  67. data/tracks/haskell/exercises/all-your-base/src/Base.hs +1 -1
  68. data/tracks/haskell/exercises/allergies/src/Allergies.hs +2 -2
  69. data/tracks/haskell/exercises/alphametics/src/Alphametics.hs +1 -1
  70. data/tracks/haskell/exercises/anagram/src/Anagram.hs +1 -1
  71. data/tracks/haskell/exercises/atbash-cipher/src/Atbash.hs +2 -2
  72. data/tracks/haskell/exercises/bank-account/src/BankAccount.hs +4 -4
  73. data/tracks/haskell/exercises/binary/src/Binary.hs +1 -1
  74. data/tracks/haskell/exercises/binary-search-tree/src/BST.hs +8 -8
  75. data/tracks/haskell/exercises/bob/src/Bob.hs +1 -1
  76. data/tracks/haskell/exercises/bowling/src/Bowling.hs +1 -1
  77. data/tracks/haskell/exercises/change/src/Change.hs +1 -1
  78. data/tracks/haskell/exercises/clock/src/Clock.hs +4 -4
  79. data/tracks/haskell/exercises/connect/src/Connect.hs +1 -1
  80. data/tracks/haskell/exercises/crypto-square/src/CryptoSquare.hs +1 -1
  81. data/tracks/haskell/exercises/custom-set/src/CustomSet.hs +13 -13
  82. data/tracks/haskell/exercises/difference-of-squares/src/Squares.hs +3 -3
  83. data/tracks/haskell/exercises/dominoes/src/Dominoes.hs +1 -1
  84. data/tracks/haskell/exercises/etl/src/ETL.hs +1 -1
  85. data/tracks/haskell/exercises/forth/src/Forth.hs +3 -3
  86. data/tracks/haskell/exercises/gigasecond/src/Gigasecond.hs +1 -1
  87. data/tracks/haskell/exercises/go-counting/src/Counting.hs +2 -2
  88. data/tracks/haskell/exercises/grade-school/src/School.hs +4 -4
  89. data/tracks/haskell/exercises/grains/src/Grains.hs +2 -2
  90. data/tracks/haskell/exercises/hamming/src/Hamming.hs +1 -1
  91. data/tracks/haskell/exercises/hexadecimal/src/Hexadecimal.hs +1 -1
  92. data/tracks/haskell/exercises/kindergarten-garden/src/Garden.hs +3 -3
  93. data/tracks/haskell/exercises/largest-series-product/src/Series.hs +1 -1
  94. data/tracks/haskell/exercises/leap/src/LeapYear.hs +1 -1
  95. data/tracks/haskell/exercises/lens-person/src/Person.hs +4 -4
  96. data/tracks/haskell/exercises/linked-list/src/Deque.hs +5 -5
  97. data/tracks/haskell/exercises/list-ops/src/ListOps.hs +8 -8
  98. data/tracks/haskell/exercises/luhn/src/Luhn.hs +5 -5
  99. data/tracks/haskell/exercises/matrix/src/Matrix.hs +10 -10
  100. data/tracks/haskell/exercises/meetup/src/Meetup.hs +1 -1
  101. data/tracks/haskell/exercises/minesweeper/src/Minesweeper.hs +1 -1
  102. data/tracks/haskell/exercises/nth-prime/src/Prime.hs +1 -1
  103. data/tracks/haskell/exercises/nucleotide-count/src/DNA.hs +2 -2
  104. data/tracks/haskell/exercises/ocr-numbers/src/OCR.hs +1 -1
  105. data/tracks/haskell/exercises/octal/src/Octal.hs +2 -2
  106. data/tracks/haskell/exercises/palindrome-products/src/Palindromes.hs +2 -2
  107. data/tracks/haskell/exercises/parallel-letter-frequency/src/Frequency.hs +1 -1
  108. data/tracks/haskell/exercises/pascals-triangle/src/Triangle.hs +1 -1
  109. data/tracks/haskell/exercises/phone-number/src/Phone.hs +3 -3
  110. data/tracks/haskell/exercises/pig-latin/src/PigLatin.hs +1 -1
  111. data/tracks/haskell/exercises/pov/src/POV.hs +2 -2
  112. data/tracks/haskell/exercises/prime-factors/src/PrimeFactors.hs +1 -1
  113. data/tracks/haskell/exercises/pythagorean-triplet/src/Triplet.hs +3 -3
  114. data/tracks/haskell/exercises/queen-attack/src/Queens.hs +2 -2
  115. data/tracks/haskell/exercises/raindrops/src/Raindrops.hs +1 -1
  116. data/tracks/haskell/exercises/rna-transcription/src/DNA.hs +1 -1
  117. data/tracks/haskell/exercises/robot-name/src/Robot.hs +3 -3
  118. data/tracks/haskell/exercises/robot-simulator/src/Robot.hs +6 -6
  119. data/tracks/haskell/exercises/roman-numerals/src/Roman.hs +1 -1
  120. data/tracks/haskell/exercises/run-length-encoding/src/RunLength.hs +2 -2
  121. data/tracks/haskell/exercises/saddle-points/src/Matrix.hs +1 -1
  122. data/tracks/haskell/exercises/say/src/Say.hs +1 -1
  123. data/tracks/haskell/exercises/scrabble-score/src/Scrabble.hs +2 -2
  124. data/tracks/haskell/exercises/secret-handshake/src/SecretHandshake.hs +1 -1
  125. data/tracks/haskell/exercises/series/src/Series.hs +1 -1
  126. data/tracks/haskell/exercises/sgf-parsing/src/Sgf.hs +1 -1
  127. data/tracks/haskell/exercises/sieve/src/Sieve.hs +1 -1
  128. data/tracks/haskell/exercises/simple-cipher/src/Cipher.hs +3 -3
  129. data/tracks/haskell/exercises/simple-linked-list/src/LinkedList.hs +8 -8
  130. data/tracks/haskell/exercises/space-age/src/SpaceAge.hs +1 -1
  131. data/tracks/haskell/exercises/strain/src/Strain.hs +2 -2
  132. data/tracks/haskell/exercises/sublist/src/Sublist.hs +1 -1
  133. data/tracks/haskell/exercises/sum-of-multiples/src/SumOfMultiples.hs +1 -1
  134. data/tracks/haskell/exercises/triangle/src/Triangle.hs +1 -1
  135. data/tracks/haskell/exercises/trinary/src/Trinary.hs +2 -2
  136. data/tracks/haskell/exercises/word-count/src/WordCount.hs +1 -1
  137. data/tracks/haskell/exercises/wordy/src/WordProblem.hs +1 -1
  138. data/tracks/haskell/exercises/zebra-puzzle/src/ZebraPuzzle.hs +1 -1
  139. data/tracks/haskell/exercises/zipper/src/Zipper.hs +9 -9
  140. data/tracks/java/docs/MAINTAINING.md +48 -0
  141. data/tracks/java/exercises/queen-attack/src/test/java/QueenAttackCalculatorTest.java +51 -51
  142. data/tracks/kotlin/exercises/etl/src/example/kotlin/ETL.kt +1 -1
  143. data/tracks/kotlin/exercises/etl/src/test/kotlin/ETLTest.kt +19 -19
  144. data/tracks/kotlin/exercises/pangram/src/test/kotlin/PangramTest.kt +5 -0
  145. data/tracks/lisp/docs/ABOUT.md +9 -0
  146. data/tracks/lua/exercises/transpose/example.lua +1 -1
  147. data/tracks/lua/exercises/transpose/transpose_spec.lua +16 -0
  148. data/tracks/pascal/config.json +36 -36
  149. data/tracks/pascal/exercises/bob/uBobTests.pas +0 -1
  150. data/tracks/pascal/exercises/hamming/uHammingTests.pas +0 -1
  151. data/tracks/pascal/exercises/leap/uLeapTests.pas +0 -1
  152. data/tracks/pascal/exercises/saddle-points/uSaddlePointsExample.pas +11 -0
  153. data/tracks/pascal/exercises/saddle-points/uSaddlePointsTests.pas +9 -1
  154. data/tracks/perl6/exercises/atbash-cipher/cipher.t +1 -1
  155. data/tracks/php/config.json +7 -0
  156. data/tracks/php/exercises/robot-simulator/example.php +148 -0
  157. data/tracks/php/exercises/robot-simulator/robot-simulator_test.php +168 -0
  158. data/tracks/pony/config.json +16 -7
  159. data/tracks/pony/exercises/roman-numerals/example.pony +35 -0
  160. data/tracks/pony/exercises/roman-numerals/test.pony +45 -0
  161. data/tracks/python/requirements-travis.txt +1 -1
  162. data/tracks/ruby/.rubocop.yml +1 -1
  163. data/tracks/ruby/bin/enable-executable +1 -1
  164. data/tracks/ruby/bin/executable-tests-check +1 -1
  165. data/tracks/ruby/exercises/acronym/example.tt +2 -3
  166. data/tracks/ruby/exercises/all-your-base/example.tt +2 -2
  167. data/tracks/ruby/exercises/alphametics/example.tt +2 -2
  168. data/tracks/ruby/exercises/anagram/example.tt +2 -3
  169. data/tracks/ruby/exercises/binary/example.tt +2 -3
  170. data/tracks/ruby/exercises/bowling/example.tt +2 -3
  171. data/tracks/ruby/exercises/bracket-push/example.tt +2 -3
  172. data/tracks/ruby/exercises/clock/example.tt +2 -3
  173. data/tracks/ruby/exercises/connect/example.rb +1 -1
  174. data/tracks/ruby/exercises/connect/example.tt +1 -1
  175. data/tracks/ruby/exercises/custom-set/example.tt +2 -3
  176. data/tracks/ruby/exercises/diamond/example.rb +1 -1
  177. data/tracks/ruby/exercises/difference-of-squares/example.tt +2 -3
  178. data/tracks/ruby/exercises/dominoes/example.tt +2 -2
  179. data/tracks/ruby/exercises/gigasecond/example.tt +2 -3
  180. data/tracks/ruby/exercises/grains/example.tt +2 -2
  181. data/tracks/ruby/exercises/hamming/example.tt +2 -3
  182. data/tracks/ruby/exercises/hello-world/example.tt +1 -2
  183. data/tracks/ruby/exercises/isogram/example.tt +2 -2
  184. data/tracks/ruby/exercises/largest-series-product/example.tt +2 -4
  185. data/tracks/ruby/exercises/leap/example.tt +2 -3
  186. data/tracks/ruby/exercises/nth-prime/example.tt +2 -4
  187. data/tracks/ruby/exercises/pangram/example.tt +2 -2
  188. data/tracks/ruby/exercises/queen-attack/example.tt +2 -3
  189. data/tracks/ruby/exercises/raindrops/example.tt +2 -3
  190. data/tracks/ruby/exercises/rna-transcription/example.tt +2 -3
  191. data/tracks/ruby/exercises/roman-numerals/example.tt +2 -3
  192. data/tracks/ruby/exercises/run-length-encoding/example.tt +2 -3
  193. data/tracks/ruby/exercises/sieve/example.tt +2 -4
  194. data/tracks/ruby/exercises/simple-linked-list/simple_linked_list_test.rb +6 -6
  195. data/tracks/ruby/exercises/tournament/example.tt +2 -3
  196. data/tracks/ruby/exercises/transpose/example.tt +2 -3
  197. data/tracks/ruby/exercises/triangle/example.tt +2 -3
  198. data/tracks/ruby/exercises/two-bucket/example.tt +2 -3
  199. data/tracks/ruby/exercises/word-count/example.tt +2 -3
  200. data/tracks/ruby/exercises/wordy/example.tt +2 -2
  201. data/tracks/ruby/lib/acronym_cases.rb +2 -0
  202. data/tracks/ruby/lib/all_your_base_cases.rb +3 -1
  203. data/tracks/ruby/lib/alphametics_cases.rb +6 -4
  204. data/tracks/ruby/lib/anagram_cases.rb +2 -0
  205. data/tracks/ruby/lib/binary_cases.rb +2 -0
  206. data/tracks/ruby/lib/bowling_cases.rb +2 -0
  207. data/tracks/ruby/lib/bracket_push_cases.rb +2 -0
  208. data/tracks/ruby/lib/clock_cases.rb +2 -0
  209. data/tracks/ruby/lib/connect_cases.rb +2 -0
  210. data/tracks/ruby/lib/custom_set_cases.rb +2 -0
  211. data/tracks/ruby/lib/difference_of_squares_cases.rb +2 -0
  212. data/tracks/ruby/lib/dominoes_cases.rb +2 -0
  213. data/tracks/ruby/lib/exercise_cases.rb +2 -0
  214. data/tracks/ruby/lib/generator/files/track_files.rb +3 -3
  215. data/tracks/ruby/lib/generator/files.rb +1 -1
  216. data/tracks/ruby/lib/generator/template_values.rb +5 -14
  217. data/tracks/ruby/lib/gigasecond_cases.rb +2 -0
  218. data/tracks/ruby/lib/grains_cases.rb +3 -1
  219. data/tracks/ruby/lib/hamming_cases.rb +2 -0
  220. data/tracks/ruby/lib/hello_world_cases.rb +2 -0
  221. data/tracks/ruby/lib/isogram_cases.rb +3 -1
  222. data/tracks/ruby/lib/largest_series_product_cases.rb +2 -0
  223. data/tracks/ruby/lib/leap_cases.rb +2 -0
  224. data/tracks/ruby/lib/nth_prime_cases.rb +2 -0
  225. data/tracks/ruby/lib/pangram_cases.rb +3 -1
  226. data/tracks/ruby/lib/queen_attack_cases.rb +2 -0
  227. data/tracks/ruby/lib/raindrops_cases.rb +2 -0
  228. data/tracks/ruby/lib/rna_transcription_cases.rb +2 -0
  229. data/tracks/ruby/lib/roman_numerals_cases.rb +2 -0
  230. data/tracks/ruby/lib/run_length_encoding_cases.rb +2 -0
  231. data/tracks/ruby/lib/sieve_cases.rb +2 -0
  232. data/tracks/ruby/lib/tournament_cases.rb +2 -0
  233. data/tracks/ruby/lib/transpose_cases.rb +2 -0
  234. data/tracks/ruby/lib/triangle_cases.rb +2 -0
  235. data/tracks/ruby/lib/two_bucket_cases.rb +2 -0
  236. data/tracks/ruby/lib/word_count_cases.rb +2 -0
  237. data/tracks/ruby/lib/wordy_cases.rb +2 -0
  238. data/tracks/ruby/test/fixtures/xruby/exercises/alpha/example.tt +2 -2
  239. data/tracks/ruby/test/fixtures/xruby/lib/alpha_cases.rb +1 -1
  240. data/tracks/ruby/test/generator/command_line_test.rb +1 -1
  241. data/tracks/ruby/test/generator/template_values_test.rb +7 -7
  242. data/tracks/rust/.travis.yml +4 -0
  243. data/tracks/rust/_test/check-exercises.sh +11 -2
  244. data/tracks/rust/config.json +9 -0
  245. data/tracks/rust/exercises/luhn/.gitignore +7 -0
  246. data/tracks/rust/exercises/luhn/Cargo.toml +3 -0
  247. data/tracks/rust/exercises/luhn/example.rs +13 -0
  248. data/tracks/rust/exercises/luhn/tests/luhn.rs +38 -0
  249. data/tracks/rust/exercises/parallel-letter-frequency/HINTS.md +32 -0
  250. data/tracks/rust/exercises/parallel-letter-frequency/benches/benchmark.rs +99 -0
  251. data/tracks/scala/config.json +57 -1
  252. data/tracks/scala/exercises/allergies/build.sbt +2 -2
  253. data/tracks/scala/exercises/atbash-cipher/build.sbt +2 -2
  254. data/tracks/scala/exercises/bank-account/build.sbt +3 -2
  255. data/tracks/scala/exercises/binary-search-tree/build.sbt +2 -2
  256. data/tracks/scala/exercises/clock/build.sbt +2 -2
  257. data/tracks/scala/exercises/crypto-square/build.sbt +2 -2
  258. data/tracks/scala/exercises/custom-set/build.sbt +3 -2
  259. data/tracks/scala/exercises/food-chain/build.sbt +3 -2
  260. data/tracks/scala/exercises/house/build.sbt +2 -2
  261. data/tracks/scala/exercises/kindergarten-garden/build.sbt +3 -2
  262. data/tracks/scala/exercises/largest-series-product/build.sbt +2 -2
  263. data/tracks/scala/exercises/linked-list/build.sbt +3 -2
  264. data/tracks/scala/exercises/matrix/build.sbt +2 -2
  265. data/tracks/scala/exercises/minesweeper/build.sbt +2 -2
  266. data/tracks/scala/exercises/nth-prime/build.sbt +2 -2
  267. data/tracks/scala/exercises/ocr-numbers/build.sbt +2 -2
  268. data/tracks/scala/exercises/palindrome-products/build.sbt +2 -2
  269. data/tracks/scala/exercises/prime-factors/build.sbt +3 -2
  270. data/tracks/scala/exercises/queen-attack/build.sbt +2 -2
  271. data/tracks/scala/exercises/raindrops/build.sbt +2 -2
  272. data/tracks/scala/exercises/robot-simulator/build.sbt +2 -2
  273. data/tracks/scala/exercises/triangle/build.sbt +2 -2
  274. data/tracks/scala/exercises/trinary/build.sbt +2 -2
  275. data/tracks/scala/exercises/wordy/build.sbt +3 -3
  276. 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,2 @@
1
+ ## Hints
2
+ This exercise requires you to implement classes with a custom equality check. For more information, see [this page](https://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx).
@@ -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
+ }