├── .appends └── .github │ └── labels.yml ├── .gitattributes ├── .github ├── CODEOWNERS ├── dependabot.yml ├── labels.yml └── workflows │ ├── configlet.yml │ ├── no-important-files-changed.yml │ ├── ping-cross-track-maintainers-team.yml │ ├── sync-labels.yml │ └── test.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── bin ├── add-exercise ├── data.py ├── fetch-configlet ├── fetch-configlet.ps1 ├── generate_tests.py ├── install-roc └── verify-exercises ├── concepts └── .keep ├── config.json ├── config └── generator_macros.j2 ├── docs ├── ABOUT.md ├── INSTALLATION.md ├── LEARNING.md ├── RESOURCES.md ├── SNIPPET.txt ├── TESTS.md └── config.json ├── exercises ├── concept │ └── .keep ├── practice │ ├── accumulate │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Accumulate.roc │ │ └── accumulate-test.roc │ ├── acronym │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Acronym.roc │ │ └── acronym-test.roc │ ├── affine-cipher │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── AffineCipher.roc │ │ └── affine-cipher-test.roc │ ├── all-your-base │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── AllYourBase.roc │ │ └── all-your-base-test.roc │ ├── allergies │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Allergies.roc │ │ └── allergies-test.roc │ ├── alphametics │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Alphametics.roc │ │ └── alphametics-test.roc │ ├── anagram │ │ ├── .docs │ │ │ ├── instructions.append.md │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Anagram.roc │ │ └── anagram-test.roc │ ├── armstrong-numbers │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── ArmstrongNumbers.roc │ │ └── armstrong-numbers-test.roc │ ├── atbash-cipher │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── AtbashCipher.roc │ │ └── atbash-cipher-test.roc │ ├── binary-search-tree │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── BinarySearchTree.roc │ │ └── binary-search-tree-test.roc │ ├── binary-search │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── BinarySearch.roc │ │ └── binary-search-test.roc │ ├── binary │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Binary.roc │ │ └── binary-test.roc │ ├── bob │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Bob.roc │ │ └── bob-test.roc │ ├── bowling │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Bowling.roc │ │ └── bowling-test.roc │ ├── change │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Change.roc │ │ └── change-test.roc │ ├── circular-buffer │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── CircularBuffer.roc │ │ └── circular-buffer-test.roc │ ├── clock │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── additional_tests.json │ │ │ ├── config.json │ │ │ ├── plugins.py │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Clock.roc │ │ └── clock-test.roc │ ├── collatz-conjecture │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── CollatzConjecture.roc │ │ └── collatz-conjecture-test.roc │ ├── complex-numbers │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── plugins.py │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── ComplexNumbers.roc │ │ └── complex-numbers-test.roc │ ├── connect │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Connect.roc │ │ └── connect-test.roc │ ├── crypto-square │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── CryptoSquare.roc │ │ └── crypto-square-test.roc │ ├── custom-set │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── additional_tests.json │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── CustomSet.roc │ │ └── custom-set-test.roc │ ├── darts │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Darts.roc │ │ └── darts-test.roc │ ├── diamond │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Diamond.roc │ │ └── diamond-test.roc │ ├── difference-of-squares │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── DifferenceOfSquares.roc │ │ └── difference-of-squares-test.roc │ ├── dominoes │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Dominoes.roc │ │ └── dominoes-test.roc │ ├── eliuds-eggs │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── EliudsEggs.roc │ │ └── eliuds-eggs-test.roc │ ├── error-handling │ │ ├── .docs │ │ │ ├── instructions.append.md │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ └── config.json │ │ ├── ErrorHandling.roc │ │ └── error-handling-test.roc │ ├── etl │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Etl.roc │ │ └── etl-test.roc │ ├── flatten-array │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── plugins.py │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── FlattenArray.roc │ │ └── flatten-array-test.roc │ ├── food-chain │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── FoodChain.roc │ │ └── food-chain-test.roc │ ├── forth │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Forth.roc │ │ └── forth-test.roc │ ├── gigasecond │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Gigasecond.roc │ │ └── gigasecond-test.roc │ ├── go-counting │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── GoCounting.roc │ │ └── go-counting-test.roc │ ├── grains │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Grains.roc │ │ └── grains-test.roc │ ├── grep │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Grep.roc │ │ ├── grep-test.roc │ │ ├── iliad.txt │ │ ├── midsummer-night.txt │ │ └── paradise-lost.txt │ ├── hamming │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Hamming.roc │ │ └── hamming-test.roc │ ├── hello-world │ │ ├── .docs │ │ │ ├── instructions.append.md │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── HelloWorld.roc │ │ └── hello-world-test.roc │ ├── hexadecimal │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ └── config.json │ │ ├── Hexadecimal.roc │ │ └── hexadecimal-test.roc │ ├── high-scores │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── HighScores.roc │ │ └── high-scores-test.roc │ ├── house │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── House.roc │ │ └── house-test.roc │ ├── isbn-verifier │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── IsbnVerifier.roc │ │ └── isbn-verifier-test.roc │ ├── isogram │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Isogram.roc │ │ └── isogram-test.roc │ ├── killer-sudoku-helper │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── KillerSudokuHelper.roc │ │ └── killer-sudoku-helper-test.roc │ ├── kindergarten-garden │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── KindergartenGarden.roc │ │ └── kindergarten-garden-test.roc │ ├── knapsack │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Knapsack.roc │ │ └── knapsack-test.roc │ ├── largest-series-product │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── LargestSeriesProduct.roc │ │ └── largest-series-product-test.roc │ ├── leap │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Leap.roc │ │ └── leap-test.roc │ ├── list-ops │ │ ├── .docs │ │ │ ├── instructions.append.md │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── ListOps.roc │ │ └── list-ops-test.roc │ ├── luhn │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Luhn.roc │ │ └── luhn-test.roc │ ├── matching-brackets │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── MatchingBrackets.roc │ │ └── matching-brackets-test.roc │ ├── matrix │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Matrix.roc │ │ └── matrix-test.roc │ ├── meetup │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Meetup.roc │ │ └── meetup-test.roc │ ├── micro-blog │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── MicroBlog.roc │ │ └── micro-blog-test.roc │ ├── minesweeper │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Minesweeper.roc │ │ └── minesweeper-test.roc │ ├── nth-prime │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── NthPrime.roc │ │ └── nth-prime-test.roc │ ├── nucleotide-count │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── NucleotideCount.roc │ │ └── nucleotide-count-test.roc │ ├── ocr-numbers │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── OcrNumbers.roc │ │ └── ocr-numbers-test.roc │ ├── octal │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ └── config.json │ │ ├── Octal.roc │ │ └── octal-test.roc │ ├── palindrome-products │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── PalindromeProducts.roc │ │ └── palindrome-products-test.roc │ ├── pangram │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Pangram.roc │ │ └── pangram-test.roc │ ├── pascals-triangle │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── PascalsTriangle.roc │ │ └── pascals-triangle-test.roc │ ├── perfect-numbers │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── PerfectNumbers.roc │ │ └── perfect-numbers-test.roc │ ├── phone-number │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── PhoneNumber.roc │ │ └── phone-number-test.roc │ ├── pig-latin │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── PigLatin.roc │ │ └── pig-latin-test.roc │ ├── poker │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Poker.roc │ │ └── poker-test.roc │ ├── prime-factors │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── PrimeFactors.roc │ │ └── prime-factors-test.roc │ ├── protein-translation │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── ProteinTranslation.roc │ │ └── protein-translation-test.roc │ ├── proverb │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Proverb.roc │ │ └── proverb-test.roc │ ├── pythagorean-triplet │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── PythagoreanTriplet.roc │ │ └── pythagorean-triplet-test.roc │ ├── queen-attack │ │ ├── .docs │ │ │ ├── instructions.append.md │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── plugins.py │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── QueenAttack.roc │ │ └── queen-attack-test.roc │ ├── rail-fence-cipher │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── RailFenceCipher.roc │ │ └── rail-fence-cipher-test.roc │ ├── raindrops │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Raindrops.roc │ │ └── raindrops-test.roc │ ├── rational-numbers │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── plugins.py │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── RationalNumbers.roc │ │ └── rational-numbers-test.roc │ ├── rectangles │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Rectangles.roc │ │ └── rectangles-test.roc │ ├── resistor-color-duo │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── ResistorColorDuo.roc │ │ └── resistor-color-duo-test.roc │ ├── resistor-color │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── ResistorColor.roc │ │ └── resistor-color-test.roc │ ├── rest-api │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── RestApi.roc │ │ └── rest-api-test.roc │ ├── reverse-string │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── ReverseString.roc │ │ └── reverse-string-test.roc │ ├── rna-transcription │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── RnaTranscription.roc │ │ └── rna-transcription-test.roc │ ├── robot-simulator │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── plugins.py │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── RobotSimulator.roc │ │ └── robot-simulator-test.roc │ ├── roman-numerals │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── RomanNumerals.roc │ │ └── roman-numerals-test.roc │ ├── rotational-cipher │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── RotationalCipher.roc │ │ └── rotational-cipher-test.roc │ ├── run-length-encoding │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── RunLengthEncoding.roc │ │ └── run-length-encoding-test.roc │ ├── saddle-points │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── SaddlePoints.roc │ │ └── saddle-points-test.roc │ ├── say │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Say.roc │ │ └── say-test.roc │ ├── scrabble-score │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── ScrabbleScore.roc │ │ └── scrabble-score-test.roc │ ├── secret-handshake │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── SecretHandshake.roc │ │ └── secret-handshake-test.roc │ ├── series │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Series.roc │ │ └── series-test.roc │ ├── sgf-parsing │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── SgfParsing.roc │ │ └── sgf-parsing-test.roc │ ├── sieve │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Sieve.roc │ │ └── sieve-test.roc │ ├── simple-linked-list │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ └── config.json │ │ ├── SimpleLinkedList.roc │ │ └── simple-linked-list-test.roc │ ├── space-age │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── SpaceAge.roc │ │ └── space-age-test.roc │ ├── spiral-matrix │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── SpiralMatrix.roc │ │ └── spiral-matrix-test.roc │ ├── square-root │ │ ├── .docs │ │ │ ├── instructions.append.md │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── SquareRoot.roc │ │ └── square-root-test.roc │ ├── strain │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Strain.roc │ │ └── strain-test.roc │ ├── sublist │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Sublist.roc │ │ └── sublist-test.roc │ ├── sum-of-multiples │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── SumOfMultiples.roc │ │ └── sum-of-multiples-test.roc │ ├── tournament │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Tournament.roc │ │ └── tournament-test.roc │ ├── transpose │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Transpose.roc │ │ └── transpose-test.roc │ ├── triangle │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Triangle.roc │ │ └── triangle-test.roc │ ├── two-bucket │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── TwoBucket.roc │ │ └── two-bucket-test.roc │ ├── two-fer │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── TwoFer.roc │ │ └── two-fer-test.roc │ ├── variable-length-quantity │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── VariableLengthQuantity.roc │ │ └── variable-length-quantity-test.roc │ ├── word-count │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── WordCount.roc │ │ └── word-count-test.roc │ ├── word-search │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── WordSearch.roc │ │ └── word-search-test.roc │ ├── wordy │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Wordy.roc │ │ └── wordy-test.roc │ ├── yacht │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── Example.roc │ │ │ ├── config.json │ │ │ ├── template.j2 │ │ │ └── tests.toml │ │ ├── Yacht.roc │ │ └── yacht-test.roc │ └── zebra-puzzle │ │ ├── .docs │ │ ├── instructions.md │ │ └── introduction.md │ │ ├── .meta │ │ ├── Example.roc │ │ ├── config.json │ │ ├── template.j2 │ │ └── tests.toml │ │ ├── ZebraPuzzle.roc │ │ └── zebra-puzzle-test.roc └── shared │ └── .docs │ ├── help.md │ └── tests.md └── requirements-generator.txt /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners 2 | .github/CODEOWNERS @exercism/maintainers-admin 3 | 4 | # Changes to `fetch-configlet` should be made in the `exercism/configlet` repo 5 | bin/fetch-configlet @exercism/maintainers-admin 6 | bin/fetch-configlet.ps1 @exercism/maintainers-admin 7 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | # Keep dependencies for GitHub Actions up-to-date 5 | - package-ecosystem: 'github-actions' 6 | directory: '/' 7 | schedule: 8 | interval: 'monthly' 9 | labels: 10 | - 'x:size/small' 11 | -------------------------------------------------------------------------------- /.github/workflows/configlet.yml: -------------------------------------------------------------------------------- 1 | name: Configlet 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | workflow_dispatch: 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | configlet: 15 | uses: exercism/github-actions/.github/workflows/configlet.yml@main 16 | -------------------------------------------------------------------------------- /.github/workflows/ping-cross-track-maintainers-team.yml: -------------------------------------------------------------------------------- 1 | name: Ping cross-track maintainers team 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | 8 | permissions: 9 | pull-requests: write 10 | 11 | jobs: 12 | ping: 13 | if: github.repository_owner == 'exercism' # Stops this job from running on forks 14 | uses: exercism/github-actions/.github/workflows/ping-cross-track-maintainers-team.yml@main 15 | secrets: 16 | github_membership_token: ${{ secrets.COMMUNITY_CONTRIBUTIONS_WORKFLOW_TOKEN }} 17 | -------------------------------------------------------------------------------- /.github/workflows/sync-labels.yml: -------------------------------------------------------------------------------- 1 | name: Tools 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - .github/labels.yml 9 | - .github/workflows/sync-labels.yml 10 | workflow_dispatch: 11 | schedule: 12 | - cron: 0 0 1 * * # First day of each month 13 | 14 | permissions: 15 | issues: write 16 | 17 | jobs: 18 | sync-labels: 19 | uses: exercism/github-actions/.github/workflows/labels.yml@main 20 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | workflow_dispatch: 9 | 10 | jobs: 11 | ci: 12 | runs-on: ubuntu-22.04 13 | 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 17 | 18 | - name: Install dependencies 19 | run: | 20 | sudo apt-get update 21 | sudo apt-get -y install wget jq coreutils libc-dev binutils 22 | 23 | - name: Install Roc 24 | run: bin/install-roc 25 | 26 | - name: Verify all exercises 27 | run: bin/verify-exercises 28 | -------------------------------------------------------------------------------- /concepts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/roc/9c9d20c07a1fa0b7f10702878d845b89769ee70d/concepts/.keep -------------------------------------------------------------------------------- /docs/INSTALLATION.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | To install Roc, please follow the instructions at [roc-lang.org/install](https://roc-lang.org/install). 4 | You only need to install Roc, and optionally the editor Extensions/Plugins of your choice, you don't need to install Rust or Zig (which are used to build Roc itself). 5 | -------------------------------------------------------------------------------- /docs/LEARNING.md: -------------------------------------------------------------------------------- 1 | # Learning 2 | 3 | - The [Roc tutorial](https://www.roc-lang.org/tutorial) is a good place to start. 4 | - You can then go through the [code examples](https://www.roc-lang.org/examples). 5 | 6 | Have fun learning Roc! 7 | -------------------------------------------------------------------------------- /docs/RESOURCES.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | 3 | - Official website: [roc-lang.org](https://www.roc-lang.org/) 4 | - Code examples: [roc-lang.org/examples](https://www.roc-lang.org/examples) 5 | - Community: [roc-lang.org/community](https://www.roc-lang.org/community) 6 | - Github: [roc-lang/roc](https://github.com/roc-lang/roc/) 7 | -------------------------------------------------------------------------------- /docs/SNIPPET.txt: -------------------------------------------------------------------------------- 1 | app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br" } 2 | import pf.Stdout 3 | 4 | factorial = \number -> 5 | when number is 6 | 1 -> 1 7 | n -> n * factorial (n - 1) 8 | 9 | expect factorial 5 == 1 * 2 * 3 * 4 * 5 10 | 11 | main! = |_args| 12 | result = factorial 20 |> Num.toStr 13 | Stdout.line! "factorial 20 = ${result}" 14 | -------------------------------------------------------------------------------- /exercises/concept/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/roc/9c9d20c07a1fa0b7f10702878d845b89769ee70d/exercises/concept/.keep -------------------------------------------------------------------------------- /exercises/practice/accumulate/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [accumulate] 2 | 3 | accumulate : List a, (a -> b) -> List b 4 | accumulate = |list, func| 5 | help = |output, input| 6 | when input is 7 | [] -> output 8 | [first, .. as rest] -> 9 | List.append(output, func(first)) 10 | |> help(rest) 11 | 12 | help([], list) 13 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Accumulate.roc" 8 | ], 9 | "test": [ 10 | "accumulate-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement the `accumulate` operation, which, given a collection and an operation to perform on each element of the collection, returns a new collection containing the result of applying that operation to each element of the input collection.", 17 | "source": "Conversation with James Edward Gray II", 18 | "source_url": "http://graysoftinc.com/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/Accumulate.roc: -------------------------------------------------------------------------------- 1 | module [accumulate] 2 | 3 | accumulate : List a, (a -> b) -> List b 4 | accumulate = |list, func| 5 | crash("Please implement 'accumulate'") 6 | -------------------------------------------------------------------------------- /exercises/practice/acronym/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Convert a phrase to its acronym. 4 | 5 | Techies love their TLA (Three Letter Acronyms)! 6 | 7 | Help generate some jargon by writing a program that converts a long name like Portable Network Graphics to its acronym (PNG). 8 | 9 | Punctuation is handled as follows: hyphens are word separators (like whitespace); all other punctuation can be removed from the input. 10 | 11 | For example: 12 | 13 | | Input | Output | 14 | | ------------------------- | ------ | 15 | | As Soon As Possible | ASAP | 16 | | Liquid-crystal display | LCD | 17 | | Thank George It's Friday! | TGIF | 18 | -------------------------------------------------------------------------------- /exercises/practice/acronym/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Acronym.roc" 8 | ], 9 | "test": [ 10 | "acronym-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert a long phrase to its acronym.", 17 | "source": "Julien Vanier", 18 | "source_url": "https://github.com/monkbroc" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/acronym/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [abbreviate] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["phrase"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/acronym/Acronym.roc: -------------------------------------------------------------------------------- 1 | module [abbreviate] 2 | 3 | abbreviate : Str -> Str 4 | abbreviate = |text| 5 | crash("Please implement the 'abbreviate' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/affine-cipher/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "AffineCipher.roc" 8 | ], 9 | "test": [ 10 | "affine-cipher-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Create an implementation of the Affine cipher, an ancient encryption algorithm from the Middle East.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Affine_cipher" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/affine-cipher/AffineCipher.roc: -------------------------------------------------------------------------------- 1 | module [encode, decode] 2 | 3 | encode : Str, { a : U64, b : U64 } -> Result Str _ 4 | encode = |phrase, key| 5 | crash("Please implement the 'encode' function") 6 | 7 | decode : Str, { a : U64, b : U64 } -> Result Str _ 8 | decode = |phrase, key| 9 | crash("Please implement the 'decode' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You've just been hired as professor of mathematics. 4 | Your first week went well, but something is off in your second week. 5 | The problem is that every answer given by your students is wrong! 6 | Luckily, your math skills have allowed you to identify the problem: the student answers _are_ correct, but they're all in base 2 (binary)! 7 | Amazingly, it turns out that each week, the students use a different base. 8 | To help you quickly verify the student answers, you'll be building a tool to translate between bases. 9 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "AllYourBase.roc" 8 | ], 9 | "test": [ 10 | "all-your-base-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert a number, represented as a sequence of digits in one base, to any other base." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} { input_base: {{ case["input"]["inputBase"] | to_roc }}, output_base: {{ case["input"]["outputBase"] | to_roc }}, digits: {{ case["input"]["digits"] | to_roc }} } 11 | {%- if case["expected"]["error"] %} 12 | result |> Result.isErr 13 | {%- else %} 14 | result == Ok {{ case["expected"] }} 15 | {%- endif %} 16 | 17 | {% endfor %} -------------------------------------------------------------------------------- /exercises/practice/all-your-base/AllYourBase.roc: -------------------------------------------------------------------------------- 1 | module [rebase] 2 | 3 | rebase : { input_base : U64, output_base : U64, digits : List U64 } -> Result (List U64) _ 4 | rebase = |{ input_base, output_base, digits }| 5 | crash("Please implement 'rebase'") 6 | -------------------------------------------------------------------------------- /exercises/practice/allergies/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Allergies.roc" 8 | ], 9 | "test": [ 10 | "allergies-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.", 17 | "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 18 | "source_url": "https://turing.edu" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/allergies/Allergies.roc: -------------------------------------------------------------------------------- 1 | module [allergic_to, set] 2 | 3 | Allergen : [Eggs, Peanuts, Shellfish, Strawberries, Tomatoes, Chocolate, Pollen, Cats] 4 | 5 | allergic_to : Allergen, U64 -> Bool 6 | allergic_to = |allergen, score| 7 | crash("Please implement 'allergic_to'") 8 | 9 | set : U64 -> Set Allergen 10 | set = |score| 11 | crash("Please implement 'set'") 12 | -------------------------------------------------------------------------------- /exercises/practice/alphametics/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Alphametics.roc" 8 | ], 9 | "test": [ 10 | "alphametics-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given an alphametics puzzle, find the correct solution." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/alphametics/Alphametics.roc: -------------------------------------------------------------------------------- 1 | module [solve] 2 | 3 | solve : Str -> Result (List (U8, U8)) _ 4 | solve = |problem| 5 | crash("Please implement 'solve'") 6 | -------------------------------------------------------------------------------- /exercises/practice/anagram/.docs/instructions.append.md: -------------------------------------------------------------------------------- 1 | # Instructions Append 2 | 3 | You must return the anagrams in the same order as they are listed in the candidate words. 4 | -------------------------------------------------------------------------------- /exercises/practice/anagram/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Anagram.roc" 8 | ], 9 | "test": [ 10 | "anagram-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a word and a list of possible anagrams, select the correct sublist.", 17 | "source": "Inspired by the Extreme Startup game", 18 | "source_url": "https://github.com/rchatley/extreme_startup" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/anagram/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header(imports=["unicode"]) }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["subject"] | to_roc }} {{ case["input"]["candidates"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/anagram/Anagram.roc: -------------------------------------------------------------------------------- 1 | module [find_anagrams] 2 | 3 | find_anagrams : Str, List Str -> List Str 4 | find_anagrams = |subject, candidates| 5 | crash("Please implement the 'find_anagrams' function") 6 | 7 | # HINT: we have added the `unicode` package to the app's header in 8 | # anagram-test.roc, so you can use it here if you need to. 9 | # For example, you could import unicode.Grapheme, just sayin'. 10 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | An [Armstrong number][armstrong-number] is a number that is the sum of its own digits each raised to the power of the number of digits. 4 | 5 | For example: 6 | 7 | - 9 is an Armstrong number, because `9 = 9^1 = 9` 8 | - 10 is _not_ an Armstrong number, because `10 != 1^2 + 0^2 = 1` 9 | - 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153` 10 | - 154 is _not_ an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190` 11 | 12 | Write some code to determine whether a number is an Armstrong number. 13 | 14 | [armstrong-number]: https://en.wikipedia.org/wiki/Narcissistic_number 15 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [is_armstrong_number] 2 | 3 | list_digits = |number| 4 | if number < 10 then 5 | [number] 6 | else 7 | (list_digits((number // 10))) |> List.append((number % 10)) 8 | 9 | is_armstrong_number : U64 -> Bool 10 | is_armstrong_number = |number| 11 | digits = list_digits(number) 12 | len = List.len(digits) 13 | candidate = 14 | digits 15 | |> List.map(|digit| digit |> Num.pow_int(len)) 16 | |> List.sum 17 | candidate == number 18 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ArmstrongNumbers.roc" 8 | ], 9 | "test": [ 10 | "armstrong-numbers-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Determine if a number is an Armstrong number.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Narcissistic_number" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [is_armstrong_number] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/ArmstrongNumbers.roc: -------------------------------------------------------------------------------- 1 | module [is_armstrong_number] 2 | 3 | is_armstrong_number : U64 -> Bool 4 | is_armstrong_number = |number| 5 | crash("Please implement the 'is_armstrong_number' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/atbash-cipher/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "AtbashCipher.roc" 8 | ], 9 | "test": [ 10 | "atbash-cipher-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Create an implementation of the Atbash cipher, an ancient encryption system created in the Middle East.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Atbash" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/atbash-cipher/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [encode, decode] 6 | 7 | {% for supercase in cases %} 8 | ## 9 | ## {{ supercase["description"] }} 10 | ## 11 | 12 | {% for case in supercase["cases"] -%} 13 | # {{ case["description"] }} 14 | expect 15 | phrase = {{ case["input"]["phrase"] | to_roc }} 16 | result = phrase |> {{ case["property"] | to_snake }} 17 | expected = {{ case["expected"] | to_roc }} 18 | result == Ok expected 19 | 20 | {% endfor %} 21 | {% endfor %} 22 | -------------------------------------------------------------------------------- /exercises/practice/atbash-cipher/AtbashCipher.roc: -------------------------------------------------------------------------------- 1 | module [encode, decode] 2 | 3 | encode : Str -> Result Str _ 4 | encode = |phrase| 5 | crash("Please implement the 'encode' function") 6 | 7 | decode : Str -> Result Str _ 8 | decode = |phrase| 9 | crash("Please implement the 'decode' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/binary-search-tree/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "BinarySearchTree.roc" 8 | ], 9 | "test": [ 10 | "binary-search-tree-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Insert and search for numbers in a binary tree.", 17 | "source": "Josh Cheek" 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/binary-search-tree/BinarySearchTree.roc: -------------------------------------------------------------------------------- 1 | module [from_list, to_list] 2 | 3 | BinaryTree : [Nil, Node { value : U64, left : BinaryTree, right : BinaryTree }] 4 | 5 | from_list : List U64 -> BinaryTree 6 | from_list = |data| 7 | crash("Please implement the 'from_list' function") 8 | 9 | to_list : BinaryTree -> List U64 10 | to_list = |tree| 11 | crash("Please implement the 'to_list' function") 12 | -------------------------------------------------------------------------------- /exercises/practice/binary-search/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "BinarySearch.roc" 8 | ], 9 | "test": [ 10 | "binary-search-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement a binary search algorithm.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/binary-search/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["input"]["array"] | to_roc }} |> {{ case["property"] | to_snake }} {{ case["input"]["value"] }} 11 | {%- if case["expected"]["error"] %} 12 | Result.isErr result 13 | {%- else %} 14 | result == Ok {{ case["expected"] }} 15 | {%- endif %} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/binary-search/BinarySearch.roc: -------------------------------------------------------------------------------- 1 | module [find] 2 | 3 | find : List U64, U64 -> Result U64 _ 4 | find = |array, value| 5 | crash("Please implement the 'find' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/binary/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [decimal] 2 | 3 | decimal : Str -> Result U64 [InvalidCharacter U8] 4 | decimal = |binary_str| 5 | binary_str 6 | |> Str.to_utf8 7 | |> List.map_try( 8 | |char| 9 | when char is 10 | '0' -> Ok(0) 11 | '1' -> Ok(1) 12 | c -> Err(InvalidCharacter(c)), 13 | )? 14 | |> List.walk( 15 | 0, 16 | |dec, bit| 17 | dec * 2 + bit, 18 | ) 19 | |> Ok 20 | -------------------------------------------------------------------------------- /exercises/practice/binary/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Binary.roc" 8 | ], 9 | "test": [ 10 | "binary-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert a binary number, represented as a string (e.g. '101010'), to its decimal equivalent using first principles.", 17 | "source": "All of Computer Science", 18 | "source_url": "https://www.wolframalpha.com/examples/mathematics/numbers/base-conversions" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/binary/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["binary"] | to_roc }} 11 | {%- if case["expected"] is not none %} 12 | result == Ok {{ case["expected"] | to_roc }} 13 | {%- else %} 14 | result |> Result.isErr 15 | {%- endif %} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/binary/Binary.roc: -------------------------------------------------------------------------------- 1 | module [decimal] 2 | 3 | decimal : Str -> Result U64 _ 4 | decimal = |binary_str| 5 | crash("Please implement the 'decimal' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/bob/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Bob is a [lackadaisical][] teenager. 4 | He likes to think that he's very cool. 5 | And he definitely doesn't get excited about things. 6 | That wouldn't be cool. 7 | 8 | When people talk to him, his responses are pretty limited. 9 | 10 | [lackadaisical]: https://www.collinsdictionary.com/dictionary/english/lackadaisical 11 | -------------------------------------------------------------------------------- /exercises/practice/bob/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Bob.roc" 8 | ], 9 | "test": [ 10 | "bob-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Bob is a lackadaisical teenager. In conversation, his responses are very limited.", 17 | "source": "Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial.", 18 | "source_url": "https://pine.fm/LearnToProgram/?Chapter=06" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/bob/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [response] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["heyBob"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} -------------------------------------------------------------------------------- /exercises/practice/bob/Bob.roc: -------------------------------------------------------------------------------- 1 | module [response] 2 | 3 | response : Str -> Str 4 | response = |hey_bob| 5 | crash("Please implement the `response` function") 6 | -------------------------------------------------------------------------------- /exercises/practice/bowling/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Bowling.roc" 8 | ], 9 | "test": [ 10 | "bowling-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Score a bowling game.", 17 | "source": "The Bowling Game Kata from UncleBob", 18 | "source_url": "https://web.archive.org/web/20221001111000/http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/bowling/Bowling.roc: -------------------------------------------------------------------------------- 1 | module [Game, create, roll, score] 2 | 3 | Game := { 4 | # TODO: change this opaque type however you need 5 | todo : U64, 6 | todo2 : U64, 7 | todo3 : U64, 8 | # etc. 9 | } 10 | 11 | create : { previous_rolls ?? List U64 } -> Result Game _ 12 | create = |{ previous_rolls ?? [] }| 13 | crash("Please implement the 'create' function") 14 | 15 | roll : Game, U64 -> Result Game _ 16 | roll = |game, pins| 17 | crash("Please implement the 'roll' function") 18 | 19 | score : Game -> Result U64 _ 20 | score = |finished_game| 21 | crash("Please implement the 'score' function") 22 | -------------------------------------------------------------------------------- /exercises/practice/change/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Determine the fewest number of coins to give a customer so that the sum of their values equals the correct amount of change. 4 | 5 | ## Examples 6 | 7 | - An amount of 15 with available coin values [1, 5, 10, 25, 100] should return one coin of value 5 and one coin of value 10, or [5, 10]. 8 | - An amount of 40 with available coin values [1, 5, 10, 25, 100] should return one coin of value 5, one coin of value 10, and one coin of value 25, or [5, 10, 25]. 9 | -------------------------------------------------------------------------------- /exercises/practice/change/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Change.roc" 8 | ], 9 | "test": [ 10 | "change-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Correctly determine change to be given using the least number of coins.", 17 | "source": "Software Craftsmanship - Coin Change Kata", 18 | "source_url": "https://web.archive.org/web/20130115115225/http://craftsmanship.sv.cmu.edu:80/exercises/coin-change-kata" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/change/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | coins = {{ case["input"]["coins"] | to_roc }} 11 | result = coins |> {{ case["property"] | to_snake }} {{ case["input"]["target"] }} 12 | {%- if case["expected"]["error"] %} 13 | result |> Result.isErr 14 | {%- else %} 15 | result == Ok {{ case["expected"] | to_roc }} 16 | {%- endif %} 17 | 18 | {% endfor %} 19 | -------------------------------------------------------------------------------- /exercises/practice/change/Change.roc: -------------------------------------------------------------------------------- 1 | module [find_fewest_coins] 2 | 3 | find_fewest_coins : List U64, U64 -> Result (List U64) _ 4 | find_fewest_coins = |coins, target| 5 | crash("Please implement the 'find_fewest_coins' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/circular-buffer/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "CircularBuffer.roc" 8 | ], 9 | "test": [ 10 | "circular-buffer-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "A data structure that uses a single, fixed-size buffer as if it were connected end-to-end.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Circular_buffer" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/clock/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Implement a clock that handles times without dates. 4 | 5 | You should be able to add and subtract minutes to it. 6 | 7 | Two clocks that represent the same time should be equal to each other. 8 | -------------------------------------------------------------------------------- /exercises/practice/clock/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Clock.roc" 8 | ], 9 | "test": [ 10 | "clock-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement a clock that handles times without dates.", 17 | "source": "Pairing session with Erin Drummond" 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/clock/.meta/plugins.py: -------------------------------------------------------------------------------- 1 | def to_hours_minutes_record(input): 2 | hours = input.get("hour", 0) 3 | minutes = input.get("minute", 0) 4 | fields = [] 5 | if hours != 0: 6 | fields.append(f"hours: {hours}") 7 | if minutes != 0: 8 | fields.append(f"minutes: {minutes}") 9 | if fields: 10 | content = ", ".join(fields) 11 | return "{ " + content + " }" 12 | else: 13 | return "{}" 14 | -------------------------------------------------------------------------------- /exercises/practice/collatz-conjecture/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Given a positive integer, return the number of steps it takes to reach 1 according to the rules of the Collatz Conjecture. 4 | -------------------------------------------------------------------------------- /exercises/practice/collatz-conjecture/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [steps] 2 | 3 | steps : U64 -> Result U64 [NumberArgWasZero] 4 | steps = |number| 5 | if number <= 0 then 6 | Err(NumberArgWasZero) 7 | else if number == 1 then 8 | Ok(0) 9 | else if Num.is_even(number) then 10 | Ok(steps(number // 2)? + 1) 11 | else 12 | Ok(steps(3 * number + 1)? + 1) 13 | -------------------------------------------------------------------------------- /exercises/practice/collatz-conjecture/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "CollatzConjecture.roc" 8 | ], 9 | "test": [ 10 | "collatz-conjecture-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Calculate the number of steps to reach 1 using the Collatz conjecture.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Collatz_conjecture" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/collatz-conjecture/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [steps] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] }} 11 | {%- if case["expected"]["error"] %} 12 | Result.isErr result 13 | {%- else %} 14 | result == Ok {{ case["expected"] }} 15 | {%- endif %} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/collatz-conjecture/CollatzConjecture.roc: -------------------------------------------------------------------------------- 1 | module [steps] 2 | 3 | steps : U64 -> Result U64 _ 4 | steps = |number| 5 | crash("Please implement the `steps` function") 6 | -------------------------------------------------------------------------------- /exercises/practice/complex-numbers/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ComplexNumbers.roc" 8 | ], 9 | "test": [ 10 | "complex-numbers-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement complex numbers.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Complex_number" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/complex-numbers/.meta/plugins.py: -------------------------------------------------------------------------------- 1 | float_map = { 2 | "e": "Num.e", 3 | "ln(2)": "Num.log 2f64", 4 | "ln(2)/2": "Num.log 2f64 / 2", 5 | "pi": "Num.pi", 6 | "pi/4": "Num.pi / 4", 7 | } 8 | 9 | 10 | def to_roc(value): 11 | if isinstance(value, str): 12 | return float_map[value] 13 | else: 14 | return f"{value}" 15 | 16 | 17 | def to_complex_number(value): 18 | if isinstance(value, list): 19 | assert len(value) == 2 20 | re = to_roc(value[0]) 21 | im = to_roc(value[1]) 22 | else: 23 | re = to_roc(value) 24 | im = 0 25 | return f"{{ re: {re}, im: {im} }}" 26 | -------------------------------------------------------------------------------- /exercises/practice/connect/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Connect.roc" 8 | ], 9 | "test": [ 10 | "connect-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Compute the result for a game of Hex / Polygon." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/connect/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | board = {{ case["input"]["board"] | to_roc_multiline_string | indent(8) }} 11 | result = board |> {{ case["property"] | to_snake }} 12 | result == {% if case["expected"] == "" %}Err NotFinished{% else %}Ok Player{{ case["expected"] }}{% endif %} 13 | 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /exercises/practice/connect/Connect.roc: -------------------------------------------------------------------------------- 1 | module [winner] 2 | 3 | winner : Str -> Result [PlayerO, PlayerX] _ 4 | winner = |board_str| 5 | crash("Please implement the 'winner' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/crypto-square/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "CryptoSquare.roc" 8 | ], 9 | "test": [ 10 | "crypto-square-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement the classic method for composing secret messages called a square code.", 17 | "source": "J Dalbey's Programming Practice problems", 18 | "source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/crypto-square/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | text = {{ case["input"]["plaintext"] | to_roc }} 11 | result = {{ case["property"] | to_snake }} text 12 | expected = Ok {{ case["expected"] | to_roc }} 13 | result == expected 14 | 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /exercises/practice/crypto-square/CryptoSquare.roc: -------------------------------------------------------------------------------- 1 | module [ciphertext] 2 | 3 | ciphertext : Str -> Result Str _ 4 | ciphertext = |text| 5 | crash("Please implement the 'ciphertext' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/custom-set/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Create a custom set type. 4 | 5 | Sometimes it is necessary to define a custom data structure of some type, like a set. 6 | In this exercise you will define your own set. 7 | How it works internally doesn't matter, as long as it behaves like a set of unique elements. 8 | -------------------------------------------------------------------------------- /exercises/practice/custom-set/.meta/additional_tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "cases": [ 3 | { 4 | "description": "an empty set has an empty list of items", 5 | "property": "toList", 6 | "input": { 7 | "set": [] 8 | }, 9 | "expected": [] 10 | }, 11 | { 12 | "description": "a set can provide the list of its items", 13 | "property": "toList", 14 | "input": { 15 | "set": [1, 2, 3, 4] 16 | }, 17 | "expected": [1, 2, 3, 4] 18 | }, 19 | { 20 | "description": "duplicate items must be removed", 21 | "property": "toList", 22 | "input": { 23 | "set": [1, 2, 2, 3, 3, 3, 4, 4, 4, 4] 24 | }, 25 | "expected": [1, 2, 3, 4] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /exercises/practice/custom-set/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "CustomSet.roc" 8 | ], 9 | "test": [ 10 | "custom-set-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Create a custom set type." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/darts/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [score] 2 | 3 | distance_squared = |x, y| 4 | x * x + y * y 5 | 6 | score : F64, F64 -> U64 7 | score = |x, y| 8 | d2 = distance_squared(x, y) 9 | if d2 > 100 then 10 | 0 11 | else if d2 > 25 then 12 | 1 13 | else if d2 > 1 then 14 | 5 15 | else 16 | 10 17 | -------------------------------------------------------------------------------- /exercises/practice/darts/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Darts.roc" 8 | ], 9 | "test": [ 10 | "darts-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Calculate the points scored in a single toss of a Darts game.", 17 | "source": "Inspired by an exercise created by a professor Della Paolera in Argentina" 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/darts/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import Darts exposing [score] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["x"] | to_roc_float }} {{ case["input"]["y"] | to_roc_float }} 11 | result == {{ case["expected"] }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/darts/Darts.roc: -------------------------------------------------------------------------------- 1 | module [score] 2 | 3 | score : F64, F64 -> U64 4 | score = |x, y| 5 | crash("Please implement the `score` function") 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/diamond/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Diamond.roc" 8 | ], 9 | "test": [ 10 | "diamond-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a letter, print a diamond starting with 'A' with the supplied letter at the widest point.", 17 | "source": "Seb Rose", 18 | "source_url": "https://web.archive.org/web/20220807163751/http://claysnow.co.uk/recycling-tests-in-tdd/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/diamond/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ exercise | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ exercise | to_snake }} '{{ case["input"]["letter"] }}' 11 | expected = {{ case["expected"] | to_roc_multiline_string | replace(" ", "·") | indent(8) }} |> Str.replaceEach "·" " " 12 | result == expected 13 | 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /exercises/practice/diamond/Diamond.roc: -------------------------------------------------------------------------------- 1 | module [diamond] 2 | 3 | diamond : U8 -> Str 4 | diamond = |letter| 5 | crash("Please implement the 'diamond' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [square_of_sum, sum_of_squares, difference_of_squares] 2 | 3 | sum : U64 -> U64 4 | sum = |number| 5 | number * (number + 1) // 2 6 | 7 | square_of_sum : U64 -> U64 8 | square_of_sum = |number| 9 | s = sum(number) 10 | s * s 11 | 12 | sum_of_squares : U64 -> U64 13 | sum_of_squares = |number| 14 | s = sum(number) 15 | s * (2 * number + 1) // 3 16 | 17 | difference_of_squares : U64 -> U64 18 | difference_of_squares = |number| 19 | (square_of_sum(number)) - (sum_of_squares(number)) 20 | -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "DifferenceOfSquares.roc" 8 | ], 9 | "test": [ 10 | "difference-of-squares-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.", 17 | "source": "Problem 6 at Project Euler", 18 | "source_url": "https://projecteuler.net/problem=6" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import DifferenceOfSquares exposing [square_of_sum, sum_of_squares, difference_of_squares] 6 | 7 | {% for supercase in cases %} 8 | ## 9 | ## {{ supercase["description"] }} 10 | ## 11 | 12 | {% for case in supercase["cases"] -%} 13 | # {{ case["description"] }} 14 | expect 15 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] }} 16 | result == {{ case["expected"] }} 17 | 18 | {% endfor %} 19 | {% endfor %} 20 | -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/DifferenceOfSquares.roc: -------------------------------------------------------------------------------- 1 | module [square_of_sum, sum_of_squares, difference_of_squares] 2 | 3 | square_of_sum : U64 -> U64 4 | square_of_sum = |number| 5 | crash("Please implement the `square_of_sum` function") 6 | 7 | sum_of_squares : U64 -> U64 8 | sum_of_squares = |number| 9 | crash("Please implement the `sum_of_squares` function") 10 | 11 | difference_of_squares : U64 -> U64 12 | difference_of_squares = |number| 13 | crash("Please implement the `difference_of_squares` function") 14 | -------------------------------------------------------------------------------- /exercises/practice/dominoes/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Dominoes.roc" 8 | ], 9 | "test": [ 10 | "dominoes-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Make a chain of dominoes." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/dominoes/Dominoes.roc: -------------------------------------------------------------------------------- 1 | module [find_chain] 2 | 3 | Domino : (U8, U8) 4 | 5 | find_chain : List Domino -> Result (List Domino) _ 6 | find_chain = |dominoes| 7 | crash("Please implement the 'find_chain' function") 8 | -------------------------------------------------------------------------------- /exercises/practice/eliuds-eggs/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to count the number of 1 bits in the binary representation of a number. 4 | 5 | ## Restrictions 6 | 7 | Keep your hands off that bit-count functionality provided by your standard library! 8 | Solve this one yourself using other basic tools instead. 9 | -------------------------------------------------------------------------------- /exercises/practice/eliuds-eggs/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [egg_count] 2 | 3 | egg_count : U64 -> U64 4 | egg_count = |number| 5 | help = |count, remaining| 6 | if remaining == 0 then 7 | count 8 | else 9 | digit = Num.rem(remaining, 2) 10 | help((count + digit), (remaining // 2)) 11 | 12 | help(0, number) 13 | -------------------------------------------------------------------------------- /exercises/practice/eliuds-eggs/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "EliudsEggs.roc" 8 | ], 9 | "test": [ 10 | "eliuds-eggs-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Help Eliud count the number of eggs in her chicken coop by counting the number of 1 bits in a binary representation.", 17 | "source": "Christian Willner, Eric Willigers", 18 | "source_url": "https://forum.exercism.org/t/new-exercise-suggestion-pop-count/7632/5" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/eliuds-eggs/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/eliuds-eggs/EliudsEggs.roc: -------------------------------------------------------------------------------- 1 | module [egg_count] 2 | 3 | egg_count : U64 -> U64 4 | egg_count = |number| 5 | crash("Please implement 'egg_count'") 6 | -------------------------------------------------------------------------------- /exercises/practice/error-handling/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Implement various kinds of error handling and resource management. 4 | 5 | An important point of programming is how to handle errors and close resources even if errors occur. 6 | 7 | This exercise requires you to handle various errors. 8 | Because error handling is rather programming language specific you'll have to refer to the tests for your track to see what's exactly required. 9 | -------------------------------------------------------------------------------- /exercises/practice/error-handling/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ErrorHandling.roc" 8 | ], 9 | "test": [ 10 | "error-handling-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement various kinds of error handling and resource management." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/etl/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [transform] 2 | 3 | to_lower : U8 -> U8 4 | to_lower = |char| 5 | if char >= 'A' and char <= 'Z' then 6 | char - 'A' + 'a' 7 | else 8 | char 9 | 10 | transform : Dict U64 (List U8) -> Dict U8 U64 11 | transform = |legacy| 12 | legacy 13 | |> Dict.join_map( 14 | |score, letters| 15 | letters 16 | |> List.map(|c| (to_lower(c), score)) 17 | |> Dict.from_list, 18 | ) 19 | -------------------------------------------------------------------------------- /exercises/practice/etl/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Etl.roc" 8 | ], 9 | "test": [ 10 | "etl-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Change the data format for scoring a game to more easily add other languages.", 17 | "source": "Based on an exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 18 | "source_url": "https://turing.edu" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/etl/Etl.roc: -------------------------------------------------------------------------------- 1 | module [transform] 2 | 3 | transform : Dict U64 (List U8) -> Dict U8 U64 4 | transform = |legacy| 5 | crash("Please implement the 'transform' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/flatten-array/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Take a nested array of any depth and return a fully flattened array. 4 | 5 | Note that some language tracks may include null-like values in the input array, and the way these values are represented varies by track. 6 | Such values should be excluded from the flattened array. 7 | 8 | Additionally, the input may be of a different data type and contain different types, depending on the track. 9 | 10 | Check the test suite for details. 11 | 12 | ## Example 13 | 14 | input: `[1, [2, 6, null], [[null, [4]], 5]]` 15 | 16 | output: `[1, 2, 6, 4, 5]` 17 | -------------------------------------------------------------------------------- /exercises/practice/flatten-array/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | A shipment of emergency supplies has arrived, but there's a problem. 4 | To protect from damage, the items — flashlights, first-aid kits, blankets — are packed inside boxes, and some of those boxes are nested several layers deep inside other boxes! 5 | 6 | To be prepared for an emergency, everything must be easily accessible in one box. 7 | Can you unpack all the supplies and place them into a single box, so they're ready when needed most? 8 | -------------------------------------------------------------------------------- /exercises/practice/flatten-array/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [flatten] 2 | 3 | NestedValue : [Value I64, Null, NestedArray (List NestedValue)] 4 | 5 | flatten : NestedValue -> List I64 6 | flatten = |array| 7 | when array is 8 | NestedArray(list) -> list |> List.join_map(flatten) 9 | Value(value) -> [value] 10 | Null -> [] 11 | -------------------------------------------------------------------------------- /exercises/practice/flatten-array/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "FlattenArray.roc" 8 | ], 9 | "test": [ 10 | "flatten-array-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Take a nested list and return a single list with all values except nil/null.", 17 | "source": "Interview Question", 18 | "source_url": "https://reference.wolfram.com/language/ref/Flatten.html" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/flatten-array/.meta/plugins.py: -------------------------------------------------------------------------------- 1 | def to_nested(value, top_level=True): 2 | if value is None: 3 | return "Null" 4 | elif isinstance(value, int): 5 | return f"Value {value}" 6 | else: 7 | content = ", ".join([to_nested(elem, False) for elem in value]) 8 | return f"NestedArray [\n{content}]" 9 | -------------------------------------------------------------------------------- /exercises/practice/flatten-array/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} ({{ plugins.to_nested(case["input"]["array"]) }}) 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/flatten-array/FlattenArray.roc: -------------------------------------------------------------------------------- 1 | module [flatten] 2 | 3 | NestedValue : [Value I64, Null, NestedArray (List NestedValue)] 4 | 5 | flatten : NestedValue -> List I64 6 | flatten = |array| 7 | crash("Please implement the 'flatten' function") 8 | -------------------------------------------------------------------------------- /exercises/practice/food-chain/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "FoodChain.roc" 8 | ], 9 | "test": [ 10 | "food-chain-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Generate the lyrics of the song 'I Know an Old Lady Who Swallowed a Fly'.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/There_Was_an_Old_Lady_Who_Swallowed_a_Fly" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/food-chain/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["startVerse"] | to_roc }} {{ case["input"]["endVerse"] | to_roc }} 11 | result == {{ case["expected"] | join('\n') | to_roc_multiline_string | indent(8) }} 12 | 13 | {% endfor %} -------------------------------------------------------------------------------- /exercises/practice/food-chain/FoodChain.roc: -------------------------------------------------------------------------------- 1 | module [recite] 2 | 3 | recite : U64, U64 -> Str 4 | recite = |start_verse, end_verse| 5 | crash("Please implement 'recite'") 6 | -------------------------------------------------------------------------------- /exercises/practice/forth/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Forth.roc" 8 | ], 9 | "test": [ 10 | "forth-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement an evaluator for a very simple subset of Forth." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/forth/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import Forth exposing [evaluate] 6 | 7 | {% for case in cases -%} 8 | {% for innerCase in case["cases"] %} 9 | # {{ case["description"] }}: {{ innerCase["description"] }} 10 | expect 11 | result = evaluate {{ innerCase["input"]["instructions"] | join('\n') | to_roc_multiline_string | indent(8) }} 12 | {%- if innerCase["expected"]["error"] %} 13 | Result.isErr result 14 | {%- else %} 15 | result == Ok {{ innerCase["expected"] }} 16 | {%- endif %} 17 | {% endfor %} 18 | {% endfor %} 19 | -------------------------------------------------------------------------------- /exercises/practice/forth/Forth.roc: -------------------------------------------------------------------------------- 1 | module [evaluate] 2 | 3 | Stack : List I16 4 | 5 | evaluate : Str -> Result Stack _ 6 | evaluate = |program| 7 | crash("Please implement 'evaluate'") 8 | -------------------------------------------------------------------------------- /exercises/practice/gigasecond/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to determine the date and time one gigasecond after a certain date. 4 | 5 | A gigasecond is one thousand million seconds. 6 | That is a one with nine zeros after it. 7 | 8 | If you were born on _January 24th, 2015 at 22:00 (10:00:00pm)_, then you would be a gigasecond old on _October 2nd, 2046 at 23:46:40 (11:46:40pm)_. 9 | -------------------------------------------------------------------------------- /exercises/practice/gigasecond/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Gigasecond.roc" 8 | ], 9 | "test": [ 10 | "gigasecond-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a moment, determine the moment that would be after a gigasecond has passed.", 17 | "source": "Chapter 9 in Chris Pine's online Learn to Program tutorial.", 18 | "source_url": "https://pine.fm/LearnToProgram/?Chapter=09" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/gigasecond/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header(imports=["isodate"]) }} 4 | 5 | import {{ exercise | to_pascal }} exposing [add] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["moment"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/gigasecond/Gigasecond.roc: -------------------------------------------------------------------------------- 1 | module [add] 2 | 3 | add : Str -> Str 4 | add = |moment| 5 | crash("Please implement the 'add' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/go-counting/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "GoCounting.roc" 8 | ], 9 | "test": [ 10 | "go-counting-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Count the scored points on a Go board." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/go-counting/GoCounting.roc: -------------------------------------------------------------------------------- 1 | module [territory, territories] 2 | 3 | Intersection : { x : U64, y : U64 } 4 | 5 | Stone : [White, Black, None] 6 | 7 | Territory : { 8 | owner : Stone, 9 | territory : Set Intersection, 10 | } 11 | 12 | Territories : { 13 | black : Set Intersection, 14 | white : Set Intersection, 15 | none : Set Intersection, 16 | } 17 | 18 | territory : Str, Intersection -> Result Territory _ 19 | territory = |board_str, { x, y }| 20 | crash("Please implement the 'territory' function") 21 | 22 | territories : Str -> Result Territories _ 23 | territories = |board_str| 24 | crash("Please implement the 'territories' function") 25 | -------------------------------------------------------------------------------- /exercises/practice/grains/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Calculate the number of grains of wheat on a chessboard. 4 | 5 | A chessboard has 64 squares. 6 | Square 1 has one grain, square 2 has two grains, square 3 has four grains, and so on, doubling each time. 7 | 8 | Write code that calculates: 9 | 10 | - the number of grains on a given square 11 | - the total number of grains on the chessboard 12 | -------------------------------------------------------------------------------- /exercises/practice/grains/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | There once was a wise servant who saved the life of a prince. 4 | The king promised to pay whatever the servant could dream up. 5 | Knowing that the king loved chess, the servant told the king he would like to have grains of wheat. 6 | One grain on the first square of a chessboard, with the number of grains doubling on each successive square. 7 | -------------------------------------------------------------------------------- /exercises/practice/grains/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [grains_on_square, total_grains] 2 | 3 | grains_on_square : U8 -> Result U64 [SquareArgWasNotBetween1And64 U8] 4 | grains_on_square = |square| 5 | if square > 0 and square <= 64 then 6 | 2u64 |> Num.pow_int((Num.to_u64(square) - 1)) |> Ok 7 | else 8 | Err(SquareArgWasNotBetween1And64(square)) 9 | 10 | total_grains : U64 11 | total_grains = 12 | Num.max_u64 13 | -------------------------------------------------------------------------------- /exercises/practice/grains/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Grains.roc" 8 | ], 9 | "test": [ 10 | "grains-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Calculate the number of grains of wheat on a chessboard given that the number on each square doubles.", 17 | "source": "The CodeRanch Cattle Drive, Assignment 6", 18 | "source_url": "https://web.archive.org/web/20240908084142/https://coderanch.com/wiki/718824/Grains" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/grains/Grains.roc: -------------------------------------------------------------------------------- 1 | module [grains_on_square, total_grains] 2 | 3 | grains_on_square : U8 -> Result U64 _ 4 | grains_on_square = |square| 5 | crash("Please implement the 'grains_on_square' function") 6 | 7 | total_grains : U64 8 | total_grains = 9 | crash("Please implement the 'total_grains' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/grep/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Grep.roc" 8 | ], 9 | "test": [ 10 | "grep-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Search a file for lines matching a regular expression pattern. Return the line number and contents of each matching line.", 17 | "source": "Conversation with Nate Foster.", 18 | "source_url": "https://www.cs.cornell.edu/Courses/cs3110/2014sp/hw/0/ps0.pdf" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/grep/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [grep] 6 | 7 | {% for case in cases -%} 8 | {% for innerCase in case["cases"] -%} 9 | # {{ case["description"] }} - {{ innerCase["description"] }} 10 | expect 11 | result = {{ innerCase["property"] | to_snake }} {{ innerCase["input"]["pattern"] | to_roc }} {{ innerCase["input"]["flags"] | to_roc }} {{ innerCase["input"]["files"] | to_roc }} 12 | result == Ok {{ innerCase["expected"] | join('\n') | to_roc_multiline_string | indent(8) }} 13 | 14 | {% endfor %} 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /exercises/practice/grep/Grep.roc: -------------------------------------------------------------------------------- 1 | module [grep] 2 | 3 | import "iliad.txt" as iliad : Str 4 | import "midsummer-night.txt" as midsummer_night : Str 5 | import "paradise-lost.txt" as paradise_lost : Str 6 | 7 | grep : Str, List Str, List Str -> Result Str _ 8 | grep = |pattern, flags, files| 9 | crash("Please implement 'grep'") 10 | -------------------------------------------------------------------------------- /exercises/practice/grep/iliad.txt: -------------------------------------------------------------------------------- 1 | Achilles sing, O Goddess! Peleus' son; 2 | His wrath pernicious, who ten thousand woes 3 | Caused to Achaia's host, sent many a soul 4 | Illustrious into Ades premature, 5 | And Heroes gave (so stood the will of Jove) 6 | To dogs and to all ravening fowls a prey, 7 | When fierce dispute had separated once 8 | The noble Chief Achilles from the son 9 | Of Atreus, Agamemnon, King of men. -------------------------------------------------------------------------------- /exercises/practice/grep/midsummer-night.txt: -------------------------------------------------------------------------------- 1 | I do entreat your grace to pardon me. 2 | I know not by what power I am made bold, 3 | Nor how it may concern my modesty, 4 | In such a presence here to plead my thoughts; 5 | But I beseech your grace that I may know 6 | The worst that may befall me in this case, 7 | If I refuse to wed Demetrius. -------------------------------------------------------------------------------- /exercises/practice/grep/paradise-lost.txt: -------------------------------------------------------------------------------- 1 | Of Mans First Disobedience, and the Fruit 2 | Of that Forbidden Tree, whose mortal tast 3 | Brought Death into the World, and all our woe, 4 | With loss of Eden, till one greater Man 5 | Restore us, and regain the blissful Seat, 6 | Sing Heav'nly Muse, that on the secret top 7 | Of Oreb, or of Sinai, didst inspire 8 | That Shepherd, who first taught the chosen Seed -------------------------------------------------------------------------------- /exercises/practice/hamming/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Calculate the Hamming distance between two DNA strands. 4 | 5 | We read DNA using the letters C, A, G and T. 6 | Two strands might look like this: 7 | 8 | GAGCCTACTAACGGGAT 9 | CATCGTAATGACGGCCT 10 | ^ ^ ^ ^ ^ ^^ 11 | 12 | They have 7 differences, and therefore the Hamming distance is 7. 13 | 14 | ## Implementation notes 15 | 16 | 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. 17 | -------------------------------------------------------------------------------- /exercises/practice/hamming/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [distance] 2 | 3 | distance : Str, Str -> Result (Num *) [StrandArgsWereNotOfEqualLength Str Str] 4 | distance = |strand1, strand2| 5 | nucleotides1 = strand1 |> Str.to_utf8 6 | nucleotides2 = strand2 |> Str.to_utf8 7 | if List.len(nucleotides1) == List.len(nucleotides2) then 8 | List.map2( 9 | nucleotides1, 10 | nucleotides2, 11 | |n1, n2| 12 | if n1 == n2 then 0 else 1, 13 | ) 14 | |> List.sum 15 | |> Ok 16 | else 17 | Err(StrandArgsWereNotOfEqualLength(strand1, strand2)) 18 | -------------------------------------------------------------------------------- /exercises/practice/hamming/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Hamming.roc" 8 | ], 9 | "test": [ 10 | "hamming-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Calculate the Hamming distance between two DNA strands.", 17 | "source": "The Calculating Point Mutations problem at Rosalind", 18 | "source_url": "https://rosalind.info/problems/hamm/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/hamming/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["strand1"] | to_roc }} {{ case["input"]["strand2"] | to_roc }} 11 | {%- if case["expected"]["error"] %} 12 | Result.isErr result 13 | {%- else %} 14 | result == Ok {{ case["expected"] }} 15 | {%- endif %} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/hamming/Hamming.roc: -------------------------------------------------------------------------------- 1 | module [distance] 2 | 3 | distance : Str, Str -> Result (Num *) _ 4 | distance = |strand1, strand2| 5 | crash("Please implement the 'distance' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.docs/instructions.append.md: -------------------------------------------------------------------------------- 1 | # Instructions append 2 | 3 | The file to edit is named `HelloWorld.roc`. 4 | 5 | If you are using the command line, run the test suite using `roc test hello-world-test.roc` 6 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | The classical introductory exercise. 4 | Just say "Hello, World!". 5 | 6 | ["Hello, World!"][hello-world] is the traditional first program for beginning programming in a new language or environment. 7 | 8 | The objectives are simple: 9 | 10 | - Modify the provided code so that it produces the string "Hello, World!". 11 | - Run the test suite and make sure that it succeeds. 12 | - Submit your solution and check it at the website. 13 | 14 | If everything goes well, you will be ready to fetch your first real exercise. 15 | 16 | [hello-world]: https://en.wikipedia.org/wiki/%22Hello,_world!%22_program 17 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [hello] 2 | 3 | hello : Str 4 | hello = "Hello, World!" 5 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "contributors": [ 6 | "keiravillekode" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "HelloWorld.roc" 11 | ], 12 | "test": [ 13 | "hello-world-test.roc" 14 | ], 15 | "example": [ 16 | ".meta/Example.roc" 17 | ] 18 | }, 19 | "blurb": "Exercism's classic introductory exercise. Just say \"Hello, World!\".", 20 | "source": "This is an exercise to introduce users to using Exercism", 21 | "source_url": "https://en.wikipedia.org/wiki/%22Hello,_world!%22_program" 22 | } 23 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | 4 | {{ macros.header()}} 5 | 6 | import HelloWorld exposing [hello] 7 | 8 | {% for case in cases -%} 9 | # {{ case["description"] }} 10 | expect 11 | result = {{ case["property"] }} 12 | result == {{ case ["expected"] | to_roc }} 13 | 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. 2 | # 3 | # Regenerating this file via `configlet sync` will: 4 | # - Recreate every `description` key/value pair 5 | # - Recreate every `reimplements` key/value pair, where they exist in problem-specifications 6 | # - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) 7 | # - Preserve any other key/value pair 8 | # 9 | # As user-added comments (using the # character) will be removed when this file 10 | # is regenerated, comments can be added via a `comment` key. 11 | 12 | [af9ffe10-dc13-42d8-a742-e7bdafac449d] 13 | description = "Say Hi!" 14 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/HelloWorld.roc: -------------------------------------------------------------------------------- 1 | module [hello] 2 | 3 | hello : Str 4 | hello = "Goodbye, Mars!" 5 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/hello-world-test.roc: -------------------------------------------------------------------------------- 1 | # These tests are auto-generated with test data from: 2 | # https://github.com/exercism/problem-specifications/tree/main/exercises/hello-world/canonical-data.json 3 | # File last updated on 2025-01-04 4 | app [main!] { 5 | pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br", 6 | } 7 | 8 | import pf.Stdout 9 | 10 | main! = |_args| 11 | Stdout.line!("") 12 | 13 | import HelloWorld exposing [hello] 14 | 15 | # Say Hi! 16 | expect 17 | result = hello 18 | result == "Hello, World!" 19 | 20 | -------------------------------------------------------------------------------- /exercises/practice/hexadecimal/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Convert a hexadecimal number, represented as a string (e.g. "10af8c"), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion). 4 | 5 | On the web we use hexadecimal to represent colors, e.g. green: 008000, teal: 008080, navy: 000080). 6 | 7 | The program should handle invalid hexadecimal strings. 8 | -------------------------------------------------------------------------------- /exercises/practice/hexadecimal/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Hexadecimal.roc" 8 | ], 9 | "test": [ 10 | "hexadecimal-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert a hexadecimal number, represented as a string (e.g. \"10af8c\"), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion).", 17 | "source": "All of Computer Science", 18 | "source_url": "https://www.wolframalpha.com/examples/mathematics/numbers/base-conversions" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/hexadecimal/Hexadecimal.roc: -------------------------------------------------------------------------------- 1 | module [parse] 2 | 3 | parse : Str -> Result U64 _ 4 | parse = |string| 5 | crash("Please implement the 'parse' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/high-scores/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Manage a game player's High Score list. 4 | 5 | Your task is to build a high-score component of the classic Frogger game, one of the highest selling and most addictive games of all time, and a classic of the arcade era. 6 | Your task is to write methods that return the highest score from the list, the last added score and the three highest scores. 7 | -------------------------------------------------------------------------------- /exercises/practice/high-scores/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [latest, personal_best, personal_top_three] 2 | 3 | Score : U64 4 | 5 | latest : List Score -> Result Score [ListWasEmpty] 6 | latest = List.last 7 | 8 | personal_best : List Score -> Result Score [ListWasEmpty] 9 | personal_best = List.max 10 | 11 | personal_top_three : List Score -> List Score 12 | personal_top_three = |scores| 13 | scores |> List.sort_desc |> List.take_first(3) 14 | -------------------------------------------------------------------------------- /exercises/practice/high-scores/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "HighScores.roc" 8 | ], 9 | "test": [ 10 | "high-scores-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Manage a player's High Score list.", 17 | "source": "Tribute to the eighties' arcade game Frogger" 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/high-scores/HighScores.roc: -------------------------------------------------------------------------------- 1 | module [latest, personal_best, personal_top_three] 2 | 3 | Score : U64 4 | 5 | latest : List Score -> Result Score _ 6 | latest = |scores| 7 | crash("Please implement the 'latest' function") 8 | 9 | personal_best : List Score -> Result Score _ 10 | personal_best = |scores| 11 | crash("Please implement the 'personal_best' function") 12 | 13 | personal_top_three : List Score -> List Score 14 | personal_top_three = |scores| 15 | crash("Please implement the 'personal_top_three' function") 16 | -------------------------------------------------------------------------------- /exercises/practice/house/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "House.roc" 8 | ], 9 | "test": [ 10 | "house-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Output the nursery rhyme 'This is the House that Jack Built'.", 17 | "source": "British nursery rhyme", 18 | "source_url": "https://en.wikipedia.org/wiki/This_Is_The_House_That_Jack_Built" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/house/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["startVerse"] }} {{ case["input"]["endVerse"] }} 11 | result == {{ "\n".join(case["expected"]) | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/house/House.roc: -------------------------------------------------------------------------------- 1 | module [recite] 2 | 3 | recite : U64, U64 -> Str 4 | recite = |start_verse, end_verse| 5 | crash("Please implement the 'recite' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/isbn-verifier/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "IsbnVerifier.roc" 8 | ], 9 | "test": [ 10 | "isbn-verifier-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Check if a given string is a valid ISBN-10 number.", 17 | "source": "Converting a string into a number and some basic processing utilizing a relatable real world example.", 18 | "source_url": "https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digit_calculation" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/isbn-verifier/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [is_valid] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["isbn"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/isbn-verifier/IsbnVerifier.roc: -------------------------------------------------------------------------------- 1 | module [is_valid] 2 | 3 | is_valid : Str -> Bool 4 | is_valid = |isbn| 5 | crash("Please implement the 'is_valid' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Determine if a word or phrase is an isogram. 4 | 5 | An isogram (also known as a "non-pattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times. 6 | 7 | Examples of isograms: 8 | 9 | - lumberjacks 10 | - background 11 | - downstream 12 | - six-year-old 13 | 14 | The word _isograms_, however, is not an isogram, because the s repeats. 15 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [is_isogram] 2 | 3 | is_isogram : Str -> Bool 4 | is_isogram = |phrase| 5 | chars = 6 | phrase 7 | |> Str.to_utf8 8 | |> List.drop_if(|c| c == ' ' or c == '-') 9 | |> List.map(|c| if c >= 'a' and c <= 'z' then c + 'A' - 'a' else c) # to uppercase 10 | 11 | (List.len(chars)) == Set.len(Set.from_list(chars)) 12 | 13 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Isogram.roc" 8 | ], 9 | "test": [ 10 | "isogram-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Determine if a word or phrase is an isogram.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Isogram" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [is_isogram] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["phrase"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/isogram/Isogram.roc: -------------------------------------------------------------------------------- 1 | module [is_isogram] 2 | 3 | is_isogram : Str -> Bool 4 | is_isogram = |phrase| 5 | crash("Please implement the 'is_isogram' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/killer-sudoku-helper/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "KillerSudokuHelper.roc" 8 | ], 9 | "test": [ 10 | "killer-sudoku-helper-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Write a tool that makes it easier to solve Killer Sudokus", 17 | "source": "Created by Sascha Mann, Jeremy Walker, and BethanyG for the Julia track on Exercism.", 18 | "source_url": "https://github.com/exercism/julia/pull/413" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/killer-sudoku-helper/KillerSudokuHelper.roc: -------------------------------------------------------------------------------- 1 | module [combinations] 2 | 3 | Combination : List U8 4 | 5 | combinations : { sum : U8, size : U8, exclude ?? List U8 } -> List Combination 6 | combinations = |{ sum, size, exclude ?? [] }| 7 | crash("Please implement the 'combinations' function") 8 | -------------------------------------------------------------------------------- /exercises/practice/kindergarten-garden/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The kindergarten class is learning about growing plants. 4 | The teacher thought it would be a good idea to give the class seeds to plant and grow in the dirt. 5 | To this end, the children have put little cups along the window sills and planted one type of plant in each cup. 6 | The children got to pick their favorites from four available types of seeds: grass, clover, radishes, and violets. 7 | -------------------------------------------------------------------------------- /exercises/practice/kindergarten-garden/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "KindergartenGarden.roc" 8 | ], 9 | "test": [ 10 | "kindergarten-garden-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a diagram, determine which plants each child in the kindergarten class is responsible for.", 17 | "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 18 | "source_url": "https://turing.edu" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/kindergarten-garden/KindergartenGarden.roc: -------------------------------------------------------------------------------- 1 | module [plants] 2 | 3 | Student : [Alice, Bob, Charlie, David, Eve, Fred, Ginny, Harriet, Ileana, Joseph, Kincaid, Larry] 4 | Plant : [Grass, Clover, Radishes, Violets] 5 | 6 | plants : Str, Student -> Result (List Plant) _ 7 | plants = |diagram, student| 8 | crash("Please implement the 'plants' function") 9 | -------------------------------------------------------------------------------- /exercises/practice/knapsack/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Lhakpa is a [Sherpa][sherpa] mountain guide and porter. 4 | After months of careful planning, the expedition Lhakpa works for is about to leave. 5 | She will be paid the value she carried to the base camp. 6 | 7 | In front of her are many items, each with a value and weight. 8 | Lhakpa would gladly take all of the items, but her knapsack can only hold so much weight. 9 | 10 | [sherpa]: https://en.wikipedia.org/wiki/Sherpa_people#Mountaineering 11 | -------------------------------------------------------------------------------- /exercises/practice/knapsack/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [maximum_value] 2 | 3 | Item : { weight : U64, value : U64 } 4 | 5 | maximum_value : { items : List Item, maximum_weight : U64 } -> U64 6 | maximum_value = |{ items, maximum_weight }| 7 | when items is 8 | [] -> 0 9 | [item, .. as rest] -> 10 | max_value_without_item = maximum_value({ items: rest, maximum_weight }) 11 | if item.weight > maximum_weight then 12 | max_value_without_item 13 | else 14 | max_value_with_item = item.value + maximum_value({ items: rest, maximum_weight: maximum_weight - item.weight }) 15 | Num.max(max_value_without_item, max_value_with_item) 16 | -------------------------------------------------------------------------------- /exercises/practice/knapsack/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Knapsack.roc" 8 | ], 9 | "test": [ 10 | "knapsack-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a knapsack that can only carry a certain weight, determine which items to put in the knapsack in order to maximize their combined value.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Knapsack_problem" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/knapsack/Knapsack.roc: -------------------------------------------------------------------------------- 1 | module [maximum_value] 2 | 3 | Item : { weight : U64, value : U64 } 4 | 5 | maximum_value : { items : List Item, maximum_weight : U64 } -> U64 6 | maximum_value = |{ items, maximum_weight }| 7 | crash("Please implement the 'maximum_value' function") 8 | -------------------------------------------------------------------------------- /exercises/practice/largest-series-product/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You work for a government agency that has intercepted a series of encrypted communication signals from a group of bank robbers. 4 | The signals contain a long sequence of digits. 5 | Your team needs to use various digital signal processing techniques to analyze the signals and identify any patterns that may indicate the planning of a heist. 6 | -------------------------------------------------------------------------------- /exercises/practice/largest-series-product/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "LargestSeriesProduct.roc" 8 | ], 9 | "test": [ 10 | "largest-series-product-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a string of digits, calculate the largest product for a contiguous substring of digits of length n.", 17 | "source": "A variation on Problem 8 at Project Euler", 18 | "source_url": "https://projecteuler.net/problem=8" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/largest-series-product/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | digits = {{ case["input"]["digits"] | to_roc }} 11 | result = digits |> {{ case["property"] | to_snake }} {{ case["input"]["span"] | to_roc }} 12 | {%- if case["expected"]["error"] %} 13 | result |> Result.isErr 14 | {%- else %} 15 | expected = Ok {{ case["expected"] | to_roc }} 16 | result == expected 17 | {%- endif %} 18 | 19 | {% endfor %} 20 | -------------------------------------------------------------------------------- /exercises/practice/largest-series-product/LargestSeriesProduct.roc: -------------------------------------------------------------------------------- 1 | module [largest_product] 2 | 3 | largest_product : Str, U64 -> Result U64 _ 4 | largest_product = |digits, span| 5 | crash("Please implement the 'largest_product' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/leap/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to determine whether a given year is a leap year. 4 | -------------------------------------------------------------------------------- /exercises/practice/leap/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | A leap year (in the Gregorian calendar) occurs: 4 | 5 | - In every year that is evenly divisible by 4. 6 | - Unless the year is evenly divisible by 100, in which case it's only a leap year if the year is also evenly divisible by 400. 7 | 8 | Some examples: 9 | 10 | - 1997 was not a leap year as it's not divisible by 4. 11 | - 1900 was not a leap year as it's not divisible by 400. 12 | - 2000 was a leap year! 13 | 14 | ~~~~exercism/note 15 | For a delightful, four-minute explanation of the whole phenomenon of leap years, check out [this YouTube video](https://www.youtube.com/watch?v=xX96xng7sAE). 16 | ~~~~ 17 | -------------------------------------------------------------------------------- /exercises/practice/leap/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [is_leap_year] 2 | 3 | is_leap_year : I64 -> Bool 4 | is_leap_year = |year| 5 | (year % 4 == 0) and (year % 400 == 0 or year % 100 != 0) 6 | -------------------------------------------------------------------------------- /exercises/practice/leap/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Leap.roc" 8 | ], 9 | "test": [ 10 | "leap-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Determine whether a given year is a leap year.", 17 | "source": "CodeRanch Cattle Drive, Assignment 3", 18 | "source_url": "https://web.archive.org/web/20240907033714/https://coderanch.com/t/718816/Leap" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/leap/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | 4 | {{ macros.header()}} 5 | 6 | import Leap exposing [is_leap_year] 7 | 8 | {% for case in cases -%} 9 | # {{ case["description"] }} 10 | expect 11 | result = (is_leap_year {{ case["input"]["year"] }}) 12 | result == {{ case ["expected"] | to_roc }} 13 | 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /exercises/practice/leap/Leap.roc: -------------------------------------------------------------------------------- 1 | module [is_leap_year] 2 | 3 | is_leap_year : I64 -> Bool 4 | is_leap_year = |year| 5 | crash("Please implement the `is_leap_year` function") 6 | -------------------------------------------------------------------------------- /exercises/practice/list-ops/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ListOps.roc" 8 | ], 9 | "test": [ 10 | "list-ops-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement basic list operations." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/luhn/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Luhn.roc" 8 | ], 9 | "test": [ 10 | "luhn-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a number determine whether or not it is valid per the Luhn formula.", 17 | "source": "The Luhn Algorithm on Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Luhn_algorithm" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/luhn/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["value"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/luhn/Luhn.roc: -------------------------------------------------------------------------------- 1 | module [valid] 2 | 3 | valid : Str -> Bool 4 | valid = |digits| 5 | crash("Please implement 'valid'") 6 | -------------------------------------------------------------------------------- /exercises/practice/matching-brackets/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Given a string containing brackets `[]`, braces `{}`, parentheses `()`, or any combination thereof, verify that any and all pairs are matched and nested correctly. 4 | Any other characters should be ignored. 5 | For example, `"{what is (42)}?"` is balanced and `"[text}"` is not. 6 | -------------------------------------------------------------------------------- /exercises/practice/matching-brackets/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You're given the opportunity to write software for the Bracketeer™, an ancient but powerful mainframe. 4 | The software that runs on it is written in a proprietary language. 5 | Much of its syntax is familiar, but you notice _lots_ of brackets, braces and parentheses. 6 | Despite the Bracketeer™ being powerful, it lacks flexibility. 7 | If the source code has any unbalanced brackets, braces or parentheses, the Bracketeer™ crashes and must be rebooted. 8 | To avoid such a scenario, you start writing code that can verify that brackets, braces, and parentheses are balanced before attempting to run it on the Bracketeer™. 9 | -------------------------------------------------------------------------------- /exercises/practice/matching-brackets/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "MatchingBrackets.roc" 8 | ], 9 | "test": [ 10 | "matching-brackets-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Make sure the brackets and braces all match.", 17 | "source": "Ginna Baker" 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/matching-brackets/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["input"]["value"] | to_roc }} |> {{ case["property"] | to_snake }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/matching-brackets/MatchingBrackets.roc: -------------------------------------------------------------------------------- 1 | module [is_paired] 2 | 3 | is_paired : Str -> Bool 4 | is_paired = |string| 5 | crash("Please implement the 'is_paired' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/matrix/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Matrix.roc" 8 | ], 9 | "test": [ 10 | "matrix-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a string representing a matrix of numbers, return the rows and columns of that matrix.", 17 | "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 18 | "source_url": "https://turing.edu" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/matrix/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [row, column] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | matrix_str = {{ case["input"]["string"] | to_roc_multiline_string | indent(8) }} 11 | result = matrix_str |> {{ case["property"] | to_snake }} {{ case["input"]["index"] | to_roc }} 12 | result == Ok {{ case["expected"] | to_roc }} 13 | 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /exercises/practice/matrix/Matrix.roc: -------------------------------------------------------------------------------- 1 | module [row, column] 2 | 3 | column : Str, U64 -> Result (List I64) _ 4 | column = |matrix_str, index| 5 | crash("Please implement the 'column' function") 6 | 7 | row : Str, U64 -> Result (List I64) _ 8 | row = |matrix_str, index| 9 | crash("Please implement the 'row' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/meetup/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Meetup.roc" 8 | ], 9 | "test": [ 10 | "meetup-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Calculate the date of meetups.", 17 | "source": "Jeremy Hinegardner mentioned a Boulder meetup that happens on the Wednesteenth of every month" 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/meetup/Meetup.roc: -------------------------------------------------------------------------------- 1 | module [meetup] 2 | 3 | Week : [First, Second, Third, Fourth, Last, Teenth] 4 | DayOfWeek : [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] 5 | 6 | meetup : { year : I64, month : U8, week : Week, day_of_week : DayOfWeek } -> Result Str _ 7 | meetup = |{ year, month, week, day_of_week }| 8 | crash("Please implement the 'meetup' function") 9 | 10 | # HINT: we have added the `roc-isodate` package to the app's header in 11 | # meetup-test.roc, so you can use it here if you need to. 12 | # For example, you could import isodate.Date, just sayin'. 13 | -------------------------------------------------------------------------------- /exercises/practice/micro-blog/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [truncate] 2 | 3 | import unicode.Grapheme 4 | 5 | GraphemeErrors : [ 6 | CodepointTooLarge, 7 | EncodesSurrogateHalf, 8 | ExpectedContinuation, 9 | InvalidUtf8, 10 | ListWasEmpty, 11 | OverlongEncoding, 12 | ] 13 | 14 | truncate : Str -> Result Str GraphemeErrors 15 | truncate = |input| 16 | input 17 | |> Grapheme.split? 18 | |> List.take_first(5) 19 | |> Str.join_with("") 20 | |> Ok 21 | -------------------------------------------------------------------------------- /exercises/practice/micro-blog/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "MicroBlog.roc" 8 | ], 9 | "test": [ 10 | "micro-blog-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given an input string, truncate it to 5 characters." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/micro-blog/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header(imports=["unicode"]) }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["phrase"] | to_roc }} 11 | result == Ok {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/micro-blog/MicroBlog.roc: -------------------------------------------------------------------------------- 1 | module [truncate] 2 | 3 | import unicode.Grapheme 4 | 5 | truncate : Str -> Result Str _ 6 | truncate = |input| 7 | crash("Please implement 'truncate'") 8 | -------------------------------------------------------------------------------- /exercises/practice/minesweeper/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | [Minesweeper][wikipedia] is a popular game where the user has to find the mines using numeric hints that indicate how many mines are directly adjacent (horizontally, vertically, diagonally) to a square. 4 | 5 | [wikipedia]: https://en.wikipedia.org/wiki/Minesweeper_(video_game) 6 | -------------------------------------------------------------------------------- /exercises/practice/minesweeper/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Minesweeper.roc" 8 | ], 9 | "test": [ 10 | "minesweeper-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Add the numbers to a minesweeper board." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/minesweeper/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | minefield = {{ case["input"]["minefield"] | to_roc_multiline_string | replace(" ", "·") | indent(8) }} |> Str.replaceEach "·" " " 11 | result = {{ case["property"] | to_snake }} minefield 12 | expected = {{ case["expected"] | to_roc_multiline_string | replace(" ", "·") | indent(8) }} |> Str.replaceEach "·" " " 13 | result == expected 14 | 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /exercises/practice/minesweeper/Minesweeper.roc: -------------------------------------------------------------------------------- 1 | module [annotate] 2 | 3 | annotate : Str -> Str 4 | annotate = |minefield| 5 | crash("Please implement the 'annotate' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/nth-prime/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Given a number n, determine what the nth prime is. 4 | 5 | By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. 6 | 7 | If your language provides methods in the standard library to deal with prime numbers, pretend they don't exist and implement them yourself. 8 | -------------------------------------------------------------------------------- /exercises/practice/nth-prime/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "NthPrime.roc" 8 | ], 9 | "test": [ 10 | "nth-prime-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a number n, determine what the nth prime is.", 17 | "source": "A variation on Problem 7 at Project Euler", 18 | "source_url": "https://projecteuler.net/problem=7" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/nth-prime/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] }} 11 | {%- if case["expected"]["error"] %} 12 | result |> Result.isErr 13 | {%- else %} 14 | result == Ok {{ case["expected"] }} 15 | {%- endif %} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/nth-prime/NthPrime.roc: -------------------------------------------------------------------------------- 1 | module [prime] 2 | 3 | prime : U64 -> Result U64 _ 4 | prime = |number| 5 | crash("Please implement the 'prime' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/nucleotide-count/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [nucleotide_counts] 2 | 3 | nucleotide_counts : Str -> Result { a : U64, c : U64, g : U64, t : U64 } _ 4 | nucleotide_counts = |input| 5 | Str.to_utf8(input) 6 | |> List.walk_try( 7 | { a: 0, c: 0, g: 0, t: 0 }, 8 | |state, elem| 9 | when elem is 10 | 'A' -> Ok({ state & a: state.a + 1 }) 11 | 'C' -> Ok({ state & c: state.c + 1 }) 12 | 'G' -> Ok({ state & g: state.g + 1 }) 13 | 'T' -> Ok({ state & t: state.t + 1 }) 14 | _ -> Err(InvalidNucleotide(elem)), 15 | ) 16 | -------------------------------------------------------------------------------- /exercises/practice/nucleotide-count/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "isaacvando" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "NucleotideCount.roc" 8 | ], 9 | "test": [ 10 | "nucleotide-count-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a DNA string, compute how many times each nucleotide occurs in the string.", 17 | "source": "The Calculating DNA Nucleotides_problem at Rosalind", 18 | "source_url": "https://rosalind.info/problems/dna/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/nucleotide-count/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["strand"] | to_roc }} 11 | {%- if case["expected"]["error"] %} 12 | Result.isErr result 13 | {%- else %} 14 | result == Ok {{ case["expected"] | to_roc }} 15 | {%- endif %} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/nucleotide-count/NucleotideCount.roc: -------------------------------------------------------------------------------- 1 | module [nucleotide_counts] 2 | 3 | nucleotide_counts : Str -> Result { a : U64, c : U64, g : U64, t : U64 } _ 4 | nucleotide_counts = |input| 5 | crash("Please implement 'nucleotide_counts'") 6 | -------------------------------------------------------------------------------- /exercises/practice/ocr-numbers/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "OcrNumbers.roc" 8 | ], 9 | "test": [ 10 | "ocr-numbers-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a 3 x 4 grid of pipes, underscores, and spaces, determine which number is represented, or whether it is garbled.", 17 | "source": "Inspired by the Bank OCR kata", 18 | "source_url": "https://codingdojo.org/kata/BankOCR/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/ocr-numbers/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | grid = {{ case["input"]["rows"] | to_roc_multiline_string | indent(8) }} 11 | result = {{ case["property"] | to_snake }} grid 12 | {%- if case["expected"]["error"] %} 13 | result |> Result.isErr 14 | {%- else %} 15 | expected = Ok {{ case["expected"] | to_roc }} 16 | result == expected 17 | {%- endif %} 18 | 19 | {% endfor %} 20 | -------------------------------------------------------------------------------- /exercises/practice/ocr-numbers/OcrNumbers.roc: -------------------------------------------------------------------------------- 1 | module [convert] 2 | 3 | convert : Str -> Result Str _ 4 | convert = |grid| 5 | crash("Please implement the 'convert' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/octal/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Octal.roc" 8 | ], 9 | "test": [ 10 | "octal-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert a octal number, represented as a string (e.g. '1735263'), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion).", 17 | "source": "All of Computer Science", 18 | "source_url": "https://www.wolframalpha.com/examples/mathematics/numbers/base-conversions" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/octal/Octal.roc: -------------------------------------------------------------------------------- 1 | module [parse] 2 | 3 | parse : Str -> Result U64 _ 4 | parse = |string| 5 | crash("Please implement the 'parse' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/palindrome-products/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "PalindromeProducts.roc" 8 | ], 9 | "test": [ 10 | "palindrome-products-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Detect palindrome products in a given range.", 17 | "source": "Problem 4 at Project Euler", 18 | "source_url": "https://projecteuler.net/problem=4" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/palindrome-products/PalindromeProducts.roc: -------------------------------------------------------------------------------- 1 | module [smallest, largest] 2 | 3 | smallest : { min : U64, max : U64 } -> Result { value : U64, factors : Set (U64, U64) } _ 4 | smallest = |{ min, max }| 5 | crash("Please implement the 'smallest' function") 6 | 7 | largest : { min : U64, max : U64 } -> Result { value : U64, factors : Set (U64, U64) } _ 8 | largest = |{ min, max }| 9 | crash("Please implement the 'largest' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/pangram/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to figure out if a sentence is a pangram. 4 | 5 | A pangram is a sentence using every letter of the alphabet at least once. 6 | It is case insensitive, so it doesn't matter if a letter is lower-case (e.g. `k`) or upper-case (e.g. `K`). 7 | 8 | For this exercise, a sentence is a pangram if it contains each of the 26 letters in the English alphabet. 9 | -------------------------------------------------------------------------------- /exercises/practice/pangram/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You work for a company that sells fonts through their website. 4 | They'd like to show a different sentence each time someone views a font on their website. 5 | To give a comprehensive sense of the font, the random sentences should use **all** the letters in the English alphabet. 6 | 7 | They're running a competition to get suggestions for sentences that they can use. 8 | You're in charge of checking the submissions to see if they are valid. 9 | 10 | ~~~~exercism/note 11 | Pangram comes from Greek, παν γράμμα, pan gramma, which means "every letter". 12 | 13 | The best known English pangram is: 14 | 15 | > The quick brown fox jumps over the lazy dog. 16 | ~~~~ 17 | -------------------------------------------------------------------------------- /exercises/practice/pangram/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [is_pangram] 2 | 3 | alphabet = 4 | List.range({ start: At('A'), end: At('Z') }) |> Set.from_list 5 | 6 | is_pangram : Str -> Bool 7 | is_pangram = |sentence| 8 | sentence 9 | |> Str.to_utf8 10 | |> Set.from_list 11 | |> Set.map(|c| if c >= 'a' and c <= 'z' then c + 'A' - 'a' else c) # to uppercase 12 | |> Set.keep_if(|c| c >= 'A' and c <= 'Z') 13 | |> Bool.is_eq(alphabet) 14 | -------------------------------------------------------------------------------- /exercises/practice/pangram/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Pangram.roc" 8 | ], 9 | "test": [ 10 | "pangram-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Determine if a sentence is a pangram.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Pangram" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/pangram/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [is_pangram] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["sentence"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/pangram/Pangram.roc: -------------------------------------------------------------------------------- 1 | module [is_pangram] 2 | 3 | is_pangram : Str -> Bool 4 | is_pangram = |sentence| 5 | crash("Please implement the 'is_pangram' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/pascals-triangle/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "PascalsTriangle.roc" 8 | ], 9 | "test": [ 10 | "pascals-triangle-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Compute Pascal's triangle up to a given number of rows.", 17 | "source": "Pascal's Triangle at Wolfram Math World", 18 | "source_url": "https://www.wolframalpha.com/input/?i=Pascal%27s+triangle" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/pascals-triangle/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [pascals_triangle] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = pascals_triangle {{ case["input"]["count"] | to_roc }} 11 | expected = [{%- for row in case["expected"] %} 12 | {{ row | to_roc }}, 13 | {%- endfor %}] 14 | result == expected 15 | 16 | {% endfor %} 17 | -------------------------------------------------------------------------------- /exercises/practice/pascals-triangle/PascalsTriangle.roc: -------------------------------------------------------------------------------- 1 | module [pascals_triangle] 2 | 3 | pascals_triangle : U64 -> List (List U64) 4 | pascals_triangle = |count| 5 | crash("Please implement the 'pascals_triangle' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/perfect-numbers/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "PerfectNumbers.roc" 8 | ], 9 | "test": [ 10 | "perfect-numbers-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Determine if a number is perfect, abundant, or deficient based on Nicomachus' (60 - 120 CE) classification scheme for positive integers.", 17 | "source": "Taken from Chapter 2 of Functional Thinking by Neal Ford.", 18 | "source_url": "https://www.oreilly.com/library/view/functional-thinking/9781449365509/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/perfect-numbers/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [classify] 6 | 7 | {% for supercase in cases %} 8 | ## 9 | ## {{ supercase["description"] }} 10 | ## 11 | 12 | {% for case in supercase["cases"] -%} 13 | # {{ case["description"] }} 14 | expect 15 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] }} 16 | {%- if case["expected"]["error"] %} 17 | Result.isErr result 18 | {%- else %} 19 | result == Ok {{ case["expected"] | to_pascal }} 20 | {%- endif %} 21 | 22 | {% endfor %} 23 | {% endfor %} 24 | -------------------------------------------------------------------------------- /exercises/practice/perfect-numbers/PerfectNumbers.roc: -------------------------------------------------------------------------------- 1 | module [classify] 2 | 3 | classify : U64 -> Result [Abundant, Deficient, Perfect] _ 4 | classify = |number| 5 | crash("Please implement the 'classify' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/phone-number/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "PhoneNumber.roc" 8 | ], 9 | "test": [ 10 | "phone-number-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Clean up user-entered phone numbers so that they can be sent SMS messages.", 17 | "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 18 | "source_url": "https://turing.edu" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/phone-number/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["phrase"] | to_roc }} 11 | {%- if case["expected"]["error"] %} 12 | result |> Result.isErr 13 | {%- else %} 14 | expected = Ok {{ case["expected"] | to_roc }} 15 | result == expected 16 | {%- endif %} 17 | 18 | {% endfor %} 19 | -------------------------------------------------------------------------------- /exercises/practice/phone-number/PhoneNumber.roc: -------------------------------------------------------------------------------- 1 | module [clean] 2 | 3 | clean : Str -> Result Str _ 4 | clean = |phone_number| 5 | crash("Please implement the 'clean' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/pig-latin/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Your parents have challenged you and your sibling to a game of two-on-two basketball. 4 | Confident they'll win, they let you score the first couple of points, but then start taking over the game. 5 | Needing a little boost, you start speaking in [Pig Latin][pig-latin], which is a made-up children's language that's difficult for non-children to understand. 6 | This will give you the edge to prevail over your parents! 7 | 8 | [pig-latin]: https://en.wikipedia.org/wiki/Pig_latin 9 | -------------------------------------------------------------------------------- /exercises/practice/pig-latin/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "PigLatin.roc" 8 | ], 9 | "test": [ 10 | "pig-latin-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement a program that translates from English to Pig Latin.", 17 | "source": "The Pig Latin exercise at Test First Teaching by Ultrasaurus", 18 | "source_url": "https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/pig-latin/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["cases"][0]["property"] | to_snake }}] 6 | 7 | {% for supercase in cases %} 8 | ## 9 | ## {{ supercase["description"] }} 10 | ## 11 | 12 | {% for case in supercase["cases"] -%} 13 | # {{ case["description"] }} 14 | expect 15 | result = {{ case["property"] | to_snake }} {{ case["input"]["phrase"] | to_roc }} 16 | result == {{ case["expected"] | to_roc }} 17 | 18 | {% endfor %} 19 | {% endfor %} 20 | -------------------------------------------------------------------------------- /exercises/practice/pig-latin/PigLatin.roc: -------------------------------------------------------------------------------- 1 | module [translate] 2 | 3 | translate : Str -> Str 4 | translate = |phrase| 5 | crash("Please implement the 'translate' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/poker/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Pick the best hand(s) from a list of poker hands. 4 | 5 | See [Wikipedia][poker-hands] for an overview of poker hands. 6 | 7 | [poker-hands]: https://en.wikipedia.org/wiki/List_of_poker_hands 8 | -------------------------------------------------------------------------------- /exercises/practice/poker/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Poker.roc" 8 | ], 9 | "test": [ 10 | "poker-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Pick the best hand(s) from a list of poker hands.", 17 | "source": "Inspired by the training course from Udacity.", 18 | "source_url": "https://www.udacity.com/course/design-of-computer-programs--cs212" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/poker/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | hands = {{ case["input"]["hands"] | to_roc }} 11 | result = {{ case["property"] | to_snake }} hands 12 | result == Ok {{ case["expected"] | to_roc }} 13 | 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /exercises/practice/poker/Poker.roc: -------------------------------------------------------------------------------- 1 | module [best_hands] 2 | 3 | best_hands : List Str -> Result (List Str) _ 4 | best_hands = |hands| 5 | crash("Please implement the 'best_hands' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/prime-factors/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [prime_factors] 2 | 3 | prime_factors : U64 -> List U64 4 | prime_factors = |value| 5 | find_prime_factors = |factors, n, p| 6 | if n < 2 then 7 | factors 8 | else if n |> Num.is_multiple_of(p) then 9 | find_prime_factors(List.append(factors, p), (n // p), p) 10 | else if p * p < n then 11 | next_p = if p == 2 then 3 else p + 2 12 | find_prime_factors(factors, n, next_p) 13 | else 14 | List.append(factors, n) 15 | 16 | find_prime_factors([], value, 2) 17 | -------------------------------------------------------------------------------- /exercises/practice/prime-factors/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "PrimeFactors.roc" 8 | ], 9 | "test": [ 10 | "prime-factors-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Compute the prime factors of a given natural number.", 17 | "source": "The Prime Factors Kata by Uncle Bob", 18 | "source_url": "https://web.archive.org/web/20221026171801/http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/prime-factors/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ exercise | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ exercise | to_snake }} {{ case["input"]["value"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/prime-factors/PrimeFactors.roc: -------------------------------------------------------------------------------- 1 | module [prime_factors] 2 | 3 | prime_factors : U64 -> List U64 4 | prime_factors = |value| 5 | crash("Please implement the 'prime_factors' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/protein-translation/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ProteinTranslation.roc" 8 | ], 9 | "test": [ 10 | "protein-translation-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Translate RNA sequences into proteins.", 17 | "source": "Tyler Long" 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/protein-translation/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [to_protein] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | rna = {{ case["input"]["strand"] | to_roc }} 11 | result = rna |> to_protein 12 | {%- if case["expected"]["error"] %} 13 | result |> Result.isErr 14 | {%- else %} 15 | result == Ok [{%- for aminoAcid in case["expected"] -%}{{ aminoAcid | to_pascal }}, {%- endfor %}] 16 | {%- endif %} 17 | 18 | {% endfor %} 19 | 20 | -------------------------------------------------------------------------------- /exercises/practice/protein-translation/ProteinTranslation.roc: -------------------------------------------------------------------------------- 1 | module [to_protein] 2 | 3 | AminoAcid : [Cysteine, Leucine, Methionine, Phenylalanine, Serine, Tryptophan, Tyrosine] 4 | Protein : List AminoAcid 5 | 6 | to_protein : Str -> Result Protein _ 7 | to_protein = |rna| 8 | crash("Please implement the 'to_protein' function") 9 | -------------------------------------------------------------------------------- /exercises/practice/proverb/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [recite] 2 | 3 | recite : List Str -> Str 4 | recite = |strings| 5 | when strings is 6 | [] -> "" 7 | [firtst_thing, .. as rest] -> 8 | rest 9 | |> List.walk( 10 | (firtst_thing, []), 11 | |(thing1, lines), thing2| 12 | (thing2, lines |> List.append("For want of a ${thing1} the ${thing2} was lost.")), 13 | ) 14 | |> .1 15 | |> List.append("And all for the want of a ${firtst_thing}.") 16 | |> Str.join_with("\n") 17 | -------------------------------------------------------------------------------- /exercises/practice/proverb/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Proverb.roc" 8 | ], 9 | "test": [ 10 | "proverb-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "For want of a horseshoe nail, a kingdom was lost, or so the saying goes. Output the full text of this proverbial rhyme.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/For_Want_of_a_Nail" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/proverb/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["strings"] | to_roc }} 11 | expected = {{ case["expected"] | to_roc_multiline_string | indent(8) }} 12 | result == expected 13 | 14 | {% endfor %} 15 | 16 | -------------------------------------------------------------------------------- /exercises/practice/proverb/Proverb.roc: -------------------------------------------------------------------------------- 1 | module [recite] 2 | 3 | recite : List Str -> Str 4 | recite = |strings| 5 | crash("Please implement the 'recite' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/pythagorean-triplet/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | A Pythagorean triplet is a set of three natural numbers, {a, b, c}, for which, 4 | 5 | ```text 6 | a² + b² = c² 7 | ``` 8 | 9 | and such that, 10 | 11 | ```text 12 | a < b < c 13 | ``` 14 | 15 | For example, 16 | 17 | ```text 18 | 3² + 4² = 5². 19 | ``` 20 | 21 | Given an input integer N, find all Pythagorean triplets for which `a + b + c = N`. 22 | 23 | For example, with N = 1000, there is exactly one Pythagorean triplet for which `a + b + c = 1000`: `{200, 375, 425}`. 24 | -------------------------------------------------------------------------------- /exercises/practice/pythagorean-triplet/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "PythagoreanTriplet.roc" 8 | ], 9 | "test": [ 10 | "pythagorean-triplet-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given an integer N, find all Pythagorean triplets for which a + b + c = N.", 17 | "source": "A variation of Problem 9 from Project Euler", 18 | "source_url": "https://projecteuler.net/problem=9" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/pythagorean-triplet/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["n"] }} 11 | expected = Set.fromList [{%- for triplet in case["expected"] %} 12 | ({{ triplet[0] }}, {{ triplet[1] }}, {{ triplet[2] }}), 13 | {%- endfor %}] 14 | result == expected 15 | 16 | {% endfor %} 17 | -------------------------------------------------------------------------------- /exercises/practice/pythagorean-triplet/PythagoreanTriplet.roc: -------------------------------------------------------------------------------- 1 | module [triplets_with_sum] 2 | 3 | Triplet : (U64, U64, U64) 4 | 5 | triplets_with_sum : U64 -> Set Triplet 6 | triplets_with_sum = |sum| 7 | crash("Please implement the 'triplets_with_sum' function") 8 | -------------------------------------------------------------------------------- /exercises/practice/queen-attack/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "QueenAttack.roc" 8 | ], 9 | "test": [ 10 | "queen-attack-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given the position of two queens on a chess board, indicate whether or not they are positioned so that they can attack each other.", 17 | "source": "J Dalbey's Programming Practice problems", 18 | "source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/queen-attack/.meta/plugins.py: -------------------------------------------------------------------------------- 1 | def to_square(queen): 2 | rank = to_rank(queen["position"]["row"]) 3 | file = to_file(queen["position"]["column"]) 4 | return f"{file}{rank}" 5 | 6 | 7 | def to_rank(row): 8 | return 8 - row 9 | 10 | 11 | def to_file(column): 12 | return chr(column + ord("A")) 13 | -------------------------------------------------------------------------------- /exercises/practice/queen-attack/QueenAttack.roc: -------------------------------------------------------------------------------- 1 | module [create, rank, file, queen_can_attack] 2 | 3 | Square := { row : U8, column : U8 } 4 | 5 | rank : Square -> U8 6 | rank = |@Square({ row, column })| 7 | crash("Please implement the 'rank' function") 8 | 9 | file : Square -> U8 10 | file = |@Square({ row, column })| 11 | crash("Please implement the 'file' function") 12 | 13 | create : Str -> Result Square _ 14 | create = |square_str| 15 | crash("Please implement the 'create' function") 16 | 17 | queen_can_attack : Square, Square -> Bool 18 | queen_can_attack = |square1, square2| 19 | crash("Please implement the 'queen_can_attack' function") 20 | -------------------------------------------------------------------------------- /exercises/practice/rail-fence-cipher/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "RailFenceCipher.roc" 8 | ], 9 | "test": [ 10 | "rail-fence-cipher-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement encoding and decoding for the rail fence cipher.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Transposition_cipher#Rail_Fence_cipher" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/rail-fence-cipher/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [encode, decode] 6 | 7 | {% for supercase in cases %} 8 | ## 9 | ## {{ supercase["description"] }} 10 | ## 11 | 12 | {% for case in supercase["cases"] -%} 13 | # {{ case["description"] }} 14 | expect 15 | message = {{ case["input"]["msg"] | to_roc }} 16 | result = message |> {{ case["property"] | to_snake }} {{ case["input"]["rails"] | to_roc }} 17 | expected = Ok {{ case["expected"] | to_roc }} 18 | result == expected 19 | 20 | {% endfor %} 21 | {% endfor %} 22 | -------------------------------------------------------------------------------- /exercises/practice/rail-fence-cipher/RailFenceCipher.roc: -------------------------------------------------------------------------------- 1 | module [encode, decode] 2 | 3 | encode : Str, U64 -> Result Str _ 4 | encode = |message, rails| 5 | crash("Please implement the 'encode' function") 6 | 7 | decode : Str, U64 -> Result Str _ 8 | decode = |encrypted, rails| 9 | crash("Please implement the 'decode' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Raindrops is a slightly more complex version of the FizzBuzz challenge, a classic interview question. 4 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [convert] 2 | 3 | convert : U64 -> Str 4 | convert = |number| 5 | pling = if number % 3 == 0 then "Pling" else "" 6 | plang = if number % 5 == 0 then "Plang" else "" 7 | plong = if number % 7 == 0 then "Plong" else "" 8 | result = "${pling}${plang}${plong}" 9 | if result == "" then 10 | Num.to_str(number) 11 | else 12 | result 13 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Raindrops.roc" 8 | ], 9 | "test": [ 10 | "raindrops-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert a number into its corresponding raindrop sounds - Pling, Plang and Plong.", 17 | "source": "A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division.", 18 | "source_url": "https://en.wikipedia.org/wiki/Fizz_buzz" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [convert] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/Raindrops.roc: -------------------------------------------------------------------------------- 1 | module [convert] 2 | 3 | convert : U64 -> Str 4 | convert = |number| 5 | crash("Please implement the 'convert' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/rational-numbers/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "RationalNumbers.roc" 8 | ], 9 | "test": [ 10 | "rational-numbers-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement rational numbers.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Rational_number" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/rational-numbers/.meta/plugins.py: -------------------------------------------------------------------------------- 1 | def to_roc_rational(r): 2 | return f"Rational {r[0]} {r[1]}" 3 | -------------------------------------------------------------------------------- /exercises/practice/rectangles/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Rectangles.roc" 8 | ], 9 | "test": [ 10 | "rectangles-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Count the rectangles in an ASCII diagram." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/rectangles/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["strings"] | to_roc_multiline_string | indent(8) }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | 15 | -------------------------------------------------------------------------------- /exercises/practice/rectangles/Rectangles.roc: -------------------------------------------------------------------------------- 1 | module [rectangles] 2 | 3 | rectangles : Str -> U64 4 | rectangles = |diagram| 5 | crash("Please implement the 'rectangles' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color-duo/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [value] 2 | 3 | Color : [ 4 | Black, 5 | Brown, 6 | Red, 7 | Orange, 8 | Yellow, 9 | Green, 10 | Blue, 11 | Violet, 12 | Grey, 13 | White, 14 | ] 15 | 16 | value : Color, Color -> U8 17 | value = |first, second| 18 | 10 * get_code(first) + get_code(second) 19 | 20 | get_code : Color -> U8 21 | get_code = |color| 22 | when color is 23 | Black -> 0 24 | Brown -> 1 25 | Red -> 2 26 | Orange -> 3 27 | Yellow -> 4 28 | Green -> 5 29 | Blue -> 6 30 | Violet -> 7 31 | Grey -> 8 32 | White -> 9 33 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color-duo/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ResistorColorDuo.roc" 8 | ], 9 | "test": [ 10 | "resistor-color-duo-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert color codes, as used on resistors, to a numeric value.", 17 | "source": "Maud de Vries, Erik Schierboom", 18 | "source_url": "https://github.com/exercism/problem-specifications/issues/1464" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color-duo/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [value] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["colors"][0] | to_pascal }} {{ case["input"]["colors"][1] | to_pascal }} 11 | result == {{ case["expected"] }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color-duo/ResistorColorDuo.roc: -------------------------------------------------------------------------------- 1 | module [value] 2 | 3 | Color : [ 4 | Black, 5 | Brown, 6 | Red, 7 | Orange, 8 | Yellow, 9 | Green, 10 | Blue, 11 | Violet, 12 | Grey, 13 | White, 14 | ] 15 | 16 | value : Color, Color -> U8 17 | value = |first, second| 18 | crash("Please implement the 'value' function") 19 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ResistorColor.roc" 8 | ], 9 | "test": [ 10 | "resistor-color-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert a resistor band's color to its numeric representation.", 17 | "source": "Maud de Vries, Erik Schierboom", 18 | "source_url": "https://github.com/exercism/problem-specifications/issues/1458" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color/ResistorColor.roc: -------------------------------------------------------------------------------- 1 | module [color_code, colors] 2 | 3 | color_code : Str -> Result U64 _ 4 | color_code = |color| 5 | crash("Please implement the 'color_code' function") 6 | 7 | colors : List Str 8 | colors = 9 | crash("Please implement the 'colors' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/rest-api/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "RestApi.roc" 8 | ], 9 | "test": [ 10 | "rest-api-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement a RESTful API for tracking IOUs." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/rest-api/RestApi.roc: -------------------------------------------------------------------------------- 1 | module [get, post] 2 | 3 | import json.Json 4 | 5 | User : { 6 | name : Str, 7 | owes : Dict Str F64, 8 | owed_by : Dict Str F64, 9 | balance : F64, 10 | } 11 | 12 | Database : { users : List User } 13 | 14 | get : Database, { url : Str, payload ?? Str } -> Result Str _ 15 | get = |database, { url, payload ?? "" }| 16 | crash("Please implement the 'get' function") 17 | 18 | post : Database, { url : Str, payload ?? Str } -> Result Str _ 19 | post = |database, { url, payload ?? "" }| 20 | crash("Please implement the 'post' function") 21 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to reverse a given string. 4 | 5 | Some examples: 6 | 7 | - Turn `"stressed"` into `"desserts"`. 8 | - Turn `"strops"` into `"sports"`. 9 | - Turn `"racecar"` into `"racecar"`. 10 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Reversing strings (reading them from right to left, rather than from left to right) is a surprisingly common task in programming. 4 | 5 | For example, in bioinformatics, reversing the sequence of DNA or RNA strings is often important for various analyses, such as finding complementary strands or identifying palindromic sequences that have biological significance. 6 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ReverseString.roc" 8 | ], 9 | "test": [ 10 | "reverse-string-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Reverse a given string.", 17 | "source": "Introductory challenge to reverse an input string", 18 | "source_url": "https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header(imports=["unicode"]) }} 4 | 5 | import {{ exercise | to_pascal }} exposing [reverse] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["value"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/ReverseString.roc: -------------------------------------------------------------------------------- 1 | module [reverse] 2 | 3 | reverse : Str -> Str 4 | reverse = |string| 5 | crash("Please implement the `reverse` function") 6 | 7 | # HINT: we have added the `unicode` package to the app's header in 8 | # reverse-string-test.roc, so you can use it here if you need to. 9 | # For example, you could use unicode.Grapheme, just sayin'. 10 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You work for a bioengineering company that specializes in developing therapeutic solutions. 4 | 5 | Your team has just been given a new project to develop a targeted therapy for a rare type of cancer. 6 | 7 | ~~~~exercism/note 8 | It's all very complicated, but the basic idea is that sometimes people's bodies produce too much of a given protein. 9 | That can cause all sorts of havoc. 10 | 11 | But if you can create a very specific molecule (called a micro-RNA), it can prevent the protein from being produced. 12 | 13 | This technique is called [RNA Interference][rnai]. 14 | 15 | [rnai]: https://admin.acceleratingscience.com/ask-a-scientist/what-is-rnai/ 16 | ~~~~ 17 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [to_rna] 2 | 3 | complement = |nucleotide| 4 | when nucleotide is 5 | 'G' -> 'C' 6 | 'C' -> 'G' 7 | 'T' -> 'A' 8 | 'A' -> 'U' 9 | c -> c # invalid nucleotides are ignored 10 | 11 | to_rna : Str -> Str 12 | to_rna = |dna| 13 | maybe_rna = 14 | dna 15 | |> Str.to_utf8 16 | |> List.map(complement) 17 | |> Str.from_utf8 18 | 19 | when maybe_rna is 20 | Ok(rna) -> rna 21 | Err(_) -> crash("Unreachable code: toUt8 -> fromUtf8 will always be Ok") 22 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "RnaTranscription.roc" 8 | ], 9 | "test": [ 10 | "rna-transcription-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a DNA strand, return its RNA complement.", 17 | "source": "Hyperphysics", 18 | "source_url": "https://web.archive.org/web/20220408112140/http://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [to_rna] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["dna"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/RnaTranscription.roc: -------------------------------------------------------------------------------- 1 | module [to_rna] 2 | 3 | to_rna : Str -> Str 4 | to_rna = |dna| 5 | crash("Please implement the 'to_rna' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/robot-simulator/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "RobotSimulator.roc" 8 | ], 9 | "test": [ 10 | "robot-simulator-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Write a robot simulator.", 17 | "source": "Inspired by an interview question at a famous company." 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/robot-simulator/.meta/plugins.py: -------------------------------------------------------------------------------- 1 | def to_robot(robot, with_defaults): 2 | x = robot["position"]["x"] 3 | y = robot["position"]["y"] 4 | direction = robot["direction"] 5 | fields = [] 6 | if x != 0 or not with_defaults: 7 | fields.append(f"x : {x}") 8 | if y != 0 or not with_defaults: 9 | fields.append(f"y : {y}") 10 | if direction != "north" or not with_defaults: 11 | fields.append(f"direction : {direction.capitalize()}") 12 | content = ", ".join(fields) 13 | return f"{{{content}}}" 14 | -------------------------------------------------------------------------------- /exercises/practice/robot-simulator/RobotSimulator.roc: -------------------------------------------------------------------------------- 1 | module [create, move] 2 | 3 | Direction : [North, East, South, West] 4 | Robot : { x : I64, y : I64, direction : Direction } 5 | 6 | create : { x ?? I64, y ?? I64, direction ?? Direction } -> Robot 7 | create = |{ x ?? 0, y ?? 0, direction ?? North }| 8 | crash("Please implement the 'create' function") 9 | 10 | move : Robot, Str -> Robot 11 | move = |robot, instructions| 12 | crash("Please implement the 'move' function") 13 | -------------------------------------------------------------------------------- /exercises/practice/roman-numerals/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Your task is to convert a number from Arabic numerals to Roman numerals. 4 | 5 | For this exercise, we are only concerned about traditional Roman numerals, in which the largest number is MMMCMXCIX (or 3,999). 6 | 7 | ~~~~exercism/note 8 | There are lots of different ways to convert between Arabic and Roman numerals. 9 | We recommend taking a naive approach first to familiarise yourself with the concept of Roman numerals and then search for more efficient methods. 10 | 11 | Make sure to check out our Deep Dive video at the end to explore the different approaches you can take! 12 | ~~~~ 13 | -------------------------------------------------------------------------------- /exercises/practice/roman-numerals/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "RomanNumerals.roc" 8 | ], 9 | "test": [ 10 | "roman-numerals-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Convert modern Arabic numbers into Roman numerals.", 17 | "source": "The Roman Numeral Kata", 18 | "source_url": "https://codingdojo.org/kata/RomanNumerals/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/roman-numerals/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] | to_roc }} 11 | result == Ok {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/roman-numerals/RomanNumerals.roc: -------------------------------------------------------------------------------- 1 | module [roman] 2 | 3 | roman : U64 -> Result Str _ 4 | roman = |number| 5 | crash("Please implement the 'roman' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/rotational-cipher/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [rotate] 2 | 3 | shift_char = |c, shift_key| 4 | if c >= 'a' and c <= 'z' then 5 | (c - 'a' + shift_key) % 26 + 'a' 6 | else if c >= 'A' and c <= 'Z' then 7 | (c - 'A' + shift_key) % 26 + 'A' 8 | else 9 | c 10 | 11 | rotate : Str, U8 -> Str 12 | rotate = |text, shift_key| 13 | text 14 | |> Str.to_utf8 15 | |> List.map(|c| shift_char(c, shift_key)) 16 | |> Str.from_utf8 17 | |> Result.with_default("Unreachable") 18 | -------------------------------------------------------------------------------- /exercises/practice/rotational-cipher/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "RotationalCipher.roc" 8 | ], 9 | "test": [ 10 | "rotational-cipher-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Create an implementation of the rotational cipher, also sometimes called the Caesar cipher.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Caesar_cipher" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/rotational-cipher/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [rotate] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["text"] | to_roc }} {{ case["input"]["shiftKey"] }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/rotational-cipher/RotationalCipher.roc: -------------------------------------------------------------------------------- 1 | module [rotate] 2 | 3 | rotate : Str, U8 -> Str 4 | rotate = |text, shift_key| 5 | crash("Please implement the 'rotate' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/run-length-encoding/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "RunLengthEncoding.roc" 8 | ], 9 | "test": [ 10 | "run-length-encoding-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement run-length encoding and decoding.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Run-length_encoding" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/run-length-encoding/RunLengthEncoding.roc: -------------------------------------------------------------------------------- 1 | module [encode, decode] 2 | 3 | encode : Str -> Result Str _ 4 | encode = |string| 5 | crash("Please implement the 'encode' function") 6 | 7 | decode : Str -> Result Str _ 8 | decode = |string| 9 | crash("Please implement the 'decode' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/saddle-points/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You plan to build a tree house in the woods near your house so that you can watch the sun rise and set. 4 | 5 | You've obtained data from a local survey company that show the height of every tree in each rectangular section of the map. 6 | You need to analyze each grid on the map to find good trees for your tree house. 7 | 8 | A good tree is both: 9 | 10 | - taller than every tree to the east and west, so that you have the best possible view of the sunrises and sunsets. 11 | - shorter than every tree to the north and south, to minimize the amount of tree climbing. 12 | -------------------------------------------------------------------------------- /exercises/practice/saddle-points/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "SaddlePoints.roc" 8 | ], 9 | "test": [ 10 | "saddle-points-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Detect saddle points in a matrix.", 17 | "source": "J Dalbey's Programming Practice problems", 18 | "source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/saddle-points/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | treeHeights = [ 11 | {%- for row in case["input"]["matrix"] %} 12 | {{ row | to_roc }}, 13 | {%- endfor %} 14 | ] 15 | result = treeHeights |> {{ case["property"] | to_snake }} 16 | expected = Set.fromList [ 17 | {%- for tree in case["expected"] %} 18 | {{ tree | to_roc }}, 19 | {%- endfor %} 20 | ] 21 | result == expected 22 | 23 | {% endfor %} 24 | -------------------------------------------------------------------------------- /exercises/practice/saddle-points/SaddlePoints.roc: -------------------------------------------------------------------------------- 1 | module [saddle_points] 2 | 3 | Forest : List (List U8) 4 | Position : { row : U64, column : U64 } 5 | 6 | saddle_points : Forest -> Set Position 7 | saddle_points = |tree_heights| 8 | crash("Please implement the 'saddle_points' function") 9 | -------------------------------------------------------------------------------- /exercises/practice/say/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Say.roc" 8 | ], 9 | "test": [ 10 | "say-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a number from 0 to 999,999,999,999, spell out that number in English.", 17 | "source": "A variation on the JavaRanch CattleDrive, Assignment 4", 18 | "source_url": "https://web.archive.org/web/20240907035912/https://coderanch.com/wiki/718804" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/say/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] | to_roc }} 11 | {%- if case["expected"]["error"] %} 12 | result |> Result.isErr 13 | {%- else %} 14 | result == Ok {{ case["expected"] | to_roc }} 15 | {% endif %} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/say/Say.roc: -------------------------------------------------------------------------------- 1 | module [say] 2 | 3 | say : U64 -> Result Str [OutOfBounds] 4 | say = |number| 5 | crash("Please implement the 'say' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/scrabble-score/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | [Scrabble][wikipedia] is a word game where players place letter tiles on a board to form words. 4 | Each letter has a value. 5 | A word's score is the sum of its letters' values. 6 | 7 | [wikipedia]: https://en.wikipedia.org/wiki/Scrabble 8 | -------------------------------------------------------------------------------- /exercises/practice/scrabble-score/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ScrabbleScore.roc" 8 | ], 9 | "test": [ 10 | "scrabble-score-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a word, compute the Scrabble score for that word.", 17 | "source": "Inspired by the Extreme Startup game", 18 | "source_url": "https://github.com/rchatley/extreme_startup" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/scrabble-score/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["word"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | 15 | -------------------------------------------------------------------------------- /exercises/practice/scrabble-score/ScrabbleScore.roc: -------------------------------------------------------------------------------- 1 | module [score] 2 | 3 | score : Str -> U64 4 | score = |word| 5 | crash("Please implement the 'score' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/secret-handshake/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You are starting a secret coding club with some friends and friends-of-friends. 4 | Not everyone knows each other, so you and your friends have decided to create a secret handshake that you can use to recognize that someone is a member. 5 | You don't want anyone who isn't in the know to be able to crack the code. 6 | 7 | You've designed the code so that one person says a number between 1 and 31, and the other person turns it into a series of actions. 8 | -------------------------------------------------------------------------------- /exercises/practice/secret-handshake/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [commands] 2 | 3 | commands : U64 -> List Str 4 | commands = |number| 5 | actions = 6 | [(1, "wink"), (2, "double blink"), (4, "close your eyes"), (8, "jump")] 7 | |> List.join_map( 8 | |(mask, action)| 9 | if Num.bitwise_and(number, mask) == 0 then [] else [action], 10 | ) 11 | 12 | if Num.bitwise_and(number, 16) == 0 then 13 | actions 14 | else 15 | List.reverse(actions) 16 | -------------------------------------------------------------------------------- /exercises/practice/secret-handshake/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "SecretHandshake.roc" 8 | ], 9 | "test": [ 10 | "secret-handshake-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.", 17 | "source": "Bert, in Mary Poppins", 18 | "source_url": "https://www.imdb.com/title/tt0058331/quotes/?item=qt0437047" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/secret-handshake/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["number"] }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/secret-handshake/SecretHandshake.roc: -------------------------------------------------------------------------------- 1 | module [commands] 2 | 3 | commands : U64 -> List Str 4 | commands = |number| 5 | crash("Please implement the 'commands' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/series/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Given a string of digits, output all the contiguous substrings of length `n` in that string in the order that they appear. 4 | 5 | For example, the string "49142" has the following 3-digit series: 6 | 7 | - "491" 8 | - "914" 9 | - "142" 10 | 11 | And the following 4-digit series: 12 | 13 | - "4914" 14 | - "9142" 15 | 16 | And if you ask for a 6-digit series from a 5-digit string, you deserve whatever you get. 17 | 18 | Note that these series are only required to occupy _adjacent positions_ in the input; 19 | the digits need not be _numerically consecutive_. 20 | -------------------------------------------------------------------------------- /exercises/practice/series/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Series.roc" 8 | ], 9 | "test": [ 10 | "series-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a string of digits, output all the contiguous substrings of length `n` in that string.", 17 | "source": "A subset of the Problem 8 at Project Euler", 18 | "source_url": "https://projecteuler.net/problem=8" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/series/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | {%- if case["expected"]["error"] %} – just return an empty list{%- endif %} 10 | expect 11 | result = {{ case["input"]["series"] | to_roc }} |> {{ case["property"] | to_snake }} {{ case["input"]["sliceLength"] | to_roc }} 12 | {%- if case["expected"]["error"] %} 13 | result == [] 14 | {%- else %} 15 | result == {{ case["expected"] | to_roc }} 16 | {%- endif %} 17 | 18 | {% endfor %} 19 | -------------------------------------------------------------------------------- /exercises/practice/series/Series.roc: -------------------------------------------------------------------------------- 1 | module [slices] 2 | 3 | slices : Str, U64 -> List Str 4 | slices = |string, slice_length| 5 | crash("Please implement the 'slices' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/sgf-parsing/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "SgfParsing.roc" 8 | ], 9 | "test": [ 10 | "sgf-parsing-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Parsing a Smart Game Format string." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/sieve/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You bought a big box of random computer parts at a garage sale. 4 | You've started putting the parts together to build custom computers. 5 | 6 | You want to test the performance of different combinations of parts, and decide to create your own benchmarking program to see how your computers compare. 7 | You choose the famous "Sieve of Eratosthenes" algorithm, an ancient algorithm, but one that should push your computers to the limits. 8 | -------------------------------------------------------------------------------- /exercises/practice/sieve/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Sieve.roc" 8 | ], 9 | "test": [ 10 | "sieve-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Use the Sieve of Eratosthenes to find all the primes from 2 up to a given number.", 17 | "source": "Sieve of Eratosthenes at Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/sieve/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["limit"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/sieve/Sieve.roc: -------------------------------------------------------------------------------- 1 | module [primes] 2 | 3 | primes : U64 -> List U64 4 | primes = |limit| 5 | crash("Please implement the 'primes' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/simple-linked-list/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You work for a music streaming company. 4 | 5 | You've been tasked with creating a playlist feature for your music player application. 6 | -------------------------------------------------------------------------------- /exercises/practice/simple-linked-list/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "SimpleLinkedList.roc" 8 | ], 9 | "test": [ 10 | "simple-linked-list-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Write a simple linked list implementation that uses Elements and a List.", 17 | "source": "Inspired by 'Data Structures and Algorithms with Object-Oriented Design Patterns in Ruby', singly linked-lists.", 18 | "source_url": "https://web.archive.org/web/20160731005714/http://brpreiss.com/books/opus8/html/page96.html" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/space-age/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "SpaceAge.roc" 8 | ], 9 | "test": [ 10 | "space-age-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given an age in seconds, calculate how old someone is in terms of a given planet's solar years.", 17 | "source": "Partially inspired by Chapter 1 in Chris Pine's online Learn to Program tutorial.", 18 | "source_url": "https://pine.fm/LearnToProgram/?Chapter=01" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/space-age/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["planet"] | to_pascal }} {{ case["input"]["seconds"] }} 11 | Num.isApproxEq result {{ case["expected"] }} { atol: 0.01 } 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/space-age/SpaceAge.roc: -------------------------------------------------------------------------------- 1 | module [age] 2 | 3 | Planet : [ 4 | Mercury, 5 | Venus, 6 | Earth, 7 | Mars, 8 | Jupiter, 9 | Saturn, 10 | Uranus, 11 | Neptune, 12 | ] 13 | 14 | age : Planet, Dec -> Dec 15 | age = |planet, seconds| 16 | crash("Please implement the 'age' function") 17 | -------------------------------------------------------------------------------- /exercises/practice/spiral-matrix/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to return a square matrix of a given size. 4 | 5 | The matrix should be filled with natural numbers, starting from 1 in the top-left corner, increasing in an inward, clockwise spiral order, like these examples: 6 | 7 | ## Examples 8 | 9 | ### Spiral matrix of size 3 10 | 11 | ```text 12 | 1 2 3 13 | 8 9 4 14 | 7 6 5 15 | ``` 16 | 17 | ### Spiral matrix of size 4 18 | 19 | ```text 20 | 1 2 3 4 21 | 12 13 14 5 22 | 11 16 15 6 23 | 10 9 8 7 24 | ``` 25 | -------------------------------------------------------------------------------- /exercises/practice/spiral-matrix/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "SpiralMatrix.roc" 8 | ], 9 | "test": [ 10 | "spiral-matrix-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given the size, return a square matrix of numbers in spiral order.", 17 | "source": "Reddit r/dailyprogrammer challenge #320 [Easy] Spiral Ascension.", 18 | "source_url": "https://web.archive.org/web/20230607064729/https://old.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/spiral-matrix/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["size"] }} 11 | {%- if case["expected"] == [] %} 12 | result == [] 13 | {%- else %} 14 | expected = [ 15 | {%- for row in case["expected"] %} 16 | {{ row | to_roc }}, 17 | {%- endfor %} 18 | ] 19 | result == expected 20 | {%- endif %} 21 | 22 | {% endfor %} 23 | -------------------------------------------------------------------------------- /exercises/practice/spiral-matrix/SpiralMatrix.roc: -------------------------------------------------------------------------------- 1 | module [spiral_matrix] 2 | 3 | spiral_matrix : U64 -> List (List U64) 4 | spiral_matrix = |size| 5 | crash("Please implement the 'spiral_matrix' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/square-root/.docs/instructions.append.md: -------------------------------------------------------------------------------- 1 | # Instructions append 2 | 3 | This problem can be solved easily using Roc's built-in `Num` module, including the [`Num.sqrt`][sqrt] function. 4 | 5 | However, we'd like you to consider the challenge of solving this exercise without using built-ins or modules. 6 | 7 | While there is a mathematical formula that will find the square root of _any_ number, we have gone the route of having only [natural numbers][natural-number] (positive integers) as solutions. 8 | 9 | [sqrt]: https://www.roc-lang.org/builtins/Num#sqrt 10 | [natural-number]: https://en.wikipedia.org/wiki/Natural_number -------------------------------------------------------------------------------- /exercises/practice/square-root/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | We are launching a deep space exploration rocket and we need a way to make sure the navigation system stays on target. 4 | 5 | As the first step in our calculation, we take a target number and find its square root (that is, the number that when multiplied by itself equals the target number). 6 | 7 | The journey will be very long. 8 | To make the batteries last as long as possible, we had to make our rocket's onboard computer very power efficient. 9 | Unfortunately that means that we can't rely on fancy math libraries and functions, as they use more power. 10 | Instead we want to implement our own square root calculation. 11 | -------------------------------------------------------------------------------- /exercises/practice/square-root/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [square_root, square_rootTheSimpleWay] 2 | 3 | square_root : U64 -> U64 4 | square_root = |radicand| 5 | binary_search = |min, max| 6 | val = (min + max) // 2 7 | square = val * val 8 | if square == radicand or min >= max then 9 | val 10 | else if square > radicand then 11 | binary_search(min, (val - 1)) 12 | else 13 | binary_search((val + 1), max) 14 | 15 | binary_search(0, radicand) 16 | 17 | square_rootTheSimpleWay = |radicand| 18 | # This works too... but it's cheating, right? 19 | radicand |> Num.to_f64 |> Num.sqrt |> Num.round 20 | -------------------------------------------------------------------------------- /exercises/practice/square-root/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "SquareRoot.roc" 8 | ], 9 | "test": [ 10 | "square-root-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a natural radicand, return its square root.", 17 | "source": "wolf99", 18 | "source_url": "https://github.com/exercism/problem-specifications/pull/1582" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/square-root/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["radicand"] | to_roc }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/square-root/SquareRoot.roc: -------------------------------------------------------------------------------- 1 | module [square_root] 2 | 3 | square_root : U64 -> U64 4 | square_root = |radicand| 5 | crash("Please implement the 'square_root' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/strain/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Strain.roc" 8 | ], 9 | "test": [ 10 | "strain-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement the `keep` and `discard` operation on collections.", 17 | "source": "Conversation with James Edward Gray II", 18 | "source_url": "http://graysoftinc.com/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/strain/Strain.roc: -------------------------------------------------------------------------------- 1 | module [keep, discard] 2 | 3 | keep : List a, (a -> Bool) -> List a 4 | keep = |list, predicate| 5 | crash("Please implement the 'keep' function") 6 | 7 | discard : List a, (a -> Bool) -> List a 8 | discard = |list, predicate| 9 | crash("Please implement the 'discard' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/sublist/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Sublist.roc" 8 | ], 9 | "test": [ 10 | "sublist-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Write a function to determine if a list is a sublist of another list." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/sublist/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["input"]["listOne"] | to_roc }} |> {{ case["property"] | to_snake }} {{ case["input"]["listTwo"] | to_roc }} 11 | result == {{ case["expected"] | to_pascal }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/sublist/Sublist.roc: -------------------------------------------------------------------------------- 1 | module [sublist] 2 | 3 | sublist : List U8, List U8 -> [Equal, Sublist, Superlist, Unequal] 4 | sublist = |list1, list2| 5 | crash("Please implement the 'sublist' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/sum-of-multiples/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You work for a company that makes an online, fantasy-survival game. 4 | 5 | When a player finishes a level, they are awarded energy points. 6 | The amount of energy awarded depends on which magical items the player found while exploring that level. 7 | -------------------------------------------------------------------------------- /exercises/practice/sum-of-multiples/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [sum_of_multiples] 2 | 3 | sum_of_multiples : List U64, U64 -> U64 4 | sum_of_multiples = |factors, limit| 5 | factors 6 | |> List.keep_if(|factor| factor > 0) 7 | |> List.join_map( 8 | |factor| 9 | List.range({ start: At(factor), end: Before(limit), step: factor }), 10 | ) 11 | |> Set.from_list 12 | |> Set.to_list 13 | |> List.sum 14 | -------------------------------------------------------------------------------- /exercises/practice/sum-of-multiples/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "SumOfMultiples.roc" 8 | ], 9 | "test": [ 10 | "sum-of-multiples-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a number, find the sum of all the multiples of particular numbers up to but not including that number.", 17 | "source": "A variation on Problem 1 at Project Euler", 18 | "source_url": "https://projecteuler.net/problem=1" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/sum-of-multiples/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ exercise | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["input"]["factors"] | to_roc }} |> {{ exercise | to_snake }} {{ case["input"]["limit"] }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/sum-of-multiples/SumOfMultiples.roc: -------------------------------------------------------------------------------- 1 | module [sum_of_multiples] 2 | 3 | sum_of_multiples : List U64, U64 -> U64 4 | sum_of_multiples = |factors, limit| 5 | crash("Please implement the 'sum_of_multiples' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/tournament/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Tournament.roc" 8 | ], 9 | "test": [ 10 | "tournament-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Tally the results of a small football competition." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/tournament/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | table = {{ case["input"]["rows"] | to_roc_multiline_string | indent(8) }} 11 | result = {{ case["property"] | to_snake }} table 12 | expected = Ok {{ case["expected"] | to_roc_multiline_string | indent(8) }} 13 | result == expected 14 | 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /exercises/practice/tournament/Tournament.roc: -------------------------------------------------------------------------------- 1 | module [tally] 2 | 3 | tally : Str -> Result Str _ 4 | tally = |table| 5 | crash("Please implement the 'tally' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/transpose/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Transpose.roc" 8 | ], 9 | "test": [ 10 | "transpose-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Take input text and output it transposed.", 17 | "source": "Reddit r/dailyprogrammer challenge #270 [Easy].", 18 | "source_url": "https://web.archive.org/web/20230630051421/https://old.reddit.com/r/dailyprogrammer/comments/4msu2x/challenge_270_easy_transpose_the_input_text/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/transpose/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | input = {{ case["input"]["lines"] | to_roc_multiline_string | replace(" ", "□") | indent(8) }} |> Str.replaceEach "□" " " 11 | result = {{ case["property"] | to_snake }} input |> Str.replaceEach " " "□" 12 | expected = {{ case["expected"] | to_roc_multiline_string | replace(" ", "□") | indent(8) }} 13 | result == expected 14 | 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /exercises/practice/transpose/Transpose.roc: -------------------------------------------------------------------------------- 1 | module [transpose] 2 | 3 | transpose : Str -> Str 4 | transpose = |string| 5 | crash("Please implement the 'transpose' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/triangle/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Triangle.roc" 8 | ], 9 | "test": [ 10 | "triangle-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Determine if a triangle is equilateral, isosceles, or scalene.", 17 | "source": "The Ruby Koans triangle project, parts 1 & 2", 18 | "source_url": "https://web.archive.org/web/20220831105330/http://rubykoans.com" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/triangle/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [is_equilateral, is_isosceles, is_scalene] 6 | 7 | {% for supercase in cases %} 8 | ## 9 | ## {{ supercase["description"] }} 10 | ## 11 | 12 | {% for case in supercase["cases"] -%} 13 | # {{ case["description"] }} 14 | expect 15 | result = is_{{ case["property"] }} {{ case["input"]["sides"] | to_roc_tuple }} 16 | result == {{ case["expected"] | to_roc }} 17 | 18 | {% endfor %} 19 | {% endfor %} -------------------------------------------------------------------------------- /exercises/practice/triangle/Triangle.roc: -------------------------------------------------------------------------------- 1 | module [is_equilateral, is_isosceles, is_scalene] 2 | 3 | is_equilateral : (F64, F64, F64) -> Bool 4 | is_equilateral = |(a, b, c)| 5 | crash("Please implement the 'is_equilateral' function") 6 | 7 | is_isosceles : (F64, F64, F64) -> Bool 8 | is_isosceles = |(a, b, c)| 9 | crash("Please implement the 'is_isosceles' function") 10 | 11 | is_scalene : (F64, F64, F64) -> Bool 12 | is_scalene = |(a, b, c)| 13 | crash("Please implement the 'is_scalene' function") 14 | -------------------------------------------------------------------------------- /exercises/practice/two-bucket/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "TwoBucket.roc" 8 | ], 9 | "test": [ 10 | "two-bucket-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given two buckets of different size, demonstrate how to measure an exact number of liters.", 17 | "source": "Water Pouring Problem", 18 | "source_url": "https://demonstrations.wolfram.com/WaterPouringProblem/" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/two-bucket/TwoBucket.roc: -------------------------------------------------------------------------------- 1 | module [measure] 2 | 3 | measure : 4 | { bucket_one : U64, bucket_two : U64, goal : U64, start_bucket : [One, Two] } 5 | -> 6 | Result { moves : U64, goal_bucket : [One, Two], other_bucket : U64 } _ 7 | measure = |{ bucket_one, bucket_two, goal, start_bucket }| 8 | crash("Please implement the 'measure' function") 9 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to determine what you will say as you give away the extra cookie. 4 | 5 | If you know the person's name (e.g. if they're named Do-yun), then you will say: 6 | 7 | ```text 8 | One for Do-yun, one for me. 9 | ``` 10 | 11 | If you don't know the person's name, you will say _you_ instead. 12 | 13 | ```text 14 | One for you, one for me. 15 | ``` 16 | 17 | Here are some examples: 18 | 19 | | Name | Dialogue | 20 | | :----- | :-------------------------- | 21 | | Alice | One for Alice, one for me. | 22 | | Bohdan | One for Bohdan, one for me. | 23 | | | One for you, one for me. | 24 | | Zaphod | One for Zaphod, one for me. | 25 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In some English accents, when you say "two for" quickly, it sounds like "two fer". 4 | Two-for-one is a way of saying that if you buy one, you also get one for free. 5 | So the phrase "two-fer" often implies a two-for-one offer. 6 | 7 | Imagine a bakery that has a holiday offer where you can buy two cookies for the price of one ("two-fer one!"). 8 | You take the offer and (very generously) decide to give the extra cookie to someone else in the queue. 9 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/Example.roc: -------------------------------------------------------------------------------- 1 | module [two_fer] 2 | 3 | two_fer : [Name Str, Anonymous] -> Str 4 | two_fer = |name| 5 | when name is 6 | Anonymous -> "One for you, one for me." 7 | Name(n) -> "One for ${n}, one for me." 8 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "TwoFer.roc" 8 | ], 9 | "test": [ 10 | "two-fer-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Create a sentence of the form \"One for X, one for me.\".", 17 | "source_url": "https://github.com/exercism/problem-specifications/issues/757" 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ exercise | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | {%- if case["input"]["name"] == None %} 11 | result = {{ case["property"] | to_snake }} Anonymous 12 | {%- else %} 13 | result = {{ case["property"] | to_snake }} (Name {{ case["input"]["name"] | to_roc }}) 14 | {%- endif %} 15 | result == {{ case["expected"] | to_roc }} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/TwoFer.roc: -------------------------------------------------------------------------------- 1 | module [two_fer] 2 | 3 | two_fer : [Name Str, Anonymous] -> Str 4 | two_fer = |name| 5 | crash("Please implement the 'two_fer' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/variable-length-quantity/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "VariableLengthQuantity.roc" 8 | ], 9 | "test": [ 10 | "variable-length-quantity-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Implement variable length quantity encoding and decoding.", 17 | "source": "A poor Splice developer having to implement MIDI encoding/decoding.", 18 | "source_url": "https://splice.com" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/variable-length-quantity/VariableLengthQuantity.roc: -------------------------------------------------------------------------------- 1 | module [encode, decode] 2 | 3 | encode : List U32 -> List U8 4 | encode = |integers| 5 | crash("Please implement the 'encode' function") 6 | 7 | decode : List U8 -> Result (List U32) _ 8 | decode = |bytes| 9 | crash("Please implement the 'decode' function") 10 | -------------------------------------------------------------------------------- /exercises/practice/word-count/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You teach English as a foreign language to high school students. 4 | 5 | You've decided to base your entire curriculum on TV shows. 6 | You need to analyze which words are used, and how often they're repeated. 7 | 8 | This will let you choose the simplest shows to start with, and to gradually increase the difficulty as time passes. 9 | -------------------------------------------------------------------------------- /exercises/practice/word-count/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "WordCount.roc" 8 | ], 9 | "test": [ 10 | "word-count-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Given a phrase, count the occurrences of each word in that phrase.", 17 | "source": "This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour." 18 | } 19 | -------------------------------------------------------------------------------- /exercises/practice/word-count/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["sentence"] | to_roc }} 11 | expected = Dict.fromList [ 12 | {%- for word, count in case["expected"].items() %} 13 | ({{ word | to_roc }}, {{ count }}), 14 | {%- endfor %} 15 | ] 16 | result == expected 17 | 18 | {% endfor %} 19 | -------------------------------------------------------------------------------- /exercises/practice/word-count/WordCount.roc: -------------------------------------------------------------------------------- 1 | module [count_words] 2 | 3 | count_words : Str -> Dict Str U64 4 | count_words = |sentence| 5 | crash("Please implement the 'count_words' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/word-search/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | In word search puzzles you get a square of letters and have to find specific words in them. 4 | 5 | For example: 6 | 7 | ```text 8 | jefblpepre 9 | camdcimgtc 10 | oivokprjsm 11 | pbwasqroua 12 | rixilelhrs 13 | wolcqlirpc 14 | screeaumgr 15 | alxhpburyi 16 | jalaycalmp 17 | clojurermt 18 | ``` 19 | 20 | There are several programming languages hidden in the above square. 21 | 22 | Words can be hidden in all kinds of directions: left-to-right, right-to-left, vertical and diagonal. 23 | 24 | Given a puzzle and a list of words return the location of the first and last letter of each word. 25 | -------------------------------------------------------------------------------- /exercises/practice/word-search/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "WordSearch.roc" 8 | ], 9 | "test": [ 10 | "word-search-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Create a program to solve a word search puzzle." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/word-search/WordSearch.roc: -------------------------------------------------------------------------------- 1 | module [search] 2 | 3 | Position : { column : U64, row : U64 } 4 | WordLocation : { start : Position, end : Position } 5 | 6 | search : Str, List Str -> Dict Str WordLocation 7 | search = |grid, words_to_search_for| 8 | crash("Please implement the 'search' function") 9 | -------------------------------------------------------------------------------- /exercises/practice/wordy/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Wordy.roc" 8 | ], 9 | "test": [ 10 | "wordy-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Parse and evaluate simple math word problems returning the answer as an integer.", 17 | "source": "Inspired by one of the generated questions in the Extreme Startup game.", 18 | "source_url": "https://github.com/rchatley/extreme_startup" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/wordy/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [answer] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} {{ case["input"]["question"] | to_roc }} 11 | {%- if case["expected"]["error"] %} 12 | Result.isErr result 13 | {%- else %} 14 | result == Ok {{ case["expected"] }} 15 | {%- endif %} 16 | 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /exercises/practice/wordy/Wordy.roc: -------------------------------------------------------------------------------- 1 | module [answer] 2 | 3 | answer : Str -> Result I64 _ 4 | answer = |question| 5 | crash("Please implement the 'answer' function") 6 | -------------------------------------------------------------------------------- /exercises/practice/yacht/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Each year, something new is "all the rage" in your high school. 4 | This year it is a dice game: [Yacht][yacht]. 5 | 6 | The game of Yacht is from the same family as Poker Dice, Generala and particularly Yahtzee, of which it is a precursor. 7 | The game consists of twelve rounds. 8 | In each, five dice are rolled and the player chooses one of twelve categories. 9 | The chosen category is then used to score the throw of the dice. 10 | 11 | [yacht]: https://en.wikipedia.org/wiki/Yacht_(dice_game) 12 | -------------------------------------------------------------------------------- /exercises/practice/yacht/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "Yacht.roc" 8 | ], 9 | "test": [ 10 | "yacht-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Score a single throw of dice in the game Yacht.", 17 | "source": "James Kilfiger, using Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Yacht_(dice_game)" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/yacht/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_snake }}] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["input"]["dice"] | to_roc }} |> {{ case["property"] | to_snake }} {{ case["input"]["category"] | to_pascal }} 11 | result == {{ case["expected"] | to_roc }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/yacht/Yacht.roc: -------------------------------------------------------------------------------- 1 | module [score] 2 | 3 | Category : [Ones, Twos, Threes, Fours, Fives, Sixes, FullHouse, FourOfAKind, LittleStraight, BigStraight, Choice, Yacht] 4 | 5 | score : List U8, Category -> U8 6 | score = |dice, category| 7 | crash("Please implement the 'score' function") 8 | -------------------------------------------------------------------------------- /exercises/practice/zebra-puzzle/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "ageron" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "ZebraPuzzle.roc" 8 | ], 9 | "test": [ 10 | "zebra-puzzle-test.roc" 11 | ], 12 | "example": [ 13 | ".meta/Example.roc" 14 | ] 15 | }, 16 | "blurb": "Solve the zebra puzzle.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Zebra_Puzzle" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/zebra-puzzle/.meta/template.j2: -------------------------------------------------------------------------------- 1 | {%- import "generator_macros.j2" as macros with context -%} 2 | {{ macros.canonical_ref() }} 3 | {{ macros.header() }} 4 | 5 | import {{ exercise | to_pascal }} exposing [owns_zebra, drinks_water] 6 | 7 | {% for case in cases -%} 8 | # {{ case["description"] }} 9 | expect 10 | result = {{ case["property"] | to_snake }} 11 | result == Ok {{ case["expected"] }} 12 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /exercises/practice/zebra-puzzle/ZebraPuzzle.roc: -------------------------------------------------------------------------------- 1 | module [owns_zebra, drinks_water] 2 | 3 | Person : [Englishman, Spaniard, Ukrainian, Norwegian, Japanese] 4 | 5 | owns_zebra : Result Person _ 6 | owns_zebra = 7 | crash("Please implement 'owns_zebra'") 8 | 9 | drinks_water : Result Person _ 10 | drinks_water = 11 | crash("Please implement 'drinks_water'") 12 | -------------------------------------------------------------------------------- /exercises/shared/.docs/help.md: -------------------------------------------------------------------------------- 1 | # Help 2 | 3 | [Roc Zulip Chat](https://roc.zulipchat.com/) is the most active community gathering place. 4 | We love it when new people stop by and introduce themselves in [`#introductions`](https://roc.zulipchat.com/#narrow/stream/387892-introductions) so others can welcome you to the community! 5 | 6 | Feel free to ask us questions, we'd be happy to help. 7 | -------------------------------------------------------------------------------- /exercises/shared/.docs/tests.md: -------------------------------------------------------------------------------- 1 | # Testing on the Command Line 2 | 3 | Roc comes with its own integrated test tools, no need to install anything else. 4 | 5 | To test your solution to an exercise, open a terminal, go to the exercise directory, run `roc test -test.roc`, for example `roc test hello-world-test.roc`, and ensure that all the tests pass. 6 | -------------------------------------------------------------------------------- /requirements-generator.txt: -------------------------------------------------------------------------------- 1 | flake8~=7.1.1 2 | Jinja2~=3.1.4 3 | python-dateutil==2.9.0.post0 4 | tomli>=2.0.0; python_full_version < '3.11.2' 5 | --------------------------------------------------------------------------------