trackler 2.2.1.40 → 2.2.1.41
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/.gitmodules +3 -0
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/dot-dsl/metadata.yml +1 -0
- data/problem-specifications/exercises/etl/metadata.yml +1 -0
- data/problem-specifications/exercises/isogram/canonical-data.json +3 -3
- data/problem-specifications/exercises/ocr-numbers/metadata.yml +1 -0
- data/problem-specifications/exercises/pascals-triangle/metadata.yml +1 -0
- data/problem-specifications/exercises/pov/metadata.yml +1 -0
- data/problem-specifications/exercises/rna-transcription/metadata.yml +1 -0
- data/problem-specifications/exercises/sgf-parsing/metadata.yml +1 -0
- data/tracks/c/exercises/all-your-base/src/example.c +14 -14
- data/tracks/c/exercises/all-your-base/src/example.h +2 -2
- data/tracks/ceylon/exercises/hamming/source/hamming/HammingTest.ceylon +1 -1
- data/tracks/ceylon/exercises/rna-transcription/source/rnatranscription/{RNAtest.ceylon → RNATest.ceylon} +0 -0
- data/tracks/cfml/.git +1 -0
- data/tracks/cfml/.gitignore +5 -0
- data/tracks/cfml/.travis.yml +18 -0
- data/tracks/cfml/CONTRIBUTING.md +10 -0
- data/tracks/cfml/LICENSE +21 -0
- data/tracks/cfml/README.md +92 -0
- data/tracks/cfml/bin/fetch-configlet +32 -0
- data/tracks/cfml/config/exercise_readme.go.tmpl +16 -0
- data/tracks/cfml/config/maintainers.json +13 -0
- data/tracks/cfml/config.json +223 -0
- data/tracks/cfml/docs/ABOUT.md +10 -0
- data/tracks/cfml/docs/EXERCISE_README_INSERT.md +15 -0
- data/tracks/cfml/docs/INSTALLATION.md +35 -0
- data/tracks/cfml/docs/LEARNING.md +37 -0
- data/tracks/cfml/docs/RESOURCES.md +29 -0
- data/tracks/cfml/docs/SNIPPET.txt +8 -0
- data/tracks/cfml/docs/TESTS.md +13 -0
- data/tracks/cfml/exercises/acronym/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/acronym/Acronym.cfc +13 -0
- data/tracks/cfml/exercises/acronym/AcronymTest.cfc +43 -0
- data/tracks/cfml/exercises/acronym/Solution.cfc +22 -0
- data/tracks/cfml/exercises/acronym/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/acronym/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/acronym/box.json +8 -0
- data/tracks/cfml/exercises/acronym/index.cfm +37 -0
- data/tracks/cfml/exercises/atbash-cipher/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/atbash-cipher/AtbashCipher.cfc +14 -0
- data/tracks/cfml/exercises/atbash-cipher/AtbashCipherTest.cfc +71 -0
- data/tracks/cfml/exercises/atbash-cipher/Solution.cfc +56 -0
- data/tracks/cfml/exercises/atbash-cipher/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/atbash-cipher/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/atbash-cipher/box.json +8 -0
- data/tracks/cfml/exercises/atbash-cipher/index.cfm +37 -0
- data/tracks/cfml/exercises/bob/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/bob/Bob.cfc +13 -0
- data/tracks/cfml/exercises/bob/BobTest.cfc +115 -0
- data/tracks/cfml/exercises/bob/Solution.cfc +27 -0
- data/tracks/cfml/exercises/bob/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/bob/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/bob/box.json +8 -0
- data/tracks/cfml/exercises/bob/index.cfm +37 -0
- data/tracks/cfml/exercises/diamond/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/diamond/Diamond.cfc +13 -0
- data/tracks/cfml/exercises/diamond/DiamondTest.cfc +35 -0
- data/tracks/cfml/exercises/diamond/Solution.cfc +35 -0
- data/tracks/cfml/exercises/diamond/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/diamond/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/diamond/box.json +8 -0
- data/tracks/cfml/exercises/diamond/index.cfm +37 -0
- data/tracks/cfml/exercises/difference-of-squares/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/difference-of-squares/DifferenceOfSquares.cfc +18 -0
- data/tracks/cfml/exercises/difference-of-squares/DifferenceOfSquaresTest.cfc +63 -0
- data/tracks/cfml/exercises/difference-of-squares/Solution.cfc +28 -0
- data/tracks/cfml/exercises/difference-of-squares/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/difference-of-squares/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/difference-of-squares/box.json +8 -0
- data/tracks/cfml/exercises/difference-of-squares/index.cfm +37 -0
- data/tracks/cfml/exercises/flatten-array/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/flatten-array/FlattenArray.cfc +13 -0
- data/tracks/cfml/exercises/flatten-array/FlattenArrayTest.cfc +42 -0
- data/tracks/cfml/exercises/flatten-array/Solution.cfc +26 -0
- data/tracks/cfml/exercises/flatten-array/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/flatten-array/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/flatten-array/box.json +8 -0
- data/tracks/cfml/exercises/flatten-array/index.cfm +37 -0
- data/tracks/cfml/exercises/gigasecond/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/gigasecond/Gigasecond.cfc +13 -0
- data/tracks/cfml/exercises/gigasecond/GigasecondTest.cfc +39 -0
- data/tracks/cfml/exercises/gigasecond/Solution.cfc +16 -0
- data/tracks/cfml/exercises/gigasecond/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/gigasecond/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/gigasecond/box.json +8 -0
- data/tracks/cfml/exercises/gigasecond/index.cfm +37 -0
- data/tracks/cfml/exercises/grains/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/grains/Grains.cfc +14 -0
- data/tracks/cfml/exercises/grains/GrainsTest.cfc +63 -0
- data/tracks/cfml/exercises/grains/Solution.cfc +22 -0
- data/tracks/cfml/exercises/grains/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/grains/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/grains/box.json +8 -0
- data/tracks/cfml/exercises/grains/index.cfm +37 -0
- data/tracks/cfml/exercises/hamming/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/hamming/Hamming.cfc +13 -0
- data/tracks/cfml/exercises/hamming/HammingTest.cfc +75 -0
- data/tracks/cfml/exercises/hamming/Solution.cfc +25 -0
- data/tracks/cfml/exercises/hamming/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/hamming/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/hamming/box.json +8 -0
- data/tracks/cfml/exercises/hamming/index.cfm +37 -0
- data/tracks/cfml/exercises/hello-world/HelloWorld.cfc +13 -0
- data/tracks/cfml/exercises/hello-world/HelloWorldTest.cfc +18 -0
- data/tracks/cfml/exercises/hello-world/Solution.cfc +13 -0
- data/tracks/cfml/exercises/hello-world/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/hello-world/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/hello-world/box.json +8 -0
- data/tracks/cfml/exercises/hello-world/index.cfm +37 -0
- data/tracks/cfml/exercises/isogram/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/isogram/Isogram.cfc +13 -0
- data/tracks/cfml/exercises/isogram/IsogramTest.cfc +55 -0
- data/tracks/cfml/exercises/isogram/Solution.cfc +23 -0
- data/tracks/cfml/exercises/isogram/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/isogram/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/isogram/box.json +8 -0
- data/tracks/cfml/exercises/isogram/index.cfm +37 -0
- data/tracks/cfml/exercises/largest-series-product/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/largest-series-product/LargestSeriesProduct.cfc +13 -0
- data/tracks/cfml/exercises/largest-series-product/LargestSeriesProductTest.cfc +75 -0
- data/tracks/cfml/exercises/largest-series-product/Solution.cfc +41 -0
- data/tracks/cfml/exercises/largest-series-product/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/largest-series-product/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/largest-series-product/box.json +8 -0
- data/tracks/cfml/exercises/largest-series-product/index.cfm +37 -0
- data/tracks/cfml/exercises/leap/Leap.cfc +15 -0
- data/tracks/cfml/exercises/leap/LeapTest.cfc +39 -0
- data/tracks/cfml/exercises/leap/README.md +33 -0
- data/tracks/cfml/exercises/leap/Solution.cfc +19 -0
- data/tracks/cfml/exercises/leap/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/leap/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/leap/box.json +8 -0
- data/tracks/cfml/exercises/leap/index.cfm +37 -0
- data/tracks/cfml/exercises/luhn/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/luhn/Luhn.cfc +13 -0
- data/tracks/cfml/exercises/luhn/LuhnTest.cfc +67 -0
- data/tracks/cfml/exercises/luhn/Solution.cfc +38 -0
- data/tracks/cfml/exercises/luhn/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/luhn/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/luhn/box.json +8 -0
- data/tracks/cfml/exercises/luhn/index.cfm +37 -0
- data/tracks/cfml/exercises/nth-prime/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/nth-prime/NthPrime.cfc +13 -0
- data/tracks/cfml/exercises/nth-prime/NthPrimeTest.cfc +35 -0
- data/tracks/cfml/exercises/nth-prime/Solution.cfc +33 -0
- data/tracks/cfml/exercises/nth-prime/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/nth-prime/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/nth-prime/box.json +8 -0
- data/tracks/cfml/exercises/nth-prime/index.cfm +37 -0
- data/tracks/cfml/exercises/pangram/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/pangram/Pangram.cfc +13 -0
- data/tracks/cfml/exercises/pangram/PangramTest.cfc +55 -0
- data/tracks/cfml/exercises/pangram/Solution.cfc +21 -0
- data/tracks/cfml/exercises/pangram/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/pangram/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/pangram/box.json +8 -0
- data/tracks/cfml/exercises/pangram/index.cfm +37 -0
- data/tracks/cfml/exercises/pig-latin/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/pig-latin/PigLatin.cfc +13 -0
- data/tracks/cfml/exercises/pig-latin/PigLatinTest.cfc +115 -0
- data/tracks/cfml/exercises/pig-latin/Solution.cfc +30 -0
- data/tracks/cfml/exercises/pig-latin/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/pig-latin/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/pig-latin/box.json +8 -0
- data/tracks/cfml/exercises/pig-latin/index.cfm +37 -0
- data/tracks/cfml/exercises/raindrops/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/raindrops/Raindrops.cfc +13 -0
- data/tracks/cfml/exercises/raindrops/RaindropsTest.cfc +87 -0
- data/tracks/cfml/exercises/raindrops/Solution.cfc +33 -0
- data/tracks/cfml/exercises/raindrops/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/raindrops/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/raindrops/box.json +8 -0
- data/tracks/cfml/exercises/raindrops/index.cfm +37 -0
- data/tracks/cfml/exercises/rna-transcription/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/rna-transcription/RnaTranscription.cfc +13 -0
- data/tracks/cfml/exercises/rna-transcription/RnaTranscriptionTest.cfc +47 -0
- data/tracks/cfml/exercises/rna-transcription/Solution.cfc +35 -0
- data/tracks/cfml/exercises/rna-transcription/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/rna-transcription/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/rna-transcription/box.json +8 -0
- data/tracks/cfml/exercises/rna-transcription/index.cfm +37 -0
- data/tracks/cfml/exercises/saddle-points/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/saddle-points/SaddlePoints.cfc +13 -0
- data/tracks/cfml/exercises/saddle-points/SaddlePointsTest.cfc +35 -0
- data/tracks/cfml/exercises/saddle-points/Solution.cfc +59 -0
- data/tracks/cfml/exercises/saddle-points/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/saddle-points/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/saddle-points/box.json +8 -0
- data/tracks/cfml/exercises/saddle-points/index.cfm +37 -0
- data/tracks/cfml/exercises/scrabble-score/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/scrabble-score/ScrabbleScore.cfc +13 -0
- data/tracks/cfml/exercises/scrabble-score/ScrabbleScoreTest.cfc +59 -0
- data/tracks/cfml/exercises/scrabble-score/Solution.cfc +50 -0
- data/tracks/cfml/exercises/scrabble-score/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/scrabble-score/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/scrabble-score/box.json +8 -0
- data/tracks/cfml/exercises/scrabble-score/index.cfm +37 -0
- data/tracks/cfml/exercises/secret-handshake/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/secret-handshake/SecretHandshake.cfc +13 -0
- data/tracks/cfml/exercises/secret-handshake/SecretHandshakeTest.cfc +63 -0
- data/tracks/cfml/exercises/secret-handshake/Solution.cfc +31 -0
- data/tracks/cfml/exercises/secret-handshake/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/secret-handshake/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/secret-handshake/box.json +8 -0
- data/tracks/cfml/exercises/secret-handshake/index.cfm +37 -0
- data/tracks/cfml/exercises/space-age/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/space-age/Solution.cfc +28 -0
- data/tracks/cfml/exercises/space-age/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/space-age/SpaceAge.cfc +13 -0
- data/tracks/cfml/exercises/space-age/SpaceAgeTest.cfc +47 -0
- data/tracks/cfml/exercises/space-age/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/space-age/box.json +8 -0
- data/tracks/cfml/exercises/space-age/index.cfm +37 -0
- data/tracks/cfml/exercises/sum-of-multiples/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/sum-of-multiples/Solution.cfc +27 -0
- data/tracks/cfml/exercises/sum-of-multiples/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/sum-of-multiples/SumOfMultiples.cfc +13 -0
- data/tracks/cfml/exercises/sum-of-multiples/SumOfMultiplesTest.cfc +63 -0
- data/tracks/cfml/exercises/sum-of-multiples/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/sum-of-multiples/box.json +8 -0
- data/tracks/cfml/exercises/sum-of-multiples/index.cfm +37 -0
- data/tracks/cfml/exercises/triangle/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/triangle/Solution.cfc +53 -0
- data/tracks/cfml/exercises/triangle/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/triangle/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/triangle/Triangle.cfc +18 -0
- data/tracks/cfml/exercises/triangle/TriangleTest.cfc +95 -0
- data/tracks/cfml/exercises/triangle/box.json +8 -0
- data/tracks/cfml/exercises/triangle/index.cfm +37 -0
- data/tracks/cfml/exercises/word-count/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/word-count/Solution.cfc +22 -0
- data/tracks/cfml/exercises/word-count/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/word-count/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/word-count/WordCount.cfc +13 -0
- data/tracks/cfml/exercises/word-count/WordCountTest.cfc +55 -0
- data/tracks/cfml/exercises/word-count/box.json +8 -0
- data/tracks/cfml/exercises/word-count/index.cfm +37 -0
- data/tracks/cfml/img/icon.png +0 -0
- data/tracks/cfml/tasks/GenerateTests.cfc +179 -0
- data/tracks/cfml/tasks/ScaffoldExercise.cfc +85 -0
- data/tracks/cfml/tasks/TestAllSolutions.cfc +24 -0
- data/tracks/cfml/tasks/exercise_template/.meta/HINTS.md +0 -0
- data/tracks/cfml/tasks/exercise_template/@@name@@.cfc +13 -0
- data/tracks/cfml/tasks/exercise_template/@@name@@Test.cfc +15 -0
- data/tracks/cfml/tasks/exercise_template/Solution.cfc +6 -0
- data/tracks/cfml/tasks/exercise_template/SolutionTest.cfc +7 -0
- data/tracks/cfml/tasks/exercise_template/TestRunner.cfc +103 -0
- data/tracks/cfml/tasks/exercise_template/box.json +8 -0
- data/tracks/cfml/tasks/exercise_template/index.cfm +37 -0
- data/tracks/coldfusion/docs/ABOUT.md +8 -6
- data/tracks/csharp/docs/GENERATORS.md +7 -0
- data/tracks/csharp/exercises/clock/ClockTest.cs +15 -15
- data/tracks/csharp/exercises/nucleotide-count/Example.cs +10 -11
- data/tracks/csharp/exercises/nucleotide-count/NucleotideCount.cs +2 -7
- data/tracks/csharp/exercises/nucleotide-count/NucleotideCountTest.cs +37 -47
- data/tracks/csharp/exercises/pig-latin/Example.cs +1 -1
- data/tracks/csharp/exercises/pig-latin/PigLatinTest.cs +19 -7
- data/tracks/csharp/exercises/sum-of-multiples/SumOfMultiplesTest.cs +7 -1
- data/tracks/csharp/exercises/tournament/Example.cs +1 -1
- data/tracks/csharp/exercises/tournament/TournamentTest.cs +151 -68
- data/tracks/csharp/exercises/triangle/Example.cs +26 -8
- data/tracks/csharp/exercises/triangle/Triangle.cs +16 -1
- data/tracks/csharp/exercises/triangle/TriangleTest.cs +44 -30
- data/tracks/csharp/generators/Exercise.cs +6 -1
- data/tracks/csharp/generators/Exercises/Clock.cs +17 -1
- data/tracks/csharp/generators/Exercises/NucleotideCount.cs +61 -0
- data/tracks/csharp/generators/Exercises/Tournament.cs +66 -0
- data/tracks/csharp/generators/Exercises/Triangle.cs +36 -0
- data/tracks/dart/config.json +15 -2
- data/tracks/dart/exercises/raindrops/lib/example.dart +23 -0
- data/tracks/dart/exercises/raindrops/lib/raindrops.dart +3 -0
- data/tracks/dart/exercises/raindrops/pubspec.lock +281 -0
- data/tracks/dart/exercises/raindrops/pubspec.yaml +3 -0
- data/tracks/dart/exercises/raindrops/test/raindrops_test.dart +94 -0
- data/tracks/delphi/exercises/pig-latin/uPigLatinExample.pas +1 -25
- data/tracks/haskell/config.json +9 -0
- data/tracks/haskell/exercises/acronym/README.md +0 -1
- data/tracks/haskell/exercises/all-your-base/README.md +1 -1
- data/tracks/haskell/exercises/allergies/README.md +0 -1
- data/tracks/haskell/exercises/alphametics/README.md +2 -2
- data/tracks/haskell/exercises/atbash-cipher/README.md +2 -1
- data/tracks/haskell/exercises/beer-song/README.md +1 -1
- data/tracks/haskell/exercises/binary/README.md +2 -0
- data/tracks/haskell/exercises/bowling/README.md +20 -6
- data/tracks/haskell/exercises/collatz-conjecture/README.md +1 -1
- data/tracks/haskell/exercises/connect/README.md +1 -1
- data/tracks/haskell/exercises/crypto-square/README.md +4 -4
- data/tracks/haskell/exercises/diamond/README.md +113 -0
- data/tracks/haskell/exercises/diamond/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/diamond/examples/success-standard/src/Diamond.hs +16 -0
- data/tracks/haskell/exercises/diamond/package.yaml +20 -0
- data/tracks/haskell/exercises/diamond/src/Diamond.hs +4 -0
- data/tracks/haskell/exercises/diamond/stack.yaml +1 -0
- data/tracks/haskell/exercises/diamond/test/Tests.hs +109 -0
- data/tracks/haskell/exercises/etl/README.md +3 -1
- data/tracks/haskell/exercises/food-chain/README.md +1 -1
- data/tracks/haskell/exercises/go-counting/README.md +1 -1
- data/tracks/haskell/exercises/grade-school/README.md +0 -1
- data/tracks/haskell/exercises/grains/README.md +0 -1
- data/tracks/haskell/exercises/house/README.md +1 -2
- data/tracks/haskell/exercises/isogram/README.md +2 -1
- data/tracks/haskell/exercises/kindergarten-garden/README.md +3 -3
- data/tracks/haskell/exercises/leap/README.md +1 -1
- data/tracks/haskell/exercises/linked-list/README.md +10 -10
- data/tracks/haskell/exercises/luhn/README.md +7 -7
- data/tracks/haskell/exercises/matrix/README.md +6 -4
- data/tracks/haskell/exercises/meetup/README.md +1 -2
- data/tracks/haskell/exercises/nucleotide-count/README.md +8 -22
- data/tracks/haskell/exercises/ocr-numbers/README.md +6 -6
- data/tracks/haskell/exercises/octal/README.md +6 -2
- data/tracks/haskell/exercises/palindrome-products/README.md +12 -6
- data/tracks/haskell/exercises/pangram/README.md +1 -1
- data/tracks/haskell/exercises/pascals-triangle/README.md +2 -2
- data/tracks/haskell/exercises/phone-number/README.md +3 -2
- data/tracks/haskell/exercises/pov/README.md +3 -3
- data/tracks/haskell/exercises/pythagorean-triplet/README.md +3 -3
- data/tracks/haskell/exercises/queen-attack/README.md +1 -1
- data/tracks/haskell/exercises/rna-transcription/README.md +1 -1
- data/tracks/haskell/exercises/roman-numerals/README.md +1 -1
- data/tracks/haskell/exercises/run-length-encoding/README.md +4 -4
- data/tracks/haskell/exercises/saddle-points/README.md +1 -1
- data/tracks/haskell/exercises/scrabble-score/README.md +3 -1
- data/tracks/haskell/exercises/secret-handshake/README.md +1 -1
- data/tracks/haskell/exercises/sgf-parsing/README.md +4 -4
- data/tracks/haskell/exercises/simple-cipher/README.md +1 -1
- data/tracks/haskell/exercises/spiral-matrix/README.md +2 -2
- data/tracks/haskell/exercises/triangle/README.md +9 -6
- data/tracks/haskell/exercises/trinary/README.md +1 -1
- data/tracks/haskell/exercises/word-count/README.md +1 -2
- data/tracks/haskell/exercises/wordy/README.md +0 -5
- data/tracks/java/config.json +56 -9
- data/tracks/java/exercises/binary-search-tree/src/test/java/BSTTest.java +4 -4
- data/tracks/javascript/exercises/two-bucket/example.js +66 -69
- data/tracks/javascript/exercises/two-bucket/two-bucket.spec.js +18 -18
- data/tracks/julia/config.json +1 -0
- data/tracks/julia/docs/ABOUT.md +3 -8
- data/tracks/prolog/README.md +1 -1
- data/tracks/purescript/.travis.yml +1 -0
- data/tracks/purescript/README.md +9 -0
- data/tracks/purescript/bin/check-bower.sh +42 -0
- data/tracks/purescript/bin/test-separate.sh +46 -0
- data/tracks/python/README.md +2 -2
- data/tracks/python/exercises/all-your-base/all_your_base.py +2 -0
- data/tracks/python/exercises/atbash-cipher/atbash_cipher.py +2 -2
- data/tracks/python/exercises/complex-numbers/complex_numbers_test.py +2 -2
- data/tracks/python/exercises/complex-numbers/example.py +2 -2
- data/tracks/python/exercises/gigasecond/gigasecond.py +1 -1
- data/tracks/python/exercises/hamming/hamming.py +1 -1
- data/tracks/python/exercises/hexadecimal/hexadecimal.py +1 -1
- data/tracks/python/exercises/leap/leap.py +1 -1
- data/tracks/python/exercises/meetup/meetup.py +1 -1
- data/tracks/python/exercises/phone-number/example.py +4 -2
- data/tracks/python/exercises/phone-number/phone_number_test.py +47 -16
- data/tracks/python/exercises/pig-latin/pig_latin.py +1 -1
- data/tracks/python/exercises/scrabble-score/scrabble_score.py +1 -1
- data/tracks/python/exercises/wordy/wordy.py +1 -1
- data/tracks/scala/exercises/meetup/example.scala +29 -10
- data/tracks/scala/exercises/meetup/src/main/scala/Meetup.scala +23 -0
- data/tracks/scala/exercises/meetup/src/test/scala/MeetupTest.scala +273 -183
- data/tracks/sml/config.json +13 -0
- data/tracks/sml/exercises/anagram/README.md +21 -5
- data/tracks/sml/exercises/anagram/anagram.sml +2 -6
- data/tracks/sml/exercises/anagram/example.sml +29 -24
- data/tracks/sml/exercises/anagram/test.sml +56 -50
- data/tracks/sml/exercises/anagram/testlib.sml +159 -0
- data/tracks/sml/exercises/diamond/README.md +89 -0
- data/tracks/sml/exercises/diamond/diamond.sml +2 -0
- data/tracks/sml/exercises/diamond/example.sml +25 -0
- data/tracks/sml/exercises/diamond/test.sml +27 -0
- data/tracks/sml/exercises/diamond/testlib.sml +159 -0
- data/tracks/sml/exercises/raindrops/raindrops.sml +2 -2
- data/tracks/sml/exercises/raindrops/test.sml +66 -95
- data/tracks/sml/exercises/raindrops/testlib.sml +159 -0
- metadata +265 -3
data/tracks/sml/config.json
CHANGED
|
@@ -236,6 +236,19 @@
|
|
|
236
236
|
|
|
237
237
|
]
|
|
238
238
|
},
|
|
239
|
+
{
|
|
240
|
+
|
|
241
|
+
"uuid": "f7ea4ee6-cd34-4dc9-bd96-abcf940873f0",
|
|
242
|
+
"slug": "diamond",
|
|
243
|
+
"core": false,
|
|
244
|
+
"unlocked_by": null,
|
|
245
|
+
"difficulty": 1,
|
|
246
|
+
"topics": [
|
|
247
|
+
"strings",
|
|
248
|
+
"lists",
|
|
249
|
+
"text_formatting"
|
|
250
|
+
]
|
|
251
|
+
},
|
|
239
252
|
{
|
|
240
253
|
"uuid": "225cfd7d-81a3-4a58-b1aa-1de2e40e7a93",
|
|
241
254
|
"slug": "binary",
|
|
@@ -6,19 +6,35 @@ Given `"listen"` and a list of candidates like `"enlists" "google"
|
|
|
6
6
|
"inlets" "banana"` the program should return a list containing
|
|
7
7
|
`"inlets"`.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Loading your exercise implementation in PolyML
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
```
|
|
12
|
+
$ poly --use {exercise}.sml
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or:
|
|
12
16
|
|
|
13
17
|
```
|
|
14
|
-
$ poly
|
|
18
|
+
$ poly
|
|
19
|
+
> use "{exercise}.sml";
|
|
15
20
|
```
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
**Note:** You have to replace {exercise}.
|
|
23
|
+
|
|
24
|
+
## Running the tests
|
|
25
|
+
|
|
18
26
|
```
|
|
19
|
-
$ poly --use
|
|
27
|
+
$ poly -q --use test.sml
|
|
20
28
|
```
|
|
21
29
|
|
|
30
|
+
## Feedback, Issues, Pull Requests
|
|
31
|
+
|
|
32
|
+
The [exercism/sml](https://github.com/exercism/sml) repository on
|
|
33
|
+
GitHub is the home for all of the Standard ML exercises.
|
|
34
|
+
|
|
35
|
+
If you have feedback about an exercise, or want to help implementing a new
|
|
36
|
+
one, head over there and create an issue. We'll do our best to help you!
|
|
37
|
+
|
|
22
38
|
## Source
|
|
23
39
|
|
|
24
40
|
Inspired by the Extreme Startup game [https://github.com/rchatley/extreme_startup](https://github.com/rchatley/extreme_startup)
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
(
|
|
2
|
-
|
|
3
|
-
determine which candidate words are anagrams of the starting word
|
|
4
|
-
*)
|
|
5
|
-
fun anagram (word: string) (candidates: string list): string list =
|
|
6
|
-
raise Fail "'anagram' has not been implemented"
|
|
1
|
+
fun anagrams (candidates: string list, subject: string): string list =
|
|
2
|
+
raise Fail "'anagrams' is not implemented"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(* Merge two ordered lists using the order lt.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*)
|
|
2
|
+
* Pre: the given lists xs and ys must already be ordered per lt.
|
|
3
|
+
* Runs in O(n) time, where n = |xs| + |ys|.
|
|
4
|
+
*)
|
|
5
5
|
fun merge lt (xs, ys) =
|
|
6
6
|
let fun loop(out, [], []) = List.rev out
|
|
7
7
|
| loop(out, x::xs, []) = loop (x::out, xs, [])
|
|
@@ -14,12 +14,12 @@ fun merge lt (xs, ys) =
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
(* mergesort = fn : ('a * 'a -> bool) -> 'a list -> 'a list
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*)
|
|
17
|
+
* given an ordering operation and a list of elements that can be ordered
|
|
18
|
+
* returns them in that ordering
|
|
19
|
+
*
|
|
20
|
+
* ex: mergesort (op <) [5,4,3,2,1]
|
|
21
|
+
* => [1, 2, 3, 4, 5] : int list
|
|
22
|
+
*)
|
|
23
23
|
fun mergesort lt xs =
|
|
24
24
|
let val merge' = merge lt
|
|
25
25
|
(* splits a list into two semi-equal halves in Linear time *)
|
|
@@ -41,18 +41,23 @@ fun mergesort lt xs =
|
|
|
41
41
|
ms xs
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
44
|
+
fun anagrams (candidates, subject) =
|
|
45
|
+
let
|
|
46
|
+
fun toLower s = map Char.toLower (explode s)
|
|
47
|
+
|
|
48
|
+
val subject' = toLower subject
|
|
49
|
+
|
|
50
|
+
val sort = mergesort (op <)
|
|
51
|
+
|
|
52
|
+
fun isAnagram a b = sort a = sort b
|
|
53
|
+
|
|
54
|
+
fun collect [] = []
|
|
55
|
+
| collect (s :: ss) =
|
|
56
|
+
if subject' = toLower s
|
|
57
|
+
then collect ss
|
|
58
|
+
else if isAnagram subject' (toLower s)
|
|
59
|
+
then s :: collect ss
|
|
60
|
+
else collect ss
|
|
61
|
+
in
|
|
62
|
+
collect candidates
|
|
63
|
+
end
|
|
@@ -1,54 +1,60 @@
|
|
|
1
|
+
(* version 1.0.1 *)
|
|
2
|
+
|
|
3
|
+
use "testlib.sml";
|
|
1
4
|
use "anagram.sml";
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
else (print (Int.toString (List.length failedTests) ^ " TEST(S) FAILED"));
|
|
6
|
+
infixr |>
|
|
7
|
+
fun x |> f = f x
|
|
8
|
+
|
|
9
|
+
val testsuite =
|
|
10
|
+
describe "anagram" [
|
|
11
|
+
test "no matches"
|
|
12
|
+
(fn _ => anagrams (["hello", "world", "zombies", "pants"], "diaper") |> Expect.equalTo []),
|
|
13
|
+
|
|
14
|
+
test "detects simple anagram"
|
|
15
|
+
(fn _ => anagrams (["tan", "stand", "at"], "ant") |> Expect.equalTo ["tan"]),
|
|
16
|
+
|
|
17
|
+
test "does not detect false positives"
|
|
18
|
+
(fn _ => anagrams (["eagle"], "galea") |> Expect.equalTo []),
|
|
19
|
+
|
|
20
|
+
test "detects two anagrams"
|
|
21
|
+
(fn _ => anagrams (["stream", "pigeon", "maters"], "master") |> Expect.equalTo ["stream", "maters"]),
|
|
22
|
+
|
|
23
|
+
test "does not detect anagram subsets"
|
|
24
|
+
(fn _ => anagrams (["dog", "goody"], "good") |> Expect.equalTo []),
|
|
25
|
+
|
|
26
|
+
test "detects anagram"
|
|
27
|
+
(fn _ => anagrams (["enlists", "google", "inlets", "banana"], "listen") |> Expect.equalTo ["inlets"]),
|
|
28
|
+
|
|
29
|
+
test "detects three anagrams"
|
|
30
|
+
(fn _ => anagrams (["gallery", "ballerina", "regally", "clergy", "largely", "leading"], "allergy") |> Expect.equalTo ["gallery", "regally", "largely"]),
|
|
31
|
+
|
|
32
|
+
test "does not detect identical words"
|
|
33
|
+
(fn _ => anagrams (["corn", "dark", "Corn", "rank", "CORN", "cron", "park"], "corn") |> Expect.equalTo ["cron"]),
|
|
34
|
+
|
|
35
|
+
test "does not detect non-anagrams with identical checksum"
|
|
36
|
+
(fn _ => anagrams (["last"], "mass") |> Expect.equalTo []),
|
|
37
|
+
|
|
38
|
+
test "detects anagrams case-insensitively"
|
|
39
|
+
(fn _ => anagrams (["cashregister", "Carthorse", "radishes"], "Orchestra") |> Expect.equalTo ["Carthorse"]),
|
|
40
|
+
|
|
41
|
+
test "detects anagrams using case-insensitive subject"
|
|
42
|
+
(fn _ => anagrams (["cashregister", "carthorse", "radishes"], "Orchestra") |> Expect.equalTo ["carthorse"]),
|
|
43
|
+
|
|
44
|
+
test "detects anagrams using case-insensitive possible matches"
|
|
45
|
+
(fn _ => anagrams (["cashregister", "Carthorse", "radishes"], "orchestra") |> Expect.equalTo ["Carthorse"]),
|
|
46
|
+
|
|
47
|
+
test "does not detect a word as its own anagram"
|
|
48
|
+
(fn _ => anagrams (["Banana"], "banana") |> Expect.equalTo []),
|
|
49
|
+
|
|
50
|
+
test "does not detect a anagram if the original word is repeated"
|
|
51
|
+
(fn _ => anagrams (["go Go GO"], "go") |> Expect.equalTo []),
|
|
52
|
+
|
|
53
|
+
test "anagrams must use all letters exactly once"
|
|
54
|
+
(fn _ => anagrams (["patter"], "tapper") |> Expect.equalTo []),
|
|
53
55
|
|
|
56
|
+
test "capital word is not own anagram"
|
|
57
|
+
(fn _ => anagrams (["Banana"], "BANANA") |> Expect.equalTo [])
|
|
58
|
+
]
|
|
54
59
|
|
|
60
|
+
val _ = Test.run testsuite
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
structure Expect =
|
|
2
|
+
struct
|
|
3
|
+
datatype expectation = Pass | Fail of string * string
|
|
4
|
+
|
|
5
|
+
local
|
|
6
|
+
fun failEq b a =
|
|
7
|
+
Fail ("Expected: " ^ b, "Got: " ^ a)
|
|
8
|
+
|
|
9
|
+
fun failExn b a =
|
|
10
|
+
Fail ("Expected: " ^ b, "Raised: " ^ a)
|
|
11
|
+
|
|
12
|
+
fun exnName (e: exn): string = General.exnName e
|
|
13
|
+
in
|
|
14
|
+
fun truthy a =
|
|
15
|
+
if a
|
|
16
|
+
then Pass
|
|
17
|
+
else failEq "true" "false"
|
|
18
|
+
|
|
19
|
+
fun falsy a =
|
|
20
|
+
if a
|
|
21
|
+
then failEq "false" "true"
|
|
22
|
+
else Pass
|
|
23
|
+
|
|
24
|
+
fun equalTo b a =
|
|
25
|
+
if a = b
|
|
26
|
+
then Pass
|
|
27
|
+
else failEq (PolyML.makestring b) (PolyML.makestring a)
|
|
28
|
+
|
|
29
|
+
fun nearTo b a =
|
|
30
|
+
if Real.== (a, b)
|
|
31
|
+
then Pass
|
|
32
|
+
else failEq (Real.toString b) (Real.toString a)
|
|
33
|
+
|
|
34
|
+
fun anyError f =
|
|
35
|
+
(
|
|
36
|
+
f ();
|
|
37
|
+
failExn "an exception" "Nothing"
|
|
38
|
+
) handle _ => Pass
|
|
39
|
+
|
|
40
|
+
fun error e f =
|
|
41
|
+
(
|
|
42
|
+
f ();
|
|
43
|
+
failExn (exnName e) "Nothing"
|
|
44
|
+
) handle e' => if exnMessage e' = exnMessage e
|
|
45
|
+
then Pass
|
|
46
|
+
else failExn (exnMessage e) (exnMessage e')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
structure TermColor =
|
|
51
|
+
struct
|
|
52
|
+
datatype color = Red | Green | Yellow | Normal
|
|
53
|
+
|
|
54
|
+
fun f Red = "\027[31m"
|
|
55
|
+
| f Green = "\027[32m"
|
|
56
|
+
| f Yellow = "\027[33m"
|
|
57
|
+
| f Normal = "\027[0m"
|
|
58
|
+
|
|
59
|
+
fun colorize color s = (f color) ^ s ^ (f Normal)
|
|
60
|
+
|
|
61
|
+
val redit = colorize Red
|
|
62
|
+
|
|
63
|
+
val greenit = colorize Green
|
|
64
|
+
|
|
65
|
+
val yellowit = colorize Yellow
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
structure Test =
|
|
69
|
+
struct
|
|
70
|
+
datatype testnode = TestGroup of string * testnode list
|
|
71
|
+
| Test of string * (unit -> Expect.expectation)
|
|
72
|
+
|
|
73
|
+
local
|
|
74
|
+
datatype evaluation = Success of string
|
|
75
|
+
| Failure of string * string * string
|
|
76
|
+
| Error of string * string
|
|
77
|
+
|
|
78
|
+
fun indent n s = (implode (List.tabulate (n, fn _ => #" "))) ^ s
|
|
79
|
+
|
|
80
|
+
fun fmt indentlvl ev =
|
|
81
|
+
let
|
|
82
|
+
val check = TermColor.greenit "\226\156\148 " (* ✔ *)
|
|
83
|
+
val cross = TermColor.redit "\226\156\150 " (* ✖ *)
|
|
84
|
+
val indentlvl = indentlvl * 2
|
|
85
|
+
in
|
|
86
|
+
case ev of
|
|
87
|
+
Success descr => indent indentlvl (check ^ descr)
|
|
88
|
+
| Failure (descr, exp, got) =>
|
|
89
|
+
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
|
90
|
+
indent (indentlvl + 2) exp,
|
|
91
|
+
indent (indentlvl + 2) got]
|
|
92
|
+
| Error (descr, reason) =>
|
|
93
|
+
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
|
94
|
+
indent (indentlvl + 2) (TermColor.redit reason)]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
fun eval (TestGroup _) = raise Fail "Only a 'Test' can be evaluated"
|
|
98
|
+
| eval (Test (descr, thunk)) =
|
|
99
|
+
(
|
|
100
|
+
case thunk () of
|
|
101
|
+
Expect.Pass => ((1, 0, 0), Success descr)
|
|
102
|
+
| Expect.Fail (s, s') => ((0, 1, 0), Failure (descr, s, s'))
|
|
103
|
+
)
|
|
104
|
+
handle e => ((0, 0, 1), Error (descr, "Unexpected error: " ^ exnMessage e))
|
|
105
|
+
|
|
106
|
+
fun flatten depth testnode =
|
|
107
|
+
let
|
|
108
|
+
fun sum (x, y, z) (a, b, c) = (x + a, y + b, z + c)
|
|
109
|
+
|
|
110
|
+
fun aux (t, (counter, acc)) =
|
|
111
|
+
let
|
|
112
|
+
val (counter', texts) = flatten (depth + 1) t
|
|
113
|
+
in
|
|
114
|
+
(sum counter' counter, texts :: acc)
|
|
115
|
+
end
|
|
116
|
+
in
|
|
117
|
+
case testnode of
|
|
118
|
+
TestGroup (descr, ts) =>
|
|
119
|
+
let
|
|
120
|
+
val (counter, texts) = foldr aux ((0, 0, 0), []) ts
|
|
121
|
+
in
|
|
122
|
+
(counter, (indent (depth * 2) descr) :: List.concat texts)
|
|
123
|
+
end
|
|
124
|
+
| Test _ =>
|
|
125
|
+
let
|
|
126
|
+
val (counter, evaluation) = eval testnode
|
|
127
|
+
in
|
|
128
|
+
(counter, [fmt depth evaluation])
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
fun println s = print (s ^ "\n")
|
|
133
|
+
in
|
|
134
|
+
fun run suite =
|
|
135
|
+
let
|
|
136
|
+
val ((succeeded, failed, errored), texts) = flatten 0 suite
|
|
137
|
+
|
|
138
|
+
val summary = String.concatWith ", " [
|
|
139
|
+
TermColor.greenit ((Int.toString succeeded) ^ " passed"),
|
|
140
|
+
TermColor.redit ((Int.toString failed) ^ " failed"),
|
|
141
|
+
TermColor.redit ((Int.toString errored) ^ " errored"),
|
|
142
|
+
(Int.toString (succeeded + failed + errored)) ^ " total"
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
val status = if failed = 0 andalso errored = 0
|
|
146
|
+
then OS.Process.success
|
|
147
|
+
else OS.Process.failure
|
|
148
|
+
|
|
149
|
+
in
|
|
150
|
+
List.app println texts;
|
|
151
|
+
println "";
|
|
152
|
+
println ("Tests: " ^ summary);
|
|
153
|
+
OS.Process.exit status
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
fun describe description tests = Test.TestGroup (description, tests)
|
|
159
|
+
fun test description thunk = Test.Test (description, thunk)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Diamond
|
|
2
|
+
|
|
3
|
+
The diamond kata takes as its input a letter, and outputs it in a diamond
|
|
4
|
+
shape. Given a letter, it prints a diamond starting with 'A', with the
|
|
5
|
+
supplied letter at the widest point.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
* The first row contains one 'A'.
|
|
10
|
+
* The last row contains one 'A'.
|
|
11
|
+
* All rows, except the first and last, have exactly two identical letters.
|
|
12
|
+
* All rows have as many trailing spaces as leading spaces. (This might be 0).
|
|
13
|
+
* The diamond is horizontally symmetric.
|
|
14
|
+
* The diamond is vertically symmetric.
|
|
15
|
+
* The diamond has a square shape (width equals height).
|
|
16
|
+
* The letters form a diamond shape.
|
|
17
|
+
* The top half has the letters in ascending order.
|
|
18
|
+
* The bottom half has the letters in descending order.
|
|
19
|
+
* The four corners (containing the spaces) are triangles.
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
In the following examples, spaces are indicated by `·` characters.
|
|
24
|
+
|
|
25
|
+
Diamond for letter 'A':
|
|
26
|
+
|
|
27
|
+
```plain
|
|
28
|
+
A
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Diamond for letter 'C':
|
|
32
|
+
|
|
33
|
+
```plain
|
|
34
|
+
··A··
|
|
35
|
+
·B·B·
|
|
36
|
+
C···C
|
|
37
|
+
·B·B·
|
|
38
|
+
··A··
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Diamond for letter 'E':
|
|
42
|
+
|
|
43
|
+
```plain
|
|
44
|
+
····A····
|
|
45
|
+
···B·B···
|
|
46
|
+
··C···C··
|
|
47
|
+
·D·····D·
|
|
48
|
+
E·······E
|
|
49
|
+
·D·····D·
|
|
50
|
+
··C···C··
|
|
51
|
+
···B·B···
|
|
52
|
+
····A····
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Loading your exercise implementation in PolyML
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
$ poly --use {exercise}.sml
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
$ poly
|
|
65
|
+
> use "{exercise}.sml";
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Note:** You have to replace {exercise}.
|
|
69
|
+
|
|
70
|
+
## Running the tests
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
$ poly -q --use test.sml
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Feedback, Issues, Pull Requests
|
|
77
|
+
|
|
78
|
+
The [exercism/sml](https://github.com/exercism/sml) repository on
|
|
79
|
+
GitHub is the home for all of the Standard ML exercises.
|
|
80
|
+
|
|
81
|
+
If you have feedback about an exercise, or want to help implementing a new
|
|
82
|
+
one, head over there and create an issue. We'll do our best to help you!
|
|
83
|
+
|
|
84
|
+
## Source
|
|
85
|
+
|
|
86
|
+
Seb Rose [http://claysnow.co.uk/recycling-tests-in-tdd/](http://claysnow.co.uk/recycling-tests-in-tdd/)
|
|
87
|
+
|
|
88
|
+
## Submitting Incomplete Solutions
|
|
89
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
fun rows (input: string): string list =
|
|
2
|
+
let
|
|
3
|
+
fun spaces n = List.tabulate (n, fn _ => #" ")
|
|
4
|
+
|
|
5
|
+
fun index c = ord c - ord #"A"
|
|
6
|
+
|
|
7
|
+
fun halfRow numcols c = spaces (numcols - index c - 1) @ [c] @ spaces (index c)
|
|
8
|
+
|
|
9
|
+
fun mkRow numcols c =
|
|
10
|
+
let
|
|
11
|
+
val half = halfRow numcols c
|
|
12
|
+
in
|
|
13
|
+
implode (half @ tl (rev half))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
fun prevLetter c = chr (ord c - 1)
|
|
17
|
+
|
|
18
|
+
val c = valOf (Char.fromString input)
|
|
19
|
+
val numcols = index c + 1
|
|
20
|
+
|
|
21
|
+
fun mkRows 0 _ acc = acc @ tl (rev acc)
|
|
22
|
+
| mkRows i c acc = mkRows (i - 1) (prevLetter c) (mkRow numcols c :: acc)
|
|
23
|
+
in
|
|
24
|
+
mkRows numcols c []
|
|
25
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
(* version 1.0.0 *)
|
|
2
|
+
|
|
3
|
+
use "diamond.sml";
|
|
4
|
+
use "testlib.sml";
|
|
5
|
+
|
|
6
|
+
infixr |>
|
|
7
|
+
fun x |> f = f x
|
|
8
|
+
|
|
9
|
+
val testsuite =
|
|
10
|
+
describe "diamond" [
|
|
11
|
+
test "Degenerate case with a single 'A' row"
|
|
12
|
+
(fn _ => rows ("A") |> Expect.equalTo ["A"]),
|
|
13
|
+
|
|
14
|
+
test "Degenerate case with no row containing 3 distinct groups of spaces"
|
|
15
|
+
(fn _ => rows ("B") |> Expect.equalTo [" A ", "B B", " A "]),
|
|
16
|
+
|
|
17
|
+
test "Smallest non-degenerate case with odd diamond side length"
|
|
18
|
+
(fn _ => rows ("C") |> Expect.equalTo [" A ", " B B ", "C C", " B B ", " A "]),
|
|
19
|
+
|
|
20
|
+
test "Smallest non-degenerate case with even diamond side length"
|
|
21
|
+
(fn _ => rows ("D") |> Expect.equalTo [" A ", " B B ", " C C ", "D D", " C C ", " B B ", " A "]),
|
|
22
|
+
|
|
23
|
+
test "Largest possible diamond"
|
|
24
|
+
(fn _ => rows ("Z") |> Expect.equalTo [" A ", " B B ", " C C ", " D D ", " E E ", " F F ", " G G ", " H H ", " I I ", " J J ", " K K ", " L L ", " M M ", " N N ", " O O ", " P P ", " Q Q ", " R R ", " S S ", " T T ", " U U ", " V V ", " W W ", " X X ", " Y Y ", "Z Z", " Y Y ", " X X ", " W W ", " V V ", " U U ", " T T ", " S S ", " R R ", " Q Q ", " P P ", " O O ", " N N ", " M M ", " L L ", " K K ", " J J ", " I I ", " H H ", " G G ", " F F ", " E E ", " D D ", " C C ", " B B ", " A "])
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
val _ = Test.run testsuite
|