trackler 2.0.8.19 → 2.0.8.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/exercises/phone-number/canonical-data.json +2 -2
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +7 -0
- data/tracks/c/exercises/react/makefile +16 -0
- data/tracks/c/exercises/react/src/example.c +185 -0
- data/tracks/c/exercises/react/src/react.h +29 -0
- data/tracks/c/exercises/react/test/test_react.c +324 -0
- data/tracks/c/exercises/react/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/react/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/react/test/vendor/unity_internals.h +701 -0
- data/tracks/csharp/.travis.yml +2 -9
- data/tracks/csharp/appveyor.yml +3 -3
- data/tracks/csharp/build.cake +13 -4
- data/tracks/csharp/build.ps1 +56 -164
- data/tracks/csharp/build.sh +33 -78
- data/tracks/csharp/circle.yml +2 -4
- data/tracks/csharp/config.json +2 -1
- data/tracks/csharp/exercises/leap/LeapTest.cs +8 -8
- data/tracks/csharp/generators/CanonicalData.cs +19 -0
- data/tracks/csharp/generators/CanonicalDataCase.cs +24 -0
- data/tracks/csharp/generators/CanonicalDataCaseJsonConverter.cs +32 -0
- data/tracks/csharp/generators/CanonicalDataCasesJsonConverter.cs +30 -0
- data/tracks/csharp/generators/CanonicalDataParser.cs +28 -0
- data/tracks/csharp/generators/ExerciseCollection.cs +23 -0
- data/tracks/csharp/generators/Exercises/Exercise.cs +14 -0
- data/tracks/csharp/generators/Exercises/LeapExercise.cs +35 -0
- data/tracks/csharp/generators/Generators.csproj +12 -0
- data/tracks/csharp/generators/Generators.csproj.user +6 -0
- data/tracks/csharp/generators/Generators.sln +22 -0
- data/tracks/csharp/generators/Program.cs +59 -0
- data/tracks/csharp/generators/TestClass.cs +13 -0
- data/tracks/csharp/generators/TestClassRenderer.cs +36 -0
- data/tracks/csharp/generators/TestMethod.cs +9 -0
- data/tracks/csharp/generators/TestMethodNameTransformer.cs +11 -0
- data/tracks/csharp/generators/TestMethodRenderer.cs +18 -0
- data/tracks/csharp/generators/To.cs +7 -0
- data/tracks/csharp/generators/generate.ps1 +2 -0
- data/tracks/csharp/generators/generate.sh +4 -0
- data/tracks/delphi/config.json +8 -0
- data/tracks/delphi/exercises/phone-number/uPhoneNumberExample.pas +6 -6
- data/tracks/delphi/exercises/phone-number/uPhoneNumberTests.pas +28 -17
- data/tracks/delphi/exercises/roman-numerals/RomanNumerals.dpr +60 -0
- data/tracks/delphi/exercises/roman-numerals/uRomanNumeralsExample.pas +49 -0
- data/tracks/delphi/exercises/roman-numerals/uRomanNumeralsTest.pas +216 -0
- data/tracks/elixir/config.json +22 -0
- data/tracks/elixir/exercises/poker/example.exs +136 -0
- data/tracks/elixir/exercises/poker/poker.exs +34 -0
- data/tracks/elixir/exercises/poker/poker_test.exs +217 -0
- data/tracks/elixir/exercises/protein-translation/example.exs +62 -0
- data/tracks/elixir/exercises/protein-translation/protein_translation.exs +34 -0
- data/tracks/elixir/exercises/protein-translation/protein_translation_test.exs +87 -0
- data/tracks/elixir/exercises/say/example.exs +139 -0
- data/tracks/elixir/exercises/say/say.exs +8 -0
- data/tracks/elixir/exercises/say/say_test.exs +85 -0
- data/tracks/go/exercises/robot-name/example.go +2 -0
- data/tracks/go/exercises/robot-name/robot_name_test.go +9 -1
- data/tracks/go/exercises/roman-numerals/roman_numerals_test.go +4 -1
- data/tracks/go/exercises/saddle-points/saddle_points_test.go +6 -6
- data/tracks/php/config.json +7 -0
- data/tracks/php/exercises/grade-school/example.php +35 -0
- data/tracks/php/exercises/grade-school/grade-school_test.php +84 -0
- metadata +43 -2
data/tracks/elixir/config.json
CHANGED
@@ -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
|
+
|