├── .appends └── .github │ └── labels.yml ├── .github ├── CODEOWNERS ├── dependabot.yml ├── labels.yml ├── stale.yml └── workflows │ ├── configlet.yml │ ├── exercises.yml │ ├── generator.yml │ ├── no-important-files-changed.yml │ ├── pause-community-contributions.yml │ └── sync-labels.yml ├── .gitignore ├── .perltidyrc ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── bin ├── README.md ├── exercise-gen.pl └── fetch-configlet ├── concepts ├── arrays-and-lists │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── basics │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── booleans-and-conditionals │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── exceptions │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── hashes │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── numbers │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── object-orientation │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── packages-and-modules │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── references │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── regular-expressions │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── strings │ ├── .meta │ │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json └── subroutines │ ├── .meta │ └── config.json │ ├── about.md │ ├── introduction.md │ └── links.json ├── config.json ├── cpanfile ├── docs ├── ABOUT.md ├── INSTALLATION.md ├── LEARNING.md ├── RESOURCES.md ├── SNIPPET.txt ├── TESTS.md └── config.json ├── exercises ├── concept │ ├── booking-up-for-beauty │ │ ├── .docs │ │ │ ├── hints.md │ │ │ ├── instructions.md │ │ │ ├── introduction.md │ │ │ └── introduction.md.tpl │ │ ├── .meta │ │ │ ├── BookingUpForBeauty.pm │ │ │ └── config.json │ │ ├── lib │ │ │ └── BookingUpForBeauty.pm │ │ └── t │ │ │ └── booking-up-for-beauty.t │ ├── high-score-board │ │ ├── .docs │ │ │ ├── hints.md │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── HighScoreBoard.pm │ │ │ └── config.json │ │ ├── lib │ │ │ └── HighScoreBoard.pm │ │ └── t │ │ │ └── high-score-board.t │ ├── inventory-management │ │ ├── .docs │ │ │ ├── hints.md │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── InventoryManagement.pm │ │ │ └── config.json │ │ ├── lib │ │ │ └── InventoryManagement.pm │ │ └── t │ │ │ └── inventory-management.t │ ├── language-list │ │ ├── .docs │ │ │ ├── hints.md │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── LanguageList.pm │ │ │ └── config.json │ │ ├── lib │ │ │ └── LanguageList.pm │ │ └── t │ │ │ └── language-list.t │ └── lasagna │ │ ├── .docs │ │ ├── hints.md │ │ ├── instructions.md │ │ └── introduction.md │ │ ├── .meta │ │ ├── Lasagna.pm │ │ └── config.json │ │ ├── lib │ │ └── Lasagna.pm │ │ └── t │ │ └── lasagna.t ├── practice │ ├── accumulate │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Accumulate.pm │ │ │ │ └── t │ │ │ │ │ └── accumulate.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Accumulate.pm │ │ └── t │ │ │ └── accumulate.t │ ├── acronym │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Acronym.pm │ │ │ │ └── t │ │ │ │ │ └── acronym.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Acronym.pm │ │ └── t │ │ │ └── acronym.t │ ├── all-your-base │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── AllYourBase.pm │ │ │ │ └── t │ │ │ │ │ └── all-your-base.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── AllYourBase.pm │ │ └── t │ │ │ └── all-your-base.t │ ├── allergies │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Allergies.pm │ │ │ │ └── t │ │ │ │ │ └── allergies.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Allergies.pm │ │ └── t │ │ │ └── allergies.t │ ├── anagram │ │ ├── .docs │ │ │ ├── instructions.append.md │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Anagram.pm │ │ │ │ └── t │ │ │ │ │ └── anagram.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Anagram.pm │ │ └── t │ │ │ └── anagram.t │ ├── armstrong-numbers │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── ArmstrongNumbers.pm │ │ │ │ └── t │ │ │ │ │ └── armstrong-numbers.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── ArmstrongNumbers.pm │ │ └── t │ │ │ └── armstrong-numbers.t │ ├── atbash-cipher │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── AtbashCipher.pm │ │ │ │ └── t │ │ │ │ │ └── atbash-cipher.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── AtbashCipher.pm │ │ └── t │ │ │ └── atbash-cipher.t │ ├── beer-song │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── BeerSong.pm │ │ │ │ └── beer-song.t │ │ │ └── tests.toml │ │ ├── BeerSong.pm │ │ └── beer-song.t │ ├── binary-search-tree │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── BinarySearchTree.pm │ │ │ │ └── t │ │ │ │ │ └── binary-search-tree.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── BinarySearchTree.pm │ │ └── t │ │ │ └── binary-search-tree.t │ ├── binary-search │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── BinarySearch.pm │ │ │ │ └── t │ │ │ │ │ └── binary-search.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── BinarySearch.pm │ │ └── t │ │ │ └── binary-search.t │ ├── binary │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── Binary.pm │ │ │ │ └── binary.t │ │ │ └── tests.toml │ │ ├── Binary.pm │ │ └── binary.t │ ├── bob │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Bob.pm │ │ │ │ └── t │ │ │ │ │ └── bob.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Bob.pm │ │ └── t │ │ │ └── bob.t │ ├── bottle-song │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── BottleSong.pm │ │ │ │ └── t │ │ │ │ │ └── bottle-song.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── BottleSong.pm │ │ └── t │ │ │ └── bottle-song.t │ ├── circular-buffer │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── CircularBuffer.pm │ │ │ │ └── t │ │ │ │ │ └── circular-buffer.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── CircularBuffer.pm │ │ └── t │ │ │ └── circular-buffer.t │ ├── clock │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Clock.pm │ │ │ │ └── t │ │ │ │ │ └── clock.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Clock.pm │ │ └── t │ │ │ └── clock.t │ ├── collatz-conjecture │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── CollatzConjecture.pm │ │ │ │ └── t │ │ │ │ │ └── collatz-conjecture.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── CollatzConjecture.pm │ │ └── t │ │ │ └── collatz-conjecture.t │ ├── crypto-square │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── CryptoSquare.pm │ │ │ │ └── t │ │ │ │ │ └── crypto-square.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── CryptoSquare.pm │ │ └── t │ │ │ └── crypto-square.t │ ├── custom-set │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── CustomSet.pm │ │ │ │ └── t │ │ │ │ │ └── custom-set.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── CustomSet.pm │ │ └── t │ │ │ └── custom-set.t │ ├── darts │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Darts.pm │ │ │ │ └── t │ │ │ │ │ └── darts.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Darts.pm │ │ └── t │ │ │ └── darts.t │ ├── difference-of-squares │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── DifferenceOfSquares.pm │ │ │ │ └── t │ │ │ │ │ └── difference-of-squares.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── DifferenceOfSquares.pm │ │ └── t │ │ │ └── difference-of-squares.t │ ├── dnd-character │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── DndCharacter.pm │ │ │ │ └── t │ │ │ │ │ └── dnd-character.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── DndCharacter.pm │ │ └── t │ │ │ └── dnd-character.t │ ├── eliuds-eggs │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── EliudsEggs.pm │ │ │ │ └── t │ │ │ │ │ └── eliuds-eggs.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── EliudsEggs.pm │ │ └── t │ │ │ └── eliuds-eggs.t │ ├── etl │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── ETL.pm │ │ │ │ └── t │ │ │ │ │ └── etl.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── ETL.pm │ │ └── t │ │ │ └── etl.t │ ├── food-chain │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── FoodChain.pm │ │ │ │ └── t │ │ │ │ │ └── food-chain.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── FoodChain.pm │ │ └── t │ │ │ └── food-chain.t │ ├── gigasecond │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Gigasecond.pm │ │ │ │ └── t │ │ │ │ │ └── gigasecond.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Gigasecond.pm │ │ └── t │ │ │ └── gigasecond.t │ ├── grade-school │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── GradeSchool.pm │ │ │ │ └── t │ │ │ │ │ └── grade-school.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── GradeSchool.pm │ │ └── t │ │ │ └── grade-school.t │ ├── grains │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Grains.pm │ │ │ │ └── t │ │ │ │ │ └── grains.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Grains.pm │ │ └── t │ │ │ └── grains.t │ ├── hamming │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Hamming.pm │ │ │ │ └── t │ │ │ │ │ └── hamming.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Hamming.pm │ │ └── t │ │ │ └── hamming.t │ ├── hello-world │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── HelloWorld.pm │ │ │ │ └── t │ │ │ │ │ └── hello-world.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── HelloWorld.pm │ │ └── t │ │ │ └── hello-world.t │ ├── hexadecimal │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ └── solutions │ │ │ │ ├── Hexadecimal.pm │ │ │ │ └── hexadecimal.t │ │ ├── Hexadecimal.pm │ │ └── hexadecimal.t │ ├── house │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── House.pm │ │ │ │ └── t │ │ │ │ │ └── house.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── House.pm │ │ └── t │ │ │ └── house.t │ ├── isogram │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Isogram.pm │ │ │ │ └── t │ │ │ │ │ └── isogram.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Isogram.pm │ │ └── t │ │ │ └── isogram.t │ ├── kindergarten-garden │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── KindergartenGarden.pm │ │ │ │ └── t │ │ │ │ │ └── kindergarten-garden.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── KindergartenGarden.pm │ │ └── t │ │ │ └── kindergarten-garden.t │ ├── knapsack │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Knapsack.pm │ │ │ │ └── t │ │ │ │ │ └── knapsack.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Knapsack.pm │ │ └── t │ │ │ └── knapsack.t │ ├── largest-series-product │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── LargestSeriesProduct.pm │ │ │ │ └── t │ │ │ │ │ └── largest-series-product.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── LargestSeriesProduct.pm │ │ └── t │ │ │ └── largest-series-product.t │ ├── leap │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Leap.pm │ │ │ │ └── t │ │ │ │ │ └── leap.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Leap.pm │ │ └── t │ │ │ └── leap.t │ ├── linked-list │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ └── solutions │ │ │ │ ├── Deque.pm │ │ │ │ └── deque.t │ │ ├── Deque.pm │ │ └── deque.t │ ├── list-ops │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── ListOps.pm │ │ │ │ └── t │ │ │ │ │ └── list-ops.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── ListOps.pm │ │ └── t │ │ │ └── list-ops.t │ ├── luhn │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Luhn.pm │ │ │ │ └── t │ │ │ │ │ └── luhn.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Luhn.pm │ │ └── t │ │ │ └── luhn.t │ ├── matching-brackets │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── MatchingBrackets.pm │ │ │ │ └── t │ │ │ │ │ └── matching-brackets.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── MatchingBrackets.pm │ │ └── t │ │ │ └── matching-brackets.t │ ├── matrix │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Matrix.pm │ │ │ │ └── t │ │ │ │ │ └── matrix.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Matrix.pm │ │ └── t │ │ │ └── matrix.t │ ├── meetup │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Meetup.pm │ │ │ │ └── t │ │ │ │ │ └── meetup.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Meetup.pm │ │ └── t │ │ │ └── meetup.t │ ├── micro-blog │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── MicroBlog.pm │ │ │ │ └── t │ │ │ │ │ └── micro-blog.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── MicroBlog.pm │ │ └── t │ │ │ └── micro-blog.t │ ├── minesweeper │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Minesweeper.pm │ │ │ │ └── t │ │ │ │ │ └── minesweeper.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Minesweeper.pm │ │ └── t │ │ │ └── minesweeper.t │ ├── nucleotide-count │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── NucleotideCount.pm │ │ │ │ └── t │ │ │ │ │ └── nucleotide-count.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── NucleotideCount.pm │ │ └── t │ │ │ └── nucleotide-count.t │ ├── ocr-numbers │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── OCRNumbers.pm │ │ │ │ └── t │ │ │ │ │ └── ocr-numbers.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── OCRNumbers.pm │ │ └── t │ │ │ └── ocr-numbers.t │ ├── palindrome-products │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── PalindromeProducts.pm │ │ │ │ └── t │ │ │ │ │ └── palindrome-products.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── PalindromeProducts.pm │ │ └── t │ │ │ └── palindrome-products.t │ ├── pangram │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Pangram.pm │ │ │ │ └── t │ │ │ │ │ └── pangram.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Pangram.pm │ │ └── t │ │ │ └── pangram.t │ ├── pascals-triangle │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── PascalsTriangle.pm │ │ │ │ └── t │ │ │ │ │ └── pascals-triangle.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── PascalsTriangle.pm │ │ └── t │ │ │ └── pascals-triangle.t │ ├── phone-number │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── PhoneNumber.pm │ │ │ │ └── t │ │ │ │ │ └── phone-number.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── PhoneNumber.pm │ │ └── t │ │ │ └── phone-number.t │ ├── pig-latin │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── PigLatin.pm │ │ │ │ └── t │ │ │ │ │ └── pig-latin.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── PigLatin.pm │ │ └── t │ │ │ └── pig-latin.t │ ├── point-mutations │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ └── solutions │ │ │ │ ├── DNA.pm │ │ │ │ └── dna.t │ │ ├── DNA.pm │ │ └── dna.t │ ├── prime-factors │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── PrimeFactors.pm │ │ │ │ └── t │ │ │ │ │ └── prime-factors.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── PrimeFactors.pm │ │ └── t │ │ │ └── prime-factors.t │ ├── proverb │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Proverb.pm │ │ │ │ └── t │ │ │ │ │ └── proverb.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Proverb.pm │ │ └── t │ │ │ └── proverb.t │ ├── pythagorean-triplet │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── PythagoreanTriplet.pm │ │ │ │ └── t │ │ │ │ │ └── pythagorean-triplet.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── PythagoreanTriplet.pm │ │ └── t │ │ │ └── pythagorean-triplet.t │ ├── queen-attack │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Queen.pm │ │ │ │ └── t │ │ │ │ │ └── queen-attack.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Queen.pm │ │ └── t │ │ │ └── queen-attack.t │ ├── raindrops │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Raindrops.pm │ │ │ │ └── t │ │ │ │ │ └── raindrops.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Raindrops.pm │ │ └── t │ │ │ └── raindrops.t │ ├── reverse-string │ │ ├── .docs │ │ │ ├── instructions.append.md │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── ReverseString.pm │ │ │ │ └── t │ │ │ │ │ └── reverse-string.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── ReverseString.pm │ │ └── t │ │ │ └── reverse-string.t │ ├── rna-transcription │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── RNA.pm │ │ │ │ └── t │ │ │ │ │ └── rna-transcription.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── RNA.pm │ │ └── t │ │ │ └── rna-transcription.t │ ├── robot-name │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── RobotName.pm │ │ │ │ └── t │ │ │ │ │ └── robot-name.t │ │ │ └── template-data.yaml │ │ ├── lib │ │ │ └── RobotName.pm │ │ └── t │ │ │ └── robot-name.t │ ├── robot-simulator │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Robot.pm │ │ │ │ └── t │ │ │ │ │ └── robot-simulator.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Robot.pm │ │ └── t │ │ │ └── robot-simulator.t │ ├── roman-numerals │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── RomanNumerals.pm │ │ │ │ └── t │ │ │ │ │ └── roman-numerals.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── RomanNumerals.pm │ │ └── t │ │ │ └── roman-numerals.t │ ├── rotational-cipher │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── RotationalCipher.pm │ │ │ │ └── t │ │ │ │ │ └── rotational-cipher.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── RotationalCipher.pm │ │ └── t │ │ │ └── rotational-cipher.t │ ├── run-length-encoding │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── RunLengthEncoding.pm │ │ │ │ └── t │ │ │ │ │ └── run-length-encoding.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── RunLengthEncoding.pm │ │ └── t │ │ │ └── run-length-encoding.t │ ├── saddle-points │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── SaddlePoints.pm │ │ │ │ └── t │ │ │ │ │ └── saddle-points.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── SaddlePoints.pm │ │ └── t │ │ │ └── saddle-points.t │ ├── say │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Say.pm │ │ │ │ └── t │ │ │ │ │ └── say.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Say.pm │ │ └── t │ │ │ └── say.t │ ├── scrabble-score │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Scrabble.pm │ │ │ │ └── t │ │ │ │ │ └── scrabble-score.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Scrabble.pm │ │ └── t │ │ │ └── scrabble-score.t │ ├── secret-handshake │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── SecretHandshake.pm │ │ │ │ └── t │ │ │ │ │ └── secret-handshake.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── SecretHandshake.pm │ │ └── t │ │ │ └── secret-handshake.t │ ├── series │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Series.pm │ │ │ │ └── t │ │ │ │ │ └── series.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Series.pm │ │ └── t │ │ │ └── series.t │ ├── sieve │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Sieve.pm │ │ │ │ └── t │ │ │ │ │ └── sieve.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Sieve.pm │ │ └── t │ │ │ └── sieve.t │ ├── simple-cipher │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── SimpleCipher.pm │ │ │ │ └── t │ │ │ │ │ └── simple-cipher.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── SimpleCipher.pm │ │ └── t │ │ │ └── simple-cipher.t │ ├── simple-linked-list │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ └── solutions │ │ │ │ ├── LinkedList.pm │ │ │ │ └── simple_linked_list.t │ │ ├── LinkedList.pm │ │ └── simple_linked_list.t │ ├── space-age │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── SpaceAge.pm │ │ │ │ └── t │ │ │ │ │ └── space-age.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── SpaceAge.pm │ │ └── t │ │ │ └── space-age.t │ ├── spiral-matrix │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── SpiralMatrix.pm │ │ │ │ └── t │ │ │ │ │ └── spiral-matrix.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── SpiralMatrix.pm │ │ └── t │ │ │ └── spiral-matrix.t │ ├── strain │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Strain.pm │ │ │ │ └── t │ │ │ │ │ └── strain.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Strain.pm │ │ └── t │ │ │ └── strain.t │ ├── sublist │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Sublist.pm │ │ │ │ └── t │ │ │ │ │ └── sublist.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Sublist.pm │ │ └── t │ │ │ └── sublist.t │ ├── sum-of-multiples │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── SumOfMultiples.pm │ │ │ │ └── t │ │ │ │ │ └── sum-of-multiples.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── SumOfMultiples.pm │ │ └── t │ │ │ └── sum-of-multiples.t │ ├── triangle │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Triangle.pm │ │ │ │ └── t │ │ │ │ │ └── triangle.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Triangle.pm │ │ └── t │ │ │ └── triangle.t │ ├── trinary │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── Trinary.pm │ │ │ │ └── trinary.t │ │ │ └── tests.toml │ │ ├── Trinary.pm │ │ └── trinary.t │ ├── twelve-days │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── TwelveDays.pm │ │ │ │ └── t │ │ │ │ │ └── twelve-days.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── TwelveDays.pm │ │ └── t │ │ │ └── twelve-days.t │ ├── two-bucket │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── TwoBucket.pm │ │ │ │ └── t │ │ │ │ │ └── two-bucket.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── TwoBucket.pm │ │ └── t │ │ │ └── two-bucket.t │ ├── two-fer │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── TwoFer.pm │ │ │ │ └── t │ │ │ │ │ └── two-fer.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── TwoFer.pm │ │ └── t │ │ │ └── two-fer.t │ ├── word-count │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── WordCount.pm │ │ │ │ └── t │ │ │ │ │ └── word-count.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── WordCount.pm │ │ └── t │ │ │ └── word-count.t │ ├── wordy │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── solutions │ │ │ │ ├── lib │ │ │ │ │ └── Wordy.pm │ │ │ │ └── t │ │ │ │ │ └── wordy.t │ │ │ ├── template-data.yaml │ │ │ └── tests.toml │ │ ├── lib │ │ │ └── Wordy.pm │ │ └── t │ │ │ └── wordy.t │ └── yacht │ │ ├── .docs │ │ ├── instructions.md │ │ └── introduction.md │ │ ├── .meta │ │ ├── config.json │ │ ├── solutions │ │ │ ├── lib │ │ │ │ ├── Yacht.pm │ │ │ │ └── Yacht │ │ │ │ │ └── Category.pm │ │ │ └── t │ │ │ │ └── yacht.t │ │ ├── template-data.yaml │ │ └── tests.toml │ │ ├── lib │ │ ├── Yacht.pm │ │ └── Yacht │ │ │ └── Category.pm │ │ └── t │ │ └── yacht.t └── shared │ └── .docs │ ├── debug.md │ ├── help.md │ └── tests.md ├── lib └── Exercism │ ├── Generator.pm │ └── QuickSolve.pm ├── reference └── implementing-a-concept-exercise.md ├── t ├── files │ └── generated-tests.t └── generator │ ├── methods.t │ └── renders.t └── templates ├── module.mustache └── test.mustache /.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 | 7 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | 5 | # Keep dependencies for GitHub Actions up-to-date 6 | - package-ecosystem: 'github-actions' 7 | directory: '/' 8 | schedule: 9 | interval: 'monthly' 10 | -------------------------------------------------------------------------------- /.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/no-important-files-changed.yml: -------------------------------------------------------------------------------- 1 | name: No important files changed 2 | 3 | on: 4 | pull_request_target: 5 | types: [opened] 6 | branches: [main] 7 | paths: 8 | - "exercises/concept/**" 9 | - "exercises/practice/**" 10 | - "!exercises/*/*/.approaches/**" 11 | - "!exercises/*/*/.articles/**" 12 | - "!exercises/*/*/.docs/**" 13 | - "!exercises/*/*/.meta/**" 14 | 15 | permissions: 16 | pull-requests: write 17 | 18 | jobs: 19 | check: 20 | uses: exercism/github-actions/.github/workflows/check-no-important-files-changed.yml@main 21 | with: 22 | repository: ${{ github.event.pull_request.head.repo.owner.login }}/${{ github.event.pull_request.head.repo.name }} 23 | ref: ${{ github.head_ref }} 24 | -------------------------------------------------------------------------------- /.github/workflows/pause-community-contributions.yml: -------------------------------------------------------------------------------- 1 | name: Pause Community Contributions 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | pull_request_target: 8 | types: 9 | - opened 10 | paths-ignore: 11 | - 'exercises/*/*/.approaches/**' 12 | - 'exercises/*/*/.articles/**' 13 | 14 | permissions: 15 | issues: write 16 | pull-requests: write 17 | 18 | jobs: 19 | pause: 20 | if: github.repository_owner == 'exercism' # Stops this job from running on forks 21 | uses: exercism/github-actions/.github/workflows/community-contributions.yml@main 22 | with: 23 | forum_category: perl5 24 | secrets: 25 | github_membership_token: ${{ secrets.COMMUNITY_CONTRIBUTIONS_WORKFLOW_TOKEN }} 26 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/configlet 2 | bin/configlet.exe 3 | .problem-specifications 4 | 5 | # Carton/Carmel-installed files 6 | local/ 7 | cpanfile.snapshot 8 | .carmel/ 9 | 10 | # Ditto, for exercises 11 | **/cpanfile.snapshot 12 | **/local/ 13 | **/.carmel/ 14 | -------------------------------------------------------------------------------- /.perltidyrc: -------------------------------------------------------------------------------- 1 | --perl-best-practices 2 | --nostandard-output 3 | --ignore-side-comment-lengths 4 | --minimum-space-to-comment=1 5 | --novalign-side-comments 6 | --freeze-newlines 7 | --keep-old-breakpoints-after='(' 8 | --nowant-right-space='A' 9 | -------------------------------------------------------------------------------- /concepts/arrays-and-lists/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Arrays and lists in Perl contain an ordered collection of scalars.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/basics/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Perl is a high-level, general-purpose, interpreted, dynamic programming language.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/basics/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/booleans-and-conditionals/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Learn about truth and falsehood in Perl.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/booleans-and-conditionals/about.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/booleans-and-conditionals/about.md -------------------------------------------------------------------------------- /concepts/booleans-and-conditionals/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/booleans-and-conditionals/introduction.md -------------------------------------------------------------------------------- /concepts/booleans-and-conditionals/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/exceptions/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Learn how to handle errors in Perl.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/exceptions/about.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/exceptions/about.md -------------------------------------------------------------------------------- /concepts/exceptions/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/exceptions/introduction.md -------------------------------------------------------------------------------- /concepts/exceptions/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/hashes/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Hashes are a data type in Perl which contain an unordered collection of string keys paired with scalar values.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/hashes/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/numbers/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Learn about numbers and arithmetic operators in Perl.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/numbers/about.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/numbers/about.md -------------------------------------------------------------------------------- /concepts/numbers/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/numbers/introduction.md -------------------------------------------------------------------------------- /concepts/numbers/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/object-orientation/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Perl has a wide variety of ways to do Object Oriented Programming.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/object-orientation/about.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/object-orientation/about.md -------------------------------------------------------------------------------- /concepts/object-orientation/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/object-orientation/introduction.md -------------------------------------------------------------------------------- /concepts/object-orientation/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/packages-and-modules/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Learn about packages and modules, and how to import and export from them.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/packages-and-modules/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/references/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "References are important to understand in Perl, fundamental to making use of complex data structures such as multidimensional arrays and nested hashes.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/references/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/regular-expressions/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Learn about Regular Expressions in the language that inspired PCRE!", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/regular-expressions/about.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/regular-expressions/about.md -------------------------------------------------------------------------------- /concepts/regular-expressions/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/regular-expressions/introduction.md -------------------------------------------------------------------------------- /concepts/regular-expressions/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/strings/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Learn about strings, interpolation, concatenation and other text-related functions.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/strings/about.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/strings/about.md -------------------------------------------------------------------------------- /concepts/strings/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/strings/introduction.md -------------------------------------------------------------------------------- /concepts/strings/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /concepts/subroutines/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Learn about subroutines, functions, and signatures.", 3 | "authors": [ 4 | "m.dango" 5 | ], 6 | "contributors": [ 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /concepts/subroutines/about.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/subroutines/about.md -------------------------------------------------------------------------------- /concepts/subroutines/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/concepts/subroutines/introduction.md -------------------------------------------------------------------------------- /concepts/subroutines/links.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /cpanfile: -------------------------------------------------------------------------------- 1 | requires 'Data::Dmp'; 2 | requires 'Feature::Compat::Class'; 3 | requires 'lib::gitroot'; 4 | requires 'namespace::autoclean'; 5 | requires 'Path::Tiny'; 6 | requires 'Perl::Tidy'; 7 | requires 'Template::Mustache'; 8 | requires 'Test2::V0'; 9 | requires 'TOML::Parser'; 10 | requires 'UUID'; 11 | requires 'YAML'; 12 | -------------------------------------------------------------------------------- /docs/LEARNING.md: -------------------------------------------------------------------------------- 1 | # Learning 2 | 3 | Exercism provides exercises and feedback but can be difficult to jump into for those learning Perl for the first time. 4 | Check out [learn.perl.org](http://learn.perl.org/) for instructions and information on getting started with Perl. 5 | -------------------------------------------------------------------------------- /docs/SNIPPET.txt: -------------------------------------------------------------------------------- 1 | package HelloWorld; 2 | use strict; 3 | use warnings; 4 | 5 | sub hello { 6 | return 'Hello, World!'; 7 | } 8 | 9 | 1; 10 | -------------------------------------------------------------------------------- /exercises/concept/booking-up-for-beauty/.docs/introduction.md.tpl: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | %{concept:packages-and-modules} 4 | -------------------------------------------------------------------------------- /exercises/concept/booking-up-for-beauty/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/BookingUpForBeauty.pm" 8 | ], 9 | "test": [ 10 | "t/booking-up-for-beauty.t" 11 | ], 12 | "exemplar": [ 13 | ".meta/BookingUpForBeauty.pm" 14 | ] 15 | }, 16 | "blurb": "Learn about importing and exporting modules in Perl by building an appointment scheduler for a beauty salon." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/concept/high-score-board/.docs/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/exercises/concept/high-score-board/.docs/introduction.md -------------------------------------------------------------------------------- /exercises/concept/high-score-board/.meta/HighScoreBoard.pm: -------------------------------------------------------------------------------- 1 | package HighScoreBoard; 2 | 3 | use v5.40; 4 | 5 | our %Scores; 6 | 7 | sub set_player_scores (%new_scores) { 8 | %Scores = ( %Scores, %new_scores ); 9 | return; 10 | } 11 | 12 | sub get_player_score ($player) { 13 | return $Scores{$player}; 14 | } 15 | 16 | sub increase_player_scores (%additional_scores) { 17 | %Scores = map { $_ => $Scores{$_} + $additional_scores{$_} } keys %Scores; 18 | return; 19 | } 20 | 21 | sub sort_players_by_name { 22 | return sort keys %Scores; 23 | } 24 | 25 | sub sort_players_by_score { 26 | return sort { $Scores{$b} <=> $Scores{$a} } keys %Scores; 27 | } 28 | 29 | sub delete_player ($player) { 30 | delete $Scores{$player}; 31 | return; 32 | } 33 | -------------------------------------------------------------------------------- /exercises/concept/high-score-board/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/HighScoreBoard.pm" 8 | ], 9 | "test": [ 10 | "t/high-score-board.t" 11 | ], 12 | "exemplar": [ 13 | ".meta/HighScoreBoard.pm" 14 | ] 15 | }, 16 | "language_versions": ">=5.38", 17 | "blurb": "Learn about hashes in Perl by modifying a scoreboard." 18 | } 19 | -------------------------------------------------------------------------------- /exercises/concept/high-score-board/lib/HighScoreBoard.pm: -------------------------------------------------------------------------------- 1 | package HighScoreBoard; 2 | 3 | use v5.40; 4 | 5 | our %Scores; 6 | 7 | sub set_player_scores (%new_scores) { 8 | } 9 | 10 | sub get_player_score ($player) { 11 | } 12 | 13 | sub increase_player_scores (%additional_scores) { 14 | } 15 | 16 | sub sort_players_by_name { 17 | } 18 | 19 | sub sort_players_by_score { 20 | } 21 | 22 | sub delete_player ($player) { 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /exercises/concept/inventory-management/.docs/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/exercises/concept/inventory-management/.docs/introduction.md -------------------------------------------------------------------------------- /exercises/concept/inventory-management/.meta/InventoryManagement.pm: -------------------------------------------------------------------------------- 1 | package InventoryManagement; 2 | 3 | use v5.40; 4 | 5 | sub create_inventory ($items) { 6 | my %inventory; 7 | for ( $items->@* ) { 8 | $inventory{$_}++; 9 | } 10 | return \%inventory; 11 | } 12 | 13 | sub add_items ( $inventory, $items ) { 14 | for ( $items->@* ) { 15 | $inventory->{$_}++; 16 | } 17 | return $inventory; 18 | } 19 | 20 | sub remove_items ( $inventory, $items ) { 21 | for ( $items->@* ) { 22 | $inventory->{$_}-- if $inventory->{$_}; 23 | } 24 | return $inventory; 25 | } 26 | 27 | sub delete_item ( $inventory, $item ) { 28 | delete $inventory->{$item}; 29 | return $inventory; 30 | } 31 | -------------------------------------------------------------------------------- /exercises/concept/inventory-management/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/InventoryManagement.pm" 8 | ], 9 | "test": [ 10 | "t/inventory-management.t" 11 | ], 12 | "exemplar": [ 13 | ".meta/InventoryManagement.pm" 14 | ] 15 | }, 16 | "language_versions": ">=5.38", 17 | "blurb": "Learn about references in Perl by modifying an inventory of materials." 18 | } 19 | -------------------------------------------------------------------------------- /exercises/concept/inventory-management/lib/InventoryManagement.pm: -------------------------------------------------------------------------------- 1 | package InventoryManagement; 2 | 3 | use v5.40; 4 | 5 | sub create_inventory ($items) { 6 | my %inventory; 7 | return \%inventory; 8 | } 9 | 10 | sub add_items ( $inventory, $items ) { 11 | return $inventory; 12 | } 13 | 14 | sub remove_items ( $inventory, $items ) { 15 | return $inventory; 16 | } 17 | 18 | sub delete_item ( $inventory, $item ) { 19 | return $inventory; 20 | } 21 | 22 | 1; 23 | -------------------------------------------------------------------------------- /exercises/concept/language-list/.docs/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/exercises/concept/language-list/.docs/introduction.md -------------------------------------------------------------------------------- /exercises/concept/language-list/.meta/LanguageList.pm: -------------------------------------------------------------------------------- 1 | package LanguageList; 2 | 3 | use v5.40; 4 | use List::Util qw; 5 | 6 | our @Languages; 7 | 8 | sub add_language ($language) { 9 | push @Languages, $language; 10 | } 11 | 12 | sub remove_language () { 13 | pop @Languages; 14 | } 15 | 16 | sub first_language () { 17 | return $Languages[0]; 18 | } 19 | 20 | sub last_language () { 21 | return $Languages[-1]; 22 | } 23 | 24 | sub get_languages (@elems) { 25 | return @Languages[ map { $_ - 1 } @elems ]; 26 | } 27 | 28 | sub has_language ($language) { 29 | return any { $_ eq $language } @Languages; 30 | } 31 | -------------------------------------------------------------------------------- /exercises/concept/language-list/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/LanguageList.pm" 8 | ], 9 | "test": [ 10 | "t/language-list.t" 11 | ], 12 | "exemplar": [ 13 | ".meta/LanguageList.pm" 14 | ] 15 | }, 16 | "language_versions": ">=5.38", 17 | "blurb": "Learn about arrays and lists in Perl by working with a collection of languages." 18 | } 19 | -------------------------------------------------------------------------------- /exercises/concept/language-list/lib/LanguageList.pm: -------------------------------------------------------------------------------- 1 | package LanguageList; 2 | 3 | use v5.40; 4 | 5 | our @Languages; 6 | 7 | sub add_language ($language) { 8 | } 9 | 10 | sub remove_language () { 11 | } 12 | 13 | sub first_language () { 14 | } 15 | 16 | sub last_language () { 17 | } 18 | 19 | sub get_languages (@elements) { 20 | } 21 | 22 | sub has_language ($language) { 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /exercises/concept/lasagna/.docs/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/perl5/86cd8656af0fb1a2c3c2562b962bc8e0af3c0658/exercises/concept/lasagna/.docs/introduction.md -------------------------------------------------------------------------------- /exercises/concept/lasagna/.meta/Lasagna.pm: -------------------------------------------------------------------------------- 1 | package Lasagna; 2 | 3 | use v5.40; 4 | 5 | our $ExpectedMinutesInOven = 40; 6 | 7 | sub remaining_minutes_in_oven ($actual_minutes_in_oven) { 8 | return $ExpectedMinutesInOven - $actual_minutes_in_oven; 9 | } 10 | 11 | sub preparation_time_in_minutes ($number_of_layers) { 12 | return $number_of_layers * 2; 13 | } 14 | 15 | sub total_time_in_minutes ( $number_of_layers, $actual_minutes_in_oven ) { 16 | return preparation_time_in_minutes($number_of_layers) + $actual_minutes_in_oven; 17 | } 18 | 19 | sub oven_alarm () { 20 | return 'Ding!'; 21 | } 22 | -------------------------------------------------------------------------------- /exercises/concept/lasagna/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/Lasagna.pm" 8 | ], 9 | "test": [ 10 | "t/lasagna.t" 11 | ], 12 | "exemplar": [ 13 | ".meta/Lasagna.pm" 14 | ] 15 | }, 16 | "language_versions": ">=5.38", 17 | "blurb": "Learn about the basics of Perl by following a lasagna recipe." 18 | } 19 | -------------------------------------------------------------------------------- /exercises/concept/lasagna/lib/Lasagna.pm: -------------------------------------------------------------------------------- 1 | package Lasagna; 2 | 3 | use v5.40; 4 | 5 | our $ExpectedMinutesInOven = undef; 6 | 7 | sub remaining_minutes_in_oven ($actual_minutes_in_oven) { 8 | } 9 | 10 | sub preparation_time_in_minutes ($number_of_layers) { 11 | } 12 | 13 | sub total_time_in_minutes ( $number_of_layers, $actual_minutes_in_oven ) { 14 | } 15 | 16 | sub oven_alarm () { 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "choroba", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/Accumulate.pm" 14 | ], 15 | "test": [ 16 | "t/accumulate.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/Accumulate.pm" 20 | ] 21 | }, 22 | "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.", 23 | "source": "Conversation with James Edward Gray II", 24 | "source_url": "http://graysoftinc.com/" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/.meta/solutions/lib/Accumulate.pm: -------------------------------------------------------------------------------- 1 | package Accumulate; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub accumulate ( $list, $func ) { 11 | my @results; 12 | 13 | for ( @{$list} ) { 14 | push @results, $func->($_); 15 | } 16 | 17 | return \@results; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/.meta/solutions/t/accumulate.t: -------------------------------------------------------------------------------- 1 | ../../../t/accumulate.t -------------------------------------------------------------------------------- /exercises/practice/accumulate/lib/Accumulate.pm: -------------------------------------------------------------------------------- 1 | package Accumulate; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub accumulate ( $list, $func ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/Acronym.pm" 8 | ], 9 | "test": [ 10 | "t/acronym.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/Acronym.pm" 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/solutions/lib/Acronym.pm: -------------------------------------------------------------------------------- 1 | package Acronym; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub abbreviate ($phrase) { 11 | 12 | # capture letters preceded by the start of the string 13 | # or by a non-(letter or apostrophe) 14 | my @letters = $phrase =~ /(?:^|[^'a-z])\K([a-z])/ig; 15 | return uc join "", @letters; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /exercises/practice/acronym/.meta/solutions/t/acronym.t: -------------------------------------------------------------------------------- 1 | ../../../t/acronym.t -------------------------------------------------------------------------------- /exercises/practice/acronym/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: abbreviate 2 | 3 | properties: 4 | abbreviate: 5 | test: |- 6 | use Data::Dmp; 7 | sprintf(<<'END', map {dmp($_)} $case->{input}{phrase}, $case->{expected}, $case->{description}); 8 | is( 9 | abbreviate( %s ), 10 | %s, 11 | %s, 12 | ); 13 | END 14 | 15 | example: |- 16 | sub abbreviate ($phrase) { 17 | # capture letters preceded by the start of the string 18 | # or by a non-(letter or apostrophe) 19 | my @letters = $phrase =~ /(?:^|[^'a-z])\K([a-z])/ig; 20 | return uc join "", @letters; 21 | } 22 | 23 | stub: |- 24 | sub abbreviate ($phrase) { 25 | return undef; 26 | } 27 | -------------------------------------------------------------------------------- /exercises/practice/acronym/lib/Acronym.pm: -------------------------------------------------------------------------------- 1 | package Acronym; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub abbreviate ($phrase) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "yanick" 4 | ], 5 | "contributors": [ 6 | "kotp", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/AllYourBase.pm" 13 | ], 14 | "test": [ 15 | "t/all-your-base.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/AllYourBase.pm" 19 | ] 20 | }, 21 | "blurb": "Convert a number, represented as a sequence of digits in one base, to any other base." 22 | } 23 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.meta/solutions/t/all-your-base.t: -------------------------------------------------------------------------------- 1 | ../../../t/all-your-base.t -------------------------------------------------------------------------------- /exercises/practice/all-your-base/lib/AllYourBase.pm: -------------------------------------------------------------------------------- 1 | package AllYourBase; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | my @errors = ( 9 | 'input base must be >= 2', 10 | 'output base must be >= 2', 11 | 'all digits must satisfy 0 <= d < input base', 12 | ); 13 | 14 | sub rebase ( $digits, $input_base, $output_base ) { 15 | return undef; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /exercises/practice/allergies/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "dnmfarrell", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/Allergies.pm" 14 | ], 15 | "test": [ 16 | "t/allergies.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/Allergies.pm" 20 | ] 21 | }, 22 | "blurb": "Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.", 23 | "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 24 | "source_url": "https://turing.edu" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/allergies/.meta/solutions/lib/Allergies.pm: -------------------------------------------------------------------------------- 1 | package Allergies; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use constant ALLERGENS => { 11 | eggs => 1, 12 | peanuts => 2, 13 | shellfish => 4, 14 | strawberries => 8, 15 | tomatoes => 16, 16 | chocolate => 32, 17 | pollen => 64, 18 | cats => 128, 19 | }; 20 | 21 | sub allergic_to ( $item, $score ) { 22 | ALLERGENS->{$item} & $score; 23 | } 24 | 25 | sub list_allergies ($score) { 26 | return [ grep { allergic_to $_, $score } 27 | keys %{ +ALLERGENS } ]; 28 | } 29 | 30 | 1; 31 | -------------------------------------------------------------------------------- /exercises/practice/allergies/.meta/solutions/t/allergies.t: -------------------------------------------------------------------------------- 1 | ../../../t/allergies.t -------------------------------------------------------------------------------- /exercises/practice/allergies/lib/Allergies.pm: -------------------------------------------------------------------------------- 1 | package Allergies; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub allergic_to ( $item, $score ) { 9 | return undef; 10 | } 11 | 12 | sub list_allergies ($score) { 13 | return undef; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /exercises/practice/anagram/.docs/instructions.append.md: -------------------------------------------------------------------------------- 1 | # Instructions Append 2 | 3 | The anagrams can be returned in any order. 4 | -------------------------------------------------------------------------------- /exercises/practice/anagram/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "szabgab" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo", 9 | "sshine" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/Anagram.pm" 14 | ], 15 | "test": [ 16 | "t/anagram.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/Anagram.pm" 20 | ] 21 | }, 22 | "blurb": "Given a word and a list of possible anagrams, select the correct sublist.", 23 | "source": "Inspired by the Extreme Startup game", 24 | "source_url": "https://github.com/rchatley/extreme_startup" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/anagram/.meta/solutions/lib/Anagram.pm: -------------------------------------------------------------------------------- 1 | package Anagram; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub match_anagrams ( $subject, $candidates ) { 11 | 12 | return [ 13 | grep { 14 | lc $_ ne lc $subject 15 | && join( '', sort( split( //, lc $_ ) ) ) eq 16 | join( '', sort( split( //, lc $subject ) ) ) 17 | } @{$candidates} 18 | ]; 19 | } 20 | 21 | 1; 22 | -------------------------------------------------------------------------------- /exercises/practice/anagram/.meta/solutions/t/anagram.t: -------------------------------------------------------------------------------- 1 | ../../../t/anagram.t -------------------------------------------------------------------------------- /exercises/practice/anagram/lib/Anagram.pm: -------------------------------------------------------------------------------- 1 | package Anagram; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub match_anagrams ( $subject, $candidates ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/ArmstrongNumbers.pm" 8 | ], 9 | "test": [ 10 | "t/armstrong-numbers.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/ArmstrongNumbers.pm" 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/solutions/lib/ArmstrongNumbers.pm: -------------------------------------------------------------------------------- 1 | package ArmstrongNumbers; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use bignum; 11 | 12 | sub is_armstrong_number ($number) { 13 | my $n = $number->copy(); 14 | my $size = $n->length(); 15 | my $sum = Math::BigInt->bzero(); 16 | my $rem; 17 | while ( $n->is_positive() ) { 18 | ( $n, $rem ) = $n->bdiv(10); 19 | $sum = $sum->badd( $rem->bpow($size) ); 20 | } 21 | return $sum->beq($number); 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.meta/solutions/t/armstrong-numbers.t: -------------------------------------------------------------------------------- 1 | ../../../t/armstrong-numbers.t -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/lib/ArmstrongNumbers.pm: -------------------------------------------------------------------------------- 1 | package ArmstrongNumbers; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub is_armstrong_number ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/atbash-cipher/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "dnmfarrell", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/AtbashCipher.pm" 14 | ], 15 | "test": [ 16 | "t/atbash-cipher.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/AtbashCipher.pm" 20 | ] 21 | }, 22 | "blurb": "Create an implementation of the Atbash cipher, an ancient encryption system created in the Middle East.", 23 | "source": "Wikipedia", 24 | "source_url": "https://en.wikipedia.org/wiki/Atbash" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/atbash-cipher/.meta/solutions/lib/AtbashCipher.pm: -------------------------------------------------------------------------------- 1 | package AtbashCipher; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use List::Util qw; 11 | 12 | my %dict; 13 | @dict{ 'a' .. 'z' } = reverse( 'a' .. 'z' ); 14 | 15 | sub encode_atbash { 16 | join( ' ', pairvalues split( /(\w{1,5})/, decode_atbash(@_) ) ); 17 | } 18 | 19 | sub decode_atbash { 20 | join '', map { /\d/ ? $_ : $dict{$_} } split( //, lc $_[0] =~ s/\W//gr ); 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /exercises/practice/atbash-cipher/.meta/solutions/t/atbash-cipher.t: -------------------------------------------------------------------------------- 1 | ../../../t/atbash-cipher.t -------------------------------------------------------------------------------- /exercises/practice/atbash-cipher/lib/AtbashCipher.pm: -------------------------------------------------------------------------------- 1 | package AtbashCipher; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub encode_atbash ($phrase) { 9 | return undef; 10 | } 11 | 12 | sub decode_atbash ($phrase) { 13 | return undef; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /exercises/practice/beer-song/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Produce the lyrics to that beloved classic, that field-trip favorite: 99 Bottles of Beer on the Wall.", 3 | "authors": [ 4 | "bistik" 5 | ], 6 | "contributors": [ 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "BeerSong.pm" 14 | ], 15 | "test": [ 16 | "beer-song.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/BeerSong.pm" 20 | ] 21 | }, 22 | "source": "Learn to Program by Chris Pine", 23 | "source_url": "http://pine.fm/LearnToProgram/?Chapter=06" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/beer-song/.meta/solutions/beer-song.t: -------------------------------------------------------------------------------- 1 | ../../beer-song.t -------------------------------------------------------------------------------- /exercises/practice/beer-song/BeerSong.pm: -------------------------------------------------------------------------------- 1 | package BeerSong; 2 | 3 | use strict; 4 | use warnings; 5 | use feature qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub sing { 11 | my ($input) = @_; 12 | return undef; 13 | } 14 | 15 | 1; 16 | -------------------------------------------------------------------------------- /exercises/practice/binary-search-tree/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bentglasstube" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/BinarySearchTree.pm" 13 | ], 14 | "test": [ 15 | "t/binary-search-tree.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/BinarySearchTree.pm" 19 | ] 20 | }, 21 | "blurb": "Insert and search for numbers in a binary tree.", 22 | "source": "Josh Cheek" 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/binary-search-tree/.meta/solutions/t/binary-search-tree.t: -------------------------------------------------------------------------------- 1 | ../../../t/binary-search-tree.t -------------------------------------------------------------------------------- /exercises/practice/binary-search-tree/lib/BinarySearchTree.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class BinarySearchTree; 5 | 6 | field $root :param; 7 | 8 | method add () { 9 | 10 | # $root contains the initial node. 11 | } 12 | 13 | method sort () { 14 | return []; 15 | } 16 | 17 | class BinarySearchTree::Node { 18 | field $data :reader :param; 19 | field $left :reader; 20 | field $right :reader; 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /exercises/practice/binary-search/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [], 3 | "contributors": [ 4 | "kytrinyx", 5 | "m-dango", 6 | "rfilipo" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "lib/BinarySearch.pm" 11 | ], 12 | "test": [ 13 | "t/binary-search.t" 14 | ], 15 | "example": [ 16 | ".meta/solutions/lib/BinarySearch.pm" 17 | ] 18 | }, 19 | "blurb": "Implement a binary search algorithm.", 20 | "source": "Wikipedia", 21 | "source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm" 22 | } 23 | -------------------------------------------------------------------------------- /exercises/practice/binary-search/.meta/solutions/t/binary-search.t: -------------------------------------------------------------------------------- 1 | ../../../t/binary-search.t -------------------------------------------------------------------------------- /exercises/practice/binary-search/lib/BinarySearch.pm: -------------------------------------------------------------------------------- 1 | package BinarySearch; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub binary_search ( $array, $value ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/binary/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Convert a binary number, represented as a string (e.g. '101010'), to its decimal equivalent using first principles", 3 | "authors": [ 4 | "bistik" 5 | ], 6 | "contributors": [ 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "Binary.pm" 14 | ], 15 | "test": [ 16 | "binary.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/Binary.pm" 20 | ] 21 | }, 22 | "source": "All of Computer Science", 23 | "source_url": "http://www.wolframalpha.com/input/?i=binary&a=*C.binary-_*MathWorld-" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/binary/.meta/solutions/Binary.pm: -------------------------------------------------------------------------------- 1 | package Binary; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ( $class, $binary ) = @_; 8 | my $self = bless { binary => $binary } => $class; 9 | 10 | return $self; 11 | } 12 | 13 | sub to_decimal { 14 | my $self = shift; 15 | 16 | return 0 if $self->{binary} =~ m/[^01]/; 17 | 18 | my $decimal = 0; 19 | my $index = length $self->{binary}; 20 | 21 | foreach my $bit ( split // => $self->{binary} ) { 22 | $decimal += $bit * 2** --$index; 23 | } 24 | 25 | return $decimal; 26 | } 27 | 28 | __PACKAGE__; 29 | -------------------------------------------------------------------------------- /exercises/practice/binary/.meta/solutions/binary.t: -------------------------------------------------------------------------------- 1 | ../../binary.t -------------------------------------------------------------------------------- /exercises/practice/binary/Binary.pm: -------------------------------------------------------------------------------- 1 | package Binary; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ( $class, $binary ) = @_; 8 | 9 | return undef; 10 | } 11 | 12 | sub to_decimal { 13 | my $self = shift; 14 | 15 | return undef; 16 | } 17 | 18 | __PACKAGE__; 19 | -------------------------------------------------------------------------------- /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/solutions/lib/Bob.pm: -------------------------------------------------------------------------------- 1 | # Declare package 'Bob' 2 | package Bob; 3 | 4 | use strict; 5 | use warnings; 6 | use experimental qw; 7 | 8 | use Exporter qw; 9 | our @EXPORT_OK = qw; 10 | 11 | sub hey ($text) { 12 | if ( uc($text) eq $text && $text =~ /\p{Uppercase}/ ) { 13 | return 'Calm down, I know what I\'m doing!' if $text =~ /\?\s*$/; 14 | return 'Whoa, chill out!'; 15 | } 16 | return 'Fine. Be that way!' if $text =~ /^\s*$/; 17 | return 'Sure.' if $text =~ /\?\s*$/; 18 | return 'Whatever.'; 19 | } 20 | 21 | 1; 22 | -------------------------------------------------------------------------------- /exercises/practice/bob/.meta/solutions/t/bob.t: -------------------------------------------------------------------------------- 1 | ../../../t/bob.t -------------------------------------------------------------------------------- /exercises/practice/bob/lib/Bob.pm: -------------------------------------------------------------------------------- 1 | # Declare package 'Bob' 2 | package Bob; 3 | 4 | use v5.40; 5 | 6 | use Exporter qw; 7 | our @EXPORT_OK = qw; 8 | 9 | sub hey ($msg) { 10 | return undef; # Replace this with your own code to pass the tests. 11 | } 12 | 13 | 1; 14 | -------------------------------------------------------------------------------- /exercises/practice/bottle-song/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/BottleSong.pm" 8 | ], 9 | "test": [ 10 | "t/bottle-song.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/BottleSong.pm" 14 | ] 15 | }, 16 | "blurb": "Produce the lyrics to the popular children's repetitive song: Ten Green Bottles.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Ten_Green_Bottles" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/bottle-song/.meta/solutions/t/bottle-song.t: -------------------------------------------------------------------------------- 1 | ../../../t/bottle-song.t -------------------------------------------------------------------------------- /exercises/practice/bottle-song/lib/BottleSong.pm: -------------------------------------------------------------------------------- 1 | package BottleSong; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | my %numbers = ( 9 | 1 => 'one', 10 | 2 => 'two', 11 | 3 => 'three', 12 | 4 => 'four', 13 | 5 => 'five', 14 | 6 => 'six', 15 | 7 => 'seven', 16 | 8 => 'eight', 17 | 9 => 'nine', 18 | 10 => 'ten', 19 | ); 20 | 21 | sub sing ( $bottles, $verses ) { 22 | return undef; 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /exercises/practice/circular-buffer/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/CircularBuffer.pm" 8 | ], 9 | "test": [ 10 | "t/circular-buffer.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/CircularBuffer.pm" 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/circular-buffer/.meta/solutions/t/circular-buffer.t: -------------------------------------------------------------------------------- 1 | ../../../t/circular-buffer.t -------------------------------------------------------------------------------- /exercises/practice/circular-buffer/lib/CircularBuffer.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class CircularBuffer; 5 | 6 | field $capacity :reader :param; 7 | 8 | method write ($item) { 9 | return undef; 10 | } 11 | 12 | method read () { 13 | return undef; 14 | } 15 | 16 | method clear () { 17 | return undef; 18 | } 19 | 20 | method overwrite ($item) { 21 | return undef; 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Clock.pm" 13 | ], 14 | "test": [ 15 | "t/clock.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Clock.pm" 19 | ] 20 | }, 21 | "blurb": "Implement a clock that handles times without dates.", 22 | "source": "Pairing session with Erin Drummond" 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/clock/.meta/solutions/t/clock.t: -------------------------------------------------------------------------------- 1 | ../../../t/clock.t -------------------------------------------------------------------------------- /exercises/practice/clock/lib/Clock.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class Clock; 5 | 6 | field $hour :reader :param; 7 | field $minute :reader :param; 8 | 9 | method time () { 10 | return undef; 11 | } 12 | 13 | method add_minutes ($amount) { 14 | return $self; 15 | } 16 | 17 | method subtract_minutes ($amount) { 18 | return $self; 19 | } 20 | 21 | 1; 22 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/CollatzConjecture.pm" 8 | ], 9 | "test": [ 10 | "t/collatz-conjecture.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/CollatzConjecture.pm" 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/solutions/lib/CollatzConjecture.pm: -------------------------------------------------------------------------------- 1 | package CollatzConjecture; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub steps ($number) { 11 | die 'Only positive integers are allowed' unless $number > 0; 12 | my $count = 0; 13 | while ( $number > 1 ) { 14 | $number = ( $number % 2 == 0 ) ? ( $number / 2 ) : ( 3 * $number + 1 ); 15 | $count++; 16 | } 17 | return $count; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /exercises/practice/collatz-conjecture/.meta/solutions/t/collatz-conjecture.t: -------------------------------------------------------------------------------- 1 | ../../../t/collatz-conjecture.t -------------------------------------------------------------------------------- /exercises/practice/collatz-conjecture/lib/CollatzConjecture.pm: -------------------------------------------------------------------------------- 1 | package CollatzConjecture; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub steps ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/crypto-square/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "alexkalderimis", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/CryptoSquare.pm" 14 | ], 15 | "test": [ 16 | "t/crypto-square.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/CryptoSquare.pm" 20 | ] 21 | }, 22 | "blurb": "Implement the classic method for composing secret messages called a square code.", 23 | "source": "J Dalbey's Programming Practice problems", 24 | "source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/crypto-square/.meta/solutions/t/crypto-square.t: -------------------------------------------------------------------------------- 1 | ../../../t/crypto-square.t -------------------------------------------------------------------------------- /exercises/practice/crypto-square/lib/CryptoSquare.pm: -------------------------------------------------------------------------------- 1 | package CryptoSquare; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub cipher ($text) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "autark" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo", 9 | "sshine" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/CustomSet.pm" 14 | ], 15 | "test": [ 16 | "t/custom-set.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/CustomSet.pm" 20 | ] 21 | }, 22 | "blurb": "Create a custom set type." 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/custom-set/.meta/solutions/t/custom-set.t: -------------------------------------------------------------------------------- 1 | ../../../t/custom-set.t -------------------------------------------------------------------------------- /exercises/practice/custom-set/lib/CustomSet.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class CustomSet; 5 | 6 | field $elements :reader :param; 7 | 8 | method is_empty () { 9 | return undef; 10 | } 11 | 12 | method contains ($element) { 13 | return undef; 14 | } 15 | 16 | method is_subset_of ($other) { 17 | return undef; 18 | } 19 | 20 | method is_disjoint_of ($other) { 21 | return undef; 22 | } 23 | 24 | method is_equal_to ($other) { 25 | return undef; 26 | } 27 | 28 | method add ($element) { 29 | return undef; 30 | } 31 | 32 | method intersection ($other) { 33 | return undef; 34 | } 35 | 36 | method difference ($other) { 37 | return undef; 38 | } 39 | 40 | method union ($other) { 41 | return undef; 42 | } 43 | 44 | 1; 45 | -------------------------------------------------------------------------------- /exercises/practice/darts/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/Darts.pm" 8 | ], 9 | "test": [ 10 | "t/darts.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/Darts.pm" 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/solutions/lib/Darts.pm: -------------------------------------------------------------------------------- 1 | package Darts; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub score_dart ( $x, $y ) { 11 | my $sqrt = sqrt $x**2 + $y**2; 12 | 13 | return 10 if $sqrt <= 1; 14 | return 5 if $sqrt <= 5; 15 | return 1 if $sqrt <= 10; 16 | return 0; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /exercises/practice/darts/.meta/solutions/t/darts.t: -------------------------------------------------------------------------------- 1 | ../../../t/darts.t -------------------------------------------------------------------------------- /exercises/practice/darts/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: score_dart 2 | properties: 3 | score: 4 | test: |- 5 | use Data::Dmp; 6 | sprintf(<<'END', map {dmp $_} $case->{input}->@{qw}, $case->@{qw}); 7 | is( 8 | score_dart( %s, %s ), 9 | %s, 10 | %s, 11 | ); 12 | END 13 | 14 | 15 | example: |- 16 | sub score_dart ( $x, $y ) { 17 | my $sqrt = sqrt $x ** 2 + $y ** 2; 18 | 19 | return 10 if $sqrt <= 1; 20 | return 5 if $sqrt <= 5; 21 | return 1 if $sqrt <= 10; 22 | return 0; 23 | } 24 | 25 | stub: |- 26 | sub score_dart ( $x, $y ) { 27 | } 28 | -------------------------------------------------------------------------------- /exercises/practice/darts/lib/Darts.pm: -------------------------------------------------------------------------------- 1 | package Darts; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub score_dart ( $x, $y ) { 9 | } 10 | 11 | 1; 12 | -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Find the difference between the square of the sum and the sum of the squares of the first N natural numbers. 4 | 5 | The square of the sum of the first ten natural numbers is 6 | (1 + 2 + ... + 10)² = 55² = 3025. 7 | 8 | The sum of the squares of the first ten natural numbers is 9 | 1² + 2² + ... + 10² = 385. 10 | 11 | Hence the difference between the square of the sum of the first ten natural numbers and the sum of the squares of the first ten natural numbers is 3025 - 385 = 2640. 12 | 13 | You are not expected to discover an efficient solution to this yourself from first principles; research is allowed, indeed, encouraged. 14 | Finding the best algorithm for the problem is a key skill in software engineering. 15 | -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo", 9 | "Scientifica96" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/DifferenceOfSquares.pm" 14 | ], 15 | "test": [ 16 | "t/difference-of-squares.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/DifferenceOfSquares.pm" 20 | ] 21 | }, 22 | "blurb": "Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.", 23 | "source": "Problem 6 at Project Euler", 24 | "source_url": "https://projecteuler.net/problem=6" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/.meta/solutions/lib/DifferenceOfSquares.pm: -------------------------------------------------------------------------------- 1 | package DifferenceOfSquares; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use List::Util qw; 11 | 12 | sub square_of_sum ($number) { 13 | return sum( 1 .. $number )**2; 14 | } 15 | 16 | sub sum_of_squares ($number) { 17 | return sum( map { $_**2 } 1 .. $number ); 18 | } 19 | 20 | sub difference_of_squares ($number) { 21 | return square_of_sum($number) - sum_of_squares($number); 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/.meta/solutions/t/difference-of-squares.t: -------------------------------------------------------------------------------- 1 | ../../../t/difference-of-squares.t -------------------------------------------------------------------------------- /exercises/practice/difference-of-squares/lib/DifferenceOfSquares.pm: -------------------------------------------------------------------------------- 1 | package DifferenceOfSquares; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub square_of_sum ($number) { 9 | return undef; 10 | } 11 | 12 | sub sum_of_squares ($number) { 13 | return undef; 14 | } 15 | 16 | sub difference_of_squares ($number) { 17 | return undef; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /exercises/practice/dnd-character/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | After weeks of anticipation, you and your friends get together for your very first game of [Dungeons & Dragons][dnd] (D&D). 4 | Since this is the first session of the game, each player has to generate a character to play with. 5 | The character's abilities are determined by rolling 6-sided dice, but where _are_ the dice? 6 | With a shock, you realize that your friends are waiting for _you_ to produce the dice; after all it was your idea to play D&D! 7 | Panicking, you realize you forgot to bring the dice, which would mean no D&D game. 8 | As you have some basic coding skills, you quickly come up with a solution: you'll write a program to simulate dice rolls. 9 | 10 | [dnd]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons 11 | -------------------------------------------------------------------------------- /exercises/practice/dnd-character/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/DndCharacter.pm" 8 | ], 9 | "test": [ 10 | "t/dnd-character.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/DndCharacter.pm" 14 | ] 15 | }, 16 | "blurb": "Randomly generate Dungeons & Dragons characters.", 17 | "source": "Simon Shine, Erik Schierboom", 18 | "source_url": "https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/dnd-character/.meta/solutions/t/dnd-character.t: -------------------------------------------------------------------------------- 1 | ../../../t/dnd-character.t -------------------------------------------------------------------------------- /exercises/practice/dnd-character/lib/DndCharacter.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class DndCharacter; 5 | 6 | # implement the DndCharacter class 7 | 8 | 1; 9 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/EliudsEggs.pm" 8 | ], 9 | "test": [ 10 | "t/eliuds-eggs.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/EliudsEggs.pm" 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/solutions/lib/EliudsEggs.pm: -------------------------------------------------------------------------------- 1 | package EliudsEggs; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub egg_count ($number) { 11 | my $count = 0; 12 | while ( $number > 0 ) { 13 | $count += $number & 1; 14 | $number >>= 1; 15 | } 16 | return $count; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /exercises/practice/eliuds-eggs/.meta/solutions/t/eliuds-eggs.t: -------------------------------------------------------------------------------- 1 | ../../../t/eliuds-eggs.t -------------------------------------------------------------------------------- /exercises/practice/eliuds-eggs/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: egg_count 2 | properties: 3 | eggCount: 4 | test: |- 5 | use Data::Dmp; 6 | sprintf(<<'END', $case->{input}{number}, $case->{expected}, dmp($case->{description})); 7 | is( 8 | egg_count(%d), 9 | %s, 10 | %s, 11 | ); 12 | END 13 | 14 | example: |- 15 | sub egg_count ($number) { 16 | my $count = 0; 17 | while ($number > 0) { 18 | $count += $number & 1; 19 | $number >>= 1; 20 | } 21 | return $count; 22 | } 23 | 24 | stub: |- 25 | sub egg_count ($number) { 26 | return undef; 27 | } 28 | -------------------------------------------------------------------------------- /exercises/practice/eliuds-eggs/lib/EliudsEggs.pm: -------------------------------------------------------------------------------- 1 | package EliudsEggs; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub egg_count ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/etl/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "darksuji", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/ETL.pm" 14 | ], 15 | "test": [ 16 | "t/etl.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/ETL.pm" 20 | ] 21 | }, 22 | "blurb": "Change the data format for scoring a game to more easily add other languages.", 23 | "source": "Based on an exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 24 | "source_url": "https://turing.edu" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/etl/.meta/solutions/lib/ETL.pm: -------------------------------------------------------------------------------- 1 | package ETL; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub transform ($data) { 11 | return { 12 | map { 13 | my $val = $_; 14 | map { lc($_) => $val } @{ $data->{$_} } 15 | } keys %{$data} 16 | }; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /exercises/practice/etl/.meta/solutions/t/etl.t: -------------------------------------------------------------------------------- 1 | ../../../t/etl.t -------------------------------------------------------------------------------- /exercises/practice/etl/lib/ETL.pm: -------------------------------------------------------------------------------- 1 | package ETL; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub transform ($data) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/food-chain/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "autark", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/FoodChain.pm" 14 | ], 15 | "test": [ 16 | "t/food-chain.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/FoodChain.pm" 20 | ] 21 | }, 22 | "blurb": "Generate the lyrics of the song 'I Know an Old Lady Who Swallowed a Fly'.", 23 | "source": "Wikipedia", 24 | "source_url": "https://en.wikipedia.org/wiki/There_Was_an_Old_Lady_Who_Swallowed_a_Fly" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/food-chain/.meta/solutions/t/food-chain.t: -------------------------------------------------------------------------------- 1 | ../../../t/food-chain.t -------------------------------------------------------------------------------- /exercises/practice/food-chain/lib/FoodChain.pm: -------------------------------------------------------------------------------- 1 | package FoodChain; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub recite ( $start, $end ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "bentglasstube" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Gigasecond.pm" 13 | ], 14 | "test": [ 15 | "t/gigasecond.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Gigasecond.pm" 19 | ] 20 | }, 21 | "blurb": "Given a moment, determine the moment that would be after a gigasecond has passed.", 22 | "source": "Chapter 9 in Chris Pine's online Learn to Program tutorial.", 23 | "source_url": "https://pine.fm/LearnToProgram/?Chapter=09" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/gigasecond/.meta/solutions/lib/Gigasecond.pm: -------------------------------------------------------------------------------- 1 | package Gigasecond; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use Time::Piece; 11 | 12 | sub add_gigasecond { 13 | ( Time::Piece->strptime( shift, '%Y-%m-%dT%T' ) + 10**9 )->datetime; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /exercises/practice/gigasecond/.meta/solutions/t/gigasecond.t: -------------------------------------------------------------------------------- 1 | ../../../t/gigasecond.t -------------------------------------------------------------------------------- /exercises/practice/gigasecond/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: add_gigasecond 2 | properties: 3 | add: 4 | test: |- 5 | use Data::Dmp; 6 | sprintf(<<'END', map {dmp($_)} $case->{input}{moment}, @{$case}{qw}); 7 | is( 8 | add_gigasecond(%s), 9 | %s, 10 | %s, 11 | ); 12 | END 13 | 14 | example: | 15 | use Time::Piece; 16 | 17 | sub add_gigasecond { 18 | (Time::Piece->strptime(shift, '%Y-%m-%dT%T') + 10**9)->datetime; 19 | } 20 | 21 | stub: | 22 | sub add_gigasecond ($time) { 23 | return undef; 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/gigasecond/lib/Gigasecond.pm: -------------------------------------------------------------------------------- 1 | package Gigasecond; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub add_gigasecond ($time) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/grade-school/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bentglasstube" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/GradeSchool.pm" 13 | ], 14 | "test": [ 15 | "t/grade-school.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/GradeSchool.pm" 19 | ] 20 | }, 21 | "blurb": "Given students' names along with the grade that they are in, create a roster for the school.", 22 | "source": "A pairing session with Phil Battos at gSchool" 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/grade-school/.meta/solutions/lib/GradeSchool.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use experimental qw; 4 | use Feature::Compat::Class; 5 | 6 | class GradeSchool; 7 | 8 | field %grades; 9 | 10 | method add ( $student, $grade ) { 11 | my %students = map { map { $_ => 1 } @{$_} } values %grades; 12 | 13 | if ( $students{$student} ) { 14 | return 0; 15 | } 16 | 17 | $grades{$grade} = [ sort @{ $grades{$grade} // [] }, $student ]; 18 | 19 | return 1; 20 | } 21 | 22 | method roster ( $grade = undef ) { 23 | if ( defined $grade ) { 24 | return $grades{$grade} // []; 25 | } 26 | return [ map { @{ $grades{$_} } } sort( keys %grades ) ]; 27 | } 28 | 29 | 1; 30 | -------------------------------------------------------------------------------- /exercises/practice/grade-school/.meta/solutions/t/grade-school.t: -------------------------------------------------------------------------------- 1 | ../../../t/grade-school.t -------------------------------------------------------------------------------- /exercises/practice/grade-school/lib/GradeSchool.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class GradeSchool; 5 | 6 | method add ( $student, $grade ) { 7 | return undef; 8 | } 9 | 10 | method roster ( $grade = undef ) { 11 | return undef; 12 | } 13 | 14 | 1; 15 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "darksuji", 7 | "dnmfarrell", 8 | "kappa", 9 | "kentfredric", 10 | "kytrinyx", 11 | "m-dango", 12 | "rfilipo", 13 | "sshine" 14 | ], 15 | "files": { 16 | "solution": [ 17 | "lib/Grains.pm" 18 | ], 19 | "test": [ 20 | "t/grains.t" 21 | ], 22 | "example": [ 23 | ".meta/solutions/lib/Grains.pm" 24 | ] 25 | }, 26 | "blurb": "Calculate the number of grains of wheat on a chessboard given that the number on each square doubles.", 27 | "source": "The CodeRanch Cattle Drive, Assignment 6", 28 | "source_url": "https://web.archive.org/web/20240908084142/https://coderanch.com/wiki/718824/Grains" 29 | } 30 | -------------------------------------------------------------------------------- /exercises/practice/grains/.meta/solutions/lib/Grains.pm: -------------------------------------------------------------------------------- 1 | package Grains; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use bignum; 11 | use List::Util qw(sum); 12 | 13 | sub grains_on_square ($square) { 14 | if ( $square < 1 || $square > 64 ) { 15 | die 'square must be between 1 and 64'; 16 | } 17 | return 2**( $square - 1 ); 18 | } 19 | 20 | sub total_grains () { 21 | return sum map { grains_on_square($_) } 1 .. 64; 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /exercises/practice/grains/.meta/solutions/t/grains.t: -------------------------------------------------------------------------------- 1 | ../../../t/grains.t -------------------------------------------------------------------------------- /exercises/practice/grains/lib/Grains.pm: -------------------------------------------------------------------------------- 1 | package Grains; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub grains_on_square ($square) { 9 | return undef; 10 | } 11 | 12 | sub total_grains () { 13 | return undef; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /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/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Your body is made up of cells that contain DNA. 4 | Those cells regularly wear out and need replacing, which they achieve by dividing into daughter cells. 5 | In fact, the average human body experiences about 10 quadrillion cell divisions in a lifetime! 6 | 7 | When cells divide, their DNA replicates too. 8 | Sometimes during this process mistakes happen and single pieces of DNA get encoded with the incorrect information. 9 | If we compare two strands of DNA and count the differences between them, we can see how many mistakes occurred. 10 | This is known as the "Hamming distance". 11 | 12 | The Hamming distance is useful in many areas of science, not just biology, so it's a nice phrase to be familiar with :) 13 | -------------------------------------------------------------------------------- /exercises/practice/hamming/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kotp", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo", 10 | "yanick" 11 | ], 12 | "files": { 13 | "solution": [ 14 | "lib/Hamming.pm" 15 | ], 16 | "test": [ 17 | "t/hamming.t" 18 | ], 19 | "example": [ 20 | ".meta/solutions/lib/Hamming.pm" 21 | ] 22 | }, 23 | "blurb": "Calculate the Hamming distance between two DNA strands.", 24 | "source": "The Calculating Point Mutations problem at Rosalind", 25 | "source_url": "https://rosalind.info/problems/hamm/" 26 | } 27 | -------------------------------------------------------------------------------- /exercises/practice/hamming/.meta/solutions/lib/Hamming.pm: -------------------------------------------------------------------------------- 1 | package Hamming; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub hamming_distance ( $strand1, $strand2 ) { 11 | if ( length $strand1 != length $strand2 ) { 12 | die 'left and right strands must be of equal length'; 13 | } 14 | return scalar grep { [ split //, $strand1 ]->[$_] ne [ split //, $strand2 ]->[$_] } 0 .. length($strand1) - 1; 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /exercises/practice/hamming/.meta/solutions/t/hamming.t: -------------------------------------------------------------------------------- 1 | ../../../t/hamming.t -------------------------------------------------------------------------------- /exercises/practice/hamming/lib/Hamming.pm: -------------------------------------------------------------------------------- 1 | package Hamming; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub hamming_distance ( $strand1, $strand2 ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "contributors": [ 6 | "kotp", 7 | "rfilipo" 8 | ], 9 | "files": { 10 | "solution": [ 11 | "lib/HelloWorld.pm" 12 | ], 13 | "test": [ 14 | "t/hello-world.t" 15 | ], 16 | "example": [ 17 | ".meta/solutions/lib/HelloWorld.pm" 18 | ] 19 | }, 20 | "blurb": "Exercism's classic introductory exercise. Just say \"Hello, World!\".", 21 | "source": "This is an exercise to introduce users to using Exercism", 22 | "source_url": "https://en.wikipedia.org/wiki/%22Hello,_world!%22_program" 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/solutions/lib/HelloWorld.pm: -------------------------------------------------------------------------------- 1 | # Declare package 'HelloWorld' 2 | package HelloWorld; 3 | 4 | use strict; 5 | use warnings; 6 | use experimental qw; 7 | 8 | use Exporter qw; 9 | our @EXPORT_OK = qw; 10 | 11 | sub hello () { 12 | return 'Hello, World!'; 13 | } 14 | 15 | 1; 16 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/solutions/t/hello-world.t: -------------------------------------------------------------------------------- 1 | ../../../t/hello-world.t -------------------------------------------------------------------------------- /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/lib/HelloWorld.pm: -------------------------------------------------------------------------------- 1 | # Declare package 'HelloWorld' 2 | package HelloWorld; 3 | 4 | use v5.40; 5 | 6 | use Exporter qw; 7 | our @EXPORT_OK = qw; 8 | 9 | sub hello () { 10 | return 'Goodbye, Mars!'; 11 | } 12 | 13 | 1; 14 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/t/hello-world.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use Test2::V0; 3 | 4 | use FindBin qw<$Bin>; 5 | use lib "$Bin/../lib", "$Bin/../local/lib/perl5"; # Find modules in the same dir as this file. 6 | 7 | use HelloWorld qw; 8 | 9 | # Run the 'is' sub from 'Test2::V0' with three arguments. # begin: af9ffe10-dc13-42d8-a742-e7bdafac449d 10 | is( 11 | hello(), # Run the 'hello' sub imported from the module. 12 | "Hello, World!", # The expected result to compare with 'hello'. 13 | "Say Hi!" # The test description. 14 | ); # end: af9ffe10-dc13-42d8-a742-e7bdafac449d 15 | 16 | done_testing; 17 | -------------------------------------------------------------------------------- /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, 6 | teal: 008080, navy: 000080). 7 | 8 | The program should handle invalid hexadecimal strings. 9 | -------------------------------------------------------------------------------- /exercises/practice/hexadecimal/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "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).", 3 | "authors": [ 4 | "bistik" 5 | ], 6 | "contributors": [ 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "Hexadecimal.pm" 14 | ], 15 | "test": [ 16 | "hexadecimal.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/Hexadecimal.pm" 20 | ] 21 | }, 22 | "source": "All of Computer Science", 23 | "source_url": "http://www.wolframalpha.com/examples/NumberBases.html" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/hexadecimal/.meta/solutions/hexadecimal.t: -------------------------------------------------------------------------------- 1 | ../../hexadecimal.t -------------------------------------------------------------------------------- /exercises/practice/hexadecimal/Hexadecimal.pm: -------------------------------------------------------------------------------- 1 | package Hexadecimal; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ( $class, $hexadecimal ) = @_; 8 | 9 | return undef; 10 | } 11 | 12 | sub to_decimal { 13 | my $self = shift; 14 | 15 | return undef; 16 | } 17 | 18 | __PACKAGE__; 19 | -------------------------------------------------------------------------------- /exercises/practice/house/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/House.pm" 13 | ], 14 | "test": [ 15 | "t/house.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/House.pm" 19 | ] 20 | }, 21 | "blurb": "Output the nursery rhyme 'This is the House that Jack Built'.", 22 | "source": "British nursery rhyme", 23 | "source_url": "https://en.wikipedia.org/wiki/This_Is_The_House_That_Jack_Built" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/house/.meta/solutions/t/house.t: -------------------------------------------------------------------------------- 1 | ../../../t/house.t -------------------------------------------------------------------------------- /exercises/practice/house/lib/House.pm: -------------------------------------------------------------------------------- 1 | package House; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub recite ( $start, $end ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/Isogram.pm" 8 | ], 9 | "test": [ 10 | "t/isogram.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/Isogram.pm" 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/solutions/lib/Isogram.pm: -------------------------------------------------------------------------------- 1 | package Isogram; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use List::Util qw(uniq); 11 | 12 | sub is_isogram ($phrase) { 13 | my @letters = grep {/[[:alpha:]]/} split "", lc $phrase; 14 | return scalar(@letters) == scalar( uniq @letters ); 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.meta/solutions/t/isogram.t: -------------------------------------------------------------------------------- 1 | ../../../t/isogram.t -------------------------------------------------------------------------------- /exercises/practice/isogram/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: is_isogram 2 | properties: 3 | isIsogram: 4 | test: |- 5 | use Data::Dmp; 6 | sprintf(<<'END', dmp($case->{input}{phrase}), $case->{expected} ? ('T', '# True') : ('DF', '# Defined but False'), dmp($case->{description})); 7 | is( 8 | is_isogram(%s), 9 | %s, %s 10 | %s 11 | ); 12 | END 13 | 14 | stub: |- 15 | sub is_isogram ($phrase) { 16 | return undef; 17 | } 18 | 19 | example: |- 20 | use List::Util qw(uniq); 21 | 22 | sub is_isogram ($phrase) { 23 | my @letters = grep { /[[:alpha:]]/ } split "", lc $phrase; 24 | return scalar(@letters) == scalar(uniq @letters); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /exercises/practice/isogram/lib/Isogram.pm: -------------------------------------------------------------------------------- 1 | package Isogram; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub is_isogram ($phrase) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/KindergartenGarden.pm" 13 | ], 14 | "test": [ 15 | "t/kindergarten-garden.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/KindergartenGarden.pm" 19 | ] 20 | }, 21 | "blurb": "Given a diagram, determine which plants each child in the kindergarten class is responsible for.", 22 | "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 23 | "source_url": "https://turing.edu" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/kindergarten-garden/.meta/solutions/lib/KindergartenGarden.pm: -------------------------------------------------------------------------------- 1 | package KindergartenGarden; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub plants ( $diagram, $student ) { 11 | my %plants = ( 12 | C => 'clover', 13 | G => 'grass', 14 | R => 'radishes', 15 | V => 'violets', 16 | ); 17 | my @rows = split /\n/, $diagram; 18 | 19 | my $i = 0; 20 | for ( 'A' .. 'Z' ) { 21 | last if substr( $student, 0, 1 ) eq $_; 22 | $i += 2; 23 | } 24 | 25 | return [ map { $plants{$_} } map { split //, substr $_, $i, 2 } @rows ]; 26 | 27 | } 28 | 29 | 1; 30 | -------------------------------------------------------------------------------- /exercises/practice/kindergarten-garden/.meta/solutions/t/kindergarten-garden.t: -------------------------------------------------------------------------------- 1 | ../../../t/kindergarten-garden.t -------------------------------------------------------------------------------- /exercises/practice/kindergarten-garden/lib/KindergartenGarden.pm: -------------------------------------------------------------------------------- 1 | package KindergartenGarden; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub plants ( $diagram, $student ) { 9 | my %plants = ( 10 | C => 'clover', 11 | G => 'grass', 12 | R => 'radishes', 13 | V => 'violets', 14 | ); 15 | 16 | return undef; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "JohnMertz" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/Knapsack.pm" 8 | ], 9 | "test": [ 10 | "t/knapsack.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/Knapsack.pm" 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/.meta/solutions/t/knapsack.t: -------------------------------------------------------------------------------- 1 | ../../../t/knapsack.t -------------------------------------------------------------------------------- /exercises/practice/knapsack/lib/Knapsack.pm: -------------------------------------------------------------------------------- 1 | package Knapsack; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub maximum_value ( $items, $weight ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "dogsleg", 7 | "kytrinyx", 8 | "m-dango", 9 | "petertseng", 10 | "rfilipo" 11 | ], 12 | "files": { 13 | "solution": [ 14 | "lib/LargestSeriesProduct.pm" 15 | ], 16 | "test": [ 17 | "t/largest-series-product.t" 18 | ], 19 | "example": [ 20 | ".meta/solutions/lib/LargestSeriesProduct.pm" 21 | ] 22 | }, 23 | "blurb": "Given a string of digits, calculate the largest product for a contiguous substring of digits of length n.", 24 | "source": "A variation on Problem 8 at Project Euler", 25 | "source_url": "https://projecteuler.net/problem=8" 26 | } 27 | -------------------------------------------------------------------------------- /exercises/practice/largest-series-product/.meta/solutions/t/largest-series-product.t: -------------------------------------------------------------------------------- 1 | ../../../t/largest-series-product.t -------------------------------------------------------------------------------- /exercises/practice/largest-series-product/lib/LargestSeriesProduct.pm: -------------------------------------------------------------------------------- 1 | package LargestSeriesProduct; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub largest_product ( $digits, $span ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "dnmfarrell" 4 | ], 5 | "contributors": [ 6 | "bistik", 7 | "darksuji", 8 | "kotp", 9 | "kytrinyx", 10 | "m-dango", 11 | "rfilipo" 12 | ], 13 | "files": { 14 | "solution": [ 15 | "lib/Leap.pm" 16 | ], 17 | "test": [ 18 | "t/leap.t" 19 | ], 20 | "example": [ 21 | ".meta/solutions/lib/Leap.pm" 22 | ] 23 | }, 24 | "blurb": "Determine whether a given year is a leap year.", 25 | "source": "CodeRanch Cattle Drive, Assignment 3", 26 | "source_url": "https://web.archive.org/web/20240907033714/https://coderanch.com/t/718816/Leap" 27 | } 28 | -------------------------------------------------------------------------------- /exercises/practice/leap/.meta/solutions/lib/Leap.pm: -------------------------------------------------------------------------------- 1 | # Declare package 'Leap' 2 | package Leap; 3 | 4 | use strict; 5 | use warnings; 6 | use experimental qw; 7 | 8 | use Exporter qw; 9 | our @EXPORT_OK = qw; 10 | 11 | sub is_leap_year ($year) { 12 | return $year % 4 == 0 && $year % 100 != 0 || $year % 400 == 0; 13 | } 14 | 15 | 1; 16 | -------------------------------------------------------------------------------- /exercises/practice/leap/.meta/solutions/t/leap.t: -------------------------------------------------------------------------------- 1 | ../../../t/leap.t -------------------------------------------------------------------------------- /exercises/practice/leap/lib/Leap.pm: -------------------------------------------------------------------------------- 1 | # Declare package 'Leap' 2 | package Leap; 3 | 4 | use v5.40; 5 | 6 | use Exporter qw; 7 | our @EXPORT_OK = qw; 8 | 9 | sub is_leap_year ($year) { 10 | return undef; # Replace this with your own code to pass the tests. 11 | } 12 | 13 | 1; 14 | -------------------------------------------------------------------------------- /exercises/practice/linked-list/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You are working on a project to develop a train scheduling system for a busy railway network. 4 | 5 | You've been asked to develop a prototype for the train routes in the scheduling system. 6 | Each route consists of a sequence of train stations that a given train stops at. 7 | -------------------------------------------------------------------------------- /exercises/practice/linked-list/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "szabgab" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "Deque.pm" 13 | ], 14 | "test": [ 15 | "deque.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/Deque.pm" 19 | ] 20 | }, 21 | "blurb": "Implement a doubly linked list.", 22 | "source": "Classic computer science topic" 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/linked-list/.meta/solutions/deque.t: -------------------------------------------------------------------------------- 1 | ../../deque.t -------------------------------------------------------------------------------- /exercises/practice/linked-list/Deque.pm: -------------------------------------------------------------------------------- 1 | package Deque; 2 | use strict; 3 | use warnings; 4 | 5 | sub new { 6 | my ($class) = @_; 7 | 8 | return undef; 9 | } 10 | 11 | sub push { 12 | my ( $self, $value ) = @_; 13 | 14 | return undef; 15 | } 16 | 17 | sub pop { 18 | my ($self) = @_; 19 | 20 | return undef; 21 | } 22 | 23 | sub shift { 24 | my ($self) = @_; 25 | 26 | return undef; 27 | } 28 | 29 | sub unshift { 30 | my ( $self, $value ) = @_; 31 | 32 | return undef; 33 | } 34 | 35 | package Element; 36 | use strict; 37 | use warnings; 38 | 39 | sub new { 40 | my ( $class, %data ) = @_; 41 | 42 | return undef; 43 | } 44 | 45 | 1; 46 | 47 | -------------------------------------------------------------------------------- /exercises/practice/list-ops/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [], 3 | "contributors": [ 4 | "kytrinyx", 5 | "m-dango", 6 | "rfilipo", 7 | "glennj" 8 | ], 9 | "files": { 10 | "solution": [ 11 | "lib/ListOps.pm" 12 | ], 13 | "test": [ 14 | "t/list-ops.t" 15 | ], 16 | "example": [ 17 | ".meta/solutions/lib/ListOps.pm" 18 | ] 19 | }, 20 | "blurb": "Implement basic list operations." 21 | } 22 | -------------------------------------------------------------------------------- /exercises/practice/list-ops/.meta/solutions/t/list-ops.t: -------------------------------------------------------------------------------- 1 | ../../../t/list-ops.t -------------------------------------------------------------------------------- /exercises/practice/list-ops/lib/ListOps.pm: -------------------------------------------------------------------------------- 1 | package ListOps; 2 | 3 | use v5.40; 4 | 5 | sub append ( $list1, $list2 ) { 6 | return undef; 7 | } 8 | 9 | sub concat ($lists) { 10 | return undef; 11 | } 12 | 13 | sub filter ( $func, $list ) { 14 | return undef; 15 | } 16 | 17 | sub length ($list) { 18 | return undef; 19 | } 20 | 21 | sub map ( $func, $list ) { 22 | return undef; 23 | } 24 | 25 | sub foldl ( $func, $initial, $list ) { 26 | return undef; 27 | } 28 | 29 | sub foldr ( $func, $initial, $list ) { 30 | return undef; 31 | } 32 | 33 | sub reverse ($list) { 34 | return undef; 35 | } 36 | 37 | 1; 38 | -------------------------------------------------------------------------------- /exercises/practice/luhn/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "alexkalderimis", 7 | "kytrinyx", 8 | "m-dango", 9 | "pgraemer", 10 | "rfilipo" 11 | ], 12 | "files": { 13 | "solution": [ 14 | "lib/Luhn.pm" 15 | ], 16 | "test": [ 17 | "t/luhn.t" 18 | ], 19 | "example": [ 20 | ".meta/solutions/lib/Luhn.pm" 21 | ] 22 | }, 23 | "blurb": "Given a number determine whether or not it is valid per the Luhn formula.", 24 | "source": "The Luhn Algorithm on Wikipedia", 25 | "source_url": "https://en.wikipedia.org/wiki/Luhn_algorithm" 26 | } 27 | -------------------------------------------------------------------------------- /exercises/practice/luhn/.meta/solutions/t/luhn.t: -------------------------------------------------------------------------------- 1 | ../../../t/luhn.t -------------------------------------------------------------------------------- /exercises/practice/luhn/lib/Luhn.pm: -------------------------------------------------------------------------------- 1 | package Luhn; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub is_luhn_valid ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "glennj" 4 | ], 5 | "contributors": [ 6 | "m-dango" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "lib/MatchingBrackets.pm" 11 | ], 12 | "test": [ 13 | "t/matching-brackets.t" 14 | ], 15 | "example": [ 16 | ".meta/solutions/lib/MatchingBrackets.pm" 17 | ] 18 | }, 19 | "blurb": "Make sure the brackets and braces all match.", 20 | "source": "Ginna Baker" 21 | } 22 | -------------------------------------------------------------------------------- /exercises/practice/matching-brackets/.meta/solutions/t/matching-brackets.t: -------------------------------------------------------------------------------- 1 | ../../../t/matching-brackets.t -------------------------------------------------------------------------------- /exercises/practice/matching-brackets/lib/MatchingBrackets.pm: -------------------------------------------------------------------------------- 1 | package MatchingBrackets; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub has_matching_brackets ($text) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/matrix/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Matrix.pm" 13 | ], 14 | "test": [ 15 | "t/matrix.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Matrix.pm" 19 | ] 20 | }, 21 | "blurb": "Given a string representing a matrix of numbers, return the rows and columns of that matrix.", 22 | "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 23 | "source_url": "https://turing.edu" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/matrix/.meta/solutions/lib/Matrix.pm: -------------------------------------------------------------------------------- 1 | package Matrix; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub extract_row ( $matrix, $row ) { 11 | return [ split / /, [ split /\n/, $matrix ]->[ $row - 1 ] ]; 12 | } 13 | 14 | sub extract_column ( $matrix, $column ) { 15 | return [ map { [ split / /, $_ ]->[ $column - 1 ] } split /\n/, $matrix ]; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /exercises/practice/matrix/.meta/solutions/t/matrix.t: -------------------------------------------------------------------------------- 1 | ../../../t/matrix.t -------------------------------------------------------------------------------- /exercises/practice/matrix/lib/Matrix.pm: -------------------------------------------------------------------------------- 1 | package Matrix; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub extract_row ( $matrix, $row ) { 9 | return undef; 10 | } 11 | 12 | sub extract_column ( $matrix, $column ) { 13 | return undef; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /exercises/practice/meetup/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "dnmfarrell" 4 | ], 5 | "contributors": [ 6 | "bistik", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/Meetup.pm" 14 | ], 15 | "test": [ 16 | "t/meetup.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/Meetup.pm" 20 | ] 21 | }, 22 | "blurb": "Calculate the date of meetups.", 23 | "source": "Jeremy Hinegardner mentioned a Boulder meetup that happens on the Wednesteenth of every month" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/meetup/.meta/solutions/t/meetup.t: -------------------------------------------------------------------------------- 1 | ../../../t/meetup.t -------------------------------------------------------------------------------- /exercises/practice/meetup/lib/Meetup.pm: -------------------------------------------------------------------------------- 1 | package Meetup; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub meetup ($desc) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/micro-blog/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/MicroBlog.pm" 8 | ], 9 | "test": [ 10 | "t/micro-blog.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/MicroBlog.pm" 14 | ] 15 | }, 16 | "blurb": "Given an input string, truncate it to 5 characters." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/micro-blog/.meta/solutions/lib/MicroBlog.pm: -------------------------------------------------------------------------------- 1 | package MicroBlog; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use Encode; 11 | 12 | sub truncate_post ($utf8_bytes) { 13 | return substr( Encode::decode( 'UTF-8', $utf8_bytes ), 0, 5 ); 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /exercises/practice/micro-blog/.meta/solutions/t/micro-blog.t: -------------------------------------------------------------------------------- 1 | ../../../t/micro-blog.t -------------------------------------------------------------------------------- /exercises/practice/micro-blog/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: truncate_post 2 | 3 | properties: 4 | truncate: 5 | test: |- 6 | use Data::Dmp; 7 | use Encode; 8 | 9 | sprintf(<<'END', dmp(Encode::encode('UTF-8', $case->{input}{phrase})), $case->{expected}, $case->{description}); 10 | is( 11 | truncate_post(%s), 12 | '%s', 13 | '%s', 14 | ); 15 | END 16 | 17 | 18 | example: |- 19 | use Encode; 20 | 21 | sub truncate_post ($utf8_bytes) { 22 | return substr(Encode::decode('UTF-8', $utf8_bytes), 0, 5); 23 | } 24 | 25 | stub: |- 26 | sub truncate_post ($utf8_bytes) { 27 | return undef; 28 | } 29 | -------------------------------------------------------------------------------- /exercises/practice/micro-blog/lib/MicroBlog.pm: -------------------------------------------------------------------------------- 1 | package MicroBlog; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub truncate_post ($utf8_bytes) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "autark" 4 | ], 5 | "contributors": [ 6 | "bistik", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/Minesweeper.pm" 14 | ], 15 | "test": [ 16 | "t/minesweeper.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/Minesweeper.pm" 20 | ] 21 | }, 22 | "blurb": "Add the numbers to a minesweeper board." 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/minesweeper/.meta/solutions/t/minesweeper.t: -------------------------------------------------------------------------------- 1 | ../../../t/minesweeper.t -------------------------------------------------------------------------------- /exercises/practice/minesweeper/lib/Minesweeper.pm: -------------------------------------------------------------------------------- 1 | package Minesweeper; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub annotate ($minefield) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/nucleotide-count/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bentglasstube" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/NucleotideCount.pm" 13 | ], 14 | "test": [ 15 | "t/nucleotide-count.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/NucleotideCount.pm" 19 | ] 20 | }, 21 | "blurb": "Given a DNA string, compute how many times each nucleotide occurs in the string.", 22 | "source": "The Calculating DNA Nucleotides_problem at Rosalind", 23 | "source_url": "https://rosalind.info/problems/dna/" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/nucleotide-count/.meta/solutions/lib/NucleotideCount.pm: -------------------------------------------------------------------------------- 1 | package NucleotideCount; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub count_nucleotides ($strand) { 11 | die 'Invalid nucleotide in strand' if $strand =~ /[^ACGT]/; 12 | my %count = qw(A 0 C 0 G 0 T 0); 13 | for ( split //, $strand ) { 14 | $count{$_}++; 15 | } 16 | return \%count; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /exercises/practice/nucleotide-count/.meta/solutions/t/nucleotide-count.t: -------------------------------------------------------------------------------- 1 | ../../../t/nucleotide-count.t -------------------------------------------------------------------------------- /exercises/practice/nucleotide-count/lib/NucleotideCount.pm: -------------------------------------------------------------------------------- 1 | package NucleotideCount; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub count_nucleotides ($strand) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/ocr-numbers/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/OCRNumbers.pm" 13 | ], 14 | "test": [ 15 | "t/ocr-numbers.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/OCRNumbers.pm" 19 | ] 20 | }, 21 | "blurb": "Given a 3 x 4 grid of pipes, underscores, and spaces, determine which number is represented, or whether it is garbled.", 22 | "source": "Inspired by the Bank OCR kata", 23 | "source_url": "https://codingdojo.org/kata/BankOCR/" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/ocr-numbers/.meta/solutions/t/ocr-numbers.t: -------------------------------------------------------------------------------- 1 | ../../../t/ocr-numbers.t -------------------------------------------------------------------------------- /exercises/practice/ocr-numbers/lib/OCRNumbers.pm: -------------------------------------------------------------------------------- 1 | package OCRNumbers; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub convert_ocr ($string) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/palindrome-products/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/PalindromeProducts.pm" 13 | ], 14 | "test": [ 15 | "t/palindrome-products.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/PalindromeProducts.pm" 19 | ] 20 | }, 21 | "blurb": "Detect palindrome products in a given range.", 22 | "source": "Problem 4 at Project Euler", 23 | "source_url": "https://projecteuler.net/problem=4" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/palindrome-products/.meta/solutions/t/palindrome-products.t: -------------------------------------------------------------------------------- 1 | ../../../t/palindrome-products.t -------------------------------------------------------------------------------- /exercises/practice/palindrome-products/lib/PalindromeProducts.pm: -------------------------------------------------------------------------------- 1 | package PalindromeProducts; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub smallest_palindrome ( $min, $max ) { 9 | return undef; 10 | } 11 | 12 | sub largest_palindrome ( $min, $max ) { 13 | return undef; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/Pangram.pm" 8 | ], 9 | "test": [ 10 | "t/pangram.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/Pangram.pm" 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/solutions/lib/Pangram.pm: -------------------------------------------------------------------------------- 1 | package Pangram; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | use List::Util qw(uniq); 11 | 12 | sub is_pangram ($text) { 13 | my @letters = grep {/[[:alpha:]]/} split "", lc $text; 14 | return scalar( uniq @letters ) == 26; 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /exercises/practice/pangram/.meta/solutions/t/pangram.t: -------------------------------------------------------------------------------- 1 | ../../../t/pangram.t -------------------------------------------------------------------------------- /exercises/practice/pangram/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: is_pangram 2 | 3 | properties: 4 | isPangram: 5 | test: |- 6 | use Data::Dmp; 7 | sprintf(<<'END', dmp($case->{input}{sentence}), $case->{expected} ? ('T', '# True') : ('DF', '# Defined but False'), dmp($case->{description})); 8 | is( 9 | is_pangram(%s), 10 | %s, %s 11 | %s 12 | ); 13 | END 14 | 15 | stub: |- 16 | sub is_pangram ($text) { 17 | return undef; 18 | } 19 | 20 | example: |- 21 | use List::Util qw(uniq); 22 | 23 | sub is_pangram ($text) { 24 | my @letters = grep { /[[:alpha:]]/ } split "", lc $text; 25 | return scalar(uniq @letters) == 26; 26 | } 27 | -------------------------------------------------------------------------------- /exercises/practice/pangram/lib/Pangram.pm: -------------------------------------------------------------------------------- 1 | package Pangram; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub is_pangram ($text) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/pascals-triangle/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "dnmfarrell", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/PascalsTriangle.pm" 14 | ], 15 | "test": [ 16 | "t/pascals-triangle.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/PascalsTriangle.pm" 20 | ] 21 | }, 22 | "blurb": "Compute Pascal's triangle up to a given number of rows.", 23 | "source": "Pascal's Triangle at Wolfram Math World", 24 | "source_url": "https://www.wolframalpha.com/input/?i=Pascal%27s+triangle" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/pascals-triangle/.meta/solutions/lib/PascalsTriangle.pm: -------------------------------------------------------------------------------- 1 | package PascalsTriangle; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub pascal_rows ($rows) { 11 | return '' if !$rows; 12 | 13 | my @result = ( [1] ); 14 | for ( my $n = 0;; $n++ ) { 15 | return join "\n", map { join ' ', @$_ } @result if @result == $rows; 16 | push @result, [ 1, ( map { 17 | $result[$n]->[$_] + $result[$n]->[ $_ + 1 ] 18 | } 0 .. $n - 1 ), 1 ]; 19 | } 20 | } 21 | 22 | 1; 23 | -------------------------------------------------------------------------------- /exercises/practice/pascals-triangle/.meta/solutions/t/pascals-triangle.t: -------------------------------------------------------------------------------- 1 | ../../../t/pascals-triangle.t -------------------------------------------------------------------------------- /exercises/practice/pascals-triangle/lib/PascalsTriangle.pm: -------------------------------------------------------------------------------- 1 | package PascalsTriangle; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub pascal_rows ($rows) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/phone-number/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You've joined LinkLine, a leading communications company working to ensure reliable connections for everyone. 4 | The team faces a big challenge: users submit phone numbers in all sorts of formats — dashes, spaces, dots, parentheses, and even prefixes. 5 | Some numbers are valid, while others are impossible to use. 6 | 7 | Your mission is to turn this chaos into order. 8 | You'll clean up valid numbers, formatting them appropriately for use in the system. 9 | At the same time, you'll identify and filter out any invalid entries. 10 | 11 | The success of LinkLine's operations depends on your ability to separate the useful from the unusable. 12 | Are you ready to take on the challenge and keep the connections running smoothly? 13 | -------------------------------------------------------------------------------- /exercises/practice/phone-number/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo", 9 | "yanick" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/PhoneNumber.pm" 14 | ], 15 | "test": [ 16 | "t/phone-number.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/PhoneNumber.pm" 20 | ] 21 | }, 22 | "blurb": "Clean up user-entered phone numbers so that they can be sent SMS messages.", 23 | "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", 24 | "source_url": "https://turing.edu" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/phone-number/.meta/solutions/t/phone-number.t: -------------------------------------------------------------------------------- 1 | ../../../t/phone-number.t -------------------------------------------------------------------------------- /exercises/practice/phone-number/lib/PhoneNumber.pm: -------------------------------------------------------------------------------- 1 | package PhoneNumber; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | my @errors = ( 9 | '11 digits must start with 1', 10 | 'must not be greater than 11 digits', 11 | 'must not be fewer than 10 digits', 12 | 'letters not permitted', 13 | 'punctuations not permitted', 14 | 'area code cannot start with zero', 15 | 'area code cannot start with one', 16 | 'exchange code cannot start with zero', 17 | 'exchange code cannot start with one', 18 | ); 19 | 20 | sub clean_number ($number) { 21 | return undef; 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/PigLatin.pm" 13 | ], 14 | "test": [ 15 | "t/pig-latin.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/PigLatin.pm" 19 | ] 20 | }, 21 | "blurb": "Implement a program that translates from English to Pig Latin.", 22 | "source": "The Pig Latin exercise at Test First Teaching by Ultrasaurus", 23 | "source_url": "https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/pig-latin/.meta/solutions/lib/PigLatin.pm: -------------------------------------------------------------------------------- 1 | package PigLatin; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub translate ($phrase) { 11 | return join( ' ', map { 12 | if (/^(?:[aeiou]|[yx][^aeiou])/) { 13 | "${phrase}ay"; 14 | } 15 | elsif (/^(y|[^aeiou]*qu|[^aeiouy]+)(.+)/) { 16 | "$2${1}ay"; 17 | } 18 | } split /\s+/, $phrase ); 19 | 20 | } 21 | 22 | 1; 23 | -------------------------------------------------------------------------------- /exercises/practice/pig-latin/.meta/solutions/t/pig-latin.t: -------------------------------------------------------------------------------- 1 | ../../../t/pig-latin.t -------------------------------------------------------------------------------- /exercises/practice/pig-latin/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: translate 2 | 3 | properties: 4 | translate: 5 | test: |- 6 | use Data::Dmp; 7 | sprintf(<<~'END', map {dmp $_} $case->{input}{phrase}, $case->@{qw}); 8 | is( 9 | translate(%s), 10 | %s, 11 | %s, 12 | ); 13 | END 14 | 15 | example: | 16 | sub translate ($phrase) { 17 | return join(' ', map { 18 | if (/^(?:[aeiou]|[yx][^aeiou])/) { 19 | "${phrase}ay" 20 | } 21 | elsif (/^(y|[^aeiou]*qu|[^aeiouy]+)(.+)/) { 22 | "$2${1}ay" 23 | } 24 | } split /\s+/, $phrase); 25 | 26 | } 27 | 28 | stub: | 29 | sub translate ($phrase) { 30 | return undef; 31 | } 32 | -------------------------------------------------------------------------------- /exercises/practice/pig-latin/lib/PigLatin.pm: -------------------------------------------------------------------------------- 1 | package PigLatin; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub translate ($phrase) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/point-mutations/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Calculate the Hamming difference between two DNA strands.", 3 | "authors": [ 4 | "bistik" 5 | ], 6 | "contributors": [ 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "DNA.pm" 14 | ], 15 | "test": [ 16 | "dna.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/DNA.pm" 20 | ] 21 | }, 22 | "source": "The Calculating Point Mutations problem at Rosalind", 23 | "source_url": "http://rosalind.info/problems/hamm/" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/point-mutations/.meta/solutions/DNA.pm: -------------------------------------------------------------------------------- 1 | package DNA; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ( $class, $strand ) = @_; 8 | my $self = bless {} => $class; 9 | $self->{strand} = $strand; 10 | $self->{len} = length $strand; 11 | return $self; 12 | } 13 | 14 | sub hamming_distance { 15 | my ( $self, $strand ) = @_; 16 | my $distance; 17 | 18 | my $len = length $strand; 19 | $len = $self->{len} if $len > $self->{len}; 20 | 21 | my @orig = split // => $self->{strand}; 22 | my @inp = split // => $strand; 23 | 24 | foreach my $index ( 0 .. $len - 1 ) { 25 | $distance++ if $orig[$index] ne $inp[$index]; 26 | } 27 | 28 | return $distance || 0; 29 | } 30 | 31 | __PACKAGE__; 32 | -------------------------------------------------------------------------------- /exercises/practice/point-mutations/.meta/solutions/dna.t: -------------------------------------------------------------------------------- 1 | ../../dna.t -------------------------------------------------------------------------------- /exercises/practice/point-mutations/DNA.pm: -------------------------------------------------------------------------------- 1 | package DNA; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ( $class, $strand ) = @_; 8 | 9 | return undef; 10 | } 11 | 12 | sub hamming_distance { 13 | my ( $self, $strand ) = @_; 14 | 15 | return undef; 16 | } 17 | 18 | __PACKAGE__; 19 | -------------------------------------------------------------------------------- /exercises/practice/prime-factors/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "szabgab" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/PrimeFactors.pm" 13 | ], 14 | "test": [ 15 | "t/prime-factors.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/PrimeFactors.pm" 19 | ] 20 | }, 21 | "blurb": "Compute the prime factors of a given natural number.", 22 | "source": "The Prime Factors Kata by Uncle Bob", 23 | "source_url": "https://web.archive.org/web/20221026171801/http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/prime-factors/.meta/solutions/lib/PrimeFactors.pm: -------------------------------------------------------------------------------- 1 | package PrimeFactors; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub factors ($number) { 11 | my @factors; 12 | 13 | for ( my $i = 2; $i * $i <= $number; $i++ ) { 14 | while ( $number % $i == 0 ) { 15 | push @factors, $i; 16 | $number /= $i; 17 | } 18 | } 19 | 20 | push @factors, $number if $number > 1; 21 | 22 | return \@factors; 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /exercises/practice/prime-factors/.meta/solutions/t/prime-factors.t: -------------------------------------------------------------------------------- 1 | ../../../t/prime-factors.t -------------------------------------------------------------------------------- /exercises/practice/prime-factors/lib/PrimeFactors.pm: -------------------------------------------------------------------------------- 1 | package PrimeFactors; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub factors ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/proverb/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Proverb.pm" 13 | ], 14 | "test": [ 15 | "t/proverb.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Proverb.pm" 19 | ] 20 | }, 21 | "blurb": "For want of a horseshoe nail, a kingdom was lost, or so the saying goes. Output the full text of this proverbial rhyme.", 22 | "source": "Wikipedia", 23 | "source_url": "https://en.wikipedia.org/wiki/For_Want_of_a_Nail" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/proverb/.meta/solutions/lib/Proverb.pm: -------------------------------------------------------------------------------- 1 | package Proverb; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub proverb ($items) { 11 | return '' unless $items->@*; 12 | my @proverb; 13 | 14 | my $last_line = "And all for the want of a $items->[0]."; 15 | 16 | while ( @$items > 1 ) { 17 | push @proverb, sprintf( 18 | "For want of a %s the %s was lost.", 19 | shift @$items, 20 | $items->[0] 21 | ); 22 | } 23 | 24 | return join "\n", @proverb, $last_line; 25 | } 26 | 27 | 1; 28 | -------------------------------------------------------------------------------- /exercises/practice/proverb/.meta/solutions/t/proverb.t: -------------------------------------------------------------------------------- 1 | ../../../t/proverb.t -------------------------------------------------------------------------------- /exercises/practice/proverb/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [e974b73e-7851-484f-8d6d-92e07fe742fc] 6 | description = "zero pieces" 7 | 8 | [2fcd5f5e-8b82-4e74-b51d-df28a5e0faa4] 9 | description = "one piece" 10 | 11 | [d9d0a8a1-d933-46e2-aa94-eecf679f4b0e] 12 | description = "two pieces" 13 | 14 | [c95ef757-5e94-4f0d-a6cb-d2083f5e5a83] 15 | description = "three pieces" 16 | 17 | [433fb91c-35a2-4d41-aeab-4de1e82b2126] 18 | description = "full proverb" 19 | 20 | [c1eefa5a-e8d9-41c7-91d4-99fab6d6b9f7] 21 | description = "four pieces modernized" 22 | -------------------------------------------------------------------------------- /exercises/practice/proverb/lib/Proverb.pm: -------------------------------------------------------------------------------- 1 | package Proverb; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub proverb ($items) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo", 9 | "habere-et-dispertire" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/PythagoreanTriplet.pm" 14 | ], 15 | "test": [ 16 | "t/pythagorean-triplet.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/PythagoreanTriplet.pm" 20 | ] 21 | }, 22 | "blurb": "Given an integer N, find all Pythagorean triplets for which a + b + c = N.", 23 | "source": "A variation of Problem 9 from Project Euler", 24 | "source_url": "https://projecteuler.net/problem=9" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/pythagorean-triplet/.meta/solutions/t/pythagorean-triplet.t: -------------------------------------------------------------------------------- 1 | ../../../t/pythagorean-triplet.t -------------------------------------------------------------------------------- /exercises/practice/pythagorean-triplet/lib/PythagoreanTriplet.pm: -------------------------------------------------------------------------------- 1 | package PythagoreanTriplet; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub triplets_with_sum ($sum) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/queen-attack/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "szabgab" 4 | ], 5 | "contributors": [ 6 | "choroba", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/Queen.pm" 14 | ], 15 | "test": [ 16 | "t/queen-attack.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/Queen.pm" 20 | ] 21 | }, 22 | "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.", 23 | "source": "J Dalbey's Programming Practice problems", 24 | "source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/queen-attack/.meta/solutions/lib/Queen.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use experimental qw; 4 | use Feature::Compat::Class; 5 | 6 | class Queen; 7 | 8 | field $row :reader :param; 9 | field $column :reader :param; 10 | 11 | ADJUST { 12 | die 'row not on board' if $row < 0 || $row > 7; 13 | die 'column not on board' if $column < 0 || $column > 7; 14 | } 15 | 16 | method can_attack ($other) { 17 | 18 | # Same row or column 19 | return 1 if $row == $other->row || $column == $other->column; 20 | 21 | # Same diagonal 22 | return 1 if abs( $row - $other->row ) == abs( $column - $other->column ); 23 | 24 | return 0; 25 | } 26 | 27 | 1; 28 | -------------------------------------------------------------------------------- /exercises/practice/queen-attack/.meta/solutions/t/queen-attack.t: -------------------------------------------------------------------------------- 1 | ../../../t/queen-attack.t -------------------------------------------------------------------------------- /exercises/practice/queen-attack/lib/Queen.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class Queen; 5 | 6 | field $row :reader :param; 7 | field $column :reader :param; 8 | 9 | method can_attack ($other) { 10 | return undef; 11 | } 12 | 13 | 1; 14 | -------------------------------------------------------------------------------- /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/solutions/lib/Raindrops.pm: -------------------------------------------------------------------------------- 1 | package Raindrops; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub raindrop ($number) { 11 | my $drops = ''; 12 | 13 | if ( $number % 3 == 0 ) { 14 | $drops .= 'Pling'; 15 | } 16 | if ( $number % 5 == 0 ) { 17 | $drops .= 'Plang'; 18 | } 19 | if ( $number % 7 == 0 ) { 20 | $drops .= 'Plong'; 21 | } 22 | 23 | return $drops || $number; 24 | } 25 | 26 | 1; 27 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.meta/solutions/t/raindrops.t: -------------------------------------------------------------------------------- 1 | ../../../t/raindrops.t -------------------------------------------------------------------------------- /exercises/practice/raindrops/lib/Raindrops.pm: -------------------------------------------------------------------------------- 1 | package Raindrops; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub raindrop ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.docs/instructions.append.md: -------------------------------------------------------------------------------- 1 | # ignore 2 | 3 | ## Unicode and grapheme clusters 4 | 5 | This exercise includes tests with Unicode strings that contain grapheme clusters. 6 | Perl's builtin string processing functions are unsufficient to handle these strings. 7 | Here are a couple of resources to help you: 8 | 9 | * [Treat Unicode strings as grapheme clusters][foy] 10 | * [Extract by Grapheme Instead of Codepoint (regex)][christiansen] 11 | 12 | [foy]: https://www.effectiveperlprogramming.com/2011/06/treat-unicode-strings-as-grapheme-clusters/ 13 | [christiansen]: https://www.perl.com/pub/2012/05/perlunicookbook-extract-by-grapheme-instead-of-codepoint-regex.html/ 14 | -------------------------------------------------------------------------------- /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 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/ReverseString.pm" 8 | ], 9 | "test": [ 10 | "t/reverse-string.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/ReverseString.pm" 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/solutions/t/reverse-string.t: -------------------------------------------------------------------------------- 1 | ../../../t/reverse-string.t -------------------------------------------------------------------------------- /exercises/practice/reverse-string/lib/ReverseString.pm: -------------------------------------------------------------------------------- 1 | package ReverseString; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub str_reverse ($text) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to determine the RNA complement of a given DNA sequence. 4 | 5 | Both DNA and RNA strands are a sequence of nucleotides. 6 | 7 | The four nucleotides found in DNA are adenine (**A**), cytosine (**C**), guanine (**G**), and thymine (**T**). 8 | 9 | The four nucleotides found in RNA are adenine (**A**), cytosine (**C**), guanine (**G**), and uracil (**U**). 10 | 11 | Given a DNA strand, its transcribed RNA strand is formed by replacing each nucleotide with its complement: 12 | 13 | - `G` -> `C` 14 | - `C` -> `G` 15 | - `T` -> `A` 16 | - `A` -> `U` 17 | 18 | ~~~~exercism/note 19 | If you want to look at how the inputs and outputs are structured, take a look at the examples in the test suite. 20 | ~~~~ 21 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "szabgab" 4 | ], 5 | "contributors": [ 6 | "bistik", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo", 10 | "yanick" 11 | ], 12 | "files": { 13 | "solution": [ 14 | "lib/RNA.pm" 15 | ], 16 | "test": [ 17 | "t/rna-transcription.t" 18 | ], 19 | "example": [ 20 | ".meta/solutions/lib/RNA.pm" 21 | ] 22 | }, 23 | "blurb": "Given a DNA strand, return its RNA complement.", 24 | "source": "Hyperphysics", 25 | "source_url": "https://web.archive.org/web/20220408112140/http://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html" 26 | } 27 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/.meta/solutions/lib/RNA.pm: -------------------------------------------------------------------------------- 1 | package RNA; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub to_rna ($dna) { $dna =~ tr/CGTA/GCAU/r } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/.meta/solutions/t/rna-transcription.t: -------------------------------------------------------------------------------- 1 | ../../../t/rna-transcription.t -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | package: RNA 2 | subs: to_rna 3 | 4 | properties: 5 | toRna: 6 | test: |- 7 | use Data::Dmp; 8 | sprintf(<<~'END', map {dmp $_} $case->{input}{dna}, $case->@{qw}); 9 | is( 10 | to_rna(%s), 11 | %s, 12 | %s, 13 | ); 14 | END 15 | 16 | example: |- 17 | sub to_rna ($dna) {$dna =~ tr/CGTA/GCAU/r} 18 | 19 | stub: |- 20 | sub to_rna ($dna) { 21 | return undef; 22 | } 23 | -------------------------------------------------------------------------------- /exercises/practice/rna-transcription/lib/RNA.pm: -------------------------------------------------------------------------------- 1 | package RNA; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub to_rna ($dna) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/robot-name/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Manage robot factory settings. 4 | 5 | When a robot comes off the factory floor, it has no name. 6 | 7 | The first time you turn on a robot, a random name is generated in the format of two uppercase letters followed by three digits, such as RX837 or BC811. 8 | 9 | Every once in a while we need to reset a robot to its factory settings, which means that its name gets wiped. 10 | The next time you ask, that robot will respond with a new random name. 11 | 12 | The names must be random: they should not follow a predictable sequence. 13 | Using random names means a risk of collisions. 14 | Your solution must ensure that every existing robot has a unique name. 15 | -------------------------------------------------------------------------------- /exercises/practice/robot-name/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "dnmfarrell" 4 | ], 5 | "contributors": [ 6 | "bistik", 7 | "choroba", 8 | "cxw42", 9 | "kytrinyx", 10 | "m-dango", 11 | "rfilipo" 12 | ], 13 | "files": { 14 | "solution": [ 15 | "lib/RobotName.pm" 16 | ], 17 | "test": [ 18 | "t/robot-name.t" 19 | ], 20 | "example": [ 21 | ".meta/solutions/lib/RobotName.pm" 22 | ] 23 | }, 24 | "blurb": "Manage robot factory settings.", 25 | "source": "A debugging session with Paul Blackwell at gSchool." 26 | } 27 | -------------------------------------------------------------------------------- /exercises/practice/robot-name/.meta/solutions/lib/RobotName.pm: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use experimental qw; 4 | use Feature::Compat::Class; 5 | 6 | class RobotName; 7 | 8 | field $name :reader; 9 | 10 | ADJUST { 11 | $name = $self->reset_name(); 12 | } 13 | 14 | method reset_name () { 15 | $name = _rand_letter() . _rand_letter() . _suffix(); 16 | return $name; 17 | } 18 | 19 | sub _rand_letter () { 20 | my @letters = 'A' .. 'Z'; 21 | return $letters[ int rand $#letters ]; 22 | } 23 | 24 | sub _suffix () { 25 | return sprintf( '%03d', int rand 1000 ); 26 | } 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /exercises/practice/robot-name/.meta/solutions/t/robot-name.t: -------------------------------------------------------------------------------- 1 | ../../../t/robot-name.t -------------------------------------------------------------------------------- /exercises/practice/robot-name/lib/RobotName.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class RobotName; 5 | 6 | field $name :reader; 7 | 8 | method reset_name () { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/robot-name/t/robot-name.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use Test2::V0; 3 | 4 | use FindBin qw<$Bin>; 5 | use lib "$Bin/../lib", "$Bin/../local/lib/perl5"; 6 | 7 | use RobotName (); 8 | 9 | my $robot = RobotName->new; # begin: 1 10 | isa_ok $robot, 'RobotName'; # end: 1 11 | 12 | my $name = $robot->name; # begin: 2 13 | my $schema = qr/^[A-Z]{2}[0-9]{3}$/; 14 | like $robot->name, $schema, 'Name should match schema'; # end: 2 15 | 16 | is $name, $robot->name, 'Name should be persistent'; # case: 3 17 | 18 | isnt $robot->name, RobotName->new->name, 'Robots should have different names'; # case: 4 19 | 20 | isnt $robot->reset_name, $name, 'reset_name should change the robot name'; # case: 5 21 | 22 | like $robot->name, $schema, 'New name should match schema'; # case: 6 23 | 24 | done_testing; 25 | -------------------------------------------------------------------------------- /exercises/practice/robot-simulator/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "autark", 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/Robot.pm" 14 | ], 15 | "test": [ 16 | "t/robot-simulator.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/Robot.pm" 20 | ] 21 | }, 22 | "blurb": "Write a robot simulator.", 23 | "source": "Inspired by an interview question at a famous company." 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/robot-simulator/.meta/solutions/t/robot-simulator.t: -------------------------------------------------------------------------------- 1 | ../../../t/robot-simulator.t -------------------------------------------------------------------------------- /exercises/practice/robot-simulator/lib/Robot.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class Robot; 5 | 6 | field $x :reader :param; 7 | field $y :reader :param; 8 | field $direction :reader :param; 9 | 10 | method enact ($instructions) { 11 | return $self; 12 | } 13 | 14 | 1; 15 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/RomanNumerals.pm" 13 | ], 14 | "test": [ 15 | "t/roman-numerals.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/RomanNumerals.pm" 19 | ] 20 | }, 21 | "blurb": "Convert modern Arabic numbers into Roman numerals.", 22 | "source": "The Roman Numeral Kata", 23 | "source_url": "https://codingdojo.org/kata/RomanNumerals/" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/roman-numerals/.meta/solutions/t/roman-numerals.t: -------------------------------------------------------------------------------- 1 | ../../../t/roman-numerals.t -------------------------------------------------------------------------------- /exercises/practice/roman-numerals/lib/RomanNumerals.pm: -------------------------------------------------------------------------------- 1 | package RomanNumerals; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub to_roman ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/rotational-cipher/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "contributors": [ 6 | "m-dango" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "lib/RotationalCipher.pm" 11 | ], 12 | "test": [ 13 | "t/rotational-cipher.t" 14 | ], 15 | "example": [ 16 | ".meta/solutions/lib/RotationalCipher.pm" 17 | ] 18 | }, 19 | "blurb": "Create an implementation of the rotational cipher, also sometimes called the Caesar cipher.", 20 | "source": "Wikipedia", 21 | "source_url": "https://en.wikipedia.org/wiki/Caesar_cipher" 22 | } 23 | -------------------------------------------------------------------------------- /exercises/practice/rotational-cipher/.meta/solutions/t/rotational-cipher.t: -------------------------------------------------------------------------------- 1 | ../../../t/rotational-cipher.t -------------------------------------------------------------------------------- /exercises/practice/rotational-cipher/lib/RotationalCipher.pm: -------------------------------------------------------------------------------- 1 | package RotationalCipher; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub caesar_cipher ( $text, $shift_key ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/run-length-encoding/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/RunLengthEncoding.pm" 8 | ], 9 | "test": [ 10 | "t/run-length-encoding.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/RunLengthEncoding.pm" 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/.meta/solutions/lib/RunLengthEncoding.pm: -------------------------------------------------------------------------------- 1 | package RunLengthEncoding; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub encode ($string) { 11 | ( my $encoded = $string ) =~ s{(.)(\1+)}{(1 + length $2) . $1}ge; 12 | return $encoded; 13 | } 14 | 15 | sub decode ($string) { 16 | ( my $decoded = $string ) =~ s{(\d+)(.)}{$2 x $1}ge; 17 | return $decoded; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /exercises/practice/run-length-encoding/.meta/solutions/t/run-length-encoding.t: -------------------------------------------------------------------------------- 1 | ../../../t/run-length-encoding.t -------------------------------------------------------------------------------- /exercises/practice/run-length-encoding/lib/RunLengthEncoding.pm: -------------------------------------------------------------------------------- 1 | package RunLengthEncoding; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub encode ($string) { 9 | return undef; 10 | } 11 | 12 | sub decode ($string) { 13 | return undef; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/SaddlePoints.pm" 13 | ], 14 | "test": [ 15 | "t/saddle-points.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/SaddlePoints.pm" 19 | ] 20 | }, 21 | "blurb": "Detect saddle points in a matrix.", 22 | "source": "J Dalbey's Programming Practice problems", 23 | "source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/saddle-points/.meta/solutions/t/saddle-points.t: -------------------------------------------------------------------------------- 1 | ../../../t/saddle-points.t -------------------------------------------------------------------------------- /exercises/practice/saddle-points/lib/SaddlePoints.pm: -------------------------------------------------------------------------------- 1 | package SaddlePoints; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub saddle_points ($matrix) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/say/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Say.pm" 13 | ], 14 | "test": [ 15 | "t/say.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Say.pm" 19 | ] 20 | }, 21 | "blurb": "Given a number from 0 to 999,999,999,999, spell out that number in English.", 22 | "source": "A variation on the JavaRanch CattleDrive, Assignment 4", 23 | "source_url": "https://web.archive.org/web/20240907035912/https://coderanch.com/wiki/718804" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/say/.meta/solutions/t/say.t: -------------------------------------------------------------------------------- 1 | ../../../t/say.t -------------------------------------------------------------------------------- /exercises/practice/say/lib/Say.pm: -------------------------------------------------------------------------------- 1 | package Say; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub say_number ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "darksuji", 7 | "drewbs", 8 | "kytrinyx", 9 | "m-dango", 10 | "rfilipo", 11 | "sshine" 12 | ], 13 | "files": { 14 | "solution": [ 15 | "lib/Scrabble.pm" 16 | ], 17 | "test": [ 18 | "t/scrabble-score.t" 19 | ], 20 | "example": [ 21 | ".meta/solutions/lib/Scrabble.pm" 22 | ] 23 | }, 24 | "blurb": "Given a word, compute the Scrabble score for that word.", 25 | "source": "Inspired by the Extreme Startup game", 26 | "source_url": "https://github.com/rchatley/extreme_startup" 27 | } 28 | -------------------------------------------------------------------------------- /exercises/practice/scrabble-score/.meta/solutions/lib/Scrabble.pm: -------------------------------------------------------------------------------- 1 | package Scrabble; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub scrabble_score ($word) { 11 | my $sum = 0; 12 | for ( split //, lc($word) ) { 13 | if (/[aeioulnrst]/) { $sum += 1 } 14 | if (/[dg]/) { $sum += 2 } 15 | if (/[bcmp]/) { $sum += 3 } 16 | if (/[fhvwy]/) { $sum += 4 } 17 | if (/[k]/) { $sum += 5 } 18 | if (/[jx]/) { $sum += 8 } 19 | if (/[qz]/) { $sum += 10 } 20 | } 21 | return $sum; 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /exercises/practice/scrabble-score/.meta/solutions/t/scrabble-score.t: -------------------------------------------------------------------------------- 1 | ../../../t/scrabble-score.t -------------------------------------------------------------------------------- /exercises/practice/scrabble-score/lib/Scrabble.pm: -------------------------------------------------------------------------------- 1 | package Scrabble; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub scrabble_score ($word) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/SecretHandshake.pm" 13 | ], 14 | "test": [ 15 | "t/secret-handshake.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/SecretHandshake.pm" 19 | ] 20 | }, 21 | "blurb": "Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.", 22 | "source": "Bert, in Mary Poppins", 23 | "source_url": "https://www.imdb.com/title/tt0058331/quotes/?item=qt0437047" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/secret-handshake/.meta/solutions/lib/SecretHandshake.pm: -------------------------------------------------------------------------------- 1 | package SecretHandshake; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub handshake ($number) { 11 | my @result; 12 | push @result, 'wink' if 0b00001 & $number; 13 | push @result, 'double blink' if 0b00010 & $number; 14 | push @result, 'close your eyes' if 0b00100 & $number; 15 | push @result, 'jump' if 0b01000 & $number; 16 | @result = reverse @result if 0b10000 & $number; 17 | return \@result; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /exercises/practice/secret-handshake/.meta/solutions/t/secret-handshake.t: -------------------------------------------------------------------------------- 1 | ../../../t/secret-handshake.t -------------------------------------------------------------------------------- /exercises/practice/secret-handshake/lib/SecretHandshake.pm: -------------------------------------------------------------------------------- 1 | package SecretHandshake; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub handshake ($number) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "autark" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Series.pm" 13 | ], 14 | "test": [ 15 | "t/series.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Series.pm" 19 | ] 20 | }, 21 | "blurb": "Given a string of digits, output all the contiguous substrings of length `n` in that string.", 22 | "source": "A subset of the Problem 8 at Project Euler", 23 | "source_url": "https://projecteuler.net/problem=8" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/series/.meta/solutions/t/series.t: -------------------------------------------------------------------------------- 1 | ../../../t/series.t -------------------------------------------------------------------------------- /exercises/practice/series/lib/Series.pm: -------------------------------------------------------------------------------- 1 | package Series; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub slices ( $series, $slice_length ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Sieve.pm" 13 | ], 14 | "test": [ 15 | "t/sieve.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Sieve.pm" 19 | ] 20 | }, 21 | "blurb": "Use the Sieve of Eratosthenes to find all the primes from 2 up to a given number.", 22 | "source": "Sieve of Eratosthenes at Wikipedia", 23 | "source_url": "https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/sieve/.meta/solutions/lib/Sieve.pm: -------------------------------------------------------------------------------- 1 | package Sieve; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | # Solved by GitHub Copilot 11 | sub find_primes ($n) { 12 | my @primes = (1) x ( $n + 1 ); 13 | $primes[0] = $primes[1] = 0; 14 | 15 | for my $i ( 2 .. int( sqrt($n) ) ) { 16 | next unless $primes[$i]; 17 | for ( my $j = $i**2; $j <= $n; $j += $i ) { 18 | $primes[$j] = 0; 19 | } 20 | } 21 | 22 | return [ grep { $primes[$_] } 2 .. $n ]; 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /exercises/practice/sieve/.meta/solutions/t/sieve.t: -------------------------------------------------------------------------------- 1 | ../../../t/sieve.t -------------------------------------------------------------------------------- /exercises/practice/sieve/lib/Sieve.pm: -------------------------------------------------------------------------------- 1 | package Sieve; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub find_primes ($limit) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/simple-cipher/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/SimpleCipher.pm" 13 | ], 14 | "test": [ 15 | "t/simple-cipher.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/SimpleCipher.pm" 19 | ] 20 | }, 21 | "blurb": "Implement a simple shift cipher like Caesar and a more secure substitution cipher.", 22 | "source": "Substitution Cipher at Wikipedia", 23 | "source_url": "https://en.wikipedia.org/wiki/Substitution_cipher" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/simple-cipher/.meta/solutions/t/simple-cipher.t: -------------------------------------------------------------------------------- 1 | ../../../t/simple-cipher.t -------------------------------------------------------------------------------- /exercises/practice/simple-cipher/lib/SimpleCipher.pm: -------------------------------------------------------------------------------- 1 | use v5.40; 2 | use experimental qw; 3 | 4 | class SimpleCipher; 5 | 6 | field $key :reader :param = ''; 7 | 8 | method encode ($plaintext) { 9 | return undef; 10 | } 11 | 12 | method decode ($ciphertext) { 13 | return undef; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /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 | "autark" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "LinkedList.pm" 13 | ], 14 | "test": [ 15 | "simple_linked_list.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/LinkedList.pm" 19 | ] 20 | }, 21 | "blurb": "Write a simple linked list implementation that uses Elements and a List.", 22 | "source": "Inspired by 'Data Structures and Algorithms with Object-Oriented Design Patterns in Ruby', singly linked-lists.", 23 | "source_url": "https://web.archive.org/web/20160731005714/http://brpreiss.com/books/opus8/html/page96.html" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/simple-linked-list/.meta/solutions/simple_linked_list.t: -------------------------------------------------------------------------------- 1 | ../../simple_linked_list.t -------------------------------------------------------------------------------- /exercises/practice/simple-linked-list/LinkedList.pm: -------------------------------------------------------------------------------- 1 | package LinkedList; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my $class = shift; 8 | 9 | return undef; 10 | } 11 | 12 | sub from_array { 13 | my ( $pkg, $array ) = @_; 14 | 15 | return undef; 16 | } 17 | 18 | sub to_array { 19 | my $self = shift; 20 | 21 | return undef; 22 | } 23 | 24 | sub reverse : method { 25 | my $self = shift; 26 | 27 | return undef; 28 | } 29 | 30 | 1; 31 | 32 | -------------------------------------------------------------------------------- /exercises/practice/space-age/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/SpaceAge.pm" 13 | ], 14 | "test": [ 15 | "t/space-age.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/SpaceAge.pm" 19 | ] 20 | }, 21 | "blurb": "Given an age in seconds, calculate how old someone is in terms of a given planet's solar years.", 22 | "source": "Partially inspired by Chapter 1 in Chris Pine's online Learn to Program tutorial.", 23 | "source_url": "https://pine.fm/LearnToProgram/?Chapter=01" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/space-age/.meta/solutions/t/space-age.t: -------------------------------------------------------------------------------- 1 | ../../../t/space-age.t -------------------------------------------------------------------------------- /exercises/practice/space-age/lib/SpaceAge.pm: -------------------------------------------------------------------------------- 1 | package SpaceAge; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub age_on_planet ( $planet, $seconds ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In a small village near an ancient forest, there was a legend of a hidden treasure buried deep within the woods. 4 | Despite numerous attempts, no one had ever succeeded in finding it. 5 | This was about to change, however, thanks to a young explorer named Elara. 6 | She had discovered an old document containing instructions on how to locate the treasure. 7 | Using these instructions, Elara was able to draw a map that revealed the path to the treasure. 8 | 9 | To her surprise, the path followed a peculiar clockwise spiral. 10 | It was no wonder no one had been able to find the treasure before! 11 | With the map in hand, Elara embarks on her journey to uncover the hidden treasure. 12 | -------------------------------------------------------------------------------- /exercises/practice/spiral-matrix/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "lib/SpiralMatrix.pm" 8 | ], 9 | "test": [ 10 | "t/spiral-matrix.t" 11 | ], 12 | "example": [ 13 | ".meta/solutions/lib/SpiralMatrix.pm" 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/solutions/t/spiral-matrix.t: -------------------------------------------------------------------------------- 1 | ../../../t/spiral-matrix.t -------------------------------------------------------------------------------- /exercises/practice/spiral-matrix/lib/SpiralMatrix.pm: -------------------------------------------------------------------------------- 1 | package SpiralMatrix; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub spiral_matrix ($size) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/strain/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Strain.pm" 13 | ], 14 | "test": [ 15 | "t/strain.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Strain.pm" 19 | ] 20 | }, 21 | "blurb": "Implement the `keep` and `discard` operation on collections.", 22 | "source": "Conversation with James Edward Gray II", 23 | "source_url": "http://graysoftinc.com/" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/strain/.meta/solutions/t/strain.t: -------------------------------------------------------------------------------- 1 | ../../../t/strain.t -------------------------------------------------------------------------------- /exercises/practice/strain/lib/Strain.pm: -------------------------------------------------------------------------------- 1 | package Strain; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub keep ( $input, $function ) { 9 | return undef; 10 | } 11 | 12 | sub discard ( $input, $function ) { 13 | return undef; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /exercises/practice/sublist/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "autark" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Sublist.pm" 13 | ], 14 | "test": [ 15 | "t/sublist.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Sublist.pm" 19 | ] 20 | }, 21 | "blurb": "Write a function to determine if a list is a sublist of another list." 22 | } 23 | -------------------------------------------------------------------------------- /exercises/practice/sublist/.meta/solutions/t/sublist.t: -------------------------------------------------------------------------------- 1 | ../../../t/sublist.t -------------------------------------------------------------------------------- /exercises/practice/sublist/lib/Sublist.pm: -------------------------------------------------------------------------------- 1 | package Sublist; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub compare_lists ( $list1, $list2 ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "alexkalderimis", 7 | "duffn", 8 | "kytrinyx", 9 | "m-dango", 10 | "rfilipo" 11 | ], 12 | "files": { 13 | "solution": [ 14 | "lib/SumOfMultiples.pm" 15 | ], 16 | "test": [ 17 | "t/sum-of-multiples.t" 18 | ], 19 | "example": [ 20 | ".meta/solutions/lib/SumOfMultiples.pm" 21 | ] 22 | }, 23 | "blurb": "Given a number, find the sum of all the multiples of particular numbers up to but not including that number.", 24 | "source": "A variation on Problem 1 at Project Euler", 25 | "source_url": "https://projecteuler.net/problem=1" 26 | } 27 | -------------------------------------------------------------------------------- /exercises/practice/sum-of-multiples/.meta/solutions/lib/SumOfMultiples.pm: -------------------------------------------------------------------------------- 1 | package SumOfMultiples; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub sum_of_multiples ( $factors, $limit ) { 11 | 12 | $factors = [ grep { $_ > 0 } @{$factors} ]; 13 | my %multiples; 14 | 15 | for my $factor (@$factors) { 16 | for ( my $i = 1; $i * $factor < $limit; $i++ ) { 17 | $multiples{ $i * $factor } = 1; 18 | } 19 | } 20 | my $sum = 0; 21 | for my $multiple ( keys %multiples ) { 22 | $sum += $multiple; 23 | } 24 | 25 | return $sum; 26 | } 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /exercises/practice/sum-of-multiples/.meta/solutions/t/sum-of-multiples.t: -------------------------------------------------------------------------------- 1 | ../../../t/sum-of-multiples.t -------------------------------------------------------------------------------- /exercises/practice/sum-of-multiples/lib/SumOfMultiples.pm: -------------------------------------------------------------------------------- 1 | package SumOfMultiples; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub sum_of_multiples ( $factors, $limit ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/triangle/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "szabgab" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Triangle.pm" 13 | ], 14 | "test": [ 15 | "t/triangle.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Triangle.pm" 19 | ] 20 | }, 21 | "blurb": "Determine if a triangle is equilateral, isosceles, or scalene.", 22 | "source": "The Ruby Koans triangle project, parts 1 & 2", 23 | "source_url": "https://web.archive.org/web/20220831105330/http://rubykoans.com" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/triangle/.meta/solutions/t/triangle.t: -------------------------------------------------------------------------------- 1 | ../../../t/triangle.t -------------------------------------------------------------------------------- /exercises/practice/triangle/lib/Triangle.pm: -------------------------------------------------------------------------------- 1 | package Triangle; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub is_equilateral ($triangle) { 9 | return undef; 10 | } 11 | 12 | sub is_isosceles ($triangle) { 13 | return undef; 14 | } 15 | 16 | sub is_scalene ($triangle) { 17 | return undef; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /exercises/practice/trinary/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "blurb": "Convert a trinary number, represented as a string (e.g. '102012'), to its decimal equivalent using first principles.", 3 | "authors": [ 4 | "bistik" 5 | ], 6 | "contributors": [ 7 | "kytrinyx", 8 | "m-dango", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "Trinary.pm" 14 | ], 15 | "test": [ 16 | "trinary.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/Trinary.pm" 20 | ] 21 | }, 22 | "source": "All of Computer Science", 23 | "source_url": "http://www.wolframalpha.com/input/?i=binary&a=*C.binary-_*MathWorld-" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/trinary/.meta/solutions/Trinary.pm: -------------------------------------------------------------------------------- 1 | package Trinary; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ( $class, $trinary ) = @_; 8 | my $self = bless {} => $class; 9 | $self->{trinary} = $trinary; 10 | return $self; 11 | } 12 | 13 | sub to_decimal { 14 | my $self = shift; 15 | 16 | return 0 unless $self->{trinary} =~ /[012]/g; 17 | 18 | my ( $sum, $index ) = ( 0, length $self->{trinary} ); 19 | 20 | foreach my $digit ( split // => $self->{trinary} ) { 21 | $sum += $digit * 3** --$index; 22 | } 23 | 24 | return $sum; 25 | } 26 | __PACKAGE__; 27 | -------------------------------------------------------------------------------- /exercises/practice/trinary/.meta/solutions/trinary.t: -------------------------------------------------------------------------------- 1 | ../../trinary.t -------------------------------------------------------------------------------- /exercises/practice/trinary/Trinary.pm: -------------------------------------------------------------------------------- 1 | package Trinary; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ( $class, $trinary ) = @_; 8 | 9 | return undef; 10 | } 11 | 12 | sub to_decimal { 13 | my $self = shift; 14 | 15 | return undef; 16 | } 17 | __PACKAGE__; 18 | -------------------------------------------------------------------------------- /exercises/practice/twelve-days/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "bistik" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "PatrickMcSweeny", 9 | "rfilipo" 10 | ], 11 | "files": { 12 | "solution": [ 13 | "lib/TwelveDays.pm" 14 | ], 15 | "test": [ 16 | "t/twelve-days.t" 17 | ], 18 | "example": [ 19 | ".meta/solutions/lib/TwelveDays.pm" 20 | ] 21 | }, 22 | "blurb": "Output the lyrics to 'The Twelve Days of Christmas'.", 23 | "source": "Wikipedia", 24 | "source_url": "https://en.wikipedia.org/wiki/The_Twelve_Days_of_Christmas_(song)" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/twelve-days/.meta/solutions/t/twelve-days.t: -------------------------------------------------------------------------------- 1 | ../../../t/twelve-days.t -------------------------------------------------------------------------------- /exercises/practice/twelve-days/lib/TwelveDays.pm: -------------------------------------------------------------------------------- 1 | package TwelveDays; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub recite ( $start, $end ) { 9 | return ''; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/two-bucket/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "glennj" 4 | ], 5 | "contributors": [ 6 | "m-dango" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "lib/TwoBucket.pm" 11 | ], 12 | "test": [ 13 | "t/two-bucket.t" 14 | ], 15 | "example": [ 16 | ".meta/solutions/lib/TwoBucket.pm" 17 | ] 18 | }, 19 | "blurb": "Given two buckets of different size, demonstrate how to measure an exact number of liters.", 20 | "source": "Water Pouring Problem", 21 | "source_url": "https://demonstrations.wolfram.com/WaterPouringProblem/" 22 | } 23 | -------------------------------------------------------------------------------- /exercises/practice/two-bucket/.meta/solutions/t/two-bucket.t: -------------------------------------------------------------------------------- 1 | ../../../t/two-bucket.t -------------------------------------------------------------------------------- /exercises/practice/two-bucket/lib/TwoBucket.pm: -------------------------------------------------------------------------------- 1 | package TwoBucket; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub measure ( $bucket_1, $bucket_2, $goal, $start_bucket ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "m-dango" 4 | ], 5 | "contributors": [ 6 | "rfilipo" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "lib/TwoFer.pm" 11 | ], 12 | "test": [ 13 | "t/two-fer.t" 14 | ], 15 | "example": [ 16 | ".meta/solutions/lib/TwoFer.pm" 17 | ] 18 | }, 19 | "blurb": "Create a sentence of the form \"One for X, one for me.\".", 20 | "source_url": "https://github.com/exercism/problem-specifications/issues/757" 21 | } 22 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/solutions/lib/TwoFer.pm: -------------------------------------------------------------------------------- 1 | package TwoFer; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub two_fer ( $name = 'you' ) { 11 | return "One for $name, one for me."; 12 | } 13 | 14 | 1; 15 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/solutions/t/two-fer.t: -------------------------------------------------------------------------------- 1 | ../../../t/two-fer.t -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/template-data.yaml: -------------------------------------------------------------------------------- 1 | subs: two_fer 2 | 3 | properties: 4 | twoFer: 5 | test: |- 6 | use Data::Dmp; 7 | sprintf(<<'END', ($case->{input}{name} ? dmp($case->{input}{name}) : ''), map {dmp $_} $case->@{qw}); 8 | is( 9 | two_fer(%s), 10 | %s, 11 | %s, 12 | ); 13 | END 14 | 15 | example: |- 16 | sub two_fer ($name = 'you') { 17 | return "One for $name, one for me."; 18 | } 19 | 20 | stub: |- 21 | sub two_fer ($name = undef) { 22 | return undef; 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/lib/TwoFer.pm: -------------------------------------------------------------------------------- 1 | package TwoFer; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub two_fer ( $name = undef ) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/t/two-fer.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use Test2::V0; 3 | 4 | use FindBin qw<$Bin>; 5 | use lib "$Bin/../lib", "$Bin/../local/lib/perl5"; 6 | 7 | use TwoFer qw; 8 | 9 | is( # begin: 1cf3e15a-a3d7-4a87-aeb3-ba1b43bc8dce 10 | two_fer(), 11 | "One for you, one for me.", 12 | "no name given", 13 | ); # end: 1cf3e15a-a3d7-4a87-aeb3-ba1b43bc8dce 14 | 15 | is( # begin: b4c6dbb8-b4fb-42c2-bafd-10785abe7709 16 | two_fer("Alice"), 17 | "One for Alice, one for me.", 18 | "a name given", 19 | ); # end: b4c6dbb8-b4fb-42c2-bafd-10785abe7709 20 | 21 | is( # begin: 3549048d-1a6e-4653-9a79-b0bda163e8d5 22 | two_fer("Bob"), 23 | "One for Bob, one for me.", 24 | "another name given", 25 | ); # end: 3549048d-1a6e-4653-9a79-b0bda163e8d5 26 | 27 | done_testing; 28 | -------------------------------------------------------------------------------- /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 | "szabgab" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/WordCount.pm" 13 | ], 14 | "test": [ 15 | "t/word-count.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/WordCount.pm" 19 | ] 20 | }, 21 | "blurb": "Given a phrase, count the occurrences of each word in that phrase.", 22 | "source": "This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour." 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/word-count/.meta/solutions/lib/WordCount.pm: -------------------------------------------------------------------------------- 1 | package WordCount; 2 | 3 | use strict; 4 | use warnings; 5 | use experimental qw; 6 | 7 | use Exporter qw; 8 | our @EXPORT_OK = qw; 9 | 10 | sub count_words ($sentence) { 11 | 12 | my $words = lc($sentence) 13 | =~ s/\s+/ /gr # Any whitespace character becomes a space 14 | =~ s/([a-z0-9]+[a-z0-9']*[a-z0-9]+)/ $1 /gr # Space separate words that might have apostrophes 15 | =~ s/[^a-z0-9']/ /gr; # Remove unwanted characters 16 | 17 | my %bag; 18 | for my $word ( split / +/, $words ) { 19 | if ( length $word && $word ne q{'} ) { 20 | $bag{$word}++; 21 | } 22 | } 23 | 24 | return \%bag; 25 | } 26 | 27 | 1; 28 | -------------------------------------------------------------------------------- /exercises/practice/word-count/.meta/solutions/t/word-count.t: -------------------------------------------------------------------------------- 1 | ../../../t/word-count.t -------------------------------------------------------------------------------- /exercises/practice/word-count/lib/WordCount.pm: -------------------------------------------------------------------------------- 1 | package WordCount; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub count_words ($sentence) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /exercises/practice/wordy/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "szabgab" 4 | ], 5 | "contributors": [ 6 | "kytrinyx", 7 | "m-dango", 8 | "rfilipo" 9 | ], 10 | "files": { 11 | "solution": [ 12 | "lib/Wordy.pm" 13 | ], 14 | "test": [ 15 | "t/wordy.t" 16 | ], 17 | "example": [ 18 | ".meta/solutions/lib/Wordy.pm" 19 | ] 20 | }, 21 | "blurb": "Parse and evaluate simple math word problems returning the answer as an integer.", 22 | "source": "Inspired by one of the generated questions in the Extreme Startup game.", 23 | "source_url": "https://github.com/rchatley/extreme_startup" 24 | } 25 | -------------------------------------------------------------------------------- /exercises/practice/wordy/.meta/solutions/t/wordy.t: -------------------------------------------------------------------------------- 1 | ../../../t/wordy.t -------------------------------------------------------------------------------- /exercises/practice/wordy/lib/Wordy.pm: -------------------------------------------------------------------------------- 1 | package Wordy; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | sub answer ($question) { 9 | return undef; 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /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 | "glennj" 4 | ], 5 | "contributors": [ 6 | "m-dango" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "lib/Yacht.pm" 11 | ], 12 | "test": [ 13 | "t/yacht.t" 14 | ], 15 | "example": [ 16 | ".meta/solutions/lib/Yacht.pm" 17 | ], 18 | "editor": [ 19 | "lib/Yacht/Category.pm" 20 | ] 21 | }, 22 | "blurb": "Score a single throw of dice in the game Yacht.", 23 | "source": "James Kilfiger, using Wikipedia", 24 | "source_url": "https://en.wikipedia.org/wiki/Yacht_(dice_game)" 25 | } 26 | -------------------------------------------------------------------------------- /exercises/practice/yacht/.meta/solutions/lib/Yacht/Category.pm: -------------------------------------------------------------------------------- 1 | ../../../../lib/Yacht/Category.pm -------------------------------------------------------------------------------- /exercises/practice/yacht/.meta/solutions/t/yacht.t: -------------------------------------------------------------------------------- 1 | ../../../t/yacht.t -------------------------------------------------------------------------------- /exercises/practice/yacht/lib/Yacht.pm: -------------------------------------------------------------------------------- 1 | package Yacht; 2 | 3 | use v5.40; 4 | 5 | use Exporter qw; 6 | our @EXPORT_OK = qw; 7 | 8 | use Yacht::Category; 9 | 10 | sub score ( $dice, $category ) { 11 | return undef; 12 | } 13 | 14 | 1; 15 | -------------------------------------------------------------------------------- /exercises/practice/yacht/lib/Yacht/Category.pm: -------------------------------------------------------------------------------- 1 | package Yacht::Category; 2 | 3 | use strict; 4 | use warnings; 5 | use Readonly; 6 | 7 | my $n = 1; 8 | Readonly our $ONES => $n++; 9 | Readonly our $TWOS => $n++; 10 | Readonly our $THREES => $n++; 11 | Readonly our $FOURS => $n++; 12 | Readonly our $FIVES => $n++; 13 | Readonly our $SIXES => $n++; 14 | Readonly our $FULL_HOUSE => $n++; 15 | Readonly our $FOUR_OF_A_KIND => $n++; 16 | Readonly our $LITTLE_STRAIGHT => $n++; 17 | Readonly our $BIG_STRAIGHT => $n++; 18 | Readonly our $YACHT => $n++; 19 | Readonly our $CHOICE => $n++; 20 | 21 | 1; 22 | -------------------------------------------------------------------------------- /exercises/shared/.docs/debug.md: -------------------------------------------------------------------------------- 1 | # Debug 2 | 3 | When a test fails, a message is displayed describing what went wrong. 4 | If you would like additional output, you can use the subroutine `::YYY()` around the code you would like to inspect. 5 | (`::` is a shortcut for `main::`). 6 | This subroutine is part of the [XXX][XXX] module. 7 | 8 | You may also simply print a message using the `say` function, e.g., `say 'Hello, World!';`. 9 | 10 | The online test runner uses the [Test Anything Protocol][TAP]. 11 | Due to the nature of TAP, the use of `print` in the online test runner is strongly discouraged. 12 | 13 | [XXX]: https://metacpan.org/dist/XXX/view/lib/XXX.pod 14 | [TAP]: https://testanything.org/ 15 | -------------------------------------------------------------------------------- /exercises/shared/.docs/help.md: -------------------------------------------------------------------------------- 1 | # Help 2 | 3 | To get help if you're having trouble, you can use one of the following resources: 4 | 5 | - [/r/perl](https://www.reddit.com/r/perl) is the Perl subreddit. 6 | - [StackOverflow](http://stackoverflow.com/questions/tagged/perl) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions. 7 | -------------------------------------------------------------------------------- /exercises/shared/.docs/tests.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | There is a Perl script with the extension `.t` contained in the `t/` directory, which will be used to test your solution. 4 | You can run through the tests by using the command: 5 | 6 | ```bash 7 | `prove` 8 | ``` 9 | 10 | Documentation about the assertions used in the test files can be found in [Test2::Manual::Testing::Introduction][test2-manual]. 11 | 12 | [test2-manual]: https://metacpan.org/pod/Test2::Manual::Testing::Introduction 13 | -------------------------------------------------------------------------------- /reference/implementing-a-concept-exercise.md: -------------------------------------------------------------------------------- 1 | # How to implement a Perl concept exercise 2 | 3 | * Create a concept in the config.json concepts array e.g. Arrays, Hashes. 4 | * Create an exercise associated with that concept. See [stories][stories] for ideas. 5 | * Create a test file in the `t` directory, a stub in the `lib` directory, and an example solution in the `.meta` directory. 6 | 7 | Read more about concept exercises on Exercism's track building documentation: https://exercism.org/docs/building/tracks/concept-exercises 8 | 9 | [stories]: https://github.com/exercism/docs/tree/main/building/tracks/stories 10 | -------------------------------------------------------------------------------- /templates/module.mustache: -------------------------------------------------------------------------------- 1 | {{^class}}{{#package_comment}}{{&package_comment}} 2 | {{/package_comment}}package {{&package}}; 3 | 4 | {{/class}}{{^older_perl_support}}use v5.40;{{#class}} 5 | use experimental qw;{{/class}}{{/older_perl_support}}{{#older_perl_support}}use strict; 6 | use warnings; 7 | use experimental qw;{{#class}} 8 | use Feature::Compat::Class;{{/class}}{{/older_perl_support}}{{#class}} 9 | class {{&package}};{{/class}} 10 | {{#subs}} 11 | use Exporter qw; 12 | our @EXPORT_OK = qw<{{&subs}}>;{{/subs}}{{#module_file}} 13 | 14 | {{&module_file}}{{/module_file}} 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /templates/test.mustache: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use Test2::V0;{{#cases}} 3 | use JSON::PP; 4 | use constant JSON => JSON::PP->new;{{/cases}} 5 | 6 | use FindBin qw<$Bin>; 7 | use lib "$Bin/../lib", "$Bin/../local/lib/perl5";{{#lib_comment}} {{&lib_comment}}{{/lib_comment}} 8 | 9 | use {{&package}} {{#subs}}qw<{{&subs}}>{{/subs}}{{^subs}}(){{/subs}};{{#modules}} 10 | use {{&use}};{{/modules}}{{#cases}} 11 | 12 | my @test_cases = do { local $/; @{ JSON->decode() }; };{{/cases}}{{#plan}} 13 | plan {{&plan}};{{#plan_comment}} {{&plan_comment}}{{/plan_comment}}{{/plan}}{{#tests}} 14 | 15 | {{&tests}}{{/tests}}{{^plan}} 16 | 17 | done_testing;{{/plan}}{{#cases}} 18 | 19 | __DATA__ 20 | {{&cases}}{{/cases}} 21 | --------------------------------------------------------------------------------