trackler 2.0.8.19 → 2.0.8.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/phone-number/canonical-data.json +2 -2
  3. data/lib/trackler/version.rb +1 -1
  4. data/tracks/c/config.json +7 -0
  5. data/tracks/c/exercises/react/makefile +16 -0
  6. data/tracks/c/exercises/react/src/example.c +185 -0
  7. data/tracks/c/exercises/react/src/react.h +29 -0
  8. data/tracks/c/exercises/react/test/test_react.c +324 -0
  9. data/tracks/c/exercises/react/test/vendor/unity.c +1300 -0
  10. data/tracks/c/exercises/react/test/vendor/unity.h +274 -0
  11. data/tracks/c/exercises/react/test/vendor/unity_internals.h +701 -0
  12. data/tracks/csharp/.travis.yml +2 -9
  13. data/tracks/csharp/appveyor.yml +3 -3
  14. data/tracks/csharp/build.cake +13 -4
  15. data/tracks/csharp/build.ps1 +56 -164
  16. data/tracks/csharp/build.sh +33 -78
  17. data/tracks/csharp/circle.yml +2 -4
  18. data/tracks/csharp/config.json +2 -1
  19. data/tracks/csharp/exercises/leap/LeapTest.cs +8 -8
  20. data/tracks/csharp/generators/CanonicalData.cs +19 -0
  21. data/tracks/csharp/generators/CanonicalDataCase.cs +24 -0
  22. data/tracks/csharp/generators/CanonicalDataCaseJsonConverter.cs +32 -0
  23. data/tracks/csharp/generators/CanonicalDataCasesJsonConverter.cs +30 -0
  24. data/tracks/csharp/generators/CanonicalDataParser.cs +28 -0
  25. data/tracks/csharp/generators/ExerciseCollection.cs +23 -0
  26. data/tracks/csharp/generators/Exercises/Exercise.cs +14 -0
  27. data/tracks/csharp/generators/Exercises/LeapExercise.cs +35 -0
  28. data/tracks/csharp/generators/Generators.csproj +12 -0
  29. data/tracks/csharp/generators/Generators.csproj.user +6 -0
  30. data/tracks/csharp/generators/Generators.sln +22 -0
  31. data/tracks/csharp/generators/Program.cs +59 -0
  32. data/tracks/csharp/generators/TestClass.cs +13 -0
  33. data/tracks/csharp/generators/TestClassRenderer.cs +36 -0
  34. data/tracks/csharp/generators/TestMethod.cs +9 -0
  35. data/tracks/csharp/generators/TestMethodNameTransformer.cs +11 -0
  36. data/tracks/csharp/generators/TestMethodRenderer.cs +18 -0
  37. data/tracks/csharp/generators/To.cs +7 -0
  38. data/tracks/csharp/generators/generate.ps1 +2 -0
  39. data/tracks/csharp/generators/generate.sh +4 -0
  40. data/tracks/delphi/config.json +8 -0
  41. data/tracks/delphi/exercises/phone-number/uPhoneNumberExample.pas +6 -6
  42. data/tracks/delphi/exercises/phone-number/uPhoneNumberTests.pas +28 -17
  43. data/tracks/delphi/exercises/roman-numerals/RomanNumerals.dpr +60 -0
  44. data/tracks/delphi/exercises/roman-numerals/uRomanNumeralsExample.pas +49 -0
  45. data/tracks/delphi/exercises/roman-numerals/uRomanNumeralsTest.pas +216 -0
  46. data/tracks/elixir/config.json +22 -0
  47. data/tracks/elixir/exercises/poker/example.exs +136 -0
  48. data/tracks/elixir/exercises/poker/poker.exs +34 -0
  49. data/tracks/elixir/exercises/poker/poker_test.exs +217 -0
  50. data/tracks/elixir/exercises/protein-translation/example.exs +62 -0
  51. data/tracks/elixir/exercises/protein-translation/protein_translation.exs +34 -0
  52. data/tracks/elixir/exercises/protein-translation/protein_translation_test.exs +87 -0
  53. data/tracks/elixir/exercises/say/example.exs +139 -0
  54. data/tracks/elixir/exercises/say/say.exs +8 -0
  55. data/tracks/elixir/exercises/say/say_test.exs +85 -0
  56. data/tracks/go/exercises/robot-name/example.go +2 -0
  57. data/tracks/go/exercises/robot-name/robot_name_test.go +9 -1
  58. data/tracks/go/exercises/roman-numerals/roman_numerals_test.go +4 -1
  59. data/tracks/go/exercises/saddle-points/saddle_points_test.go +6 -6
  60. data/tracks/php/config.json +7 -0
  61. data/tracks/php/exercises/grade-school/example.php +35 -0
  62. data/tracks/php/exercises/grade-school/grade-school_test.php +84 -0
  63. metadata +43 -2
@@ -27,6 +27,14 @@
27
27
  "string processing"
28
28
  ]
29
29
  },
30
+ {
31
+ "slug": "protein-translation",
32
+ "difficulty": 2,
33
+ "topics": [
34
+ "pattern matching",
35
+ "string processing"
36
+ ]
37
+ },
30
38
  {
31
39
  "slug": "space-age",
32
40
  "difficulty": 2,
@@ -400,6 +408,13 @@
400
408
  "topics": [
401
409
  ]
402
410
  },
411
+ {
412
+ "slug": "poker",
413
+ "difficulty": 7,
414
+ "topics": [
415
+ "sorting"
416
+ ]
417
+ },
403
418
  {
404
419
  "slug": "bowling",
405
420
  "difficulty": 8,
@@ -442,6 +457,13 @@
442
457
  "Strings",
443
458
  "Enumerations"
444
459
  ]
460
+ },
461
+ {
462
+ "slug": "say",
463
+ "difficulty": 3,
464
+ "topics": [
465
+ "Pattern Matching"
466
+ ]
445
467
  }
446
468
  ],
447
469
  "deprecated": [
@@ -0,0 +1,136 @@
1
+ defmodule Poker do
2
+ @doc """
3
+ Given a list of poker hands, return a list containing the highest scoring hand.
4
+
5
+ If two or more hands tie, return the list of tied hands in the order they were received.
6
+
7
+ The basic rules and hand rankings for Poker can be found at:
8
+
9
+ https://en.wikipedia.org/wiki/List_of_poker_hands
10
+
11
+ For this exercise, we'll consider the game to be using no Jokers,
12
+ so five-of-a-kind hands will not be tested. We will also consider
13
+ the game to be using multiple decks, so it is possible for multiple
14
+ players to have identical cards.
15
+
16
+ Aces can be used in low (A 2 3 4 5) or high (10 J Q K A) straights, but do not count as
17
+ a high card in the former case.
18
+
19
+ For example, (A 2 3 4 5) will lose to (2 3 4 5 6).
20
+
21
+ You can also assume all inputs will be valid, and do not need to perform error checking
22
+ when parsing card values. All hands will be a list of 5 strings, containing a number
23
+ (or letter) for the rank, followed by the suit.
24
+
25
+ Ranks (lowest to highest): 2 3 4 5 6 7 8 9 10 J Q K A
26
+ Suits (order doesn't matter): C D H S
27
+
28
+ Example hand: ~w(4S 5H 4C 5D 4H) # Full house, 5s over 4s
29
+ """
30
+ @spec best_hand(list(list(String.t()))) :: list(list(String.t()))
31
+ def best_hand(hands) do
32
+ sorted_hands = hands
33
+ |> Enum.map(&score_hand/1)
34
+ |> Enum.sort(&sort_scored_hands/2)
35
+
36
+ [{_, highest_score, highest_extra} | _] = sorted_hands
37
+
38
+ highest_args = {highest_score, highest_extra}
39
+
40
+ sorted_hands
41
+ |> Enum.group_by(fn {_hand, score, extra} -> {score, extra} end)
42
+ |> Map.get(highest_args)
43
+ |> Enum.map(fn {hand, _score, _extra} -> hand end)
44
+ end
45
+
46
+ @ranks ~w(2 3 4 5 6 7 8 9 10 J Q K A)
47
+ @suits ~w(clubs diamonds hearts spades)a
48
+ @scores ~w(straight_flush four_of_a_kind full_house flush straight three_of_a_kind two_pair pair high_card)a
49
+
50
+ for {rank, value} <- Enum.with_index(@ranks, 2), suit <- @suits do
51
+ suit_char = suit |> to_string |> String.upcase |> String.first
52
+
53
+ defp card(<< unquote(rank), unquote(suit_char) >>), do: {unquote(value), unquote(suit)}
54
+ end
55
+
56
+ defp score_hand(hand) do
57
+ {ranks, suits} = hand
58
+ |> Enum.map(&card/1)
59
+ |> Enum.sort(&sort_rank_asc/2)
60
+ |> Enum.unzip
61
+
62
+ flush = suits |> Enum.uniq |> length |> Kernel.==(1)
63
+
64
+ ranks
65
+ |> Enum.group_by(fn x -> x end)
66
+ |> Enum.into(%{}, fn {k, v} -> {k, length(v)} end)
67
+ |> Enum.sort(&sort_count_then_rank_asc/2)
68
+ |> score_hand(ranks, flush)
69
+ |> Tuple.insert_at(0, hand)
70
+ end
71
+
72
+ defp score_hand(_, [2, 3, 4, 5, 14], true), do: {:straight_flush, {5}}
73
+ defp score_hand(_, [2, 3, 4, 5, 14], _), do: {:straight, {5}}
74
+ defp score_hand(counts, [low, _, _, _, high], true) when length(counts) == 5 and high-low == 4, do: {:straight_flush, {high}}
75
+ defp score_hand(counts, [low, _, _, _, high], _) when length(counts) == 5 and high-low == 4, do: {:straight, {high}}
76
+ defp score_hand(_, ranks, true), do: {:flush, {ranks |> Enum.sort |> Enum.reverse}}
77
+ defp score_hand([{kicker, 1}, {high, 4}], _, _), do: {:four_of_a_kind, {high, kicker}}
78
+ defp score_hand([{pair, 2}, {triplet, 3}], _, _), do: {:full_house, {triplet, pair}}
79
+ defp score_hand([{kicker1, 1}, {kicker2, 1}, {triplet, 3}], _, _), do: {:three_of_a_kind, {triplet, [ kicker1, kicker2 ] |> Enum.sort |> Enum.reverse}}
80
+ defp score_hand([{kicker, 1}, {low_pair, 2}, {high_pair, 2}], _, _), do: {:two_pair, {high_pair, low_pair, kicker}}
81
+ defp score_hand([{kicker1, 1}, {kicker2, 1}, {kicker3, 1}, {pair, 2}], _, _), do: {:pair, {pair, [ kicker1, kicker2, kicker3 ] |> Enum.sort |> Enum.reverse}}
82
+ defp score_hand(_, ranks, _), do: {:high_card, {ranks |> Enum.sort |> Enum.reverse}}
83
+
84
+ defp sort_rank_asc({rank1, _}, {rank2, _}), do: rank1 <= rank2
85
+ defp sort_count_then_rank_asc({rank1, count1}, {rank2, count2}), do: count1 <= count2 and rank1 <= rank2
86
+
87
+ # Compare different scores against each other first
88
+ for {score, index} <- @scores |> Enum.with_index(1) do
89
+ for other_score <- @scores |> Enum.drop(index) do
90
+ defp sort_scored_hands({_, unquote(score), _}, {_, unquote(other_score), _} ), do: true
91
+ defp sort_scored_hands({_, unquote(other_score), _}, {_, unquote(score), _} ), do: false
92
+ end
93
+ end
94
+
95
+ # Additional rules for tiebreakers
96
+
97
+ # Straight flush tie determined by high card
98
+ defp sort_scored_hands({_, :straight_flush, {high_a}}, {_, :straight_flush, {high_b}}), do: high_a >= high_b
99
+
100
+ # 4-of-a-kind tie determined by rank, then by kicker
101
+ defp sort_scored_hands({_, :four_of_a_kind, {rank_a, _}}, {_, :four_of_a_kind, {rank_b, _}}) when rank_a > rank_b, do: true
102
+ defp sort_scored_hands({_, :four_of_a_kind, {rank_a, _}}, {_, :four_of_a_kind, {rank_b, _}}) when rank_a < rank_b, do: false
103
+ defp sort_scored_hands({_, :four_of_a_kind, {_, kicker_a}}, {_, :four_of_a_kind, {_, kicker_b}}), do: kicker_a >= kicker_b
104
+
105
+ # Full house tie determined by triplet, then pair
106
+ defp sort_scored_hands({_, :full_house, {triplet_a, _}}, {_, :full_house, {triplet_b, _}}) when triplet_a > triplet_b, do: true
107
+ defp sort_scored_hands({_, :full_house, {triplet_a, _}}, {_, :full_house, {triplet_b, _}}) when triplet_a < triplet_b, do: false
108
+ defp sort_scored_hands({_, :full_house, {_, pair_a}}, {_, :full_house, {_, pair_b}}), do: pair_a >= pair_b
109
+
110
+ # Flush tie determined by high card, comparing all 5 if necessary
111
+ defp sort_scored_hands({_, :flush, {ranks_a}}, {_, :flush, {ranks_b}}), do: ranks_a >= ranks_b
112
+
113
+ # Straight tie determined by high card
114
+ defp sort_scored_hands({_, :straight, {high_a}}, {_, :straight, {high_b}}), do: high_a >= high_b
115
+
116
+ # 3-of-a-kind tie determined by triplet, then by high card, comparing both if necessary
117
+ defp sort_scored_hands({_, :three_of_a_kind, {triplet_a, _}}, {_, :three_of_a_kind, {triplet_b, _}}) when triplet_a > triplet_b, do: true
118
+ defp sort_scored_hands({_, :three_of_a_kind, {triplet_a, _}}, {_, :three_of_a_kind, {triplet_b, _}}) when triplet_a < triplet_b, do: false
119
+ defp sort_scored_hands({_, :three_of_a_kind, {_, ranks_a}}, {_, :three_of_a_kind, {_, ranks_b}}), do: ranks_a >= ranks_b
120
+
121
+ # Two-pair tie determined by high pair, then low pair, then by kicker
122
+ defp sort_scored_hands({_, :two_pair, {high_a, _, _}}, {_, :two_pair, {high_b, _, _}}) when high_a > high_b, do: true
123
+ defp sort_scored_hands({_, :two_pair, {high_a, _, _}}, {_, :two_pair, {high_b, _, _}}) when high_a < high_b, do: false
124
+ defp sort_scored_hands({_, :two_pair, {_, low_a, _}}, {_, :two_pair, {_, low_b, _}}) when low_a > low_b, do: true
125
+ defp sort_scored_hands({_, :two_pair, {_, low_a, _}}, {_, :two_pair, {_, low_b, _}}) when low_a < low_b, do: false
126
+ defp sort_scored_hands({_, :two_pair, {_, _, kicker_a}}, {_, :two_pair, {_, _, kicker_b}}), do: kicker_a >= kicker_b
127
+
128
+ # Pair tie determined by pair rank, then by high card, comparing all 3 if necessary
129
+ defp sort_scored_hands({_, :pair, {pair_a, _}}, {_, :pair, {pair_b, _}}) when pair_a > pair_b, do: true
130
+ defp sort_scored_hands({_, :pair, {pair_a, _}}, {_, :pair, {pair_b, _}}) when pair_a < pair_b, do: false
131
+ defp sort_scored_hands({_, :pair, {_, kickers_a}}, {_, :pair, {_, kickers_b}}), do: kickers_a >= kickers_b
132
+
133
+ # High-card tie determined by high card, comparing all 5 if necessary
134
+ defp sort_scored_hands({_, :high_card, {ranks_a}}, {_, :high_card, {ranks_b}}), do: ranks_a >= ranks_b
135
+ end
136
+
@@ -0,0 +1,34 @@
1
+ defmodule Poker do
2
+ @doc """
3
+ Given a list of poker hands, return a list containing the highest scoring hand.
4
+
5
+ If two or more hands tie, return the list of tied hands in the order they were received.
6
+
7
+ The basic rules and hand rankings for Poker can be found at:
8
+
9
+ https://en.wikipedia.org/wiki/List_of_poker_hands
10
+
11
+ For this exercise, we'll consider the game to be using no Jokers,
12
+ so five-of-a-kind hands will not be tested. We will also consider
13
+ the game to be using multiple decks, so it is possible for multiple
14
+ players to have identical cards.
15
+
16
+ Aces can be used in low (A 2 3 4 5) or high (10 J Q K A) straights, but do not count as
17
+ a high card in the former case.
18
+
19
+ For example, (A 2 3 4 5) will lose to (2 3 4 5 6).
20
+
21
+ You can also assume all inputs will be valid, and do not need to perform error checking
22
+ when parsing card values. All hands will be a list of 5 strings, containing a number
23
+ (or letter) for the rank, followed by the suit.
24
+
25
+ Ranks (lowest to highest): 2 3 4 5 6 7 8 9 10 J Q K A
26
+ Suits (order doesn't matter): C D H S
27
+
28
+ Example hand: ~w(4S 5H 4C 5D 4H) # Full house, 5s over 4s
29
+ """
30
+ @spec best_hand(list(list(String.t()))) :: list(list(String.t()))
31
+ def best_hand(hands) do
32
+ end
33
+ end
34
+
@@ -0,0 +1,217 @@
1
+ if !System.get_env("EXERCISM_TEST_EXAMPLES") do
2
+ Code.load_file("poker.exs", __DIR__)
3
+ end
4
+
5
+ ExUnit.start
6
+ ExUnit.configure exclude: :pending, trace: true
7
+
8
+ defmodule PokerTest do
9
+ use ExUnit.Case
10
+
11
+ #@tag :pending
12
+ test "single hand always wins" do
13
+ high_of_jack = ~w(4S 5S 7H 8D JC)
14
+ assert Poker.best_hand([high_of_jack]) == [high_of_jack]
15
+ end
16
+
17
+ @tag :pending
18
+ test "highest card out of all hands wins" do
19
+ high_of_8 = ~w(4D 5S 6S 8D 3C)
20
+ high_of_10 = ~w(2S 4C 7S 9H 10H)
21
+ high_of_jack = ~w(3S 4S 5D 6H JH)
22
+ assert Poker.best_hand([high_of_8, high_of_10, high_of_jack]) == [high_of_jack]
23
+ end
24
+
25
+ @tag :pending
26
+ test "a tie has multiple winners" do
27
+ high_of_8 = ~w(4D 5S 6S 8D 3C)
28
+ high_of_10 = ~w(2S 4C 7S 9H 10H)
29
+ high_of_jack = ~w(3S 4S 5D 6H JH)
30
+ another_high_of_jack = ~w(3H 4H 5C 6C JD)
31
+
32
+ hands = [high_of_8, high_of_10, high_of_jack, another_high_of_jack]
33
+ assert Poker.best_hand(hands) == [high_of_jack, another_high_of_jack]
34
+ end
35
+
36
+ @tag :pending
37
+ test "multiple hands with the same high cards, tie compares next highest ranked, down to last card" do
38
+ high_of_8_low_of_3 = ~w(3S 5H 6S 8D 7H)
39
+ high_of_8_low_of_2 = ~w(2S 5D 6D 8C 7S)
40
+ assert Poker.best_hand([high_of_8_low_of_3, high_of_8_low_of_2]) == [high_of_8_low_of_3]
41
+ end
42
+
43
+ @tag :pending
44
+ test "one pair beats high card" do
45
+ high_of_king = ~w(4S 5H 6C 8D KH)
46
+ pair_of_4 = ~w(2S 4H 6S 4D JH)
47
+ assert Poker.best_hand([high_of_king, pair_of_4]) == [pair_of_4]
48
+ end
49
+
50
+ @tag :pending
51
+ test "highest pair wins" do
52
+ pair_of_2 = ~w(4S 2H 6S 2D JH)
53
+ pair_of_4 = ~w(2S 4H 6C 4D JD)
54
+ assert Poker.best_hand([pair_of_2, pair_of_4]) == [pair_of_4]
55
+ end
56
+
57
+ @tag :pending
58
+ test "two pairs beats one pair" do
59
+ pair_of_8 = ~w(2S 8H 6S 8D JH)
60
+ fives_and_fours = ~w(4S 5H 4C 8C 5C)
61
+ assert Poker.best_hand([pair_of_8, fives_and_fours]) == [fives_and_fours]
62
+ end
63
+
64
+ @tag :pending
65
+ test "both hands have two pairs, highest ranked pair wins" do
66
+ eights_and_twos = ~w(2S 8H 2D 8D 3H)
67
+ fives_and_fours = ~w(4S 5H 4C 8S 5D)
68
+ assert Poker.best_hand([eights_and_twos, fives_and_fours]) == [eights_and_twos]
69
+ end
70
+
71
+ @tag :pending
72
+ test "both hands have two pairs, with the same highest ranked pair, tie goes to low pair" do
73
+ queens_and_twos = ~w(2S QS 2C QD JH)
74
+ queens_and_jacks = ~w(JD QH JS 8D QC)
75
+ assert Poker.best_hand([queens_and_twos, queens_and_jacks]) == [queens_and_jacks]
76
+ end
77
+
78
+ @tag :pending
79
+ test "both hands have two identically ranked pairs, tie goes to remaining card (kicker)" do
80
+ queens_jacks_and_8 = ~w(JD QH JS 8D QC)
81
+ queens_jacks_and_2 = ~w(JS QS JC 2D QD)
82
+ assert Poker.best_hand([queens_jacks_and_8, queens_jacks_and_2]) == [queens_jacks_and_8]
83
+ end
84
+
85
+ @tag :pending
86
+ test "three of a kind beats two pair" do
87
+ eights_and_twos = ~w(2S 8H 2H 8D JH)
88
+ three_fours = ~w(4S 5H 4C 8S 4H)
89
+ assert Poker.best_hand([eights_and_twos, three_fours]) == [three_fours]
90
+ end
91
+
92
+ @tag :pending
93
+ test "both hands have three of a kind, tie goes to highest ranked triplet" do
94
+ three_twos = ~w(2S 2H 2C 8D JH)
95
+ three_aces = ~w(4S AH AS 8C AD)
96
+ assert Poker.best_hand([three_twos, three_aces]) == [three_aces]
97
+ end
98
+
99
+ @tag :pending
100
+ test "with multiple decks, two players can have same three of a kind, ties go to highest remaining cards" do
101
+ three_aces_7_high = ~w(4S AH AS 7C AD)
102
+ three_aces_8_high = ~w(4S AH AS 8C AD)
103
+ assert Poker.best_hand([three_aces_7_high, three_aces_8_high]) == [three_aces_8_high]
104
+
105
+ three_aces_8_high_5_low = ~w(5S AH AS 8C AD)
106
+ assert Poker.best_hand([three_aces_8_high_5_low, three_aces_8_high]) == [three_aces_8_high_5_low]
107
+ end
108
+
109
+ @tag :pending
110
+ test "a straight beats three of a kind" do
111
+ three_fours = ~w(4S 5H 4C 8D 4H)
112
+ straight = ~w(3S 4D 2S 6D 5C)
113
+ assert Poker.best_hand([three_fours, straight]) == [straight]
114
+ end
115
+
116
+ @tag :pending
117
+ test "aces can be end a straight (10 J Q K A)" do
118
+ three_fours = ~w(4S 5H 4C 8D 4H)
119
+ straight_to_ace = ~w(10D JH QS KD AC)
120
+ assert Poker.best_hand([three_fours, straight_to_ace]) == [straight_to_ace]
121
+ end
122
+
123
+ @tag :pending
124
+ test "aces can be start a straight (A 2 3 4 5)" do
125
+ three_fours = ~w(4S 5H 4C 8D 4H)
126
+ straight_to_5 = ~w(4D AH 3S 2D 5C)
127
+ assert Poker.best_hand([three_fours, straight_to_5]) == [straight_to_5]
128
+ end
129
+
130
+ @tag :pending
131
+ test "both hands with a straight, tie goes to highest ranked card" do
132
+ straight_to_8 = ~w(4S 6C 7S 8D 5H)
133
+ straight_to_9 = ~w(5S 7H 8S 9D 6H)
134
+ assert Poker.best_hand([straight_to_8, straight_to_9]) == [straight_to_9]
135
+ end
136
+
137
+ @tag :pending
138
+ test "even though an ace is usually high, a 5-high straight is the lowest-scoring straight" do
139
+ straight_to_6 = ~w(2H 3C 4D 5D 6H)
140
+ straight_to_5 = ~w(4S AH 3S 2D 5H)
141
+ assert Poker.best_hand([straight_to_6, straight_to_5]) == [straight_to_6]
142
+ end
143
+
144
+ @tag :pending
145
+ test "straight beats a flush" do
146
+ straight_to_8 = ~w(4C 6H 7D 8D 5H)
147
+ flush_to_7 = ~w(2S 4S 5S 6S 7S)
148
+ assert Poker.best_hand([straight_to_8, flush_to_7]) == [flush_to_7]
149
+ end
150
+
151
+ @tag :pending
152
+ test "both hands have a flush, tie goes to high card, down to the last one if necessary" do
153
+ flush_to_9 = ~w(4H 7H 8H 9H 6H)
154
+ flush_to_7 = ~w(2S 4S 5S 6S 7S)
155
+ assert Poker.best_hand([flush_to_9, flush_to_7]) == [flush_to_9]
156
+
157
+ flush_to_9_with_4_matches = ~w(3S 6S 7S 8S 9S)
158
+ assert Poker.best_hand([flush_to_9, flush_to_9_with_4_matches]) == [flush_to_9]
159
+ end
160
+
161
+ @tag :pending
162
+ test "full house beats a flush" do
163
+ flush_to_8 = ~w(3H 6H 7H 8H 5H)
164
+ full = ~w(4S 5H 4C 5D 4H)
165
+ assert Poker.best_hand([flush_to_8, full]) == [full]
166
+ end
167
+
168
+ @tag :pending
169
+ test "both hands have a full house, tie goes to highest-ranked triplet" do
170
+ full_of_4_by_9 = ~w(4H 4S 4D 9S 9D)
171
+ full_of_5_by_8 = ~w(5H 5S 5D 8S 8D)
172
+ assert Poker.best_hand([full_of_4_by_9, full_of_5_by_8]) == [full_of_5_by_8]
173
+ end
174
+
175
+ @tag :pending
176
+ test "with multiple decks, both hands have a full house with the same triplet, tie goes to the pair" do
177
+ full_of_5_by_9 = ~w(5H 5S 5D 9S 9D)
178
+ full_of_5_by_8 = ~w(5H 5S 5D 8S 8D)
179
+ assert Poker.best_hand([full_of_5_by_9, full_of_5_by_8]) == [full_of_5_by_9]
180
+ end
181
+
182
+ @tag :pending
183
+ test "four of a kind beats a full house" do
184
+ full = ~w(4S 5H 4D 5D 4H)
185
+ four_3s = ~w(3S 3H 2S 3D 3C)
186
+ assert Poker.best_hand([four_3s, full]) == [four_3s]
187
+ end
188
+
189
+ @tag :pending
190
+ test "both hands have four of a kind, tie goes to high quad" do
191
+ four_2s = ~w(2S 2H 2C 8D 2D)
192
+ four_5s = ~w(4S 5H 5S 5D 5C)
193
+ assert Poker.best_hand([four_2s, four_5s]) == [four_5s]
194
+ end
195
+
196
+ @tag :pending
197
+ test "with multiple decks, both hands with identical four of a kind, tie determined by kicker" do
198
+ four_3s_and_2 = ~w(3S 3H 2S 3D 3C)
199
+ four_3s_and_4 = ~w(3S 3H 4S 3D 3C)
200
+ assert Poker.best_hand([four_3s_and_2, four_3s_and_4]) == [four_3s_and_4]
201
+ end
202
+
203
+ @tag :pending
204
+ test "straight flush beats four of a kind" do
205
+ four_5s = ~w(4S 5H 5S 5D 5C)
206
+ straight_flush_to_10 = ~w(7S 8S 9S 6S 10S)
207
+ assert Poker.best_hand([four_5s, straight_flush_to_10]) == [straight_flush_to_10]
208
+ end
209
+
210
+ @tag :pending
211
+ test "both hands have straight flush, tie goes to highest-ranked card" do
212
+ straight_flush_to_8 = ~w(4H 6H 7H 8H 5H)
213
+ straight_flush_to_9 = ~w(5S 7S 8S 9S 6S)
214
+ assert Poker.best_hand([straight_flush_to_8, straight_flush_to_9]) == [straight_flush_to_9]
215
+ end
216
+ end
217
+
@@ -0,0 +1,62 @@
1
+ defmodule ProteinTranslation do
2
+ @doc """
3
+ Given an RNA string, return a list of proteins specified by codons, in order.
4
+ """
5
+ @spec of_rna(String.t()) :: { atom, list(String.t()) }
6
+ def of_rna(rna) do
7
+ translate_rna(rna, [])
8
+ end
9
+
10
+ @doc """
11
+ Given a codon, return the corresponding protein
12
+
13
+ UGU -> Cysteine
14
+ UGC -> Cysteine
15
+ UUA -> Leucine
16
+ UUG -> Leucine
17
+ AUG -> Methionine
18
+ UUU -> Phenylalanine
19
+ UUC -> Phenylalanine
20
+ UCU -> Serine
21
+ UCC -> Serine
22
+ UCA -> Serine
23
+ UCG -> Serine
24
+ UGG -> Tryptophan
25
+ UAU -> Tyrosine
26
+ UAC -> Tyrosine
27
+ UAA -> STOP
28
+ UAG -> STOP
29
+ UGA -> STOP
30
+ """
31
+ @spec of_codon(String.t()) :: { atom, String.t() }
32
+ def of_codon(codon) do
33
+ translate_codon(codon)
34
+ end
35
+
36
+ @codons %{
37
+ "Methionine" => ~w(AUG),
38
+ "Phenylalanine" => ~w(UUU UUC),
39
+ "Leucine" => ~w(UUA UUG),
40
+ "Serine" => ~w(UCU UCC UCA UCG),
41
+ "Tyrosine" => ~w(UAU UAC),
42
+ "Cysteine" => ~w(UGU UGC),
43
+ "Tryptophan" => ~w(UGG),
44
+ }
45
+ @stop ~w(UAA UAG UGA)
46
+
47
+ defp translate_rna("", results), do: { :ok, Enum.reverse(results) }
48
+
49
+ for codon <- @stop do
50
+ defp translate_rna(unquote(codon) <> _rest, results), do: { :ok, Enum.reverse(results) }
51
+ defp translate_codon(unquote(codon)), do: { :ok, "STOP" }
52
+ end
53
+
54
+ for { protein, codons } <- @codons, codon <- codons do
55
+ defp translate_rna(unquote(codon) <> rest, results), do: translate_rna(rest, [unquote(protein) | results])
56
+ defp translate_codon(unquote(codon)), do: { :ok, unquote(protein) }
57
+ end
58
+
59
+ defp translate_rna(_, _), do: { :error, "invalid RNA"}
60
+ defp translate_codon(_), do: { :error, "invalid codon"}
61
+ end
62
+