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.
- 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
|
+
|