Showing preview only (2,596K chars total). Download the full file or copy to clipboard to get everything.
Repository: exercism/kotlin
Branch: main
Commit: a7d115e1df85
Files: 1488
Total size: 2.1 MB
Directory structure:
gitextract_p8afkg7r/
├── .appends/
│ └── .github/
│ └── labels.yml
├── .github/
│ ├── CODEOWNERS
│ ├── dependabot.yml
│ ├── labels.yml
│ └── workflows/
│ ├── configlet.yml
│ ├── no-important-files-changed.yml
│ ├── pause-community-contributions.yml
│ ├── ping-cross-track-maintainers-team.yml
│ ├── run-configlet-sync.yml
│ ├── sync-labels.yml
│ └── test.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── _template/
│ ├── build.gradle.kts
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── settings.gradle.kts
│ └── src/
│ ├── example/
│ │ └── kotlin/
│ │ └── .keep
│ ├── main/
│ │ └── kotlin/
│ │ └── .keep
│ └── test/
│ └── kotlin/
│ └── .keep
├── bin/
│ ├── README.md
│ ├── build-jq.sh
│ ├── fetch-configlet
│ ├── journey-test.sh
│ ├── run-journey-test-from-ci.sh
│ └── unit-tests.sh
├── concepts/
│ ├── basics/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── bitwise-operations/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── booleans/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── chars/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── conditionals/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── nullability/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ └── strings/
│ ├── .meta/
│ │ └── config.json
│ ├── about.md
│ ├── introduction.md
│ └── links.json
├── config.json
├── docs/
│ ├── ABOUT.md
│ ├── INSTALLATION.md
│ ├── LEARNING.md
│ ├── RESOURCES.md
│ ├── SNIPPET.txt
│ ├── TESTS.md
│ └── config.json
├── exercises/
│ ├── build.gradle.kts
│ ├── concept/
│ │ ├── annalyns-infiltration/
│ │ │ ├── .docs/
│ │ │ │ ├── hints.md
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── design.md
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── AnnalynsInfiltration.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── AnnalynsInfiltration.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AnnalynsInfiltrationTest.kt
│ │ ├── log-levels/
│ │ │ ├── .docs/
│ │ │ │ ├── hints.md
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── LogLevels.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── LogLevels.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── LogLevelsTest.kt
│ │ └── lucians-luscious-lasagna/
│ │ ├── .docs/
│ │ │ ├── hints.md
│ │ │ ├── instructions.md
│ │ │ └── introduction.md
│ │ ├── .meta/
│ │ │ ├── config.json
│ │ │ ├── design.md
│ │ │ └── src/
│ │ │ └── reference/
│ │ │ └── kotlin/
│ │ │ └── LuciansLusciousLasagna.kt
│ │ ├── build.gradle.kts
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── settings.gradle.kts
│ │ └── src/
│ │ ├── main/
│ │ │ └── kotlin/
│ │ │ └── LuciansLusciousLasagna.kt
│ │ └── test/
│ │ └── kotlin/
│ │ └── LuciansLusciousLasagnaTests.kt
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradle.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── practice/
│ │ ├── accumulate/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── Accumulate.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Accumulate.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AccumulateTest.kt
│ │ ├── acronym/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Acronym.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Acronym.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AcronymTest.kt
│ │ ├── affine-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── AffineCipher.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── AffineCipher.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AffineCipherTest.kt
│ │ ├── all-your-base/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BaseConverter.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BaseConverter.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BaseConverterTest.kt
│ │ ├── allergies/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Allergen.kt
│ │ │ │ │ └── Allergies.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Allergen.kt
│ │ │ │ └── Allergies.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AllergiesTest.kt
│ │ ├── anagram/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.append.md
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Anagram.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Anagram.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AnagramTest.kt
│ │ ├── armstrong-numbers/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ArmstrongNumber.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ArmstrongNumber.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ArmstrongNumberTest.kt
│ │ ├── atbash-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Atbash.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Atbash.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AtbashTest.kt
│ │ ├── bank-account/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── BankAccount.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BankAccount.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BankAccountTest.kt
│ │ ├── beer-song/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BeerSong.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BeerSong.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BeerSongTest.kt
│ │ ├── binary/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Binary.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Binary.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BinaryTest.kt
│ │ ├── binary-search/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BinarySearch.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BinarySearch.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BinarySearchTest.kt
│ │ ├── binary-search-tree/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BinarySearchTree.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BinarySearchTree.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BinarySearchTreeTest.kt
│ │ ├── bob/
│ │ │ ├── .approaches/
│ │ │ │ ├── answer-list/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── config.json
│ │ │ │ ├── if-expressions/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── introduction.md
│ │ │ │ └── when-expression/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Bob.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Bob.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BobTest.kt
│ │ ├── bottle-song/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BottleSong.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BottleSong.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BottleSongTest.kt
│ │ ├── bowling/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── BowlingGame.kt
│ │ │ │ │ └── Frame.kt
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BowlingGame.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BowlingGameTest.kt
│ │ ├── change/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ChangeCalculator.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ChangeCalculator.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ChangeCalculatorTest.kt
│ │ ├── circular-buffer/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── CircularBuffer.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── CircularBuffer.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── CircularBufferTest.kt
│ │ ├── clock/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Clock.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Clock.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ ├── ClockAddTest.kt
│ │ │ ├── ClockCreationTest.kt
│ │ │ ├── ClockEqualTest.kt
│ │ │ └── ClockSubtractTest.kt
│ │ ├── collatz-conjecture/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── CollatzCalculator.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── CollatzCalculator.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── CollatzCalculatorTest.kt
│ │ ├── complex-numbers/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ComplexNumber.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ComplexNumber.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ComplexNumberTest.kt
│ │ ├── crypto-square/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── CryptoSquare.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── CryptoSquare.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── CryptoSquareTest.kt
│ │ ├── custom-set/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── CustomSet.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── CustomSet.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── CustomSetTest.kt
│ │ ├── darts/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── hypot-for-radius/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Darts.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Darts.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DartsTest.kt
│ │ ├── diamond/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── DiamondPrinter.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── DiamondPrinter.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DiamondPrinterTest.kt
│ │ ├── difference-of-squares/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── formula/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── DifferenceOfSquares.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── DifferenceOfSquares.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SquaresTest.kt
│ │ ├── diffie-hellman/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── DiffieHellman.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── DiffieHellman.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DiffieHellmanTest.kt
│ │ ├── dnd-character/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── DndCharacter.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── DndCharacter.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DndCharacterTest.kt
│ │ ├── dominoes/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Dominoes.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Dominoes.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DominoesTest.kt
│ │ ├── eliuds-eggs/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── EliudsEggs.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── EliudsEggs.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── EliudsEggsTest.kt
│ │ ├── etl/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ETL.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ETL.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ETLTest.kt
│ │ ├── flatten-array/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Flattener.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Flattener.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── FlattenerTest.kt
│ │ ├── flower-field/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── FlowerField.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── FlowerField.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── FlowerFieldTest.kt
│ │ ├── forth/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Forth.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Forth.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ForthTest.kt
│ │ ├── gigasecond/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── introduction.md
│ │ │ │ └── secondary-constructor-atstartofday/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Gigasecond.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Gigasecond.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── GigasecondTest.kt
│ │ ├── grade-school/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── GradeSchool.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── GradeSchool.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SchoolTest.kt
│ │ ├── grains/
│ │ │ ├── .approaches/
│ │ │ │ ├── bit-shifting/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── config.json
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Grains.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Grains.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BoardTest.kt
│ │ ├── hamming/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── introduction.md
│ │ │ │ └── zip-count/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Hamming.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Hamming.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── HammingTest.kt
│ │ ├── hello-world/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.append.md
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── HelloWorld.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── TUTORIAL.md
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── HelloWorld.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── HelloWorldTest.kt
│ │ ├── hexadecimal/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── Hexadecimal.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Hexadecimal.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── HexadecimalTest.kt
│ │ ├── isbn-verifier/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── fold-when-let/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── IsbnVerifier.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── IsbnVerifier.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── IsbnVerifierTest.kt
│ │ ├── isogram/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Isogram.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Isogram.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── IsogramTest.kt
│ │ ├── kindergarten-garden/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── KindergartenGarden.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── KindergartenGarden.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── KindergartenGardenTest.kt
│ │ ├── knapsack/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Knapsack.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Knapsack.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── KnapsackTest.kt
│ │ ├── largest-series-product/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── LargestSeriesProduct.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── LargestSeriesProduct.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SeriesTest.kt
│ │ ├── leap/
│ │ │ ├── .approaches/
│ │ │ │ ├── boolean-chain/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── built-in-method/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── config.json
│ │ │ │ ├── introduction.md
│ │ │ │ ├── plusdays/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── ternary-expression/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Leap.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Leap.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── LeapTest.kt
│ │ ├── linked-list/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── LinkedList.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── LinkedList.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DequeTest.kt
│ │ ├── list-ops/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.append.md
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ListOps.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ListOps.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ListExtensionsTest.kt
│ │ ├── luhn/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Luhn.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Luhn.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── LuhnTest.kt
│ │ ├── matching-brackets/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── MatchingBrackets.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── MatchingBrackets.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MatchingBracketsTest.kt
│ │ ├── matrix/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Matrix.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Matrix.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MatrixTest.kt
│ │ ├── meetup/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Meetup.kt
│ │ │ │ │ └── MeetupSchedule.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Meetup.kt
│ │ │ │ └── MeetupSchedule.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MeetupTest.kt
│ │ ├── minesweeper/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Minesweeper.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Minesweeper.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MinesweeperBoardTest.kt
│ │ ├── nth-prime/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── NthPrime.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── NthPrime.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PrimeTest.kt
│ │ ├── nucleotide-count/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── groupby-plus/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Dna.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Dna.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DnaTest.kt
│ │ ├── pangram/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Pangram.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Pangram.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PangramTest.kt
│ │ ├── pascals-triangle/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── PascalsTriangle.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── PascalsTriangle.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PascalsTriangleTest.kt
│ │ ├── perfect-numbers/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── NaturalNumber.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── NaturalNumber.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── NaturalNumberTest.kt
│ │ ├── phone-number/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── PhoneNumber.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── PhoneNumber.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PhoneNumberTest.kt
│ │ ├── pig-latin/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── hashset-lookup/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── PigLatin.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── PigLatin.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PigLatinTest.kt
│ │ ├── prime-factors/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── PrimeFactors.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── PrimeFactors.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PrimeFactorCalculatorTest.kt
│ │ ├── protein-translation/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ProteinTranslation.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ProteinTranslation.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ProteinTranslationTest.kt
│ │ ├── rail-fence-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RailFenceCipher.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RailFenceCipher.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RailFenceCipherTest.kt
│ │ ├── raindrops/
│ │ │ ├── .approaches/
│ │ │ │ ├── buildstring/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── config.json
│ │ │ │ ├── fold-on-list/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Raindrops.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Raindrops.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RaindropsTest.kt
│ │ ├── react/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── React.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── React.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ReactTest.kt
│ │ ├── resistor-color/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ResistorColor.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ResistorColor.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ResistorColorTest.kt
│ │ ├── resistor-color-duo/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ └── ResistorColorDuo.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Color.kt
│ │ │ │ └── ResistorColorDuo.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ResistorColorDuoTest.kt
│ │ ├── resistor-color-trio/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ ├── ResistorColorTrio.kt
│ │ │ │ │ └── Unit.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Color.kt
│ │ │ │ ├── ResistorColorTrio.kt
│ │ │ │ └── Unit.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ResistorColorTrioTest.kt
│ │ ├── reverse-string/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ReverseString.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ReverseString.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ReverseStringTest.kt
│ │ ├── rna-transcription/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RnaTranscription.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RnaTranscription.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RnaTranscriptionTest.kt
│ │ ├── robot-name/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── RobotName.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RobotName.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RobotTest.kt
│ │ ├── robot-simulator/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── GridPosition.kt
│ │ │ │ │ ├── Orientation.kt
│ │ │ │ │ └── Robot.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── GridPosition.kt
│ │ │ │ ├── Orientation.kt
│ │ │ │ └── Robot.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RobotTest.kt
│ │ ├── roman-numerals/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── fold-repeat/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RomanNumerals.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RomanNumerals.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RomanNumeralsTest.kt
│ │ ├── rotational-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RotationalCipher.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RotationalCipher.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RotationalCipherTest.kt
│ │ ├── run-length-encoding/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RunLengthEncoding.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RunLengthEncoding.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RunLengthEncodingTest.kt
│ │ ├── saddle-points/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Matrix.kt
│ │ │ │ │ └── MatrixCoordinate.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Matrix.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MatrixTest.kt
│ │ ├── say/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Say.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Say.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── NumberSpellerTest.kt
│ │ ├── scale-generator/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Scale.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Scale.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ScaleTest.kt
│ │ ├── scrabble-score/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── introduction.md
│ │ │ │ ├── map/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── when/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ScrabbleScore.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ScrabbleScore.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ScrabbleScoreTest.kt
│ │ ├── secret-handshake/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── HandshakeCalculator.kt
│ │ │ │ │ └── Signal.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── HandshakeCalculator.kt
│ │ │ │ └── Signal.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── HandshakeCalculatorTest.kt
│ │ ├── series/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Series.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Series.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SeriesTest.kt
│ │ ├── sieve/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Sieve.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Sieve.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SieveTest.kt
│ │ ├── simple-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── SimpleCipher.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── SimpleCipher.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ ├── IncorrectKeyCipherTest.kt
│ │ │ ├── RandomKeyCipherTest.kt
│ │ │ ├── SimpleCipherTest.kt
│ │ │ └── SubstitutionCipherTest.kt
│ │ ├── space-age/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── SpaceAge.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── SpaceAge.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SpaceAgeTest.kt
│ │ ├── spiral-matrix/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── SpiralMatrix.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── SpiralMatrix.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SpiralMatrixTest.kt
│ │ ├── strain/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── Strain.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Strain.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── StrainTest.kt
│ │ ├── sublist/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Relationship.kt
│ │ │ │ │ └── Sublist.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Sublist.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SublistTest.kt
│ │ ├── sum-of-multiples/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── SumOfMultiples.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── SumOfMultiples.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SumOfMultiplesTest.kt
│ │ ├── transpose/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Transpose.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Transpose.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── TransposeTest.kt
│ │ ├── triangle/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Triangle.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Triangle.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── TriangleTest.kt
│ │ ├── two-fer/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── TwoFer.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── TwoFer.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── TwoFerTest.kt
│ │ ├── word-count/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── findall-groupingby-eachcount/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── WordCount.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── WordCount.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── WordCountTest.kt
│ │ ├── wordy/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Wordy.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Wordy.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── WordyTest.kt
│ │ ├── yacht/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Yacht.kt
│ │ │ │ │ └── YachtCategory.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Yacht.kt
│ │ │ │ └── YachtCategory.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── YachtTest.kt
│ │ └── zebra-puzzle/
│ │ ├── .docs/
│ │ │ ├── instructions.md
│ │ │ └── introduction.md
│ │ ├── .meta/
│ │ │ ├── config.json
│ │ │ ├── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ ├── HeapsPermutation.kt
│ │ │ │ └── ZebraPuzzle.kt
│ │ │ ├── tests.toml
│ │ │ └── version
│ │ ├── build.gradle.kts
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── settings.gradle.kts
│ │ └── src/
│ │ ├── main/
│ │ │ └── kotlin/
│ │ │ └── ZebraPuzzle.kt
│ │ └── test/
│ │ └── kotlin/
│ │ └── ZebraPuzzleTest.kt
│ ├── settings.gradle.kts
│ └── shared/
│ └── .docs/
│ ├── help.md
│ └── tests.md
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── reference/
│ └── implementing-a-concept-exercise.md
└── scripts/
├── canonical_data_check.sh
├── fix_exercises_symlinks.sh
├── updateGradleFilesFromTemplate.kts
└── updateTemplateBuildFile.kts
================================================
FILE CONTENTS
================================================
================================================
FILE: .appends/.github/labels.yml
================================================
# ----------------------------------------------------------------------------------------- #
# These are the repository-specific labels that augment the Exercise-wide labels defined in #
# https://github.com/exercism/org-wide-files/blob/main/global-files/.github/labels.yml. #
# ----------------------------------------------------------------------------------------- #
- name: "good first issue"
description: ""
color: "fafafa"
- name: "help wanted"
description: ""
color: "Ff7f00"
- name: "issue: in progress"
description: "Issue that is already occupied by somebody (usually by assigned person)."
color: "7987f2"
- name: "issue: meta"
description: "Meta-discussions."
color: "d4c5f9"
- name: "issue: new exercise"
description: "Request to add new exercise."
color: "ff9682"
- name: "issue: ready for dev"
description: "Issue is ready for development."
color: "97e87d"
- name: "issue: requires investigation"
description: "This issue requires further investigation from maintainers."
color: "26b75e"
- name: "issue: waiting response"
description: "Issue marked with this label requires additional information from the author."
color: "005b93"
- name: "meta:v3"
description: "Discussions related to exercism v3"
color: "006b75"
- name: "pr: dont merge"
description: "Don't merge this PR for some reasons (e.g. tests are failing)."
color: "ea3c99"
- name: "pr: not ready"
description: ""
color: "ff0000"
- name: "pr: rebase required"
description: "PR marked with this label requires rebase on other branch (`master` by default)."
color: "eeeeee"
- name: "pr: review needed"
description: ""
color: "268902"
================================================
FILE: .github/CODEOWNERS
================================================
# Code owners
.github/CODEOWNERS @exercism/maintainers-admin
# Changes to `fetch-configlet` should be made in the `exercism/configlet` repo
bin/fetch-configlet @exercism/maintainers-admin
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
# Keep dependencies for GitHub Actions up-to-date
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'monthly'
================================================
FILE: .github/labels.yml
================================================
# --------------------------------------------------------------- #
# This is an auto-generated file - Do not manually edit this file #
# --------------------------------------------------------------- #
# This file is automatically generated by concatenating two files:
#
# 1. The Exercism-wide labels: defined in https://github.com/exercism/org-wide-files/blob/main/global-files/.github/labels.yml
# 2. The repository-specific labels: defined in the `.appends/.github/labels.yml` file within this repository.
#
# If any of these two files change, a pull request is automatically created containing a re-generated version of this file.
# Consequently, to change repository-specific labels you should update the `.appends/.github/labels.yml` file and _not_ this file.
#
# When the pull request has been merged, the GitHub labels will be automatically updated by the "Sync labels" workflow.
# This typically takes 5-10 minutes.
# --------------------------------------------------------------------- #
# These are the Exercism-wide labels which are shared across all repos. #
# --------------------------------------------------------------------- #
# The following Exercism-wide labels are used to show "tasks" on the website, which will point users to things they can contribute to.
# The `x:action/<value>` labels describe what sort of work the contributor will be engaged in when working on the issue
- name: "x:action/create"
description: "Work on something from scratch"
color: "ffffff"
- name: "x:action/fix"
description: "Fix an issue"
color: "ffffff"
- name: "x:action/improve"
description: "Improve existing functionality/content"
color: "ffffff"
- name: "x:action/proofread"
description: "Proofread text"
color: "ffffff"
- name: "x:action/sync"
description: "Sync content with its latest version"
color: "ffffff"
# The `x:knowledge/<value>` labels describe how much Exercism knowledge is required by the contributor
- name: "x:knowledge/none"
description: "No existing Exercism knowledge required"
color: "ffffff"
- name: "x:knowledge/elementary"
description: "Little Exercism knowledge required"
color: "ffffff"
- name: "x:knowledge/intermediate"
description: "Quite a bit of Exercism knowledge required"
color: "ffffff"
- name: "x:knowledge/advanced"
description: "Comprehensive Exercism knowledge required"
color: "ffffff"
# The `x:module/<value>` labels indicate what part of Exercism the contributor will be working on
- name: "x:module/analyzer"
description: "Work on Analyzers"
color: "ffffff"
- name: "x:module/concept"
description: "Work on Concepts"
color: "ffffff"
- name: "x:module/concept-exercise"
description: "Work on Concept Exercises"
color: "ffffff"
- name: "x:module/generator"
description: "Work on Exercise generators"
color: "ffffff"
- name: "x:module/practice-exercise"
description: "Work on Practice Exercises"
color: "ffffff"
- name: "x:module/representer"
description: "Work on Representers"
color: "ffffff"
- name: "x:module/test-runner"
description: "Work on Test Runners"
color: "ffffff"
# The `x:rep/<value>` labels describe the amount of reputation to award
#
# For more information on reputation and how these labels should be used,
# check out https://exercism.org/docs/using/product/reputation
- name: "x:rep/tiny"
description: "Tiny amount of reputation"
color: "ffffff"
- name: "x:rep/small"
description: "Small amount of reputation"
color: "ffffff"
- name: "x:rep/medium"
description: "Medium amount of reputation"
color: "ffffff"
- name: "x:rep/large"
description: "Large amount of reputation"
color: "ffffff"
- name: "x:rep/massive"
description: "Massive amount of reputation"
color: "ffffff"
# The `x:size/<value>` labels describe the expected amount of work for a contributor
- name: "x:size/tiny"
description: "Tiny amount of work"
color: "ffffff"
- name: "x:size/small"
description: "Small amount of work"
color: "ffffff"
- name: "x:size/medium"
description: "Medium amount of work"
color: "ffffff"
- name: "x:size/large"
description: "Large amount of work"
color: "ffffff"
- name: "x:size/massive"
description: "Massive amount of work"
color: "ffffff"
# The `x:status/<value>` label indicates if there is already someone working on the issue
- name: "x:status/claimed"
description: "Someone is working on this issue"
color: "ffffff"
# The `x:type/<value>` labels describe what type of work the contributor will be engaged in
- name: "x:type/ci"
description: "Work on Continuous Integration (e.g. GitHub Actions workflows)"
color: "ffffff"
- name: "x:type/coding"
description: "Write code that is not student-facing content (e.g. test-runners, generators, but not exercises)"
color: "ffffff"
- name: "x:type/content"
description: "Work on content (e.g. exercises, concepts)"
color: "ffffff"
- name: "x:type/docker"
description: "Work on Dockerfiles"
color: "ffffff"
- name: "x:type/docs"
description: "Work on Documentation"
color: "ffffff"
# This Exercism-wide label is added to all automatically created pull requests that help migrate/prepare a track for Exercism v3
- name: "v3-migration 🤖"
description: "Preparing for Exercism v3"
color: "e99695"
# This Exercism-wide label can be used to bulk-close issues in preparation for pausing community contributions
- name: "paused"
description: "Work paused until further notice"
color: "e4e669"
# ----------------------------------------------------------------------------------------- #
# These are the repository-specific labels that augment the Exercise-wide labels defined in #
# https://github.com/exercism/org-wide-files/blob/main/global-files/.github/labels.yml. #
# ----------------------------------------------------------------------------------------- #
- name: "good first issue"
description: ""
color: "fafafa"
- name: "help wanted"
description: ""
color: "Ff7f00"
- name: "issue: in progress"
description: "Issue that is already occupied by somebody (usually by assigned person)."
color: "7987f2"
- name: "issue: meta"
description: "Meta-discussions."
color: "d4c5f9"
- name: "issue: new exercise"
description: "Request to add new exercise."
color: "ff9682"
- name: "issue: ready for dev"
description: "Issue is ready for development."
color: "97e87d"
- name: "issue: requires investigation"
description: "This issue requires further investigation from maintainers."
color: "26b75e"
- name: "issue: waiting response"
description: "Issue marked with this label requires additional information from the author."
color: "005b93"
- name: "meta:v3"
description: "Discussions related to exercism v3"
color: "006b75"
- name: "pr: dont merge"
description: "Don't merge this PR for some reasons (e.g. tests are failing)."
color: "ea3c99"
- name: "pr: not ready"
description: ""
color: "ff0000"
- name: "pr: rebase required"
description: "PR marked with this label requires rebase on other branch (`master` by default)."
color: "eeeeee"
- name: "pr: review needed"
description: ""
color: "268902"
================================================
FILE: .github/workflows/configlet.yml
================================================
name: Configlet
on:
pull_request:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
jobs:
configlet:
uses: exercism/github-actions/.github/workflows/configlet.yml@main
================================================
FILE: .github/workflows/no-important-files-changed.yml
================================================
name: No important files changed
on:
pull_request_target:
types: [opened]
branches: [main]
paths:
- "exercises/concept/**"
- "exercises/practice/**"
- "!exercises/*/*/.approaches/**"
- "!exercises/*/*/.articles/**"
- "!exercises/*/*/.docs/**"
- "!exercises/*/*/.meta/**"
permissions:
pull-requests: write
jobs:
check:
uses: exercism/github-actions/.github/workflows/check-no-important-files-changed.yml@main
with:
repository: ${{ github.event.pull_request.head.repo.owner.login }}/${{ github.event.pull_request.head.repo.name }}
ref: ${{ github.head_ref }}
================================================
FILE: .github/workflows/pause-community-contributions.yml
================================================
name: Pause Community Contributions
on:
issues:
types:
- opened
pull_request_target:
types:
- opened
paths-ignore:
- 'exercises/*/*/.approaches/**'
- 'exercises/*/*/.articles/**'
permissions:
issues: write
pull-requests: write
jobs:
pause:
if: github.repository_owner == 'exercism' # Stops this job from running on forks
uses: exercism/github-actions/.github/workflows/community-contributions.yml@main
with:
forum_category: kotlin
secrets:
github_membership_token: ${{ secrets.COMMUNITY_CONTRIBUTIONS_WORKFLOW_TOKEN }}
================================================
FILE: .github/workflows/ping-cross-track-maintainers-team.yml
================================================
name: Ping cross-track maintainers team
on:
pull_request_target:
types:
- opened
permissions:
pull-requests: write
jobs:
ping:
if: github.repository_owner == 'exercism' # Stops this job from running on forks
uses: exercism/github-actions/.github/workflows/ping-cross-track-maintainers-team.yml@main
secrets:
github_membership_token: ${{ secrets.COMMUNITY_CONTRIBUTIONS_WORKFLOW_TOKEN }}
================================================
FILE: .github/workflows/run-configlet-sync.yml
================================================
name: Run Configlet Sync
on:
workflow_dispatch:
schedule:
- cron: '0 0 15 * *'
jobs:
call-gha-workflow:
uses: exercism/github-actions/.github/workflows/configlet-sync.yml@main
================================================
FILE: .github/workflows/sync-labels.yml
================================================
name: Tools
on:
push:
branches:
- main
paths:
- .github/labels.yml
- .github/workflows/sync-labels.yml
workflow_dispatch:
schedule:
- cron: 0 0 1 * * # First day of each month
permissions:
issues: write
jobs:
sync-labels:
uses: exercism/github-actions/.github/workflows/labels.yml@main
================================================
FILE: .github/workflows/test.yml
================================================
name: Kotlin / Test
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Run tests for all exercises
run: bin/journey-test.sh
================================================
FILE: .gitignore
================================================
*.swp
.DS_Store
bin/configlet
bin/configlet.exe
bin/jq*
CHECKLIST
build
.gradle
.idea
*.iml
out/
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of Conduct
## Introduction
Exercism is a platform centered around empathetic conversation.
We have a low tolerance for communication that makes anyone feel unwelcome, unsupported, insulted or discriminated against.
## Seen or experienced something uncomfortable?
If you see or experience abuse, harassment, discrimination, or feel unsafe or upset, please email [abuse@exercism.org](mailto:abuse@exercism.org?subject=%5BCoC%5D) and include \[CoC\] in the subject line.
We will follow up with you as a priority.
## Enforcement
We actively monitor for Code of Conduct (CoC) violations and take any reports of violations extremely seriously.
We have banned contributors, mentors and users due to violations.
After we receive a report of a CoC violation, we view that person's conversation history on Exercism and related communication channels and attempt to understand whether someone has deliberately broken the CoC, or accidentally crossed a line.
We generally reach out to the person who has been reported to discuss any concerns we have and warn them that repeated violations will result in a ban.
Sometimes we decide that no violation has occurred and that no action is required and sometimes we will also ban people on a first offense.
We strive to be fair, but will err on the side of protecting the culture of our community.
Exercism's leadership reserve the right to take whatever action they feel appropriate with regards to CoC violations.
## The simple version
- Be empathetic
- Be welcoming
- Be kind
- Be honest
- Be supportive
- Be polite
## The details
Exercism should be a safe place for everybody regardless of
- Gender, gender identity or gender expression
- Sexual orientation
- Disability
- Physical appearance (including but not limited to body size)
- Race
- Age
- Religion
- Anything else you can think of
As someone who is part of this community, you agree that:
- We are collectively and individually committed to safety and inclusivity
- We have zero tolerance for abuse, harassment, or discrimination
- We respect people’s boundaries and identities
- We refrain from using language that can be considered offensive or oppressive (systemically or otherwise), eg. sexist, racist, homophobic, transphobic, ableist, classist, etc.
- this includes (but is not limited to) various slurs.
- We avoid using offensive topics as a form of humor
We actively work towards:
- Being a safe community
- Cultivating a network of support & encouragement for each other
- Encouraging responsible and varied forms of expression
We condemn:
- Stalking, doxxing, or publishing private information
- Violence, threats of violence or violent language
- Anything that compromises people’s safety
- Conduct or speech which might be considered sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory or offensive in nature
- The use of unwelcome, suggestive, derogatory or inappropriate nicknames or terms
- Disrespect towards others (jokes, innuendo, dismissive attitudes) and towards differences of opinion
- Intimidation or harassment (online or in-person).
Please read the [Citizen Code of Conduct](https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md) for how we interpret harassment
- Inappropriate attention or contact
- Not understanding the differences between constructive criticism and disparagement
These things are NOT OK.
Be aware of how your actions affect others.
If it makes someone uncomfortable, stop.
If you say something that is found offensive, and you are called out on it, try to:
- Listen without interruption
- Believe what the person is saying & do not attempt to disqualify what they have to say
- Ask for tips / help with avoiding making the offense in the future
- Apologize and ask forgiveness
## History
This policy was initially adopted from the Front-end London Slack community and has been modified since.
A version history can be seen on [GitHub](https://github.com/exercism/website-copy/edit/main/pages/code_of_conduct.md).
_This policy is a "living" document, and subject to refinement and expansion in the future.
This policy applies to the Exercism website, the Exercism GitHub organization, any other Exercism-related communication channels (e.g. Discord, Forum, Twitter, email) and any other Exercism entity or event._
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 Exercism
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Exercism Kotlin Track
[](https://travis-ci.org/exercism/kotlin)
Source for Exercism Exercises in Kotlin.
## Contributing Guide
For general information about how to contribute to Exercism, please refer to the [contributing guide](https://exercism.org/docs/building).
## Table of Contents
* [Overview](#overview)
* [Contributing With Minimal Setup](#contributing-with-minimal-setup)
* [Getting Familiar With the Codebase](#getting-familiar-with-the-codebase)
* [The `exercises` Module](#the-exercises-module)
* [The Problem Submodules](#the-problem-submodules)
* [Advanced: Complete Local Setup](#advanced-complete-local-setup)
* [Tip: `gradle clean` before `exercism fetch`](#tip-gradle-clean-before-exercism-fetch)
## Overview
This guide covers contributing to the Kotlin track. If you are new, this guide is for you.
If, at any point, you're having any trouble, pop in the [Building Exercism](https://forum.exercism.org/c/exercism/building-exercism/125) category of the [Exercism forum](https://forum.exercism.org/) for help.
## Contributing With Minimal Setup
First things first: by contributing to Exercism, you are making this learning tool that much better and improving our industry as a whole... thank you!!!
To submit a fix for an existing exercise or port an exercise to Kotlin with the least amount of setup:
1. **Ensure you have the basic Java tooling installed:** JDK 1.8+, an editor and Gradle 2.x.
(see [exercism.io: Installing Kotlin](https://exercism.org/docs/tracks/kotlin/installation))
- **Setup a branch on a fork of [exercism/kotlin](https://github.com/exercism/kotlin) on your computer.**
Next steps:
* "fork" a repository on GitHub;
- install `git`;
- "clone" a copy of your fork;
- configure an "upstream remote" (in this case, `exercism/kotlin`);
- create a branch to house your work
- **Write the codes.** Do your work on that branch you just created.
The [Getting Familiar With the Codebase](#getting-familiar-with-the-codebase) section, below, is an orientation.
- **Commit, push and create a pull request.**
Something like:
```
$ git add .
$ git commit -m "(An intention-revealing commit message)"
$ git push
```
It is advised you write meaningful commit messages. [Chris Beams wrote about "How to Write a Git Commit Message"](https://chris.beams.io/posts/git-commit/).
- **Verify that your work passes all tests.** When you create a pull request (PR), GitHub triggers a build on Travis CI. Your PR will not be merged unless those tests pass.
## Getting Familiar With the Codebase
There are two objectives to the design of this build:
1. when a problem is built from within the `exercism/kotlin` repo (i.e. when you, the contributor, are developing the exercise), the tests run against the reference solution;
2. when a problem is built outside the `exercism/kotlin` repo (when a participant is solving the exercise), the tests run against the "main" code.
This repo is a multi-project gradle build.
### The `exercises` Module
This is the top-level module, contained in the `exercises` directory. It is a container for the problem sub-modules.
* its `build.gradle` points the "main" sourceset to the reference solution.
* its `settings.gradle` names each of the subprojects, one for each problem in the set.
### The Problem Submodules
The `exercises` subdirectory contains all of the problem submodules.
Each problem/submodule is a subdirectory of the same name as its slug.
* its `build.gradle.kts` names dependencies required to work that problem.
Each problem/submodule has three source sets:
* `src/test/kotlin/` — a test suite defining the edges of the problem
* `.meta/src/reference/kotlin/` — a reference solution that passes all the tests
* `src/main/kotlin/` — starter source files, if required/desired *(this directory usually only has a `.keep` file in it)*.
To run the tests for a specific exercise, run the `test` Gradle task from the exercises
directory. For example:
```bash
cd exercises
https://github.com/exercism/v3/blob/main/gradlew bob:test
```
Steps for modifying an exercise:
1. Change the test(s).
2. Watch the changes fail.
3. Update the reference solution to make the test(s) pass.
----
## Advanced: Complete Local Setup
If you are going to make significant contribution(s) to the track, you might find it handy to have a complete local install of exercism on your computer. This way, you can run the full suite of tests without having to create/update a PR.
The easiest way to achieve this is simply use the `bin/journey-test.sh` script. However, you may want to perform other tests, depending on what you are doing. You can do so by duplicating the setup performed by the `bin/journey-test.sh` script.
### Tip: `gradle clean` before `exercism fetch`
If you `exercism fetch` after doing a build, the CLI will fail with the following error message:
```
$ exercism fetch kotlin bob
2015/09/06 15:03:21 an internal server error was received.
Please file a bug report with the contents of 'exercism debug' at: https://github.com/exercism/exercism.io/issues
```
and if you review the logs of your x-api, you'll find:
```
127.0.0.1 - - [06/Sep/2015:15:20:56 -0700] "GET /v2/exercises/kotlin/bob HTTP/1.1" 500 514949 0.2138
2015-09-06 15:21:01 - JSON::GeneratorError - source sequence is illegal/malformed utf-8:
```
This is because some files generated by the build can't be served from the x-api. This is by design: the CLI does not serve binaries. To fix this, simply make sure you do a clean in your `exercism/kotlin` repo before you fetch:
```
cd ~/workspace/exercism/kotlin/exercises
gradle clean
cd ~/workspace/exercism/exercises
exercism fetch kotlin bob
```
================================================
FILE: _template/build.gradle.kts
================================================
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
plugins {
kotlin("jvm")
}
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
testImplementation("junit:junit:4.13.2")
testImplementation(kotlin("test-junit"))
}
tasks.withType<Test> {
testLogging {
exceptionFormat = TestExceptionFormat.FULL
events("passed", "failed", "skipped")
}
}
================================================
FILE: _template/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: _template/gradlew
================================================
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
================================================
FILE: _template/gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: _template/settings.gradle.kts
================================================
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
resolutionStrategy {
eachPlugin {
when (requested.id.id) {
"org.jetbrains.kotlin.jvm" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0")
}
}
}
}
================================================
FILE: _template/src/example/kotlin/.keep
================================================
================================================
FILE: _template/src/main/kotlin/.keep
================================================
================================================
FILE: _template/src/test/kotlin/.keep
================================================
================================================
FILE: bin/README.md
================================================
# Cross-track consistency
Many of these scripts are shared between the Java and Kotlin tracks. If you make an update to a script in one of these tracks, please also update the same script in the other track if appropriate. Thank you!
================================================
FILE: bin/build-jq.sh
================================================
#!/usr/bin/env bash
set -ex
pushd bin
curl --location https://github.com/stedolan/jq/releases/download/jq-1.5/jq-1.5.tar.gz >jq-1.5.tar.gz
tar xvf jq-1.5.tar.gz
cd jq-1.5
./configure --disable-maintainer-mode && make
mv jq ..
popd
================================================
FILE: bin/fetch-configlet
================================================
#!/usr/bin/env bash
# This file is a copy of the
# https://github.com/exercism/configlet/blob/main/scripts/fetch-configlet file.
# Please submit bugfixes/improvements to the above file to ensure that all tracks benefit from the changes.
set -eo pipefail
curlopts=(
--silent
--show-error
--fail
--location
--retry 3
)
if [[ -n "${GITHUB_TOKEN}" ]]; then
curlopts+=(--header "authorization: Bearer ${GITHUB_TOKEN}")
fi
get_download_url() {
local os="$1"
local ext="$2"
local latest='https://api.github.com/repos/exercism/configlet/releases/latest'
local arch
case "$(uname -m)" in
aarch64|arm64) arch='arm64' ;;
x86_64) arch='x86-64' ;;
*686*) arch='i386' ;;
*386*) arch='i386' ;;
*) arch='x86-64' ;;
esac
local suffix="${os}_${arch}.${ext}"
curl "${curlopts[@]}" --header 'Accept: application/vnd.github.v3+json' "${latest}" |
grep "\"browser_download_url\": \".*/download/.*/configlet.*${suffix}\"$" |
cut -d'"' -f4
}
main() {
local output_dir
if [[ -d ./bin ]]; then
output_dir="./bin"
elif [[ $PWD == */bin ]]; then
output_dir="$PWD"
else
echo "Error: no ./bin directory found. This script should be ran from a repo root." >&2
return 1
fi
local os
case "$(uname -s)" in
Darwin*) os='macos' ;;
Linux*) os='linux' ;;
Windows*) os='windows' ;;
MINGW*) os='windows' ;;
MSYS_NT-*) os='windows' ;;
*) os='linux' ;;
esac
local ext
case "${os}" in
windows) ext='zip' ;;
*) ext='tar.gz' ;;
esac
echo "Fetching configlet..." >&2
local download_url
download_url="$(get_download_url "${os}" "${ext}")"
local output_path="${output_dir}/latest-configlet.${ext}"
curl "${curlopts[@]}" --output "${output_path}" "${download_url}"
case "${ext}" in
zip) unzip "${output_path}" -d "${output_dir}" ;;
*) tar xzf "${output_path}" -C "${output_dir}" ;;
esac
rm -f "${output_path}"
local executable_ext
case "${os}" in
windows) executable_ext='.exe' ;;
*) executable_ext='' ;;
esac
local configlet_path="${output_dir}/configlet${executable_ext}"
local configlet_version
configlet_version="$(${configlet_path} --version)"
echo "Downloaded configlet ${configlet_version} to ${configlet_path}"
}
main
================================================
FILE: bin/journey-test.sh
================================================
#!/usr/bin/env bash
TRACK=kotlin
TRACK_REPO="$TRACK"
EXERCISES_TO_SOLVE=$@
on_exit() {
echo ">>> on_exit()"
cd $EXECPATH
echo "<<< on_exit()"
}
assert_installed() {
local binary=$1
echo ">>> assert_installed(binary=\"${binary}\")"
if [[ "`which $binary`" == "" ]]; then
echo "${binary} not found; it is required to perform this test."
echo -e "Have you completed the setup instructions at https://github.com/exercism/${TRACK_REPO} ?\n"
echo "PATH=${PATH}"
echo "aborting."
exit 1
fi
echo "<<< assert_installed()"
}
clean() {
local build_dir="$1"
echo ">>> clean(build_dir=\"${build_dir}\")"
# empty, absolute path, or parent reference are considered dangerous to rm -rf against.
if [[ "${build_dir}" == "" || ${build_dir} =~ ^/ || ${build_dir} =~ \.\. ]] ; then
echo "Value for build_dir looks dangerous. Aborting."
exit 1
fi
local build_path=$( pwd )/${build_dir}
if [[ -d "${build_path}" ]] ; then
echo "Cleaning journey script build output directory (${build_path})."
rm -rf "${build_path}"
fi
cd exercises
"$EXECPATH"/gradlew clean
cd ..
echo "<<< clean()"
}
solve_exercise() {
local exercise="$1"
local exercise_type="$2"
echo -e "\n\n"
echo "=================================================="
echo "Solving ${exercise}"
echo "=================================================="
mkdir -p ${exercism_exercises_dir}/${TRACK}
cp -R -H ${track_root}/exercises/${exercise_type}/${exercise} ${exercism_exercises_dir}/${TRACK}/${exercise}
cp -R -H ${track_root}/exercises/${exercise_type}/${exercise}/.meta/src/reference/${TRACK}/* ${exercism_exercises_dir}/${TRACK}/${exercise}/src/main/${TRACK}/
pushd ${exercism_exercises_dir}/${TRACK}/${exercise}
# Check that tests compile before we strip @Ignore annotations
"$EXECPATH"/gradlew compileTestJava
# Ensure we run all the tests (as delivered, all but the first is @Ignore'd)
for testfile in `find src/test/kotlin -name "*Test.kt"`; do
# Strip @Ignore annotations to ensure we run the tests (as delivered, all but the first is @Ignore'd).
# Note that unit-test.sh also strips @Ignore annotations via the Gradle task copyTestsFilteringIgnores.
# The stripping implementations here and in copyTestsFilteringIgnores should be kept consistent.
sed 's/@Ignore\(\(.*\)\)\{0,1\}//' ${testfile} > "${tempfile}" && mv "${tempfile}" "${testfile}"
done
"$EXECPATH"/gradlew test
echo "exit code: $?"
popd
}
solve_all_exercises() {
local exercism_exercises_dir="$1"
echo ">>> solve_all_exercises(exercism_exercises_dir=\"${exercism_exercises_dir}\")"
local track_root=$( pwd )
local concept_exercises=`jq -r '.exercises.concept[].slug' config.json | sort | xargs`
local practice_exercises=`jq -r '.exercises.practice[].slug' config.json | sort | xargs`
local total_exercises=`jq '.exercises.concept + .exercises.practice | length' config.json`
local current_exercise_number=1
local tempfile="${TMPDIR:-/tmp}/journey-test.sh-unignore_all_tests.txt"
mkdir -p ${exercism_exercises_dir}
pushd ${exercism_exercises_dir}
for exercise in $concept_exercises; do
echo -e "\n\n"
echo "=================================================="
echo "${current_exercise_number} of ${total_exercises} -- ${exercise}"
echo "=================================================="
solve_exercise "${exercise}" "concept"
current_exercise_number=$((current_exercise_number + 1))
done
for exercise in $practice_exercises; do
echo -e "\n\n"
echo "=================================================="
echo "${current_exercise_number} of ${total_exercises} -- ${exercise}"
echo "=================================================="
solve_exercise "${exercise}" "practice"
current_exercise_number=$((current_exercise_number + 1))
done
popd
}
solve_single_exercise() {
local exercism_exercises_dir="$1"
local exercise_to_solve="$2"
local exercise_type="$3"
echo ">>> solve_single_exercises(exercism_exercises_dir=\"${exercism_exercises_dir}\", exercise_to_solve=\"$exercise_to_solve\")"
local track_root=$( pwd )
local tempfile="${TMPDIR:-/tmp}/journey-test.sh-unignore_all_tests.txt"
mkdir -p ${exercism_exercises_dir}
pushd ${exercism_exercises_dir}
solve_exercise "${exercise_to_solve}" "${exercise_type}"
popd
}
main() {
# all functions assume current working directory is repository root.
cd "${SCRIPTPATH}/.."
local track_root=$( pwd )
local build_dir="build"
local build_path="${track_root}/${build_dir}"
local exercism_home="${build_path}/exercism"
# fail fast if required binaries are not installed.
assert_installed "jq"
clean "${build_dir}"
if [[ $EXERCISES_TO_SOLVE == "" ]]; then
solve_all_exercises "${exercism_home}"
else
for exercise in $EXERCISES_TO_SOLVE; do
if [ -d "${exercism_home}/exercises/concept/${exercise}" ]; then
solve_single_exercise "${exercism_home}" "${exercise}" "concept"
else
solve_single_exercise "${exercism_home}" "${exercise}" "practice"
fi
done
fi
}
##########################################################################
# Execution begins here...
# If any command fails, fail the script.
set -exo pipefail
SCRIPTPATH=$( pushd `dirname $0` > /dev/null && pwd && popd > /dev/null )
EXECPATH=$( pwd )
# Make output easier to read in CI
TERM=dumb
trap on_exit EXIT
main
================================================
FILE: bin/run-journey-test-from-ci.sh
================================================
#!/bin/bash
contains_setup_file() {
local files=$1
for file in $files; do
if [[ $file == *.gradle || $file == *.gradle.kts || $file == *.sh || $file == config.json ]]; then
return 0
fi
done
return 1
}
contains_exercise() {
local files=$1
for file in $files; do
if [[ $file == exercises* ]]; then
return 0
fi
done
return 1
}
run_journey_test_with_modified_exercises() {
local modded_files=$1
local last_modded_exercise=""
local modded_exercises=""
for file in $modded_files; do
if [[ $file == exercises* ]] && [[ $file != exercises/settings.gradle ]] && [[ $file != exercises/build.gradle.kts ]]; then
local modded_exercise=${file#exercises/}
modded_exercise=${modded_exercise%%/*}
if [[ $last_modded_exercise != $modded_exercise ]]; then
modded_exercises=$modded_exercises$modded_exercise$'\n'
fi
last_modded_exercise=$modded_exercise
fi
done
echo "Running journey test with modified exercise(s): ${modded_exercises}"
bin/journey-test.sh $modded_exercises
}
run_journey_test_with_all_exercises() {
echo "Running journey test with all exercises"
bin/journey-test.sh
}
main() {
bin/build-jq.sh
local pr_files_json=`curl -s https://api.github.com/repos/exercism/kotlin/pulls/${TRAVIS_PULL_REQUEST}/files`
echo "Pull request number: ${TRAVIS_PULL_REQUEST}"
echo "Changes in pr json: ${pr_files_json}"
# if jq fails to get the required data, then that means TRAVIS_PULL_REQUEST was not set (not run in travis-ci),
# or was false (not a pull request), or the api limit was reached, or some other error occurred.
# In that case, we should fall back with testing every exercise
local pr_files_json_type=`echo $pr_files_json | bin/jq -r 'type'`
if [[ $pr_files_json_type != "array" ]]; then
echo "Didn't get pr changes from travis"
run_journey_test_with_all_exercises
return
fi
local modded_files=`echo $pr_files_json | bin/jq -r '.[].filename'`
# If the changed files contain a .sh file or .gradle.kts file or config.json then we should run all the exercises
if contains_setup_file "${modded_files}"; then
echo "Pr changes contain setup file(s): ${modded_files}"
run_journey_test_with_all_exercises
return
fi
if contains_exercise "${modded_files}"; then
echo "Pr changes contain modified exercise file(s)"
run_journey_test_with_modified_exercises "${modded_files}"
fi
}
trap 'exit 1' ERR
main
================================================
FILE: bin/unit-tests.sh
================================================
#!/usr/bin/env bash
set -e
./gradlew --version
# Clean up any left-over files from a previous invocation, to avoid configlet
# erroring when it finds an unexpected directory inside exercises.
rm -rf ./exercises/build
echo ""
echo ">>> Running configlet..."
bin/fetch-configlet
bin/configlet lint
pushd exercises
echo ""
echo ">>> Running tests..."
TERM=dumb ../gradlew check compileStarterSourceKotlin --continue
popd
================================================
FILE: concepts/basics/.meta/config.json
================================================
{
"blurb": "TODO: add blurb for basics concept",
"authors": [
"dector"
],
"contributors": []
}
================================================
FILE: concepts/basics/about.md
================================================
# About Basics
Kotlin is a statically typed language, designed to be fully interoperable with Java.
Distinguishing it from Java, Kotlin:
- has a cleaner, more concise syntax;
- incorporates many features of functional languages;
- has extensive support for nullable values.
## Variables
Because Kotlin is statically typed, it is necessary to _know_ the type of each value at compile time.
However, Kotlin's [type inference][inference] is very powerful, so _specifying_ the type is often optional.
There are two ways to declare a variable.
1. `val` creates an immutable variable, and trying to change it is a compile-time error.
```kotlin
val x = 42 // => 42
x = 43 // => 'val' cannot be reasssigned
```
2. `var` creates a mutable variable.
```Kotlin
var x = 42 // => 42
x = 43 // => 43
```
Because immutable variables eliminate a common class of bugs, use of `val` is encouraged whenever possible.
Also, even a `var` cannot change type:
```kotlin
var x = 42
x = "foobar" // => Type mismatch: inferred type is String but Int was expected
```
To reduce visual distraction, explicit types will mostly be omitted from this syllabus.
Nevertheless, it is recommended to specify types at least for:
- public APIs
- function signatures
- where it needs documentation
Some companies and organisations will require strict type safety and disallow type inference, whilst others restrict it to "simple" types, or embrace type inference fully.
```kotlin
val x: Int = 42 // => 42
```
In general, the names of variables and functions should be in `camelCase`, not `snake_case`
## Functions
Declare a function with the `fun` keyword.
Unlike Java, functions are not required to be part of a class.
```Kotlin
fun hello(): String {
return "Hello, World!"
}
fun add(x: Int, y: Int): Int {
return x + y
}
```
Some points to note:
- Parentheses `()` are needed after the function name, even if the function takes no arguments.
- Function arguments need to specify the type: there is no type inference (in contrast to variables).
- The body of the function is enclosed in braces `{ }` (though see below).
- The `return` keyword is required, if returning a value.
- Semicolons `;` at the end of lines are optional, and usually omitted.
- Arithmetic operators `+`, `-`, `*`, `/` are similar to most mainstream languages.
However, for these very simple, "single-expression" functions, there is an abbreviated syntax:
```Kotlin
// return type is usually omitted for single-expression functions
fun add(x: Int, y: Int) = x + y
```
Functions can have parameters with default values.
These values will be used if they are omitted where the function is invoked:
```kotlin
fun ping(host: String = "localhost") {
println("PING --> $host")
}
ping("exercism.io") // PING --> exercism.io
ping() // PING --> localhost
```
Functions within Exercism will usually return a value (because of the way the test runner is structured).
To use Kotlin more widely, it may be useful to know that a function which returns no value can omit the return type and the return keyword.
It is then said to have a `Unit` return type: equivalent to `void` in Java and several other languages.
## Comments
Single-line comments start with `//`, and the rest of the line is then ignored.
Multi-line comments start with `/*` and end with `*/`
```Kotlin
fun hello(): String {
/*
* Failing to run this program on a new installation
* is considered bad luck
*/
return "Hello, World!" // the compiler pixies are now happy
}
```
This is the same as Java.
~~~~exercism/note
Because of the importance of Java interop, many Kotlin learners are at least somewhat familiar with Java.
We will try to point out similarities and differences between the languages throughout the syllabus.
_Please ignore this if you are a Kotlin-first learner!_
~~~~
[inference]: https://en.wikipedia.org/wiki/Type_inference
================================================
FILE: concepts/basics/introduction.md
================================================
# Introduction
Kotlin is a **statically typed** programming language developed by JetBrains. This means that the type of variables is defined at compile-time.
## Variables
Similarly to other statically-typed programming languages, the type of each variable should be defined at compile time. You can avoid explicit type declarations where they can be inferred by the compiler from their context.
Kotlin has immutable (`val`) and mutable (`var`) variables. The value of an immutable variable can't be changed after it's initial value is assigned. Most of the time you will use this type of variable.
```kotlin
val robotName = "HAL-9000"
userId = "T-1000" // This will not compile
```
A mutable variable's value can be changed one or more times:
```kotlin
var index = 12
print(index) // 12
index = 100
print(index) // 100
```
Semicolons in Kotlin are optional, except for a few special cases that will be covered later.
## Functions
Functions in Kotlin are defined with the `fun` keyword and are _first-class citizens_ (not related to OOP). It means that you can declare (so-called `top-level functions`) them right in files (e.g. in Java you can define methods only in classes, not in files):
```kotlin
// This is content of the Hello.kt file
fun hello() {}
```
Functions can receive arguments. Each argument has a name and a type. Unlike variables, the type of arguments can't be inferred. Functions can have zero or more arguments:
```kotlin
fun hello() {}
fun hello(name: String) {}
fun hello(name: String, age: Int) {}
```
Kotlin functions might or might not return a value:
```kotlin
fun min(a: Int, b: Int): Int
fun countBonuses(user: User): Bonuses
fun run() {}
```
To return a value from a function, the `return` keyword is used:
```kotlin
fun getName(): String {
return "Alice"
}
```
Functions can have parameters with default values. These values will be used if they are omitted where function is invoked:
```kotlin
fun ping(host: String = "localhost") {
println("PING --> $host")
}
ping("exercism.io") // PING --> exercism.io
ping() // PING --> localhost
```
## Comments
Use `//` to define single-line comment:
```kotlin
foo() // Everything after `//` will be ignored by compiler
// I will be ignored too
```
or `/*` and `*/` to define multi-line comments:
```kotlin
/*
This this an example
for a multiline comment
*/
```
================================================
FILE: concepts/basics/links.json
================================================
[]
================================================
FILE: concepts/bitwise-operations/.meta/config.json
================================================
{
"authors": [
"colinleach"
],
"contributors": [],
"blurb": "Kotlin provides a set of bitwise operations that allow you to manipulate the individual bits of integers."
}
================================================
FILE: concepts/bitwise-operations/about.md
================================================
# About Bits
Binary digits ultimately map directly to the transistors in your CPU or RAM, and whether each is "on" or "off".
Low-level manipulation, informally called "bit-twiddling", is particularly important in system languages.
Higher-level languages like Kotlin usually abstract away most of this detail.
However, a basic range of bit-level operations [is available][ref-bitwise].
~~~~exercism/note
To see human-readable binary output, nearly all the examples below need to be wrapped in an [`Integer.toBinaryString()`][web-binstring] function, or converted with `toString(radix = 2)`.
This is visually distracting, so most occurrences of this function have been edited out, and the results are represented with `0b` notation.
[web-binstring]: https://www.baeldung.com/kotlin/int-binary-representation
~~~~
## Bit-shift operations
`Int` or `Long` types, both signed and unsigned, can be represented as a String of 1's and 0's, and manipulated as a sequence of bits.
Perhaps surprisingly, `Byte` or `Short` types are not compatible with most bitwise operations in Kotlin.
All the examples below use 32-bit integers (`Int` or `UInt`).
```kotlin
val ns = 0b111 // 7 decimal
Integer.toBinaryString(ns) // => "111"
```
Bit-shifts move everything to the left or right by a specified number of positions.
Some bits drop off one end, and the other end is padded with zeros or ones.
- Left shift with `shl`: zero-padding.
- Right shift with `shr` or `ushr`: zero padding for positive numbers (see later section for negative numbers).
```kotlin
val ns = 0b111 // 7 decimal
ns shl 1 // => 0b1110, decimal 14
ns shr 1 // => 0b11, decimal 3
ns ushr 1 // => 0b11
val nu: UInt = 0b111u // 7 unsigned
nu shr 1 // => 0b11
```
Each left-shift doubles the value, and each right-shift halves it (subject to truncation).
This is more obvious in decimal representation:
```kotlin
3 shl 2 // => 12
24 shr 3 // => 3
```
Such bit-shifting is much faster than "proper" arithmetic, making the technique very popular in low-level coding.
### Bit-shifting negative integers
With _negative integers_, we need to be a bit more careful.
Negative values are stored in [two's complement][wiki-2complement] form, which means that the left-most bit is 1.
No problem for a left-shift, but when right-shifting how do we pad the left-most bits?
```kotlin
val ns = -0b111 // => 0b11111111111111111111111111111001
// shift left: simple
ns shl 1 // => 0b11111111111111111111111111110010, decimal -14
// shift right: preserves sign bit
ns shr 1 // => 0b11111111111111111111111111111100, decimal -4
// unsigned shift right: left-pads with zeros
ns ushr 1 // => 0b01111111111111111111111111111100, decimal 2147483644
```
The [`shr`][ref-shr] operator performs [arithmetic shift][wiki-arithmetic], preserving the sign bit.
The [`ushr`][ref-ushr] operator performs [logical shift][wiki-logical], padding with zeros as if the number was unsigned.
## Bitwise logic
We saw in the [Booleans Concept][concept-booleans] that the operators `&&` (and), `||` (or) and `!` (not) are used with boolean values.
There are equivalent operators `and`, `or`, `xor` ([exclusive-or][wiki-xor]) to compare the bits in two integers, and an `inv` (inversion) function to flip all the bits.
```kotlin
0b1011 and 0b0010 // bit is 1 in both numbers
// => 0b0010
0b1011 or 0b0010 // bit is 1 in at least one number
// => 0b1011
0b1011 xor 0b0010 // bit is 1 in exactly one number, not both
// => 0b1001
0b1011.inv() // flip all bits (in a 32-bit signed Int)
// => 0b11111111111111111111111111110100
```
[ref-bitwise]: https://kotlinlang.org/docs/numbers.html#bitwise-operations
[wiki-xor]: https://en.wikipedia.org/wiki/Exclusive_or
[wiki-2complement]: https://en.wikipedia.org/wiki/Two%27s_complement
[wiki-arithmetic]: https://en.wikipedia.org/wiki/Arithmetic_shift
[wiki-logical]: https://en.wikipedia.org/wiki/Logical_shift
[web-binstring]: https://www.baeldung.com/kotlin/int-binary-representation
[ref-shr]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/shr.html
[ref-ushr]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/ushr.html
[concept-booleans]: https://exercism.org/tracks/kotlin/concepts/booleans
================================================
FILE: concepts/bitwise-operations/introduction.md
================================================
# Introduction
Binary digits ultimately map directly to the transistors in your CPU or RAM, and whether each is "on" or "off".
Low-level manipulation, informally called "bit-twiddling", is particularly important in system languages.
Higher-level languages like Kotlin usually abstract away most of this detail.
However, a basic range of bit-level operations [is available][ref-bitwise].
## Bit-shift operations
`Int` or `Long` types, signed or unsigned, can be represented as a string of 1's and 0's and manipulated as a sequence of bits.
Perhaps surprisingly, `Byte` or `Short` types are not compatible with most bitwise operations in Kotlin.
All the examples below use 32-bit integers (`Int` or `UInt`).
```kotlin
val ns = 0b111 // 7 decimal
Integer.toBinaryString(ns) // => "111"
```
Bit-shifts just move everything to the left or right by a specified number of positions.
Some bits drop off one end, and the other end is padded with zeros or ones.
- Left shift with `shl`: zero-padding.
- Right shift with `shr` or `ushr`: zero padding for positive numbers (see later for negative numbers).
```kotlin
val ns = 0b111 // 7 decimal
ns shl 1 // => 0b1110, decimal 14
ns shr 1 // => 0b11, decimal 3
ns ushr 1 // => 0b11
val nu: UInt = 0b111u // 7 unsigned
nu shr 1 // => 0b11
```
Each left-shift doubles the value, and each right-shift halves it (subject to truncation).
This is more obvious in decimal representation:
```kotlin
3 shl 2 // => 12
24 shr 3 // => 3
```
Such bit-shifting is much faster than "proper" arithmetic, making the technique very popular in low-level coding.
With _negative integers_, we need to be a bit more careful.
Negative values are stored in [two's complement][wiki-2complement] form, which means that the left-most bit is 1.
No problem for a left-shift, but when right-shifting how do we pad the left-most bits?
```kotlin
val ns = -0b111 // => 0b11111111111111111111111111111001
// shift left: simple
ns shl 1 // => 0b11111111111111111111111111110010, decimal -14
// shift right: preserves sign bit
ns shr 1 // => 0b11111111111111111111111111111100, decimal -4
// unsigned shift right: left-pads with zeros
ns ushr 1 // => 0b01111111111111111111111111111100, decimal 2147483644
```
The `shr` operator performs [arithmetic shift][wiki-arithmetic], preserving the sign bit.
The `ushr` operator performs [logical shift][wiki-logical], padding with zeros as if the number was unsigned.
## Bitwise logic
We saw in the [Booleans Concept][concept-booleans] that the operators `&&` (and), `||` (or) and `!` (not) are used with boolean values.
There are equivalent operators `and`, `or`, `xor` ([exclusive-or][wiki-xor]) to compare the bits in two integers, and an `inv` (inversion) function to flip all the bits.
```kotlin
0b1011 and 0b0010 // bit is 1 in both numbers
// => 0b0010
0b1011 or 0b0010 // bit is 1 in at least one number
// => 0b1011
0b1011 xor 0b0010 // bit is 1 in exactly one number, not both
// => 0b1001
0b1011.inv() // flip all bits (in a 32-bit signed Int)
// => 0b11111111111111111111111111110100
```
[ref-bitwise]: https://kotlinlang.org/docs/numbers.html#bitwise-operations
[wiki-xor]: https://en.wikipedia.org/wiki/Exclusive_or
[wiki-2complement]: https://en.wikipedia.org/wiki/Two%27s_complement
[wiki-arithmetic]: https://en.wikipedia.org/wiki/Arithmetic_shift
[wiki-logical]: https://en.wikipedia.org/wiki/Logical_shift
[concept-booleans]: https://exercism.org/tracks/kotlin/concepts/booleans
================================================
FILE: concepts/bitwise-operations/links.json
================================================
[
{
"url": "https://kotlinlang.org/docs/numbers.html#bitwise-operations",
"description": "Kotlin manual: bitwise operations"
}
]
================================================
FILE: concepts/booleans/.meta/config.json
================================================
{
"blurb": "TODO: add blurb for booleans concept",
"authors": ["dector"],
"contributors": []
}
================================================
FILE: concepts/booleans/about.md
================================================
# About
Booleans in Kotlin are represented by the `Boolean` type, which values can be either `true` or `false`.
Kotlin supports three built-in [boolean operators][reference]: `!` (negation aka NOT), `&&` (lazy conjunction aka AND), and `||` (lazy disjunction aka OR). The `&&` and `||` operators use _short-circuit evaluation_, which means that the right-hand side of the operator is only evaluated when needed.
```kotlin
true || false // => true
true && false // => false
```
The three boolean operators each have a different [_operator precedence_][precedence]. As a consequence, they are evaluated in this order: `!` first, `&&` second, and finally `||`. If you want to 'escape' these rules, you can enclose a boolean expression in parentheses (`()`), as the parentheses have an even higher operator precedence.
```kotlin
!true && false // => false
!(true && false) // => true
```
[reference]: https://kotlinlang.org/docs/reference/basic-types.html#booleans
[precedence]: https://kotlinlang.org/docs/reference/grammar.html#expressions
================================================
FILE: concepts/booleans/introduction.md
================================================
# Introduction
Booleans in Kotlin are represented by the `Boolean` type, which values can be either `true` or `false`.
Kotlin supports three built-in [boolean operators][reference]: `!` (negation aka NOT), `&&` (lazy conjunction aka AND), and `||` (lazy disjunction aka OR). The `&&` and `||` operators use _short-circuit evaluation_, which means that the right-hand side of the operator is only evaluated when needed.
================================================
FILE: concepts/booleans/links.json
================================================
[
{
"url": "https://kotlinlang.org/docs/reference/basic-types.html#booleans",
"description": "reference"
},
{
"url": "https://kotlinlang.org/docs/reference/grammar.html#expressions",
"description": "precedence"
}
]
================================================
FILE: concepts/chars/.meta/config.json
================================================
{
"authors": [
"colinleach"
],
"contributors": [],
"blurb": "Kotlin was designed from the beginning to use a large subset of Unicode characters, to represent a wide range of writing systems."
}
================================================
FILE: concepts/chars/about.md
================================================
# About chars
This is potentially a _big_ subject!
It is possible to write a long book about it, and several people have done so (search Amazon for "unicode book" to see some examples).
## A very brief history
Handling characters in computers was much simpler in earlier decades, when programmers assumed that English was the only important language.
So: 26 letters, upper and lower case, 10 digits, several punctuation marks, plus a code (0x07) to ring a bell, and it all fitted into 7 bits: the [ASCII][wiki-ascii] character set.
Naturally, people started asking what about à, ä and Ł, then other people started asking about ऄ, ஹ and ญ, and young people wanted emojis 😱.
What to do?
To cut a long story short, many smart and patient people had to serve on committees for years, working out the details of the [Unicode][web-unicode] character set, and of encodings such as [UTF-8][wiki-utf-8], and lots of software needed a _very_ complicated rewrite.
Also, lots of new bugs were introduced.
To prevent _everything_ breaking, the Unicode/UTF-8 design ensures that the first 127 codes are identical to ASCII _(even the bell)_.
## Characters in Kotlin
Languages designed after about 2005 have the huge advantage that a reasonably stable Unicode standard already existed.
Kotlin (first released in 2011) was able to assume that users would use a variety of (human) languages, and would need Unicode to express them.
~~~~exercism/advanced
[Characters][ref-char] in Kotlin are 16-bit (UTF-16) [`codepoints`][wiki-codepoint], the same as a JVM `char`.
This is enough to express most written alphabets, but not the entire range of emojis.
The full Unicode standard uses up to six bytes (48 bits) per character (called a [`grapheme`][wiki-grapheme]).
Kotlin `Strings` support this full standard by using multiple codepoints per character, when necessary.
For example, 😱 would be `\uD83D` and `\uDE31`.
Unfortunately, Java has no built-in grapheme support, and for compatibility neither does Kotlin.
[wiki-codepoint]: https://en.wikipedia.org/wiki/Code_point
[wiki-grapheme]: https://en.wikipedia.org/wiki/Grapheme
[ref-char]: https://kotlinlang.org/docs/characters.html
~~~~
Character literals are written in single-quotes, and are distinct from strings written in double quotes.
This is probably obvious to people from the C/C++ world, but potentially confusing to Python and JavaScript programmers.
```kotlin
val a = 'a'
a::class.qualifiedName // => kotlin.Char
a.code // => 97
val jha = 'झ' // Devanagari alphabet
jha.code // => 2333
val heart = '❤' // heart emoji
heart.code // => 10084
Char.MAX_VALUE.code // => 65535 (64k, the largest code point allowed)
val not_char = 'abc' // => Too many characters in a character literal.
```
Converting between `Char` and `Int` is straightforward:
```kotlin
a.code // => 97
Char(97) // => 'a'
```
The compiler allows _some_ forms of integer arithmetic on `Char`s:
```kotlin
'a' + 5 // => 'f'
'c' - 'a' // => 2
'c' + 'a' // => error!
'f' + ('A' - 'a') // => 'F' (same as 'f'.uppercase()
'f'.dec() // => 'e' (decrement)
'f'.inc() // => 'g' (increment)
```
## Some functions for `Char`
As always, there are far too [many functions][ref-char-lib] to discuss here, so this is just a selection.
- For appropriate alphabets, change case with [`uppercase()`][ref-uppercase] and [`lowercase()`][ref-lowercase].
- Test case with [`isUpperCase()`][ref-isuppercase] and [`isLowerCase()`][ref-islowercase].
- Test character type with:
- [`isLetter()`][ref-isletter], covers many alphabets (the Lu, Ll, Lt, Lm, and Lo categories in unicode)
- [`isDigit()`][ref-isdigit], in range 0..9 (the Nd category in unicode)
- `isLetterOrDigit()`, combines the previous two
- [`isWhitespace()`][ref-iswhitespace], any whitespace character (the Cc, Zp, Zl, and Zs categories in unicode)
```kotlin
'झ'.isLetter() // => true
'A'.isLowerCase() // => false
'4'.isDigit() // => true
'\t'.isWhitespace() // => true (tab character)
```
Also, [regular expressions][ref-regex] (which will be the subject of a later Concept) allow powerful search and manipulation.
## Char List and String interconversions
To convert from a `String` to a `List` of `Char`s, we can use `toList()`.
To convert a `List` of `Char`s to a `String`, there is the [`joinToString()`][ref-jointostring] function, which takes a separator (often the empty string) as argument.
```kotlin
val kt = "kotlin".toList() // => [k, o, t, l, i, n]
kt.joinToString("") // => "kotlin"
kt.joinToString("_") // => "k_o_t_l_i_n"
```
Note that `joinToString()` operates on a List or Array.
To _cast_ a single `Char` to a 1-character string, use `toString()`.
```kotlin
'a'.toString() // => "a"
```
To check if a character is present in a `String`, or a `Char` list or array, we have `in`, which maps to the [`contains()`][ref-contains] function.
```kotlin
val clist = "kotlin".toList() // => [k, o, t, l, i, n]
't' in clist // => true
't' in "kotlin" // => true
```
[ref-char]: https://kotlinlang.org/docs/characters.html
[ref-char-lib]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-char/
[wiki-ascii]: https://en.wikipedia.org/wiki/ASCII
[web-unicode]: https://home.unicode.org/
[wiki-utf-8]: https://en.wikipedia.org/wiki/UTF-8
[ref-uppercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/uppercase.html
[ref-lowercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/lowercase.html
[ref-isuppercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-upper-case.html
[ref-islowercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-lower-case.html
[ref-isletter]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-letter.html
[ref-isdigit]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-digit.html
[ref-iswhitespace]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-whitespace.html
[ref-jointostring]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/join-to-string.html
[ref-contains]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/contains.html
[ref-regex]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-regex/
================================================
FILE: concepts/chars/introduction.md
================================================
# Introduction
This is potentially a _big_ subject!
It is possible to write a long book about it, and several people have done so (search Amazon for "unicode book" to see some examples).
## A very brief history
Handling characters in computers was much simpler in earlier decades, when programmers assumed that English was the only important language.
So: 26 letters, upper and lower case, 10 digits, several punctuation marks, plus a code (0x07) to ring a bell, and it all fitted into 7 bits: the [ASCII][wiki-ascii] character set.
Naturally, people started asking what about à, ä and Ł, then other people started asking about ऄ, ஹ and ญ, and young people wanted emojis 😱.
What to do?
To cut a long story short, many smart and patient people had to serve on committees for years, working out the details of the [Unicode][web-unicode] character set, and of encodings such as [UTF-8][wiki-utf-8], and lots of software needed a _very_ complicated rewrite.
Also, lots of new bugs were introduced.
To prevent _everything_ breaking, the Unicode/UTF-8 design ensures that the first 127 codes are identical to ASCII _(even the bell)_.
## Characters in Kotlin
Languages designed after about 2005 have the huge advantage that a reasonably stable Unicode standard already existed.
Kotlin (first released in 2011) was able to assume that users would use a variety of (human) languages, and would need Unicode to express them.
Character literals are written in single-quotes, and are distinct from strings written in double quotes.
This is probably obvious to people from the C/C++ world, but potentially confusing to Python and JavaScript programmers.
```kotlin
val a = 'a'
a::class.qualifiedName // => kotlin.Char
a.code // => 97
val jha = 'झ' // Devanagari alphabet
jha.code // => 2333
val heart = '❤' // heart emoji
heart.code // => 10084
Char.MAX_VALUE.code // => 65535 (64k, the largest code point allowed)
```
Converting between `Char` and `Int` is simple:
```kotlin
a.code // => 97 (a.toInt() is deprecated)
Char(97) // => 'a'
```
The compiler allows _some_ forms of integer arithmetic on `Char`s:
```kotlin
'a' + 5 // => 'f'
'c' - 'a' // => 2
'c' + 'a' // => error!
'f' + ('A' - 'a') // => 'F' (same as 'f'.uppercase()
'f'.dec() // => 'e' (decrement)
'f'.inc() // => 'g' (increment)
```
## Some functions for `Char`
As always, there are far too [many functions][ref-char-lib] to discuss here, so this is just a selection.
- For appropriate alphabets, change case with [`uppercase()`][ref-uppercase] and [`lowercase()`][ref-lowercase].
- Test case with [`isUpperCase()`][ref-isuppercase] and [`isLowerCase()`][ref-islowercase].
- Test character type with:
- [`isLetter()`][ref-isletter], covers many alphabets
- [`isDigit()`][ref-isdigit], in range 0..9
- `isLetterOrDigit()`, combines the previous two
- [`isWhitespace()`][ref-iswhitespace], any whitespace character
```kotlin
'झ'.isLetter() // => true
'A'.isLowerCase() // => false
'4'.isDigit() // => true
'\t'.isWhitespace() // => true (tab character)
```
## Char List and String interconversions
For String to Char List, we can use `toList()`.
For Char List to String, there is the [`joinToString()`][ref-jointostring] function, which takes a separator (often the empty string) as argument.
```kotlin
val kt = "kotlin".toList() // => [k, o, t, l, i, n]
kt.joinToString("") // => "kotlin"
kt.joinToString("_") // => "k_o_t_l_i_n"
```
Note that `joinToString()` operates on a List or Array.
To _cast_ a single `Char` to a 1-character string, use `toString()`.
```kotlin
'a'.toString() // => "a"
```
To check if a character is present in a `String`, or a `Char` list or array, we have `in`, which maps to the [`contains()`][ref-contains] function.
```kotlin
val clist = "kotlin".toList() // => [k, o, t, l, i, n]
't' in clist // => true
't' in "kotlin" // => true
```
[ref-char]: https://kotlinlang.org/docs/characters.html
[ref-char-lib]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-char/
[wiki-ascii]: https://en.wikipedia.org/wiki/ASCII
[web-unicode]: https://home.unicode.org/
[wiki-utf-8]: https://en.wikipedia.org/wiki/UTF-8
[ref-uppercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/uppercase.html
[ref-lowercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/lowercase.html
[ref-isuppercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-upper-case.html
[ref-islowercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-lower-case.html
[ref-isletter]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-letter.html
[ref-isdigit]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-digit.html
[ref-iswhitespace]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/is-whitespace.html
[ref-jointostring]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/join-to-string.html
[ref-contains]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/contains.html
[ref-regex]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-regex/
================================================
FILE: concepts/chars/links.json
================================================
[
{
"url": "https://kotlinlang.org/docs/characters.html",
"description": "Kotlin introduction to characters."
},
{
"url": "https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-char/",
"description": "Char type and functions"
}
]
================================================
FILE: concepts/conditionals/.meta/config.json
================================================
{
"authors": [
"colinleach"
],
"contributors": [],
"blurb": "The conditionals `if`, `else if` and `else` are used to control the flow of execution and make decisions in a program."
}
================================================
FILE: concepts/conditionals/about.md
================================================
# About conditionals
## Comparison operators
[Comparison operators][operators] are similar to many other languages, with a few extensions.
For equality, the operators are `==` (equal) and `!=` (not equal).
```Kotlin
val txt = "abc"
txt == "abc" // => true
txt != "abc" // => false
```
Additionally, the `===` and `!==` operators test for ["referential equality"][referential-equality]:
`a === b` if and only if `a` and `b` point to the same object.
This should make more sense later in the syllabus.
The greater/less than operators are also conventional.
```Kotlin
1 < 3 // => true
3 > 3 // => false
3 <= 3 // => true
4 >= 3 // => true
```
## Branching with `if`
This is the full form of an [`if` expression][if-else]:
```Kotlin
if (conditional1) {
// something...
} else if (conditional2) {
// something...
} else {
// something...
}
```
- Parentheses `()` around each conditional are required.
- A conditional must evaluate to a Boolean `true` or `false`.
Kotlin has no concept of "truthy" and "falsy" as found in some languages.
- Braces `{}` are optional, if there is only a single expression.
- Both `else if` and `else` are optional, and there can be multiple `else if` blocks.
## Alternatives?
By deliberate choice, Kotlin does _not_ have the ternary operator `? :` found in Java.
A concise form of `if ... else` is preferred:
```Kotlin
val result = if (isOk) goodValue else badValue
return if (isOK) goodValue else badValue
```
Unlike Ruby, the concise `if ... else` form *always* needs an `else` and thus cannot be used as a guard statement:
```kotlin
return 42 if (isOk)
// Syntax error: Unexpected tokens (use ';' to separate expressions on the same line).
// Syntax error: Expecting an expression.
return if (isOk) true
// 'if' must have both main and 'else' branches when used as an expression.
```
Note that in Kotlin, `if` is an [_expression_][expression] returning a value.
It is not a [_statement_][statement] as in Java.
We will see in a later Concept that Kotlin has a powerful [`when`][when] construct, intended to replace long chains of `else if` clauses with pattern matching.
[operators]: https://kotlinlang.org/docs/keyword-reference.html#operators-and-special-symbols
[referential-equality]: https://kotlinlang.org/docs/equality.html#floating-point-numbers-equality
[if-else]: https://kotlinlang.org/docs/control-flow.html#if-expression
[when]: https://kotlinlang.org/docs/control-flow.html#when-expressions-and-statements
[expression]: https://en.wikipedia.org/wiki/Expression_(computer_science)
[statement]: https://en.wikipedia.org/wiki/Statement_(computer_science)
================================================
FILE: concepts/conditionals/introduction.md
================================================
# Introduction
## Comparison operators
Comparison operators are similar to many other languages.
For equality, the operators are `==` (equal) and `!=` (not equal).
```Kotlin
val txt = "abc"
txt == "abc" // => true
txt != "abc" // => false
```
The greater/less than operators are also conventional.
```Kotlin
1 < 3 // => true
3 > 3 // => false
3 <= 3 // => true
4 >= 3 // => true
```
## Branching with `if`
This is the full form of an `if` expression:
```Kotlin
if (conditional1) {
// something...
} else if (conditional2) {
// something...
} else {
// something...
}
```
- Parentheses `()` around each conditional are required.
- A conditional must evaluate to a Boolean `true` or `false`.
Kotlin has no concept of "truthy" and "falsy" as found in some languages.
- Braces `{}` are optional, if there is only a single expression.
- Both `else if` and `else` are optional, and there can be multiple `else if` blocks.
## Alternatives?
By deliberate choice, Kotlin does _not_ have the ternary operator `? :` found in Java.
A concise form of `if ... else` is preferred:
```Kotlin
return if (isOK) goodValue else badValue
```
================================================
FILE: concepts/conditionals/links.json
================================================
[
{
"url": "https://kotlinlang.org/docs/keyword-reference.html#operators-and-special-symbols",
"description": "Operators reference."
},
{
"url": "https://kotlinlang.org/docs/control-flow.html#if-expression",
"description": "Control flow introduction."
},
{
"url": "https://kotlinlang.org/docs/coding-conventions.html#control-flow-statements",
"description": "Coding conventions."
}
]
================================================
FILE: concepts/nullability/.meta/config.json
================================================
{
"authors": [
"colinleach"
],
"contributors": [],
"blurb": "Kotlin provides optional nullable types, plus functionality to make nullability safe and convenient to use."
}
================================================
FILE: concepts/nullability/about.md
================================================
# About Nullability
In an ideal world, we could rely on everything being nicely defined, with concrete values and no gaps.
This conflicts with our everyday experience, and thus many programming languages have a way to represent the absence of a value: null or NULL, nil, None, nothing...
This was easy to introduce (back in 1965), but soon led to regrets.
The inventor later called it his ["Billion Dollar Mistake"][web-mistake].
In recent decades, language designers have explored many ways to make nulls available but (mostly) safe.
Kotlin has a few [general principles][ref-null-safety], which [differ significantly from Java][ref-java2kotlin].
_The differences mean that Kotlin has special functionality to deal with Java interop, though details are beyond the scope of this Concept._
- Kotlin has a special `null` value.
- All types _default_ to being non-nullable (i.e. can not be `null`) .
- All types can be _nullable_, but this must be explicitly done.
- Functions which might fail with an exception are likely to have a variant with a nullable return value.
- Special, highly terse syntax tries to make testing for and responding to nulls as easy as possible.
## Creating nullable variables
A type can be made [nullable][ref-nullable-type] by adding the `?` suffix (e.g. `String?` instead of `String`).
```kotlin
var a = "Kotlin" // inferred type is String
a = null // => Error: Null can not be a value of a non-null type String
var b: String? = "Kotlin" // nullable type
b = null // => b is now null
b == null // => true
```
## Useful operators and functions
### The [safe call operator][ref-safe-call] `?.`
For a non-nullable `String`, we can get the `.length` property.
A nullable `String?` fails with the same syntax, but using `?.length` allows for the possibility of a `null`.
The return type is `Int?`.
```kotlin
var a = "Kotlin"
a.length // => 6
// b is still null
b.length // => Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
b?.length // => null
a?.length // => 6
```
As we saw in the last line above, `?.` also works with non-nullable types.
### The [Elvis operator][ref-elvis] `?:`
Extending the idea of the safe-call operator, the [Elvis operator][wiki-elvis] lets us supply a default value to replace `null`.
```kotlin
// b is still null
b?.length ?: -1 // => -1, in place of null
a?.length ?: -1 // => 6, as before
```
### [Not-null assertion operator][ref-not-null] `!!`
With this operator, a nullable type is forced to be treated as non-null, when the programmer is confident about this.
Perhaps we sometimes understand the program logic better than an over-cautious compiler?
```kotlin
// b is still a String?
b = "Kotlin?"
b!!.length // => 7
```
The responsibility is now on us: if `b` is still `null` we get a `NullPointerException`.
### [Let function][ref-let] `?.let`
If passing a nullable item to a block of code, we could do specific null checks `if (item != null) { do something }`.
It is simpler and more idiomatic to use `item?.let { do something }`,
The `do something` will only execute when `item` is not null.
### Functions of type `somethingOrNone()`
Some functions may fail, for example when asking for an invalid index in a string or list.
Rather than throwing an exception, we could use the [`...OrNull` variant][ref-elem-at-or-null] of the function, to get (in this case) an `Int?` return value.
```kotlin
val str = "Kotlin"
str.elementAtOrNull(10) // => null
str.elementAt(10) // => StringIndexOutOfBoundsException: String index out of range: 10
```
[ref-java2kotlin]: https://kotlinlang.org/docs/java-to-kotlin-nullability-guide.html
[web-mistake]: https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/
[ref-null-safety]: https://kotlinlang.org/docs/null-safety.html
[ref-elvis]: https://kotlinlang.org/docs/null-safety.html#elvis-operator
[wiki-elvis]: https://en.wikipedia.org/wiki/Elvis_operator
[ref-nullable-type]: https://kotlinlang.org/docs/null-safety.html#nullable-types-and-non-nullable-types
[ref-safe-call]: https://kotlinlang.org/docs/null-safety.html#safe-call-operator
[ref-not-null]: https://kotlinlang.org/docs/null-safety.html#not-null-assertion-operator
[ref-let]: https://kotlinlang.org/docs/null-safety.html#let-function
[ref-elem-at-or-null]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/element-at-or-null.html
================================================
FILE: concepts/nullability/introduction.md
================================================
# Introduction
In an ideal world, we could rely on everything being nicely defined, with concrete values and no gaps.
This conflicts with our everyday experience, and thus many programming languages have a way to represent the absence of a value: null or NULL, nil, None, nothing...
This was easy to introduce (back in 1965), but soon led to regrets.
The inventor later called it his "Billion Dollar Mistake".
In recent decades, language designers have explored many ways to make nulls available but (mostly) safe.
Kotlin has a few [general principles][ref-null-safety], which differ significantly from Java.
- Kotlin has a special `null` value.
- All types _default_ to being non-nullable.
- Most types can be _made_ nullable, but the programmer must explicitly order this.
- Functions which might fail with an exception are likely to have a variant with a nullable return value.
- Special, highly terse syntax tries to make testing for and responding to nulls as easy as possible.
## Creating nullable variables
Standard types generally have a nullable equivalent, with a `?` suffix: for example `String?` instead of `String`.
```kotlin
var a = "Kotlin" // inferred type is String
a = null // => Error: Null can not be a value of a non-null type String
var b: String? = "Kotlin" // nullable type
b = null // => b is now null
b == null // => true
```
## Useful operators and functions
### The safe call operator `?.`
For a non-nullable `String`, we can get the `.length` property.
A nullable `String?` fails with the same syntax, but using `?.length` allows for the possibility of a `null`.
The return type is `Int?`.
```kotlin
var a = "Kotlin"
a.length // => 6
// b is still null
b.length // => Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
b?.length // => null
a?.length // => 6
```
As we saw in the last line above, `?.` also works with non-nullable types.
### The Elvis operator `?:`
Extending the idea of the safe-call operator, the [Elvis operator][wiki-elvis] lets us supply a default value to replace `null`.
```kotlin
// b is still null
b?.length ?: -1 // => -1, in place of null
a?.length ?: -1 // => 6, as before
```
### Not-null assertion operator `!!`
With this operator, a nullable type is forced to be treated as non-null, when the programmer is confident about this.
Perhaps we sometimes understand the program logic better than an over-cautious compiler?
```kotlin
// b is still a String?
b = "Kotlin?"
b!!.length // => 7
```
The responsibility is now on us: if `b` is still `null` we get a `NullPointerException`.
### Let function `?.let`
If passing a nullable item to a block of code, we could do specific null checks `if (item != null) { do something }`.
It is simpler and more idiomatic to use `item?.let { do something }`,
The `do something` will only execute when `item` is not null.
### Functions of type `somethingOrNone()`
Some functions may fail, for example when asking for an invalid index in a string or list.
Rather than throwing an exception, we could use the `...OrNull` variant of the function, to get (in this case) an `Int?` return value.
```kotlin
val str = "Kotlin"
str.elementAtOrNull(10) // => null
str.elementAt(10) // => StringIndexOutOfBoundsException: String index out of range: 10
```
[web-mistake]: https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/
[ref-null-safety]: https://kotlinlang.org/docs/null-safety.html
[wiki-elvis]: https://en.wikipedia.org/wiki/Elvis_operator
================================================
FILE: concepts/nullability/links.json
================================================
[
{
"url": "https://kotlinlang.org/docs/null-safety.html",
"description": "Kotlin introduction to null safety."
},
{
"url": "https://kotlinlang.org/docs/java-to-kotlin-nullability-guide.html",
"description": "Nullability guide for Java to Kotlin migration."
}
]
================================================
FILE: concepts/strings/.meta/config.json
================================================
{
"authors": [
"colinleach"
],
"contributors": [],
"blurb": "Strings are an immutable sequence of Unicode characters."
}
================================================
FILE: concepts/strings/about.md
================================================
# About Strings
A [`string`][ref-string] in Kotlin is an immutable sequence of Unicode characters.
[`Immutable`][wiki-immutable] means that any operation on a string must return a new string: the original string can never change.
[`Unicode`][wiki-unicode] means that most of the world's writing systems can be represented, but (in contrast to older languages such as C) there is no 1:1 mapping between characters and bytes.
This will be discussed further in the [`Chars`][concept-chars] Concept.
A string is surrounded by double-quotes `" "`.
Some characters need escaping: `\\`, plus the usual non-printing characters such as `\t` (tab) and `\n` (newline).
```kotlin
val s = "Escape backslash \\."
// Escape backslash \.
```
Multi-line strings are surrounded by 3 double-quotes, and can contain arbitrary text (no need for escaping).
```kotlin
val multi = """I'm a
multi-line
string with special characters \ \t """
//I'm a
// multi-line
// string with special characters \ \t
```
Use [trimIndent][trimIndent-doc] to remove the common indenting from the lines.
This is useful for formatting the string:
```kotlin
val multi = """
I'm a
multi-line
string""".trimIndent()
//I'm a
// multi-line
//string
```
Alternatively, [trimMargin][trimMargin-doc] lets you specify a delimiter.
Each line in the `String` then begins after the delimiter.
The delimiter defaults to `|`, but you can specify a different delimiter as a parameter.
For example:
```kotlin
val multi = """
|I'm a
| multi-line
|string""".trimMargin()
//I'm a
// multi-line
//string
val multi2 = """
start>I'm a
start> multi-line
start>string""".trimMargin("start>")
//I'm a
// multi-line
//string
```
Strings can be concatenated with `+`, but this is best limited to short and simple cases.
There are other and often better options.
## String templates
[`Templates`][ref-templates] refers to what some other languages call "interpolation".
If a string contains a dollar sign `$`, followed by an identifier, or contains braces (`{expression}`) surrounding an expression, those are substituted by respectively the value or the result of the expression.
```kotlin
val x = 42
val st = "x is $x, x squared is {x * x}"
// x is 42, x squared is 1764
```
## String formatting
On the JVM platform (only), `String.format()` allows more precise formatting than string templates, with [syntax][web-formats] similar to the (_very old!_) [`printf`][wiki-printf] functions.
```kotlin
String.format("%s %.3f", "π ≈", 3.14159)
//π ≈ 3.142
```
~~~~exercism/advanced
Kotlin can be compiled to several different targets: the Java Virtual Machine, JavaScript, native binaries for Linux, Windows, Android and Apple, plus two variants of WebAssembly.
Essentially the same code can be used for each, but different capabilities in the target platforms mean some differences in which standard library functions are supported.
Exercism currently uses the JVM for testing.
~~~~
## String functions
Kotlin provides _many_ [`functions`][ref-string-functions] to manipulate strings.
Mostly, these are [`extensions functions`][ref-extensions] rather than members of the `String` class, though this has little effect on how we use them.
~~~~exercism/note
Kotlin's rather complex [documentation][ref-string-functions] pages hide extension functions in the default view.
At moment of writing this, the most valuable content is hidden in a tab named `Members & Extensions`.
Click it to expand this section and see all the members and extensions available on the `String` class.
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/
~~~~
The following example shows just a small selection of what is available:
```kotlin
val str = "Hello World!"
str.length // => 12 (a property, not a function)
str.elementAt(6) // => W
str.elementAtOrNull(20) // => null (index out of range)
str.substring(6, 11) // => "World"
str.substringAfter(" ") // => "World!"
str.lowercase() // => "hello world!"
str.uppercase() // => "HELLO WORLD!"
str.startsWith("Hel") // => true
str.endsWith("xyz") // => false
str.indexOf("0") // => 4
str.toCharArray() // => [H, e, l, l, o, , W, o, r, l, d, !]
"42".toInt() + 1 // => 43 (parsing; see also toFloat)
"Howdy! ".trim() // => "Howdy"
```
## Building a string
Sometimes a long string needs to be built up in stages, for example within a loop.
Concatenating strings with `+` soon becomes neither elegant nor performant: immutability means that there is a _lot_ of copying required.
Kotlin has various more efficient ways to combine multiple string:
- String templates, described above.
- [`joinToString()][ref-jointostring], which will be covered in the [Lists][concept-lists] Concept.
- Java's [`StringBuilder`][ref-stringbuilder], which is not regarded as particularly idiomatic Kotlin.
- Kotlin's [`buildString()`][ref-buildstring], which wraps `StringBuilder` in a more concise and idiomatic syntax.
This takes string-building logic as a lambda argument, which will be discussed in a later Concept.
In essence, a `StringBuilder` is a list-like structure, with many convenient methods.
This is a small selection:
- [`append()`][ref-sb-append] to add to the end.
- [`insert()`][ref-sb-insert] to add at a specified position.
- [`deleteAt()`][ref-sb-deleteat] and [`deleteRange()`][ref-sb-deleterange] to remove from specified position(s).
- `toString()` to convert to a normal string at the end: concatenating everything in a single, performant operation.
```kotlin
// Available, not recommended
val sb = StringBuilder()
sb.append("Hello ")
sb.append("World!")
sb.toString()
//Hello World!
```
A `buildString()` example, using syntax from later Concepts:
```kotlin
val countDown = buildString {
for (i in 5 downTo 1) {
append(i)
append("_")
}
}
// countDown is "5_4_3_2_1_"
```
[ref-string]: https://kotlinlang.org/docs/strings.html
[wiki-immutable]: https://en.wikipedia.org/wiki/Immutable_object
[wiki-unicode]: https://en.wikipedia.org/wiki/Unicode
[web-formats]: https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html#summary
[wiki-printf]: https://en.wikipedia.org/wiki/Printf
[ref-stringbuilder]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/
[ref-extensions]: https://kotlinlang.org/docs/extensions.html#extensions.md
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/
[concept-chars]: https://exercism.org/tracks/kotlin/concepts/chars
[concept-lists]: https://exercism.org/tracks/kotlin/concepts/lists
[ref-templates]: https://kotlinlang.org/docs/strings.html#string-templates
[ref-sb-append]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/#9100522%2FFunctions%2F-705004581
[ref-sb-insert]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/#-132863384%2FFunctions%2F-705004581
[ref-sb-deleteat]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/#-386007892%2FFunctions%2F-956074838
[ref-sb-deleterange]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/#-1622040372%2FFunctions%2F-956074838
[ref-buildstring]: https://kotlinlang.org/docs/java-to-kotlin-idioms-strings.html#build-a-string
[ref-jointostring]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/join-to-string.html
[trimIndent-doc]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/trim-indent.html
[trimMargin-doc]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/trim-margin.html
================================================
FILE: concepts/strings/introduction.md
================================================
# Introduction
A [`string`][ref-string] in Kotlin is an immutable sequence of Unicode characters.
[`Immutable`][wiki-immutable] means that any operation on a string must return a new string: the original string can never change.
[`Unicode`][wiki-unicode] means that most of the world's writing systems can be represented, but (in contrast to older languages such as C) there is no 1:1 mapping between characters and bytes.
A string is surrounded by double-quotes `" "`.
Some characters need escaping: `\\`, plus the usual non-printing characters such as `\t` (tab) and `\n` (newline).
```kotlin
val s = "Escape backslash \\."
// Escape backslash \.
```
Multi-line strings are surrounded by 3 double-quotes, and can contain arbitrary text (no need for escaping).
```kotlin
val multi = """I'm a
multi-line
string with special characters \ \t """
//I'm a
// multi-line
// string with special characters \ \t
```
Use [trimIndent][trimIndent-doc] to remove the common indenting from the lines.
This is useful for formatting the string:
```kotlin
val multi = """
I'm a
multi-line
string""".trimIndent()
//I'm a
// multi-line
//string
```
Alternatively, [trimMargin][trimMargin-doc] lets you specify a delimiter.
Each line in the `String` then begins after the delimiter.
The delimiter defaults to `|`, but you can specify a different delimiter as a parameter.
For example:
```kotlin
val multi = """
|I'm a
| multi-line
|string""".trimMargin()
//I'm a
// multi-line
//string
val multi2 = """
start>I'm a
start> multi-line
start>string""".trimMargin("start>")
//I'm a
// multi-line
//string
```
Strings can be concatenated with `+`, but this is best limited to short and simple cases.
There are other and often better options.
## String templates
This refers to what some other languages call "interpolation".
If a string contains a dollar sign `$`, followed by an identifier, or contains braces (`{expression}`) surrounding an expression, those are substituted by respectively the value or the result of the expression.
```kotlin
val x = 42
val st = "x is $x, x squared is {x * x}"
// x is 42, x squared is 1764
```
The braces `{ }` are needed around expressions when parsing would otherwise be ambiguous.
In general, use of string templates is a more efficient and idiomatic way to combine strings than using `+`.
## String functions
Kotlin provides _many_ [`functions`][ref-string-functions] to manipulate strings.
Mostly, these are [`extensions functions`][ref-extensions] rather than members of the `String` class, though this has little effect on how we use them.
~~~~exercism/note
Kotlin's rather complex [documentation][ref-string-functions] pages hide extension functions in the default view.
Be sure to click `Members & Extensions` to expand this section.
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/
~~~~
The following examples show just a small selection of what is available:
```kotlin
val str = "Hello World!"
str.length // => 12 (a property, not a function)
str.elementAt(6) // => W
str.elementAtOrNull(20) // => null (index out of range)
str.substring(6, 11) // => "World"
str.substringAfter(" ") // => "World!"
str.lowercase() // => "hello world!"
str.uppercase() // => "HELLO WORLD!"
str.startsWith("Hel") // => true
str.endsWith("xyz") // => false
str.indexOf("0") // => 4
str.toCharArray() // => [H, e, l, l, o, , W, o, r, l, d, !]
"42".toInt() + 1 // => 43 (parsing; see also toFloat)
"Howdy! ".trim() // => "Howdy"
```
[ref-string]: https://kotlinlang.org/docs/strings.html
[wiki-immutable]: https://en.wikipedia.org/wiki/Immutable_object
[wiki-unicode]: https://en.wikipedia.org/wiki/Unicode
[ref-stringbuilder]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/
[ref-extensions]: https://kotlinlang.org/docs/extensions.html#extensions.md
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/
[trimIndent-doc]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/trim-indent.html
[trimMargin-doc]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/trim-margin.html
================================================
FILE: concepts/strings/links.json
================================================
[
{
"url": "https://kotlinlang.org/docs/strings.html",
"description": "Kotlin string introduction"
},
{
"url": "https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/",
"description": "String functions"
},
{
"url": "https://kotlinlang.org/docs/strings.html#string-templates",
"description": "String Templates"
}
]
================================================
FILE: config.json
================================================
{
"language": "Kotlin",
"slug": "kotlin",
"active": true,
"status": {
"concept_exercises": false,
"test_runner": true,
"representer": false,
"analyzer": false
},
"blurb": "Kotlin is a pragmatic programming language for JVM and Android that combines OO and functional features and is focused on interoperability, safety, clarity and tooling support.",
"version": 3,
"online_editor": {
"indent_style": "space",
"indent_size": 4,
"highlightjs_language": "kotlin"
},
"test_runner": {
"average_run_time": 4
},
"files": {
"solution": [
"src/main/kotlin/%{pascal_slug}.kt"
],
"test": [
"src/test/kotlin/%{pascal_slug}Test.kt"
],
"example": [
".meta/src/reference/kotlin/%{pascal_slug}.kt"
],
"exemplar": [
".meta/src/reference/kotlin/%{pascal_slug}.kt"
]
},
"exercises": {
"concept": [
{
"slug": "lucians-luscious-lasagna",
"name": "Lucian's Luscious Lasagna",
"uuid": "de14936d-28d7-4531-9761-69deba31a7ca",
"concepts": [
"basics"
],
"prerequisites": [],
"status": "wip"
},
{
"slug": "annalyns-infiltration",
"name": "Annalyn's Infiltration",
"uuid": "5a0af671-2549-411c-860a-f36859b429e5",
"concepts": [
"booleans"
],
"prerequisites": [
"basics"
],
"status": "wip"
},
{
"slug": "log-levels",
"name": "log-levels",
"uuid": "ef54c5e6-7d31-42d1-a300-e405169dbd7f",
"concepts": [
"strings"
],
"prerequisites": [
"basics"
],
"status": "wip"
}
],
"practice": [
{
"slug": "accumulate",
"name": "Accumulate",
"uuid": "86015770-603b-44cf-aedf-f2a7cf79c841",
"practices": [],
"prerequisites": [],
"difficulty": 1,
"status": "deprecated",
"topics": [
"lists"
]
},
{
"slug": "binary",
"name": "Binary",
"uuid": "def44955-c048-4b74-8777-2fb7d779b09e",
"practices": [],
"prerequisites": [],
"difficulty": 1,
"status": "deprecated",
"topics": [
"strings"
]
},
{
"slug": "hello-world",
"name": "Hello World",
"uuid": "58c16459-348a-4536-8228-43379174735e",
"practices": [],
"prerequisites": [],
"difficulty": 1,
"topics": [
"strings"
]
},
{
"slug": "hexadecimal",
"name": "Hexadecimal",
"uuid": "13b1a62e-8e0e-4d57-b8c9-341b41f25cf5",
"practices": [],
"prerequisites": [],
"difficulty": 1,
"status": "deprecated",
"topics": [
"string",
"integers"
]
},
{
"slug": "reverse-string",
"name": "Reverse String",
"uuid": "95d495a6-b1a2-42d5-8190-443d6f94e80b",
"practices": [],
"prerequisites": [],
"difficulty": 1,
"topics": [
"strings"
]
},
{
"slug": "strain",
"name": "Strain",
"uuid": "8ae8492d-620c-4446-9928-5b4d78d496d9",
"practices": [],
"prerequisites": [],
"difficulty": 1,
"status": "deprecated",
"topics": [
"arrays",
"filtering"
]
},
{
"slug": "bob",
"name": "Bob",
"uuid": "f3713067-7f37-4dd6-a189-c80f46dab8ec",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"booleans",
"conditionals",
"strings"
]
},
{
"slug": "collatz-conjecture",
"name": "Collatz Conjecture",
"uuid": "ab52d0f4-a001-4d44-951e-0cfc396374f3",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"conditionals",
"exception_handling",
"integers",
"math",
"recursion"
]
},
{
"slug": "darts",
"name": "Darts",
"uuid": "c2b49ff6-e7bf-40bb-b619-9cdfaa43c065",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"pattern_matching",
"conditionals",
"math"
]
},
{
"slug": "eliuds-eggs",
"name": "Eliud's Eggs",
"uuid": "88e7d43f-87f8-4c00-a463-f1593d725e18",
"practices": [],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "etl",
"name": "ETL",
"uuid": "f0f297f2-429f-4626-8b7f-0706a1e8f255",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"lists",
"maps",
"transforming"
]
},
{
"slug": "grains",
"name": "Grains",
"uuid": "1fa1e0f9-6410-4197-8778-debeb274e6d4",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"integers"
]
},
{
"slug": "isogram",
"name": "Isogram",
"uuid": "e5338be9-6f51-4448-9b10-20de7b1338b9",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"conditionals",
"loops",
"parsing",
"strings"
]
},
{
"slug": "leap",
"name": "Leap",
"uuid": "639e59b6-84aa-4f13-9718-537606703c43",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"conditionals",
"integers"
]
},
{
"slug": "nucleotide-count",
"name": "Nucleotide Count",
"uuid": "62bd648a-e959-4ec4-8a5f-09e08fa0b2c8",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"conditionals",
"exception_handling",
"integers",
"maps",
"parsing",
"searching",
"strings"
]
},
{
"slug": "protein-translation",
"name": "Protein Translation",
"uuid": "368ba5ef-8c54-4016-93df-3a7d3b136243",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"algorithms",
"lists",
"conditionals",
"loops",
"strings"
]
},
{
"slug": "rna-transcription",
"name": "RNA Transcription",
"uuid": "9772c916-c619-445c-834d-af7dbf1ad2d9",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"loops",
"maps",
"strings"
]
},
{
"slug": "sum-of-multiples",
"name": "Sum of Multiples",
"uuid": "d3f960e5-cf19-4308-a1bc-897777f62689",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"arrays",
"conditionals",
"integers",
"loops",
"math"
]
},
{
"slug": "triangle",
"name": "Triangle",
"uuid": "e282536b-267f-490c-a453-758135051a54",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"conditionals",
"exception_handling",
"integers",
"recursion"
]
},
{
"slug": "two-fer",
"name": "Two Fer",
"uuid": "40f85461-c256-4b96-8d5b-0509f42fab17",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"conditionals",
"strings"
]
},
{
"slug": "acronym",
"name": "Acronym",
"uuid": "d8288e46-2e8c-42e4-8e14-20b1efd0f574",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"loops",
"parsing",
"searching",
"strings"
]
},
{
"slug": "allergies",
"name": "Allergies",
"uuid": "a826af04-b7f3-426e-9bce-42375d0d928b",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"booleans",
"conditionals",
"enumerations",
"integers",
"lists",
"loops"
]
},
{
"slug": "anagram",
"name": "Anagram",
"uuid": "f754e1cc-cb88-4776-ab11-3e6ae8362d5a",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"arrays",
"conditionals",
"equality",
"lists",
"loops",
"strings"
]
},
{
"slug": "armstrong-numbers",
"name": "Armstrong Numbers",
"uuid": "3905dff6-7835-44ff-a8c9-7f4d184ab714",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"algorithms",
"loops",
"math"
]
},
{
"slug": "binary-search",
"name": "Binary Search",
"uuid": "c8815b6c-19b8-4f4d-9be4-6717e933591a",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"arrays",
"generics",
"recursion",
"searching"
]
},
{
"slug": "clock",
"name": "Clock",
"uuid": "1dcefdea-5447-4622-a064-079aad781398",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"equality",
"integers",
"logic",
"object_oriented_programming",
"strings",
"time"
]
},
{
"slug": "crypto-square",
"name": "Crypto Square",
"uuid": "2928cf06-dab8-4522-a6d8-b2a15d7d356b",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"strings",
"text_formatting",
"transforming"
]
},
{
"slug": "difference-of-squares",
"name": "Difference of Squares",
"uuid": "d54a68fc-02dd-45ee-8c6f-3efb781ed0d2",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"integers",
"loops",
"math"
]
},
{
"slug": "dnd-character",
"name": "D&D Character",
"uuid": "a550dafa-bcec-448c-a7dd-af0ebd4e1070",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"integers",
"randomness"
]
},
{
"slug": "flatten-array",
"name": "Flatten Array",
"uuid": "c67907b6-0d8b-4b12-9c41-6069845952a3",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"stacks",
"strings"
]
},
{
"slug": "gigasecond",
"name": "Gigasecond",
"uuid": "1eb4c9d3-0085-4ca3-b1bb-9a20b88a1e7f",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"dates",
"integers",
"time"
]
},
{
"slug": "hamming",
"name": "Hamming",
"uuid": "7151ff23-ebc6-43d7-86b6-81cf0dd45309",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"integers",
"loops",
"strings"
]
},
{
"slug": "pangram",
"name": "Pangram",
"uuid": "0e9ca09d-c32e-4fed-930f-1b7c10b67dc2",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"pattern_matching",
"regular_expressions",
"strings"
]
},
{
"slug": "perfect-numbers",
"name": "Perfect Numbers",
"uuid": "ad7c8fd8-acf0-40d0-8a30-d959c4b0252a",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"enumerations",
"exception_handling",
"filtering",
"integers",
"math"
]
},
{
"slug": "phone-number",
"name": "Phone Number",
"uuid": "2c8c1c16-bbb8-49e5-a248-f7a473c2bc86",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"conditionals",
"pattern_matching",
"regular_expressions",
"strings"
]
},
{
"slug": "prime-factors",
"name": "Prime Factors",
"uuid": "0e92ba19-2727-4a5e-be38-e88878322c53",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"arrays",
"conditionals",
"integers",
"lists",
"loops",
"math"
]
},
{
"slug": "raindrops",
"name": "Raindrops",
"uuid": "93ee76ba-d19f-4c72-b011-676f40dcda5e",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"conditionals",
"integers",
"strings"
]
},
{
"slug": "resistor-color",
"name": "Resistor Color",
"uuid": "9d62b45c-1acf-4ae6-b990-73e5bc2b5893",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"lists"
]
},
{
"slug": "resistor-color-duo",
"name": "Resistor Color Duo",
"uuid": "84bdc53f-aa1f-4ddf-9c5d-95b03cfff72d",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"lists"
]
},
{
"slug": "resistor-color-trio",
"name": "Resistor Color Trio",
"uuid": "ae4df67d-c848-42e6-9fd7-d3cec83c1691",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"math",
"type_conversion",
"lists"
]
},
{
"slug": "rotational-cipher",
"name": "Rotational Cipher",
"uuid": "7c24087a-ca61-48d3-9cb9-c3fde2edba86",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"cryptography",
"integers",
"strings"
]
},
{
"slug": "run-length-encoding",
"name": "Run-Length Encoding",
"uuid": "483b5124-b5b2-4bb0-aa69-b04e3ea6aeb6",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"loops",
"regular_expressions",
"strings",
"transforming",
"type_conversion"
]
},
{
"slug": "scale-generator",
"name": "Scale Generator",
"uuid": "dfa35a61-07da-4317-8c25-0c630e551d8c",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"status": "deprecated",
"topics": [
"lists",
"strings"
]
},
{
"slug": "scrabble-score",
"name": "Scrabble Score",
"uuid": "4d8a68eb-eee9-4c51-97b8-57f3b69f5970",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"games",
"loops",
"pattern_matching",
"strings",
"transforming"
]
},
{
"slug": "secret-handshake",
"name": "Secret Handshake",
"uuid": "feee3ee9-81d5-4a4f-ad98-e1ecf21757ed",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"bitwise_operations",
"conditionals",
"cryptography",
"enumerations",
"integers",
"loops",
"transforming"
]
},
{
"slug": "series",
"name": "Series",
"uuid": "9caa5fd9-a774-4d4c-951d-053a4f3f2726",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"conditionals",
"lists",
"loops",
"strings",
"type_conversion"
]
},
{
"slug": "space-age",
"name": "Space Age",
"uuid": "a91ce7e9-9a2a-44de-b10c-cc1be63df2a1",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"conditionals",
"floating_point_numbers"
]
},
{
"slug": "sublist",
"name": "Sublist",
"uuid": "ebfdf40a-1fde-4c88-aa93-95e3190f5261",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"enumerations",
"generics",
"lists",
"loops",
"searching"
]
},
{
"slug": "word-count",
"name": "Word Count",
"uuid": "3b8b77ef-da2d-499d-9513-8fe771e86b3e",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"conditionals",
"integers",
"loops",
"maps",
"strings"
]
},
{
"slug": "yacht",
"name": "Yacht",
"uuid": "2702ffe9-26c3-4f68-86dc-2993dfa2de91",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"enums",
"functional_programming",
"lists",
"pattern_matching"
]
},
{
"slug": "affine-cipher",
"name": "Affine Cipher",
"uuid": "94fdd990-101b-4daf-8692-75085e6563f2",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"cryptography",
"security",
"strings"
]
},
{
"slug": "all-your-base",
"name": "All Your Base",
"uuid": "19d00436-f26a-47ad-b13e-128181dc09f3",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"arrays",
"conditionals",
"exception_handling",
"integers",
"loops",
"math"
]
},
{
"slug": "atbash-cipher",
"name": "Atbash Cipher",
"uuid": "b325401a-c8f0-49da-9f1a-a83318e780c9",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"cryptography",
"security",
"strings"
]
},
{
"slug": "diamond",
"name": "Diamond",
"uuid": "03c71e34-ecaf-47a4-9854-48600e1bf0d4",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"arrays",
"lists",
"loops",
"strings",
"text_formatting"
]
},
{
"slug": "grade-school",
"name": "Grade School",
"uuid": "62eb71dd-18ba-427f-a27a-86e993b4055a",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"conditionals",
"lists",
"maps",
"sorting",
"strings"
]
},
{
"slug": "isbn-verifier",
"name": "ISBN Verifier",
"uuid": "400d8014-9f75-43da-8a1c-93d95d91f4d2",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"integers",
"loops",
"strings"
]
},
{
"slug": "kindergarten-garden",
"name": "Kindergarten Garden",
"uuid": "1603e77a-0fbc-43ed-8200-b86a4219af8d",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"arrays",
"enumerations",
"lists",
"logic",
"loops",
"pattern_recognition",
"strings"
]
},
{
"slug": "largest-series-product",
"name": "Largest Series Product",
"uuid": "aa11e242-77b9-4ba7-97a2-d9b36e454a9d",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"integers",
"loops",
"math",
"strings",
"type_conversion"
]
},
{
"slug": "luhn",
"name": "Luhn",
"uuid": "3cf8a650-6a25-416e-a0af-036f41c11cca",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"algorithms",
"booleans",
"loops",
"strings",
"type_conversion"
]
},
{
"slug": "matrix",
"name": "Matrix",
"uuid": "46ab876c-cde2-4fa7-8970-b250ad8ccf74",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"loops",
"strings",
"pattern_matching",
"type_conversion",
"transforming"
]
},
{
"slug": "nth-prime",
"name": "Nth Prime",
"uuid": "6e2bbe8d-b6ab-4675-9c31-5b437cefd0c4",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"arrays",
"exception_handling",
"integers",
"lists",
"loops",
"math"
]
},
{
"slug": "robot-simulator",
"name": "Robot Simulator",
"uuid": "6e3b294b-16a3-4ebb-a78b-4bf7f6b96736",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"classes",
"enumerations",
"logic",
"loops"
]
},
{
"slug": "roman-numerals",
"name": "Roman Numerals",
"uuid": "da466ad5-6837-47d8-af39-2c0563d35a3c",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"integers",
"logic",
"loops",
"maps",
"strings"
]
},
{
"slug": "saddle-points",
"name": "Saddle Points",
"uuid": "371901d4-0728-4abd-8374-1905d7d70329",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"arrays",
"conditionals",
"exception_handling",
"integers",
"loops"
]
},
{
"slug": "sieve",
"name": "Sieve",
"uuid": "87ca4323-8a19-4529-962d-0f2ee63ebb2f",
"practices": [],
"prerequisites": [],
"difficulty": 4,
"topics": [
"algorithms",
"integers",
"lists",
"loops",
"math"
]
},
{
"slug": "binary-search-tree",
"name": "Binary Search Tree",
"uuid": "12a9dd9f-28ed-4159-baf3-d28654cb8fa7",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"arrays",
"generics",
"recursion",
"searching"
]
},
{
"slug": "circular-buffer",
"name": "Circular Buffer",
"uuid": "e32c0edd-367c-4b66-b677-35e518d6831f",
"practices": [],
"prerequisites": [
"generics"
],
"difficulty": 5
},
{
"slug": "custom-set",
"name": "Custom Set",
"uuid": "10b6cca2-6c36-4017-9464-32aa11c59f85",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"object_oriented_programming",
"sets",
"varargs"
]
},
{
"slug": "knapsack",
"name": "Knapsack",
"uuid": "1c2e8e65-1d1f-43ce-a626-70769f8bae5f",
"practices": [],
"prerequisites": [
"arrays",
"loops",
"lists",
"conditionals"
],
"difficulty": 5,
"topics": [
"algorithms",
"logic"
]
},
{
"slug": "matching-brackets",
"name": "Matching Brackets",
"uuid": "cbbbd7db-224f-45ca-a108-4dc6bc98e4a0",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"stacks",
"strings"
]
},
{
"slug": "meetup",
"name": "Meetup",
"uuid": "d617987e-64b8-4c21-89a9-66a932c4668d",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"conditionals",
"dates",
"enumerations",
"loops"
]
},
{
"slug": "pascals-triangle",
"name": "Pascal's Triangle",
"uuid": "67db30e4-b4d8-4224-b0f8-19a00af40387",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"algorithms",
"arrays",
"exception_handling",
"integers",
"math",
"matrices"
]
},
{
"slug": "pig-latin",
"name": "Pig Latin",
"uuid": "cb2ce8e5-f143-4423-a3bc-959f4222c186",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"arrays",
"lists",
"strings",
"transforming"
]
},
{
"slug": "robot-name",
"name": "Robot Name",
"uuid": "ce475b23-5dfc-4049-90c5-0c387926686f",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"pattern_matching",
"randomness",
"regular_expressions",
"strings",
"text_formatting"
]
},
{
"slug": "spiral-matrix",
"name": "Spiral Matrix",
"uuid": "e3407da5-0524-4565-b724-9778bba1033f",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"arrays",
"integers",
"loops",
"matrices"
]
},
{
"slug": "transpose",
"name": "Transpose",
"uuid": "045de074-eeb3-499e-9cf4-65b75d9988fc",
"practices": [],
"prerequisites": [],
"difficulty": 5,
"topics": [
"lists",
"loops",
"maps",
"strings"
]
},
{
"slug": "bank-account",
"name": "Bank Account",
"uuid": "12e1d685-32be-4b2c-a40b-c68e5b60de1d",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"concurrency",
"exception_handling",
"integers"
]
},
{
"slug": "beer-song",
"name": "Beer Song",
"uuid": "34f0e7d0-29df-44e5-a7a7-4a12584af62e",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"status": "deprecated",
"topics": [
"conditionals",
"loops",
"strings",
"text_formatting",
"variables"
]
},
{
"slug": "bottle-song",
"name": "Bottle Song",
"uuid": "3e82fc4b-0863-43c1-86b5-70dce3c78711",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"conditionals",
"loops",
"strings",
"text_formatting",
"variables"
]
},
{
"slug": "bowling",
"name": "Bowling",
"uuid": "ae084405-48d7-43ea-9bc5-6c4ebae4c1ef",
"practices": [],
"prerequisites": [
"for-loops",
"arrays"
],
"difficulty": 6
},
{
"slug": "flower-field",
"name": "Flower Field",
"uuid": "2bc77dfb-0e27-4beb-b8a1-20bed83ab6b7",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"conditionals",
"games",
"integers",
"lists",
"matrices",
"strings"
]
},
{
"slug": "linked-list",
"name": "Linked List",
"uuid": "fc977979-c8a4-44b6-a685-c8a32bd12bc3",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"algorithms",
"generics",
"lists"
]
},
{
"slug": "minesweeper",
"name": "Minesweeper",
"uuid": "8eb6f225-fa3d-4a33-b476-2cae45053c82",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"conditionals",
"games",
"integers",
"lists",
"matrices",
"strings"
],
"status": "deprecated"
},
{
"slug": "rail-fence-cipher",
"name": "Rail Fence Cipher",
"uuid": "49e730fb-7031-4de9-9bfd-b86564f20d8a",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"cryptography",
"algorithms",
"strings",
"transforming"
]
},
{
"slug": "say",
"name": "Say",
"uuid": "5607dae5-13aa-4cd4-8b4c-d270516182d7",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"strings",
"transforming"
]
},
{
"slug": "wordy",
"name": "Wordy",
"uuid": "3c7a3c6b-8dc7-4e5a-ba72-e1a4bffb0bc4",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"loops",
"pattern_matching",
"strings",
"recursion"
]
},
{
"slug": "dominoes",
"name": "Dominoes",
"uuid": "c52c4b61-dca2-4b73-87b6-b4f2f63d9fdb",
"practices": [],
"prerequisites": [],
"difficulty": 7,
"topics": [
"algorithms",
"exception_handling",
"games",
"lists"
]
},
{
"slug": "change",
"name": "Change",
"uuid": "0d69c1cd-f190-4b3b-8472-bf78c02acbc5",
"practices": [],
"prerequisites": [],
"difficulty": 8,
"topics": [
"algorithms",
"exception_handling",
"integers",
"lists"
]
},
{
"slug": "complex-numbers",
"name": "Complex Numbers",
"uuid": "83dec96f-9cdf-4b9b-abc4-cbd2066d919a",
"practices": [],
"prerequisites": [],
"difficulty": 8,
"topics": [
"floating_point_numbers",
"math"
]
},
{
"slug": "diffie-hellman",
"name": "Diffie-Hellman",
"uuid": "33d64c7c-292e-4221-aed8-ac411a9d490d",
"practices": [],
"prerequisites": [],
"difficulty": 8,
"topics": [
"cryptography",
"randomness",
"algorithms",
"integers"
]
},
{
"slug": "forth",
"name": "Forth",
"uuid": "81d48ea4-0e88-45f2-839f-fe13e2059e92",
"practices": [],
"prerequisites": [],
"difficulty": 8,
"topics": [
"pattern_matching",
"integers"
]
},
{
"slug": "list-ops",
"name": "List Ops",
"uuid": "34f1d5bf-f31f-415e-9905-4d48e6205d28",
"practices": [],
"prerequisites": [],
"difficulty": 8,
"topics": [
"filtering",
"functional_programming",
"generics",
"lists",
"loops"
]
},
{
"slug": "simple-cipher",
"name": "Simple Cipher",
"uuid": "e23b06de-bd91-482f-9783-b0334b75b489",
"practices": [],
"prerequisites": [],
"difficulty": 8,
"topics": [
"cryptography",
"exception_handling",
"randomness",
"security",
"strings"
]
},
{
"slug": "zebra-puzzle",
"name": "Zebra Puzzle",
"uuid": "fe876a9b-2991-4624-a6fe-4311cb78f068",
"practices": [],
"prerequisites": [],
"difficulty": 9,
"topics": [
"algorithms",
"arrays",
"conditionals",
"games"
]
},
{
"slug": "react",
"name": "React",
"uuid": "240788cd-afa5-4fd6-8df0-a158239c0610",
"practices": [],
"prerequisites": [],
"difficulty": 10,
"topics": [
"generics",
"functional_programming",
"classes",
"reactive_programming"
]
}
]
},
"concepts": [
{
"uuid": "72e47dcb-dccf-44a5-ab91-8773c2aec5bd",
"slug": "basics",
"name": "Basics"
},
{
"uuid": "53e0b729-810e-4042-9477-8c8d05a7b302",
"slug": "booleans",
"name": "Booleans"
},
{
"uuid": "157bbe3b-e4f5-41f7-8e0e-e2f57d526617",
"slug": "strings",
"name": "Strings"
},
{
"uuid": "168827c0-4867-449a-ad22-611c87314c48",
"slug": "conditionals",
"name": "Conditionals"
},
{
"uuid": "660e1acd-3072-4bbc-ae44-bbc204da5eab",
"slug": "chars",
"name": "Chars"
},
{
"uuid": "98809a4c-ca3e-4504-b723-aff13bfae850",
"slug": "nullability",
"name": "Nullability"
},
{
"uuid": "1050abed-4271-4519-a44c-a0ca121c7de2",
"slug": "bitwise-operations",
"name": "Bitwise Operations"
}
],
"key_features": [
{
"title": "Pragmatic",
"content": "Kotlin is trying hard to be a modern language with great tooling support.",
"icon": "powerful"
},
{
"title": "Statically Typed",
"content": "Strong type-safety and null-safety features for building robust software.",
"icon": "immutable"
},
{
"title": "Multi-Paradigm",
"content": "Kotlin support both functional and mainstream OOP programming principles.",
"icon": "multi-paradigm"
},
{
"title": "Platform Independent",
"content": "Develop for Android, iOS, JVM, Node.js, browser and many native targets.",
"icon": "cross-platform"
},
{
"title": "Garbage collected",
"content": "Kotlin (as a modern generic-purpose language) does memory management for you.",
"icon": "garbage-collected"
},
{
"title": "Open-Source",
"content": "Kotlin is fully open-source. Submit patches or suggest language improvements.",
"icon": "community"
}
],
"tags": [
"execution_mode/compiled",
"paradigm/functional",
"paradigm/imperative",
"paradigm/object_oriented",
"platform/android",
"platform/linux",
"platform/mac",
"platform/web",
"platform/windows",
"runtime/jvm",
"typing/static",
"typing/strong",
"used_for/backends",
"used_for/cross_platform_development",
"used_for/games",
"used_for/mobile"
]
}
================================================
FILE: docs/ABOUT.md
================================================
# About
Kotlin was designed and developed by JetBrains, the company behind IntelliJ.
It is a language that runs on the JVM which can target versions 6+ (including the [Android platform](https://blog.jetbrains.com/kotlin/2017/05/kotlin-on-android-now-official/)).
JetBrains wanted to use a statically typed language which can remove Java boilerplate code, provide modern functional paradigms, and had seamless two-way Java interoperability with their existing codebase.
The JVM already had alternate languages like Groovy and Scala but neither fit the bill with their desired criteria, so they built Kotlin.
Kotlin syntax is similar to Scala and Swift but pulls in the best-of-breed features from other languages such as
C# and Groovy.
Kotlin took a pragmatic approach at features included in the language by only providing functionality that has
been proven to be useful for developers.
With this decision they implemented a subset of features of Scala with the intent that it will provide more maintainable code with an easier learning curve for developers looking for a "better Java".
JetBrains has a dedicated team of developers working on Kotlin with the codebase available on [Github](https://github.com/JetBrains/kotlin).
================================================
FILE: docs/INSTALLATION.md
================================================
# Installing Kotlin
In addition to the exercism CLI and your favorite text editor, practicing with Exercism exercises in Kotlin requires
* the **Java Development Kit** (JDK) — Kotlin compiles to Java bytecodes; you need to install the JDK which includes both a Java Runtime *and* development tools (most notably, the Java compiler); and
* **Gradle** — a build tool specifically for JVM-based projects and supports Kotlin.
Choose your operating system:
* [Windows](#h-windows)
* [macOS](#h-macos)
* [Linux](#h-linux)
... or ...
* if you prefer to not use a package manager, you can [install manually](#h-install-manually).
Optionally, you can also use a [Java IDE](#h-java-ides).
----
## Windows
Open an administrative command prompt. (If you need assistance opening an administrative prompt, see [open an elevated prompt in Windows 8+](http://www.howtogeek.com/194041/how-to-open-the-command-prompt-as-administrator-in-windows-8.1/) (or [Windows 7](http://www.howtogeek.com/howto/windows-vista/run-a-command-as-administrator-from-the-windows-vista-run-box/)).
1. If you have not installed Chocolatey, do so now:
```batchfile
C:\Windows\system32> @powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
```
2. Install the JDK:
```batchfile
C:\Windows\system32> choco install openjdk11
...
C:\Windows\system32> refreshenv
...
```
We recommend closing the administrative command prompt and opening a new command prompt -- you do not require administrator privileges to practice Exercism exercises.
You now are ready to get started with the Kotlin track of Exercism!
To get started, see "[Running the Tests](https://exercism.org/docs/tracks/kotlin/tests)".
----
## macOS
Below are instructions for install using the most common method - using Homebrew. If you'd rather, you can also [install on macOS without Homebrew](#h-installing-on-macos-without-homebrew).
### Installing
1. If you haven't installed [Homebrew](http://brew.sh), yet, do so now:
```sh
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
2. Tap the [Homebrew Cask](https://caskroom.github.io/) — this allows us to install pre-built binaries like the JDK.
```
$ brew tap adoptopenjdk/openjdk
```
3. Install the JDK:
```
$ brew install --cask adoptopenjdk11
```
You now are ready to get started with the Kotlin track of Exercism!
To get started, see "[Running the Tests](https://exercism.org/docs/tracks/kotlin/tests)".
----
## Linux
Below are instructions for install using the package manager of your distro. If you'd rather, you can also [install on Linux without a package manager](#h-installing-on-linux-without-a-package-manager).
* [Debian](#h-debian)
* [Other Linux distributions](#h-other-linux-distributions)
### Debian
If you are using Debian or its derivatives (like Ubuntu or Linux Mint), use APT:
*(verified on: Ubuntu 14, 16 and 18)*
1. Install the JDK:
```sh
$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:openjdk-r/ppa
$ sudo apt-get update
$ sudo apt-get install openjdk-11-jdk
```
You now are ready to get started with the Kotlin track of Exercism!
To get started, see "[Running the Tests](https://exercism.org/docs/tracks/kotlin/tests)".
----
### Other Linux distributions
There are a lot of ways to install Jdk 11, but one of the easiest ways is to use SDKMAN,
which lets you install OpenJdk11 with ease. Use the following steps:
1. Install SDKMAN:
```sh
$ curl -s "https://get.sdkman.io" | bash
```
(if that doesn't work, take a look at the instructions found here: https://sdkman.io/install )
1. Install openjdk11:
```
$ sdk install java 11.0.2-open
```
You now are ready to get started with the Kotlin track of Exercism!
To get started, see "[Running the Tests](https://exercism.org/docs/tracks/kotlin/tests)".
----
## Install Manually
* [Installing on Windows manually](#h-installing-on-windows-manually)
* [Installing on macOS without Homebrew](#h-installing-on-macos-without-homebrew)
* [Installing on Linux without a package manager](#h-installing-on-linux-without-a-package-manager)
----
### Installing on Windows manually
*NOTE: these instructions are intended for experienced Windows users. If you don't already know how to set environment variables or feel comfortable managing the directory structure, we highly recommend you use the Chocolatey-based install, [above](#h-windows).*
1. Install the JDK:
1. Download "**OpenJDK 11 (LTS)**" from [AdoptOpenJDK](https://adoptopenjdk.net/releases.html?variant=openjdk11#x64_win) (choose **"Install JDK"**).
- Run the installer, using all the defaults.
You now are ready to get started with the Kotlin track of Exercism!
To get started, see "[Running the Tests](https://exercism.org/docs/tracks/kotlin/tests)".
----
### Installing on macOS without Homebrew
*NOTE: these instructions are intended for experienced macOS users. Unless you specifically do not want to use a package manager, we highly recommend using the Homebrew-based installation instructions, [above](#h-macos).*
1. Install the JDK:
1. Download "**OpenJDK 11 (LTS)**" from [AdoptOpenJDK](https://adoptopenjdk.net/releases.html?variant=openjdk11#x64_mac) (choose **"Install JDK"**).
2. Run the installer, using all the defaults.
You now are ready to get started with the Kotlin track of Exercism!
To get started, see "[Running the Tests](https://exercism.org/docs/tracks/kotlin/tests)".
----
### Installing on Linux without a package manager
*NOTE: these instructions are intended for experienced Linux users. Unless you specifically do not want to use a package manager, we highly recommend using the the installation instructions, [above](#h-linux).*
1. Install the JDK:
1. Choose your distribution and download "**OpenJDK 11 (LTS)**" from [AdoptOpenJDK](https://adoptopenjdk.net/releases.html?variant=openjdk11) (choose **"Install JDK"**).
2. Run the installer, using all the defaults.
You now are ready to get started with the Kotlin track of Exercism!
To get started, see "[Running the Tests](https://exercism.org/docs/tracks/kotlin/tests)".
----
## Java IDEs
There are many Java IDEs available. The three most popular are:
* [IntelliJ IDEA](https://www.jetbrains.com/idea/download/) (download the "Community" edition)
- from the authors of Kotlin, this IDE provides the best support for the language.
- [Eclipse](https://www.eclipse.org/downloads/)
- [NetBeans](https://netbeans.org/downloads/) (download the "Java SE" bundle)
and there are [others](https://en.wikibooks.org/wiki/Java_Programming/Java_IDEs).
================================================
FILE: docs/LEARNING.md
================================================
# Recommended learning resources
* [Get started with Kotlin](https://kotlinlang.org/docs/getting-started.html)
* [Kotlin Documentation](https://kotlinlang.org/docs/home.html)
* [Kotlin Idioms](https://kotlinlang.org/docs/idioms.html)
* [Kotlin Tutorial Videos](https://kotlinlang.org/docs/videos.html)
* [Kotlin examples](https://play.kotlinlang.org/byExample/overview)
* [Kotlin on Stack Overflow](https://stackoverflow.com/questions/tagged/kotlin)
================================================
FILE: docs/RESOURCES.md
================================================
# Recommended resources
* [Kotlin Documentation](https://kotlinlang.org/docs/reference/)
* [Kotlin Forums](https://discuss.kotlinlang.org/)
* [Kotlin Slack Channel](http://kotlinlang.slack.com/): [get invite here](http://slack.kotlinlang.org/)
* [Stack Overflow](https://stackoverflow.com/questions/tagged/kotlin)
* [Reddit Channel](https://www.reddit.com/r/kotlin)
* [X (formerly Twitter)](https://x.com/kotlin)
================================================
FILE: docs/SNIPPET.txt
================================================
fun getGreeting(): String {
return "Hello, World!"
}
================================================
FILE: docs/TESTS.md
================================================
# Tests
## Running the Tests
1. Get an exercise:
```bash
$ exercism download -track=kotlin --exercise=hello-world
```
2. Change directory into the exercise:
```bash
$ cd <path_to_exercise_directory>
```
3. Run the tests:
```bash
$ ./gradlew test
```
On most exercises, only the first test is run by default.
The other tests are annotated with `@Ignore` to skip them.
As you solve each test, remove the `@Ignore` from the next one to progress.
This is common practice in test-driven development (or TDD for short).
It is used to ensure that you are working on one problem at a time.
---
Good luck! Have fun!
If you get stuck at any point, feel free to reach out for help on the [forum](https://exercism.org/r/forum) or our `#get-help` channel on our [Discord server](https://exercism.org/r/discord).
================================================
FILE: docs/config.json
================================================
{
"docs": [
{
"uuid": "91fa3615-3f2d-44fe-a060-93dac297583c",
"slug": "installation",
"path": "docs/INSTALLATION.md",
"title": "Installing Kotlin locally",
"blurb": "Learn how to install Kotlin locally to solve Exercism's exercises on your own machine"
},
{
"uuid": "015670c8-aded-4ba5-9824-454e928b8d37",
"slug": "learning",
"path": "docs/LEARNING.md",
"title": "How to learn Kotlin",
"blurb": "An overview of how to get started from scratch with Kotlin"
},
{
"uuid": "f2a23a48-b160-4925-98c6-8844ab63b931",
"slug": "tests",
"path": "docs/TESTS.md",
"title": "Testing on the Kotlin track",
"blurb": "Learn how to test your Kotlin exercises on Exercism"
},
{
"uuid": "336b6d0a-43a1-44d4-b1ac-0320aed1baa7",
"slug": "resources",
"path": "docs/RESOURCES.md",
"title": "Useful Kotlin resources",
"blurb": "A collection of useful resources to help you master Kotlin"
}
]
}
================================================
FILE: exercises/build.gradle.kts
================================================
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm")
}
project(":practice").subprojects {
afterEvaluate {
configurations {
create("starterSourceCompile").extendsFrom(getByName("implementation"))
create("starterSourceRuntime").extendsFrom(getByName("runtimeOnly"))
create("exerciseTestsCompile").extendsFrom(getByName("testImplementation"))
create("exerciseTestsRuntime").extendsFrom(getByName("testRuntimeOnly"))
}
kotlin {
sourceSets {
main {
kotlin.setSrcDirs(listOf(file(".meta/src/reference/kotlin")))
}
test {
kotlin.setSrcDirs(listOf("build/gen/test/kotlin"))
}
val starterSource by creating {
kotlin.setSrcDirs(listOf("src/main/kotlin"))
}
val exerciseTests by creating {
kotlin.setSrcDirs(listOf("src/test/kotlin"))
}
}
}
tasks {
val copyTestsFilteringIgnores by creating(Copy::class) {
from("src/test/kotlin")
into("build/gen/test/kotlin")
filter { line -> if (line.contains("@Ignore")) "" else line }
}
compileKotlin {
doFirst {
println(" (source = ${source.asPath})")
}
}
compileTestKotlin {
dependsOn(copyTestsFilteringIgnores)
doFirst {
println(" (test source = ${source.asPath})")
}
}
/*val compileStarterSourceKotlin by existing(KotlinCompile::class) {
println(" (source = ${source.asPath})")
}*/
}
}
}
================================================
FILE: exercises/concept/annalyns-infiltration/.docs/hints.md
================================================
# Hints
## General
- There are three [boolean operators][reference] to work with boolean values.
- Multiple operators can be combined in a single expression.
## 1. Check if a fast attack can be made
- The [boolean operators][reference] can also be applied to boolean parameters.
[reference]: https://kotlinlang.org/docs/reference/basic-types.html#booleans
================================================
FILE: exercises/concept/annalyns-infiltration/.docs/instructions.md
================================================
# Instructions
In this exercise, you'll be implementing the quest logic for a new RPG game a friend is developing. The game's main character is Annalyn, a brave girl with a fierce and loyal pet dog. Unfortunately, disaster strikes, as her best friend was kidnapped while searching for berries in the forest. Annalyn will try to find and free her best friend, optionally taking her dog with her on this quest.
After some time spent following her best friend's trail, she finds the camp in which her best friend is imprisoned. It turns out there are two kidnappers: a mighty knight and a cunning archer.
Having found the kidnappers, Annalyn considers which of the following actions she can engage in:
- Fast attack: a fast attack can be made if the knight is sleeping, as it takes time for him to get his armor on, so he will be vulnerable.
- Spy: the group can be spied upon if at least one of them is awake. Otherwise, spying is a waste of time.
- Signal prisoner: the prisoner can be signalled using bird sounds if the prisoner is awake and the archer is sleeping, as archers are trained in bird signaling so they could intercept the message.
- _Free prisoner_: Annalyn can try sneaking into the camp to free the prisoner.
This is a risky thing to do and can only succeed in one of two ways:
- If Annalyn has her pet dog with her she can rescue the prisoner if the archer is asleep.
The knight is scared of the dog and the archer will not have time to get ready before Annalyn and the prisoner can escape.
- If Annalyn does not have her dog then she and the prisoner must be very sneaky!
Annalyn can free the prisoner if the prisoner is awake and the knight and archer are both sleeping, but if the prisoner is sleeping they can't be rescued: the prisoner would be startled by Annalyn's sudden appearance and wake up the knight and archer.
You have four tasks: to implement the logic for determining if the above actions are available based on the state of the three characters found in the forest and whether Annalyn's pet dog is present or not.
## 1. Check if a fast attack can be made
Implement the `canFastAttack()` method that takes a boolean value that indicates if the knight is awake. This method returns `true` if a fast attack can be made based on the state of the knight. Otherwise, returns `false`:
```kotlin
val knightIsAwake = true
canFastAttack(knightIsAwake)
// => false
```
## 2. Check if the group can be spied upon
Implement the `canSpy()` method that takes three boolean values, indicating if the knight, archer and the prisoner, respectively, are awake. The method returns `true` if the group can be spied upon, based on the state of the three characters. Otherwise, returns `false`:
```kotlin
val knightIsAwake = false
val archerIsAwake = true
val prisonerIsAwake = false
canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake)
// => true
```
## 3. Check if the prisoner can be signalled
Implement the `canSignalPrisoner()` method that takes two boolean values, indicating if the archer and the prisoner, respectively, are awake. The method returns `true` if the prisoner can be signalled, based on the state of the two characters. Otherwise, returns `false`:
```kotlin
val archerIsAwake = false
val prisonerIsAwake = true
canSignalPrisoner(archerIsAwake, prisonerIsAwake)
// => true
```
## 4. Check if the prisoner can be freed
Implement the `canFreePrisoner()` method that takes four boolean values. The first three parameters indicate if the knight, archer and the prisoner, respectively, are awake. The last parameter indicates if Annalyn's pet dog is present. The method returns `true` if the prisoner can be freed based on the state of the three characters and Annalyn's pet dog presence. Otherwise, it returns `false`:
```kotlin
val knightIsAwake = false
val archerIsAwake = true
val prisonerIsAwake = false
val petDogIsPresent = false
canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent)
// => false
```
================================================
FILE: exercises/concept/annalyns-infiltration/.docs/introduction.md
================================================
# Introduction
Booleans in Kotlin are represented by the `Boolean` type, which values can be either `true` or `false`.
Kotlin supports three built-in [boolean operators][reference]: `!` (negation aka NOT), `&&` (lazy conjunction aka AND), and `||` (lazy disjunction aka OR). The `&&` and `||` operators use _short-circuit evaluation_, which means that the right-hand side of the operator is only evaluated when needed.
================================================
FILE: exercises/concept/annalyns-infiltration/.meta/config.json
================================================
{
"authors": [
"dector"
],
"files": {
"solution": [
"src/main/kotlin/AnnalynsInfiltration.kt"
],
"test": [
"src/test/kotlin/AnnalynsInfiltrationTest.kt"
],
"exemplar": [
".meta/src/reference/kotlin/AnnalynsInfiltration.kt"
]
},
"forked_from": [
"fsharp/annalyns-infiltration"
],
"blurb": "Learn about booleans while helping Annalyn rescue her friend."
}
================================================
FILE: exercises/concept/annalyns-infiltration/.meta/design.md
================================================
# Design
## Learning objectives
- Know of the existence of the `Boolean` type and its two values.
- Know about boolean operators and how to build logical expressions with them.
- Know of the boolean operator precedence rules.
## Out of scope
- Pattern matching on booleans.
## Concepts
- `booleans`: know of the existence of the `Boolean` type and its two values; know about boolean operators and how to build logical expressions with them; know of the boolean operator precedence rules.
## Prerequisites
This exercise's prerequisites Concepts are:
- `basics`: know how to define methods.
================================================
FILE: exercises/concept/annalyns-infiltration/.meta/src/reference/kotlin/AnnalynsInfiltration.kt
================================================
fun canFastAttack(knightIsAwake: Boolean): Boolean =
!knightIsAwake
fun canSpy(
knightIsAwake: Boolean,
archerIsAwake: Boolean,
prisonerIsAwake: Boolean
): Boolean =
knightIsAwake || archerIsAwake || prisonerIsAwake
fun canSignalPrisoner(archerIsAwake: Boolean, prisonerIsAwake: Boolean): Boolean =
!archerIsAwake && prisonerIsAwake
fun canFreePrisoner(
knightIsAwake: Boolean,
archerIsAwake: Boolean,
prisonerIsAwake: Boolean,
petDogIsPresent: Boolean
): Boolean =
!knightIsAwake &&
!archerIsAwake &&
prisonerIsAwake || !archerIsAwake &&
petDogIsPresent
================================================
FILE: exercises/concept/annalyns-infiltration/build.gradle.kts
================================================
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
plugins {
kotlin("jvm")
}
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
testImplementation("junit:junit:4.13.2")
testImplementation(kotlin("test-junit"))
}
tasks.withType<Test> {
testLogging {
exceptionFormat = TestExceptionFormat.FULL
events("passed", "failed", "skipped")
}
}
================================================
FILE: exercises/concept/annalyns-infiltration/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: exercises/concept/annalyns-infiltration/gradlew
================================================
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
================================================
FILE: exercises/concept/annalyns-infiltration/gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: exercises/concept/annalyns-infiltration/settings.gradle.kts
================================================
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
resolutionStrategy {
eachPlugin {
when (requested.id.id) {
"org.jetbrains.kotlin.jvm" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0")
}
}
}
}
================================================
FILE: exercises/concept/annalyns-infiltration/src/main/kotlin/AnnalynsInfiltration.kt
================================================
fun canFastAttack(knightIsAwake: Boolean): Boolean {
TODO("Please implement the canFastAttack() method")
}
fun canSpy(
knightIsAwake: Boolean,
archerIsAwake: Boolean,
prisonerIsAwake: Boolean
): Boolean {
TODO("Please implement the canSpy() method")
}
fun canSignalPrisoner(archerIsAwake: Boolean, prisonerIsAwake: Boolean): Boolean {
TODO("Please implement the canSignalPrisoner() method")
}
fun canFreePrisoner(
knightIsAwake: Boolean,
archerIsAwake: Boolean,
prisonerIsAwake: Boolean,
petDogIsPresent: Boolean
): Boolean {
TODO("Please implement the canFreePrisoner() method")
}
================================================
FILE: exercises/concept/annalyns-infiltration/src/test/kotlin/AnnalynsInfiltrationTest.kt
================================================
import org.junit.Test
import org.junit.Ignore
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class AnnalynsInfiltrationTest {
@Test
fun `Cannot execute fast attack if knight is awake`() {
val knightIsAwake = true
assertFalse(canFastAttack(knightIsAwake))
}
@Test
fun `Can execute fast attack if knight is sleeping`() {
val knightIsAwake = false
assertTrue(canFastAttack(knightIsAwake))
}
@Test
fun `Cannot spy if everyone is sleeping`() {
val knightIsAwake = false
val archerIsAwake = false
val prisonerIsAwake = false
assertFalse(canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
}
@Test
fun `Can spy if everyone but knight is sleeping`() {
val knightIsAwake = true
val archerIsAwake = false
val prisonerIsAwake = false
assertTrue(canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
}
@Test
fun `Can spy if everyone but archer is sleeping`() {
val knightIsAwake = false
val archerIsAwake = true
val prisonerIsAwake = false
assertTrue(canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
}
@Test
fun `Can spy if everyone but prisoner is sleeping`() {
val knightIsAwake = false
val archerIsAwake = false
val prisonerIsAwake = true
assertTrue(canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
}
@Test
fun `Can spy if only knight is sleeping`() {
val knightIsAwake = false
val archerIsAwake = true
val prisonerIsAwake = true
assertTrue(canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
}
@Test
fun `Can spy if only archer is sleeping`() {
val knightIsAwake = true
val archerIsAwake = false
val prisonerIsAwake = true
assertTrue(canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
}
@Test
fun `Can spy if only prisoner is sleeping`() {
val knightIsAwake = true
val archerIsAwake = true
val prisonerIsAwake = false
assertTrue(canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
}
@Test
fun `Can spy if everyone is awake`() {
val knightIsAwake = true
val archerIsAwake = true
val prisonerIsAwake = true
assertTrue(canSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
}
@Test
fun `Can signal prisoner ifarcher is sleeping and prisoner is awake`() {
val archerIsAwake = false
val prisonerIsAwake = true
assertTrue(canSignalPrisoner(archerIsAwake, prisonerIsAwake))
}
@Test
fun `Cannot signal prisoner ifarcher is awake and prisoner is sleeping`() {
val archerIsAwake = true
val prisonerIsAwake = false
assertFalse(canSignalPrisoner(archerIsAwake, prisonerIsAwake))
}
@Test
fun `Cannot signal prisoner ifarcher and prisoner are both sleeping`() {
val archerIsAwake = false
val prisonerIsAwake = false
assertFalse(canSignalPrisoner(archerIsAwake, prisonerIsAwake))
}
@Test
fun `Cannot signal prisoner ifarcher and prisoner are both awake`() {
val archerIsAwake = true
val prisonerIsAwake = true
assertFalse(canSignalPrisoner(archerIsAwake, prisonerIsAwake))
}
@Test
fun `Cannot release prisoner if everyone is awake and pet dog is present`() {
val knightIsAwake = true
val archerIsAwake = true
val prisonerIsAwake = true
val petDogIsPresent = true
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if everyone is awake and pet dog is absent`() {
val knightIsAwake = true
val archerIsAwake = true
val prisonerIsAwake = true
val petDogIsPresent = false
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Can release prisoner if everyone is asleep and pet dog is present`() {
val knightIsAwake = false
val archerIsAwake = false
val prisonerIsAwake = false
val petDogIsPresent = true
assertTrue(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if everyone is asleep and pet dog is absent`() {
val knightIsAwake = false
val archerIsAwake = false
val prisonerIsAwake = false
val petDogIsPresent = false
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Can release prisoner if only prisoner is awake and pet dog is present`() {
val knightIsAwake = false
val archerIsAwake = false
val prisonerIsAwake = true
val petDogIsPresent = true
assertTrue(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Can release prisoner if only prisoner is awake and pet dog is absent`() {
val knightIsAwake = false
val archerIsAwake = false
val prisonerIsAwake = true
val petDogIsPresent = false
assertTrue(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if only archer is awake and pet dog is present`() {
val knightIsAwake = false
val archerIsAwake = true
val prisonerIsAwake = false
val petDogIsPresent = true
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if only archer is awake and pet dog is absent`() {
val knightIsAwake = false
val archerIsAwake = true
val prisonerIsAwake = false
val petDogIsPresent = false
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Can release prisoner if only knight is awake and pet dog is present`() {
val knightIsAwake = true
val archerIsAwake = false
val prisonerIsAwake = false
val petDogIsPresent = true
assertTrue(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if only knight is awake and pet dog is absent`() {
val knightIsAwake = true
val archerIsAwake = false
val prisonerIsAwake = false
val petDogIsPresent = false
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if only knight is asleep and pet dog is present`() {
val knightIsAwake = false
val archerIsAwake = true
val prisonerIsAwake = true
val petDogIsPresent = true
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if only knight is asleep and pet dog is absent`() {
val knightIsAwake = false
val archerIsAwake = true
val prisonerIsAwake = true
val petDogIsPresent = false
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Can release prisoner if only archer is asleep and pet dog is present`() {
val knightIsAwake = true
val archerIsAwake = false
val prisonerIsAwake = true
val petDogIsPresent = true
assertTrue(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if only archer is asleep and pet dog is absent`() {
val knightIsAwake = true
val archerIsAwake = false
val prisonerIsAwake = true
val petDogIsPresent = false
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if only prisoner is asleep and pet dog is present`() {
val knightIsAwake = true
val archerIsAwake = true
val prisonerIsAwake = false
val petDogIsPresent = true
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
@Test
fun `Cannot release prisoner if only prisoner is asleep and pet dog is absent`() {
val knightIsAwake = true
val archerIsAwake = true
val prisonerIsAwake = false
val petDogIsPresent = false
assertFalse(canFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
}
}
================================================
FILE: exercises/concept/log-levels/.docs/hints.md
================================================
# Hints
## General
- Kotlin provides many [functions][ref-strings] for working with Strings. Be sure to check out the `Members & Extensions` tab!
## 1. Get message from a log line
- There is a [function][ref-string-substringAfter] to extract the part of a `String` after a given delimiter.
- Removing whitespace from a `String` is explored in [Remove All Whitespaces from a String in Kotlin][tutorial-trim-white-space].
## 2. Get log level from a log line
- There is also a [function][ref-string-substringBefore] to extract part of a `String` _before_ a given delimiter.
- There is a [way][ref-string-lowercase] to change a `String` to lowercase.
## 3. Reformat a log line
- [String templates][docs-string-template] can be done with a [multiline string][docs-string-multiline].
[docs-string-multiline]: https://kotlinlang.org/docs/strings.html#multiline-strings
[docs-string-template]: https://kotlinlang.org/docs/strings.html#string-templates
[ref-strings]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/
[ref-string-indexOf]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/#-537588047%2FFunctions%2F-1430298843
[ref-string-lowercase]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/#-648004414%2FFunctions%2F-956074838
[ref-string-substringAfter]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/#1564391517%2FFunctions%2F-1430298843
[tutorial-search-text-in-string]: https://javarevisited.blogspot.com/2016/10/how-to-check-if-string-contains-another-substring-in-java-indexof-example.html
[tutorial-trim-white-space]: https://www.baeldung.com/kotlin/string-remove-whitespace
================================================
FILE: exercises/concept/log-levels/.docs/instructions.md
================================================
# Instructions
In this exercise you'll be processing log-liners.
Each log line is a string formatted as follows: "[<LEVEL>]: <MESSAGE>*".
## 1. Get the message from a log line
Implement the `LogLevels.message()` function to return the message from a log line, with the leading and trailing whitespaces removed.
## 2. Get the log level from a log line
Implement the `LogLevels.logLevel()` function to return the log level from a log line in lower case.
## 3. Reformat a log line
Implement the `LogLevels.reformat()` method that takes a log line and a location string and reformats into a message containing two lines.
The first line is formatted as `<LEVEL>@<LOCATIOON>:`, where:
* `<LEVEL>` is the log level in lower case (as from 2. Get the log level from a log line).
* `<LOCATION>` is the location given as the second parameter.
The second line contains exactly two spaces, followed by the log message (as from 1. Get the message from a log line):
```kotlin
reformat("[TRACE]: Start of function", 2, 8)
// => "trace@208:
Start of function"
```
================================================
FILE: exercises/concept/log-levels/.docs/introduction.md
================================================
# Introduction
A [`string`][ref-string] in Kotlin is an immutable sequence of Unicode characters.
[`Immutable`][wiki-immutable] means that any operation on a string must return a new string: the original string can never change.
[`Unicode`][wiki-unicode] means that most of the world's writing systems can be represented, but (in contrast to older languages such as C) there is no 1:1 mapping between characters and bytes.
A string is usually surrounded by double-quotes `" "`.
Some characters need escaping: `\'`, `\\`, plus the usual non-printing characters such as `\t` (tab) and `\n` (newline).
```kotlin
val s = "Escape apostrophe \' and backslash \\."
// Escape apostrophe ' and backslash \.
```
Multi-line strings are surrounded by 3 double-quotes, and can contain arbitrary text (no need for escaping).
```kotlin
val multi = """I'm a
multi-line
string with special characters \ \t """
//I'm a
// multi-line
// string with special characters \ \t
```
Use [trimIndent][trimIndent-doc] to remove the common indenting from the lines.
This is useful for formatting the string:
```kotlin
val multi = """
I'm a
multi-line
string""".trimIndent()
//I'm a
// multi-line
//string
```
Alternatively, [trimMargin][trimMargin-doc] lets you specify a delimiter.
Each line in the `String` then begins after the delimiter.
The delimiter defaults to `|`, but you can specify a different delimiter as a parameter.
For example:
```kotlin
val multi = """
|I'm a
| multi-line
|string""".trimMargin()
//I'm a
// multi-line
//string
val multi2 = """
start>I'm a
start> multi-line
start>string""".trimMargin("start>")
//I'm a
// multi-line
//string
```
Strings can be concatenated with `+`, but this is best limited to short and simple cases.
There are other and often better options.
## String templates
This refers to what some other languages call "interpolation".
If a string contains a dollar sign `$`, followed by an identifier, or contains braces (`{expression}`) surrounding an expression, those are substituted by respectively the value or the result of the expression.
```kotlin
val x = 42
val st = "x is $x, x squared is {x * x}"
// x is 42, x squared is 1764
```
The braces `{ }` are needed around expressions when parsing would otherwise be ambiguous.
In general, use of string templates is a more efficient and idiomatic way to combine strings than using `+`.
## String functions
Kotlin provides _many_ [`functions`][ref-string-functions] to manipulate strings.
Mostly, these are [`extensions functions`][ref-extensions] rather than members of the `String` class, though this has little effect on how we use them.
~~~~exercism/note
Kotlin's rather complex [documentation][ref-string-functions] pages hide extension functions in the default view.
Be sure to click `Members & Extensions` to expand this section.
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/
~~~~
The following examples show just a small selection of what is available:
```kotlin
val str = "Hello World!"
str.length // => 12 (a property, not a function)
str.elementAt(6) // => W
str.elementAtOrNull(20) // => null (index out of range)
str.substring(6, 11) // => "World"
str.substringAfter(" ") // => "World!"
str.lowercase() // => "hello world!"
str.uppercase() // => "HELLO WORLD!"
str.startsWith("Hel") // => true
str.endsWith("xyz") // => false
str.indexOf("0") // => 4
str.toCharArray() // => [H, e, l, l, o, , W, o, r, l, d, !]
"42".toInt() + 1 // => 43 (parsing; see also toFloat)
"Howdy! ".trim() // => "Howdy"
```
[ref-string]: https://kotlinlang.org/docs/strings.html
[wiki-immutable]: https://en.wikipedia.org/wiki/Immutable_object
[wiki-unicode]: https://en.wikipedia.org/wiki/Unicode
[ref-stringbuilder]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/
[ref-extensions]: https://kotlinlang.org/docs/extensions.html#extensions.md
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/
[trimIndent-doc]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/trim-indent.html
[trimMargin-doc]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/trim-margin.html
================================================
FILE: exercises/concept/log-levels/.meta/config.json
================================================
{
"authors": [
"kahgoh"
],
"files": {
"solution": [
"src/main/kotlin/LogLevels.kt"
],
"test": [
"src/test/kotlin/LogLevelsTest.kt"
],
"exemplar": [
".meta/src/reference/kotlin/LogLevels.kt"
]
},
"blurb": "Learn about strings by processing logs."
}
================================================
FILE: exercises/concept/log-levels/.meta/src/reference/kotlin/LogLevels.kt
================================================
fun message(logLine : String) : String {
return logLine.substringAfter(":").trim()
}
fun logLevel(logLine : String) : String {
return logLine.substringBefore(":").removeSurrounding("[", "]").lowercase()
}
fun reformat(logLine : String, location : String) : String {
return """
|${logLevel(logLine)}@$location:
| ${message(logLine)}
""".trimMargin()
}
================================================
FILE: exercises/concept/log-levels/build.gradle.kts
================================================
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
plugins {
kotlin("jvm")
}
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
testImplementation("junit:junit:4.13.2")
testImplementation(kotlin("test-junit"))
}
tasks.withType<Test> {
testLogging {
exceptionFormat = TestExceptionFormat.FULL
events("passed", "failed", "skipped")
}
}
================================================
FILE: exercises/concept/log-levels/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: exercises/concept/log-levels/gradlew
================================================
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional"
gitextract_p8afkg7r/
├── .appends/
│ └── .github/
│ └── labels.yml
├── .github/
│ ├── CODEOWNERS
│ ├── dependabot.yml
│ ├── labels.yml
│ └── workflows/
│ ├── configlet.yml
│ ├── no-important-files-changed.yml
│ ├── pause-community-contributions.yml
│ ├── ping-cross-track-maintainers-team.yml
│ ├── run-configlet-sync.yml
│ ├── sync-labels.yml
│ └── test.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── _template/
│ ├── build.gradle.kts
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── settings.gradle.kts
│ └── src/
│ ├── example/
│ │ └── kotlin/
│ │ └── .keep
│ ├── main/
│ │ └── kotlin/
│ │ └── .keep
│ └── test/
│ └── kotlin/
│ └── .keep
├── bin/
│ ├── README.md
│ ├── build-jq.sh
│ ├── fetch-configlet
│ ├── journey-test.sh
│ ├── run-journey-test-from-ci.sh
│ └── unit-tests.sh
├── concepts/
│ ├── basics/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── bitwise-operations/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── booleans/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── chars/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── conditionals/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ ├── nullability/
│ │ ├── .meta/
│ │ │ └── config.json
│ │ ├── about.md
│ │ ├── introduction.md
│ │ └── links.json
│ └── strings/
│ ├── .meta/
│ │ └── config.json
│ ├── about.md
│ ├── introduction.md
│ └── links.json
├── config.json
├── docs/
│ ├── ABOUT.md
│ ├── INSTALLATION.md
│ ├── LEARNING.md
│ ├── RESOURCES.md
│ ├── SNIPPET.txt
│ ├── TESTS.md
│ └── config.json
├── exercises/
│ ├── build.gradle.kts
│ ├── concept/
│ │ ├── annalyns-infiltration/
│ │ │ ├── .docs/
│ │ │ │ ├── hints.md
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── design.md
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── AnnalynsInfiltration.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── AnnalynsInfiltration.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AnnalynsInfiltrationTest.kt
│ │ ├── log-levels/
│ │ │ ├── .docs/
│ │ │ │ ├── hints.md
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── LogLevels.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── LogLevels.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── LogLevelsTest.kt
│ │ └── lucians-luscious-lasagna/
│ │ ├── .docs/
│ │ │ ├── hints.md
│ │ │ ├── instructions.md
│ │ │ └── introduction.md
│ │ ├── .meta/
│ │ │ ├── config.json
│ │ │ ├── design.md
│ │ │ └── src/
│ │ │ └── reference/
│ │ │ └── kotlin/
│ │ │ └── LuciansLusciousLasagna.kt
│ │ ├── build.gradle.kts
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── settings.gradle.kts
│ │ └── src/
│ │ ├── main/
│ │ │ └── kotlin/
│ │ │ └── LuciansLusciousLasagna.kt
│ │ └── test/
│ │ └── kotlin/
│ │ └── LuciansLusciousLasagnaTests.kt
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradle.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── practice/
│ │ ├── accumulate/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── Accumulate.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Accumulate.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AccumulateTest.kt
│ │ ├── acronym/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Acronym.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Acronym.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AcronymTest.kt
│ │ ├── affine-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── AffineCipher.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── AffineCipher.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AffineCipherTest.kt
│ │ ├── all-your-base/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BaseConverter.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BaseConverter.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BaseConverterTest.kt
│ │ ├── allergies/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Allergen.kt
│ │ │ │ │ └── Allergies.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Allergen.kt
│ │ │ │ └── Allergies.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AllergiesTest.kt
│ │ ├── anagram/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.append.md
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Anagram.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Anagram.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AnagramTest.kt
│ │ ├── armstrong-numbers/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ArmstrongNumber.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ArmstrongNumber.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ArmstrongNumberTest.kt
│ │ ├── atbash-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Atbash.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Atbash.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── AtbashTest.kt
│ │ ├── bank-account/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── BankAccount.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BankAccount.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BankAccountTest.kt
│ │ ├── beer-song/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BeerSong.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BeerSong.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BeerSongTest.kt
│ │ ├── binary/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Binary.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Binary.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BinaryTest.kt
│ │ ├── binary-search/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BinarySearch.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BinarySearch.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BinarySearchTest.kt
│ │ ├── binary-search-tree/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BinarySearchTree.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BinarySearchTree.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BinarySearchTreeTest.kt
│ │ ├── bob/
│ │ │ ├── .approaches/
│ │ │ │ ├── answer-list/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── config.json
│ │ │ │ ├── if-expressions/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── introduction.md
│ │ │ │ └── when-expression/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Bob.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Bob.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BobTest.kt
│ │ ├── bottle-song/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── BottleSong.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BottleSong.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BottleSongTest.kt
│ │ ├── bowling/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── BowlingGame.kt
│ │ │ │ │ └── Frame.kt
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── BowlingGame.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BowlingGameTest.kt
│ │ ├── change/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ChangeCalculator.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ChangeCalculator.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ChangeCalculatorTest.kt
│ │ ├── circular-buffer/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── CircularBuffer.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── CircularBuffer.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── CircularBufferTest.kt
│ │ ├── clock/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Clock.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Clock.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ ├── ClockAddTest.kt
│ │ │ ├── ClockCreationTest.kt
│ │ │ ├── ClockEqualTest.kt
│ │ │ └── ClockSubtractTest.kt
│ │ ├── collatz-conjecture/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── CollatzCalculator.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── CollatzCalculator.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── CollatzCalculatorTest.kt
│ │ ├── complex-numbers/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ComplexNumber.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ComplexNumber.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ComplexNumberTest.kt
│ │ ├── crypto-square/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── CryptoSquare.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── CryptoSquare.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── CryptoSquareTest.kt
│ │ ├── custom-set/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── CustomSet.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── CustomSet.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── CustomSetTest.kt
│ │ ├── darts/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── hypot-for-radius/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Darts.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Darts.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DartsTest.kt
│ │ ├── diamond/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── DiamondPrinter.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── DiamondPrinter.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DiamondPrinterTest.kt
│ │ ├── difference-of-squares/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── formula/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── DifferenceOfSquares.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── DifferenceOfSquares.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SquaresTest.kt
│ │ ├── diffie-hellman/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── DiffieHellman.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── DiffieHellman.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DiffieHellmanTest.kt
│ │ ├── dnd-character/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── DndCharacter.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── DndCharacter.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DndCharacterTest.kt
│ │ ├── dominoes/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Dominoes.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Dominoes.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DominoesTest.kt
│ │ ├── eliuds-eggs/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── EliudsEggs.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── EliudsEggs.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── EliudsEggsTest.kt
│ │ ├── etl/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ETL.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ETL.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ETLTest.kt
│ │ ├── flatten-array/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Flattener.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Flattener.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── FlattenerTest.kt
│ │ ├── flower-field/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── FlowerField.kt
│ │ │ │ └── tests.toml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── FlowerField.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── FlowerFieldTest.kt
│ │ ├── forth/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Forth.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Forth.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ForthTest.kt
│ │ ├── gigasecond/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── introduction.md
│ │ │ │ └── secondary-constructor-atstartofday/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Gigasecond.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Gigasecond.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── GigasecondTest.kt
│ │ ├── grade-school/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── GradeSchool.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── GradeSchool.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SchoolTest.kt
│ │ ├── grains/
│ │ │ ├── .approaches/
│ │ │ │ ├── bit-shifting/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── config.json
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Grains.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Grains.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── BoardTest.kt
│ │ ├── hamming/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── introduction.md
│ │ │ │ └── zip-count/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Hamming.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Hamming.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── HammingTest.kt
│ │ ├── hello-world/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.append.md
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── HelloWorld.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── TUTORIAL.md
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── HelloWorld.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── HelloWorldTest.kt
│ │ ├── hexadecimal/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── Hexadecimal.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Hexadecimal.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── HexadecimalTest.kt
│ │ ├── isbn-verifier/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── fold-when-let/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── IsbnVerifier.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── IsbnVerifier.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── IsbnVerifierTest.kt
│ │ ├── isogram/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Isogram.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Isogram.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── IsogramTest.kt
│ │ ├── kindergarten-garden/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── KindergartenGarden.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── KindergartenGarden.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── KindergartenGardenTest.kt
│ │ ├── knapsack/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Knapsack.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Knapsack.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── KnapsackTest.kt
│ │ ├── largest-series-product/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── LargestSeriesProduct.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── LargestSeriesProduct.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SeriesTest.kt
│ │ ├── leap/
│ │ │ ├── .approaches/
│ │ │ │ ├── boolean-chain/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── built-in-method/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── config.json
│ │ │ │ ├── introduction.md
│ │ │ │ ├── plusdays/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── ternary-expression/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Leap.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Leap.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── LeapTest.kt
│ │ ├── linked-list/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── LinkedList.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── LinkedList.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DequeTest.kt
│ │ ├── list-ops/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.append.md
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ListOps.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ListOps.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ListExtensionsTest.kt
│ │ ├── luhn/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Luhn.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Luhn.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── LuhnTest.kt
│ │ ├── matching-brackets/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── MatchingBrackets.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── MatchingBrackets.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MatchingBracketsTest.kt
│ │ ├── matrix/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Matrix.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Matrix.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MatrixTest.kt
│ │ ├── meetup/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Meetup.kt
│ │ │ │ │ └── MeetupSchedule.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Meetup.kt
│ │ │ │ └── MeetupSchedule.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MeetupTest.kt
│ │ ├── minesweeper/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Minesweeper.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Minesweeper.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MinesweeperBoardTest.kt
│ │ ├── nth-prime/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── NthPrime.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── NthPrime.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PrimeTest.kt
│ │ ├── nucleotide-count/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── groupby-plus/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Dna.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Dna.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── DnaTest.kt
│ │ ├── pangram/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Pangram.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Pangram.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PangramTest.kt
│ │ ├── pascals-triangle/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── PascalsTriangle.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── PascalsTriangle.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PascalsTriangleTest.kt
│ │ ├── perfect-numbers/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── NaturalNumber.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── NaturalNumber.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── NaturalNumberTest.kt
│ │ ├── phone-number/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── PhoneNumber.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── PhoneNumber.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PhoneNumberTest.kt
│ │ ├── pig-latin/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── hashset-lookup/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── PigLatin.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── PigLatin.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PigLatinTest.kt
│ │ ├── prime-factors/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── PrimeFactors.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── PrimeFactors.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── PrimeFactorCalculatorTest.kt
│ │ ├── protein-translation/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ProteinTranslation.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ProteinTranslation.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ProteinTranslationTest.kt
│ │ ├── rail-fence-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RailFenceCipher.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RailFenceCipher.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RailFenceCipherTest.kt
│ │ ├── raindrops/
│ │ │ ├── .approaches/
│ │ │ │ ├── buildstring/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ ├── config.json
│ │ │ │ ├── fold-on-list/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Raindrops.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Raindrops.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RaindropsTest.kt
│ │ ├── react/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── React.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── React.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ReactTest.kt
│ │ ├── resistor-color/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ResistorColor.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ResistorColor.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ResistorColorTest.kt
│ │ ├── resistor-color-duo/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ └── ResistorColorDuo.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Color.kt
│ │ │ │ └── ResistorColorDuo.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ResistorColorDuoTest.kt
│ │ ├── resistor-color-trio/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ ├── ResistorColorTrio.kt
│ │ │ │ │ └── Unit.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Color.kt
│ │ │ │ ├── ResistorColorTrio.kt
│ │ │ │ └── Unit.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ResistorColorTrioTest.kt
│ │ ├── reverse-string/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ReverseString.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ReverseString.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ReverseStringTest.kt
│ │ ├── rna-transcription/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RnaTranscription.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RnaTranscription.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RnaTranscriptionTest.kt
│ │ ├── robot-name/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── RobotName.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RobotName.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RobotTest.kt
│ │ ├── robot-simulator/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── GridPosition.kt
│ │ │ │ │ ├── Orientation.kt
│ │ │ │ │ └── Robot.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── GridPosition.kt
│ │ │ │ ├── Orientation.kt
│ │ │ │ └── Robot.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RobotTest.kt
│ │ ├── roman-numerals/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── fold-repeat/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RomanNumerals.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RomanNumerals.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RomanNumeralsTest.kt
│ │ ├── rotational-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RotationalCipher.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RotationalCipher.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RotationalCipherTest.kt
│ │ ├── run-length-encoding/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── RunLengthEncoding.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── RunLengthEncoding.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── RunLengthEncodingTest.kt
│ │ ├── saddle-points/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Matrix.kt
│ │ │ │ │ └── MatrixCoordinate.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Matrix.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── MatrixTest.kt
│ │ ├── say/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Say.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Say.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── NumberSpellerTest.kt
│ │ ├── scale-generator/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Scale.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Scale.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ScaleTest.kt
│ │ ├── scrabble-score/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── introduction.md
│ │ │ │ ├── map/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── when/
│ │ │ │ ├── content.md
│ │ │ │ └── snippet.txt
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── ScrabbleScore.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── ScrabbleScore.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── ScrabbleScoreTest.kt
│ │ ├── secret-handshake/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── HandshakeCalculator.kt
│ │ │ │ │ └── Signal.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── HandshakeCalculator.kt
│ │ │ │ └── Signal.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── HandshakeCalculatorTest.kt
│ │ ├── series/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Series.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Series.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SeriesTest.kt
│ │ ├── sieve/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Sieve.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Sieve.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SieveTest.kt
│ │ ├── simple-cipher/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── SimpleCipher.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── SimpleCipher.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ ├── IncorrectKeyCipherTest.kt
│ │ │ ├── RandomKeyCipherTest.kt
│ │ │ ├── SimpleCipherTest.kt
│ │ │ └── SubstitutionCipherTest.kt
│ │ ├── space-age/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── SpaceAge.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── SpaceAge.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SpaceAgeTest.kt
│ │ ├── spiral-matrix/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── SpiralMatrix.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── SpiralMatrix.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SpiralMatrixTest.kt
│ │ ├── strain/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ └── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ └── Strain.kt
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Strain.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── StrainTest.kt
│ │ ├── sublist/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Relationship.kt
│ │ │ │ │ └── Sublist.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Sublist.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SublistTest.kt
│ │ ├── sum-of-multiples/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── SumOfMultiples.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── SumOfMultiples.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── SumOfMultiplesTest.kt
│ │ ├── transpose/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Transpose.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Transpose.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── TransposeTest.kt
│ │ ├── triangle/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Triangle.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Triangle.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── TriangleTest.kt
│ │ ├── two-fer/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── TwoFer.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── TwoFer.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── TwoFerTest.kt
│ │ ├── word-count/
│ │ │ ├── .approaches/
│ │ │ │ ├── config.json
│ │ │ │ ├── findall-groupingby-eachcount/
│ │ │ │ │ ├── content.md
│ │ │ │ │ └── snippet.txt
│ │ │ │ └── introduction.md
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── WordCount.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── WordCount.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── WordCountTest.kt
│ │ ├── wordy/
│ │ │ ├── .docs/
│ │ │ │ └── instructions.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ └── Wordy.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ └── Wordy.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── WordyTest.kt
│ │ ├── yacht/
│ │ │ ├── .docs/
│ │ │ │ ├── instructions.md
│ │ │ │ └── introduction.md
│ │ │ ├── .meta/
│ │ │ │ ├── config.json
│ │ │ │ ├── src/
│ │ │ │ │ └── reference/
│ │ │ │ │ └── kotlin/
│ │ │ │ │ ├── Yacht.kt
│ │ │ │ │ └── YachtCategory.kt
│ │ │ │ ├── tests.toml
│ │ │ │ └── version
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle.kts
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ └── kotlin/
│ │ │ │ ├── Yacht.kt
│ │ │ │ └── YachtCategory.kt
│ │ │ └── test/
│ │ │ └── kotlin/
│ │ │ └── YachtTest.kt
│ │ └── zebra-puzzle/
│ │ ├── .docs/
│ │ │ ├── instructions.md
│ │ │ └── introduction.md
│ │ ├── .meta/
│ │ │ ├── config.json
│ │ │ ├── src/
│ │ │ │ └── reference/
│ │ │ │ └── kotlin/
│ │ │ │ ├── HeapsPermutation.kt
│ │ │ │ └── ZebraPuzzle.kt
│ │ │ ├── tests.toml
│ │ │ └── version
│ │ ├── build.gradle.kts
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── settings.gradle.kts
│ │ └── src/
│ │ ├── main/
│ │ │ └── kotlin/
│ │ │ └── ZebraPuzzle.kt
│ │ └── test/
│ │ └── kotlin/
│ │ └── ZebraPuzzleTest.kt
│ ├── settings.gradle.kts
│ └── shared/
│ └── .docs/
│ ├── help.md
│ └── tests.md
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── reference/
│ └── implementing-a-concept-exercise.md
└── scripts/
├── canonical_data_check.sh
├── fix_exercises_symlinks.sh
├── updateGradleFilesFromTemplate.kts
└── updateTemplateBuildFile.kts
Condensed preview — 1488 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,467K chars).
[
{
"path": ".appends/.github/labels.yml",
"chars": 1677,
"preview": "# ----------------------------------------------------------------------------------------- #\n# These are the repository"
},
{
"path": ".github/CODEOWNERS",
"chars": 199,
"preview": "# Code owners\n.github/CODEOWNERS @exercism/maintainers-admin\n\n# Changes to `fetch-configlet` should be made in the "
},
{
"path": ".github/dependabot.yml",
"chars": 173,
"preview": "version: 2\n\nupdates:\n\n # Keep dependencies for GitHub Actions up-to-date\n - package-ecosystem: 'github-actions'\n di"
},
{
"path": ".github/labels.yml",
"chars": 7149,
"preview": "# --------------------------------------------------------------- #\n# This is an auto-generated file - Do not manually e"
},
{
"path": ".github/workflows/configlet.yml",
"chars": 215,
"preview": "name: Configlet\n\non:\n pull_request:\n push:\n branches:\n - main\n workflow_dispatch:\n\npermissions:\n contents: r"
},
{
"path": ".github/workflows/no-important-files-changed.yml",
"chars": 634,
"preview": "name: No important files changed\n\non:\n pull_request_target:\n types: [opened]\n branches: [main]\n paths:\n -"
},
{
"path": ".github/workflows/pause-community-contributions.yml",
"chars": 596,
"preview": "name: Pause Community Contributions\n\non:\n issues:\n types:\n - opened\n pull_request_target:\n types:\n - o"
},
{
"path": ".github/workflows/ping-cross-track-maintainers-team.yml",
"chars": 424,
"preview": "name: Ping cross-track maintainers team\n\non:\n pull_request_target:\n types:\n - opened\n\npermissions:\n pull-reque"
},
{
"path": ".github/workflows/run-configlet-sync.yml",
"chars": 192,
"preview": "name: Run Configlet Sync\n\non:\n workflow_dispatch:\n schedule:\n - cron: '0 0 15 * *'\n\njobs:\n call-gha-workflow:\n "
},
{
"path": ".github/workflows/sync-labels.yml",
"chars": 333,
"preview": "name: Tools\n\non:\n push:\n branches:\n - main\n paths:\n - .github/labels.yml\n - .github/workflows/sync"
},
{
"path": ".github/workflows/test.yml",
"chars": 325,
"preview": "name: Kotlin / Test\n\non:\n push:\n branches: [main]\n pull_request:\n workflow_dispatch:\n\njobs:\n ci:\n runs-on: ubu"
},
{
"path": ".gitignore",
"chars": 97,
"preview": "*.swp\n.DS_Store\nbin/configlet\nbin/configlet.exe\nbin/jq*\nCHECKLIST\nbuild\n.gradle\n.idea\n*.iml\nout/\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 4341,
"preview": "# Code of Conduct\n\n## Introduction\n\nExercism is a platform centered around empathetic conversation.\nWe have a low tolera"
},
{
"path": "LICENSE",
"chars": 1065,
"preview": "MIT License\n\nCopyright (c) 2021 Exercism\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
},
{
"path": "README.md",
"chars": 5805,
"preview": "# Exercism Kotlin Track\n\n[](https://travis-ci.or"
},
{
"path": "_template/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "_template/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "_template/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "_template/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "_template/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "_template/src/example/kotlin/.keep",
"chars": 0,
"preview": ""
},
{
"path": "_template/src/main/kotlin/.keep",
"chars": 0,
"preview": ""
},
{
"path": "_template/src/test/kotlin/.keep",
"chars": 0,
"preview": ""
},
{
"path": "bin/README.md",
"chars": 235,
"preview": "# Cross-track consistency\n\nMany of these scripts are shared between the Java and Kotlin tracks. If you make an update to"
},
{
"path": "bin/build-jq.sh",
"chars": 233,
"preview": "#!/usr/bin/env bash\nset -ex\n\npushd bin\ncurl --location https://github.com/stedolan/jq/releases/download/jq-1.5/jq-1.5.ta"
},
{
"path": "bin/fetch-configlet",
"chars": 2349,
"preview": "#!/usr/bin/env bash\n\n# This file is a copy of the\n# https://github.com/exercism/configlet/blob/main/scripts/fetch-config"
},
{
"path": "bin/journey-test.sh",
"chars": 5830,
"preview": "#!/usr/bin/env bash\n\nTRACK=kotlin\nTRACK_REPO=\"$TRACK\"\nEXERCISES_TO_SOLVE=$@\n\non_exit() {\n echo \">>> on_exit()\"\n cd"
},
{
"path": "bin/run-journey-test-from-ci.sh",
"chars": 2676,
"preview": "#!/bin/bash\n\ncontains_setup_file() {\n local files=$1\n for file in $files; do\n if [[ $file == *.gradle || $f"
},
{
"path": "bin/unit-tests.sh",
"chars": 422,
"preview": "#!/usr/bin/env bash\nset -e\n./gradlew --version\n\n# Clean up any left-over files from a previous invocation, to avoid conf"
},
{
"path": "concepts/basics/.meta/config.json",
"chars": 107,
"preview": "{\n \"blurb\": \"TODO: add blurb for basics concept\",\n \"authors\": [\n \"dector\"\n ],\n \"contributors\": []\n}\n"
},
{
"path": "concepts/basics/about.md",
"chars": 3939,
"preview": "# About Basics\n\nKotlin is a statically typed language, designed to be fully interoperable with Java.\n\nDistinguishing it "
},
{
"path": "concepts/basics/introduction.md",
"chars": 2397,
"preview": "# Introduction\n\nKotlin is a **statically typed** programming language developed by JetBrains. This means that the type o"
},
{
"path": "concepts/basics/links.json",
"chars": 3,
"preview": "[]\n"
},
{
"path": "concepts/bitwise-operations/.meta/config.json",
"chars": 182,
"preview": "{\n \"authors\": [\n \"colinleach\"\n ],\n \"contributors\": [],\n \"blurb\": \"Kotlin provides a set of bitwise operations tha"
},
{
"path": "concepts/bitwise-operations/about.md",
"chars": 4216,
"preview": "# About Bits\n\nBinary digits ultimately map directly to the transistors in your CPU or RAM, and whether each is \"on\" or \""
},
{
"path": "concepts/bitwise-operations/introduction.md",
"chars": 3486,
"preview": "# Introduction\n\nBinary digits ultimately map directly to the transistors in your CPU or RAM, and whether each is \"on\" or"
},
{
"path": "concepts/bitwise-operations/links.json",
"chars": 141,
"preview": "[\n {\n \"url\": \"https://kotlinlang.org/docs/numbers.html#bitwise-operations\",\n \"description\": \"Kotlin manual: bitwi"
},
{
"path": "concepts/booleans/.meta/config.json",
"chars": 101,
"preview": "{\n \"blurb\": \"TODO: add blurb for booleans concept\",\n \"authors\": [\"dector\"],\n \"contributors\": []\n}\n"
},
{
"path": "concepts/booleans/about.md",
"chars": 1046,
"preview": "# About\n\nBooleans in Kotlin are represented by the `Boolean` type, which values can be either `true` or `false`.\n\nKotlin"
},
{
"path": "concepts/booleans/introduction.md",
"chars": 421,
"preview": "# Introduction\n\nBooleans in Kotlin are represented by the `Boolean` type, which values can be either `true` or `false`.\n"
},
{
"path": "concepts/booleans/links.json",
"chars": 239,
"preview": "[\n {\n \"url\": \"https://kotlinlang.org/docs/reference/basic-types.html#booleans\",\n \"description\": \"reference\"\n },\n"
},
{
"path": "concepts/chars/.meta/config.json",
"chars": 206,
"preview": "{\n \"authors\": [\n \"colinleach\"\n ],\n \"contributors\": [],\n \"blurb\": \"Kotlin was designed from the beginning to use a"
},
{
"path": "concepts/chars/about.md",
"chars": 6202,
"preview": "# About chars\n\nThis is potentially a _big_ subject!\nIt is possible to write a long book about it, and several people hav"
},
{
"path": "concepts/chars/introduction.md",
"chars": 5102,
"preview": "# Introduction\n\nThis is potentially a _big_ subject!\nIt is possible to write a long book about it, and several people ha"
},
{
"path": "concepts/chars/links.json",
"chars": 254,
"preview": "[\n {\n \"url\": \"https://kotlinlang.org/docs/characters.html\",\n \"description\": \"Kotlin introduction to characters.\"\n"
},
{
"path": "concepts/conditionals/.meta/config.json",
"chars": 195,
"preview": "{\n \"authors\": [\n \"colinleach\"\n ],\n \"contributors\": [],\n \"blurb\": \"The conditionals `if`, `else if` and `else` are"
},
{
"path": "concepts/conditionals/about.md",
"chars": 2628,
"preview": "# About conditionals\n\n## Comparison operators\n\n[Comparison operators][operators] are similar to many other languages, wi"
},
{
"path": "concepts/conditionals/introduction.md",
"chars": 1146,
"preview": "# Introduction\n\n## Comparison operators\n\nComparison operators are similar to many other languages.\n\nFor equality, the op"
},
{
"path": "concepts/conditionals/links.json",
"chars": 420,
"preview": "[\n {\n \"url\": \"https://kotlinlang.org/docs/keyword-reference.html#operators-and-special-symbols\",\n \"description\": "
},
{
"path": "concepts/nullability/.meta/config.json",
"chars": 184,
"preview": "{\n \"authors\": [\n \"colinleach\"\n ],\n \"contributors\": [],\n \"blurb\": \"Kotlin provides optional nullable types, plus f"
},
{
"path": "concepts/nullability/about.md",
"chars": 4468,
"preview": "# About Nullability\n\nIn an ideal world, we could rely on everything being nicely defined, with concrete values and no ga"
},
{
"path": "concepts/nullability/introduction.md",
"chars": 3600,
"preview": "# Introduction\n\nIn an ideal world, we could rely on everything being nicely defined, with concrete values and no gaps.\n\n"
},
{
"path": "concepts/nullability/links.json",
"chars": 286,
"preview": "[\n {\n \"url\": \"https://kotlinlang.org/docs/null-safety.html\",\n \"description\": \"Kotlin introduction to null safety."
},
{
"path": "concepts/strings/.meta/config.json",
"chars": 133,
"preview": "{\n \"authors\": [\n \"colinleach\"\n ],\n \"contributors\": [],\n \"blurb\": \"Strings are an immutable sequence of Unicode ch"
},
{
"path": "concepts/strings/about.md",
"chars": 7653,
"preview": "# About Strings\n\nA [`string`][ref-string] in Kotlin is an immutable sequence of Unicode characters.\n\n[`Immutable`][wiki-"
},
{
"path": "concepts/strings/introduction.md",
"chars": 4262,
"preview": "# Introduction\n\nA [`string`][ref-string] in Kotlin is an immutable sequence of Unicode characters.\n\n[`Immutable`][wiki-i"
},
{
"path": "concepts/strings/links.json",
"chars": 357,
"preview": "[\n {\n \"url\": \"https://kotlinlang.org/docs/strings.html\",\n \"description\": \"Kotlin string introduction\"\n },\n {\n "
},
{
"path": "config.json",
"chars": 35518,
"preview": "{\n \"language\": \"Kotlin\",\n \"slug\": \"kotlin\",\n \"active\": true,\n \"status\": {\n \"concept_exercises\": false,\n \"test_"
},
{
"path": "docs/ABOUT.md",
"chars": 1247,
"preview": "# About\n\nKotlin was designed and developed by JetBrains, the company behind IntelliJ. \r\nIt is a language that runs on th"
},
{
"path": "docs/INSTALLATION.md",
"chars": 6992,
"preview": "# Installing Kotlin\n\nIn addition to the exercism CLI and your favorite text editor, practicing with Exercism exercises i"
},
{
"path": "docs/LEARNING.md",
"chars": 453,
"preview": "# Recommended learning resources\n\n* [Get started with Kotlin](https://kotlinlang.org/docs/getting-started.html)\n* [Kotli"
},
{
"path": "docs/RESOURCES.md",
"chars": 415,
"preview": "# Recommended resources\n\n* [Kotlin Documentation](https://kotlinlang.org/docs/reference/)\n* [Kotlin Forums](https://disc"
},
{
"path": "docs/SNIPPET.txt",
"chars": 57,
"preview": "fun getGreeting(): String {\n return \"Hello, World!\"\n}\n"
},
{
"path": "docs/TESTS.md",
"chars": 849,
"preview": "# Tests\n\n## Running the Tests\n\n1. Get an exercise:\n\n ```bash\n $ exercism download -track=kotlin --exercise=hello-w"
},
{
"path": "docs/config.json",
"chars": 1025,
"preview": "{\n \"docs\": [\n {\n \"uuid\": \"91fa3615-3f2d-44fe-a060-93dac297583c\",\n \"slug\": \"installation\",\n \"path\": \"d"
},
{
"path": "exercises/build.gradle.kts",
"chars": 1876,
"preview": "import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n kotlin(\"jvm\")\n}\n\nproject(\":practice\").subprojects "
},
{
"path": "exercises/concept/annalyns-infiltration/.docs/hints.md",
"chars": 361,
"preview": "# Hints\n\n## General\n\n- There are three [boolean operators][reference] to work with boolean values.\n- Multiple operators "
},
{
"path": "exercises/concept/annalyns-infiltration/.docs/instructions.md",
"chars": 3995,
"preview": "# Instructions\n\nIn this exercise, you'll be implementing the quest logic for a new RPG game a friend is developing. The "
},
{
"path": "exercises/concept/annalyns-infiltration/.docs/introduction.md",
"chars": 421,
"preview": "# Introduction\n\nBooleans in Kotlin are represented by the `Boolean` type, which values can be either `true` or `false`.\n"
},
{
"path": "exercises/concept/annalyns-infiltration/.meta/config.json",
"chars": 418,
"preview": "{\n \"authors\": [\n \"dector\"\n ],\n \"files\": {\n \"solution\": [\n \"src/main/kotlin/AnnalynsInfiltration.kt\"\n ],"
},
{
"path": "exercises/concept/annalyns-infiltration/.meta/design.md",
"chars": 598,
"preview": "# Design\n\n## Learning objectives\n\n- Know of the existence of the `Boolean` type and its two values.\n- Know about boolean"
},
{
"path": "exercises/concept/annalyns-infiltration/.meta/src/reference/kotlin/AnnalynsInfiltration.kt",
"chars": 626,
"preview": "fun canFastAttack(knightIsAwake: Boolean): Boolean =\n !knightIsAwake\n\nfun canSpy(\n knightIsAwake: Boolean,\n arc"
},
{
"path": "exercises/concept/annalyns-infiltration/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/concept/annalyns-infiltration/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/concept/annalyns-infiltration/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/concept/annalyns-infiltration/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/concept/annalyns-infiltration/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/concept/annalyns-infiltration/src/main/kotlin/AnnalynsInfiltration.kt",
"chars": 629,
"preview": "fun canFastAttack(knightIsAwake: Boolean): Boolean {\n TODO(\"Please implement the canFastAttack() method\")\n}\n\nfun canS"
},
{
"path": "exercises/concept/annalyns-infiltration/src/test/kotlin/AnnalynsInfiltrationTest.kt",
"chars": 8823,
"preview": "import org.junit.Test\nimport org.junit.Ignore\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n\nclass Annal"
},
{
"path": "exercises/concept/log-levels/.docs/hints.md",
"chars": 1644,
"preview": "# Hints\n\n## General\n\n- Kotlin provides many [functions][ref-strings] for working with Strings. Be sure to check out the "
},
{
"path": "exercises/concept/log-levels/.docs/instructions.md",
"chars": 1059,
"preview": "# Instructions\n\nIn this exercise you'll be processing log-liners.\n\nEach log line is a string formatted as follows: \"[<LE"
},
{
"path": "exercises/concept/log-levels/.docs/introduction.md",
"chars": 4311,
"preview": "# Introduction\n\nA [`string`][ref-string] in Kotlin is an immutable sequence of Unicode characters.\n\n[`Immutable`][wiki-i"
},
{
"path": "exercises/concept/log-levels/.meta/config.json",
"chars": 304,
"preview": "{\n \"authors\": [\n \"kahgoh\"\n ],\n \"files\": {\n \"solution\": [\n \"src/main/kotlin/LogLevels.kt\"\n ],\n \"test\""
},
{
"path": "exercises/concept/log-levels/.meta/src/reference/kotlin/LogLevels.kt",
"chars": 385,
"preview": "fun message(logLine : String) : String {\n return logLine.substringAfter(\":\").trim()\n}\n\nfun logLevel(logLine : String)"
},
{
"path": "exercises/concept/log-levels/build.gradle.kts",
"chars": 430,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/concept/log-levels/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/concept/log-levels/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/concept/log-levels/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/concept/log-levels/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/concept/log-levels/src/main/kotlin/LogLevels.kt",
"chars": 307,
"preview": "fun message(logLine : String) : String {\n TODO(\"Please implement the message() function\")\n}\n\nfun logLevel(logLine : S"
},
{
"path": "exercises/concept/log-levels/src/test/kotlin/LogLevelsTest.kt",
"chars": 2455,
"preview": "import kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass LogLevelsTest {\n @Test\n fun `error message`() {\n "
},
{
"path": "exercises/concept/lucians-luscious-lasagna/.docs/hints.md",
"chars": 1663,
"preview": "# Hints\n\n## General\n\n- An [integer (`Int`) value][numbers] can be defined as one or more consecutive digits.\n- Use varia"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/.docs/instructions.md",
"chars": 2117,
"preview": "# Instructions\n\nThe owner of your local pizza place has asked you to help her to calculate cooking times for different p"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/.docs/introduction.md",
"chars": 2397,
"preview": "# Introduction\n\nKotlin is a **statically typed** programming language developed by JetBrains. This means that the type o"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/.meta/config.json",
"chars": 430,
"preview": "{\n \"authors\": [\n \"dector\"\n ],\n \"files\": {\n \"solution\": [\n \"src/main/kotlin/LuciansLusciousLasagna.kt\"\n "
},
{
"path": "exercises/concept/lucians-luscious-lasagna/.meta/design.md",
"chars": 1253,
"preview": "# Design\n\n## Goal\n\nThis exercise should teach bare minimum to help students understand Kotlin programs.\n\n## Learning obj"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/.meta/src/reference/kotlin/LuciansLusciousLasagna.kt",
"chars": 540,
"preview": "fun remainingMinutesInOven(actualMinutesInOven: Int = 0): Int {\n val cookingTime = 40\n\n return cookingTime - actua"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/build.gradle.kts",
"chars": 430,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/concept/lucians-luscious-lasagna/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/src/main/kotlin/LuciansLusciousLasagna.kt",
"chars": 192,
"preview": "// TODO: define `remainingMinutesInOven()`. Use named variable to store expected time in oven.\n\n// TODO: define `prepara"
},
{
"path": "exercises/concept/lucians-luscious-lasagna/src/test/kotlin/LuciansLusciousLasagnaTests.kt",
"chars": 186,
"preview": "import org.junit.Test\nimport org.junit.Ignore\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\nclass Lucian"
},
{
"path": "exercises/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/gradle.properties",
"chars": 50,
"preview": "kotlin.incremental=false\norg.gradle.parallel=true\n"
},
{
"path": "exercises/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/gradlew.bat",
"chars": 2868,
"preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
},
{
"path": "exercises/practice/accumulate/.docs/instructions.md",
"chars": 694,
"preview": "# Instructions\n\nImplement the `accumulate` operation, which, given a collection and an\noperation to perform on each elem"
},
{
"path": "exercises/practice/accumulate/.meta/config.json",
"chars": 765,
"preview": "{\n \"blurb\": \"Implement the `accumulate` operation, which, given a collection and an operation to perform on each elemen"
},
{
"path": "exercises/practice/accumulate/.meta/src/reference/kotlin/Accumulate.kt",
"chars": 258,
"preview": "object Accumulate {\n fun <T, R> accumulate(collection: List<T>, function: (T) -> R): List<R> {\n val retVal = m"
},
{
"path": "exercises/practice/accumulate/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/practice/accumulate/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/practice/accumulate/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/practice/accumulate/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/practice/accumulate/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/practice/accumulate/src/main/kotlin/Accumulate.kt",
"chars": 192,
"preview": "object Accumulate {\n fun accumulate(collection: List<Any>, converter: (Any) -> Any): List<Any> {\n TODO(\"Change"
},
{
"path": "exercises/practice/accumulate/src/test/kotlin/AccumulateTest.kt",
"chars": 1717,
"preview": "import org.junit.Test\nimport org.junit.Ignore\nimport kotlin.test.assertEquals\n\nclass AccumulateTest {\n\n\n @Test\n fu"
},
{
"path": "exercises/practice/acronym/.docs/instructions.md",
"chars": 571,
"preview": "# Instructions\n\nConvert a phrase to its acronym.\n\nTechies love their TLA (Three Letter Acronyms)!\n\nHelp generate some ja"
},
{
"path": "exercises/practice/acronym/.meta/config.json",
"chars": 590,
"preview": "{\n \"authors\": [\n \"sdavids13\"\n ],\n \"contributors\": [\n \"beatbrot\",\n \"dector\",\n \"eparovyshnaya\",\n \"jtigge"
},
{
"path": "exercises/practice/acronym/.meta/src/reference/kotlin/Acronym.kt",
"chars": 213,
"preview": "object Acronym {\n fun generate(phrase: String) = Regex(\"[A-Z]+[a-z]*|[a-z]+\")\n .findAll(phrase.replace(\"'\""
},
{
"path": "exercises/practice/acronym/.meta/tests.toml",
"chars": 1163,
"preview": "# This is an auto-generated file.\n#\n# Regenerating this file via `configlet sync` will:\n# - Recreate every `description`"
},
{
"path": "exercises/practice/acronym/.meta/version",
"chars": 6,
"preview": "1.7.0\n"
},
{
"path": "exercises/practice/acronym/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/practice/acronym/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/practice/acronym/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/practice/acronym/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/practice/acronym/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/practice/acronym/src/main/kotlin/Acronym.kt",
"chars": 129,
"preview": "object Acronym {\n fun generate(phrase: String) : String {\n TODO(\"Implement the function to complete the task\")"
},
{
"path": "exercises/practice/acronym/src/test/kotlin/AcronymTest.kt",
"chars": 1536,
"preview": "import org.junit.Test\nimport org.junit.Ignore\nimport kotlin.test.assertEquals\n\nclass AcronymTest {\n @Test\n fun `ca"
},
{
"path": "exercises/practice/affine-cipher/.docs/instructions.md",
"chars": 2982,
"preview": "# Instructions\n\nCreate an implementation of the affine cipher, an ancient encryption system created in the Middle East.\n"
},
{
"path": "exercises/practice/affine-cipher/.meta/config.json",
"chars": 523,
"preview": "{\n \"authors\": [\n \"lathspell\"\n ],\n \"contributors\": [\n \"eparovyshnaya\",\n \"uzilan\"\n ],\n \"files\": {\n \"solut"
},
{
"path": "exercises/practice/affine-cipher/.meta/src/reference/kotlin/AffineCipher.kt",
"chars": 1740,
"preview": "object AffineCipher {\n\n /** Number of characters in the alphabet (a-z). */\n private const val ALPHABET_SIZE = 26\n\n"
},
{
"path": "exercises/practice/affine-cipher/.meta/tests.toml",
"chars": 1875,
"preview": "# This is an auto-generated file.\n#\n# Regenerating this file via `configlet sync` will:\n# - Recreate every `description`"
},
{
"path": "exercises/practice/affine-cipher/.meta/version",
"chars": 6,
"preview": "2.0.0\n"
},
{
"path": "exercises/practice/affine-cipher/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/practice/affine-cipher/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/practice/affine-cipher/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/practice/affine-cipher/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/practice/affine-cipher/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/practice/affine-cipher/src/main/kotlin/AffineCipher.kt",
"chars": 254,
"preview": "object AffineCipher {\n\n fun encode(input: String, a: Int, b: Int) {\n TODO(\"Implement the function to complete "
},
{
"path": "exercises/practice/affine-cipher/src/test/kotlin/AffineCipherTest.kt",
"chars": 2549,
"preview": "import kotlin.test.Ignore\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\ncl"
},
{
"path": "exercises/practice/all-your-base/.docs/instructions.md",
"chars": 843,
"preview": "# Instructions\n\nConvert a sequence of digits in one base, representing a number, into a sequence of digits in another ba"
},
{
"path": "exercises/practice/all-your-base/.docs/introduction.md",
"chars": 519,
"preview": "# Introduction\n\nYou've just been hired as professor of mathematics.\nYour first week went well, but something is off in y"
},
{
"path": "exercises/practice/all-your-base/.meta/config.json",
"chars": 539,
"preview": "{\n \"authors\": [\n \"stkent\"\n ],\n \"contributors\": [\n \"dector\",\n \"eparovyshnaya\",\n \"lihofm\",\n \"mdowds\",\n "
},
{
"path": "exercises/practice/all-your-base/.meta/src/reference/kotlin/BaseConverter.kt",
"chars": 2151,
"preview": "import kotlin.math.floor\nimport kotlin.math.pow\n\nclass BaseConverter(originalBase: Int, originalDigits: IntArray) {\n\n "
},
{
"path": "exercises/practice/all-your-base/.meta/tests.toml",
"chars": 2097,
"preview": "# This is an auto-generated file.\n#\n# Regenerating this file via `configlet sync` will:\n# - Recreate every `description`"
},
{
"path": "exercises/practice/all-your-base/.meta/version",
"chars": 6,
"preview": "2.3.0\n"
},
{
"path": "exercises/practice/all-your-base/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/practice/all-your-base/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/practice/all-your-base/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/practice/all-your-base/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/practice/all-your-base/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/practice/all-your-base/src/main/kotlin/BaseConverter.kt",
"chars": 202,
"preview": "class BaseConverter {\n // TODO: implement proper constructor to complete the task\n\n fun convertToBase(newBase: Int"
},
{
"path": "exercises/practice/all-your-base/src/test/kotlin/BaseConverterTest.kt",
"chars": 7353,
"preview": "import org.junit.Assert.assertArrayEquals\nimport org.junit.Ignore\nimport org.junit.Rule\nimport org.junit.Test\nimport org"
},
{
"path": "exercises/practice/allergies/.docs/instructions.md",
"chars": 991,
"preview": "# Instructions\n\nGiven a person's allergy score, determine whether or not they're allergic to a given item, and their ful"
},
{
"path": "exercises/practice/allergies/.meta/config.json",
"chars": 720,
"preview": "{\n \"authors\": [\n \"sdavids13\"\n ],\n \"contributors\": [\n \"dector\",\n \"eparovyshnaya\",\n \"jtigger\",\n \"lihofm\""
},
{
"path": "exercises/practice/allergies/.meta/src/reference/kotlin/Allergen.kt",
"chars": 175,
"preview": "enum class Allergen(val score: Int) {\n EGGS(1),\n PEANUTS(2),\n SHELLFISH(4),\n STRAWBERRIES(8),\n TOMATOES(1"
},
{
"path": "exercises/practice/allergies/.meta/src/reference/kotlin/Allergies.kt",
"chars": 208,
"preview": "class Allergies(val score: Int) {\n\n fun getList(): List<Allergen> = Allergen.values().filter { isAllergicTo(it) }\n\n "
},
{
"path": "exercises/practice/allergies/.meta/tests.toml",
"chars": 3787,
"preview": "[canonical-tests]\n\n# not allergic to anything\n\"17fc7296-2440-4ac4-ad7b-d07c321bc5a0\" = true\n\n# allergic only to eggs\n\"07"
},
{
"path": "exercises/practice/allergies/.meta/version",
"chars": 6,
"preview": "2.0.0\n"
},
{
"path": "exercises/practice/allergies/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/practice/allergies/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/practice/allergies/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/practice/allergies/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/practice/allergies/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/practice/allergies/src/main/kotlin/Allergen.kt",
"chars": 175,
"preview": "enum class Allergen(val score: Int) {\n EGGS(1),\n PEANUTS(2),\n SHELLFISH(4),\n STRAWBERRIES(8),\n TOMATOES(1"
},
{
"path": "exercises/practice/allergies/src/main/kotlin/Allergies.kt",
"chars": 296,
"preview": "class Allergies {\n // TODO: implement proper constructor to complete the task\n\n fun getList(): List<Allergen> {\n "
},
{
"path": "exercises/practice/allergies/src/test/kotlin/AllergiesTest.kt",
"chars": 6382,
"preview": "import org.junit.Test\nimport org.junit.Ignore\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFalse\nimport kotl"
},
{
"path": "exercises/practice/anagram/.docs/instructions.append.md",
"chars": 66,
"preview": "# Instructions Append\n\nThe anagrams can be returned in any order.\n"
},
{
"path": "exercises/practice/anagram/.docs/instructions.md",
"chars": 888,
"preview": "# Instructions\n\nGiven a target word and one or more candidate words, your task is to find the candidates that are anagra"
},
{
"path": "exercises/practice/anagram/.docs/introduction.md",
"chars": 782,
"preview": "# Introduction\n\nAt a garage sale, you find a lovely vintage typewriter at a bargain price!\nExcitedly, you rush home, ins"
},
{
"path": "exercises/practice/anagram/.meta/config.json",
"chars": 646,
"preview": "{\n \"authors\": [\n \"sdavids13\"\n ],\n \"contributors\": [\n \"dector\",\n \"eparovyshnaya\",\n \"jtigger\",\n \"lihofm\""
},
{
"path": "exercises/practice/anagram/.meta/src/reference/kotlin/Anagram.kt",
"chars": 411,
"preview": "class Anagram(private val word: String) {\n\n fun match(anagrams: Collection<String>) =\n anagrams.filter { c"
},
{
"path": "exercises/practice/anagram/.meta/tests.toml",
"chars": 1250,
"preview": "[canonical-tests]\n\n# no matches\n\"dd40c4d2-3c8b-44e5-992a-f42b393ec373\" = true\n\n# detects two anagrams\n\"b3cca662-f50a-489"
},
{
"path": "exercises/practice/anagram/.meta/version",
"chars": 6,
"preview": "1.5.0\n"
},
{
"path": "exercises/practice/anagram/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/practice/anagram/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/practice/anagram/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/practice/anagram/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/practice/anagram/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/practice/anagram/src/main/kotlin/Anagram.kt",
"chars": 207,
"preview": "class Anagram {\n // TODO: implement proper constructor to complete the task\n\n fun match(anagrams: Collection<Strin"
},
{
"path": "exercises/practice/anagram/src/test/kotlin/AnagramTest.kt",
"chars": 3158,
"preview": "import org.junit.Test\nimport org.junit.Ignore\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\n\nclass Anagr"
},
{
"path": "exercises/practice/armstrong-numbers/.docs/instructions.md",
"chars": 599,
"preview": "# Instructions\n\nAn [Armstrong number][armstrong-number] is a number that is the sum of its own digits each raised to the"
},
{
"path": "exercises/practice/armstrong-numbers/.meta/config.json",
"chars": 483,
"preview": "{\n \"authors\": [\n \"lathspell\"\n ],\n \"contributors\": [\n \"eparovyshnaya\",\n \"uzilan\"\n ],\n \"files\": {\n \"solut"
},
{
"path": "exercises/practice/armstrong-numbers/.meta/src/reference/kotlin/ArmstrongNumber.kt",
"chars": 455,
"preview": "import java.math.BigInteger\n\nobject ArmstrongNumber {\n\n fun check(input: Long): Boolean {\n val str = input.toS"
},
{
"path": "exercises/practice/armstrong-numbers/.meta/tests.toml",
"chars": 861,
"preview": "[canonical-tests]\n\n# Zero is an Armstrong number\n\"c1ed103c-258d-45b2-be73-d8c6d9580c7b\" = true\n\n# Single digit numbers a"
},
{
"path": "exercises/practice/armstrong-numbers/.meta/version",
"chars": 6,
"preview": "1.1.0\n"
},
{
"path": "exercises/practice/armstrong-numbers/build.gradle.kts",
"chars": 434,
"preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\n\nplugins {\n kotlin(\"jvm\")\n}\n\nrepositories {\n maven"
},
{
"path": "exercises/practice/armstrong-numbers/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "exercises/practice/armstrong-numbers/gradlew",
"chars": 8669,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "exercises/practice/armstrong-numbers/gradlew.bat",
"chars": 2776,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "exercises/practice/armstrong-numbers/settings.gradle.kts",
"chars": 318,
"preview": "pluginManagement {\n repositories {\n mavenCentral()\n gradlePluginPortal()\n }\n resolutionStrategy {"
},
{
"path": "exercises/practice/armstrong-numbers/src/main/kotlin/ArmstrongNumber.kt",
"chars": 132,
"preview": "object ArmstrongNumber {\n\n fun check(input: Int): Boolean {\n TODO(\"Implement the function to complete the task"
},
{
"path": "exercises/practice/armstrong-numbers/src/test/kotlin/ArmstrongNumberTest.kt",
"chars": 1225,
"preview": "import kotlin.test.Test\nimport kotlin.test.assertTrue\nimport kotlin.test.assertFalse\nimport kotlin.test.Ignore\n\nclass Ar"
},
{
"path": "exercises/practice/atbash-cipher/.docs/instructions.md",
"chars": 1183,
"preview": "# Instructions\n\nCreate an implementation of the Atbash cipher, an ancient encryption system created in the Middle East.\n"
},
{
"path": "exercises/practice/atbash-cipher/.meta/config.json",
"chars": 642,
"preview": "{\n \"authors\": [\n \"sdavids13\"\n ],\n \"contributors\": [\n \"dector\",\n \"eparovyshnaya\",\n \"jtigger\",\n \"kytriny"
},
{
"path": "exercises/practice/atbash-cipher/.meta/src/reference/kotlin/Atbash.kt",
"chars": 696,
"preview": "object Atbash {\n private const val GROUP_SIZE = 5\n\n fun encode(s: String): String = cipherSubstitution(s).mapIndex"
},
{
"path": "exercises/practice/atbash-cipher/.meta/tests.toml",
"chars": 1673,
"preview": "# This is an auto-generated file.\n#\n# Regenerating this file via `configlet sync` will:\n# - Recreate every `description`"
},
{
"path": "exercises/practice/atbash-cipher/.meta/version",
"chars": 6,
"preview": "1.2.0\n"
}
]
// ... and 1288 more files (download for full content)
About this extraction
This page contains the full source code of the exercism/kotlin GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1488 files (2.1 MB), approximately 654.0k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.