diff --git a/haskell/collatz-conjecture/collatz-conjecture.cabal b/haskell/collatz-conjecture/collatz-conjecture.cabal new file mode 100644 index 00000000..c1f936ea --- /dev/null +++ b/haskell/collatz-conjecture/collatz-conjecture.cabal @@ -0,0 +1,34 @@ +cabal-version: 1.12 + +-- This file has been generated from package.yaml by hpack version 0.35.1. +-- +-- see: https://github.com/sol/hpack + +name: collatz-conjecture +version: 1.2.1.4 +build-type: Simple + +library + exposed-modules: + CollatzConjecture + other-modules: + Paths_collatz_conjecture + hs-source-dirs: + src + ghc-options: -Wall + build-depends: + base + default-language: Haskell2010 + +test-suite test + type: exitcode-stdio-1.0 + main-is: Tests.hs + other-modules: + Paths_collatz_conjecture + hs-source-dirs: + test + build-depends: + base + , collatz-conjecture + , hspec + default-language: Haskell2010 diff --git a/haskell/collatz-conjecture/src/CollatzConjecture.hs b/haskell/collatz-conjecture/src/CollatzConjecture.hs index 1560f655..c8247c2d 100644 --- a/haskell/collatz-conjecture/src/CollatzConjecture.hs +++ b/haskell/collatz-conjecture/src/CollatzConjecture.hs @@ -1,4 +1,11 @@ -module CollatzConjecture (collatz) where +module CollatzConjecture + ( collatz + ) where collatz :: Integer -> Maybe Integer -collatz n = error "You need to implement this function." + +-- +collatz n | n < 1 = Nothing + | n == 1 = Just 0 + | even n = (n `div` + | otherwise = n * 3 + 1 diff --git a/haskell/collatz-conjecture/stack.yaml.lock b/haskell/collatz-conjecture/stack.yaml.lock new file mode 100644 index 00000000..d4302c7d --- /dev/null +++ b/haskell/collatz-conjecture/stack.yaml.lock @@ -0,0 +1,12 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: [] +snapshots: +- completed: + sha256: 9fa4bece7acfac1fc7930c5d6e24606004b09e80aa0e52e9f68b148201008db9 + size: 649606 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/18.yaml + original: lts-20.18 diff --git a/haskell/hamming/.exercism/config.json b/haskell/hamming/.exercism/config.json new file mode 100644 index 00000000..2521d679 --- /dev/null +++ b/haskell/hamming/.exercism/config.json @@ -0,0 +1,34 @@ +{ + "authors": [ + "petertseng" + ], + "contributors": [ + "chastell", + "iHiD", + "kytrinyx", + "lpalma", + "ppartarr", + "rbasso", + "sshine", + "tejasbubane", + "tqa236" + ], + "files": { + "solution": [ + "src/Hamming.hs", + "package.yaml" + ], + "test": [ + "test/Tests.hs" + ], + "example": [ + ".meta/examples/success-standard/src/Hamming.hs" + ], + "invalidator": [ + "stack.yaml" + ] + }, + "blurb": "Calculate the Hamming difference between two DNA strands.", + "source": "The Calculating Point Mutations problem at Rosalind", + "source_url": "https://rosalind.info/problems/hamm/" +} diff --git a/haskell/hamming/.exercism/metadata.json b/haskell/hamming/.exercism/metadata.json new file mode 100644 index 00000000..fcd6b074 --- /dev/null +++ b/haskell/hamming/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"haskell","exercise":"hamming","id":"b700b38ddb564020a7e2ec1f437b446c","url":"https://exercism.org/tracks/haskell/exercises/hamming","handle":"vpayno","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/haskell/hamming/HELP.md b/haskell/hamming/HELP.md new file mode 100644 index 00000000..fced72bd --- /dev/null +++ b/haskell/hamming/HELP.md @@ -0,0 +1,86 @@ +# Help + +## Running the tests + +To run the test suite, execute the following command: + +```bash +stack test +``` + +#### If you get an error message like this... + +``` +No .cabal file found in directory +``` + +or + +``` +RedownloadInvalidResponse Request { +... +} + "/home/username/.stack/build-plan/lts-xx.yy.yaml" (Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"}, +``` + +You are probably running an old stack version and need +to upgrade it. Try running: + +```bash +stack upgrade +``` + +Or see other options for upgrading at [Stack documentation](https://docs.haskellstack.org/en/stable/install_and_upgrade/#upgrade). + +#### Otherwise, if you get an error message like this... + +``` +No compiler found, expected minor version match with... +Try running "stack setup" to install the correct GHC... +``` + +Just do as it says and it will download and install +the correct compiler version: + +```bash +stack setup +``` + +If you want to play with your solution in GHCi, just run the command: + +```bash +stack ghci +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit src/Hamming.hs package.yaml` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Haskell track's documentation](https://exercism.org/docs/tracks/haskell) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +## Getting Started + +Please refer to the [installation](https://exercism.io/tracks/haskell/installation) +and [learning](https://exercism.io/tracks/haskell/learning) help pages. + +## Feedback, Issues, Pull Requests + +The [exercism/haskell](https://github.com/exercism/haskell) repository on +GitHub is the home for all of the Haskell exercises. + +If you have feedback about an exercise, or want to help implementing a new +one, head over there and create an issue. We'll do our best to help you! \ No newline at end of file diff --git a/haskell/hamming/README.md b/haskell/hamming/README.md new file mode 100644 index 00000000..bf43ecd1 --- /dev/null +++ b/haskell/hamming/README.md @@ -0,0 +1,49 @@ +# Hamming + +Welcome to Hamming on Exercism's Haskell Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Calculate the Hamming Distance between two DNA strands. + +Your body is made up of cells that contain DNA. Those cells regularly wear out and need replacing, which they achieve by dividing into daughter cells. In fact, the average human body experiences about 10 quadrillion cell divisions in a lifetime! + +When cells divide, their DNA replicates too. Sometimes during this process mistakes happen and single pieces of DNA get encoded with the incorrect information. If we compare two strands of DNA and count the differences between them we can see how many mistakes occurred. This is known as the "Hamming Distance". + +We read DNA using the letters C,A,G and T. Two strands might look like this: + + GAGCCTACTAACGGGAT + CATCGTAATGACGGCCT + ^ ^ ^ ^ ^ ^^ + +They have 7 differences, and therefore the Hamming Distance is 7. + +The Hamming Distance is useful for lots of things in science, not just biology, so it's a nice phrase to be familiar with :) + +The Hamming distance is only defined for sequences of equal length, so +an attempt to calculate it between sequences of different lengths should +not work. The general handling of this situation (e.g., raising an +exception vs returning a special value) may differ between languages. + +## Source + +### Created by + +- @petertseng + +### Contributed to by + +- @chastell +- @iHiD +- @kytrinyx +- @lpalma +- @ppartarr +- @rbasso +- @sshine +- @tejasbubane +- @tqa236 + +### Based on + +The Calculating Point Mutations problem at Rosalind - https://rosalind.info/problems/hamm/ \ No newline at end of file diff --git a/haskell/hamming/package.yaml b/haskell/hamming/package.yaml new file mode 100644 index 00000000..2f43e527 --- /dev/null +++ b/haskell/hamming/package.yaml @@ -0,0 +1,21 @@ +name: hamming +version: 2.3.0.10 + +dependencies: + - base + +library: + exposed-modules: Hamming + source-dirs: src + ghc-options: -Wall + # dependencies: + # - foo # List here the packages you + # - bar # want to use in your solution. + +tests: + test: + main: Tests.hs + source-dirs: test + dependencies: + - hamming + - hspec diff --git a/haskell/hamming/src/Hamming.hs b/haskell/hamming/src/Hamming.hs new file mode 100644 index 00000000..2b2b6fbe --- /dev/null +++ b/haskell/hamming/src/Hamming.hs @@ -0,0 +1,4 @@ +module Hamming (distance) where + +distance :: String -> String -> Maybe Int +distance xs ys = error "You need to implement this function." diff --git a/haskell/hamming/stack.yaml b/haskell/hamming/stack.yaml new file mode 100644 index 00000000..11587821 --- /dev/null +++ b/haskell/hamming/stack.yaml @@ -0,0 +1 @@ +resolver: lts-20.18 diff --git a/haskell/hamming/test/Tests.hs b/haskell/hamming/test/Tests.hs new file mode 100644 index 00000000..fb35a102 --- /dev/null +++ b/haskell/hamming/test/Tests.hs @@ -0,0 +1,74 @@ +{-# OPTIONS_GHC -fno-warn-type-defaults #-} +{-# LANGUAGE RecordWildCards #-} + +import Data.Foldable (for_) +import Test.Hspec (Spec, describe, it, shouldBe) +import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith) + +import Hamming (distance) + +main :: IO () +main = hspecWith defaultConfig {configFailFast = True} specs + +specs :: Spec +specs = describe "distance" $ for_ cases test + where + + test Case{..} = it description assertion + where + assertion = expression `shouldBe` fromIntegral <$> expected + expression = distance strand1 strand2 + +data Case = Case { description :: String + , strand1 :: String + , strand2 :: String + , expected :: Maybe Integer + } + +cases :: [Case] +cases = [ Case { description = "empty strands" + , strand1 = "" + , strand2 = "" + , expected = Just 0 + } + , Case { description = "single letter identical strands" + , strand1 = "A" + , strand2 = "A" + , expected = Just 0 + } + , Case { description = "single letter different strands" + , strand1 = "G" + , strand2 = "T" + , expected = Just 1 + } + , Case { description = "long identical strands" + , strand1 = "GGACTGAAATCTG" + , strand2 = "GGACTGAAATCTG" + , expected = Just 0 + } + , Case { description = "long different strands" + , strand1 = "GGACGGATTCTG" + , strand2 = "AGGACGGATTCT" + , expected = Just 9 + } + , Case { description = "disallow first strand longer" + , strand1 = "AATG" + , strand2 = "AAA" + , expected = Nothing + } + , Case { description = "disallow second strand longer" + , strand1 = "ATA" + , strand2 = "AGTG" + , expected = Nothing + } + , Case { description = "disallow left empty strand" + , strand1 = "" + , strand2 = "G" + , expected = Nothing + } + , Case { description = "disallow right empty strand" + , strand1 = "G" + , strand2 = "" + , expected = Nothing + } + ] diff --git a/haskell/protein-translation/.exercism/config.json b/haskell/protein-translation/.exercism/config.json new file mode 100644 index 00000000..a409bf85 --- /dev/null +++ b/haskell/protein-translation/.exercism/config.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "Average-user" + ], + "contributors": [ + "iHiD", + "petertseng", + "ppartarr", + "sshine", + "tejasbubane" + ], + "files": { + "solution": [ + "src/ProteinTranslation.hs", + "package.yaml" + ], + "test": [ + "test/Tests.hs" + ], + "example": [ + ".meta/examples/success-standard/src/ProteinTranslation.hs" + ], + "invalidator": [ + "stack.yaml" + ] + }, + "blurb": "Translate RNA sequences into proteins.", + "source": "Tyler Long" +} diff --git a/haskell/protein-translation/.exercism/metadata.json b/haskell/protein-translation/.exercism/metadata.json new file mode 100644 index 00000000..f0cc2c10 --- /dev/null +++ b/haskell/protein-translation/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"haskell","exercise":"protein-translation","id":"549646afc02849b8868a8b46b9d1f833","url":"https://exercism.org/tracks/haskell/exercises/protein-translation","handle":"vpayno","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/haskell/protein-translation/HELP.md b/haskell/protein-translation/HELP.md new file mode 100644 index 00000000..acfb2a65 --- /dev/null +++ b/haskell/protein-translation/HELP.md @@ -0,0 +1,86 @@ +# Help + +## Running the tests + +To run the test suite, execute the following command: + +```bash +stack test +``` + +#### If you get an error message like this... + +``` +No .cabal file found in directory +``` + +or + +``` +RedownloadInvalidResponse Request { +... +} + "/home/username/.stack/build-plan/lts-xx.yy.yaml" (Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"}, +``` + +You are probably running an old stack version and need +to upgrade it. Try running: + +```bash +stack upgrade +``` + +Or see other options for upgrading at [Stack documentation](https://docs.haskellstack.org/en/stable/install_and_upgrade/#upgrade). + +#### Otherwise, if you get an error message like this... + +``` +No compiler found, expected minor version match with... +Try running "stack setup" to install the correct GHC... +``` + +Just do as it says and it will download and install +the correct compiler version: + +```bash +stack setup +``` + +If you want to play with your solution in GHCi, just run the command: + +```bash +stack ghci +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit src/ProteinTranslation.hs package.yaml` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Haskell track's documentation](https://exercism.org/docs/tracks/haskell) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +## Getting Started + +Please refer to the [installation](https://exercism.io/tracks/haskell/installation) +and [learning](https://exercism.io/tracks/haskell/learning) help pages. + +## Feedback, Issues, Pull Requests + +The [exercism/haskell](https://github.com/exercism/haskell) repository on +GitHub is the home for all of the Haskell exercises. + +If you have feedback about an exercise, or want to help implementing a new +one, head over there and create an issue. We'll do our best to help you! \ No newline at end of file diff --git a/haskell/protein-translation/README.md b/haskell/protein-translation/README.md new file mode 100644 index 00000000..59d13563 --- /dev/null +++ b/haskell/protein-translation/README.md @@ -0,0 +1,65 @@ +# Protein Translation + +Welcome to Protein Translation on Exercism's Haskell Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Translate RNA sequences into proteins. + +RNA can be broken into three nucleotide sequences called codons, and then translated to a polypeptide like so: + +RNA: `"AUGUUUUCU"` => translates to + +Codons: `"AUG", "UUU", "UCU"` +=> which become a polypeptide with the following sequence => + +Protein: `"Methionine", "Phenylalanine", "Serine"` + +There are 64 codons which in turn correspond to 20 amino acids; however, all of the codon sequences and resulting amino acids are not important in this exercise. If it works for one codon, the program should work for all of them. +However, feel free to expand the list in the test suite to include them all. + +There are also three terminating codons (also known as 'STOP' codons); if any of these codons are encountered (by the ribosome), all translation ends and the protein is terminated. + +All subsequent codons after are ignored, like this: + +RNA: `"AUGUUUUCUUAAAUG"` => + +Codons: `"AUG", "UUU", "UCU", "UAA", "AUG"` => + +Protein: `"Methionine", "Phenylalanine", "Serine"` + +Note the stop codon `"UAA"` terminates the translation and the final methionine is not translated into the protein sequence. + +Below are the codons and resulting Amino Acids needed for the exercise. + +Codon | Protein +:--- | :--- +AUG | Methionine +UUU, UUC | Phenylalanine +UUA, UUG | Leucine +UCU, UCC, UCA, UCG | Serine +UAU, UAC | Tyrosine +UGU, UGC | Cysteine +UGG | Tryptophan +UAA, UAG, UGA | STOP + +Learn more about [protein translation on Wikipedia](https://en.wikipedia.org/wiki/Translation_(biology)) + +## Source + +### Created by + +- @Average-user + +### Contributed to by + +- @iHiD +- @petertseng +- @ppartarr +- @sshine +- @tejasbubane + +### Based on + +Tyler Long \ No newline at end of file diff --git a/haskell/protein-translation/package.yaml b/haskell/protein-translation/package.yaml new file mode 100644 index 00000000..fa3ff3fe --- /dev/null +++ b/haskell/protein-translation/package.yaml @@ -0,0 +1,21 @@ +name: protein-translation +version: 1.1.1.3 + +dependencies: + - base + +library: + exposed-modules: ProteinTranslation + source-dirs: src + ghc-options: -Wall + # dependencies: + # - foo # List here the packages you + # - bar # want to use in your solution. + +tests: + test: + main: Tests.hs + source-dirs: test + dependencies: + - protein-translation + - hspec diff --git a/haskell/protein-translation/src/ProteinTranslation.hs b/haskell/protein-translation/src/ProteinTranslation.hs new file mode 100644 index 00000000..42e87037 --- /dev/null +++ b/haskell/protein-translation/src/ProteinTranslation.hs @@ -0,0 +1,4 @@ +module ProteinTranslation(proteins) where + +proteins :: String -> Maybe [String] +proteins = error "You need to implement this function!" diff --git a/haskell/protein-translation/stack.yaml b/haskell/protein-translation/stack.yaml new file mode 100644 index 00000000..11587821 --- /dev/null +++ b/haskell/protein-translation/stack.yaml @@ -0,0 +1 @@ +resolver: lts-20.18 diff --git a/haskell/protein-translation/test/Tests.hs b/haskell/protein-translation/test/Tests.hs new file mode 100644 index 00000000..b0a59084 --- /dev/null +++ b/haskell/protein-translation/test/Tests.hs @@ -0,0 +1,119 @@ +{-# LANGUAGE RecordWildCards #-} + +import Data.Foldable (for_) +import Test.Hspec (Spec, describe, it, shouldBe) +import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith) + +import ProteinTranslation (proteins) + +main :: IO () +main = hspecWith defaultConfig {configFailFast = True} specs + +specs :: Spec +specs = describe "proteins" $ for_ cases test + where + + test Case{..} = it description assertion + where + assertion = proteins input `shouldBe` expected + + +data Case = Case { description :: String + , input :: String + , expected :: Maybe [String] + } + +cases :: [Case] +cases = [ Case { description = "Methionine RNA sequence" + , input = "AUG" + , expected = Just ["Methionine"] + } + , Case { description = "Phenylalanine RNA sequence 1" + , input = "UUU" + , expected = Just ["Phenylalanine"] + } + , Case { description = "Phenylalanine RNA sequence 2" + , input = "UUC" + , expected = Just ["Phenylalanine"] + } + , Case { description = "Leucine RNA sequence 1" + , input = "UUA" + , expected = Just ["Leucine"] + } + , Case { description = "Leucine RNA sequence 2" + , input = "UUG" + , expected = Just ["Leucine"] + } + , Case { description = "Serine RNA sequence 1" + , input = "UCU" + , expected = Just ["Serine"] + } + , Case { description = "Serine RNA sequence 2" + , input = "UCC" + , expected = Just ["Serine"] + } + , Case { description = "Serine RNA sequence 3" + , input = "UCA" + , expected = Just ["Serine"] + } + , Case { description = "Serine RNA sequence 4" + , input = "UCG" + , expected = Just ["Serine"] + } + , Case { description = "Tyrosine RNA sequence 1" + , input = "UAU" + , expected = Just ["Tyrosine"] + } + , Case { description = "Tyrosine RNA sequence 2" + , input = "UAC" + , expected = Just ["Tyrosine"] + } + , Case { description = "Cysteine RNA sequence 1" + , input = "UGU" + , expected = Just ["Cysteine"] + } + , Case { description = "Cysteine RNA sequence 2" + , input = "UGC" + , expected = Just ["Cysteine"] + } + , Case { description = "Tryptophan RNA sequence" + , input = "UGG" + , expected = Just ["Tryptophan"] + } + , Case { description = "STOP codon RNA sequence 1" + , input = "UAA" + , expected = Just [] + } + , Case { description = "STOP codon RNA sequence 2" + , input = "UAG" + , expected = Just [] + } + , Case { description = "STOP codon RNA sequence 3" + , input = "UGA" + , expected = Just [] + } + , Case { description = "Translate RNA strand into correct protein list" + , input = "AUGUUUUGG" + , expected = Just ["Methionine","Phenylalanine","Tryptophan"] + } + , Case { description = "Translation stops if STOP codon at beginning of sequence" + , input = "UAGUGG" + , expected = Just [] + } + , Case { description = "Translation stops if STOP codon at end of two-codon sequence" + , input = "UGGUAG" + , expected = Just ["Tryptophan"] + } + , Case { description = "Translation stops if STOP codon at end of three-codon sequence" + , input = "AUGUUUUAA" + , expected = Just ["Methionine","Phenylalanine"] + } + , Case { description = "Translation stops if STOP codon in middle of three-codon sequence" + , input = "UGGUAGUGG" + , expected = Just ["Tryptophan"] + } + , Case { description = "Translation stops if STOP codon in middle of six-codon sequence" + , input = "UGGUGUUAUUAAUGGUUU" + , expected = Just ["Tryptophan","Cysteine","Tyrosine"] + } + ] diff --git a/haskell/robot-simulator/.exercism/config.json b/haskell/robot-simulator/.exercism/config.json new file mode 100644 index 00000000..7b7587de --- /dev/null +++ b/haskell/robot-simulator/.exercism/config.json @@ -0,0 +1,33 @@ +{ + "authors": [ + "etrepum" + ], + "contributors": [ + "iHiD", + "kytrinyx", + "lpalma", + "petertseng", + "ppartarr", + "rbasso", + "sshine", + "tejasbubane", + "thalesmg" + ], + "files": { + "solution": [ + "src/Robot.hs", + "package.yaml" + ], + "test": [ + "test/Tests.hs" + ], + "example": [ + ".meta/examples/success-standard/src/Robot.hs" + ], + "invalidator": [ + "stack.yaml" + ] + }, + "blurb": "Write a robot simulator.", + "source": "Inspired by an interview question at a famous company." +} diff --git a/haskell/robot-simulator/.exercism/metadata.json b/haskell/robot-simulator/.exercism/metadata.json new file mode 100644 index 00000000..05dfe623 --- /dev/null +++ b/haskell/robot-simulator/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"haskell","exercise":"robot-simulator","id":"49571a0987ed4b73935526fc0448b3c8","url":"https://exercism.org/tracks/haskell/exercises/robot-simulator","handle":"vpayno","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/haskell/robot-simulator/HELP.md b/haskell/robot-simulator/HELP.md new file mode 100644 index 00000000..977dd824 --- /dev/null +++ b/haskell/robot-simulator/HELP.md @@ -0,0 +1,86 @@ +# Help + +## Running the tests + +To run the test suite, execute the following command: + +```bash +stack test +``` + +#### If you get an error message like this... + +``` +No .cabal file found in directory +``` + +or + +``` +RedownloadInvalidResponse Request { +... +} + "/home/username/.stack/build-plan/lts-xx.yy.yaml" (Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"}, +``` + +You are probably running an old stack version and need +to upgrade it. Try running: + +```bash +stack upgrade +``` + +Or see other options for upgrading at [Stack documentation](https://docs.haskellstack.org/en/stable/install_and_upgrade/#upgrade). + +#### Otherwise, if you get an error message like this... + +``` +No compiler found, expected minor version match with... +Try running "stack setup" to install the correct GHC... +``` + +Just do as it says and it will download and install +the correct compiler version: + +```bash +stack setup +``` + +If you want to play with your solution in GHCi, just run the command: + +```bash +stack ghci +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit src/Robot.hs package.yaml` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Haskell track's documentation](https://exercism.org/docs/tracks/haskell) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +## Getting Started + +Please refer to the [installation](https://exercism.io/tracks/haskell/installation) +and [learning](https://exercism.io/tracks/haskell/learning) help pages. + +## Feedback, Issues, Pull Requests + +The [exercism/haskell](https://github.com/exercism/haskell) repository on +GitHub is the home for all of the Haskell exercises. + +If you have feedback about an exercise, or want to help implementing a new +one, head over there and create an issue. We'll do our best to help you! \ No newline at end of file diff --git a/haskell/robot-simulator/README.md b/haskell/robot-simulator/README.md new file mode 100644 index 00000000..d3f4df1f --- /dev/null +++ b/haskell/robot-simulator/README.md @@ -0,0 +1,69 @@ +# Robot Simulator + +Welcome to Robot Simulator on Exercism's Haskell Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Write a robot simulator. + +A robot factory's test facility needs a program to verify robot movements. + +The robots have three possible movements: + +- turn right +- turn left +- advance + +Robots are placed on a hypothetical infinite grid, facing a particular +direction (north, east, south, or west) at a set of {x,y} coordinates, +e.g., {3,8}, with coordinates increasing to the north and east. + +The robot then receives a number of instructions, at which point the +testing facility verifies the robot's new position, and in which +direction it is pointing. + +- The letter-string "RAALAL" means: + - Turn right + - Advance twice + - Turn left + - Advance once + - Turn left yet again +- Say a robot starts at {7, 3} facing north. Then running this stream + of instructions should leave it at {9, 4} facing west. + +To complete this exercise, you need to create the data type `Robot`, +and implement the following functions: + +- `bearing` +- `coordinates` +- `mkRobot` +- `simulate` +- `turnLeft` +- `turnRight` + +You will find a dummy data declaration and type signatures already in place, +but it is up to you to define the functions and create a meaningful data type, +newtype or type synonym. + +## Source + +### Created by + +- @etrepum + +### Contributed to by + +- @iHiD +- @kytrinyx +- @lpalma +- @petertseng +- @ppartarr +- @rbasso +- @sshine +- @tejasbubane +- @thalesmg + +### Based on + +Inspired by an interview question at a famous company. \ No newline at end of file diff --git a/haskell/robot-simulator/package.yaml b/haskell/robot-simulator/package.yaml new file mode 100644 index 00000000..ec8ac351 --- /dev/null +++ b/haskell/robot-simulator/package.yaml @@ -0,0 +1,21 @@ +name: robot-simulator +version: 3.2.0.8 + +dependencies: + - base + +library: + exposed-modules: Robot + source-dirs: src + ghc-options: -Wall + # dependencies: + # - foo # List here the packages you + # - bar # want to use in your solution. + +tests: + test: + main: Tests.hs + source-dirs: test + dependencies: + - robot-simulator + - hspec diff --git a/haskell/robot-simulator/src/Robot.hs b/haskell/robot-simulator/src/Robot.hs new file mode 100644 index 00000000..83d8c3ab --- /dev/null +++ b/haskell/robot-simulator/src/Robot.hs @@ -0,0 +1,27 @@ +module Robot + ( Bearing(East,North,South,West) + , bearing + , coordinates + , mkRobot + , move + ) where + +data Bearing = North + | East + | South + | West + deriving (Eq, Show) + +data Robot = Dummy + +bearing :: Robot -> Bearing +bearing robot = error "You need to implement this function." + +coordinates :: Robot -> (Integer, Integer) +coordinates robot = error "You need to implement this function." + +mkRobot :: Bearing -> (Integer, Integer) -> Robot +mkRobot direction coordinates = error "You need to implement this function." + +move :: Robot -> String -> Robot +move robot instructions = error "You need to implement this function." diff --git a/haskell/robot-simulator/stack.yaml b/haskell/robot-simulator/stack.yaml new file mode 100644 index 00000000..11587821 --- /dev/null +++ b/haskell/robot-simulator/stack.yaml @@ -0,0 +1 @@ +resolver: lts-20.18 diff --git a/haskell/robot-simulator/test/Tests.hs b/haskell/robot-simulator/test/Tests.hs new file mode 100644 index 00000000..3cb2bcc0 --- /dev/null +++ b/haskell/robot-simulator/test/Tests.hs @@ -0,0 +1,97 @@ +{-# OPTIONS_GHC -fno-warn-type-defaults #-} + +import Test.Hspec (Spec, describe, it, shouldBe) +import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith) + +import Robot + ( Bearing ( East + , North + , South + , West + ) + , bearing + , coordinates + , mkRobot + , move + ) + +main :: IO () +main = hspecWith defaultConfig {configFailFast = True} specs + +specs :: Spec +specs = do + + describe "mkRobot" $ do + + -- The function described by the reference file + -- as `create` is called `mkRobot` in this track. + + it "Create robot at origin facing north" $ do + let robot = mkRobot North (0, 0) + coordinates robot `shouldBe` (0, 0) + bearing robot `shouldBe` North + + it "Create robot at negative position facing south" $ do + let robot = mkRobot South (-1, -1) + coordinates robot `shouldBe` (-1, -1) + bearing robot `shouldBe` South + + let turnTest inst dir dir2 = + let robot = mkRobot dir (0, 0) in + describe ("from " ++ show dir) $ do + it "should change direction" $ + bearing (move robot inst) `shouldBe` dir2 + it "shouldn't change position" $ + coordinates (move robot inst) `shouldBe` (0, 0) + + describe "Rotating clockwise" $ do + let rightTest = turnTest "R" + rightTest North East + rightTest East South + rightTest South West + rightTest West North + + describe "Rotating counter-clockwise" $ do + let leftTest = turnTest "L" + leftTest North West + leftTest West South + leftTest South East + leftTest East North + + describe "Moving forward one" $ do + let dir `from` pos = move (mkRobot dir pos) "A" + let test desc dir pos = + describe (show dir ++ " from " ++ show pos) $ do + it "shouldn't change direction" $ + bearing (dir `from` (0, 0)) `shouldBe` dir + it desc $ + coordinates (dir `from` (0, 0)) `shouldBe` pos + + test "facing north increments Y" North (0, 1) + test "facing south decrements Y" South (0, -1) + test "facing east increments X" East (1, 0) + test "facing west decrements X" West (-1, 0) + + describe "Follow series of instructions" $ do + + let simulation pos dir = move (mkRobot dir pos) + + it "moving east and north from README" $ do + let robot = simulation (7, 3) North "RAALAL" + coordinates robot `shouldBe` (9, 4) + bearing robot `shouldBe` West + + it "moving west and north" $ do + let robot = simulation (0, 0) North "LAAARALA" + coordinates robot `shouldBe` (-4, 1) + bearing robot `shouldBe` West + + it "moving west and south" $ do + let robot = simulation (2, -7) East "RRAAAAALA" + coordinates robot `shouldBe` (-3, -8) + bearing robot `shouldBe` South + + it "moving east and north" $ do + let robot = simulation (8, 4) South "LAAARRRALLLL" + coordinates robot `shouldBe` (11, 5) + bearing robot `shouldBe` North diff --git a/haskell/yacht/.exercism/config.json b/haskell/yacht/.exercism/config.json new file mode 100644 index 00000000..e35cd47b --- /dev/null +++ b/haskell/yacht/.exercism/config.json @@ -0,0 +1,30 @@ +{ + "authors": [ + "guygastineau" + ], + "contributors": [ + "iHiD", + "petertseng", + "ppartarr", + "sshine", + "tejasbubane" + ], + "files": { + "solution": [ + "src/Yacht.hs", + "package.yaml" + ], + "test": [ + "test/Tests.hs" + ], + "example": [ + ".meta/examples/success-standard/src/Yacht.hs" + ], + "invalidator": [ + "stack.yaml" + ] + }, + "blurb": "Score a single throw of dice in the game Yacht.", + "source": "James Kilfiger, using wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Yacht_(dice_game)" +} diff --git a/haskell/yacht/.exercism/metadata.json b/haskell/yacht/.exercism/metadata.json new file mode 100644 index 00000000..8e5f3d4c --- /dev/null +++ b/haskell/yacht/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"haskell","exercise":"yacht","id":"eeb7f25e703a4ba38bc021b87f9f0154","url":"https://exercism.org/tracks/haskell/exercises/yacht","handle":"vpayno","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/haskell/yacht/HELP.md b/haskell/yacht/HELP.md new file mode 100644 index 00000000..e121e2b3 --- /dev/null +++ b/haskell/yacht/HELP.md @@ -0,0 +1,86 @@ +# Help + +## Running the tests + +To run the test suite, execute the following command: + +```bash +stack test +``` + +#### If you get an error message like this... + +``` +No .cabal file found in directory +``` + +or + +``` +RedownloadInvalidResponse Request { +... +} + "/home/username/.stack/build-plan/lts-xx.yy.yaml" (Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"}, +``` + +You are probably running an old stack version and need +to upgrade it. Try running: + +```bash +stack upgrade +``` + +Or see other options for upgrading at [Stack documentation](https://docs.haskellstack.org/en/stable/install_and_upgrade/#upgrade). + +#### Otherwise, if you get an error message like this... + +``` +No compiler found, expected minor version match with... +Try running "stack setup" to install the correct GHC... +``` + +Just do as it says and it will download and install +the correct compiler version: + +```bash +stack setup +``` + +If you want to play with your solution in GHCi, just run the command: + +```bash +stack ghci +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit src/Yacht.hs package.yaml` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Haskell track's documentation](https://exercism.org/docs/tracks/haskell) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +## Getting Started + +Please refer to the [installation](https://exercism.io/tracks/haskell/installation) +and [learning](https://exercism.io/tracks/haskell/learning) help pages. + +## Feedback, Issues, Pull Requests + +The [exercism/haskell](https://github.com/exercism/haskell) repository on +GitHub is the home for all of the Haskell exercises. + +If you have feedback about an exercise, or want to help implementing a new +one, head over there and create an issue. We'll do our best to help you! \ No newline at end of file diff --git a/haskell/yacht/README.md b/haskell/yacht/README.md new file mode 100644 index 00000000..389d2362 --- /dev/null +++ b/haskell/yacht/README.md @@ -0,0 +1,58 @@ +# Yacht + +Welcome to Yacht on Exercism's Haskell Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +The dice game [Yacht](https://en.wikipedia.org/wiki/Yacht_(dice_game)) is from +the same family as Poker Dice, Generala and particularly Yahtzee, of which it +is a precursor. In the game, five dice are rolled and the result can be entered +in any of twelve categories. The score of a throw of the dice depends on +category chosen. + +## Scores in Yacht + +| Category | Score | Description | Example | +| -------- | ----- | ----------- | ------- | +| Ones | 1 × number of ones | Any combination | 1 1 1 4 5 scores 3 | +| Twos | 2 × number of twos | Any combination | 2 2 3 4 5 scores 4 | +| Threes | 3 × number of threes | Any combination | 3 3 3 3 3 scores 15 | +| Fours | 4 × number of fours | Any combination | 1 2 3 3 5 scores 0 | +| Fives | 5 × number of fives| Any combination | 5 1 5 2 5 scores 15 | +| Sixes | 6 × number of sixes | Any combination | 2 3 4 5 6 scores 6 | +| Full House | Total of the dice | Three of one number and two of another | 3 3 3 5 5 scores 19 | +| Four of a Kind | Total of the four dice | At least four dice showing the same face | 4 4 4 4 6 scores 16 | +| Little Straight | 30 points | 1-2-3-4-5 | 1 2 3 4 5 scores 30 | +| Big Straight | 30 points | 2-3-4-5-6 | 2 3 4 5 6 scores 30 | +| Choice | Sum of the dice | Any combination | 2 3 3 4 6 scores 18 | +| Yacht | 50 points | All five dice showing the same face | 4 4 4 4 4 scores 50 | + +If the dice do not satisfy the requirements of a category, the score is zero. +If, for example, *Four Of A Kind* is entered in the *Yacht* category, zero +points are scored. A *Yacht* scores zero if entered in the *Full House* category. + +## Task +Given a list of values for five dice and a category, your solution should return +the score of the dice for that category. If the dice do not satisfy the requirements +of the category your solution should return 0. You can assume that five values +will always be presented, and the value of each will be between one and six +inclusively. You should not assume that the dice are ordered. + +## Source + +### Created by + +- @guygastineau + +### Contributed to by + +- @iHiD +- @petertseng +- @ppartarr +- @sshine +- @tejasbubane + +### Based on + +James Kilfiger, using wikipedia - https://en.wikipedia.org/wiki/Yacht_(dice_game) \ No newline at end of file diff --git a/haskell/yacht/package.yaml b/haskell/yacht/package.yaml new file mode 100644 index 00000000..a58038a0 --- /dev/null +++ b/haskell/yacht/package.yaml @@ -0,0 +1,21 @@ +name: yacht +version: 1.2.0.0 + +dependencies: + - base + +library: + exposed-modules: Yacht + source-dirs: src + ghc-options: -Wall + # dependencies: + # - foo # List here the packages you + # - bar # want to use in your solution. + +tests: + test: + main: Tests.hs + source-dirs: test + dependencies: + - yacht + - hspec diff --git a/haskell/yacht/src/Yacht.hs b/haskell/yacht/src/Yacht.hs new file mode 100644 index 00000000..185bc9ca --- /dev/null +++ b/haskell/yacht/src/Yacht.hs @@ -0,0 +1,17 @@ +module Yacht (yacht, Category(..)) where + +data Category = Ones + | Twos + | Threes + | Fours + | Fives + | Sixes + | FullHouse + | FourOfAKind + | LittleStraight + | BigStraight + | Choice + | Yacht + +yacht :: Category -> [Int] -> Int +yacht category dice = error "You need to implement this function." diff --git a/haskell/yacht/stack.yaml b/haskell/yacht/stack.yaml new file mode 100644 index 00000000..11587821 --- /dev/null +++ b/haskell/yacht/stack.yaml @@ -0,0 +1 @@ +resolver: lts-20.18 diff --git a/haskell/yacht/test/Tests.hs b/haskell/yacht/test/Tests.hs new file mode 100644 index 00000000..d1f18e73 --- /dev/null +++ b/haskell/yacht/test/Tests.hs @@ -0,0 +1,166 @@ +{-# LANGUAGE RecordWildCards #-} + +import Data.Foldable (for_) +import Test.Hspec (Spec, describe, it, shouldBe) +import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith) + +import Yacht (yacht, Category(..)) + +main :: IO () +main = hspecWith defaultConfig {configFailFast = True} specs + +specs :: Spec +specs = describe "yacht" $ for_ cases test + where + test Case{..} = it description assertion + where + assertion = yacht category dice `shouldBe` expected + +data Case = Case { description :: String + , dice :: [Int] + , category :: Category + , expected :: Int + } + +cases :: [Case] +cases = [ Case { description = "Yacht" + , dice = [5, 5, 5, 5, 5] + , category = Yacht + , expected = 50 + } + , Case { description = "Not Yacht" + , dice = [1, 3, 3, 2, 5] + , category = Yacht + , expected = 0 + } + , Case { description = "Ones" + , dice = [1, 1, 1, 3, 5] + , category = Ones + , expected = 3 + } + , Case { description = "Ones, out of order" + , dice = [3, 1, 1, 5, 1] + , category = Ones + , expected = 3 + } + , Case { description = "No ones" + , dice = [4, 3, 6, 5, 5] + , category = Ones + , expected = 0 + } + , Case { description = "Twos" + , dice = [2, 3, 4, 5, 6] + , category = Twos + , expected = 2 + } + , Case { description = "Fours" + , dice = [1, 4, 1, 4, 1] + , category = Fours + , expected = 8 + } + , Case { description = "Yacht counted as threes" + , dice = [3, 3, 3, 3, 3] + , category = Threes + , expected = 15 + } + , Case { description = "Yacht of 3s counted as fives" + , dice = [3, 3, 3, 3, 3] + , category = Fives + , expected = 0 + } + , Case { description = "Sixes" + , dice = [2, 3, 4, 5 ,6] + , category = Sixes + , expected = 6 + } + , Case { description = "Full house two small, three big" + , dice = [2, 2, 4, 4, 4] + , category = FullHouse + , expected = 16 + } + , Case { description = "Full house three small, two big" + , dice = [5, 3, 3, 5, 3] + , category = FullHouse + , expected = 19 + } + , Case { description = "Two pair is not a full house" + , dice = [2, 2, 4, 4, 5] + , category = FullHouse + , expected = 0 + } + , Case { description = "Four of a kind is not a full house" + , dice = [1, 4, 4, 4, 4] + , category = FullHouse + , expected = 0 + } + , Case { description = "Yacht is not a full house" + , dice = [2, 2, 2, 2, 2] + , category = FullHouse + , expected = 0 + } + , Case { description = "Four of a Kind" + , dice = [6, 6, 4, 6, 6] + , category = FourOfAKind + , expected = 24 + } + , Case { description = "Yacht can be scored as Four of a Kind" + , dice = [3, 3, 3, 3, 3] + , category = FourOfAKind + , expected = 12 + } + , Case { description = "Full house is not Four of a Kind" + , dice = [3, 3, 3, 5, 5] + , category = FourOfAKind + , expected = 0 + } + , Case { description = "Little Straight" + , dice = [3, 5, 4, 1, 2] + , category = LittleStraight + , expected = 30 + } + , Case { description = "Little Straight as Big Straight" + , dice = [1, 2, 3, 4, 5] + , category = BigStraight + , expected = 0 + } + , Case { description = "Four in order but not a little straight" + , dice = [1, 1, 2, 3, 4] + , category = LittleStraight + , expected = 0 + } + , Case { description = "No pairs but not a little straight" + , dice = [1, 2, 3, 4, 6] + , category = LittleStraight + , expected = 0 + } + , Case { description = "Minimum is 1, maximum is 5, but not a little straight" + , dice = [1, 1, 3, 4, 5] + , category = LittleStraight + , expected = 0 + } + , Case { description = "Big Straight" + , dice = [4, 6, 2, 5, 3] + , category = BigStraight + , expected = 30 + } + , Case { description = "Big Straight as little straight" + , dice = [6, 5, 4, 3, 2] + , category = LittleStraight + , expected = 0 + } + , Case { description = "No pairs but not a big straight" + , dice = [6, 5, 4, 3, 1] + , category = BigStraight + , expected = 0 + } + , Case { description = "Choice" + , dice = [3, 3, 5, 6, 6] + , category = Choice + , expected = 23 + } + , Case { description = "Yacht as choice" + , dice = [2, 2, 2, 2, 2] + , category = Choice + , expected = 10 + } + ]