trackler 2.1.0.26 → 2.1.0.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/common/CONTRIBUTING.md +0 -15
  3. data/common/exercises/secret-handshake/canonical-data.json +14 -7
  4. data/lib/trackler/version.rb +1 -1
  5. data/tracks/dlang/config.json +18 -0
  6. data/tracks/dlang/exercises/leap/leap.d +8 -0
  7. data/tracks/dlang/exercises/leap/leap_example.d +15 -0
  8. data/tracks/dlang/exercises/react/react.d +211 -0
  9. data/tracks/dlang/exercises/react/react_example.d +291 -0
  10. data/tracks/factor/README.md +7 -7
  11. data/tracks/factor/config.json +13 -4
  12. data/tracks/factor/exercises/hello-world/hello-world-example.factor +2 -3
  13. data/tracks/factor/exercises/hello-world/hello-world-tests.factor +1 -5
  14. data/tracks/factor/exercises/hello-world/hello-world.factor +1 -1
  15. data/tracks/factor/exercises/two-fer/two-fer-example.factor +6 -0
  16. data/tracks/factor/exercises/two-fer/two-fer-tests.factor +8 -0
  17. data/tracks/fortran/Makefile +1 -2
  18. data/tracks/fortran/config.json +6 -0
  19. data/tracks/fortran/exercises/bob/bob.fun +18 -18
  20. data/tracks/fortran/exercises/hamming/example.f90 +25 -0
  21. data/tracks/fortran/exercises/hamming/hamming.fun +75 -0
  22. data/tracks/go/exercises/poker/.meta/gen.go +76 -0
  23. data/tracks/go/exercises/poker/cases_test.go +240 -0
  24. data/tracks/go/exercises/poker/example.go +10 -1
  25. data/tracks/go/exercises/poker/poker_test.go +1 -224
  26. data/tracks/go/exercises/sum-of-multiples/.meta/gen.go +43 -0
  27. data/tracks/go/exercises/sum-of-multiples/cases_test.go +24 -0
  28. data/tracks/go/exercises/sum-of-multiples/example.go +1 -1
  29. data/tracks/go/exercises/sum-of-multiples/sum_of_multiples_test.go +1 -18
  30. data/tracks/groovy/exercises/robot-name/RobotSpec.groovy +38 -0
  31. data/tracks/kotlin/config.json +10 -0
  32. data/tracks/kotlin/exercises/collatz-conjecture/build.gradle +28 -0
  33. data/tracks/kotlin/exercises/collatz-conjecture/src/example/kotlin/CollatzCalculator.kt +12 -0
  34. data/tracks/kotlin/exercises/collatz-conjecture/src/main/kotlin/.keep +0 -0
  35. data/tracks/kotlin/exercises/collatz-conjecture/src/test/kotlin/CollatzCalculatorTest.kt +51 -0
  36. data/tracks/kotlin/exercises/diamond/build.gradle +28 -0
  37. data/tracks/kotlin/exercises/diamond/src/example/kotlin/DiamondPrinter.kt +35 -0
  38. data/tracks/kotlin/exercises/diamond/src/main/kotlin/DiamondPrinter.kt +5 -0
  39. data/tracks/kotlin/exercises/diamond/src/test/kotlin/DiamondPrinterTest.kt +121 -0
  40. data/tracks/kotlin/exercises/settings.gradle +2 -0
  41. data/tracks/ocaml/.gitignore +1 -0
  42. data/tracks/ocaml/.vscode/launch.json +14 -0
  43. data/tracks/ocaml/tools/test-generator/src/controller.ml +15 -16
  44. data/tracks/ocaml/tools/test-generator/src/languages.ml +30 -0
  45. data/tracks/ocaml/tools/test-generator/src/ocaml_special_cases.ml +137 -0
  46. data/tracks/ocaml/tools/test-generator/src/purescript_special_cases.ml +13 -0
  47. data/tracks/ocaml/tools/test-generator/src/special_cases.ml +7 -132
  48. data/tracks/ocaml/tools/test-generator/src/template.ml +3 -3
  49. data/tracks/ocaml/tools/test-generator/src/test_gen.ml +13 -3
  50. data/tracks/ocaml/tools/test-generator/templates/{acronym → ocaml/acronym}/template.ml +0 -0
  51. data/tracks/ocaml/tools/test-generator/templates/{all-your-base → ocaml/all-your-base}/template.ml +0 -0
  52. data/tracks/ocaml/tools/test-generator/templates/{anagram → ocaml/anagram}/template.ml +0 -0
  53. data/tracks/ocaml/tools/test-generator/templates/{atbash-cipher → ocaml/atbash-cipher}/template.ml +0 -0
  54. data/tracks/ocaml/tools/test-generator/templates/{beer-song → ocaml/beer-song}/template.ml +0 -0
  55. data/tracks/ocaml/tools/test-generator/templates/{binary-search → ocaml/binary-search}/template.ml +0 -0
  56. data/tracks/ocaml/tools/test-generator/templates/{bob → ocaml/bob}/template.ml +0 -0
  57. data/tracks/ocaml/tools/test-generator/templates/{bowling → ocaml/bowling}/template.ml +0 -0
  58. data/tracks/ocaml/tools/test-generator/templates/{bracket-push → ocaml/bracket-push}/template.ml +0 -0
  59. data/tracks/ocaml/tools/test-generator/templates/{change → ocaml/change}/template.ml +0 -0
  60. data/tracks/ocaml/tools/test-generator/templates/{connect → ocaml/connect}/template.ml +0 -0
  61. data/tracks/ocaml/tools/test-generator/templates/{difference-of-squares → ocaml/difference-of-squares}/template.ml +0 -0
  62. data/tracks/ocaml/tools/test-generator/templates/{dominoes → ocaml/dominoes}/template.ml +0 -0
  63. data/tracks/ocaml/tools/test-generator/templates/{etl → ocaml/etl}/template.ml +0 -0
  64. data/tracks/ocaml/tools/test-generator/templates/{forth → ocaml/forth}/template.ml +0 -0
  65. data/tracks/ocaml/tools/test-generator/templates/{hamming → ocaml/hamming}/template.ml +0 -0
  66. data/tracks/ocaml/tools/test-generator/templates/{hello-world → ocaml/hello-world}/template.ml +0 -0
  67. data/tracks/ocaml/tools/test-generator/templates/{leap → ocaml/leap}/template.ml +0 -0
  68. data/tracks/ocaml/tools/test-generator/templates/{luhn → ocaml/luhn}/template.ml +0 -0
  69. data/tracks/ocaml/tools/test-generator/templates/{minesweeper → ocaml/minesweeper}/template.ml +0 -0
  70. data/tracks/ocaml/tools/test-generator/templates/{pangram → ocaml/pangram}/template.ml +0 -0
  71. data/tracks/ocaml/tools/test-generator/templates/{phone-number → ocaml/phone-number}/template.ml +0 -0
  72. data/tracks/ocaml/tools/test-generator/templates/{prime-factors → ocaml/prime-factors}/template.ml +0 -0
  73. data/tracks/ocaml/tools/test-generator/templates/{raindrops → ocaml/raindrops}/template.ml +0 -0
  74. data/tracks/ocaml/tools/test-generator/templates/{roman-numerals → ocaml/roman-numerals}/template.ml +0 -0
  75. data/tracks/ocaml/tools/test-generator/templates/{run-length-encoding → ocaml/run-length-encoding}/template.ml +0 -0
  76. data/tracks/ocaml/tools/test-generator/templates/{say → ocaml/say}/template.ml +0 -0
  77. data/tracks/ocaml/tools/test-generator/templates/{space-age → ocaml/space-age}/template.ml +0 -0
  78. data/tracks/ocaml/tools/test-generator/templates/{triangle → ocaml/triangle}/template.ml +0 -0
  79. data/tracks/ocaml/tools/test-generator/templates/{word-count → ocaml/word-count}/template.ml +0 -0
  80. data/tracks/ocaml/tools/test-generator/templates/purescript/hamming/Main.purs +18 -0
  81. data/tracks/ocaml/tools/test-generator/test/all_tests.ml +2 -2
  82. data/tracks/ocaml/tools/test-generator/test/{special_cases_test.ml → ocaml_special_cases_test.ml} +3 -3
  83. data/tracks/ocaml/tools/test-generator/test/template_test.ml +1 -0
  84. metadata +59 -34
  85. data/tracks/groovy/exercises/robot-name/RobotTest.groovy +0 -34
@@ -1,4 +1,8 @@
1
- # xfactor
1
+ # xFactor
2
+
3
+ ---
4
+
5
+ [![Build Status](https://travis-ci.org/exercism/xfactor.svg?branch=master)](https://travis-ci.org/exercism/xfactor)
2
6
 
3
7
  Exercism problems in Factor.
4
8
 
@@ -35,9 +39,7 @@ Here's what you need to do to start working with the Factor code in the `exercis
35
39
 
36
40
  testing exercise: hello-world
37
41
 
38
- Unit Test: { { "Hello, World!" } [ "" hello-you ] }
39
- Unit Test: { { "Hello, Alice!" } [ "Alice" hello-you ] }
40
- Unit Test: { { "Hello, Bob!" } [ "Bob" hello-you ] }
42
+ Unit Test: { { "Hello, World!" } [ say-hello ] }
41
43
  ```
42
44
 
43
45
  Alternatively, to run all tests in all exercise directories:
@@ -49,9 +51,7 @@ Here's what you need to do to start working with the Factor code in the `exercis
49
51
 
50
52
  testing exercise: hello-world
51
53
 
52
- Unit Test: { { "Hello, World!" } [ "" hello-you ] }
53
- Unit Test: { { "Hello, Alice!" } [ "Alice" hello-you ] }
54
- Unit Test: { { "Hello, Bob!" } [ "Bob" hello-you ] }
54
+ Unit Test: { { "Hello, World!" } [ say-hello ] }
55
55
  ```
56
56
 
57
57
  `config.json` is verified for logical integrity on each run. To only check `config.json`'s validity:
@@ -4,26 +4,35 @@
4
4
  "repository": "https://github.com/exercism/xfactor",
5
5
  "active": false,
6
6
  "test_pattern": "TODO",
7
+
7
8
  "exercises": [
8
9
  {
9
10
  "slug": "hello-world",
10
11
  "difficulty": 1,
11
12
  "topics": [
12
13
  "word definition",
13
- "stack effect",
14
- "text formatting",
15
- "quotations"
14
+ "stack effect"
16
15
  ]
17
16
  },
18
17
  {
19
18
  "slug": "leap",
20
- "difficulty": 2,
19
+ "difficulty": 3,
21
20
  "topics": [
22
21
  "quotations",
23
22
  "word definition",
24
23
  "conditionals",
25
24
  "logical operators"
26
25
  ]
26
+ },
27
+ {
28
+ "slug": "two-fer",
29
+ "difficulty": 2,
30
+ "topics": [
31
+ "word definition",
32
+ "stack effect",
33
+ "text formatting",
34
+ "quotations"
35
+ ]
27
36
  }
28
37
  ],
29
38
 
@@ -1,6 +1,5 @@
1
1
  USING: formatting kernel sequences ;
2
2
  IN: hello-world
3
3
 
4
- : hello-name ( name -- string )
5
- dup empty? [ drop "World" ] when
6
- "Hello, %s!" sprintf ;
4
+ : say-hello ( -- string )
5
+ "Hello, World!" ;
@@ -1,8 +1,4 @@
1
1
  USING: hello-world tools.test ;
2
2
  IN: hello-world.tests
3
3
 
4
- ! There are no variadic functions in Factor, due to the nature of the stack.
5
- ! Usually, if you need var args, use an array. Here, we'll just use an empty string.
6
- { "Hello, World!" } [ "" hello-name ] unit-test
7
- { "Hello, Alice!" } [ "Alice" hello-name ] unit-test
8
- { "Hello, Bob!" } [ "Bob" hello-name ] unit-test
4
+ { "Hello, World!" } [ say-hello ] unit-test
@@ -4,4 +4,4 @@ USING: ;
4
4
  IN: hello-world
5
5
 
6
6
  ! your implementation goes here
7
- ! : hello-name ( -- ) ;
7
+ ! : say-hello ( -- ) ;
@@ -0,0 +1,6 @@
1
+ USING: formatting kernel sequences ;
2
+ IN: two-fer
3
+
4
+ : 2-for-1 ( name -- string )
5
+ dup empty? [ drop "you" ] when
6
+ "One for %s, one for me." sprintf ;
@@ -0,0 +1,8 @@
1
+ USING: hello-world tools.test ;
2
+ IN: two-fer.tests
3
+
4
+ ! There are no variadic functions in Factor, due to the nature of the stack.
5
+ ! Usually, if you need var args, use an array. Here, we'll just use an empty string.
6
+ { "One for you, one for me." } [ "" 2-for-1 ] unit-test
7
+ { "One for Alice, one for me." } [ "Alice" 2-for-1 ] unit-test
8
+ { "One for Bob, one for me." } [ "Bob" 2-for-1 ] unit-test
@@ -30,8 +30,7 @@ install-test: ## install test dependency: funit
30
30
 
31
31
  test-assignment: ## run single test using ASSIGNMENTS: test-assignment ASSIGNMENT=wordy
32
32
  @echo "running tests for: $(ASSIGNMENT)"
33
- # @cat ./exercises/$(ASSIGNMENT)/$(TSTFILE) | sed '/markTestSkipped()/d' > $(OUTDIR)/$(TSTFILE)
34
- @cat ./exercises/$(ASSIGNMENT)/$(TSTFILE) > $(OUTDIR)/$(TSTFILE)
33
+ @cat ./exercises/$(ASSIGNMENT)/$(TSTFILE) | sed 's/Xtest/test/' > $(OUTDIR)/$(TSTFILE)
35
34
  @cp ./exercises/$(ASSIGNMENT)/$(EXAMPLE) $(OUTDIR)/$(ASSIGNMENT).$(FILEEXT)
36
35
  @cd $(OUTDIR) && funit
37
36
 
@@ -16,6 +16,12 @@
16
16
  "difficulty": 1,
17
17
  "topics": [
18
18
  ]
19
+ },
20
+ {
21
+ "slug": "hamming",
22
+ "difficulty": 1,
23
+ "topics": [
24
+ ]
19
25
  }
20
26
  ],
21
27
  "deprecated": [
@@ -38,75 +38,75 @@ test stating_something
38
38
  assert_equal( 'Whatever.' , hey('Tom-ay-to, tomaaaah-to.') )
39
39
  end test
40
40
 
41
- test shouting
41
+ Xtest shouting
42
42
  assert_equal( 'Whoa chill out!' , hey('WATCH OUT!') )
43
43
  end test
44
44
 
45
- test shouting_gibberish
45
+ Xtest shouting_gibberish
46
46
  assert_equal( 'Whoa chill out!' , hey(random_shouting(11)) )
47
47
  end test
48
48
 
49
- test asking_a_question
49
+ Xtest asking_a_question
50
50
  assert_equal( 'Sure.' , hey('Does this cryogenic chamber make me look fat?') )
51
51
  end test
52
52
 
53
- test asking_a_numeric_question
53
+ Xtest asking_a_numeric_question
54
54
  assert_equal( 'Sure.' , hey('You are, what, like 15?') )
55
55
  end test
56
56
 
57
- test asking_gibberish
57
+ Xtest asking_gibberish
58
58
  assert_equal( 'Sure.' , hey(random_question(11)) )
59
59
  end test
60
60
 
61
- test talking_forcefully
61
+ Xtest talking_forcefully
62
62
  assert_equal( 'Whatever.' , hey('Lets''s go make out behind the gym!') )
63
63
  end test
64
64
 
65
- test using_acronyms_in_regular_speech
65
+ Xtest using_acronyms_in_regular_speech
66
66
  assert_equal( 'Whatever.' , hey('It''s OK if you don''t want to go to the DMV.') )
67
67
  end test
68
68
 
69
- test forceful_questions
69
+ Xtest forceful_questions
70
70
  assert_equal( 'Whoa chill out!' , hey('WHAT THE HELL WHERE YOU THINKING?') )
71
71
  end test
72
72
 
73
- test shouting_numbers
73
+ Xtest shouting_numbers
74
74
  assert_equal( 'Whoa chill out!' , hey('1, 2, 3, GO!') )
75
75
  end test
76
76
 
77
- test only_numbers
77
+ Xtest only_numbers
78
78
  assert_equal( 'Whatever.' , hey('1, 2, 3') )
79
79
  end test
80
80
 
81
- test questions_with_only_numbers
81
+ Xtest questions_with_only_numbers
82
82
  assert_equal( 'Sure.' , hey('4?') )
83
83
  end test
84
84
 
85
- test shouting_with_special_characters
85
+ Xtest shouting_with_special_characters
86
86
  assert_equal( 'Whoa chill out!' , hey('ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!') )
87
87
  end test
88
88
 
89
- test shouting_with_no_exclamation_mark
89
+ Xtest shouting_with_no_exclamation_mark
90
90
  assert_equal( 'Whoa chill out!' , hey('I HATE YOU') )
91
91
  end test
92
92
 
93
- test statement_containing_exclamation_mark
93
+ Xtest statement_containing_exclamation_mark
94
94
  assert_equal( 'Whatever.' , hey('Ending with ? means a question.') )
95
95
  end test
96
96
 
97
- test prattling_on
97
+ Xtest prattling_on
98
98
  assert_equal( 'Sure.' , hey('Wait! Hang on. Are you going to ge OK?') )
99
99
  end test
100
100
 
101
- test silence
101
+ Xtest silence
102
102
  assert_equal( 'Fine. Be that way!' , hey('') )
103
103
  end test
104
104
 
105
- test prolonged_silence
105
+ Xtest prolonged_silence
106
106
  assert_equal( 'Fine. Be that way!' , hey(' ') )
107
107
  end test
108
108
 
109
- test on_multiple_line_questions
109
+ Xtest on_multiple_line_questions
110
110
  multi_line_string = ''//NEW_LINE('A')//'Does this cryogenic chamber make me look fat?'//NEW_LINE('A')//'no'
111
111
  assert_equal( 'Whatever.' , hey(multi_line_string) )
112
112
  end test
@@ -0,0 +1,25 @@
1
+ module hamming
2
+ contains
3
+
4
+ function compute(strand1, strand2, distance)
5
+ character(*) :: strand1, strand2
6
+ integer :: distance, i
7
+ logical :: compute
8
+
9
+ distance = 0
10
+ compute = .true.
11
+
12
+ if ( len(strand1) .NE. len(strand2) ) then
13
+ compute = .false.
14
+ return
15
+ end if
16
+
17
+ do i = 1,len(strand1)
18
+ if (strand1(i:i) .NE. strand2(i:i)) then
19
+ distance = distance + 1
20
+ end if
21
+
22
+ end do
23
+
24
+ end function compute
25
+ end module hamming
@@ -0,0 +1,75 @@
1
+ test_suite hamming
2
+ integer :: distance
3
+
4
+ setup
5
+ end setup
6
+
7
+ test identical_strands
8
+ assert_true( compute('A', 'A', distance ) )
9
+ assert_equal( 0, distance )
10
+ end test
11
+
12
+ Xtest long_identical_strands
13
+ assert_true( compute('GGACTGA', 'GGACTGA', distance ) )
14
+ assert_equal( 0, distance )
15
+ end test
16
+
17
+ Xtest complete_distance_in_single_nucleotide_strands
18
+ assert_true( compute('A', 'G', distance) )
19
+ assert_equal( 1, distance )
20
+ end test
21
+
22
+ Xtest complete_distance_in_small_strands
23
+ assert_true( compute('AG', 'CT', distance) )
24
+ assert_equal( 2, distance )
25
+ end test
26
+
27
+ Xtest small_distance_in_small_strands
28
+ assert_true( compute('AT', 'CT', distance) )
29
+ assert_equal( 1, distance )
30
+ end test
31
+
32
+ Xtest small_distance
33
+ assert_true( compute('GGACG', 'GGTCG', distance) )
34
+ assert_equal( 1, distance )
35
+ end test
36
+
37
+ Xtest small_distance_in_long_strands
38
+ assert_true( compute('ACCAGGG', 'ACTATGG', distance) )
39
+ assert_equal( 2, distance )
40
+ end test
41
+
42
+ Xtest non_unique_character_in_first_strand
43
+ assert_true( compute('AGA', 'AGG', distance) )
44
+ assert_equal( 1, distance )
45
+ end test
46
+
47
+ Xtest same_nucleotides_in_different_positions
48
+ assert_true( compute('TAG', 'GAT', distance) )
49
+ assert_equal( 2, distance )
50
+ end test
51
+
52
+ Xtest large_distance
53
+ assert_true( compute('GATACA', 'GCATAA', distance) )
54
+ assert_equal( 4, distance )
55
+ end test
56
+
57
+ Xtest large_distance_in_off_by_one_strand
58
+ assert_true( compute('GGACGGATTCTG', 'AGGACGGATTCT', distance) )
59
+ assert_equal( 9, distance )
60
+ end test
61
+
62
+ Xtest empty_strands
63
+ assert_true( compute('', '', distance) )
64
+ assert_equal( 0, distance )
65
+ end test
66
+
67
+ Xtest disallow_first_strand_longer
68
+ assert_false( compute('AATG', 'AAA', distance) )
69
+ end test
70
+
71
+ Xtest disallow_second_strand_longer
72
+ assert_false( compute('ATA', 'AGTG', distance) )
73
+ end test
74
+
75
+ end test_suite
@@ -0,0 +1,76 @@
1
+ package main
2
+
3
+ import (
4
+ "log"
5
+ "strings"
6
+ "text/template"
7
+
8
+ "../../../gen"
9
+ )
10
+
11
+ func main() {
12
+ t := template.New("").Funcs(template.FuncMap{
13
+ "pokerHands": PokerHands,
14
+ })
15
+ t, err := t.Parse(tmpl)
16
+ if err != nil {
17
+ log.Fatal(err)
18
+ }
19
+ var j js
20
+ if err := gen.Gen("poker", &j, t); err != nil {
21
+ log.Fatal(err)
22
+ }
23
+ }
24
+
25
+ // The JSON structure we expect to be able to unmarshal into
26
+ type js struct {
27
+ Cases []struct {
28
+ Description string
29
+ Input []string
30
+ Expected []string
31
+ }
32
+ }
33
+
34
+ var suitCharToSymbol = map[byte]string{'C': "♧", 'D': "♢", 'H': "♡", 'S': "♤"}
35
+
36
+ // PokerHands converts hands using C/D/H/S as the suit
37
+ // to one which uses the symbols ♧ / ♢ / ♡ / ♤ instead.
38
+ // For example, "2H 3C 4D 5S 9S" is converted to "2♡ 3♧ 4♢ 5♤ 9♤".
39
+ func PokerHands(inputHands []string) []string {
40
+ hands := make([]string, len(inputHands))
41
+ for i, inputHand := range inputHands {
42
+ cards := strings.Fields(inputHand)
43
+ handStr := ""
44
+ for j, c := range cards {
45
+ rankStr := c[0 : len(c)-1]
46
+ handStr += rankStr + suitCharToSymbol[c[len(c)-1]]
47
+ if j != len(cards)-1 {
48
+ handStr += " "
49
+ }
50
+ }
51
+ hands[i] = handStr
52
+ }
53
+ return hands
54
+ }
55
+
56
+ // template applied to above data structure generates the Go test cases
57
+ var tmpl = `package poker
58
+
59
+ {{.Header}}
60
+
61
+ type validTestCase struct {
62
+ name string
63
+ hands []string
64
+ best []string
65
+ }
66
+
67
+ var validTestCases = []validTestCase {
68
+ {{range .J.Cases}}{
69
+ name: "{{.Description}}",
70
+ hands: []string{
71
+ {{range pokerHands .Input}} {{printf "%q" .}},
72
+ {{end}} },
73
+ best: {{pokerHands .Expected | printf "%#v"}},
74
+ },
75
+ {{end}}}
76
+ `
@@ -0,0 +1,240 @@
1
+ package poker
2
+
3
+ // Source: exercism/x-common
4
+ // Commit: d078ba8 poker: Add canonical-data (#793)
5
+ // x-common version: 1.0.0
6
+
7
+ type validTestCase struct {
8
+ name string
9
+ hands []string
10
+ best []string
11
+ }
12
+
13
+ var validTestCases = []validTestCase{
14
+ {
15
+ name: "single hand always wins",
16
+ hands: []string{
17
+ "4♤ 5♤ 7♡ 8♢ J♧",
18
+ },
19
+ best: []string{"4♤ 5♤ 7♡ 8♢ J♧"},
20
+ },
21
+ {
22
+ name: "highest card out of all hands wins",
23
+ hands: []string{
24
+ "4♢ 5♤ 6♤ 8♢ 3♧",
25
+ "2♤ 4♧ 7♤ 9♡ 10♡",
26
+ "3♤ 4♤ 5♢ 6♡ J♡",
27
+ },
28
+ best: []string{"3♤ 4♤ 5♢ 6♡ J♡"},
29
+ },
30
+ {
31
+ name: "a tie has multiple winners",
32
+ hands: []string{
33
+ "4♢ 5♤ 6♤ 8♢ 3♧",
34
+ "2♤ 4♧ 7♤ 9♡ 10♡",
35
+ "3♤ 4♤ 5♢ 6♡ J♡",
36
+ "3♡ 4♡ 5♧ 6♧ J♢",
37
+ },
38
+ best: []string{"3♤ 4♤ 5♢ 6♡ J♡", "3♡ 4♡ 5♧ 6♧ J♢"},
39
+ },
40
+ {
41
+ name: "multiple hands with the same high cards, tie compares next highest ranked, down to last card",
42
+ hands: []string{
43
+ "3♤ 5♡ 6♤ 8♢ 7♡",
44
+ "2♤ 5♢ 6♢ 8♧ 7♤",
45
+ },
46
+ best: []string{"3♤ 5♡ 6♤ 8♢ 7♡"},
47
+ },
48
+ {
49
+ name: "one pair beats high card",
50
+ hands: []string{
51
+ "4♤ 5♡ 6♧ 8♢ K♡",
52
+ "2♤ 4♡ 6♤ 4♢ J♡",
53
+ },
54
+ best: []string{"2♤ 4♡ 6♤ 4♢ J♡"},
55
+ },
56
+ {
57
+ name: "highest pair wins",
58
+ hands: []string{
59
+ "4♤ 2♡ 6♤ 2♢ J♡",
60
+ "2♤ 4♡ 6♧ 4♢ J♢",
61
+ },
62
+ best: []string{"2♤ 4♡ 6♧ 4♢ J♢"},
63
+ },
64
+ {
65
+ name: "two pairs beats one pair",
66
+ hands: []string{
67
+ "2♤ 8♡ 6♤ 8♢ J♡",
68
+ "4♤ 5♡ 4♧ 8♧ 5♧",
69
+ },
70
+ best: []string{"4♤ 5♡ 4♧ 8♧ 5♧"},
71
+ },
72
+ {
73
+ name: "both hands have two pairs, highest ranked pair wins",
74
+ hands: []string{
75
+ "2♤ 8♡ 2♢ 8♢ 3♡",
76
+ "4♤ 5♡ 4♧ 8♤ 5♢",
77
+ },
78
+ best: []string{"2♤ 8♡ 2♢ 8♢ 3♡"},
79
+ },
80
+ {
81
+ name: "both hands have two pairs, with the same highest ranked pair, tie goes to low pair",
82
+ hands: []string{
83
+ "2♤ Q♤ 2♧ Q♢ J♡",
84
+ "J♢ Q♡ J♤ 8♢ Q♧",
85
+ },
86
+ best: []string{"J♢ Q♡ J♤ 8♢ Q♧"},
87
+ },
88
+ {
89
+ name: "both hands have two identically ranked pairs, tie goes to remaining card (kicker)",
90
+ hands: []string{
91
+ "J♢ Q♡ J♤ 8♢ Q♧",
92
+ "J♤ Q♤ J♧ 2♢ Q♢",
93
+ },
94
+ best: []string{"J♢ Q♡ J♤ 8♢ Q♧"},
95
+ },
96
+ {
97
+ name: "three of a kind beats two pair",
98
+ hands: []string{
99
+ "2♤ 8♡ 2♡ 8♢ J♡",
100
+ "4♤ 5♡ 4♧ 8♤ 4♡",
101
+ },
102
+ best: []string{"4♤ 5♡ 4♧ 8♤ 4♡"},
103
+ },
104
+ {
105
+ name: "both hands have three of a kind, tie goes to highest ranked triplet",
106
+ hands: []string{
107
+ "2♤ 2♡ 2♧ 8♢ J♡",
108
+ "4♤ A♡ A♤ 8♧ A♢",
109
+ },
110
+ best: []string{"4♤ A♡ A♤ 8♧ A♢"},
111
+ },
112
+ {
113
+ name: "with multiple decks, two players can have same three of a kind, ties go to highest remaining cards",
114
+ hands: []string{
115
+ "4♤ A♡ A♤ 7♧ A♢",
116
+ "4♤ A♡ A♤ 8♧ A♢",
117
+ },
118
+ best: []string{"4♤ A♡ A♤ 8♧ A♢"},
119
+ },
120
+ {
121
+ name: "a straight beats three of a kind",
122
+ hands: []string{
123
+ "4♤ 5♡ 4♧ 8♢ 4♡",
124
+ "3♤ 4♢ 2♤ 6♢ 5♧",
125
+ },
126
+ best: []string{"3♤ 4♢ 2♤ 6♢ 5♧"},
127
+ },
128
+ {
129
+ name: "aces can end a straight (10 J Q K A)",
130
+ hands: []string{
131
+ "4♤ 5♡ 4♧ 8♢ 4♡",
132
+ "10♢ J♡ Q♤ K♢ A♧",
133
+ },
134
+ best: []string{"10♢ J♡ Q♤ K♢ A♧"},
135
+ },
136
+ {
137
+ name: "aces can start a straight (A 2 3 4 5)",
138
+ hands: []string{
139
+ "4♤ 5♡ 4♧ 8♢ 4♡",
140
+ "4♢ A♡ 3♤ 2♢ 5♧",
141
+ },
142
+ best: []string{"4♢ A♡ 3♤ 2♢ 5♧"},
143
+ },
144
+ {
145
+ name: "both hands with a straight, tie goes to highest ranked card",
146
+ hands: []string{
147
+ "4♤ 6♧ 7♤ 8♢ 5♡",
148
+ "5♤ 7♡ 8♤ 9♢ 6♡",
149
+ },
150
+ best: []string{"5♤ 7♡ 8♤ 9♢ 6♡"},
151
+ },
152
+ {
153
+ name: "even though an ace is usually high, a 5-high straight is the lowest-scoring straight",
154
+ hands: []string{
155
+ "2♡ 3♧ 4♢ 5♢ 6♡",
156
+ "4♤ A♡ 3♤ 2♢ 5♡",
157
+ },
158
+ best: []string{"2♡ 3♧ 4♢ 5♢ 6♡"},
159
+ },
160
+ {
161
+ name: "flush beats a straight",
162
+ hands: []string{
163
+ "4♧ 6♡ 7♢ 8♢ 5♡",
164
+ "2♤ 4♤ 5♤ 6♤ 7♤",
165
+ },
166
+ best: []string{"2♤ 4♤ 5♤ 6♤ 7♤"},
167
+ },
168
+ {
169
+ name: "both hands have a flush, tie goes to high card, down to the last one if necessary",
170
+ hands: []string{
171
+ "4♡ 7♡ 8♡ 9♡ 6♡",
172
+ "2♤ 4♤ 5♤ 6♤ 7♤",
173
+ },
174
+ best: []string{"4♡ 7♡ 8♡ 9♡ 6♡"},
175
+ },
176
+ {
177
+ name: "full house beats a flush",
178
+ hands: []string{
179
+ "3♡ 6♡ 7♡ 8♡ 5♡",
180
+ "4♤ 5♡ 4♧ 5♢ 4♡",
181
+ },
182
+ best: []string{"4♤ 5♡ 4♧ 5♢ 4♡"},
183
+ },
184
+ {
185
+ name: "both hands have a full house, tie goes to highest-ranked triplet",
186
+ hands: []string{
187
+ "4♡ 4♤ 4♢ 9♤ 9♢",
188
+ "5♡ 5♤ 5♢ 8♤ 8♢",
189
+ },
190
+ best: []string{"5♡ 5♤ 5♢ 8♤ 8♢"},
191
+ },
192
+ {
193
+ name: "with multiple decks, both hands have a full house with the same triplet, tie goes to the pair",
194
+ hands: []string{
195
+ "5♡ 5♤ 5♢ 9♤ 9♢",
196
+ "5♡ 5♤ 5♢ 8♤ 8♢",
197
+ },
198
+ best: []string{"5♡ 5♤ 5♢ 9♤ 9♢"},
199
+ },
200
+ {
201
+ name: "four of a kind beats a full house",
202
+ hands: []string{
203
+ "4♤ 5♡ 4♢ 5♢ 4♡",
204
+ "3♤ 3♡ 2♤ 3♢ 3♧",
205
+ },
206
+ best: []string{"3♤ 3♡ 2♤ 3♢ 3♧"},
207
+ },
208
+ {
209
+ name: "both hands have four of a kind, tie goes to high quad",
210
+ hands: []string{
211
+ "2♤ 2♡ 2♧ 8♢ 2♢",
212
+ "4♤ 5♡ 5♤ 5♢ 5♧",
213
+ },
214
+ best: []string{"4♤ 5♡ 5♤ 5♢ 5♧"},
215
+ },
216
+ {
217
+ name: "with multiple decks, both hands with identical four of a kind, tie determined by kicker",
218
+ hands: []string{
219
+ "3♤ 3♡ 2♤ 3♢ 3♧",
220
+ "3♤ 3♡ 4♤ 3♢ 3♧",
221
+ },
222
+ best: []string{"3♤ 3♡ 4♤ 3♢ 3♧"},
223
+ },
224
+ {
225
+ name: "straight flush beats four of a kind",
226
+ hands: []string{
227
+ "4♤ 5♡ 5♤ 5♢ 5♧",
228
+ "7♤ 8♤ 9♤ 6♤ 10♤",
229
+ },
230
+ best: []string{"7♤ 8♤ 9♤ 6♤ 10♤"},
231
+ },
232
+ {
233
+ name: "both hands have straight flush, tie goes to highest-ranked card",
234
+ hands: []string{
235
+ "4♡ 6♡ 7♡ 8♡ 5♡",
236
+ "5♤ 7♤ 8♤ 9♤ 6♤",
237
+ },
238
+ best: []string{"5♤ 7♤ 8♤ 9♤ 6♤"},
239
+ },
240
+ }