trackler 2.2.1.33 → 2.2.1.34
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/README.md +1 -1
- data/problem-specifications/exercises/palindrome-products/description.md +9 -3
- data/tracks/c/exercises/hamming/src/example.c +9 -8
- data/tracks/c/exercises/hamming/src/example.h +1 -1
- data/tracks/c/exercises/hamming/test/test_hamming.c +31 -7
- data/tracks/clojure/config.json +10 -0
- data/tracks/clojure/exercises/collatz-conjecture/README.md +34 -0
- data/tracks/clojure/exercises/collatz-conjecture/project.clj +4 -0
- data/tracks/clojure/exercises/collatz-conjecture/src/collatz_conjecture.clj +3 -0
- data/tracks/clojure/exercises/collatz-conjecture/src/example.clj +13 -0
- data/tracks/clojure/exercises/collatz-conjecture/test/collatz_conjecture_test.clj +29 -0
- data/tracks/coldfusion/.gitignore +1 -0
- data/tracks/coldfusion/.travis.yml +16 -4
- data/tracks/coldfusion/CONTRIBUTING.md +10 -0
- data/tracks/coldfusion/README.md +85 -6
- data/tracks/coldfusion/config.json +195 -10
- data/tracks/coldfusion/config/maintainers.json +8 -1
- data/tracks/coldfusion/docs/ABOUT.md +8 -0
- data/tracks/coldfusion/docs/EXERCISE_README_INSERT.md +15 -0
- data/tracks/coldfusion/docs/INSTALLATION.md +35 -0
- data/tracks/coldfusion/docs/LEARNING.md +37 -0
- data/tracks/coldfusion/docs/RESOURCES.md +29 -0
- data/tracks/coldfusion/docs/SNIPPET.txt +8 -0
- data/tracks/coldfusion/docs/TESTS.md +19 -0
- data/tracks/coldfusion/exercises/acronym/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/acronym/Acronym.cfc +13 -0
- data/tracks/coldfusion/exercises/acronym/AcronymTest.cfc +43 -0
- data/tracks/coldfusion/exercises/acronym/Solution.cfc +22 -0
- data/tracks/coldfusion/exercises/acronym/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/acronym/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/acronym/box.json +8 -0
- data/tracks/coldfusion/exercises/acronym/index.cfm +37 -0
- data/tracks/coldfusion/exercises/atbash-cipher/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/atbash-cipher/AtbashCipher.cfc +14 -0
- data/tracks/coldfusion/exercises/atbash-cipher/AtbashCipherTest.cfc +71 -0
- data/tracks/coldfusion/exercises/atbash-cipher/Solution.cfc +56 -0
- data/tracks/coldfusion/exercises/atbash-cipher/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/atbash-cipher/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/atbash-cipher/box.json +8 -0
- data/tracks/coldfusion/exercises/atbash-cipher/index.cfm +37 -0
- data/tracks/coldfusion/exercises/diamond/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/diamond/Diamond.cfc +13 -0
- data/tracks/coldfusion/exercises/diamond/DiamondTest.cfc +35 -0
- data/tracks/coldfusion/exercises/diamond/Solution.cfc +35 -0
- data/tracks/coldfusion/exercises/diamond/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/diamond/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/diamond/box.json +8 -0
- data/tracks/coldfusion/exercises/diamond/index.cfm +37 -0
- data/tracks/coldfusion/exercises/difference-of-squares/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/difference-of-squares/DifferenceOfSquares.cfc +18 -0
- data/tracks/coldfusion/exercises/difference-of-squares/DifferenceOfSquaresTest.cfc +63 -0
- data/tracks/coldfusion/exercises/difference-of-squares/Solution.cfc +28 -0
- data/tracks/coldfusion/exercises/difference-of-squares/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/difference-of-squares/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/difference-of-squares/box.json +8 -0
- data/tracks/coldfusion/exercises/difference-of-squares/index.cfm +37 -0
- data/tracks/coldfusion/exercises/flatten-array/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/flatten-array/FlattenArray.cfc +13 -0
- data/tracks/coldfusion/exercises/flatten-array/FlattenArrayTest.cfc +42 -0
- data/tracks/coldfusion/exercises/flatten-array/Solution.cfc +26 -0
- data/tracks/coldfusion/exercises/flatten-array/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/flatten-array/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/flatten-array/box.json +8 -0
- data/tracks/coldfusion/exercises/flatten-array/index.cfm +37 -0
- data/tracks/coldfusion/exercises/gigasecond/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/gigasecond/Gigasecond.cfc +13 -0
- data/tracks/coldfusion/exercises/gigasecond/GigasecondTest.cfc +39 -0
- data/tracks/coldfusion/exercises/gigasecond/Solution.cfc +16 -0
- data/tracks/coldfusion/exercises/gigasecond/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/gigasecond/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/gigasecond/box.json +8 -0
- data/tracks/coldfusion/exercises/gigasecond/index.cfm +37 -0
- data/tracks/coldfusion/exercises/grains/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/grains/Grains.cfc +14 -0
- data/tracks/coldfusion/exercises/grains/GrainsTest.cfc +63 -0
- data/tracks/coldfusion/exercises/grains/Solution.cfc +22 -0
- data/tracks/coldfusion/exercises/grains/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/grains/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/grains/box.json +8 -0
- data/tracks/coldfusion/exercises/grains/index.cfm +37 -0
- data/tracks/coldfusion/exercises/hamming/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/hamming/Hamming.cfc +13 -0
- data/tracks/coldfusion/exercises/hamming/HammingTest.cfc +75 -0
- data/tracks/coldfusion/exercises/hamming/Solution.cfc +25 -0
- data/tracks/coldfusion/exercises/hamming/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/hamming/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/hamming/box.json +8 -0
- data/tracks/coldfusion/exercises/hamming/index.cfm +37 -0
- data/tracks/coldfusion/exercises/hello-world/HelloWorld.cfc +13 -0
- data/tracks/coldfusion/exercises/hello-world/HelloWorldTest.cfc +18 -0
- data/tracks/coldfusion/exercises/hello-world/Solution.cfc +13 -0
- data/tracks/coldfusion/exercises/hello-world/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/hello-world/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/hello-world/box.json +8 -0
- data/tracks/coldfusion/exercises/hello-world/index.cfm +37 -0
- data/tracks/coldfusion/exercises/isogram/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/isogram/Isogram.cfc +13 -0
- data/tracks/coldfusion/exercises/isogram/IsogramTest.cfc +55 -0
- data/tracks/coldfusion/exercises/isogram/Solution.cfc +23 -0
- data/tracks/coldfusion/exercises/isogram/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/isogram/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/isogram/box.json +8 -0
- data/tracks/coldfusion/exercises/isogram/index.cfm +37 -0
- data/tracks/coldfusion/exercises/largest-series-product/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/largest-series-product/LargestSeriesProduct.cfc +13 -0
- data/tracks/coldfusion/exercises/largest-series-product/LargestSeriesProductTest.cfc +75 -0
- data/tracks/coldfusion/exercises/largest-series-product/Solution.cfc +41 -0
- data/tracks/coldfusion/exercises/largest-series-product/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/largest-series-product/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/largest-series-product/box.json +8 -0
- data/tracks/coldfusion/exercises/largest-series-product/index.cfm +37 -0
- data/tracks/coldfusion/exercises/leap/Leap.cfc +15 -0
- data/tracks/coldfusion/exercises/leap/LeapTest.cfc +39 -0
- data/tracks/coldfusion/exercises/leap/Solution.cfc +19 -0
- data/tracks/coldfusion/exercises/leap/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/leap/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/leap/box.json +8 -0
- data/tracks/coldfusion/exercises/leap/index.cfm +37 -0
- data/tracks/coldfusion/exercises/luhn/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/luhn/Luhn.cfc +13 -0
- data/tracks/coldfusion/exercises/luhn/LuhnTest.cfc +67 -0
- data/tracks/coldfusion/exercises/luhn/Solution.cfc +38 -0
- data/tracks/coldfusion/exercises/luhn/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/luhn/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/luhn/box.json +8 -0
- data/tracks/coldfusion/exercises/luhn/index.cfm +37 -0
- data/tracks/coldfusion/exercises/nth-prime/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/nth-prime/NthPrime.cfc +13 -0
- data/tracks/coldfusion/exercises/nth-prime/NthPrimeTest.cfc +35 -0
- data/tracks/coldfusion/exercises/nth-prime/Solution.cfc +33 -0
- data/tracks/coldfusion/exercises/nth-prime/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/nth-prime/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/nth-prime/box.json +8 -0
- data/tracks/coldfusion/exercises/nth-prime/index.cfm +37 -0
- data/tracks/coldfusion/exercises/pangram/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/pangram/Pangram.cfc +13 -0
- data/tracks/coldfusion/exercises/pangram/PangramTest.cfc +55 -0
- data/tracks/coldfusion/exercises/pangram/Solution.cfc +21 -0
- data/tracks/coldfusion/exercises/pangram/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/pangram/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/pangram/box.json +8 -0
- data/tracks/coldfusion/exercises/pangram/index.cfm +37 -0
- data/tracks/coldfusion/exercises/pig-latin/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/pig-latin/PigLatin.cfc +13 -0
- data/tracks/coldfusion/exercises/pig-latin/PigLatinTest.cfc +115 -0
- data/tracks/coldfusion/exercises/pig-latin/Solution.cfc +30 -0
- data/tracks/coldfusion/exercises/pig-latin/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/pig-latin/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/pig-latin/box.json +8 -0
- data/tracks/coldfusion/exercises/pig-latin/index.cfm +37 -0
- data/tracks/coldfusion/exercises/raindrops/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/raindrops/Raindrops.cfc +13 -0
- data/tracks/coldfusion/exercises/raindrops/RaindropsTest.cfc +87 -0
- data/tracks/coldfusion/exercises/raindrops/Solution.cfc +33 -0
- data/tracks/coldfusion/exercises/raindrops/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/raindrops/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/raindrops/box.json +8 -0
- data/tracks/coldfusion/exercises/raindrops/index.cfm +37 -0
- data/tracks/coldfusion/exercises/rna-transcription/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/rna-transcription/RnaTranscription.cfc +13 -0
- data/tracks/coldfusion/exercises/rna-transcription/RnaTranscriptionTest.cfc +47 -0
- data/tracks/coldfusion/exercises/rna-transcription/Solution.cfc +35 -0
- data/tracks/coldfusion/exercises/rna-transcription/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/rna-transcription/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/rna-transcription/box.json +8 -0
- data/tracks/coldfusion/exercises/rna-transcription/index.cfm +37 -0
- data/tracks/coldfusion/exercises/saddle-points/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/saddle-points/SaddlePoints.cfc +13 -0
- data/tracks/coldfusion/exercises/saddle-points/SaddlePointsTest.cfc +35 -0
- data/tracks/coldfusion/exercises/saddle-points/Solution.cfc +59 -0
- data/tracks/coldfusion/exercises/saddle-points/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/saddle-points/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/saddle-points/box.json +8 -0
- data/tracks/coldfusion/exercises/saddle-points/index.cfm +37 -0
- data/tracks/coldfusion/exercises/scrabble-score/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/scrabble-score/ScrabbleScore.cfc +13 -0
- data/tracks/coldfusion/exercises/scrabble-score/ScrabbleScoreTest.cfc +59 -0
- data/tracks/coldfusion/exercises/scrabble-score/Solution.cfc +50 -0
- data/tracks/coldfusion/exercises/scrabble-score/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/scrabble-score/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/scrabble-score/box.json +8 -0
- data/tracks/coldfusion/exercises/scrabble-score/index.cfm +37 -0
- data/tracks/coldfusion/exercises/secret-handshake/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/secret-handshake/SecretHandshake.cfc +13 -0
- data/tracks/coldfusion/exercises/secret-handshake/SecretHandshakeTest.cfc +63 -0
- data/tracks/coldfusion/exercises/secret-handshake/Solution.cfc +31 -0
- data/tracks/coldfusion/exercises/secret-handshake/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/secret-handshake/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/secret-handshake/box.json +8 -0
- data/tracks/coldfusion/exercises/secret-handshake/index.cfm +37 -0
- data/tracks/coldfusion/exercises/space-age/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/space-age/Solution.cfc +28 -0
- data/tracks/coldfusion/exercises/space-age/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/space-age/SpaceAge.cfc +13 -0
- data/tracks/coldfusion/exercises/space-age/SpaceAgeTest.cfc +47 -0
- data/tracks/coldfusion/exercises/space-age/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/space-age/box.json +8 -0
- data/tracks/coldfusion/exercises/space-age/index.cfm +37 -0
- data/tracks/coldfusion/exercises/sum-of-multiples/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/sum-of-multiples/Solution.cfc +27 -0
- data/tracks/coldfusion/exercises/sum-of-multiples/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/sum-of-multiples/SumOfMultiples.cfc +13 -0
- data/tracks/coldfusion/exercises/sum-of-multiples/SumOfMultiplesTest.cfc +63 -0
- data/tracks/coldfusion/exercises/sum-of-multiples/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/sum-of-multiples/box.json +8 -0
- data/tracks/coldfusion/exercises/sum-of-multiples/index.cfm +37 -0
- data/tracks/coldfusion/exercises/triangle/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/exercises/triangle/Solution.cfc +53 -0
- data/tracks/coldfusion/exercises/triangle/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/exercises/triangle/TestRunner.cfc +103 -0
- data/tracks/coldfusion/exercises/triangle/Triangle.cfc +18 -0
- data/tracks/coldfusion/exercises/triangle/TriangleTest.cfc +95 -0
- data/tracks/coldfusion/exercises/triangle/box.json +8 -0
- data/tracks/coldfusion/exercises/triangle/index.cfm +37 -0
- data/tracks/coldfusion/tasks/GenerateTests.cfc +179 -0
- data/tracks/coldfusion/tasks/ScaffoldExercise.cfc +85 -0
- data/tracks/coldfusion/tasks/TestAllSolutions.cfc +24 -0
- data/tracks/coldfusion/tasks/exercise_template/.meta/HINTS.md +0 -0
- data/tracks/coldfusion/tasks/exercise_template/@@name@@.cfc +13 -0
- data/tracks/coldfusion/tasks/exercise_template/@@name@@Test.cfc +15 -0
- data/tracks/coldfusion/tasks/exercise_template/Solution.cfc +6 -0
- data/tracks/coldfusion/tasks/exercise_template/SolutionTest.cfc +7 -0
- data/tracks/coldfusion/tasks/exercise_template/TestRunner.cfc +103 -0
- data/tracks/coldfusion/tasks/exercise_template/box.json +8 -0
- data/tracks/coldfusion/tasks/exercise_template/index.cfm +37 -0
- data/tracks/common-lisp/config.json +12 -0
- data/tracks/common-lisp/exercises/collatz-conjecture/README.md +84 -0
- data/tracks/common-lisp/exercises/collatz-conjecture/collatz-conjecture-test.lisp +31 -0
- data/tracks/common-lisp/exercises/collatz-conjecture/collatz-conjecture.lisp +7 -0
- data/tracks/common-lisp/exercises/collatz-conjecture/example.lisp +14 -0
- data/tracks/csharp/exercises/clock/Clock.cs +20 -4
- data/tracks/csharp/exercises/clock/ClockTest.cs +290 -55
- data/tracks/csharp/exercises/clock/Example.cs +11 -8
- data/tracks/csharp/generators/Exercises/Clock.cs +75 -0
- data/tracks/csharp/generators/Output/FormattingExtensions.cs +0 -1
- data/tracks/csharp/generators/Program.cs +2 -1
- data/tracks/haskell/config.json +10 -0
- data/tracks/haskell/exercises/collatz-conjecture/README.md +87 -0
- data/tracks/haskell/exercises/collatz-conjecture/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/collatz-conjecture/examples/success-standard/src/CollatzConjecture.hs +9 -0
- data/tracks/haskell/exercises/collatz-conjecture/package.yaml +20 -0
- data/tracks/haskell/exercises/collatz-conjecture/src/CollatzConjecture.hs +4 -0
- data/tracks/haskell/exercises/collatz-conjecture/stack.yaml +1 -0
- data/tracks/haskell/exercises/collatz-conjecture/test/Tests.hs +52 -0
- data/tracks/idris/docs/SNIPPET.txt +10 -0
- data/tracks/rust/README.md +83 -2
- data/tracks/rust/config.json +24 -0
- data/tracks/rust/exercises/perfect-numbers/.gitignore +7 -0
- data/tracks/rust/exercises/perfect-numbers/Cargo.toml +5 -0
- data/tracks/rust/exercises/perfect-numbers/README.md +56 -0
- data/tracks/rust/exercises/perfect-numbers/example.rs +20 -0
- data/tracks/rust/exercises/perfect-numbers/src/lib.rs +0 -0
- data/tracks/rust/exercises/perfect-numbers/tests/perfect-numbers.rs +33 -0
- data/tracks/rust/exercises/poker/.gitignore +7 -0
- data/tracks/rust/exercises/poker/.meta/hints.md +8 -0
- data/tracks/rust/exercises/poker/Cargo-example.toml +8 -0
- data/tracks/rust/exercises/poker/Cargo.toml +6 -0
- data/tracks/rust/exercises/poker/README.md +54 -0
- data/tracks/rust/exercises/poker/example.rs +341 -0
- data/tracks/rust/exercises/poker/src/lib.rs +7 -0
- data/tracks/rust/exercises/poker/tests/poker.rs +298 -0
- metadata +242 -5
- data/tracks/coldfusion/exercises/leap/example.cfc +0 -11
- data/tracks/coldfusion/exercises/leap/leap.cfc +0 -5
- data/tracks/coldfusion/exercises/leap/leap_tests.cfc +0 -35
data/tracks/rust/config.json
CHANGED
@@ -167,6 +167,16 @@
|
|
167
167
|
"loop"
|
168
168
|
]
|
169
169
|
},
|
170
|
+
{
|
171
|
+
"uuid": "20e7d347-b80a-4656-ac34-0825126939ff",
|
172
|
+
"slug": "perfect-numbers",
|
173
|
+
"core": false,
|
174
|
+
"unlocked_by": null,
|
175
|
+
"difficulty": 4,
|
176
|
+
"topics": [
|
177
|
+
"Mathematics"
|
178
|
+
]
|
179
|
+
},
|
170
180
|
{
|
171
181
|
"uuid": "543a3ca2-fb9b-4f20-a873-ff23595d41df",
|
172
182
|
"slug": "clock",
|
@@ -623,6 +633,20 @@
|
|
623
633
|
"topics": [
|
624
634
|
]
|
625
635
|
},
|
636
|
+
{
|
637
|
+
"uuid": "0a33f3ac-cedd-4a40-a132-9d044b0e9977",
|
638
|
+
"slug": "poker",
|
639
|
+
"core": false,
|
640
|
+
"unlocked_by": null,
|
641
|
+
"difficulty": 6,
|
642
|
+
"topics": [
|
643
|
+
"lifetimes",
|
644
|
+
"struct",
|
645
|
+
"string parsing",
|
646
|
+
"enum",
|
647
|
+
"traits"
|
648
|
+
]
|
649
|
+
},
|
626
650
|
{
|
627
651
|
"uuid": "f3172997-91f5-4941-a76e-91c4b8eed401",
|
628
652
|
"slug": "anagram",
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Perfect Numbers
|
2
|
+
|
3
|
+
Determine if a number is perfect, abundant, or deficient based on
|
4
|
+
Nicomachus' (60 - 120 CE) classification scheme for natural numbers.
|
5
|
+
|
6
|
+
The Greek mathematician [Nicomachus](https://en.wikipedia.org/wiki/Nicomachus) devised a classification scheme for natural numbers, identifying each as belonging uniquely to the categories of **perfect**, **abundant**, or **deficient** based on their [aliquot sum](https://en.wikipedia.org/wiki/Aliquot_sum). The aliquot sum is defined as the sum of the factors of a number not including the number itself. For example, the aliquot sum of 15 is (1 + 3 + 5) = 9
|
7
|
+
|
8
|
+
- **Perfect**: aliquot sum = number
|
9
|
+
- 6 is a perfect number because (1 + 2 + 3) = 6
|
10
|
+
- 28 is a perfect number because (1 + 2 + 4 + 7 + 14) = 28
|
11
|
+
- **Abundant**: aliquot sum > number
|
12
|
+
- 12 is an abundant number because (1 + 2 + 3 + 4 + 6) = 16
|
13
|
+
- 24 is an abundant number because (1 + 2 + 3 + 4 + 6 + 8 + 12) = 36
|
14
|
+
- **Deficient**: aliquot sum < number
|
15
|
+
- 8 is a deficient number because (1 + 2 + 4) = 7
|
16
|
+
- Prime numbers are deficient
|
17
|
+
|
18
|
+
Implement a way to determine whether a given number is **perfect**. Depending on your language track, you may also need to implement a way to determine whether a given number is **abundant** or **deficient**.
|
19
|
+
|
20
|
+
## Rust Installation
|
21
|
+
|
22
|
+
Refer to the [exercism help page][help-page] for Rust installation and learning
|
23
|
+
resources.
|
24
|
+
|
25
|
+
## Writing the Code
|
26
|
+
|
27
|
+
Execute the tests with:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
$ cargo test
|
31
|
+
```
|
32
|
+
|
33
|
+
All but the first test have been ignored. After you get the first test to
|
34
|
+
pass, remove the ignore flag (`#[ignore]`) from the next test and get the tests
|
35
|
+
to pass again. The test file is located in the `tests` directory. You can
|
36
|
+
also remove the ignore flag from all the tests to get them to run all at once
|
37
|
+
if you wish.
|
38
|
+
|
39
|
+
Make sure to read the [Crates and Modules](https://doc.rust-lang.org/stable/book/crates-and-modules.html) chapter if you
|
40
|
+
haven't already, it will help you with organizing your files.
|
41
|
+
|
42
|
+
## Feedback, Issues, Pull Requests
|
43
|
+
|
44
|
+
The [exercism/rust](https://github.com/exercism/rust) repository on GitHub is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the [rust track team](https://github.com/orgs/exercism/teams/rust) are happy to help!
|
45
|
+
|
46
|
+
If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
|
47
|
+
|
48
|
+
[help-page]: http://exercism.io/languages/rust
|
49
|
+
[crates-and-modules]: http://doc.rust-lang.org/stable/book/crates-and-modules.html
|
50
|
+
|
51
|
+
## Source
|
52
|
+
|
53
|
+
Taken from Chapter 2 of Functional Thinking by Neal Ford. [http://shop.oreilly.com/product/0636920029687.do](http://shop.oreilly.com/product/0636920029687.do)
|
54
|
+
|
55
|
+
## Submitting Incomplete Solutions
|
56
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
pub fn classify(num: u64) -> Result<Classification, & 'static str> {
|
2
|
+
if num == 0 {
|
3
|
+
return Err("Number must be positive");
|
4
|
+
}
|
5
|
+
let sum: u64 = (1..num).filter(|i| num%i == 0).sum();
|
6
|
+
if sum == num {
|
7
|
+
Ok(Classification::Perfect)
|
8
|
+
} else if sum < num {
|
9
|
+
Ok(Classification::Deficient)
|
10
|
+
} else {
|
11
|
+
Ok(Classification::Abundant)
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
#[derive(Debug, PartialEq, Eq)]
|
16
|
+
pub enum Classification {
|
17
|
+
Abundant,
|
18
|
+
Perfect,
|
19
|
+
Deficient
|
20
|
+
}
|
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
extern crate perfect_numbers;
|
2
|
+
|
3
|
+
use perfect_numbers::{Classification, classify};
|
4
|
+
|
5
|
+
#[test]
|
6
|
+
fn basic() {
|
7
|
+
assert_eq!(classify(0), Err("Number must be positive"));
|
8
|
+
}
|
9
|
+
|
10
|
+
#[test]
|
11
|
+
#[ignore]
|
12
|
+
fn test_all() {
|
13
|
+
struct TestClassification {
|
14
|
+
num: u64,
|
15
|
+
result: perfect_numbers::Classification
|
16
|
+
}
|
17
|
+
let test_table: Vec<TestClassification> = vec![
|
18
|
+
TestClassification { num: 6, result: Classification::Perfect },
|
19
|
+
TestClassification { num: 28, result: Classification::Perfect },
|
20
|
+
TestClassification { num: 33550336, result: Classification::Perfect },
|
21
|
+
TestClassification { num: 12, result: Classification::Abundant },
|
22
|
+
TestClassification { num: 30, result: Classification::Abundant },
|
23
|
+
TestClassification { num: 33550335, result: Classification::Abundant },
|
24
|
+
TestClassification { num: 2, result: Classification::Deficient },
|
25
|
+
TestClassification { num: 4, result: Classification::Deficient },
|
26
|
+
TestClassification { num: 32, result: Classification::Deficient },
|
27
|
+
TestClassification { num: 33550337, result: Classification::Deficient },
|
28
|
+
TestClassification { num: 1, result: Classification::Deficient },
|
29
|
+
];
|
30
|
+
for t in test_table {
|
31
|
+
assert_eq!(classify(t.num), Ok(t.result));
|
32
|
+
}
|
33
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
## Hints
|
2
|
+
|
3
|
+
- Ranking a list of poker hands can be considered a sorting problem.
|
4
|
+
- Rust provides the [sort](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort) method for `Vec<T> where T: Ord`.
|
5
|
+
- [`Ord` types](https://doc.rust-lang.org/std/cmp/trait.Ord.html) are form a [total order](https://en.wikipedia.org/wiki/Total_order): exactly one of `a < b`, `a == b`, or `a > b` must be true.
|
6
|
+
- Poker hands do not conform to a total order: it is possible for two hands to be non-equal but have equal sort order. Example: `3S 4S 5D 6H JH"`, `"3H 4H 5C 6C JD"`.
|
7
|
+
- Rust provides the [`PartialOrd` trait](https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html) to handle the case of sortable things which do not have a total order. However, it doesn't provide a standard `sort` method for `Vec<T> where T: PartialOrd`. The standard idiom to sort a vector in this case is `your_vec.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::{Less|Equal|Greater}));`, depending on your needs. `
|
8
|
+
- You might consider implementing a type representing a poker hand which implements `PartialOrd`.
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Poker
|
2
|
+
|
3
|
+
Pick the best hand(s) from a list of poker hands.
|
4
|
+
|
5
|
+
See [wikipedia](https://en.wikipedia.org/wiki/List_of_poker_hands) for an
|
6
|
+
overview of poker hands.
|
7
|
+
|
8
|
+
## Hints
|
9
|
+
|
10
|
+
- Ranking a list of poker hands can be considered a sorting problem.
|
11
|
+
- Rust provides the [sort](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort) method for `Vec<T> where T: Ord`.
|
12
|
+
- [`Ord` types](https://doc.rust-lang.org/std/cmp/trait.Ord.html) are form a [total order](https://en.wikipedia.org/wiki/Total_order): exactly one of `a < b`, `a == b`, or `a > b` must be true.
|
13
|
+
- Poker hands do not conform to a total order: it is possible for two hands to be non-equal but have equal sort order. Example: `3S 4S 5D 6H JH"`, `"3H 4H 5C 6C JD"`.
|
14
|
+
- Rust provides the [`PartialOrd` trait](https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html) to handle the case of sortable things which do not have a total order. However, it doesn't provide a standard `sort` method for `Vec<T> where T: PartialOrd`. The standard idiom to sort a vector in this case is `your_vec.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::{Less|Equal|Greater}));`, depending on your needs. `
|
15
|
+
- You might consider implementing a type representing a poker hand which implements `PartialOrd`.
|
16
|
+
|
17
|
+
|
18
|
+
## Rust Installation
|
19
|
+
|
20
|
+
Refer to the [exercism help page][help-page] for Rust installation and learning
|
21
|
+
resources.
|
22
|
+
|
23
|
+
## Writing the Code
|
24
|
+
|
25
|
+
Execute the tests with:
|
26
|
+
|
27
|
+
```bash
|
28
|
+
$ cargo test
|
29
|
+
```
|
30
|
+
|
31
|
+
All but the first test have been ignored. After you get the first test to
|
32
|
+
pass, remove the ignore flag (`#[ignore]`) from the next test and get the tests
|
33
|
+
to pass again. The test file is located in the `tests` directory. You can
|
34
|
+
also remove the ignore flag from all the tests to get them to run all at once
|
35
|
+
if you wish.
|
36
|
+
|
37
|
+
Make sure to read the [Crates and Modules](https://doc.rust-lang.org/stable/book/crates-and-modules.html) chapter if you
|
38
|
+
haven't already, it will help you with organizing your files.
|
39
|
+
|
40
|
+
## Feedback, Issues, Pull Requests
|
41
|
+
|
42
|
+
The [exercism/rust](https://github.com/exercism/rust) repository on GitHub is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the [rust track team](https://github.com/orgs/exercism/teams/rust) are happy to help!
|
43
|
+
|
44
|
+
If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
|
45
|
+
|
46
|
+
[help-page]: http://exercism.io/languages/rust
|
47
|
+
[crates-and-modules]: http://doc.rust-lang.org/stable/book/crates-and-modules.html
|
48
|
+
|
49
|
+
## Source
|
50
|
+
|
51
|
+
Inspired by the training course from Udacity. [https://www.udacity.com/course/viewer#!/c-cs212/](https://www.udacity.com/course/viewer#!/c-cs212/)
|
52
|
+
|
53
|
+
## Submitting Incomplete Solutions
|
54
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,341 @@
|
|
1
|
+
use std::fmt;
|
2
|
+
use std::cmp::Ordering;
|
3
|
+
|
4
|
+
#[macro_use]
|
5
|
+
extern crate try_opt;
|
6
|
+
|
7
|
+
extern crate counter;
|
8
|
+
use counter::Counter;
|
9
|
+
|
10
|
+
/// Given a list of poker hands, return a list of those hands which win.
|
11
|
+
///
|
12
|
+
/// Note the type signature: this function should return _the same_ reference to
|
13
|
+
/// the winning hand(s) as were passed in, not reconstructed strings which happen to be equal.
|
14
|
+
pub fn winning_hands<'a>(hands: &[&'a str]) -> Option<Vec<&'a str>> {
|
15
|
+
let mut hands = try_opt!(
|
16
|
+
hands
|
17
|
+
.iter()
|
18
|
+
.map(|source| Hand::try_from(source))
|
19
|
+
.collect::<Option<Vec<Hand>>>()
|
20
|
+
);
|
21
|
+
hands.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Less));
|
22
|
+
hands.last().map(|last| {
|
23
|
+
hands
|
24
|
+
.iter()
|
25
|
+
.rev()
|
26
|
+
.take_while(|&item| item.partial_cmp(last) == Some(Ordering::Equal))
|
27
|
+
.map(|hand| hand.source)
|
28
|
+
.collect()
|
29
|
+
})
|
30
|
+
}
|
31
|
+
|
32
|
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy, Hash)]
|
33
|
+
enum Suit {
|
34
|
+
Spades,
|
35
|
+
Clubs,
|
36
|
+
Diamonds,
|
37
|
+
Hearts,
|
38
|
+
}
|
39
|
+
|
40
|
+
impl Suit {
|
41
|
+
fn try_from(source: &str) -> Option<Suit> {
|
42
|
+
use Suit::*;
|
43
|
+
match source {
|
44
|
+
"S" => Some(Spades),
|
45
|
+
"C" => Some(Clubs),
|
46
|
+
"D" => Some(Diamonds),
|
47
|
+
"H" => Some(Hearts),
|
48
|
+
_ => None,
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
impl fmt::Display for Suit {
|
54
|
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
55
|
+
use Suit::*;
|
56
|
+
write!(
|
57
|
+
f,
|
58
|
+
"{}",
|
59
|
+
match *self {
|
60
|
+
Spades => "S",
|
61
|
+
Clubs => "C",
|
62
|
+
Diamonds => "D",
|
63
|
+
Hearts => "H",
|
64
|
+
}
|
65
|
+
)
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
70
|
+
enum Rank {
|
71
|
+
Number(u8),
|
72
|
+
Jack,
|
73
|
+
Queen,
|
74
|
+
King,
|
75
|
+
Ace,
|
76
|
+
}
|
77
|
+
|
78
|
+
impl Rank {
|
79
|
+
fn try_from(source: &str) -> Option<Rank> {
|
80
|
+
use Rank::*;
|
81
|
+
match source {
|
82
|
+
"A" => Some(Ace),
|
83
|
+
"K" => Some(King),
|
84
|
+
"Q" => Some(Queen),
|
85
|
+
"J" => Some(Jack),
|
86
|
+
"10" => Some(Number(10)),
|
87
|
+
"9" => Some(Number(9)),
|
88
|
+
"8" => Some(Number(8)),
|
89
|
+
"7" => Some(Number(7)),
|
90
|
+
"6" => Some(Number(6)),
|
91
|
+
"5" => Some(Number(5)),
|
92
|
+
"4" => Some(Number(4)),
|
93
|
+
"3" => Some(Number(3)),
|
94
|
+
"2" => Some(Number(2)),
|
95
|
+
_ => None,
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
fn value(&self) -> usize {
|
100
|
+
use Rank::*;
|
101
|
+
match *self {
|
102
|
+
Ace => 14,
|
103
|
+
King => 13,
|
104
|
+
Queen => 12,
|
105
|
+
Jack => 11,
|
106
|
+
Number(n) => n as usize,
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
impl fmt::Display for Rank {
|
112
|
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
113
|
+
use Rank::*;
|
114
|
+
let num_str; // early declaration to placate NLL of Number case
|
115
|
+
write!(
|
116
|
+
f,
|
117
|
+
"{}",
|
118
|
+
match *self {
|
119
|
+
Ace => "A",
|
120
|
+
King => "K",
|
121
|
+
Queen => "Q",
|
122
|
+
Jack => "J",
|
123
|
+
Number(n) => {
|
124
|
+
num_str = n.to_string();
|
125
|
+
&num_str
|
126
|
+
}
|
127
|
+
}
|
128
|
+
)
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
impl PartialOrd for Rank {
|
133
|
+
fn partial_cmp(&self, other: &Rank) -> Option<Ordering> {
|
134
|
+
Some(self.value().cmp(&other.value()))
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)]
|
139
|
+
struct Card {
|
140
|
+
rank: Rank,
|
141
|
+
suit: Suit,
|
142
|
+
}
|
143
|
+
|
144
|
+
impl Card {
|
145
|
+
fn try_from_split(source: &str, split: usize) -> Option<Card> {
|
146
|
+
Some(Card {
|
147
|
+
rank: try_opt!(Rank::try_from(&source[..split])),
|
148
|
+
suit: try_opt!(Suit::try_from(&source[split..])),
|
149
|
+
})
|
150
|
+
}
|
151
|
+
|
152
|
+
fn try_from(source: &str) -> Option<Card> {
|
153
|
+
match source.len() {
|
154
|
+
3 => Card::try_from_split(source, 2),
|
155
|
+
2 => Card::try_from_split(source, 1),
|
156
|
+
_ => None,
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
impl fmt::Display for Card {
|
162
|
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
163
|
+
write!(f, "{}{}", self.rank, self.suit)
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
168
|
+
enum PokerHand {
|
169
|
+
HighCard,
|
170
|
+
OnePair,
|
171
|
+
TwoPair,
|
172
|
+
ThreeOfAKind,
|
173
|
+
Straight,
|
174
|
+
Flush,
|
175
|
+
FullHouse,
|
176
|
+
FourOfAKind,
|
177
|
+
StraightFlush,
|
178
|
+
}
|
179
|
+
|
180
|
+
impl PokerHand {
|
181
|
+
fn is_ace_low_straight(cards: &[Card]) -> bool {
|
182
|
+
// special case: ace-low straight
|
183
|
+
// still depends on the sorted precondition
|
184
|
+
cards[0].rank.value() == 2 && cards[4].rank == Rank::Ace &&
|
185
|
+
cards
|
186
|
+
.windows(2)
|
187
|
+
.take(3) // (0, 1), (1, 2), (2, 3) --> skips 4, ace
|
188
|
+
.map(|pair| pair[1].rank.value() - pair[0].rank.value())
|
189
|
+
.all(|diff| diff == 1)
|
190
|
+
}
|
191
|
+
|
192
|
+
fn analyze(cards: &[Card]) -> Option<PokerHand> {
|
193
|
+
if cards.len() == 5 {
|
194
|
+
let suit_counter = Counter::init(cards.iter().map(|c| c.suit));
|
195
|
+
let is_flush = suit_counter
|
196
|
+
.most_common()
|
197
|
+
.map(|(_suit, count)| count)
|
198
|
+
.next() == Some(5);
|
199
|
+
// Note that `is_straight` depends on a precondition: it only works
|
200
|
+
// if the input `cards` are sorted by rank value ascending.
|
201
|
+
let is_straight = cards
|
202
|
+
.windows(2)
|
203
|
+
.map(|pair| pair[1].rank.value() - pair[0].rank.value())
|
204
|
+
.all(|diff| diff == 1) ||
|
205
|
+
PokerHand::is_ace_low_straight(cards);
|
206
|
+
|
207
|
+
if is_flush && is_straight {
|
208
|
+
return Some(PokerHand::StraightFlush);
|
209
|
+
}
|
210
|
+
|
211
|
+
let rank_counter = Counter::init(cards.iter().map(|c| c.rank));
|
212
|
+
let mut rc_iter = rank_counter.most_common().map(|(_rank, count)| count);
|
213
|
+
let rc_most = rc_iter.next();
|
214
|
+
let rc_second = rc_iter.next();
|
215
|
+
|
216
|
+
if rc_most == Some(4) {
|
217
|
+
return Some(PokerHand::FourOfAKind);
|
218
|
+
}
|
219
|
+
if rc_most == Some(3) && rc_second == Some(2) {
|
220
|
+
return Some(PokerHand::FullHouse);
|
221
|
+
}
|
222
|
+
if is_flush {
|
223
|
+
return Some(PokerHand::Flush);
|
224
|
+
}
|
225
|
+
if is_straight {
|
226
|
+
return Some(PokerHand::Straight);
|
227
|
+
}
|
228
|
+
if rc_most == Some(3) {
|
229
|
+
return Some(PokerHand::ThreeOfAKind);
|
230
|
+
}
|
231
|
+
if rc_most == Some(2) && rc_second == Some(2) {
|
232
|
+
return Some(PokerHand::TwoPair);
|
233
|
+
}
|
234
|
+
if rc_most == Some(2) {
|
235
|
+
return Some(PokerHand::OnePair);
|
236
|
+
}
|
237
|
+
Some(PokerHand::HighCard)
|
238
|
+
} else {
|
239
|
+
None
|
240
|
+
}
|
241
|
+
}
|
242
|
+
}
|
243
|
+
|
244
|
+
#[derive(Debug, PartialEq, Eq)]
|
245
|
+
struct Hand<'a> {
|
246
|
+
source: &'a str,
|
247
|
+
cards: [Card; 5],
|
248
|
+
hand_type: PokerHand,
|
249
|
+
}
|
250
|
+
|
251
|
+
impl<'a> Hand<'a> {
|
252
|
+
fn try_from(source: &'a str) -> Option<Hand> {
|
253
|
+
let mut cards = try_opt!(
|
254
|
+
source
|
255
|
+
.split_whitespace()
|
256
|
+
.map(|s| Card::try_from(s))
|
257
|
+
.collect::<Option<Vec<Card>>>()
|
258
|
+
);
|
259
|
+
cards.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Less));
|
260
|
+
if cards.len() == 5 {
|
261
|
+
Some(Hand {
|
262
|
+
source: source,
|
263
|
+
cards: [cards[0], cards[1], cards[2], cards[3], cards[4]],
|
264
|
+
hand_type: try_opt!(PokerHand::analyze(&cards)),
|
265
|
+
})
|
266
|
+
} else {
|
267
|
+
None
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
271
|
+
fn cmp_high_card(&self, other: &Hand, card: usize) -> Ordering {
|
272
|
+
let mut ordering = self.cards[card].rank.value().cmp(
|
273
|
+
&other.cards[card].rank.value(),
|
274
|
+
);
|
275
|
+
if card != 0 {
|
276
|
+
ordering = ordering.then_with(|| self.cmp_high_card(other, card - 1));
|
277
|
+
}
|
278
|
+
ordering
|
279
|
+
}
|
280
|
+
|
281
|
+
fn value_by_frequency(&self) -> (Option<Rank>, Option<Rank>, Option<Rank>) {
|
282
|
+
let rank_counter = Counter::init(self.cards.iter().map(|c| c.rank));
|
283
|
+
let mut rc_iter = rank_counter
|
284
|
+
.most_common_tiebreaker(|a, b| b.partial_cmp(a).unwrap_or(Ordering::Less))
|
285
|
+
.map(|(rank, _count)| rank);
|
286
|
+
(rc_iter.next(), rc_iter.next(), rc_iter.next())
|
287
|
+
}
|
288
|
+
|
289
|
+
fn cmp_cascade_by_freq(&self, other: &Hand) -> Ordering {
|
290
|
+
let (s1, s2, s3) = self.value_by_frequency();
|
291
|
+
let (o1, o2, o3) = other.value_by_frequency();
|
292
|
+
s1.partial_cmp(&o1)
|
293
|
+
.map(|c| {
|
294
|
+
c.then(
|
295
|
+
s2.partial_cmp(&o2)
|
296
|
+
.map(|c2| c2.then(s3.partial_cmp(&o3).unwrap_or(Ordering::Equal)))
|
297
|
+
.unwrap_or(Ordering::Equal),
|
298
|
+
)
|
299
|
+
})
|
300
|
+
.unwrap_or(Ordering::Equal)
|
301
|
+
}
|
302
|
+
|
303
|
+
fn cmp_straight(&self, other: &Hand) -> Ordering {
|
304
|
+
let s = if PokerHand::is_ace_low_straight(&self.cards) {
|
305
|
+
5
|
306
|
+
} else {
|
307
|
+
self.cards[4].rank.value()
|
308
|
+
};
|
309
|
+
let o = if PokerHand::is_ace_low_straight(&other.cards) {
|
310
|
+
5
|
311
|
+
} else {
|
312
|
+
other.cards[4].rank.value()
|
313
|
+
};
|
314
|
+
s.cmp(&o)
|
315
|
+
}
|
316
|
+
}
|
317
|
+
|
318
|
+
impl<'a> fmt::Display for Hand<'a> {
|
319
|
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
320
|
+
write!(f, "{}", self.source)
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
impl<'a> PartialOrd for Hand<'a> {
|
325
|
+
fn partial_cmp(&self, other: &Hand) -> Option<Ordering> {
|
326
|
+
Some(self.hand_type.cmp(&other.hand_type).then_with(|| {
|
327
|
+
use PokerHand::*;
|
328
|
+
match self.hand_type {
|
329
|
+
HighCard => self.cmp_high_card(other, 4),
|
330
|
+
OnePair => self.cmp_cascade_by_freq(other),
|
331
|
+
TwoPair => self.cmp_cascade_by_freq(other),
|
332
|
+
ThreeOfAKind => self.cmp_cascade_by_freq(other),
|
333
|
+
Straight => self.cmp_straight(other),
|
334
|
+
Flush => self.cmp_high_card(other, 4),
|
335
|
+
FullHouse => self.cmp_cascade_by_freq(other),
|
336
|
+
FourOfAKind => self.cmp_cascade_by_freq(other),
|
337
|
+
StraightFlush => self.cmp_straight(other),
|
338
|
+
}
|
339
|
+
}))
|
340
|
+
}
|
341
|
+
}
|