├── .test ├── settings.gradle.kts ├── .gitignore ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── test │ │ └── kotlin │ │ └── com │ │ └── igorwojda │ │ └── challenge │ │ └── utils │ │ ├── ChallengeFile.kt │ │ ├── TestUtils.kt │ │ └── KotlinParserUtils.kt ├── buildSrc │ ├── src │ │ └── main │ │ │ └── kotlin │ │ │ └── com │ │ │ └── igorwojda │ │ │ └── challenge │ │ │ └── utils │ │ │ ├── ChallengeFile.kt │ │ │ └── KotlinParserUtils.kt │ └── build.gradle.kts ├── build.gradle.kts └── README.md ├── settings.gradle.kts ├── .editorconfig ├── misc ├── image │ ├── avatar.png │ ├── run-test.png │ └── challenge-structure.png └── template │ └── challenge │ ├── Solution.kt │ ├── Challenge.kt │ └── README.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src └── test │ └── kotlin │ └── com │ └── igorwojda │ ├── common │ └── anycallback │ │ ├── Challenge.kt │ │ ├── README.md │ │ ├── Tests.kt │ │ └── Solution.kt │ ├── range │ └── containsrange │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── list │ ├── reverse │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── countuniquevalues │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── capitalizefirst │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── search │ │ ├── linearsearch │ │ │ ├── Solution.kt │ │ │ ├── README.md │ │ │ └── Challenge.kt │ │ └── binarysearch │ │ │ ├── Solution.kt │ │ │ ├── README.md │ │ │ └── Challenge.kt │ ├── product │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── coins │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── flatten │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── sort │ │ ├── insertionsort │ │ │ ├── README.md │ │ │ └── Solution.kt │ │ ├── quicksort │ │ │ └── README.md │ │ ├── mergesort │ │ │ ├── README.md │ │ │ └── Solution.kt │ │ ├── selectionsort │ │ │ ├── Solution.kt │ │ │ └── README.md │ │ └── bubblesort │ │ │ ├── Solution.kt │ │ │ ├── README.md │ │ │ └── Challenge.kt │ ├── sumzero │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── chunk │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── pairaverage │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── subtract │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── medianoftwosorted │ │ ├── README.md │ │ └── Challenge.kt │ ├── maxsublistsum │ │ ├── README.md │ │ └── Challenge.kt │ ├── minsublistlength │ │ └── README.md │ ├── largestelements │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── smallestelements │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── formattrainroute │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ └── squareequal │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── integer │ ├── reverse │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── countdown │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── power │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── addupto │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── printnumber │ │ ├── basic │ │ │ ├── README.md │ │ │ ├── Solution.kt │ │ │ └── Challenge.kt │ │ └── steps │ │ │ ├── README.md │ │ │ ├── Challenge.kt │ │ │ └── Solution.kt │ ├── getodd │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── countupanddown │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── digitfrequency │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── factorial │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── fibonacci │ │ ├── basic │ │ │ ├── README.md │ │ │ ├── Challenge.kt │ │ │ └── Solution.kt │ │ └── recursivecached │ │ │ ├── Solution.kt │ │ │ ├── README.md │ │ │ └── Challenge.kt │ ├── stepsgenerator │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── fizzbuzz │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── pyramidgenerator │ │ ├── README.md │ │ └── Challenge.kt │ └── generateallpairs │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── string │ ├── capitalizesentence │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── longestword │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── vowels │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── reverse │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── ispalindrome │ │ ├── basic │ │ │ ├── README.md │ │ │ ├── Challenge.kt │ │ │ └── Solution.kt │ │ ├── permutation │ │ │ ├── README.md │ │ │ ├── Solution.kt │ │ │ └── Challenge.kt │ │ └── tolerant │ │ │ └── README.md │ ├── maxoccurringchar │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── hasrepeatedcharacter │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── getduplicatedarguments │ │ ├── README.md │ │ ├── Challenge.kt │ │ └── Solution.kt │ ├── decapitalizeconst │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── issubstring │ │ ├── README.md │ │ └── Challenge.kt │ ├── isanagram │ │ ├── README.md │ │ └── Solution.kt │ ├── caesarcipher │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ └── surroundedletter │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ ├── tree │ ├── multiway │ │ ├── levelwidth │ │ │ └── README.md │ │ └── traversal │ │ │ └── breathfirst │ │ │ └── README.md │ ├── binarysearchtree │ │ └── README.md │ ├── heap │ │ └── maxbinaryheap │ │ │ └── README.md │ └── binarytree │ │ ├── insert │ │ ├── Solution.kt │ │ └── README.md │ │ └── validate │ │ ├── README.md │ │ └── Solution.kt │ ├── cache │ ├── lru │ │ ├── Challenge.kt │ │ ├── README.md │ │ └── Tests.kt │ └── advancedlru │ │ ├── Challenge.kt │ │ └── README.md │ ├── linkedlist │ └── singly │ │ ├── fromlast │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ │ ├── addnumbers │ │ ├── README.md │ │ ├── Solution.kt │ │ └── Challenge.kt │ │ ├── midpoint │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ │ └── circularcheck │ │ ├── Solution.kt │ │ ├── README.md │ │ └── Challenge.kt │ ├── matrix │ ├── findallrectangles │ │ └── README.md │ ├── spiralmatrixgenerator │ │ ├── README.md │ │ └── Challenge.kt │ └── findrectangle │ │ └── README.md │ ├── queue │ ├── combine │ │ ├── Solution.kt │ │ └── README.md │ └── basic │ │ └── README.md │ └── stack │ └── basic │ └── README.md ├── renovate.json ├── .gitignore ├── LICENSE.md └── .github └── workflows └── run-checks.yml /.test/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "test" 2 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "kotlin-coding-challenges" 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{kt,kts}] 2 | ktlint_custom-rule-set_filename = disabled 3 | -------------------------------------------------------------------------------- /misc/image/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igorwojda/kotlin-coding-challenges/HEAD/misc/image/avatar.png -------------------------------------------------------------------------------- /misc/image/run-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igorwojda/kotlin-coding-challenges/HEAD/misc/image/run-test.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igorwojda/kotlin-coding-challenges/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /misc/image/challenge-structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igorwojda/kotlin-coding-challenges/HEAD/misc/image/challenge-structure.png -------------------------------------------------------------------------------- /.test/.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle 2 | .gradle 3 | build/ 4 | 5 | # IntelliJ 6 | .idea/ 7 | *.iml 8 | 9 | # Misc 10 | *.log 11 | .DS_Store -------------------------------------------------------------------------------- /.test/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igorwojda/kotlin-coding-challenges/HEAD/.test/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/common/anycallback/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.common.anycallback 2 | 3 | fun anyCallback(list: List, predicate: (T) -> Boolean): Boolean { 4 | TODO("Add your solution here") 5 | } 6 | 7 | 8 | -------------------------------------------------------------------------------- /misc/template/challenge/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.challenge 2 | 3 | // Time complexity: 4 | // ??? 5 | private object Solution1 { 6 | 7 | } 8 | 9 | // Time complexity: 10 | // ??? 11 | private object Solution2 { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /.test/src/test/kotlin/com/igorwojda/challenge/utils/ChallengeFile.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.challenge.utils 2 | 3 | enum class ChallengeFile(val fileName: String) { 4 | SOLUTIONS_KT("Solution.kt"), 5 | DESC_MD("README.md"), 6 | CHALLENGE_KT("Challenge.kt"), 7 | } 8 | -------------------------------------------------------------------------------- /.test/buildSrc/src/main/kotlin/com/igorwojda/challenge/utils/ChallengeFile.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.challenge.utils 2 | 3 | enum class ChallengeFile(val fileName: String) { 4 | SOLUTIONS_KT("Solution.kt"), 5 | DESC_MD("README.md"), 6 | CHALLENGE_KT("Challenge.kt"), 7 | } 8 | -------------------------------------------------------------------------------- /.test/buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | // The kotlin-dsl plugin requires a repository to be declared 6 | repositories { 7 | mavenCentral() 8 | } 9 | 10 | 11 | dependencies { 12 | implementation("org.jetbrains.kotlin:kotlin-compiler:1.9.25") 13 | } 14 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /.test/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/range/containsrange/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.range.containsrange 2 | 3 | private object Solution1 { 4 | private fun containsRange(range1: IntRange, range2: IntRange) = 5 | range2.first >= range1.first && range2.last <= range1.last 6 | } 7 | 8 | private object KtLintWillNotComplain 9 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/reverse/README.md: -------------------------------------------------------------------------------- 1 | # Chunk 2 | 3 | ## Instructions 4 | 5 | Reverse the given list. Don't use `list.reversed()` method. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | reverse(["a", "b"]) // ["b", "a"] 13 | 14 | reverse(["a", "b", "c"]) // ["c", "b", "a"] 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /misc/template/challenge/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.challenge 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun challenge() { 7 | 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `simple test`() { 13 | val actual = challenge() 14 | actual shouldBeEqualTo "expected" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/reverse/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.reverse 2 | 3 | import kotlin.math.sign 4 | 5 | private object Solution1 { 6 | private fun reverseInt(i: Int): Int { 7 | val reverse = i.toString().removePrefix("-").reversed() 8 | return reverse.toInt() * i.sign 9 | } 10 | } 11 | 12 | private object KtLintWillNotComplain 13 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/countdown/README.md: -------------------------------------------------------------------------------- 1 | # Count down 2 | 3 | ## Instructions 4 | 5 | Given positive integer `n` implement a function which returns a list containing all steps from `n` to `0`. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | countDown(1) // [1, 0] 13 | 14 | countDown(4) // [4, 3, 2, 1, 0] 15 | ``` 16 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/power/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.power 2 | 3 | // Recursive solution 4 | private object Solution1 { 5 | private fun power(base: Int, exponent: Int): Int { 6 | if (exponent == 1) { 7 | return base 8 | } 9 | 10 | return base * power(base, exponent - 1) 11 | } 12 | } 13 | 14 | private object KtLintWillNotComplain 15 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/addupto/README.md: -------------------------------------------------------------------------------- 1 | # Add up to 2 | 3 | ## Instructions 4 | 5 | Given positive integer `n` implement a function which calculates sum of all numbers from `1` up to (and including) 6 | number `n`. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | addUpTo(1) // 1 14 | 15 | addUpTo(2) // 3 16 | 17 | addUpTo(3) // 6 18 | ``` 19 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/countuniquevalues/README.md: -------------------------------------------------------------------------------- 1 | # Count unique values 2 | 3 | ## Instructions 4 | 5 | Given a sorted list of integers implement a function which counts the unique values. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | countUniqueValues([]) // 0 13 | 14 | countUniqueValues([1, 1, 6]) // 2 15 | 16 | countUniqueValues([-2, -1, -1, 0, 1]) // 4 17 | ``` 18 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/capitalizesentence/README.md: -------------------------------------------------------------------------------- 1 | # Capitalize sentence 2 | 3 | ## Instructions 4 | 5 | Given a string implement a function which capitalizes first letter of every word in that string. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | capitalizeSentence("flower") // Flower 13 | 14 | capitalizeSentence("this is a house") // This Is A House 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/reverse/README.md: -------------------------------------------------------------------------------- 1 | # Reverse Int 2 | 3 | ## Instructions 4 | 5 | Given an integer `n`, return an integer that is the reverse ordering of digits. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | reverseInt(15) // 51 13 | 14 | reverseInt(981) // 189 15 | 16 | reverseInt(500) // 5 17 | 18 | reverseInt(-15) // -51 19 | 20 | reverseInt(-90) // -9 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/capitalizefirst/README.md: -------------------------------------------------------------------------------- 1 | # Capitalize First 2 | 3 | ## Instructions 4 | 5 | Given list of strings implement a **recursive** function which will capitalize first letter of each string in the list. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | capitalizeFirst(listOf("igor")) // listOf("Igor") 13 | 14 | capitalizeFirst(listOf("igor", "wojda")) // listOf("Igor", "Wojda") 15 | ``` 16 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/longestword/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.longestword 2 | 3 | private object Solution1 { 4 | private fun longestWord(str: String): String { 5 | return str.map { if (it.isLetter()) it else ' ' } 6 | .joinToString(separator = "") 7 | .split(" ") 8 | .filterNot { it.isBlank() } 9 | .maxBy { it.length } 10 | } 11 | } 12 | 13 | private object KtLintWillNotComplain 14 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/range/containsrange/README.md: -------------------------------------------------------------------------------- 1 | # Contains range 2 | 3 | ## Instructions 4 | 5 | Given two [ranges](https://kotlinlang.org/docs/ranges.html) implement a function which checks if range1 contains range2. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | containsRange(5..7, 5..7) // true 13 | 14 | containsRange(1..12, 5..7) // true 15 | 16 | containsRange(5..8, 5..9) // false 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/vowels/README.md: -------------------------------------------------------------------------------- 1 | # Find the vowels 2 | 3 | ## Instructions 4 | 5 | Given string implement a function, which returns the number of vowels used in a string. Vowels are the characters `a` 6 | , `e` `i`, `o`, `u` and 7 | `y`. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | vowels('Hi There!') // 3 15 | 16 | vowels('Why do you ask?') // 6 17 | 18 | vowels('Why?') // 1 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/search/linearsearch/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.search.linearsearch 2 | 3 | // Time complexity: O(n) 4 | private object Solution1 { 5 | private fun getIndex(list: List, str: String): Int { 6 | list.forEachIndexed { index, element -> 7 | if (element == str) { 8 | return index 9 | } 10 | } 11 | return -1 12 | } 13 | } 14 | 15 | private object KtLintWillNotComplain 16 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/reverse/README.md: -------------------------------------------------------------------------------- 1 | # Reverse string 2 | 3 | ## Instructions 4 | 5 | Given a string implement a function which returns a reversed copy of that string. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Limitations: 10 | 11 | Don't use Kotlin `String.reverse` function 12 | 13 | ## Examples 14 | 15 | ```kotlin 16 | reverse('apple') == 'leppa' 17 | 18 | reverse('hello') == 'olleh' 19 | 20 | reverse('Greetings!') == '!sgniteerG' 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/printnumber/basic/README.md: -------------------------------------------------------------------------------- 1 | # Print numbers 2 | 3 | ## Instructions 4 | 5 | Given positive integer `n` implement a function which returns a list representing all numbers from `n` to `1`. If `n` 6 | value is zero then empty list should be returned. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | printNumber(0) // [] 14 | 15 | printNumber(2) // [2, 1] 16 | 17 | printNumber(5) // [5, 4, 3, 2, 1] 18 | ``` 19 | 20 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ], 6 | "lockFileMaintenance": { 7 | "enabled": true, 8 | "automerge": true, 9 | "automergeType": "pr", 10 | "platformAutomerge": true 11 | }, 12 | "packageRules": [ 13 | { 14 | "matchUpdateTypes": [ 15 | "minor", 16 | "patch" 17 | ], 18 | "matchCurrentVersion": "!/^0/", 19 | "automerge": true 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/getodd/README.md: -------------------------------------------------------------------------------- 1 | # Get odd numbers 2 | 3 | ## Nice to solve before 4 | 5 | - [Count down](../countdown/README.md) 6 | 7 | ## Instructions 8 | 9 | Given a list of integers return a list that contains only odd integers (only integers which are not a multiple of `2`). 10 | 11 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 12 | 13 | ## Examples 14 | 15 | ```kotlin 16 | getOdd(listOf(1, 2, 3)) // 1, 3 17 | 18 | getOdd(listOf(4, 6, 8, 7, 9)) // 7, 9 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/tree/multiway/levelwidth/README.md: -------------------------------------------------------------------------------- 1 | # Tree level width 2 | 3 | ## Nice to solve before 4 | 5 | [Tree traversal](../traversal/README.md) 6 | 7 | ## Instructions 8 | 9 | Given the root node of a tree, return a list where each element is the width of the tree at each level. 10 | 11 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 12 | 13 | ## Examples 14 | 15 | ```kotlin 16 | A 17 | / | \ 18 | B C D 19 | | | 20 | E F 21 | 22 | Answer: [1, 3, 2] 23 | ``` 24 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/countupanddown/README.md: -------------------------------------------------------------------------------- 1 | # Count up and down 2 | 3 | ## Nice to solve before 4 | 5 | [Count down](../countdown/README.md) 6 | 7 | ## Instructions 8 | 9 | Given positive integer `n` implement a function which returns a list containing all steps up from `0` to `n` and down to 10 | `0`. 11 | 12 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 13 | 14 | ## Examples 15 | 16 | ```kotlin 17 | countUpAndDown(1) // [0, 1, 0] 18 | 19 | countUpAndDown(2) // [0, 1, 2, 1, 0] 20 | ``` 21 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/digitfrequency/README.md: -------------------------------------------------------------------------------- 1 | # Digit frequency 2 | 3 | ## Instructions 4 | 5 | Given two integers implement a function which determines if they have the same frequency of digits. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | equalDigitFrequency("123", "321") // true 13 | 14 | equalDigitFrequency("4557", "745") // false 15 | ``` 16 | 17 | ## Hints 18 | 19 |
20 | Hint 1 21 | Use frequency map 22 |
23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/product/README.md: -------------------------------------------------------------------------------- 1 | # Product 2 | 3 | ## Instructions 4 | 5 | Given a list of integers implement a function which returns the product of all numbers in the list. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | product(listOf(1, 2)) // 2 13 | 14 | product(listOf(1, 2, 4)) // 8 15 | 16 | product(listOf(2, 4, 10)) // 80 17 | ``` 18 | 19 | ## Hints 20 | 21 |
22 | Hint 1 23 | You can use recursion 24 |
25 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/ispalindrome/basic/README.md: -------------------------------------------------------------------------------- 1 | # Is palindrome 2 | 3 | ## Instructions 4 | 5 | Given a string, return true if the string is a palindrome or false if it is not. Palindromes are strings that form the 6 | same word if it is reversed. Include spaces and punctuation in determining if the string is a palindrome. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | palindrome("abba") // true 14 | 15 | palindrome("abcdefg") // false 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/power/README.md: -------------------------------------------------------------------------------- 1 | # Power 2 | 3 | ## Instructions 4 | 5 | Given positive integer `base` and positive integer `exponent` implement a function which calculates power of base of 6 | exponent. This function should mimic functionality of [Math.pow](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/pow.html). 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | power(2, 1) // 1 14 | 15 | power(2, 2) // 4 16 | 17 | power(3, 3) // 27 18 | ``` 19 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/coins/README.md: -------------------------------------------------------------------------------- 1 | # Coins 2 | 3 | ## Instructions 4 | 5 | Given an amount of money and an array of coins write a method that computes the number of ways to make the amount of 6 | money with coins of the available coins. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | Example 1 13 | 14 | ```kotlin 15 | getCoins(4, listOf(1, 2, 3)) // 4 16 | 17 | Ways to make 4 with those denominations : 18 | 1¢, 1¢, 1¢, 1¢ 19 | 1¢, 1¢, 2¢ 20 | 1¢, 3¢ 21 | 2¢, 2¢ 22 | 23 | ``` 24 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/flatten/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.flatten 2 | 3 | private object Solution1 { 4 | fun flatten(list: List<*>): List<*> { 5 | val result = mutableListOf() 6 | 7 | list.forEach { 8 | if (it is List<*>) { 9 | result.addAll(flatten(it)) 10 | } else { 11 | result.add(it) 12 | } 13 | } 14 | 15 | return result.filterNotNull() 16 | } 17 | } 18 | 19 | private object KtLintWillNotComplain 20 | -------------------------------------------------------------------------------- /misc/template/challenge/README.md: -------------------------------------------------------------------------------- 1 | # Challenge name 2 | 3 | ## Nice to solve before 4 | 5 | ## Instructions 6 | 7 | ??? 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Limitations 12 | 13 | ## Steps 14 | 15 | ??? 16 | 17 | ### Step 1 18 | 19 | ??? 20 | 21 | ### Step 2 22 | 23 | ??? 24 | 25 | ## Examples 26 | 27 | Example 1 28 | 29 | ```kotlin 30 | 31 | ``` 32 | 33 | Example 2 34 | 35 | ```kotlin 36 | 37 | ``` 38 | 39 | ## Hints 40 | 41 |
42 | Hint 1 43 | ??? 44 |
45 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/longestword/README.md: -------------------------------------------------------------------------------- 1 | # Longest word 2 | 3 | ## Instructions 4 | 5 | Given a string implement a function which returns longest word in that string. If there are two or more words that have 6 | the same length, return the first longest word from the string. Ignore punctuation. Input string can't be empty or blank 7 | sering. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | longestWord("big flower") // flower 15 | 16 | longestWord("this is a house") // house 17 | ``` 18 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/maxoccurringchar/README.md: -------------------------------------------------------------------------------- 1 | # Max occurring char 2 | 3 | ## Instructions 4 | 5 | Given a string implement a function which returns the character that is most commonly used in that string. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | maxOccurringChar("abcccccccd") // "c" 13 | 14 | maxOccurringChar("apple 1231111") // "1" 15 | ``` 16 | 17 | ## Hints 18 | 19 |
20 | Hint 1 21 | Use frequency counter or multiple pointers pattern. 22 |
23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/printnumber/steps/README.md: -------------------------------------------------------------------------------- 1 | # Print numbers with steps 2 | 3 | ## Instructions 4 | 5 | Given positive integer `n` and integer `step` implement a function which returns a list representing all numbers from 6 | `n` to `1` taking `step` into consideration. If `n` value is zero then empty list should be returned. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | printNumber(0, 1) // [] 14 | 15 | printNumber(6, 1) // [6, 5, 4, 3, 2, 1] 16 | 17 | printNumber(6, 2) // [6, 4, 2] 18 | ``` 19 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/reverse/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.reverse 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun reverse(str: String): String { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `Reverse of 'abcd' is 'dcba'`() { 13 | reverse("abcd") shouldBeEqualTo "dcba" 14 | } 15 | 16 | @Test 17 | fun `Reverse of 'aabbccdd' is 'ddccbbaa'`() { 18 | reverse("aabbccdd") shouldBeEqualTo "ddccbbaa" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/cache/lru/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.cache.lru 2 | 3 | interface LRUCache { 4 | val size: Int 5 | 6 | fun get(key: K): V? 7 | fun put(key: K, value: V) 8 | } 9 | 10 | class LRUCacheImpl(private val capacity: Int) : LRUCache { 11 | override val size: Int get() = TODO("Add your solution here") 12 | 13 | override fun get(key: K): V? { 14 | TODO("Add your solution here") 15 | } 16 | 17 | override fun put(key: K, value: V) { 18 | TODO("Add your solution here") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/factorial/README.md: -------------------------------------------------------------------------------- 1 | # Factorial 2 | 3 | ## Instructions 4 | 5 | Given positive integer `n` implement a function, which returns a [factorial](https://en.wikipedia.org/wiki/Factorial) of 6 | that integer. Factorial (of positive integer) is number that is created by multiplying all numbers from 1 to `n` eg. 7 | factorial of `3` (`3!`) is equal to `6` (`3 * 2 * 1`) 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | factorial(1) // 1 15 | 16 | factorial(2) // 2 17 | 18 | factorial(3) // 6 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/insertionsort/README.md: -------------------------------------------------------------------------------- 1 | # Insertion sort 2 | 3 | ## Instructions 4 | 5 | Sort list of numbers from lowest number to greatest number using 6 | [insertion sort](https://www.geeksforgeeks.org/insertion-sort/). 7 | 8 | ## Algorithm 9 | 10 | - Start from the 2nd element of the list 11 | - Compare 2nd element with one before and insert it if necessary 12 | - Continue to next element and if it is in the incorrect order, iterate through "sorted portion" to place element at 13 | correct position. 14 | 15 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 16 | 17 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/tree/binarysearchtree/README.md: -------------------------------------------------------------------------------- 1 | # Binary search tree 2 | 3 | ## Instructions 4 | 5 | Implement [binary search tree (BST)](https://en.wikipedia.org/wiki/Binary_search_tree). 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | //----------Tree------------ 13 | // 14 | // 6 15 | // / \ 16 | // 3 8 17 | // / 18 | // 1 19 | // 20 | //-------------------------- 21 | 22 | val bst = BinarySearchTree() 23 | bst.add(6) 24 | bst.add(3) 25 | bst.add(1) 26 | bst.add(8) 27 | ``` 28 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fibonacci/basic/README.md: -------------------------------------------------------------------------------- 1 | # Fibonacci 2 | 3 | ## Instructions 4 | 5 | Print out the n-th entry in the fibonacciSequence series. The 6 | [fibonacci](https://en.wikipedia.org/wiki/Fibonacci_number) series is an ordering of numbers where each number is the 7 | sum of the preceding two. For example, the sequence `[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]` forms the first ten entries of 8 | the fibonacci sequence. 9 | 10 | ## Example 11 | 12 | ```kotlin 13 | fibonacci(1) // 1 14 | 15 | fibonacci(2) // 1 16 | 17 | fibonacci(3) // 2 18 | 19 | fibonacci(4) // 3 20 | ``` 21 | 22 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/reverse/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.reverse 2 | 3 | // Time complexity: O(n) 4 | private object Solution1 { 5 | private fun reverse(list: List): List { 6 | val newList = list.toMutableList() 7 | 8 | repeat(newList.size / 2) { 9 | val temp = newList[it] 10 | val other = newList[newList.size - it - 1] 11 | newList[it] = other 12 | newList[newList.size - it - 1] = temp 13 | } 14 | 15 | return newList 16 | } 17 | } 18 | 19 | private object KtLintWillNotComplain 20 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sumzero/README.md: -------------------------------------------------------------------------------- 1 | # Sum zero 2 | 3 | ## Instructions 4 | 5 | Given sorted list of integers implement a function which finds the first pair where the sum equals to `0`. Return an 6 | pair that includes both values that sum to zero or null if a pair does not exist. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | sumZero(listOf(1, 2)) // null 14 | 15 | sumZero(listOf(-3, -2, 0, 1, 2)) // Pair(-2, 2) 16 | ``` 17 | 18 | ## Hints 19 | 20 |
21 | Hint 1 22 | Use double pointer 23 |
24 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/addupto/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.addupto 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun addUpTo(n: Int): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `add up to 1`() { 13 | addUpTo(1) shouldBeEqualTo 1 14 | } 15 | 16 | @Test 17 | fun `add up to 3`() { 18 | addUpTo(3) shouldBeEqualTo 6 19 | } 20 | 21 | @Test 22 | fun `add up to 10`() { 23 | addUpTo(10) shouldBeEqualTo 55 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/hasrepeatedcharacter/README.md: -------------------------------------------------------------------------------- 1 | # Has repeated char 2 | 3 | ## Instructions 4 | 5 | Given a string implement a function which returns `true` if string contains at least one repeated character, otherwise 6 | it returns `false`. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | hasRepeatedCharacter("abc") // false" 14 | 15 | hasRepeatedCharacter("aabc") // true 16 | 17 | hasRepeatedCharacter("aabcc") // true 18 | ``` 19 | 20 | ## Hints 21 | 22 |
23 | Hint 1 24 | Use frequency counter. 25 |
26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/chunk/README.md: -------------------------------------------------------------------------------- 1 | # Chunk 2 | 3 | ## Instructions 4 | 5 | Given a list and chunk size, divide the list into multiple sub lists where each sub-list is of length of chunk size. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Examples 10 | 11 | ```kotlin 12 | chunk([1, 2, 3, 4], 2) // [[ 1, 2], [3, 4]] 13 | 14 | chunk([1, 2, 3, 4, 5], 2) // [[ 1, 2], [3, 4], [5]] 15 | 16 | chunk([1, 2, 3, 4, 5, 6, 7, 8], 3) // [[ 1, 2, 3], [4, 5, 6], [7, 8]] 17 | 18 | chunk([1, 2, 3, 4, 5], 4) // [[ 1, 2, 3, 4], [5]] 19 | 20 | chunk([1, 2, 3, 4, 5], 10) // [[ 1, 2, 3, 4, 5]] 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/stepsgenerator/README.md: -------------------------------------------------------------------------------- 1 | # Steps generator 2 | 3 | ## Instructions 4 | 5 | Given a positive integer `n` implement a function which returns a list representing the generated steps with `n` levels 6 | using the `#` character. Make sure the step has appropriate number of spaces on the right hand side! 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | steps(2) 14 | '# ' 15 | '##' 16 | 17 | steps(3) 18 | '# ' 19 | '## ' 20 | '###' 21 | 22 | steps(4) 23 | '# ' 24 | '## ' 25 | '### ' 26 | '####' 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/search/linearsearch/README.md: -------------------------------------------------------------------------------- 1 | # Linear search 2 | 3 | ## Instructions 4 | 5 | Given list of strings and a string return index of th value in the list or `-1` if value was not found. 6 | 7 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 8 | 9 | ## Limitations 10 | 11 | Don't use any Kotlin build-in methods that are directly returning index of element like `indexOf` / `lastIndexOf` / 12 | `indexOfFirst` / `indexOfLast`, etc. 13 | 14 | ## Examples 15 | 16 | ```kotlin 17 | getIndex(listOf("A", "B", "C"), "A") // 0 18 | 19 | getIndex(listOf("A", "B", "C"), "B") // 1 20 | 21 | getIndex(listOf("A", "B", "C"), "D") // -1 22 | ``` 23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/countdown/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.countdown 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun countDown(n: Int): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `count down 0`() { 13 | countDown(0) shouldBeEqualTo listOf(0) 14 | } 15 | 16 | @Test 17 | fun `count down 1`() { 18 | countDown(1) shouldBeEqualTo listOf(1, 0) 19 | } 20 | 21 | @Test 22 | fun `count down 5`() { 23 | countDown(5) shouldBeEqualTo listOf(5, 4, 3, 2, 1, 0) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/capitalizesentence/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.capitalizesentence 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun capitalizeSentence(str: String): String { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `"flower" is capitalized to "Flower"`() { 13 | capitalizeSentence("flower") shouldBeEqualTo "Flower" 14 | } 15 | 16 | @Test 17 | fun `"this is a house" is capitalised to "This Is A House"`() { 18 | capitalizeSentence("this is a house") shouldBeEqualTo "This Is A House" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/cache/advancedlru/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.cache.advancedlru 2 | 3 | import java.time.Clock 4 | import java.time.Duration 5 | 6 | interface LRUCache { 7 | fun put(key: K, value: V, priority: Int, ttl: Duration) 8 | fun get(key: K): V? 9 | } 10 | 11 | class AdvancedLRUCache(private val capacity: Int, private val clock: Clock = Clock.systemDefaultZone()): LRUCache { 12 | override fun put(key: K, value: V, priority: Int, ttl: Duration) { 13 | TODO("Add your solution here") 14 | } 15 | 16 | override fun get(key: K): V? { 17 | TODO("Add your solution here") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fizzbuzz/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.fizzbuzz 2 | 3 | private object Solution1 { 4 | private fun fizzBuzz(n: Int): List { 5 | val list = mutableListOf() 6 | 7 | (1..n).forEach { 8 | val item = when { 9 | it % 3 == 0 && it % 5 == 0 -> "FizzBuzz" // also (it % 15 == 0) because 3x5=15 10 | it % 3 == 0 -> "Fizz" 11 | it % 5 == 0 -> "Buzz" 12 | else -> it.toString() 13 | } 14 | 15 | list.add(item) 16 | } 17 | 18 | return list 19 | } 20 | } 21 | 22 | private object KtLintWillNotComplain 23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/pyramidgenerator/README.md: -------------------------------------------------------------------------------- 1 | # Pyramid generator 2 | 3 | ## Instructions 4 | 5 | Given a positive integer `n` implement a function which returns a list representing the generatePyramid shape with n 6 | levels. The function should console log a generatePyramid shape with N levels using the `#` character. Make sure the 7 | generatePyramid has spaces on both the left and right hand sides. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | pyramid(1) 15 | '#' 16 | 17 | pyramid(2) 18 | ' # ' 19 | '###' 20 | 21 | pyramid(3) 22 | ' # ' 23 | ' ### ' 24 | '#####' 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/product/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.product 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun product(list: List): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `product 0 returns 0`() { 13 | product(listOf(0)) shouldBeEqualTo 0 14 | } 15 | 16 | @Test 17 | fun `product 1, 2, 3 returns 6`() { 18 | product(listOf(1, 2, 3)) shouldBeEqualTo 6 19 | } 20 | 21 | @Test 22 | fun `product 4, 2, 10 returns 80`() { 23 | product(listOf(2, 4, 10)) shouldBeEqualTo 80 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/getduplicatedarguments/README.md: -------------------------------------------------------------------------------- 1 | # Get duplicated arguments 2 | 3 | ## Instructions 4 | 5 | Given variable number of arguments (list of strings) checks whether there are any duplicates among the arguments and 6 | return list of all unique duplicates. If no arguments are passes return empty list. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | getDuplicatedParams("a", "b", "c") //empty list 14 | 15 | getDuplicatedParams("a", "b", "c", "a") // [a] 16 | ``` 17 | 18 | ## Hints 19 | 20 |
21 | Hint 1 22 | Use frequency counter or multiple pointers pattern. 23 |
24 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/decapitalizeconst/README.md: -------------------------------------------------------------------------------- 1 | # Decapitalize const 2 | 3 | ## Instructions 4 | 5 | Given a string representing constant name (upper case words 6 | separated by underscore eg `FOO_BAR`) implement a function which 7 | converts it into variable name (eg. `fooBar`): 8 | - convert first word to lowercase 9 | - convert next words to lowercase, but first character is still uppercase 10 | - remove all underscore characters 11 | 12 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 13 | 14 | ## Examples 15 | 16 | ```kotlin 17 | decapitalizeConst("FOO") // foo 18 | 19 | decapitalizeConst("FOO_BAR") // fooBar 20 | 21 | decapitalizeConst("__FOO_BAR_BAZ") // fooBarBaz 22 | ``` 23 | 24 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fizzbuzz/README.md: -------------------------------------------------------------------------------- 1 | # FizzBuzz 2 | 3 | ## Instructions 4 | 5 | Given positive integer `n` implement a function which returns a list numbers from `1` to `n`. However for multiples of 6 | three list should contain word `Fizz` instead of the number and for the multiples of five list should contain 7 | word `Buzz`. For numbers which are multiples of both three and five list should contain `FizzBuzz` word. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | fizzBuzz(5) // [1, 2, "Fizz", 4, "Buzz"] 15 | 16 | fizzBuzz(16) // [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz", 16] 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/pairaverage/README.md: -------------------------------------------------------------------------------- 1 | # The pair with average 2 | 3 | ## Instructions 4 | 5 | Given sorted list of integers and target average implement a function which determine if there is a pair of values in 6 | the list where their average equals target average. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | hasAverage(listOf(), 1.0) // false 14 | 15 | hasAverage(listOf(3, 4, 7, 9), 6.5) // true 16 | 17 | hasAverage(listOf(3, 4, 7, 9), 3.0) // false 18 | 19 | hasAverage(listOf(3, 5, 9, 7, 11, 14), 8.0) // true 20 | ``` 21 | 22 | ## Hints 23 | 24 |
25 | Hint 1 26 | Use double pointer 27 |
28 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/subtract/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.subtract 2 | 3 | private object Solution1 { 4 | private fun getSubtraction(list1: List, list2: List): List { 5 | val frequencyMap1 = list1.groupingBy { it }.eachCount() 6 | val frequencyMap2 = list2.groupingBy { it }.eachCount() 7 | 8 | val itemList1 = frequencyMap1.flatMap { entry -> List(entry.value) { entry.key } }.toMutableList() 9 | val itemList2 = frequencyMap2.flatMap { entry -> List(entry.value) { entry.key } } 10 | 11 | itemList2.forEach { itemList1.remove(it) } 12 | 13 | return itemList1 14 | } 15 | } 16 | 17 | private object KtLintWillNotComplain 18 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/fromlast/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.linkedlist.singly.fromlast 2 | 3 | import com.igorwojda.linkedlist.singly.base.Solution1.Node 4 | import com.igorwojda.linkedlist.singly.base.Solution1.SinglyLinkedList 5 | 6 | private object Solution1 { 7 | private fun fromLast(list: SinglyLinkedList, endIndex: Int): Node? { 8 | var slow = list.first 9 | var fast = list.first 10 | 11 | repeat(endIndex) { fast = fast?.next } 12 | 13 | while (fast?.next != null) { 14 | slow = slow?.next 15 | fast = fast?.next 16 | } 17 | 18 | return slow 19 | } 20 | } 21 | 22 | private object KtLintWillNotComplain 23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/countupanddown/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.countupanddown 2 | 3 | // Calculate element value from element position 4 | private object Solution1 { 5 | private fun countUpAndDown(n: Int): List { 6 | val size = (n * 2) + 1 7 | 8 | return List(size) { 9 | when { 10 | it <= n -> it 11 | else -> (n * 2) - it 12 | } 13 | } 14 | } 15 | } 16 | 17 | // Returns a new list combining one collection of numbers from 0 to n-1 and another with numbers from n to 0 18 | private object Solution2 { 19 | private fun countUpAndDown(n: Int): List { 20 | return (0 until n) + (n downTo 0) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/medianoftwosorted/README.md: -------------------------------------------------------------------------------- 1 | # Median Of Two Sorted Lists 2 | 3 | ## Instructions 4 | 5 | Given two sorted lists `list1` and `list2` of integers return the median of the two sorted lists. 6 | 7 | The overall run time complexity should be `O(log (m+n))`. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | medianOfSortedLists(listOf(1, 3), listOf(2)) // 2.0 (merged list = [1, 2, 3] and median is 2) 15 | 16 | medianOfSortedLists(listOf(1, 2), listOf(3, 4)) // 2.5 (merged list = [1, 2, 3, 4] and median is (2 + 3) / 2 = 2.5) 17 | 18 | medianOfSortedLists(listOf(1, 5, 7), listOf(2)) // 3.5 (merged list = [1, 2, 5, 7] and median is (2 + 5) / 2 = 3.5) 19 | ``` 20 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/hasrepeatedcharacter/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.hasrepeatedcharacter 2 | 3 | // Time complexity: O(n) 4 | private object Solution1 { 5 | private fun hasRepeatedChar(str: String): Boolean { 6 | val frequency = str.groupingBy { it }.eachCount() 7 | return frequency.any { it.value > 1 } 8 | } 9 | } 10 | 11 | // Time complexity: O(n) 12 | private object Solution2 { 13 | private fun hasRepeatedChar(str: String): Boolean { 14 | val frequency = str.groupingBy { it }.eachCount() 15 | 16 | frequency.forEach { 17 | if (it.value > 1) { 18 | return true 19 | } 20 | } 21 | 22 | return false 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/hasrepeatedcharacter/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.hasrepeatedcharacter 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun hasRepeatedChar(str: String): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `'abc' don't have repeated character`() { 13 | hasRepeatedChar("abc") shouldBeEqualTo false 14 | } 15 | 16 | @Test 17 | fun `'aabc' has repeated character`() { 18 | hasRepeatedChar("aabc") shouldBeEqualTo true 19 | } 20 | 21 | @Test 22 | fun `'aabcc' has repeated character`() { 23 | hasRepeatedChar("aabcc") shouldBeEqualTo true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/power/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.power 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun power(base: Int, exponent: Int): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `power 2^1 returns 2`() { 13 | power(2, 1) shouldBeEqualTo 2 14 | } 15 | 16 | @Test 17 | fun `power 2^2 returns 2`() { 18 | power(2, 2) shouldBeEqualTo 4 19 | } 20 | 21 | @Test 22 | fun `power 2^3 returns 8`() { 23 | power(2, 3) shouldBeEqualTo 8 24 | } 25 | 26 | @Test 27 | fun `power 3^4 returns 81`() { 28 | power(3, 4) shouldBeEqualTo 81 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/addnumbers/README.md: -------------------------------------------------------------------------------- 1 | # Add Numbers 2 | 3 | ## Instructions 4 | 5 | Compute the sum of two non-empty linked lists, each representing a non-negative integer. he individual digits of these 6 | integers are stored in the linked lists in reverse order, with each node holding a single digit. The result of the 7 | addition should be returned as a linked list. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | private data class ListNode( 15 | var data: Int, 16 | var next: ListNode? = null, 17 | ) 18 | 19 | val i1 = ListNode(1) 20 | i1.next = ListNode(3) 21 | 22 | val i2 = ListNode(11) 23 | 24 | addTwoNumbers(i1, i2) // returns ListNode(2, ListNode(4)) 25 | ``` 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/generateallpairs/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.generateallpairs 2 | 3 | private object Solution1 { 4 | private fun getAllPairs(n: Int): List> { 5 | val result = mutableListOf>() 6 | 7 | (0..n).forEach { i -> 8 | (0..n).forEach { j -> 9 | result.add(i to j) 10 | } 11 | } 12 | 13 | return result 14 | } 15 | } 16 | 17 | private object Solution2 { 18 | private fun getAllPairs(n: Int): List> { 19 | return (0..n).map { i -> 20 | (0..n).map { j -> 21 | i to j 22 | } 23 | }.flatten() 24 | } 25 | } 26 | 27 | private object KtLintWillNotComplain 28 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/maxsublistsum/README.md: -------------------------------------------------------------------------------- 1 | # Max sub-list sum 2 | 3 | ## Instructions 4 | 5 | 6 | Given `list` of integers and integer `n` implement a function which calculates the maximum sum of `n` consecutive 7 | elements in the `list` (sum of `n` digits next to another that have the largest sum). 8 | 9 | You can use helper `max` function to deal with Kotlin nullability. 10 | 11 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 12 | 13 | ## Examples 14 | 15 | ```kotlin 16 | maxSubListSum(listOf(), 3) // null 17 | 18 | maxSubListSum(listOf(4, 2, 7), 2) // 9 19 | 20 | maxSubListSum(listOf(4, 2, 7, 5, 8, 9, 5, 1), 3) // 22 21 | ``` 22 | 23 | ## Hints 24 | 25 |
26 | Hint 1 27 | Use sliding window 28 |
29 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/ispalindrome/permutation/README.md: -------------------------------------------------------------------------------- 1 | # Is permutation palindrome 2 | 3 | ## Nice to solve before 4 | 5 | - [Palindrome](../basic/README.md) 6 | 7 | ## Instructions 8 | 9 | Given a string, return true if the input string is a permutation of palindrome or false if it is not. 10 | Permutation means that all letters of the string can be used to create a palindrome. 11 | 12 | Palindromes are strings that form the same word if it is reversed. 13 | 14 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 15 | 16 | ## Examples 17 | 18 | ```kotlin 19 | permutationPalindrome("gikig") == true 20 | 21 | permutationPalindrome("ookvk") == true 22 | 23 | permutationPalindrome("sows") == false 24 | 25 | permutationPalindrome("tami") == false 26 | ``` 27 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/stepsgenerator/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.stepsgenerator 2 | 3 | // Kotlin repeat function 4 | private object Solution1 { 5 | private fun generateSteps(n: Int) = List(n) { "#".repeat(it + 1) + " ".repeat(n - it - 1) } 6 | } 7 | 8 | // iterative solution 9 | private object Solution2 { 10 | private fun generateSteps(n: Int): MutableList { 11 | val list = mutableListOf() 12 | 13 | (1..n).forEach { row -> 14 | var item = "" 15 | 16 | (1..n).forEach { column -> 17 | val char = if (column <= row) '#' else ' ' 18 | item += char 19 | } 20 | 21 | list.add(item) 22 | } 23 | 24 | return list 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/insertionsort/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.sort.insertionsort 2 | 3 | // Time complexity (Best): Ω(n) - all data besides one element are sorted 4 | // Time complexity (Average): Θ(n^2) 5 | // Time complexity (Worst): O(n^2) 6 | // Space complexity: O(1) 7 | private object Solution1 { 8 | private fun insertionSort(list: MutableList): List { 9 | (1..list.lastIndex).forEach { i -> 10 | var j = i - 1 11 | 12 | while (j >= 0 && list[j] > list[i]) { 13 | j-- 14 | } 15 | 16 | list.removeAt(i).also { 17 | list.add(j + 1, it) 18 | } 19 | } 20 | 21 | return list 22 | } 23 | } 24 | 25 | private object KtLintWillNotComplain 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/ispalindrome/tolerant/README.md: -------------------------------------------------------------------------------- 1 | # Is tolerant palindrome 2 | 3 | ## Nice to solve before 4 | 5 | - [Palindrome](../basic/README.md) 6 | 7 | ## Instructions 8 | 9 | Given a string, return true if the string is a palindrome or false if it is not. 10 | 11 | Palindromes are strings that form the same word when reversed (including spaces and punctuation). 12 | 13 | In this exercise one bad character is allowed. The string will be (tolerant) palindrome if after removing one 14 | character string is a palindrome. 15 | 16 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 17 | 18 | ## Examples 19 | 20 | ```kotlin 21 | tolerantPalindrome("abba") == true 22 | 23 | tolerantPalindrome("abb#a") == true 24 | 25 | tolerantPalindrome("abcdefg") == false 26 | ``` 27 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/coins/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.coins 2 | 3 | // Time complexity: O(n∗m) 4 | // Space complexity: O(n)O(n) 5 | private object Solution1 { 6 | private fun getCoins(amount: Int, coins: List): Int { 7 | // array of zeros from 0..amount 8 | val waysOfDoingNCents = IntArray(amount + 1) 9 | 10 | waysOfDoingNCents[0] = 1 11 | 12 | for (coin in coins) { 13 | for (higherAmount in coin..amount) { 14 | val higherAmountRemainder = higherAmount - coin 15 | waysOfDoingNCents[higherAmount] += waysOfDoingNCents[higherAmountRemainder] 16 | } 17 | } 18 | 19 | return waysOfDoingNCents[amount] 20 | } 21 | } 22 | 23 | private object KtLintWillNotComplain 24 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/capitalizesentence/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.capitalizesentence 2 | 3 | // Kotlin idiomatic solution 4 | private object Solution1 { 5 | private fun capitalizeSentence(str: String): String { 6 | return str 7 | .split(" ") 8 | .joinToString(" ") { string -> 9 | string.replaceFirstChar { it.uppercase() } 10 | } 11 | } 12 | } 13 | 14 | // Iterative solution 15 | private object Solution2 { 16 | private fun capitalizeSentence(str: String): String { 17 | val words = mutableListOf() 18 | 19 | str.split(" ").forEach { 20 | words.add(it[0].uppercase() + it.substring(1)) 21 | } 22 | 23 | return words.joinToString(" ") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/ispalindrome/permutation/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.ispalindrome.permutation 2 | 3 | // frequency map solution 4 | private object Solution1 { 5 | private fun isPermutationPalindrome(str: String, characterRemoved: Boolean = false): Boolean { 6 | val charactersFrequencyMap = str.groupingBy { it }.eachCount() 7 | 8 | val filtered = charactersFrequencyMap.filter { it.value % 2 == 1 } 9 | 10 | return filtered.size <= 1 11 | } 12 | } 13 | 14 | private object Solution2 { 15 | private fun isPermutationPalindrome(str: String): Boolean { 16 | return str 17 | .groupBy { it } 18 | .map { it.value } 19 | .map { it.size } 20 | .count { it % 2 == 1 } == 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Tests generated by subproject 2 | src/test/kotlin/generated/ 3 | 4 | # Built application files 5 | *.apk 6 | *.ap_ 7 | *.aab 8 | 9 | # Files for the ART/Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/ 42 | 43 | # Google Services (e.g. APIs or Firebase) 44 | google-services.json 45 | 46 | #MacOS DS_Store 47 | .DS_Store 48 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/factorial/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.factorial 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun factorial(n: Int): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `factorial 0 should equal 1`() { 13 | factorial(0) shouldBeEqualTo 1 14 | } 15 | 16 | @Test 17 | fun `factorial 3 should equal 6`() { 18 | factorial(3) shouldBeEqualTo 6 19 | } 20 | 21 | @Test 22 | fun `factorial 5 should equal 120`() { 23 | factorial(5) shouldBeEqualTo 120 24 | } 25 | 26 | @Test 27 | fun `factorial 10 should equal 3628800`() { 28 | factorial(10) shouldBeEqualTo 3628800 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/generateallpairs/README.md: -------------------------------------------------------------------------------- 1 | # Generate all pairs 2 | 3 | ## Instructions 4 | 5 | Given positive Int `n` implement a function which returns a list of containing pairs with all combinations of numbers 6 | from `0` to `n`. Use Kotlin [Pair](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/) class. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | Example 1 13 | 14 | ```kotlin 15 | getAllPairs(0) // [Pair(0, 0)] 16 | ``` 17 | 18 | Example 2 19 | 20 | ```kotlin 21 | getAllPairs(1) // [Pair(0, 0), Pair(0, 1), Pair(1, 0), Pair(1, 1)] 22 | ``` 23 | 24 | Example 3 25 | 26 | ```kotlin 27 | getAllPairs(2) // [Pair(0, 0), Pair(0, 1), Pair(0, 2), Pair(1, 0), Pair(1, 1), Pair(1, 2), Pair(2, 0), Pair(2, 1), Pair(2, 2)] 28 | ``` 29 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/issubstring/README.md: -------------------------------------------------------------------------------- 1 | # Is substring 2 | 3 | ## Instructions 4 | 5 | Given two strings implement a function which determines whether the characters in the `second` string is a substring of 6 | the characters in the `first` string (check if `second` string exists as continuous/unbroken chain of characters the 7 | `first` string). 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Limitations 12 | 13 | Don't use `String.contains` method. 14 | 15 | ## Examples 16 | 17 | ```kotlin 18 | isSubstring("go home", "ome") // true 19 | 20 | isSubstring("go home", "me") // true 21 | 22 | isSubstring("go home", "abc") // false 23 | ``` 24 | 25 | ## Hints 26 | 27 |
28 | Hint 1 29 | Use double pointer or recursion 30 |
31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/midpoint/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.linkedlist.singly.midpoint 2 | 3 | import com.igorwojda.linkedlist.singly.base.Solution1.Node 4 | import com.igorwojda.linkedlist.singly.base.Solution1.SinglyLinkedList 5 | 6 | private object Solution1 { 7 | private fun midpoint(list: SinglyLinkedList): Node? { 8 | var slowPointer = list.first 9 | var fastPointer = list.first 10 | 11 | list.forEach { 12 | if (fastPointer?.next?.next == null) { 13 | return slowPointer 14 | } 15 | slowPointer = slowPointer?.next 16 | fastPointer = fastPointer?.next?.next 17 | } 18 | 19 | return null 20 | } 21 | } 22 | 23 | private object KtLintWillNotComplain 24 | 25 | // list.forEach 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/isanagram/README.md: -------------------------------------------------------------------------------- 1 | # Is anagram 2 | 3 | ## Instructions 4 | 5 | Given two strings, implement a function to determine if the second string is an anagram of the first. An anagram is a 6 | word, phrase, or name formed by rearranging the letters of another, such as `cinema`, formed from `iceman`. Only 7 | consider characters, not spaces or punctuation. Consider capital letters to be the same as lower case. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | anagrams('rail safety', 'fairy tales') --> True 15 | 16 | anagrams('RAIL! SAFETY!', 'fairy tales') --> True 17 | 18 | anagrams('Hi there', 'Bye there') --> False 19 | ``` 20 | 21 | ## Hints 22 | 23 |
24 | Hint 1 25 | Use frequency counter. 26 |
27 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/quicksort/README.md: -------------------------------------------------------------------------------- 1 | # Quick sort 2 | 3 | ## Instructions 4 | 5 | Sort list of numbers from lowest number to greatest number using 6 | [quick sort](https://en.wikipedia.org/wiki/Quicksort). 7 | 8 | Algorithm: 9 | - Pick first element as pivot (pivot can be also last, random element but we explicitly always pick first element) 10 | - Partition elements - start traversing from the leftmost element and if a smaller element is found, swap current 11 | element with `list[i]`. Keep track of index of smaller to elements at index (`pivotIndex`). 12 | - Swap pivot with element at `pivotIndex` 13 | - Recursively repeat the process for left partition (element on the left side of pivot) and right partition (element on 14 | the right side of the pivot) 15 | 16 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 17 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/matrix/findallrectangles/README.md: -------------------------------------------------------------------------------- 1 | # Find All rectangle 2 | 3 | ## Instructions 4 | 5 | Image is represent as a simple 2D array where every pixel is a 1 or a 0. The image you get is known to have multiple 6 | rectangles of 0s on a background of 1s. 7 | 8 | Write a function that takes in the image and returns list containing coordinates of top-left and bottom-right pixels 9 | represented of each rectangle: 10 | 11 | [Challenge.kt](Challenge.kt) | [solution](Solution.kt) 12 | 13 | ## Examples 14 | 15 | Example 1 16 | 17 | ```kotlin 18 | val image = listOf( 19 | listOf(0, 1, 0, 0, 0, 1), 20 | listOf(1, 1, 0, 0, 0, 1), 21 | listOf(1, 1, 1, 1, 1, 1), 22 | listOf(0, 0, 1, 1, 1, 1), 23 | ) 24 | 25 | findRectangle(image) // listOf(listOf(0, 0, 0, 0), listOf(2, 0, 4, 1), listOf(3, 0, 3, 1)) 26 | 27 | ``` 28 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/circularcheck/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.linkedlist.singly.circularcheck 2 | 3 | import com.igorwojda.linkedlist.singly.base.Solution1.SinglyLinkedList 4 | 5 | private object Solution1 { 6 | private fun circularCheck(list: SinglyLinkedList): Boolean { 7 | var slowPointer = list.first 8 | var fastPointer = list.first 9 | 10 | while (fastPointer != null) { 11 | list.forEach { 12 | slowPointer = slowPointer?.next 13 | fastPointer = fastPointer?.next?.next 14 | 15 | if (fastPointer != null && slowPointer == fastPointer) { 16 | return true 17 | } 18 | } 19 | } 20 | 21 | return false 22 | } 23 | } 24 | 25 | private object KtLintWillNotComplain 26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fizzbuzz/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.fizzbuzz 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun fizzBuzz(n: Int): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | 12 | @Test 13 | fun `Calling fizzbuzz with "5" returns list with 5 items`() { 14 | fizzBuzz(5) shouldBeEqualTo listOf("1", "2", "Fizz", "4", "Buzz") 15 | } 16 | 17 | @Test 18 | fun `Calling fizzbuzz with 16 returns out the correct values`() { 19 | val list = listOf( 20 | "1", "2", "Fizz", "4", "Buzz", "Fizz", 21 | "7", "8", "Fizz", "Buzz", "11", "Fizz", 22 | "13", "14", "FizzBuzz", "16", 23 | ) 24 | 25 | fizzBuzz(16) shouldBeEqualTo list 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/minsublistlength/README.md: -------------------------------------------------------------------------------- 1 | # Min sub-list length 2 | 3 | ## Instructions 4 | 5 | Given list of positive integers and positive integer `n` implement a function which finds minimum length of sub-list 6 | where sum all elements is equal or greater than `n` 7 | 8 | You can use helper `min` function to deal with Kotlin nullability. 9 | 10 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 11 | 12 | ## Examples 13 | 14 | ```kotlin 15 | minSubListLength(listOf(1, 3, 4), 5) // 2 (smallest sub-list [3, 4]) 16 | 17 | minSubListLength(listOf(1, 2, 11, 5, 9, 4, 6), 22) // 3 (smallest sub-list [11, 5, 9]) 18 | 19 | minSubListLength(listOf(1, 20, 11, 5, 9, 4, 6), 200) // 0 (non of the integers sums up to 200) 20 | ``` 21 | 22 | ## Hints 23 | 24 |
25 | Hint 1 26 | Use sliding window 27 |
28 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/matrix/spiralmatrixgenerator/README.md: -------------------------------------------------------------------------------- 1 | # Spiral matrix generator 2 | 3 | ## Instructions 4 | 5 | Given integer `n` implement a function which generates a spiral numbers matrix (size `n` x `n`). Numbers in matrix are 6 | placed according to spiral - starting top left corner and then go right, down, left, up, right... 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | Example 1 13 | 14 | ```kotlin 15 | generateSpiralMatrix(2) 16 | [[1, 2], 17 | [4, 3]] 18 | ``` 19 | 20 | Example 2 21 | 22 | ```kotlin 23 | generateSpiralMatrix(3) 24 | [[1, 2, 3], 25 | [8, 9, 4], 26 | [7, 6, 5]] 27 | ``` 28 | 29 | Example 3 30 | 31 | ```kotlin 32 | generateSpiralMatrix(4) 33 | [[1, 2, 3, 4], 34 | [12, 13, 14, 5], 35 | [11, 16, 15, 6], 36 | [10, 9, 8, 7]] 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/tree/multiway/traversal/breathfirst/README.md: -------------------------------------------------------------------------------- 1 | # Tree traversal 2 | 3 | ## Nice to solve before 4 | 5 | [Queue](../../../../queue/basic/README.md) 6 | 7 | ## Instructions 8 | 9 | Traverse [tree](https://en.wikipedia.org/wiki/Tree_(data_structure)) using `Breath-First` traversal. 10 | 11 | Implement breath-first traversal - visit every node on a level before going to a lower level. 12 | 13 | ![breadth_first_traversal.svg](misc/breadth_first_traversal.svg) 14 | 15 | ## Examples 16 | 17 | ```kotlin 18 | // ---------Tree------------ 19 | // 20 | // A 21 | // / \ 22 | // B C 23 | // 24 | // -------------------------- 25 | 26 | 27 | val tree = BinarySearchTree() 28 | tree.add('A') 29 | tree.add('B') 30 | tree.add('C') 31 | 32 | tree.traverseBreathFirst() // listOf('A', 'B', 'C') 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/common/anycallback/README.md: -------------------------------------------------------------------------------- 1 | # Any callback 2 | 3 | ## Nice to solve before 4 | 5 | - [Count down](../../integer/countdown/README.md) 6 | - [Get odd](../../integer/getodd/README.md) 7 | 8 | ## Instructions 9 | 10 | Given list of integers and callback implement a **recursive** function which returns `true` if simple value in the list 11 | passed to callback returns `true`, otherwise return `false`. 12 | 13 | [Challenge](Challenge.kt) | [Solution](Solution.kt) | [Tests](Tests.kt) 14 | 15 | ## Examples 16 | 17 | Example 1 18 | 19 | ```kotlin 20 | val callback:((Int) -> Boolean) = { it > 3 } 21 | anyCallback(listOf(1, 2, 3, 4), callback) shouldBeEqualTo true 22 | ``` 23 | 24 | Example 2 25 | 26 | ```kotlin 27 | val callback:((Int) -> Boolean) = { it > 3 } 28 | anyCallback(listOf(1, 2, 3), callback) shouldBeEqualTo false 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/caesarcipher/README.md: -------------------------------------------------------------------------------- 1 | # Caesar Cipher 2 | 3 | ## Instructions 4 | 5 | Given a string and integer `shift` implement a function which shifts each character in that string by `shift` amount ([cesar cipher](https://cryptii.com/pipes/caesar-cipher)) eg. if shift is `1` then `a` becomes `b`, `c` becomes`d`, `z` 6 | became `a` etc. Allowed input is string containing only lowercase characters from alphabet `abcdefghijklmnopqrstuvwxyz`. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | ```kotlin 13 | encodeCaesarCipher("abc", 1) // bcd 14 | 15 | encodeCaesarCipher("abc", 3) // def 16 | 17 | encodeCaesarCipher("xyz", 1) // yza 18 | ``` 19 | 20 | ## Hints 21 | 22 |
23 | Hint 1 24 | Use ASCI character table 25 |
26 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/printnumber/basic/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.printnumber.basic 2 | 3 | private object Solution1 { 4 | private fun printNumber(n: Int): List { 5 | return (n downTo 1).toList() 6 | } 7 | } 8 | 9 | private object Solution2 { 10 | private fun printNumber(n: Int): List = 11 | when (n) { 12 | 0 -> emptyList() 13 | else -> listOf(n) + printNumber(n - 1) 14 | } 15 | } 16 | 17 | private object Solution3 { 18 | private fun printNumber(n: Int): List { 19 | val list = mutableListOf() 20 | 21 | if (n == 0) { 22 | return emptyList() 23 | } else { 24 | list.add(n) 25 | } 26 | 27 | list.addAll(printNumber(n - 1)) 28 | return list 29 | } 30 | } 31 | 32 | private object KtLintWillNotComplain 33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/largestelements/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.largestelements 2 | 3 | import java.util.* 4 | 5 | // Time complexity: O(n log k) 6 | private object Solution1 { 7 | private fun largestElements(list: List, count: Int): List { 8 | if (list.size <= count) { 9 | return list 10 | } 11 | 12 | val priorityQueue = PriorityQueue() 13 | 14 | repeat(count) { 15 | priorityQueue.add(list[it]) 16 | } 17 | 18 | list 19 | .drop(count) 20 | .forEach { 21 | if (it > priorityQueue.peek()) { 22 | priorityQueue.poll() 23 | priorityQueue.add(it) 24 | } 25 | } 26 | 27 | return priorityQueue.toList() 28 | } 29 | } 30 | 31 | private object KtLintWillNotComplain 32 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/pairaverage/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.pairaverage 2 | 3 | // Time complexity: O(n) 4 | // Optimal solution using double pointer. 5 | private object Solution1 { 6 | fun hasAverage(list: List, average: Double): Boolean { 7 | if (list.size < 2) { 8 | return false 9 | } 10 | 11 | var pointer1 = 0 12 | var pointer2 = list.lastIndex 13 | 14 | while (pointer1 != pointer2) { 15 | val pairAvg: Double = (list[pointer1].toDouble() + list[pointer2].toDouble()) / 2 16 | 17 | when { 18 | pairAvg == average -> return true 19 | pairAvg < average -> pointer1++ 20 | pairAvg > average -> pointer2-- 21 | } 22 | } 23 | 24 | return false 25 | } 26 | } 27 | 28 | private object KtLintWillNotComplain 29 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/flatten/README.md: -------------------------------------------------------------------------------- 1 | # Flatten 2 | 3 | ## Nice to solve before 4 | 5 | ## Instructions 6 | 7 | Given list containing items (integer, lists, sub-lists) implement **recursive** function which returns list with all 8 | values flattened. This function mimics behaviour of Kotlin build in ` flatten` method. 9 | 10 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 11 | 12 | ## Limitations 13 | 14 | Don't use Kotlin build in [flatten](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/flatten.html) 15 | function. 16 | 17 | ## Examples 18 | 19 | ```kotlin 20 | flatten(listOf(1)) // 1 21 | 22 | flatten(listOf(1), listOf(listOf(2))) // 1, 2 23 | 24 | flatten(listOf(1), listOf(listOf(2), listOf(listOf(3)))) // 1, 2, 3 25 | ``` 26 | 27 | ## Hints 28 | 29 |
30 | Hint 1 31 | Use helper recursive function. 32 |
33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/largestelements/README.md: -------------------------------------------------------------------------------- 1 | # Largest Elements 2 | 3 | Implement a function that takes a list of integers and an integer `count` as input parameters. The purpose of the 4 | function is to find the largest `count` numbers from the provided list. 5 | 6 | If the size of the list is less than or equal to 'count', the function should return the original list. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | Example 1 13 | 14 | ```kotlin 15 | val list = listOf(5, 1, 3) 16 | largestElements(list, 2) shouldBeEqualTo listOf(3, 5) 17 | ``` 18 | 19 | Example 2 20 | 21 | ```kotlin 22 | val list = listOf(5, 1, 3) 23 | largestElements(list, 3) shouldBeEqualTo listOf(5, 1, 3) 24 | ``` 25 | 26 | ## Hints 27 | 28 |
29 | Hint 1 30 | Use `PriorityQueue` to store the largest elements. 31 |
32 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/queue/combine/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.queue.combine 2 | 3 | private object Solution1 { 4 | class Queue { 5 | private val list = mutableListOf() 6 | 7 | fun add(element: E) { 8 | list.add(element) 9 | } 10 | 11 | fun remove() = if (list.isEmpty()) null else list.removeAt(0) 12 | 13 | fun peek() = list.firstOrNull() 14 | } 15 | 16 | fun combine(q1: Queue<*>, q2: Queue<*>): Queue<*> { 17 | val result = Queue() 18 | 19 | while (true) { 20 | q1.remove()?.let { result.add(it) } 21 | q2.remove()?.let { result.add(it) } 22 | 23 | if (q1.peek() == null && q2.peek() == null) { 24 | break 25 | } 26 | } 27 | 28 | return result 29 | } 30 | } 31 | 32 | private object KtLintWillNotComplain 33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/printnumber/basic/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.printnumber.basic 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun printNumber(n: Int): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `printNumber 0 return listOf()`() { 13 | printNumber(0) shouldBeEqualTo listOf() 14 | } 15 | 16 | @Test 17 | fun `printNumber 1 return listOf(1)`() { 18 | printNumber(1) shouldBeEqualTo listOf(1) 19 | } 20 | 21 | @Test 22 | fun `printNumber 3 return listOf(3, 2, 1)`() { 23 | printNumber(3) shouldBeEqualTo listOf(3, 2, 1) 24 | } 25 | 26 | @Test 27 | fun `printNumber 5 return listOf(5, 4, 3, 2, 1)`() { 28 | printNumber(5) shouldBeEqualTo listOf(5, 4, 3, 2, 1) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/smallestelements/README.md: -------------------------------------------------------------------------------- 1 | # Smallest Elements 2 | 3 | Implement a function that takes a list of integers and an integer `count` as input parameters. The purpose of the 4 | function is to find the smallest `count` numbers from the provided list. 5 | 6 | If the size of the list is less than or equal to 'count', the function should return the original list. 7 | 8 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 9 | 10 | ## Examples 11 | 12 | Example 1 13 | 14 | ```kotlin 15 | val list = listOf(5, 1, 3) 16 | smallestElements(list, 2) shouldBeEqualTo listOf(3, 1) 17 | ``` 18 | 19 | Example 2 20 | 21 | ```kotlin 22 | val list = listOf(5, 1, 3) 23 | smallestElements(list, 3) shouldBeEqualTo listOf(5, 1, 3) 24 | ``` 25 | 26 | ## Hints 27 | 28 |
29 | Hint 1 30 | Use `PriorityQueue` to store the smallest elements. 31 |
32 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/getodd/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.getodd 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun filterOdd(list: List): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `empty list returns empty list`() { 13 | filterOdd(listOf()) shouldBeEqualTo emptyList() 14 | } 15 | 16 | @Test 17 | fun `1, 2, 3 returns 1, 3`() { 18 | filterOdd(listOf(1, 2, 3)) shouldBeEqualTo listOf(1, 3) 19 | } 20 | 21 | @Test 22 | fun `2, 9, 2, 5, 4 returns 9, 5`() { 23 | filterOdd(listOf(2, 9, 2, 5, 4)) shouldBeEqualTo listOf(9, 5) 24 | } 25 | 26 | @Test 27 | fun `7, 4, 6, 8, 7, 9 returns 7, 7, 9`() { 28 | filterOdd(listOf(7, 4, 6, 8, 7, 9)) shouldBeEqualTo listOf(7, 7, 9) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/smallestelements/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.smallestelements 2 | 3 | import java.util.* 4 | 5 | // Time complexity: O(n log k) 6 | private object Solution1 { 7 | private fun smallestElements(list: List, count: Int): List { 8 | if (list.size <= count) { 9 | return list 10 | } 11 | 12 | val priorityQueue = PriorityQueue(Collections.reverseOrder()) 13 | 14 | repeat(count) { 15 | priorityQueue.add(list[it]) 16 | } 17 | 18 | list 19 | .drop(count) 20 | .forEach { 21 | if (it < priorityQueue.peek()) { 22 | priorityQueue.poll() 23 | priorityQueue.add(it) 24 | } 25 | } 26 | 27 | return priorityQueue.toList() 28 | } 29 | } 30 | 31 | private object KtLintWillNotComplain 32 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/ispalindrome/permutation/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.ispalindrome.permutation 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun isPermutationPalindrome(str: String): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `'gikig' is a palindrome`() { 13 | isPermutationPalindrome("gikig") shouldBeEqualTo true 14 | } 15 | 16 | @Test 17 | fun `'ookvk' is a palindrome`() { 18 | isPermutationPalindrome("ookvk") shouldBeEqualTo true 19 | } 20 | 21 | @Test 22 | fun `'sows' is not a palindrome`() { 23 | isPermutationPalindrome("sows") shouldBeEqualTo false 24 | } 25 | 26 | @Test 27 | fun `'tami' is not a palindrome`() { 28 | isPermutationPalindrome("tami") shouldBeEqualTo false 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/longestword/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.longestword 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun longestWord(str: String): String { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `'flower' return 'flower'`() { 13 | longestWord("flower") shouldBeEqualTo "flower" 14 | } 15 | 16 | @Test 17 | fun `'flower is growing fast' return 'growing'`() { 18 | longestWord("flower is growing fast") shouldBeEqualTo "growing" 19 | } 20 | 21 | @Test 22 | fun `'This is my jeep' return 'jeep'`() { 23 | longestWord("This is my jeep") shouldBeEqualTo "This" 24 | } 25 | 26 | @Test 27 | fun `'Home!@#&sweet home' return 'sweet'`() { 28 | longestWord("Home!@&#sweet home") shouldBeEqualTo "sweet" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/maxoccurringchar/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.maxoccurringchar 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun maxOccurringChar(str: String): Char? { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `Don't find a char in empty string`() { 13 | maxOccurringChar("") shouldBeEqualTo null 14 | } 15 | 16 | @Test 17 | fun `Finds char 'a' in string 'a'`() { 18 | maxOccurringChar("a") shouldBeEqualTo 'a' 19 | } 20 | 21 | @Test 22 | fun `Finds char 'a' in string 'abcdefghijklmnaaaaa'`() { 23 | maxOccurringChar("abcdefghijklmnaaaaa") shouldBeEqualTo 'a' 24 | } 25 | 26 | @Test 27 | fun `Finds char '1' in string 'ab1c1d1e1f1g1'`() { 28 | maxOccurringChar("ab1c1d1e1f1g1") shouldBeEqualTo '1' 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/countuniquevalues/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.countuniquevalues 2 | 3 | private object Solution1 { 4 | private fun countUniqueValues(list: List): Int { 5 | val map = mutableMapOf() 6 | 7 | list.forEach { 8 | var value = map.getOrDefault(it, 0) 9 | value++ 10 | map[it] = value 11 | } 12 | 13 | return map.count() 14 | } 15 | } 16 | 17 | private object Solution2 { 18 | private fun countUniqueValues(list: List): Int { 19 | return list.toSet().size 20 | } 21 | } 22 | 23 | private object Solution3 { 24 | private fun countUniqueValues(list: List): Int { 25 | return list.distinct().size 26 | } 27 | } 28 | 29 | private object Solution4 { 30 | private fun countUniqueValues(list: List): Int { 31 | return list.groupBy { it }.size 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/vowels/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.vowels 2 | 3 | // Kotlin collection processing 4 | private object Solution1 { 5 | private fun vowels(str: String): Int { 6 | val vowels = listOf('a', 'e', 'i', 'o', 'u', 'y') 7 | return str.count { it.lowercaseChar() in vowels } 8 | } 9 | } 10 | 11 | // Iterative 12 | private object Solution2 { 13 | private fun vowels(str: String): Int { 14 | val vowels = listOf('a', 'e', 'i', 'o', 'u', 'y') 15 | var counter = 0 16 | 17 | str.forEach { 18 | if (vowels.contains(it.lowercaseChar())) { 19 | counter++ 20 | } 21 | } 22 | 23 | return counter 24 | } 25 | } 26 | 27 | // Regex 28 | private object Solution3 { 29 | private fun vowels(str: String): Int { 30 | return Regex("[aeiouy]").findAll(str.lowercase()).count() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/formattrainroute/README.md: -------------------------------------------------------------------------------- 1 | # Format train route 2 | 3 | ## Instructions 4 | 5 | Given list of strings representing train station names implement a function which will return passenger friendly 6 | `String`: 7 | - String always starts with `Train is calling at` 8 | - If list contains single train station name, then return `Train is calling at stationName` 9 | - If list contains multiple train station names, then return comma separated station names, but the last two names are separated by `and` word. 10 | 11 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 12 | 13 | ## Examples 14 | 15 | ```kotlin 16 | formatTrainRoute(listOf("Luton")) // "Train is calling at Luton" 17 | 18 | formatTrainRoute(listOf("Luton", "Harpenden")) // "Train is calling at Luton and Harpenden" 19 | 20 | formatTrainRoute(listOf("Luton", "Harpenden", "London")) // "Train is calling at Luton, Harpenden and London" 21 | ``` 22 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/search/linearsearch/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.search.linearsearch 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun getIndex(list: List, str: String): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `index of 'A' in 'A, B, C' is 0`() { 13 | getIndex(listOf("A", "B", "C"), "A") shouldBeEqualTo 0 14 | } 15 | 16 | @Test 17 | fun `index of 'B' in 'A, B, C' is 1`() { 18 | getIndex(listOf("A", "B", "C"), "B") shouldBeEqualTo 1 19 | } 20 | 21 | @Test 22 | fun `index of 'C' in 'A, B, C' is 2`() { 23 | getIndex(listOf("A", "B", "C"), "C") shouldBeEqualTo 2 24 | } 25 | 26 | @Test 27 | fun `index of 'D' in 'A, B, C' is -1`() { 28 | getIndex(listOf("A", "B", "C"), "D") shouldBeEqualTo -1 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/mergesort/README.md: -------------------------------------------------------------------------------- 1 | # Merge sort 2 | 3 | ## Instructions 4 | 5 | Sort list of numbers from lowest number to greatest number using [merge sort](https://en.wikipedia.org/wiki/Merge_sort). 6 | 7 | Algorithm: 8 | 1. Find middle point 9 | 2. Split unsorted list into two lists (using middle point) 10 | 3. Split lists until each list has single element (a list containing one element is considered sorted) 11 | 4. Merge sub-lists to produce new sorted sub-lists until there is only one sub-list remaining. This will be the sorted 12 | list. 13 | 14 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 15 | 16 | ## Examples 17 | 18 | Sort `[5, 1, 4, 2]` 19 | 20 | ```kotlin 21 | [5, 1, 4, 2] Split 22 | [5, 1] [4, 2] Split 23 | [5] [1] [4] [2] All lists are sorted 24 | [1, 5] [2,4] Merge 25 | [1, 2, 4, 5] Merge 26 | ``` 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/printnumber/steps/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.printnumber.steps 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun printNumber(n: Int, step: Int = 1): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `printNumber 0 step 1 return listOf()`() { 13 | printNumber(0, 1) shouldBeEqualTo listOf() 14 | } 15 | 16 | @Test 17 | fun `printNumber 1 step 1 return listOf(1)`() { 18 | printNumber(1, 1) shouldBeEqualTo listOf(1) 19 | } 20 | 21 | @Test 22 | fun `printNumber 3 step 2 return listOf(3, 1)`() { 23 | printNumber(3, 2) shouldBeEqualTo listOf(3, 1) 24 | } 25 | 26 | @Test 27 | fun `printNumber 11 step 3 return listOf(1, 8, 5, 2)`() { 28 | printNumber(11, 3) shouldBeEqualTo listOf(11, 8, 5, 2) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/vowels/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.vowels 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun vowels(str: String): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `'aeiouy' has 6 vovels`() { 13 | vowels("aeiouy") shouldBeEqualTo 6 14 | } 15 | 16 | @Test 17 | fun `'AEIOUY' has 6 vovels`() { 18 | vowels("AEIOUY") shouldBeEqualTo 6 19 | } 20 | 21 | @Test 22 | fun `'abcdefghijklmnopqrstuvwxyz' has 6 vovels`() { 23 | vowels("abcdefghijklmnopqrstuvwxyz") shouldBeEqualTo 6 24 | } 25 | 26 | @Test 27 | fun `'bcadfaghijkl' has 3 vovels`() { 28 | vowels("bcadfaghijkl") shouldBeEqualTo 3 29 | } 30 | 31 | @Test 32 | fun `'bcdfghjkl' has 0 vovels`() { 33 | vowels("bcdfghjkl") shouldBeEqualTo 0 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/cache/lru/README.md: -------------------------------------------------------------------------------- 1 | # LRU Cache 2 | 3 | ## Instructions 4 | 5 | Design a data structure that enables the storage and retrieval of items via a key, subject to a specified capacity 6 | limit. In cases where the addition of new items exceeds this capacity, ensure that space is made available through 7 | removing the item that was least recently accessed or used. 8 | 9 | The overall run time complexity of each method should be `O(1)`. 10 | 11 | [Challenge](Challenge.kt) | [Solution](Solution.kt) | [Tests](Tests.kt) 12 | 13 | ## Examples 14 | 15 | ```kotlin 16 | val cache = LRUCache(3) 17 | cache.size shouldBeEqualTo 0 18 | ``` 19 | 20 | ```kotlin 21 | val cache = LRUCache(2) 22 | cache.put(1, 10) 23 | cache.put(2, 20) 24 | cache.put(3, 30) 25 | 26 | cache.size shouldBeEqualTo 2 27 | cache.get(1) shouldBeEqualTo null // value removed due to capacity limit 28 | cache.get(2) shouldBeEqualTo 20 29 | cache.get(3) shouldBeEqualTo 30 30 | ``` 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fibonacci/recursivecached/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.fibonacci.recursivecached 2 | 3 | private object Solution1 { 4 | private data class MethodCache(val n: Int, val result: Int) 5 | 6 | private fun fibonacciSequenceRecursiveCached( 7 | n: Int, 8 | methodCache: MutableList = mutableListOf(), 9 | ): Int { 10 | var result = methodCache.firstOrNull { it.n == n }?.result 11 | 12 | if (result == null) { 13 | if (n < 2) { 14 | methodCache.add(MethodCache(n, n)) 15 | return n 16 | } 17 | 18 | result = fibonacciSequenceRecursiveCached(n - 1, methodCache) + 19 | fibonacciSequenceRecursiveCached(n - 2, methodCache) 20 | methodCache.add(MethodCache(n, result)) 21 | } 22 | 23 | return result 24 | } 25 | } 26 | 27 | private object KtLintWillNotComplain 28 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/reverse/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.reverse 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun reverse(list: List): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `reverse empty`() { 13 | val list = listOf() 14 | reverse(list) shouldBeEqualTo listOf() 15 | } 16 | 17 | @Test 18 | fun `reverse a`() { 19 | val list = listOf("a") 20 | reverse(list) shouldBeEqualTo listOf("a") 21 | } 22 | 23 | @Test 24 | fun `reverse even list`() { 25 | val list = listOf("a", "b") 26 | reverse(list) shouldBeEqualTo listOf("b", "a") 27 | } 28 | 29 | @Test 30 | fun `reverse odd list`() { 31 | val list = listOf("a", "b", "c") 32 | reverse(list) shouldBeEqualTo listOf("c", "b", "a") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/product/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.product 2 | 3 | // Kotlin idiomatic solution 4 | private object Solution1 { 5 | private fun product(list: List): Int { 6 | return list.reduce { accumulated, current -> accumulated * current } 7 | } 8 | } 9 | 10 | // Recursive solution 11 | private object Solution2 { 12 | private fun product(list: List): Int { 13 | if (list.size == 1) { 14 | return list.first() 15 | } 16 | 17 | return list.first() * product(list.drop(1)) 18 | } 19 | } 20 | 21 | // Tail-recursive solution 22 | private object Solution3 { 23 | private fun product(list: List): Int { 24 | fun prod(acc: Int, list: List): Int { 25 | if (list.isEmpty()) { 26 | return acc 27 | } 28 | return prod(acc * list.first(), list.drop(1)) 29 | } 30 | return prod(1, list) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/getduplicatedarguments/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.getduplicatedarguments 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | fun getDuplicatedArguments(vararg strings: String): List? { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `a, b, c returns empty list`() { 13 | getDuplicatedArguments("a", "b", "c") shouldBeEqualTo listOf() 14 | } 15 | 16 | @Test 17 | fun `a, b, c, a returns a`() { 18 | getDuplicatedArguments("a", "b", "c", "a") shouldBeEqualTo listOf("a") 19 | } 20 | 21 | @Test 22 | fun `a, e, a, e, d, a returns a, e`() { 23 | getDuplicatedArguments("a", "e", "a", "e", "d", "a") shouldBeEqualTo listOf("a", "e") 24 | } 25 | 26 | @Test 27 | fun `no arguments returns empty list`() { 28 | getDuplicatedArguments() shouldBeEqualTo listOf() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/queue/combine/README.md: -------------------------------------------------------------------------------- 1 | # Combine two queues 2 | 3 | ## Instructions 4 | 5 | Given two queues implement a function which combines the contents of each queue into third queue. The third queue should 6 | contain the content of the two queues. The function should handle queues of different lengths without inserting `null` 7 | into the new one. Take into consideration the fact that both queues may be of different length. IntQueue can only expose 8 | `add`, `remove`, and `peek` methods to external clients. 9 | 10 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 11 | 12 | ## Examples 13 | 14 | ```kotlin 15 | val queueOne = new Queue() 16 | queueOne.add(1) 17 | queueOne.add(2) 18 | 19 | val queueTwo = new Queue() 20 | queueTwo.add('Hi') 21 | queueTwo.add('There') 22 | 23 | val queueThree = weave(queueOne, queueTwo) 24 | queueThree.remove() // 1 25 | queueThree.remove() // 'Hi' 26 | queueThree.remove() // 2 27 | queueThree.remove() // 'There' 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/tree/heap/maxbinaryheap/README.md: -------------------------------------------------------------------------------- 1 | # Max binary heap 2 | 3 | ## Instructions 4 | 5 | Implement [Max binary heap](https://en.wikipedia.org/wiki/Heap_(data_structure)). In the `Max Binary Heap` each node may 6 | have from `0` to `2` children. Parent nodes are always larger than child nodes, in other words all children are always 7 | smaller than a parents. Heap always have to be filled from "left side" meaning that we can add children to new level 8 | only if current level is full (each parent from previous level have two children). 9 | 10 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 11 | 12 | ## Examples 13 | 14 | ```kotlin 15 | // ----------Heap------------ 16 | // 17 | // 9 18 | // / \ 19 | // 7 6 20 | // / \ / 21 | // 3 2 4 22 | // 23 | // -------------------------- 24 | 25 | val heap = MaxBinaryHeap() 26 | heap.add(9) 27 | heap.add(7) 28 | heap.add(6) 29 | heap.add(3) 30 | heap.add(2) 31 | heap.add(4) 32 | ``` 33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/selectionsort/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.sort.selectionsort 2 | 3 | // Time complexity (Best): Ω(n^2) 4 | // Time complexity (Average): Θ(n^2) 5 | // Time complexity (Worst): O(n^2) 6 | // Space complexity: O(1) 7 | private object Solution1 { 8 | private fun selectionSort(list: List): List { 9 | val sorted = list.toMutableList() 10 | 11 | (0..sorted.lastIndex).forEach { i -> 12 | var indexOfMin = i 13 | 14 | ((i + 1)..sorted.lastIndex).forEach { j -> 15 | if (sorted[j] < sorted[indexOfMin]) { 16 | indexOfMin = j 17 | } 18 | } 19 | 20 | if (indexOfMin != i) { 21 | val temp = sorted[i] 22 | sorted[i] = sorted[indexOfMin] 23 | sorted[indexOfMin] = temp 24 | } 25 | } 26 | 27 | return sorted 28 | } 29 | } 30 | 31 | private object KtLintWillNotComplain 32 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/selectionsort/README.md: -------------------------------------------------------------------------------- 1 | # Selection sort 2 | 3 | ## Instructions 4 | 5 | Sort list of numbers from lowest number to greatest number using 6 | [selection sort](https://en.wikipedia.org/wiki/Selection_sort). 7 | 8 | Algorithm: Sort an list by repeatedly finding the minimum element (ascending order) from unsorted part and putting it at 9 | the beginning of the list. 10 | 11 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 12 | 13 | ## Examples 14 | 15 | Sort `[5, 1, 4, 2, 8]` 16 | 17 | Find the minimum element in sub-list indexes 1...4 and place it at index 0 18 | ```kotlin 19 | [5, 1, 4, 2, 8] // [1, 5, 4, 2, 8] Swap since 1 < 5 20 | ``` 21 | 22 | Find the minimum element in sub-list indexes 2...4 and place it at index 1 23 | ```kotlin 24 | [1, 5, 4, 2, 8] // [1, 2, 4, 5, 8] Swap since 2 < 4 25 | ``` 26 | 27 | Find the minimum element in sub-list indexes 3...4 and place it at index 2 28 | ```kotlin 29 | [1, 2, 4, 5, 8] // [1, 2, 4, 5, 8] No swap since 5 < 8 30 | ``` 31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/stepsgenerator/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.stepsgenerator 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | fun generateSteps(n: Int): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `steps n = 1`() { 13 | val actual = generateSteps(1) 14 | actual.size shouldBeEqualTo 1 15 | actual[0] shouldBeEqualTo "#" 16 | } 17 | 18 | @Test 19 | fun `steps n = 2`() { 20 | val actual = generateSteps(2) 21 | actual.size shouldBeEqualTo 2 22 | actual[0] shouldBeEqualTo "# " 23 | actual[1] shouldBeEqualTo "##" 24 | } 25 | 26 | @Test 27 | fun `steps n = 3`() { 28 | val actual = generateSteps(3) 29 | actual.size shouldBeEqualTo 3 30 | actual[0] shouldBeEqualTo "# " 31 | actual[1] shouldBeEqualTo "## " 32 | actual[2] shouldBeEqualTo "###" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/squareequal/README.md: -------------------------------------------------------------------------------- 1 | # Square equals 2 | 3 | ## Instructions 4 | 5 | Given two lists of integers implement a function which returns `true` if every value in the first list has it's 6 | corresponding value squared in the second list. The frequency of values must be the same eg. if there are two values in 7 | first list, two exactly two squared values must exist in second list. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | squareEquals(listOf(2), listOf(4)) // true 15 | 16 | squareEquals(listOf(1, 2, 3), listOf(9, 1, 4)) // true 17 | 18 | squareEquals(listOf(1, 2, 3), listOf(9, 1, 7)) // false (does not have square of 2) 19 | 20 | squareEquals(listOf(1, 2, 3), listOf(9, 1)) // false (does not have square of 2) 21 | 22 | squareEquals(listOf(1, 2, 1), listOf(4, 1, 4)) // false (frequency must be the same) 23 | ``` 24 | 25 | ## Hints 26 | 27 |
28 | Hint 1 29 | Use frequency counter. 30 |
31 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/surroundedletter/README.md: -------------------------------------------------------------------------------- 1 | # Surrounded letter 2 | 3 | ## Instructions 4 | 5 | Given a string containing letters and `+` characters implement a function which determines if each letter in the string 6 | is surrounded by `+` character. There may be more than one `+` character between letters (`+a++b+`) and letters may be 7 | surrounded by the same `+` character (`+a+b+`). 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Examples 12 | 13 | ```kotlin 14 | surroundedLetter("+a+") // true 15 | 16 | surroundedLetter("+ab+") // false 17 | 18 | surroundedLetter("+a+b+") // true 19 | 20 | surroundedLetter("+a++b++") // true 21 | ``` 22 | 23 | ## Hints 24 | 25 |
26 | Hint 1 27 | Use can use regex to determine number of available patterns (plus character ; letter ; plus character) in the string. 28 |
29 | 30 | 31 |
32 | Hint 2 33 | You can also get number of available letters in the string. 34 |
35 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/common/anycallback/Tests.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.common.anycallback 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | class Tests { 7 | // Easily switch between a known solution and Challenge code 8 | val functionUnderTest: (list: List, callback: (Int) -> Boolean)->Boolean = ::anyCallback // or SolutionN::anyCallback 9 | 10 | @Test 11 | fun `any callback returns true`() { 12 | val callback: ((Int) -> Boolean) = { it > 3 } 13 | functionUnderTest(listOf(1, 2, 3, 4), callback) shouldBeEqualTo true 14 | } 15 | 16 | @Test 17 | fun `any callback returns false`() { 18 | val callback: ((Int) -> Boolean) = { it > 3 } 19 | functionUnderTest(listOf(1, 2, 3), callback) shouldBeEqualTo false 20 | } 21 | 22 | @Test 23 | fun `empty list returns false`() { 24 | val callback: ((Int) -> Boolean) = { it > 3 } 25 | functionUnderTest(emptyList(), callback) shouldBeEqualTo false 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/generateallpairs/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.generateallpairs 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun getAllPairs(n: Int): List> { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `get all pairs 0`() { 13 | getAllPairs(0) shouldBeEqualTo listOf(0 to 0) 14 | } 15 | 16 | @Test 17 | fun `get all pairs 1`() { 18 | getAllPairs(1) shouldBeEqualTo listOf( 19 | 0 to 0, 20 | 0 to 1, 21 | 1 to 0, 22 | 1 to 1, 23 | ) 24 | } 25 | 26 | @Test 27 | fun `get all pairs 2`() { 28 | getAllPairs(2) shouldBeEqualTo listOf( 29 | 0 to 0, 30 | 0 to 1, 31 | 0 to 2, 32 | 1 to 0, 33 | 1 to 1, 34 | 1 to 2, 35 | 2 to 0, 36 | 2 to 1, 37 | 2 to 2, 38 | ) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/printnumber/steps/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.printnumber.steps 2 | 3 | private object Solution1 { 4 | private fun printNumber(n: Int, step: Int = 1): List = 5 | (n downTo 1 step step).toList() 6 | } 7 | 8 | private object Solution2 { 9 | private fun printNumber(n: Int, step: Int = 1): List { 10 | fun printNumberRec(n: Int): List = 11 | when { 12 | n <= 0 -> emptyList() 13 | else -> listOf(n) + printNumberRec(n - step) 14 | } 15 | return printNumberRec(n) 16 | } 17 | } 18 | 19 | private object Solution3 { 20 | private fun printNumber(n: Int, step: Int = 1): List { 21 | val list = mutableListOf() 22 | 23 | if (n <= 0) { 24 | return emptyList() 25 | } else { 26 | list.add(n) 27 | } 28 | 29 | list.addAll(printNumber(n - step, step)) 30 | return list 31 | } 32 | } 33 | 34 | private object KtLintWillNotComplain 35 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/formattrainroute/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.formattrainroute 2 | 3 | private object Solution1 { 4 | private fun formatTrainRoute(stations: List): String { 5 | val prefix = "Train is calling at " 6 | 7 | if (stations.size == 1) { 8 | return prefix + stations[0] 9 | } 10 | 11 | val lastStation = stations.takeLast(1) 12 | .joinToString { it } 13 | 14 | val followingStations = stations.dropLast(1) 15 | .joinToString { it } 16 | 17 | return "$prefix$followingStations and $lastStation" 18 | } 19 | } 20 | 21 | private object Solution2 { 22 | private fun formatTrainRoute(stations: List): String { 23 | var res = "" 24 | stations.forEach { 25 | res += when (it) { 26 | stations.first() -> it 27 | stations.last() -> " and $it" 28 | else -> ", $it" 29 | } 30 | } 31 | return "Train is calling at $res" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sumzero/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.sumzero 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun sumZero(list: List): Pair? { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `sumZero empty list return null`() { 13 | sumZero(listOf()) shouldBeEqualTo null 14 | } 15 | 16 | @Test 17 | fun `sumZero 1, 2 return null`() { 18 | sumZero(listOf(1, 2)) shouldBeEqualTo null 19 | } 20 | 21 | @Test 22 | fun `sumZero 1, 2, 4, 7 return null`() { 23 | sumZero(listOf(1, 2, 4, 7)) shouldBeEqualTo null 24 | } 25 | 26 | @Test 27 | fun `sumZero -4, -3, -2, 1, 2, 3, 5 return Pair(-3, 3)`() { 28 | sumZero(listOf(-4, -3, -2, 1, 2, 3, 5)) shouldBeEqualTo Pair(-3, 3) 29 | } 30 | 31 | @Test 32 | fun `sumZero -4, -3, -2, 1, 2, 5 return Pair(-2, 2)`() { 33 | sumZero(listOf(-4, -3, -2, 1, 2, 5)) shouldBeEqualTo Pair(-2, 2) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fibonacci/recursivecached/README.md: -------------------------------------------------------------------------------- 1 | # Recursive cache fibonacci 2 | 3 | ## Instructions 4 | 5 | Below function returns out the n-th entry in the [fibonacci](https://en.wikipedia.org/wiki/Fibonacci_number) series. 6 | ```kotlin 7 | private fun fibonacciSequenceRecursiveCached(n: Int): Int { 8 | if (n < 2) { 9 | return n 10 | } 11 | 12 | return fibonacciSequenceRecursiveCached(n - 1) + fibonacciSequenceRecursiveCached(n - 2) 13 | } 14 | ``` 15 | 16 | However due to recursion this function has exponential complexity (function is called recursively multiple times with 17 | identical arguments), so its execution takes a long time. Store arguments of each call along with the result using 18 | `MethodCache` class. 19 | 20 | ```kotlin 21 | private data class MethodCache(val n: Int, val result: Int) 22 | ``` 23 | 24 | If the function is called again with the same arguments, return the precomputed result rather than running the function 25 | again. 26 | 27 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/reverse/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.reverse 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun reverseInt(i: Int): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `ReverseInt handles 0 as an input`() { 13 | reverseInt(0) shouldBeEqualTo 0 14 | } 15 | 16 | @Test 17 | fun `ReverseInt flips a positive number`() { 18 | reverseInt(5) shouldBeEqualTo 5 19 | reverseInt(15) shouldBeEqualTo 51 20 | reverseInt(90) shouldBeEqualTo 9 21 | reverseInt(700) shouldBeEqualTo 7 22 | reverseInt(2359) shouldBeEqualTo 9532 23 | } 24 | 25 | @Test 26 | fun `ReverseInt flips a negative number`() { 27 | reverseInt(-5) shouldBeEqualTo -5 28 | reverseInt(-15) shouldBeEqualTo -51 29 | reverseInt(-90) shouldBeEqualTo -9 30 | reverseInt(-700) shouldBeEqualTo -7 31 | reverseInt(-2359) shouldBeEqualTo -9532 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/fromlast/README.md: -------------------------------------------------------------------------------- 1 | # Take n-th element from last 2 | 3 | ## Nice to solve before 4 | 5 | - [Singly linked list](../base/README.md) 6 | - [Midpoint](../midpoint/README.md) 7 | - [Circular check](../circularcheck/README.md) 8 | 9 | ## Instructions 10 | 11 | Given a linked list, return the element n positions from the last node in the list. Assume that `endIndex` will always 12 | be less than the length of the list. 13 | 14 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 15 | 16 | ## Limitations 17 | 18 | Do not use a counter variable, do not retrieve the `size` of the list, and only iterate through the **whole*- list one 19 | time. 20 | 21 | ## Examples 22 | 23 | ```kotlin 24 | val l = LinkedList() 25 | l.insertLast('a') 26 | l.insertLast('b') 27 | l.insertLast('c') 28 | l.insertLast('d') 29 | l.insertLast('e') 30 | 31 | fromLast(l, 0)?.data shouldBeEqualTo 'e' 32 | fromLast(l, 3)?.data shouldBeEqualTo 'b' 33 | ``` 34 | 35 | ## Hints 36 | 37 |
38 | Hint 1 39 | desc 40 |
41 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/smallestelements/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.smallestelements 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun smallestElements(list: List, count: Int): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `4 smallest elements`() { 13 | val list = listOf(5, 1, 3) 14 | 15 | smallestElements(list, 3) shouldBeEqualTo listOf(5, 1, 3) 16 | } 17 | 18 | @Test 19 | fun `3 smallest elements`() { 20 | val list = listOf(5, 1, 3) 21 | 22 | smallestElements(list, 3) shouldBeEqualTo listOf(5, 1, 3) 23 | } 24 | 25 | @Test 26 | fun `2 smallest elements`() { 27 | val list = listOf(5, 1, 3) 28 | 29 | smallestElements(list, 2) shouldBeEqualTo listOf(3, 1) 30 | } 31 | 32 | @Test 33 | fun `1 smallest element`() { 34 | val list = listOf(5, 1, 3) 35 | 36 | smallestElements(list, 1) shouldBeEqualTo listOf(1) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fibonacci/basic/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.fibonacci.basic 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun fibonacci(n: Int): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `calculates correct fib value for 0`() { 13 | fibonacci(0) shouldBeEqualTo 0 14 | } 15 | 16 | @Test 17 | fun `calculates correct fib value for 1`() { 18 | fibonacci(1) shouldBeEqualTo 1 19 | } 20 | 21 | @Test 22 | fun `calculates correct fib value for 2`() { 23 | fibonacci(2) shouldBeEqualTo 1 24 | } 25 | 26 | @Test 27 | fun `calculates correct fib value for 3`() { 28 | fibonacci(3) shouldBeEqualTo 2 29 | } 30 | 31 | @Test 32 | fun `calculates correct fib value for 4`() { 33 | fibonacci(4) shouldBeEqualTo 3 34 | } 35 | 36 | @Test 37 | fun `calculates correct fib value for 39`() { 38 | fibonacci(39) shouldBeEqualTo 63245986 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/capitalizefirst/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.capitalizefirst 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun capitalizeFirst(list: List): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `capitalize list with one string`() { 13 | capitalizeFirst(listOf("igor")) shouldBeEqualTo listOf("Igor") 14 | } 15 | 16 | @Test 17 | fun `capitalize list with two strings`() { 18 | capitalizeFirst(listOf("igor", "wojda")) shouldBeEqualTo listOf("Igor", "Wojda") 19 | } 20 | 21 | @Test 22 | fun `capitalize list with empty string`() { 23 | capitalizeFirst(listOf("")) shouldBeEqualTo listOf("") 24 | } 25 | 26 | @Test 27 | fun `capitalize list with sentence`() { 28 | capitalizeFirst(listOf("what a", "beautiful", "morning")) shouldBeEqualTo listOf( 29 | "What a", 30 | "Beautiful", 31 | "Morning", 32 | ) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/search/binarysearch/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.search.binarysearch 2 | 3 | // Time complexity (Best): Ω(1) 4 | // Time complexity (Average): Θ(log(n)) 5 | // Time complexity(Worst): O(log(n)) 6 | private object Solution1 { 7 | private fun binarySearch(list: List, element: Char): Int { 8 | var left = 0 9 | var right = list.size - 1 10 | 11 | while (left <= right) { 12 | val middle = (right + left) / 2 13 | 14 | // Check if x is present at mid 15 | if (list[middle] == element) { 16 | return middle 17 | } 18 | 19 | if (list[middle] < element) { 20 | left = middle + 1 // x greater than middle, so ignore left half 21 | } else { 22 | right = middle - 1 // x greater than middle, so , ignore right half 23 | } 24 | } 25 | 26 | // if we reach here, then element was 27 | // not present 28 | return -1 29 | } 30 | } 31 | 32 | private object KtLintWillNotComplain 33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/bubblesort/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.sort.bubblesort 2 | 3 | // Time complexity (Best): Ω(n) - all data besides one element are sorted 4 | // Time complexity (Average): Θ(n^2) 5 | // Time complexity (Worst): O(n^2) 6 | // Space complexity: O(1) 7 | private object Solution1 { 8 | private fun bubbleSort(list: List): List { 9 | val sorted = list.toMutableList() 10 | 11 | (0..sorted.lastIndex).forEach { i -> 12 | var swapped = false 13 | (0 until (sorted.size - i - 1)).forEach { j -> 14 | val element = sorted[j] 15 | val nextElement = sorted[j + 1] 16 | 17 | if (element > nextElement) { 18 | sorted[j] = nextElement 19 | sorted[j + 1] = element 20 | swapped = true 21 | } 22 | } 23 | 24 | if (!swapped) { 25 | return sorted 26 | } 27 | } 28 | 29 | return sorted 30 | } 31 | } 32 | 33 | private object KtLintWillNotComplain 34 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/stack/basic/README.md: -------------------------------------------------------------------------------- 1 | # Stack 2 | 3 | ## Instructions 4 | 5 | Implement a [stack](https://en.wikipedia.org/wiki/Stack) data structure. Adding to the stack should store an element 6 | until it is removed. First element added to a stack will be the last that is removed (FILO). 7 | 8 | The stack should be a class with members: 9 | - `add` method - adds element to the stack 10 | - `remove` method - removes the "top" element from the stack 11 | - `peek` method - returns "top" element (the one that should be returned) without removing (removeping) it from the stack 12 | - `isEmpty()` - returns true if there are elements on the stack, otherwise return false 13 | - `size` - numbers of items in the stack 14 | 15 | The stack can be implemented in few different ways by using different underlying data structures. Implement each of 16 | them: 17 | - List 18 | - Linked list 19 | 20 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 21 | 22 | ## Examples 23 | 24 | ```kotlin 25 | val s = new Stack() 26 | s.add(1) 27 | s.add(2) 28 | s.remove() // 2 29 | s.remove() // 1 30 | s.remove() // null 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/tree/binarytree/insert/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.tree.binarytree.insert 2 | 3 | private object Solution1 { 4 | private data class Node>( 5 | var data: E, 6 | var left: Node? = null, 7 | var right: Node? = null, 8 | ) { 9 | fun insert(e: E) { 10 | if (e < data) { // left node 11 | if (left == null) { 12 | left = Node(e) 13 | } else { 14 | left?.insert(e) 15 | } 16 | } else if (e > data) { // right node 17 | if (right == null) { 18 | right = Node(e) 19 | } else { 20 | right?.insert(e) 21 | } 22 | } 23 | } 24 | 25 | fun contains(e: E): Boolean = when { 26 | e == data -> true 27 | e < data -> left?.contains(e) ?: false 28 | e > data -> right?.contains(e) ?: false 29 | else -> false 30 | } 31 | } 32 | } 33 | 34 | private object KtLintWillNotComplain 35 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/digitfrequency/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.digitfrequency 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun equalDigitFrequency(i1: Int, i2: Int): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `'789' and '897' have the same digit frequency`() { 13 | equalDigitFrequency(789, 897) shouldBeEqualTo true 14 | } 15 | 16 | @Test 17 | fun `'123445' and '451243' have the same digit frequency`() { 18 | equalDigitFrequency(123445, 451243) shouldBeEqualTo true 19 | } 20 | 21 | @Test 22 | fun `'447' and '477' have different digit frequency`() { 23 | equalDigitFrequency(447, 477) shouldBeEqualTo false 24 | } 25 | 26 | @Test 27 | fun `'578' and '0' have different digit frequency`() { 28 | equalDigitFrequency(578, 0) shouldBeEqualTo false 29 | } 30 | 31 | @Test 32 | fun `'0' and '0' have the same digit frequency`() { 33 | equalDigitFrequency(0, 0) shouldBeEqualTo true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/surroundedletter/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.surroundedletter 2 | 3 | // Regex solution 4 | private object Solution1 { 5 | private fun surroundedLetter(str: String): Boolean { 6 | val pattern = Regex("(?=(\\+[a-z]\\+))") 7 | .findAll(str) 8 | .count() 9 | 10 | val letters = str.count { it.isLetter() } 11 | 12 | return pattern == letters 13 | } 14 | } 15 | 16 | // Iterative solution 17 | private object Solution2 { 18 | private fun surroundedLetter(str: String): Boolean { 19 | if (str.length < 3) { 20 | return false 21 | } 22 | 23 | if (str.first().isLetter() || str.last().isLetter()) { 24 | return false 25 | } 26 | 27 | var previousCharacter = str.first() 28 | 29 | str.drop(1).forEach { currentCharacter -> 30 | if (currentCharacter.isLetter() && previousCharacter.isLetter()) { 31 | return false 32 | } 33 | 34 | previousCharacter = currentCharacter 35 | } 36 | 37 | return true 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Igor Wojda 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/squareequal/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.squareequal 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun squareEquals(list: List, squared: List): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `square 2 equal square 4`() { 13 | squareEquals(listOf(2), listOf(4)) shouldBeEqualTo true 14 | } 15 | 16 | @Test 17 | fun `square 1, 2, 3 equals square 9, 1, 4`() { 18 | squareEquals(listOf(1, 2, 3), listOf(9, 1, 4)) shouldBeEqualTo true 19 | } 20 | 21 | @Test 22 | fun `square 1, 2, 3 does not equal square 9, 1, 7`() { 23 | squareEquals(listOf(1, 2, 3), listOf(9, 1, 7)) shouldBeEqualTo false 24 | } 25 | 26 | @Test 27 | fun `square 1, 2, 3 does not equal square 9, 1`() { 28 | squareEquals(listOf(1, 2, 3), listOf(9, 1)) shouldBeEqualTo false 29 | } 30 | 31 | @Test 32 | fun `square 1, 2, 1 does not equal 4, 1, 4`() { 33 | squareEquals(listOf(1, 2, 1), listOf(4, 1, 4)) shouldBeEqualTo false 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/tree/binarytree/validate/README.md: -------------------------------------------------------------------------------- 1 | # Binary Tree (validate) 2 | 3 | ## Nice to solve before 4 | 5 | [Binary search tree](../insert/README.md) 6 | 7 | ## Instructions 8 | 9 | Given a node, validate the binary search tree, ensuring that every node's left hand child is less than the parent node's value, and that 10 | every node's right hand child is greater than the parent 11 | 12 | Requirements that are always true for any given node in `Binary Search Tree`: 13 | - parent node value is always 14 | greater than value of *all* nodes in the left subtree 15 | and less than value of *all* nodes in the right subtree 16 | - left node value is also a valid BST 17 | - right node value is also a valid BST 18 | 19 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 20 | 21 | ## Examples 22 | 23 | ```kotlin 24 | val tree = Node(2) 25 | tree.insert(10) 26 | isValidSearchBinaryTree(tree) // true 27 | ``` 28 | 29 | ## Hints 30 | 31 |
32 | Hint 1 33 | Use recursion 34 |
35 | 36 | Hint 2 37 |
38 | Pass `min` and `max` to `isValidSearchBinaryTree` method 39 |
40 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/factorial/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.factorial 2 | 3 | // iterative solution 4 | private object Solution1 { 5 | private fun factorial(n: Int): Int { 6 | var total = 1 7 | 8 | (1..n).forEach { 9 | total *= it 10 | } 11 | 12 | return total 13 | } 14 | } 15 | 16 | // another iterative solution 17 | private object Solution2 { 18 | private fun factorial(n: Int): Int = 19 | when (n) { 20 | 0 -> 1 21 | else -> (n downTo 1).reduce { acc, it -> acc * it } 22 | } 23 | } 24 | 25 | // recursive solution 26 | private object Solution3 { 27 | private fun factorial(n: Int): Int = 28 | when (n) { 29 | 0, 1 -> 1 30 | else -> n * factorial(n - 1) 31 | } 32 | } 33 | 34 | // Tail-recursive solution 35 | private object Solution4 { 36 | private fun factorial(n: Int): Int { 37 | fun fact(n: Int, acc: Int = 1): Int = 38 | when (n) { 39 | 0, 1 -> acc 40 | else -> fact(n - 1, acc * n) 41 | } 42 | return fact(n) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/capitalizefirst/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.capitalizefirst 2 | 3 | // Kotlin idiomatic solution 4 | private object Solution1 { 5 | private fun capitalizeFirst(list: List): List { 6 | return list.map { it.replaceFirstChar { string -> string.uppercaseChar() } } 7 | } 8 | } 9 | 10 | // Recursive solution 11 | private object Solution2 { 12 | private fun capitalizeFirst(list: List): List { 13 | return if (list.isEmpty()) { 14 | emptyList() 15 | } else { 16 | listOf(list.first().replaceFirstChar { string -> string.uppercaseChar() }) + capitalizeFirst(list.drop(1)) 17 | } 18 | } 19 | } 20 | 21 | // Recursive solution 22 | private object Solution3 { 23 | private fun capitalizeFirst(list: List): List { 24 | if (list.size == 1) { 25 | return list.map { it.replaceFirstChar { string -> string.uppercaseChar() } } 26 | } 27 | 28 | return list.take(1) 29 | .map { it.replaceFirstChar { string -> string.uppercaseChar() } } + capitalizeFirst(list.drop(1)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/caesarcipher/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.caesarcipher 2 | 3 | private object Solution1 { 4 | private fun encodeCaesarCipher(str: String, shift: Int): String { 5 | val aCode = 'a'.code 6 | val zCode = 'z'.code 7 | val realShift = shift % (zCode - aCode + 1) 8 | 9 | return str.map { 10 | var code = it.code 11 | code += realShift 12 | 13 | if (code > zCode) { 14 | code = aCode + (code % zCode) - 1 15 | } 16 | 17 | code.toChar() 18 | }.joinToString(separator = "") 19 | } 20 | } 21 | 22 | private object Solution2 { 23 | private fun encodeCaesarCipher(str: String, shift: Int): String { 24 | val alphabet = "abcdefghijklmnopqrstuvwxyz" 25 | 26 | var encoded = "" 27 | 28 | str.forEach { 29 | val indexInAlphabet = alphabet.indexOf(it) 30 | val newIndex = (indexInAlphabet + shift) % alphabet.length 31 | encoded += alphabet[newIndex] 32 | } 33 | 34 | return encoded 35 | } 36 | } 37 | 38 | private object KtLintWillNotComplain 39 | -------------------------------------------------------------------------------- /.test/src/test/kotlin/com/igorwojda/challenge/utils/TestUtils.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.challenge.utils 2 | 3 | import java.io.File 4 | 5 | object TestUtils { 6 | 7 | /** 8 | * Return repository root directory File 9 | */ 10 | private val repoRootDirectoryFile by lazy { 11 | val scriptDirectory = File("") 12 | scriptDirectory.absoluteFile.parentFile 13 | } 14 | 15 | /** 16 | * Return list of project names 17 | */ 18 | fun challengeDirectories(): List { 19 | val path = "${repoRootDirectoryFile.path}/src/test/kotlin/com/igorwojda" 20 | val directory = File(path) 21 | val miscDirectoryName = "misc" 22 | 23 | return directory 24 | .walk() 25 | .filter { it.isDirectory } 26 | .filter { it.name != miscDirectoryName } 27 | .filter { it.isHighLevelDirectory } 28 | .toList() 29 | } 30 | 31 | /** 32 | * Checks whatever or not directory is high level directory (challenge grouping directory) 33 | */ 34 | private val File.isHighLevelDirectory get() = this.isDirectory && this.listFiles().none { it.isDirectory } 35 | } 36 | -------------------------------------------------------------------------------- /.test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | import com.igorwojda.challenge.utils.TestUtils 3 | import org.gradle.api.tasks.testing.logging.TestExceptionFormat 4 | 5 | plugins { 6 | kotlin("jvm") version "1.9.25" 7 | id("com.adarshr.test-logger") version "3.2.0" 8 | id("com.diffplug.spotless") version "6.25.0" 9 | } 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | testImplementation("org.junit.jupiter:junit-jupiter:5.14.1") 17 | testImplementation("org.amshove.kluent:kluent:1.73") 18 | testImplementation("org.jetbrains.kotlin:kotlin-compiler:1.9.25") 19 | } 20 | 21 | tasks.test { 22 | useJUnitPlatform() 23 | 24 | testLogging { 25 | events("failed") 26 | 27 | // log full stacktrace of failed test (assertion library descriptive error) 28 | exceptionFormat = TestExceptionFormat.FULL 29 | } 30 | } 31 | 32 | task("generateTests") { 33 | group = "verification" 34 | 35 | TestUtils.generateTestFiles(project) 36 | } 37 | 38 | kotlin { 39 | jvmToolchain(19) 40 | } 41 | 42 | spotless { 43 | kotlin { 44 | ktlint() 45 | 46 | indentWithSpaces() 47 | endWithNewline() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /.github/workflows/run-checks.yml: -------------------------------------------------------------------------------- 1 | name: Check 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | types: [ opened, synchronize ] 8 | 9 | jobs: 10 | check: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: checkout 14 | uses: actions/checkout@v4 15 | 16 | - name: Set up JDK 17 | uses: actions/setup-java@v3 18 | with: 19 | java-version: 19 20 | distribution: 'zulu' 21 | 22 | - name: Verify project consistency 23 | run: cd .test && ./gradlew test 24 | 25 | - name: spotless check (test project) 26 | run: cd .test && ./gradlew spotlessCheck 27 | 28 | - name: spotless check (root project) 29 | run: ./gradlew spotlessCheck 30 | 31 | - name: Generate tests for every solution 32 | run: cd .test && ./gradlew generateTests 33 | 34 | - name: Navigate to root project 35 | run: cd .test 36 | 37 | - name: Run generated solution tests 38 | run: ./gradlew test --tests "generated.com.igorwojda.*" 39 | 40 | - uses: actions/upload-artifact@v3 41 | with: 42 | name: unit-test-report 43 | path: ./**/build/reports/tests/ 44 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/decapitalizeconst/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.decapitalizeconst 2 | 3 | // Kotlin idiomatic solution 4 | private object Solution1 { 5 | private fun decapitalizeConst(str: String): String { 6 | val subsStringsList = str 7 | .split("_") 8 | .map { it.lowercase() } 9 | .map { it.replaceFirstChar { string -> string.uppercaseChar() } } 10 | 11 | return subsStringsList 12 | .joinToString("") 13 | .replaceFirstChar { 14 | it.lowercaseChar() 15 | } 16 | } 17 | } 18 | 19 | // Another Approach 20 | private object Solution2 { 21 | private fun decapitalizeConst(str: String): String? { 22 | val words = str.split("_").filter { it.isNotEmpty() } 23 | 24 | if (words.size == 1) return words.first().lowercase() 25 | 26 | return words.mapIndexed { index, word -> 27 | if (index == 0) { 28 | word.lowercase() 29 | } else { 30 | word.first().uppercase() + word.drop(1).lowercase() 31 | } 32 | }.joinToString(separator = "") 33 | } 34 | } 35 | 36 | private object KtLintWillNotComplain 37 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/pyramidgenerator/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.pyramidgenerator 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | fun generatePyramid(n: Int): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | 12 | @Test 13 | fun `pyramid n = 2`() { 14 | generatePyramid(2).also { 15 | it.size shouldBeEqualTo 2 16 | it[0] shouldBeEqualTo " # " 17 | it[1] shouldBeEqualTo "###" 18 | } 19 | } 20 | 21 | @Test 22 | fun `pyramid n = 3`() { 23 | generatePyramid(3).also { 24 | it.size shouldBeEqualTo 3 25 | it[0] shouldBeEqualTo " # " 26 | it[1] shouldBeEqualTo " ### " 27 | it[2] shouldBeEqualTo "#####" 28 | } 29 | } 30 | 31 | @Test 32 | fun `pyramid n = 4`() { 33 | generatePyramid(4).also { 34 | it.size shouldBeEqualTo 4 35 | it[0] shouldBeEqualTo " # " 36 | it[1] shouldBeEqualTo " ### " 37 | it[2] shouldBeEqualTo " ##### " 38 | it[3] shouldBeEqualTo "#######" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/isanagram/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.isanagram 2 | 3 | private object Solution1 { 4 | private fun isAnagram(str1: String, str2: String): Boolean { 5 | val a1 = str1.uppercase().filter { it.isLetter() }.groupBy { it } 6 | val a2 = str2.uppercase().filter { it.isLetter() }.groupBy { it } 7 | return a1 == a2 8 | } 9 | } 10 | 11 | private object Solution2 { 12 | private fun isAnagram(str1: String, str2: String): Boolean { 13 | return getCharFrequency(str1) == getCharFrequency(str2) 14 | } 15 | 16 | private fun getCharFrequency(str: String): Map> { 17 | return str.lowercase() 18 | .filter { it.isLetterOrDigit() } 19 | .groupBy { it } 20 | } 21 | } 22 | 23 | private object Solution3 { 24 | private fun isAnagram(str1: String, str2: String): Boolean { 25 | return getCharFrequency(str1) == getCharFrequency(str2) 26 | } 27 | 28 | private fun getCharFrequency(str: String): Map { 29 | return str.lowercase() 30 | .filter { it.isLetterOrDigit() } 31 | .groupingBy { it } 32 | .eachCount() 33 | } 34 | } 35 | 36 | private object KtLintWillNotComplain 37 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/getodd/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.getodd 2 | 3 | // Kotlin idiomatic solution 4 | private object Solution1 { 5 | private fun filterOdd(list: List): List { 6 | return list.filter { it % 2 == 1 } 7 | } 8 | } 9 | 10 | // Recursive solution 11 | private object Solution2 { 12 | private fun filterOdd(list: List): List { 13 | if (list.isEmpty()) { 14 | return list 15 | } 16 | 17 | return if (list.first() % 2 == 1) { 18 | mutableListOf(list.first()) + filterOdd(list.drop(1)) 19 | } else { 20 | filterOdd(list.drop(1)) 21 | } 22 | } 23 | } 24 | 25 | // Recursive solution with helper function 26 | private object Solution3 { 27 | private fun filterOdd(list: List): List { 28 | val result = mutableListOf() 29 | 30 | fun helper(list: List) { 31 | if (list.isEmpty()) { 32 | return 33 | } 34 | 35 | if (list.first() % 2 == 1) { 36 | result.add(list.first()) 37 | } 38 | 39 | helper(list.drop(1)) 40 | } 41 | 42 | helper(list) 43 | 44 | return result 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/ispalindrome/basic/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.ispalindrome.basic 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun isPalindrome(str: String): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | 12 | @Test 13 | fun `'aba' is a palindrome`() { 14 | isPalindrome("aba") shouldBeEqualTo true 15 | } 16 | 17 | @Test 18 | fun `' aba' is not a palindrome`() { 19 | isPalindrome(" aba") shouldBeEqualTo false 20 | } 21 | 22 | @Test 23 | fun `'aba ' is not a palindrome`() { 24 | isPalindrome("aba ") shouldBeEqualTo false 25 | } 26 | 27 | @Test 28 | fun `'greetings' is not a palindrome`() { 29 | isPalindrome("greetings") shouldBeEqualTo false 30 | } 31 | 32 | @Test 33 | fun `'1000000001' a palindrome`() { 34 | isPalindrome("1000000001") shouldBeEqualTo true 35 | } 36 | 37 | @Test 38 | fun `'Fish hsif' is not a palindrome`() { 39 | isPalindrome("Fish hsif") shouldBeEqualTo false 40 | } 41 | 42 | @Test 43 | fun `'pennep' a palindrome`() { 44 | isPalindrome("pennep") shouldBeEqualTo true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/formattrainroute/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.formattrainroute 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun formatTrainRoute(stations: List): String { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `formatTrainRoute list 'Luton'`() { 13 | formatTrainRoute(listOf("Luton")) shouldBeEqualTo "Train is calling at Luton" 14 | } 15 | 16 | @Test 17 | fun `formatTrainRoute list 'Luton', 'Harpenden'`() { 18 | formatTrainRoute(listOf("Luton", "Harpenden")) shouldBeEqualTo "Train is calling at Luton and Harpenden" 19 | } 20 | 21 | @Test 22 | fun `formatTrainRoute list 'Luton', 'Harpenden', 'London'`() { 23 | val list = listOf("Luton", "Harpenden", "London") 24 | formatTrainRoute(list) shouldBeEqualTo "Train is calling at Luton, Harpenden and London" 25 | } 26 | 27 | @Test 28 | fun `formatTrainRoute list 'Luton', 'Harpenden', 'St Albans', 'London'`() { 29 | val list = listOf("Luton", "Harpenden", "St Albans", "London") 30 | formatTrainRoute(list) shouldBeEqualTo "Train is calling at Luton, Harpenden, St Albans and London" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/range/containsrange/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.range.containsrange 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun containsRange(range1: IntRange, range2: IntRange): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `5-7 range contains 5-7`() { 13 | containsRange(5..7, 5..7) shouldBeEqualTo true 14 | } 15 | 16 | @Test 17 | fun `1-12 range contains 5-7`() { 18 | containsRange(1..12, 5..7) shouldBeEqualTo true 19 | } 20 | 21 | @Test 22 | fun `12-17 range contains 12-14`() { 23 | containsRange(12..17, 12..14) shouldBeEqualTo true 24 | } 25 | 26 | @Test 27 | fun `12-17 range contains 15-17`() { 28 | containsRange(12..17, 15..17) shouldBeEqualTo true 29 | } 30 | 31 | @Test 32 | fun `5-7 range contains 1-12`() { 33 | containsRange(5..7, 1..12) shouldBeEqualTo false 34 | } 35 | 36 | @Test 37 | fun `5-8 range contains 5-9`() { 38 | containsRange(5..8, 5..9) shouldBeEqualTo false 39 | } 40 | 41 | @Test 42 | fun `5-8 range contains 3-5`() { 43 | containsRange(5..8, 3..5) shouldBeEqualTo false 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/flatten/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.flatten 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | fun flatten(list: List<*>): List<*> { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `flatten test 1`() { 13 | flatten(listOf(1)) shouldBeEqualTo listOf(1) 14 | } 15 | 16 | @Test 17 | fun `flatten test 2`() { 18 | flatten(listOf(1, listOf(2))) shouldBeEqualTo listOf(1, 2) 19 | } 20 | 21 | @Test 22 | fun `flatter test 3`() { 23 | flatten(listOf(1, listOf(2, listOf(3), emptyList()))) shouldBeEqualTo listOf(1, 2, 3) 24 | } 25 | 26 | @Test 27 | fun `flatter test 4`() { 28 | flatten( 29 | listOf( 30 | 1, 31 | listOf(2, listOf(emptyList())), 32 | listOf(3), 33 | ), 34 | ) shouldBeEqualTo listOf(1, 2, 3) 35 | } 36 | 37 | @Test 38 | fun `flatter test 5`() { 39 | flatten( 40 | listOf( 41 | 1, 42 | listOf(2, listOf(3), listOf(4, listOf(listOf(5)))), 43 | ), 44 | ) shouldBeEqualTo listOf(1, 2, 3, 4, 5) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/maxsublistsum/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.maxsublistsum 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | import kotlin.math.max 6 | 7 | private fun maxSubListSum(list: List, numElements: Int): Int? { 8 | TODO("Add your solution here") 9 | } 10 | 11 | private fun max(i1: Int?, i2: Int?): Int? { 12 | return when { 13 | i1 != null && i2 != null -> max(i1, i2) 14 | i1 != null && i2 == null -> i1 15 | i1 == null && i2 != null -> i2 16 | else -> null 17 | } 18 | } 19 | 20 | private class Test { 21 | @Test 22 | fun `max sublist sum for list 4, 2, 7 and n 2 `() { 23 | maxSubListSum(listOf(4, 2, 7), 2) shouldBeEqualTo 9 24 | } 25 | 26 | @Test 27 | fun `max sublist sum for list 4, 2, 7, 5, 8, 9, 5, 1 and n 3 `() { 28 | maxSubListSum(listOf(4, 2, 7, 5, 8, 9, 5, 1), 3) shouldBeEqualTo 22 29 | } 30 | 31 | @Test 32 | fun `max sublist sum for list 1,2,5,2,8,1,5 and n 4 `() { 33 | maxSubListSum(listOf(1, 2, 5, 2, 8, 1, 5), 4) shouldBeEqualTo 17 34 | } 35 | 36 | @Test 37 | fun `max sublist sum for empty list and n 5 `() { 38 | maxSubListSum(emptyList(), 5) shouldBeEqualTo null 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/matrix/findrectangle/README.md: -------------------------------------------------------------------------------- 1 | # Find rectangle 2 | 3 | ## Instructions 4 | 5 | Image is represent as a simple 2D array where every pixel is a 1 or a 0. The image you get is known to have a single 6 | rectangle of 0s on a background of 1s. 7 | 8 | Write a function that takes in the image and returns list containing coordinates of top-left and bottom-right pixels 9 | represented as list of internees: 10 | 11 | [Challenge.kt](Challenge.kt) | [solution](Solution.kt) 12 | 13 | ## Examples 14 | 15 | Example 1 16 | 17 | ```kotlin 18 | val image = listOf( 19 | listOf(1, 1, 0, 0, 0, 1), 20 | listOf(1, 1, 0, 0, 0, 1), 21 | listOf(1, 1, 1, 1, 1, 1), 22 | listOf(1, 1, 1, 1, 1, 1) 23 | ) 24 | 25 | findRectangle(image) // [0, 2, 1, 4] 26 | 27 | ``` 28 | 29 | Example 2 30 | 31 | ```kotlin 32 | val image = listOf( 33 | listOf(1, 0, 0, 1, 1, 1), 34 | listOf(1, 0, 0, 1, 1, 1), 35 | listOf(1, 0, 0, 1, 1, 1) 36 | ) 37 | 38 | findRectangle(image) // [0, 1, 2, 2] 39 | 40 | ``` 41 | 42 | Example 3 43 | 44 | ```kotlin 45 | val image = listOf( 46 | listOf(1, 1, 1, 1, 1), 47 | listOf(1, 1, 1, 0, 0), 48 | listOf(1, 1, 1, 0, 0), 49 | listOf(1, 1, 1, 0, 0), 50 | listOf(1, 1, 1, 0, 0) 51 | ) 52 | 53 | findRectangle(image) // [1, 3, 4, 4] 54 | 55 | ``` 56 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/caesarcipher/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.caesarcipher 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun encodeCaesarCipher(str: String, shift: Int): String { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `'abc' with shift 1 return 'bcd'`() { 13 | encodeCaesarCipher("abc", 1) shouldBeEqualTo "bcd" 14 | } 15 | 16 | @Test 17 | fun `'abcdefghijklmnopqrstuvwxyz' shift 1 returns 'bcdefghijklmnopqrstuvwxyza'`() { 18 | encodeCaesarCipher( 19 | "abcdefghijklmnopqrstuvwxyz", 20 | 1, 21 | ) shouldBeEqualTo "bcdefghijklmnopqrstuvwxyza" 22 | } 23 | 24 | @Test 25 | fun `'abcdefghijklmnopqrstuvwxyz' shift 7 returns 'hijklmnopqrstuvwxyzabcdefg'`() { 26 | encodeCaesarCipher( 27 | "abcdefghijklmnopqrstuvwxyz", 28 | 7, 29 | ) shouldBeEqualTo "hijklmnopqrstuvwxyzabcdefg" 30 | } 31 | 32 | @Test 33 | fun `'abcdefghijklmnopqrstuvwxyz' shift 50 returns 'yzabcdefghijklmnopqrstuvwx'`() { 34 | encodeCaesarCipher( 35 | "abcdefghijklmnopqrstuvwxyz", 36 | 50, 37 | ) shouldBeEqualTo "yzabcdefghijklmnopqrstuvwx" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/tree/binarytree/insert/README.md: -------------------------------------------------------------------------------- 1 | # Binary Search Tree (insert) 2 | 3 | ## Instructions 4 | 5 | Having binary node (`data`, `left`, `right`) we need to implement two methods 6 | [binary search tree](https://en.wikipedia.org/wiki/Binary_search_tree) methods: 7 | - `insert` - accepts an argument `data`, then create an insert a new node at the 8 | appropriate location in the tree. 9 | - `contains` - accepts a `data` argument and return the `true` if node with given value already exists in the tree, otherwise returns `false` 10 | 11 | Requirements that are always true for any given node in `Binary Search Tree`: 12 | - parent node value is always 13 | greater then value of *all* nodes in the left subtree 14 | and less than value of *all* nodes in the right subtree 15 | - left node value is also a valid BST 16 | - right node value is also a valid BST 17 | 18 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 19 | 20 | ## Examples 21 | 22 | Example 1 23 | 24 | ```kotlin 25 | val tree = Node(1) 26 | tree.insert(4) 27 | tree.insert(2) 28 | 29 | // Result 30 | // 31 | // 1 32 | // / \ 33 | // 2 4 34 | ``` 35 | 36 | Example 2 37 | 38 | ```kotlin 39 | val tree = Node(1) 40 | tree.insert(4) 41 | tree.insert(2) 42 | tree.contains(4) // true 43 | tree.contains(99) // false 44 | ``` 45 | 46 | -------------------------------------------------------------------------------- /.test/README.md: -------------------------------------------------------------------------------- 1 | # Test Project Consistency And The Solutions Correctness 2 | 3 | This subproject is designed to verify the root project. Checks are running with every PR. 4 | 5 | ## Solution Checks 6 | 7 | Verify correctness of the provided solutions. 8 | 9 | Every coding challenge in this repo consists of a container that has tests and 10 | empty placeholder for a user-coded solution. Since the placeholder is non-implemented method 11 | all tests in the root project will fail by design. This subproject allows to generate a test suite for each challenge 12 | by combining challenge container (`Challenge.kt` file) with every solution present in the `Solution.kt` file. 13 | 14 | To generate tests go into `.test` subproject and run the `generateTests` command: 15 | 16 | ```shell 17 | cd .test && ./gradlew generateTests 18 | ```` 19 | 20 | Generated tests will be placed in the `src/test/kotlin/generated` directory (root project). 21 | 22 | To run generated tests use `./gradlew test --tests "generated.com.igorwojda.*"` (root project). 23 | 24 | ## Consistency Checks 25 | 26 | Verify consistency across various challenges such as file naming and file structure. 27 | 28 | To run checks go into `.test` subproject and run the `test` command: 29 | 30 | To run tests use `cd .test && ./gradlew test` command. 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/circularcheck/README.md: -------------------------------------------------------------------------------- 1 | # Circular singly linked list 2 | 3 | ## Nice to solve before 4 | 5 | - [Singly linked List](../base/README.md) 6 | 7 | ## Instructions 8 | 9 | Given a linked list, return true if the list is circular, false if it is not. 10 | 11 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 12 | 13 | ## Examples 14 | 15 | Example 1 16 | 17 | ```kotlin 18 | val l = new SinglyLinkedList () 19 | val a = new Node ('a') 20 | val b = new Node ('b') 21 | val c = new Node ('c') 22 | l.head = a 23 | a.next = b 24 | b.next = c 25 | c.next = b 26 | circular(l) // true 27 | ``` 28 | 29 | Example 2 30 | 31 | ```kotlin 32 | val l = new List () 33 | val a = new Node ('a') 34 | circular(l) // false 35 | ``` 36 | 37 | ## Hints 38 | 39 |
40 | Hint 1 41 | We should use more then one variable to store values that are retrieved during iteration (two pointer solution) 42 |
43 | 44 |
45 | Hint 2 46 | Name of these variables should be `slow` and `fast` 47 |
48 | 49 |
50 | Hint 3 51 | Assign next node to `slow` variable in every iteration 52 |
53 | 54 |
55 | Hint 4 56 | Assign next node of next node to `fast` variable in every iteration 57 |
58 | 59 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/largestelements/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.largestelements 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | import java.util.* 6 | 7 | private fun largestElements(list: List, count: Int): List { 8 | if (list.size <= count) { 9 | return list 10 | } 11 | 12 | val priorityQueue = PriorityQueue() 13 | 14 | repeat(count) { 15 | priorityQueue.add(list[it]) 16 | } 17 | 18 | list 19 | .drop(count) 20 | .forEach { 21 | if (it > priorityQueue.peek()) { 22 | priorityQueue.poll() 23 | priorityQueue.add(it) 24 | } 25 | } 26 | 27 | return priorityQueue.toList() 28 | } 29 | 30 | private class Test { 31 | @Test 32 | fun `3 largest elements`() { 33 | val list = listOf(5, 1, 3) 34 | 35 | largestElements(list, 3) shouldBeEqualTo listOf(5, 1, 3) 36 | } 37 | 38 | @Test 39 | fun `2 largest elements`() { 40 | val list = listOf(5, 1, 3) 41 | 42 | largestElements(list, 2) shouldBeEqualTo listOf(3, 5) 43 | } 44 | 45 | @Test 46 | fun `1 largest element`() { 47 | val list = listOf(5, 1, 3) 48 | 49 | largestElements(list, 1) shouldBeEqualTo listOf(5) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/mergesort/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.sort.mergesort 2 | 3 | // Time complexity (Best): Ω(n log(n)) 4 | // Time complexity (Average): Θ(n log(n)) 5 | // Time complexity (Worst): O(n log(n)) 6 | // Space complexity: O(n) 7 | private object Solution1 { 8 | private fun mergeSort(list: List): List { 9 | if (list.size <= 1) return list 10 | 11 | // Take two sorted lists and merge them together into one sorted list 12 | fun merge(left: MutableList, right: MutableList): MutableList { 13 | val result = mutableListOf() 14 | 15 | while (left.isNotEmpty() && right.isNotEmpty()) { 16 | if (left.first() < right.first()) { 17 | result.add(left.removeAt(0)) 18 | } else { 19 | result.add(right.removeAt(0)) 20 | } 21 | } 22 | 23 | result.addAll(left) 24 | result.addAll(right) 25 | 26 | return result 27 | } 28 | 29 | val mid = list.size / 2 30 | val left = mergeSort(list.subList(0, mid)).toMutableList() 31 | val right = mergeSort(list.subList(mid, list.size)).toMutableList() 32 | return merge(left, right) 33 | } 34 | } 35 | 36 | private object KtLintWillNotComplain 37 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/addupto/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.addupto 2 | 3 | // Kotlin idiomatic solution 4 | private object Solution1 { 5 | private fun addUpTo(n: Int): Int { 6 | return (1..n).sum() 7 | } 8 | } 9 | 10 | // Kotlin idiomatic solution 11 | private object Solution2 { 12 | private fun addUpTo(n: Int): Int { 13 | return (0..n).fold(0) { accumulated, current -> accumulated + current } 14 | } 15 | } 16 | 17 | // Recursive solution 18 | private object Solution3 { 19 | private fun addUpTo(n: Int): Int { 20 | if (n == 1) { 21 | return 1 22 | } 23 | 24 | return n + addUpTo(n - 1) 25 | } 26 | } 27 | 28 | // Time Complexity: O(1) 29 | // Mathematical formula 30 | private object Solution4 { 31 | private fun addUpTo(n: Int): Int { 32 | return n * (n + 1) / 2 33 | } 34 | } 35 | 36 | // Time Complexity: O(n) 37 | // Iterative solution 38 | private object Solution5 { 39 | private fun addUpTo(n: Int): Int { 40 | var total = 0 41 | 42 | (0..n).forEach { total += it } 43 | 44 | return total 45 | } 46 | } 47 | 48 | // Iterative solution 49 | private object Solution6 { 50 | private fun addUpTo(n: Int): Int { 51 | var total = 0 52 | repeat(n + 1) { total += it } 53 | return total 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sumzero/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.sumzero 2 | 3 | private object Solution1 { 4 | // Optimal solution using double pointer. 5 | // Time complexity: O(n) 6 | fun sumZero(list: List): Pair? { 7 | if (list.isEmpty()) { 8 | return null 9 | } 10 | 11 | var pointer1 = 0 12 | var pointer2 = list.lastIndex 13 | 14 | // declare loop 15 | while (pointer1 != pointer2) { 16 | val element1 = list[pointer1] 17 | val element2 = list[pointer2] 18 | val sum = element1 + element2 19 | 20 | when { 21 | sum == 0 -> return Pair(element1, element2) 22 | sum > 0 -> pointer2-- 23 | sum < 0 -> pointer1++ 24 | } 25 | } 26 | 27 | return null 28 | } 29 | } 30 | 31 | // Naive solution using nested loop 32 | // Time complexity: O(n^2) 33 | private object Solution2 { 34 | fun sumZero(list: List): Pair? { 35 | list.forEachIndexed { index, element1 -> 36 | (index..list.lastIndex).forEach { index2 -> 37 | if (element1 + list[index2] == 0) { 38 | return element1 to list[index2] 39 | } 40 | } 41 | } 42 | 43 | return null 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/tree/binarytree/validate/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.tree.binarytree.validate 2 | 3 | private object Solution1 { 4 | private fun isValidSearchBinaryTree(node: Node, min: Int? = null, max: Int? = null): Boolean { 5 | if (min != null && node.data < min) { 6 | return false 7 | } 8 | if (max != null && node.data > max) { 9 | return false 10 | } 11 | 12 | return node.left?.let { isValidSearchBinaryTree(it, min, node.data) } ?: true && 13 | node.right?.let { isValidSearchBinaryTree(it, node.data, max) } ?: true 14 | } 15 | 16 | private data class Node>( 17 | var data: E, 18 | var left: Node? = null, 19 | var right: Node? = null, 20 | ) { 21 | fun insert(e: E) { 22 | if (e < data) { // left node 23 | if (left == null) { 24 | left = Node(e) 25 | } else { 26 | left?.insert(e) 27 | } 28 | } else if (e > data) { // right node 29 | if (right == null) { 30 | right = Node(e) 31 | } else { 32 | right?.insert(e) 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | private object KtLintWillNotComplain 40 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/countdown/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.countdown 2 | 3 | // Kotlin idiomatic solution 4 | private object Solution1 { 5 | private fun countDown(n: Int): List { 6 | // Create a range and convert it to a list 7 | return (n downTo 0).toList() 8 | } 9 | } 10 | 11 | // Recursive solution 12 | private object Solution2 { 13 | private fun countDown(n: Int): List { 14 | if (n == 0) { 15 | return listOf(0) 16 | } 17 | 18 | return mutableListOf(n).also { it.addAll(countDown(n - 1)) } 19 | } 20 | } 21 | 22 | // Recursive solution with helper function 23 | private object Solution3 { 24 | private fun countDown(n: Int): List { 25 | // We want to keep return type unchanged while implementing recursive solution, so we will 26 | // use helper method defied inside countDown function. 27 | fun helper(n: Int): MutableList { 28 | if (n == 0) { 29 | return mutableListOf(0) 30 | } 31 | 32 | return mutableListOf(n).also { it.addAll(countDown(n - 1)) } 33 | } 34 | 35 | return helper(n).toList() 36 | } 37 | } 38 | 39 | // Kotlin idiomatic solution 40 | private object Solution4 { 41 | private fun countDown(n: Int): List { 42 | return List(n + 1) { n - it } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/matrix/spiralmatrixgenerator/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.matrix.spiralmatrixgenerator 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun generateSpiralMatrix(n: Int): List> { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `generateSpiralMatrix generates a 2x2 matrix`() { 13 | val matrix = generateSpiralMatrix(2) 14 | matrix.size shouldBeEqualTo 2 15 | matrix[0] shouldBeEqualTo listOf(1, 2) 16 | matrix[1] shouldBeEqualTo listOf(4, 3) 17 | } 18 | 19 | @Test 20 | fun `generateSpiralMatrix generates a 3x3 matrix`() { 21 | val matrix = generateSpiralMatrix(3) 22 | matrix.size shouldBeEqualTo 3 23 | matrix[0] shouldBeEqualTo listOf(1, 2, 3) 24 | matrix[1] shouldBeEqualTo listOf(8, 9, 4) 25 | matrix[2] shouldBeEqualTo listOf(7, 6, 5) 26 | } 27 | 28 | @Test 29 | fun `generateSpiralMatrix generates a 4x4 matrix`() { 30 | val matrix = generateSpiralMatrix(4) 31 | matrix.size shouldBeEqualTo 4 32 | matrix[0] shouldBeEqualTo listOf(1, 2, 3, 4) 33 | matrix[1] shouldBeEqualTo listOf(12, 13, 14, 5) 34 | matrix[2] shouldBeEqualTo listOf(11, 16, 15, 6) 35 | matrix[3] shouldBeEqualTo listOf(10, 9, 8, 7) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/subtract/README.md: -------------------------------------------------------------------------------- 1 | # List subtract 2 | 3 | ## Nice to solve before 4 | 5 | - [Is anagram](../../string/isanagram/README.md) 6 | - [Square equals](../squareequal/README.md) 7 | - [Digit frequency](../../integer/digitfrequency/README.md) 8 | - [Max occurring char](../../string/maxoccurringchar/README.md) 9 | - [Get duplicated arguments](../../string/getduplicatedarguments/README.md) 10 | 11 | ## Instructions 12 | 13 | Given two lists implement a function which will determine witch elements from first list have to be subtracted (removed) 14 | to obtain second list (what elements needs to be removed from first list so it it would be equal to second list). There 15 | may be more than one element with the same value. For simplicity we assume that input is always correct (it is always 16 | possible to remove values from first list to form second list). 17 | 18 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 19 | 20 | ## Examples 21 | 22 | ```kotlin 23 | getSubtraction(listOf("A", "B", "C"), listOf("A")) // "B", "C" 24 | 25 | getSubtraction(listOf("A", "B", "C"), listOf("A", "B")) // "C" 26 | 27 | getSubtraction(listOf("A", "B", "C", "A"), listOf("A", "B")) // "C", "A" 28 | 29 | getSubtraction(listOf("A", "B", "C"), listOf("A", "B", "C")) // nothing 30 | ``` 31 | 32 | ## Hints 33 | 34 |
35 | Hint 1 36 | Use frequency counter. 37 |
38 | 39 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/cache/lru/Tests.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.cache.lru 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | class Tests { 7 | // Easily switch between a known solution and Challenge code 8 | val classUnderTest: (Int)->LRUCache = ::LRUCacheImpl // or SolutionN::LRUCacheImpl 9 | 10 | @Test 11 | fun `lru cache is empty after creation`() { 12 | val cache = classUnderTest(3) 13 | 14 | cache.size shouldBeEqualTo 0 15 | } 16 | 17 | @Test 18 | fun `oldest value is not removed from cache after capacity is exceeded`() { 19 | val cache = classUnderTest(2) 20 | 21 | cache.put(1, "Value-1") 22 | cache.put(2, "Value-2") 23 | cache.put(3, "Value-3") 24 | 25 | cache.size shouldBeEqualTo 2 26 | cache.get(1) shouldBeEqualTo null 27 | cache.get(2) shouldBeEqualTo "Value-2" 28 | cache.get(3) shouldBeEqualTo "Value-3" 29 | } 30 | 31 | @Test 32 | fun `retrieved element becomes most recently used`() { 33 | val cache = classUnderTest(2) 34 | cache.put(1, "Value-1") 35 | cache.put(2, "Value-2") 36 | cache.get(1) 37 | cache.put(3, "Value-3") 38 | 39 | cache.get(1) shouldBeEqualTo "Value-1" 40 | cache.get(2) shouldBeEqualTo null 41 | cache.get(3) shouldBeEqualTo "Value-3" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/search/binarysearch/README.md: -------------------------------------------------------------------------------- 1 | # Binary search 2 | 3 | ## Instructions 4 | 5 | Given list of **sorted** elements and a element return index of that element in the list or `-1` if element was not 6 | found. Use 7 | [binary search](https://www.youtube.com/watch?v=T2sFYY-fT5o) algorithm. 8 | 9 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 10 | 11 | ## Algorithm 12 | We ignore half of the elements after each loop. 13 | 14 | - Compare element with the middle element. 15 | - If element matches with middle element, we return the middle element index. 16 | - Else If element is greater than the mid element, then element can only lie in right half sub-list after the mid 17 | element. So we deal only with right half. 18 | - Else (x is smaller) deal only with the left half. 19 | 20 | ## Examples 21 | 22 | Example 1 23 | 24 | Search for `C` in `[A, B, C, D, E, F, G, H, I, J, K, L, M, O, P]` 25 | 26 | ```kotlin 27 | 28 | [A, B, C, D, E, F, G, H, I, J, K, L, M, O, P] // (left = A, middle = H, right = P) 29 | [A, B, C, D, E, F, G, H, I, J, K, L, M, O, P] // (left = A, middle = D, right = G) 30 | [A, B, C, D, E, F, G, H, I, J, K, L, M, O, P] // (left = A, middle = C, right = F) 31 | ``` 32 | 33 | Example 2 34 | 35 | ```kotlin 36 | binarySearch(listOf('A', 'B', 'C'), 'A') // 0 37 | 38 | binarySearch(listOf('A', 'B', 'C'), 'B') // 1 39 | 40 | binarySearch(listOf('A', 'B', 'C'), 'H') // -1 41 | ``` 42 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fibonacci/basic/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.fibonacci.basic 2 | 3 | // iterative solution 4 | private object Solution1 { 5 | private fun fibonacci(n: Int): Int { 6 | if (n < 2) { 7 | return n 8 | } 9 | 10 | var first = 0 11 | var second = 1 12 | var current = 0 13 | 14 | (2..n).forEach { 15 | current = first + second 16 | first = second 17 | second = current 18 | } 19 | 20 | return current 21 | } 22 | } 23 | 24 | // iterative solution with temporary list (not efficient) 25 | private object Solution2 { 26 | private fun fibonacci(n: Int): Int { 27 | val list = mutableListOf(0, 1) 28 | 29 | for (it in list.size..n) { 30 | list.add(list.takeLast(2).sum()) 31 | } 32 | 33 | return list[n] 34 | } 35 | } 36 | 37 | // recursive solution 38 | private object Solution3 { 39 | private fun fibonacci(n: Int): Int { 40 | return when (n) { 41 | 0 -> 0 42 | 1 -> 1 43 | else -> fibonacci(n - 1) + fibonacci(n - 2) 44 | } 45 | } 46 | } 47 | 48 | // recursive solution 49 | private object Solution4 { 50 | private fun fibonacci(n: Int): Int { 51 | if (n < 2) { 52 | return n 53 | } 54 | 55 | return fibonacci(n - 1) + fibonacci(n - 2) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/addnumbers/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.linkedlist.singly.addnumbers 2 | 3 | object Solution1 { 4 | private fun addTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode? { 5 | val n1 = getNumber(l1) 6 | val n2 = getNumber(l2) 7 | 8 | val result = n1 + n2 9 | 10 | return getList(result) 11 | } 12 | 13 | private fun getNumber(l1: ListNode?): Int { 14 | var node = l1 15 | var numberStr = "" 16 | 17 | while (node != null) { 18 | numberStr += node.data 19 | node = node.next 20 | } 21 | 22 | return numberStr.reversed().toInt() 23 | } 24 | 25 | private fun getList(int: Int): ListNode? { 26 | val intStr = int.toString().reversed() 27 | var list: ListNode? = null 28 | var lastListNode: ListNode? = null 29 | 30 | intStr.forEach { 31 | val node = ListNode(it.digitToInt()) 32 | 33 | if (list == null) { 34 | list = node 35 | lastListNode = node 36 | } else { 37 | lastListNode?.next = node 38 | lastListNode = node 39 | } 40 | } 41 | 42 | return list 43 | } 44 | 45 | private data class ListNode( 46 | var data: Int, 47 | var next: ListNode? = null, 48 | ) 49 | } 50 | 51 | private object KtLintWillNotComplain 52 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/fromlast/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.linkedlist.singly.fromlast 2 | 3 | import com.igorwojda.linkedlist.singly.base.Solution1.Node 4 | import com.igorwojda.linkedlist.singly.base.Solution1.SinglyLinkedList 5 | import org.amshove.kluent.shouldBeEqualTo 6 | import org.junit.jupiter.api.Test 7 | 8 | private fun fromLast(list: SinglyLinkedList, endIndex: Int): Node? { 9 | TODO("Add your solution here") 10 | } 11 | 12 | private class Test { 13 | @Test 14 | fun `returns the node 0 elements from the end`() { 15 | SinglyLinkedList().apply { 16 | insertLast('a') 17 | insertLast('b') 18 | 19 | fromLast(this, 0)?.data shouldBeEqualTo 'b' 20 | } 21 | } 22 | 23 | @Test 24 | fun `returns the node 1 elements from the end`() { 25 | SinglyLinkedList().apply { 26 | insertLast('a') 27 | insertLast('b') 28 | 29 | fromLast(this, 1)?.data shouldBeEqualTo 'a' 30 | } 31 | } 32 | 33 | @Test 34 | fun `fromLast returns the node 3 elements from the end`() { 35 | SinglyLinkedList().apply { 36 | insertLast('a') 37 | insertLast('b') 38 | insertLast('c') 39 | insertLast('d') 40 | insertLast('e') 41 | 42 | fromLast(this, 3)?.data shouldBeEqualTo 'b' 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/decapitalizeconst/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.decapitalizeconst 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun decapitalizeConst(str: String): String { 7 | val subsStringsList = str 8 | .split("_") 9 | .map { it.lowercase() } 10 | .map { it.replaceFirstChar { string -> string.uppercaseChar() } } 11 | 12 | return subsStringsList 13 | .joinToString("") 14 | .replaceFirstChar { 15 | it.lowercaseChar() 16 | } 17 | } 18 | 19 | private class Test { 20 | @Test 21 | fun `'FOOBAR' return foobar`() { 22 | decapitalizeConst("FOOBAR") shouldBeEqualTo "foobar" 23 | } 24 | 25 | @Test 26 | fun `'FOO_BAR' return 'fooBar'`() { 27 | decapitalizeConst("FOO_BAR") shouldBeEqualTo "fooBar" 28 | } 29 | 30 | @Test 31 | fun `'FOO_BAR_BAZ' return 'fooBarBaz'`() { 32 | decapitalizeConst("FOO_BAR_BAZ") shouldBeEqualTo "fooBarBaz" 33 | } 34 | 35 | @Test 36 | fun `'__F_BAR' return 'fBar'`() { 37 | decapitalizeConst("__F_BAR") shouldBeEqualTo "fBar" 38 | } 39 | 40 | @Test 41 | fun `'F_BAR' return 'fBar'`() { 42 | decapitalizeConst("F_BAR") shouldBeEqualTo "fBar" 43 | } 44 | 45 | @Test 46 | fun `empty string return empty string`() { 47 | decapitalizeConst("") shouldBeEqualTo "" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/chunk/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.listchunk 2 | 3 | private object Solution1 { 4 | private fun chunk(list: List, size: Int): List> { 5 | val chunks = mutableListOf>() 6 | 7 | list.forEach { 8 | if (chunks.size == 0 || chunks.last().size == size) { 9 | chunks.add(mutableListOf(it)) 10 | } else { 11 | chunks.last().add(it) 12 | } 13 | } 14 | 15 | return chunks 16 | } 17 | } 18 | 19 | private object Solution2 { 20 | private fun chunk(list: List, size: Int): List> { 21 | val chunks = mutableListOf>() 22 | 23 | for (i in 0..list.lastIndex step size) { 24 | val rightIndex = if (i + size < list.size) i + size else list.size 25 | chunks.add(list.subList(i, rightIndex)) 26 | } 27 | 28 | return chunks 29 | } 30 | } 31 | 32 | private object Solution3 { 33 | private fun chunk(list: List, size: Int): List> { 34 | var index = 0 35 | val chunks = mutableListOf>() 36 | 37 | while (index <= list.lastIndex) { 38 | val rightIndex = if (index + size < list.size) index + size else list.size 39 | chunks.add(list.subList(index, rightIndex)) 40 | 41 | index += size 42 | } 43 | 44 | return chunks 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/coins/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.coins 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun getCoins(amount: Int, coins: List): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `4 wys`() { 13 | val actual: Int = getCoins(4, listOf(1, 2, 3)) 14 | val expected = 4 15 | actual shouldBeEqualTo expected 16 | } 17 | 18 | @Test 19 | fun `one way`() { 20 | val actual: Int = getCoins(0, listOf(1, 2)) 21 | val expected = 1 22 | actual shouldBeEqualTo expected 23 | } 24 | 25 | @Test 26 | fun `no coins returns 0`() { 27 | val actual: Int = getCoins(1, listOf()) 28 | val expected = 0 29 | actual shouldBeEqualTo expected 30 | } 31 | 32 | @Test 33 | fun `big coins`() { 34 | val actual: Int = getCoins(5, listOf(25, 50)) 35 | val expected = 0 36 | actual shouldBeEqualTo expected 37 | } 38 | 39 | @Test 40 | fun `big amount`() { 41 | val actual: Int = getCoins(50, listOf(5, 10)) 42 | val expected = 6 43 | actual shouldBeEqualTo expected 44 | } 45 | 46 | @Test 47 | fun `a lot of change`() { 48 | val actual: Int = getCoins(100, listOf(1, 5, 10, 25, 50)) 49 | val expected = 292 50 | actual shouldBeEqualTo expected 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/queue/basic/README.md: -------------------------------------------------------------------------------- 1 | # Queue 2 | 3 | ## Nice to solve before 4 | 5 | - [Stack](../../stack/basic/README.md) 6 | 7 | ## Instructions 8 | 9 | Implement a [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) data structure. Adding to the queue should store an element until it is removed. First element added to a queue will be the first that 10 | is removed (FIFO). The queue should be a 11 | class with methods: 12 | - `add` method - adds element to a queue (enqueue the element) 13 | - `remove` method - removes the element from a queue (enqueue the element) 14 | - `peek` method - returns last element (the one that should be returned) without removing it from the queue 15 | - `isEmpty` method - return `true` if queue is empty, otherwise return `false` 16 | 17 | The queue can be implemented in few different ways by using different underlying data structures. Implement each of 18 | them: 19 | - List 20 | - Linked list 21 | - Two Stacks 22 | 23 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 24 | 25 | ## Examples 26 | 27 | Example 1 28 | 29 | ```kotlin 30 | val q = Queue() 31 | q.add(1) 32 | q.remove() // 1 33 | q.remove() // null 34 | ``` 35 | 36 | Example 2 37 | 38 | ```kotlin 39 | val q = Queue() 40 | q.isEmpty() // true 41 | q.add('A') 42 | q.isEmpty() // false 43 | q.add('B') 44 | q.add('C') 45 | q.remove() // A 46 | q.peek() // A 47 | q.peek() // A 48 | q.remove() // B 49 | q.remove() // C 50 | q.remove() // null 51 | ``` 52 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/squareequal/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.squareequal 2 | 3 | private object Solution1 { 4 | // Time complexity: O(n) 5 | // Create two frequency map for each list and compare them 6 | private fun squareEquals(list: List, squared: List): Boolean { 7 | if (list.size != squared.size) { 8 | return false 9 | } 10 | 11 | val frequencyCounter1 = list.map { it * it }.groupBy { it } 12 | 13 | val frequencyCounter2 = squared.groupBy { it } 14 | 15 | return frequencyCounter1 == frequencyCounter2 16 | } 17 | } 18 | 19 | private object Solution2 { 20 | // Time complexity: O(n^2) 21 | // Loop through first list and look for value square in the second list. If square if found 22 | // remove it from second list to make sure that item frequency match. 23 | private fun squareEquals(list: List, squared: List): Boolean { 24 | val mutableList2 = squared.toMutableList() 25 | 26 | if (list.size != squared.size) { 27 | return false 28 | } 29 | 30 | list.forEach { 31 | // under the hood 'indexOf' iterates through entire list (it's like nested loop) 32 | val index = mutableList2.indexOf(it * it) 33 | 34 | if (index == -1) { 35 | return false 36 | } 37 | 38 | mutableList2.removeAt(index) 39 | } 40 | 41 | return true 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/countupanddown/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.countupanddown 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun countUpAndDown(n: Int): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `count up and down 0`() { 13 | countUpAndDown(0) shouldBeEqualTo listOf(0) 14 | } 15 | 16 | @Test 17 | fun `count up and down 1`() { 18 | countUpAndDown(1) shouldBeEqualTo listOf(0, 1, 0) 19 | } 20 | 21 | @Test 22 | fun `count up and down 2`() { 23 | countUpAndDown(2) shouldBeEqualTo listOf(0, 1, 2, 1, 0) 24 | } 25 | 26 | @Test 27 | fun `count up and down 3`() { 28 | countUpAndDown(3) shouldBeEqualTo listOf(0, 1, 2, 3, 2, 1, 0) 29 | } 30 | 31 | @Test 32 | fun `count up and down 4`() { 33 | countUpAndDown(4) shouldBeEqualTo listOf(0, 1, 2, 3, 4, 3, 2, 1, 0) 34 | } 35 | 36 | @Test 37 | fun `count up and down 9`() { 38 | countUpAndDown(9) shouldBeEqualTo listOf( 39 | 0, 40 | 1, 41 | 2, 42 | 3, 43 | 4, 44 | 5, 45 | 6, 46 | 7, 47 | 8, 48 | 9, 49 | 8, 50 | 7, 51 | 6, 52 | 5, 53 | 4, 54 | 3, 55 | 2, 56 | 1, 57 | 0, 58 | ) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/chunk/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.listchunk 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun chunk(list: List, size: Int): List> { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `chunk divides an list of 10 elements with chunk size 2`() { 13 | val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 14 | 15 | chunk(list, 2) shouldBeEqualTo listOf( 16 | listOf(1, 2), 17 | listOf(3, 4), 18 | listOf(5, 6), 19 | listOf(7, 8), 20 | listOf(9, 10), 21 | ) 22 | } 23 | 24 | @Test 25 | fun `chunk divides an list of 3 elements with chunk size 1`() { 26 | val list = listOf(1, 2, 3) 27 | chunk(list, 1) shouldBeEqualTo listOf(listOf(1), listOf(2), listOf(3)) 28 | } 29 | 30 | @Test 31 | fun `chunk divides an list of 5 elements with chunk size 3`() { 32 | val list = listOf(1, 2, 3, 4, 5) 33 | chunk(list, 3) shouldBeEqualTo listOf(listOf(1, 2, 3), listOf(4, 5)) 34 | } 35 | 36 | @Test 37 | fun `chunk divides an list of 13 elements with chunk size 5`() { 38 | val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) 39 | chunk(list, 5) shouldBeEqualTo listOf( 40 | listOf(1, 2, 3, 4, 5), 41 | listOf(6, 7, 8, 9, 10), 42 | listOf(11, 12, 13), 43 | ) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/medianoftwosorted/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.medianoftwosorted 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | fun medianOfSortedLists(list1: List, list2: List): Double { 7 | val mergedList = list1 8 | .plus(list2) 9 | .sorted() 10 | 11 | val median = if (mergedList.size % 2 != 0) { 12 | mergedList[mergedList.size / 2].toDouble() 13 | } else { 14 | (mergedList[mergedList.size / 2].toDouble() + mergedList[mergedList.size / 2 - 1].toDouble()) / 2 15 | } 16 | 17 | return median 18 | } 19 | 20 | private class Test { 21 | @Test 22 | fun `median of sorted lists 1, 3 and 2 returns 2,0`() { 23 | medianOfSortedLists(listOf(1, 3), listOf(2)) shouldBeEqualTo 2.0 24 | } 25 | 26 | @Test 27 | fun `median of sorted lists 1, 3 and 2 returns 2,5`() { 28 | medianOfSortedLists(listOf(1, 2), listOf(3, 4)) shouldBeEqualTo 2.5 29 | } 30 | 31 | @Test 32 | fun `median of sorted lists 2 and 1, 3 returns 2,0`() { 33 | medianOfSortedLists(listOf(2), listOf(1, 3)) shouldBeEqualTo 2.0 34 | } 35 | 36 | @Test 37 | fun `median of sorted lists 1, 3, 4 and 2 returns 3,5`() { 38 | medianOfSortedLists(listOf(1, 5, 7), listOf(2)) shouldBeEqualTo 3.5 39 | } 40 | 41 | @Test 42 | fun `median of sorted lists 2 and 1, 3, 4 returns 4,0`() { 43 | medianOfSortedLists(listOf(2), listOf(1, 6, 7)) shouldBeEqualTo 4.0 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/pairaverage/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.pairaverage 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | fun hasAverage(list: List, average: Double): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | inline fun MutableMap.incrementExisting(key: K, value: V) { 11 | put(key, value) 12 | } 13 | 14 | private class Test { 15 | @Test 16 | fun `empty list return false`() { 17 | hasAverage(listOf(), 1.0) shouldBeEqualTo false 18 | } 19 | 20 | @Test 21 | fun `list size 1 return false`() { 22 | hasAverage(listOf(1), 1.0) shouldBeEqualTo false 23 | } 24 | 25 | @Test 26 | fun `list 3, 5 should with average 5,5 return true`() { 27 | hasAverage(listOf(3, 5), 5.5) shouldBeEqualTo false 28 | } 29 | 30 | @Test 31 | fun `list 3, 4, 7, 9 should with average 6,5 return true`() { 32 | hasAverage(listOf(3, 4, 7, 9), 6.5) shouldBeEqualTo true 33 | } 34 | 35 | @Test 36 | fun `list 3, 5 should with average 2,7 return true`() { 37 | hasAverage(listOf(3, 5), 2.7) shouldBeEqualTo false 38 | } 39 | 40 | @Test 41 | fun `list 3, 5, 9, 7, 11, 14 should with average 8,0 return true`() { 42 | hasAverage(listOf(3, 5, 9, 7, 11, 14), 8.0) shouldBeEqualTo true 43 | } 44 | 45 | @Test 46 | fun `list 3, 7, 5 should with average 3,5 return true`() { 47 | hasAverage(listOf(3, 5, 7), 3.5) shouldBeEqualTo false 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/digitfrequency/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.digitfrequency 2 | 3 | // Time complexity: O(n) 4 | // Generate digit frequency map for each integer and compare them 5 | private object Solution1 { 6 | private fun equalDigitFrequency(i1: Int, i2: Int): Boolean { 7 | val i1Str = i1.toString() 8 | val i2Str = i2.toString() 9 | 10 | if (i1Str.length != i2Str.length) { 11 | return false 12 | } 13 | 14 | val frequencyCounter1 = i1Str.groupingBy { it }.eachCount() 15 | val frequencyCounter2 = i2Str.groupingBy { it }.eachCount() 16 | return frequencyCounter1 == frequencyCounter2 17 | } 18 | } 19 | 20 | // Time complexity: O(n^2) 21 | // Loop through each character of first integer and look for this character in another integer. If character if found 22 | // remove it from second integer to make sure that character frequency match. 23 | private object Solution2 { 24 | private fun equalDigitFrequency(i1: Int, i2: Int): Boolean { 25 | val i1Str = i1.toString().toList() 26 | val i2Str = i2.toString().toMutableList() 27 | 28 | if (i1Str.size != i2Str.size) { 29 | return false 30 | } 31 | 32 | i1Str.forEach { 33 | // under the hood 'indexOf' iterates through entire list (it's like nested loop) 34 | val index = i2Str.indexOf(it) 35 | 36 | if (index == -1) { 37 | return false 38 | } 39 | 40 | i2Str.removeAt(index) 41 | } 42 | 43 | return true 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/common/anycallback/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.common.anycallback 2 | 3 | internal object Solution1 { 4 | fun anyCallback(list: List, predicate: (T) -> Boolean): Boolean { 5 | if (list.size == 1) { 6 | return predicate(list.first()) 7 | } 8 | 9 | return predicate(list.first()) || anyCallback(list.drop(1), predicate) 10 | } 11 | } 12 | 13 | internal object Solution2 { 14 | fun anyCallback(list: List, predicate: (T) -> Boolean): Boolean { 15 | if (list.isEmpty()) return false 16 | return predicate(list.first()) || anyCallback(list.subList(1, list.size), predicate) 17 | } 18 | } 19 | 20 | internal object Solution3 { 21 | fun anyCallback(list: List, predicate: (T) -> Boolean): Boolean { 22 | fun _randomAccessOptimized(list: List, predicate: (T) -> Boolean): Boolean { 23 | if (list.isEmpty()) return false 24 | return predicate(list.first()) || _randomAccessOptimized(list.subList(1, list.size), predicate) 25 | } 26 | 27 | fun _sequentialOptimized(list: List, predicate: (T) -> Boolean): Boolean { 28 | if (list.isEmpty()) return false 29 | return predicate(list.first()) || _sequentialOptimized(list.drop(1), predicate) 30 | } 31 | 32 | 33 | return if (list is RandomAccess) { 34 | _randomAccessOptimized(list, predicate) 35 | } 36 | else { 37 | _sequentialOptimized(list, predicate) 38 | } 39 | } 40 | } 41 | 42 | private object KtLintWillNotComplain 43 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/integer/fibonacci/recursivecached/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.integer.fibonacci.recursivecached 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | import org.junit.jupiter.api.Timeout 6 | import java.util.concurrent.TimeUnit 7 | 8 | private fun fibonacciSequenceRecursiveCached(n: Int, methodCache: MutableList = mutableListOf()): Int { 9 | if (n < 2) { 10 | return n 11 | } 12 | 13 | return fibonacciSequenceRecursiveCached(n - 1) + fibonacciSequenceRecursiveCached(n - 2) 14 | } 15 | 16 | private data class MethodCache(val n: Int, val result: Int) 17 | 18 | private class Test { 19 | @Test 20 | fun `calculates correct fib value for 0`() { 21 | fibonacciSequenceRecursiveCached(0) shouldBeEqualTo 0 22 | } 23 | 24 | @Test 25 | fun `calculates correct fib value for 1`() { 26 | fibonacciSequenceRecursiveCached(1) shouldBeEqualTo 1 27 | } 28 | 29 | @Test 30 | fun `calculates correct fib value for 2`() { 31 | fibonacciSequenceRecursiveCached(2) shouldBeEqualTo 1 32 | } 33 | 34 | @Test 35 | fun `calculates correct fib value for 3`() { 36 | fibonacciSequenceRecursiveCached(3) shouldBeEqualTo 2 37 | } 38 | 39 | @Test 40 | fun `calculates correct fib value for 4`() { 41 | fibonacciSequenceRecursiveCached(4) shouldBeEqualTo 3 42 | } 43 | 44 | @Timeout(value = 500, unit = TimeUnit.MILLISECONDS) 45 | fun `calculates correct fib value for 45`() { 46 | fibonacciSequenceRecursiveCached(45) shouldBeEqualTo 1134903170 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/maxoccurringchar/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.maxoccurringchar 2 | 3 | // Kotlin idiomatic solution 4 | private object Solution1 { 5 | private fun maxOccurringChar(str: String): Char? { 6 | if (str.isBlank()) return null 7 | 8 | return str.toCharArray() 9 | .groupBy { it } 10 | .maxBy { it.value.size } 11 | .key 12 | } 13 | } 14 | 15 | // Kotlin idiomatic solution 16 | private object Solution2 { 17 | private fun maxOccurringChar(str: String): Char? { 18 | if (str.isBlank()) return null 19 | 20 | return str.toList() 21 | .groupingBy { it } 22 | .eachCount() 23 | .maxBy { it.value } 24 | .key 25 | } 26 | } 27 | 28 | private object Solution3 { 29 | private fun maxOccurringChar(str: String): Char? { 30 | if (str.isBlank()) return null 31 | 32 | val map = mutableMapOf() 33 | 34 | str.forEach { 35 | map[it] = (map[it] ?: 0) + 1 36 | } 37 | 38 | return map.maxBy { it.value }.key 39 | } 40 | } 41 | 42 | // Recursive naive approach 43 | // Time complexity: O(n^2) 44 | private object Solution4 { 45 | private fun maxOccurringChar(str: String): Char? { 46 | if (str.length == 1) { 47 | return str.first() 48 | } 49 | 50 | str.forEachIndexed { index, c -> 51 | str.substring(index + 1).forEach { 52 | if (c == it) { 53 | return it 54 | } 55 | } 56 | } 57 | 58 | return null 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/circularcheck/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.linkedlist.singly.circularcheck 2 | 3 | import com.igorwojda.linkedlist.singly.base.Solution1.Node 4 | import com.igorwojda.linkedlist.singly.base.Solution1.SinglyLinkedList 5 | import org.amshove.kluent.shouldBeEqualTo 6 | import org.junit.jupiter.api.Test 7 | 8 | private fun circularCheck(list: SinglyLinkedList): Boolean { 9 | TODO("Add your solution here") 10 | } 11 | 12 | private class Test { 13 | @Test 14 | fun `circular detects circular linked lists`() { 15 | val l = SinglyLinkedList() 16 | val a = Node('a') 17 | val b = Node('b') 18 | val c = Node('c') 19 | 20 | l.head = a 21 | a.next = b 22 | b.next = c 23 | c.next = b 24 | 25 | circularCheck(l) shouldBeEqualTo true 26 | } 27 | 28 | @Test 29 | fun `circular detects circular linked lists linked at the head`() { 30 | val l = SinglyLinkedList() 31 | val a = Node('a') 32 | val b = Node('b') 33 | val c = Node('c') 34 | 35 | l.head = a 36 | a.next = b 37 | b.next = c 38 | c.next = a 39 | 40 | circularCheck(l) shouldBeEqualTo true 41 | } 42 | 43 | @Test 44 | fun `circular detects non-circular linked lists`() { 45 | val l = SinglyLinkedList() 46 | val a = Node('a') 47 | val b = Node('b') 48 | val c = Node('c') 49 | 50 | l.head = a 51 | a.next = b 52 | b.next = c 53 | c.next = null 54 | 55 | circularCheck(l) shouldBeEqualTo false 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/reverse/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.reverse 2 | 3 | // Kotlin idiomatic way 4 | private object Solution1 { 5 | private fun reverse(str: String): String { 6 | return str.reversed() 7 | } 8 | } 9 | 10 | // Iterative approach 11 | private object Solution2 { 12 | private fun reverse(str: String): String { 13 | var reversed = "" 14 | str.forEach { 15 | reversed = it + reversed 16 | } 17 | return reversed 18 | } 19 | } 20 | 21 | // Recursive approach 22 | private object Solution3 { 23 | private fun reverse(str: String): String { 24 | if (str.isEmpty()) { 25 | return str 26 | } 27 | 28 | return reverse(str.drop(1)) + str.first() 29 | } 30 | } 31 | 32 | // Kotlin fold 33 | private object Solution4 { 34 | private fun reverse(str: String): String { 35 | return str.foldRight("") { char, reversed -> reversed + char } 36 | } 37 | } 38 | 39 | // Time complexity: O(n) 40 | // Space complexity: O(1) 41 | // Reverse in place 42 | private object Solution5 { 43 | private fun reverse(str: String): String { 44 | val chars = str.toMutableList() 45 | 46 | var leftIndex = 0 47 | var rightIndex = chars.lastIndex 48 | 49 | while (leftIndex <= rightIndex) { 50 | val temp = chars[leftIndex] 51 | chars[leftIndex] = chars[rightIndex] 52 | chars[rightIndex] = temp 53 | 54 | leftIndex++ 55 | rightIndex-- 56 | } 57 | 58 | return chars.joinToString(transform = { it.toString() }, separator = "") 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/bubblesort/README.md: -------------------------------------------------------------------------------- 1 | # Bubble sort 2 | 3 | ## Instructions 4 | 5 | Sort list of numbers from lowest number to greatest number using 6 | [bubble sort](https://en.wikipedia.org/wiki/Bubble_sort). 7 | 8 | ## Algorithm 9 | 10 | Starting from the beginning of the list, compare every adjacent pair, swap their position if they are not in the right 11 | order (the latter one is smaller than the former one). After each iteration, one less element (the last one) 12 | is needed to be compared until there are no more elements left to be compared. 13 | 14 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 15 | 16 | ## Examples 17 | 18 | Sort `[5, 1, 4, 2, 8]` 19 | 20 | **First Pass** 21 | ```kotlin 22 | [5, 1, 4, 2, 8] // [1, 5, 4, 2, 8] Compares the first two elements, and swap since 5 > 1 23 | [1, 5, 4, 2, 8] // [1, 4, 5, 2, 8] Swap since 5 > 4 24 | [1, 4, 5, 2, 8] // [1, 4, 2, 5, 8] Swap since 5 > 2 25 | [1, 4, 2, 5, 8] // [1, 4, 2, 5, 8] Now, since these elements are already in order (8 > 5), algorithm does not swap them 26 | ``` 27 | 28 | **Second Pass** 29 | ```kotlin 30 | [1, 4, 2, 5, 8] // [1, 4, 2, 5, 8] 31 | [1, 4, 2, 5, 8] // [1, 2, 4, 5, 8] Swap since 4 > 2 32 | [1, 2, 4, 5, 8] // [1, 2, 4, 5, 8] 33 | [1, 2, 4, 5, 8] // [1, 2, 4, 5, 8] 34 | ``` 35 | 36 | Now, the list is already sorted, but the algorithm does not know if it is completed. The algorithm needs one whole pass 37 | without any swap to know it is sorted 38 | 39 | **Third Pass** 40 | ```kotlin 41 | [1, 2, 4, 5, 8] // [1, 2, 4, 5, 8] 42 | [1, 2, 4, 5, 8] // [1, 2, 4, 5, 8] 43 | [1, 2, 4, 5, 8] // [1, 2, 4, 5, 8] 44 | [1, 2, 4, 5, 8] // [1, 2, 4, 5, 8] 45 | ``` 46 | 47 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/search/binarysearch/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.search.binarysearch 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun binarySearch(list: List, element: Char): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `index of A in A, B, C is 0`() { 13 | binarySearch(listOf('A', 'B', 'C'), 'A') shouldBeEqualTo 0 14 | } 15 | 16 | @Test 17 | fun `index of B in A, B, C is 1`() { 18 | binarySearch(listOf('A', 'B', 'C'), 'B') shouldBeEqualTo 1 19 | } 20 | 21 | @Test 22 | fun `index of C in A, B, C is 2`() { 23 | binarySearch(listOf('A', 'B', 'C'), 'C') shouldBeEqualTo 2 24 | } 25 | 26 | @Test 27 | fun `index of H in A, B, C is -1`() { 28 | binarySearch(listOf('A', 'B', 'C'), 'H') shouldBeEqualTo -1 29 | } 30 | 31 | @Test 32 | fun `index of A in A, B, C, D is 0`() { 33 | binarySearch(listOf('A', 'B', 'C', 'D'), 'A') shouldBeEqualTo 0 34 | } 35 | 36 | @Test 37 | fun `index of B in A, B, C, D is 1`() { 38 | binarySearch(listOf('A', 'B', 'C', 'D'), 'B') shouldBeEqualTo 1 39 | } 40 | 41 | @Test 42 | fun `index of C in A, B, C, D is 2`() { 43 | binarySearch(listOf('A', 'B', 'C', 'D'), 'C') shouldBeEqualTo 2 44 | } 45 | 46 | @Test 47 | fun `index of D in A, B, C, D is 2`() { 48 | binarySearch(listOf('A', 'B', 'C', 'D'), 'D') shouldBeEqualTo 3 49 | } 50 | 51 | @Test 52 | fun `index of H in A, B, C, D is -1`() { 53 | binarySearch(listOf('A', 'B', 'C', 'D'), 'H') shouldBeEqualTo -1 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /.test/buildSrc/src/main/kotlin/com/igorwojda/challenge/utils/KotlinParserUtils.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.challenge.utils 2 | 3 | import com.intellij.openapi.util.Disposer 4 | import com.intellij.psi.PsiManager 5 | import com.intellij.testFramework.LightVirtualFile 6 | import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles 7 | import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment 8 | import org.jetbrains.kotlin.config.CompilerConfiguration 9 | import org.jetbrains.kotlin.idea.KotlinFileType 10 | import org.jetbrains.kotlin.psi.KtFile 11 | import java.io.File 12 | 13 | object KotlinParserUtils { 14 | private val project by lazy { 15 | KotlinCoreEnvironment.createForProduction( 16 | Disposer.newDisposable(), 17 | CompilerConfiguration(), 18 | EnvironmentConfigFiles.JVM_CONFIG_FILES 19 | ).project 20 | } 21 | 22 | fun getChallengeFile(challengeDirectoryPath: File, challengeFile: ChallengeFile): File { 23 | val path = "${challengeDirectoryPath.path}/${challengeFile.fileName}" 24 | return File(path) 25 | } 26 | 27 | fun getChallengeKtFile(challengeDirectoryPath: File, challengeFile: ChallengeFile): KtFile { 28 | val file = getChallengeFile(challengeDirectoryPath, challengeFile) 29 | val fullFileName = "${challengeDirectoryPath.path}/${challengeFile.fileName}" 30 | return getChallengeKtFile(file.readText(), fullFileName) 31 | } 32 | 33 | private fun getChallengeKtFile(codeString: String, fileName: String) = 34 | PsiManager.getInstance(project) 35 | .findFile( 36 | LightVirtualFile(fileName, KotlinFileType.INSTANCE, codeString) 37 | ) as KtFile 38 | } 39 | -------------------------------------------------------------------------------- /.test/src/test/kotlin/com/igorwojda/challenge/utils/KotlinParserUtils.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.challenge.utils 2 | 3 | import com.intellij.openapi.util.Disposer 4 | import com.intellij.psi.PsiManager 5 | import com.intellij.testFramework.LightVirtualFile 6 | import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles 7 | import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment 8 | import org.jetbrains.kotlin.config.CompilerConfiguration 9 | import org.jetbrains.kotlin.idea.KotlinFileType 10 | import org.jetbrains.kotlin.psi.KtFile 11 | import java.io.File 12 | 13 | object KotlinParserUtils { 14 | 15 | private val project by lazy { 16 | KotlinCoreEnvironment.createForProduction( 17 | Disposer.newDisposable(), 18 | CompilerConfiguration(), 19 | EnvironmentConfigFiles.JVM_CONFIG_FILES, 20 | ).project 21 | } 22 | 23 | private fun getChallengeFile(challengeDirectoryPath: File, challengeFile: ChallengeFile): File { 24 | val path = "${challengeDirectoryPath.path}/${challengeFile.fileName}" 25 | return File(path) 26 | } 27 | 28 | fun getChallengeKtFile(challengeDirectoryPath: File, challengeFile: ChallengeFile): KtFile { 29 | val file = getChallengeFile(challengeDirectoryPath, challengeFile) 30 | val fullFileName = "${challengeDirectoryPath.path}/${challengeFile.fileName}" 31 | return getChallengeKtFile(file.readText(), fullFileName) 32 | } 33 | 34 | private fun getChallengeKtFile(codeString: String, fileName: String) = 35 | PsiManager.getInstance(project) 36 | .findFile( 37 | LightVirtualFile(fileName, KotlinFileType.INSTANCE, codeString), 38 | ) as KtFile 39 | } 40 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/getduplicatedarguments/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.getduplicatedarguments 2 | 3 | // Time complexity: O(n) 4 | // Determine the frequency of each argument and then filter arguments with frequency > 1 5 | private object Solution1 { 6 | fun getDuplicatedArguments(vararg strings: String): List? = strings 7 | .groupingBy { it } 8 | .eachCount() 9 | .filter { it.value != 1 } 10 | .map { it.key } 11 | } 12 | 13 | // Time complexity: O(n) 14 | // Using double pointer. 15 | private object Solution2 { 16 | fun getDuplicatedArguments(vararg strings: String): List? { 17 | var pointer1 = 0 18 | var pointer2 = 1 19 | val result = mutableSetOf() 20 | val sortedList = strings.sorted() 21 | 22 | for (it in 0 until sortedList.lastIndex) { 23 | if (sortedList[pointer1] == sortedList[pointer2]) { 24 | result.add(sortedList[pointer1]) 25 | } 26 | 27 | pointer1++ 28 | pointer2++ 29 | } 30 | 31 | return result.toList() 32 | } 33 | } 34 | 35 | // Time complexity: O(n^2) 36 | // Loop through all arguments and compare given argument with all other arguments. 37 | private object Solution3 { 38 | fun getDuplicatedArguments(vararg strings: String): List? { 39 | val result = mutableSetOf() 40 | 41 | strings.forEachIndexed { index, element1 -> 42 | (index + 1..strings.lastIndex).forEach { index2 -> 43 | if (element1 == strings[index2]) { 44 | result.add(element1) 45 | } 46 | } 47 | } 48 | 49 | return result.toList() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/midpoint/README.md: -------------------------------------------------------------------------------- 1 | # Linked list midpoint 2 | 3 | ## Nice to solve before 4 | 5 | [Linked List.kt](../base/SinglyLinkedList.kt) 6 | 7 | ## Instructions 8 | 9 | Return the 'middle' node of a linked list. If the list has an even number of elements, return 10 | the node at the end of the first half of the list. 11 | 12 | We are using version of linked list that implements Kotlin 13 | [Iterator](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-iterator/index.html) interface, so we can 14 | use `forEach` instead of `while` loop. 15 | 16 | [Challenge](Challenge.kt) | [Solution](Solution.kt) 17 | 18 | ## Limitations 19 | 20 | Do not use a counter variable, do not retrieve the `size` of the list, and only iterate through the list one time. 21 | 22 | ## Examples 23 | 24 | Example 1 25 | 26 | ```kotlin 27 | val l = new LinkedList() 28 | l.insertLast('a') 29 | l.insertLast('b') 30 | l.insertLast('c') 31 | midpoint(l).data // 'b' 32 | ``` 33 | 34 | Example 2 35 | 36 | ```kotlin 37 | val l = new LinkedList() 38 | l.insertLast('a') 39 | l.insertLast('b') 40 | l.insertLast('c') 41 | l.insertLast('d') 42 | midpoint(l).data // 'b' 43 | ``` 44 | 45 | ## Hints 46 | 47 |
48 | Hint 1 49 | Use more then one variable to store values that are retrieved during iteration (double pointer solution) 50 |
51 | 52 |
53 | Hint 2 54 | Name of these variables should be `slow` and `fast` 55 |
56 | 57 |
58 | Hint 3 59 | Assign next node to `slow` variable in every iteration 60 |
61 | 62 |
63 | Hint 4 64 | Assign next node of next node to `fast` variable in every iteration 65 |
66 | 67 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/surroundedletter/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.surroundedletter 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun surroundedLetter(str: String): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `'a' return 'false'`() { 13 | surroundedLetter("a") shouldBeEqualTo false 14 | } 15 | 16 | @Test 17 | fun `'+a+' return 'true'`() { 18 | surroundedLetter("+a+") shouldBeEqualTo true 19 | } 20 | 21 | @Test 22 | fun `'a+' return 'false'`() { 23 | surroundedLetter("a+") shouldBeEqualTo false 24 | } 25 | 26 | @Test 27 | fun `'+a' return 'false'`() { 28 | surroundedLetter("+a") shouldBeEqualTo false 29 | } 30 | 31 | @Test 32 | fun `'+a+b+' return 'true'`() { 33 | surroundedLetter("+a+b+") shouldBeEqualTo true 34 | } 35 | 36 | @Test 37 | fun `'+a++b+' return 'true'`() { 38 | surroundedLetter("+a++b+") shouldBeEqualTo true 39 | } 40 | 41 | @Test 42 | fun `'+ab+' return 'false'`() { 43 | surroundedLetter("+ab+") shouldBeEqualTo false 44 | } 45 | 46 | @Test 47 | fun `'a+b+' return 'false'`() { 48 | surroundedLetter("a+b+") shouldBeEqualTo false 49 | } 50 | 51 | @Test 52 | fun `'+a+b' return 'false'`() { 53 | surroundedLetter("+a+b") shouldBeEqualTo false 54 | } 55 | 56 | @Test 57 | fun `'+a+b+++c++d+e++' return 'true'`() { 58 | surroundedLetter("+a+b+++c++d+e++") shouldBeEqualTo true 59 | } 60 | 61 | @Test 62 | fun `'+++a+d++de++e++' return 'false'`() { 63 | surroundedLetter("+a+d++de++e+") shouldBeEqualTo false 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/addnumbers/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.linkedlist.singly.addnumbers 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private data class ListNode( 7 | var data: Int, 8 | var next: ListNode? = null, 9 | ) 10 | 11 | private fun addTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode? { 12 | TODO("Add your solution here") 13 | } 14 | 15 | private class Test { 16 | @Test 17 | fun `add 5, 3, 7 to 2, 3, 3 returns 7, 3, 8`() { 18 | val number1 = getList(5, 3, 7) 19 | val number2 = getList(7, 3, 8) 20 | val result = getList(2, 7, 5, 1) 21 | 22 | addTwoNumbers(number1, number2) shouldBeEqualTo result 23 | } 24 | 25 | @Test 26 | fun `add 0 to 0 returns 0`() { 27 | val number1 = getList(0) 28 | val number2 = getList(0) 29 | val result = getList(0) 30 | 31 | addTwoNumbers(number1, number2) shouldBeEqualTo result 32 | } 33 | 34 | @Test 35 | fun `add 7 to 2, 3, 5 returns 9, 3, 5`() { 36 | val number1 = getList(7) 37 | val number2 = getList(2, 3, 5) 38 | val result = getList(9, 3, 5) 39 | 40 | addTwoNumbers(number1, number2) shouldBeEqualTo result 41 | } 42 | 43 | private fun getList(vararg ints: Int): ListNode? { 44 | var head: ListNode? = null 45 | var current: ListNode? = null 46 | 47 | ints.forEach { 48 | val node = ListNode(it) 49 | 50 | if (head == null) { 51 | head = node 52 | current = node 53 | } else { 54 | current?.next = node 55 | current = node 56 | } 57 | } 58 | 59 | return head 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/ispalindrome/basic/Solution.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.ispalindrome.basic 2 | 3 | // string reverse 4 | private object Solution1 { 5 | private fun isPalindrome(str: String): Boolean { 6 | return str == str.reversed() 7 | } 8 | } 9 | 10 | // iterative, double pointer solution 11 | private object Solution2 { 12 | private fun isPalindrome(str: String): Boolean { 13 | var leftIndex = 0 14 | var rightIndex = str.lastIndex 15 | 16 | while (leftIndex <= rightIndex) { 17 | val leftValue = str[leftIndex] 18 | val rightValue = str[rightIndex] 19 | 20 | if (leftValue != rightValue) { 21 | return false 22 | } 23 | 24 | leftIndex++ 25 | rightIndex-- 26 | } 27 | 28 | return true 29 | } 30 | } 31 | 32 | // iterative, double pointer solution 33 | private object Solution3 { 34 | private fun isPalindrome(str: String): Boolean { 35 | str.forEachIndexed { index, char -> 36 | val rightIndex = str.lastIndex - index 37 | 38 | if (char != str[rightIndex]) { 39 | return false 40 | } 41 | 42 | if (index > rightIndex) { 43 | return true 44 | } 45 | } 46 | 47 | return true 48 | } 49 | } 50 | 51 | // recursive solution 52 | private object Solution4 { 53 | private fun isPalindrome(str: String): Boolean { 54 | return if (str.isEmpty() || str.length == 1) { 55 | true 56 | } else { 57 | if (str.first() == str.last()) { 58 | isPalindrome(str.substring(1 until str.lastIndex)) 59 | } else { 60 | false 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/subtract/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.subtract 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun getSubtraction(list1: List, list2: List): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `A, B, C and B ,C returns A`() { 13 | getSubtraction(listOf("A", "B", "C"), listOf("B", "C")) shouldBeEqualTo listOf("A") 14 | } 15 | 16 | @Test 17 | fun `E, F, D and D returns E, F`() { 18 | getSubtraction(listOf("E", "F", "D"), listOf("D")) shouldBeEqualTo listOf("E", "F") 19 | } 20 | 21 | @Test 22 | fun `G and G returns empty list`() { 23 | getSubtraction(listOf("G"), listOf("G")) shouldBeEqualTo emptyList() 24 | } 25 | 26 | @Test 27 | fun `I, B, H and I, B ,H returns empty list`() { 28 | getSubtraction(listOf("I", "B", "H"), listOf("I", "B", "H")) shouldBeEqualTo emptyList() 29 | } 30 | 31 | @Test 32 | fun `B, Z, Z, G and B returns B, Z, Z`() { 33 | getSubtraction(listOf("B", "Z", "Z", "G"), listOf("Z", "Z")) shouldBeEqualTo listOf( 34 | "B", 35 | "G", 36 | ) 37 | } 38 | 39 | @Test 40 | fun `G, D, D, D, A, A and D, A returns G, D, D, A`() { 41 | getSubtraction( 42 | listOf("G", "D", "D", "D", "A", "A"), 43 | listOf("D", "A"), 44 | ) shouldBeEqualTo listOf("G", "D", "D", "A") 45 | } 46 | 47 | @Test 48 | fun `G, H, H, B, B and empty list returns G, H, H, B, B`() { 49 | getSubtraction(listOf("G", "H", "H", "B", "B"), emptyList()) shouldBeEqualTo listOf( 50 | "G", 51 | "H", 52 | "H", 53 | "B", 54 | "B", 55 | ) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/cache/advancedlru/README.md: -------------------------------------------------------------------------------- 1 | # Advanced LRU Cache 2 | 3 | ## Nice to solve before 4 | 5 | - [LRU Cache](../lru/README.md) 6 | 7 | ## Instructions 8 | 9 | Design a data structure that enables the storage and retrieval of items via a key, subject to a specified capacity 10 | limit. In cases where the addition of new items exceeds this capacity, ensure that space is made available through the 11 | following sequence of operations: 12 | 13 | - Firstly, discard items that have exceeded their validity period (`expiryTime` > `getSystemTimeForExpiry()`). 14 | - If there are no items past their validity, identify the items with the earliest expiry time, and from those the items with the lowest priority rating, and from these remove 15 | the item that was least recently accessed or used. 16 | 17 | To simplify expiry logic testing use the provided `Clock` to determine the current time in milliseconds using `clock.millis()`. 18 | 19 | [Challenge](Challenge.kt) | [Solution](Solution.kt) | [Tests](Tests.kt) 20 | 21 | ## Examples 22 | 23 | ```kotlin 24 | val cache = AdvancedLRUCache(2) 25 | cache.put("A", 1, 5, Duration.ofMinutes(15)) 26 | cache.get("A") // 1 27 | ``` 28 | 29 | ```kotlin 30 | val cache = AdvancedLRUCache(2, Clock.fixed(...)) // testing clock, fixed at a moment in time 31 | cache.put("A", 1, 5, Duration.ofMinutes(15)) 32 | cache.put("B", 2, 1, Duration.ofMinutes(15)) 33 | cache.put("C", 3, 10, Duration.ofMinutes(15)) 34 | 35 | 36 | cache.get("A") // 1 37 | cache.get("B") // null - "B" was evicted due to lower priority. 38 | cache.get("C") // 3 39 | ``` 40 | 41 | ```kotlin 42 | val cache = AdvancedLRUCache(100) 43 | cache.put("A", 1, 1, Duration.ofMillis(1)) 44 | cache.put("B", 2, 1, Duration.ofMillis(1)) 45 | 46 | sleep(100) 47 | 48 | cache.get("A") // null - "A" was evicted due to expiry. 49 | cache.get("B") // null - "B" was evicted due to expiry. 50 | ``` 51 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/countuniquevalues/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.countuniquevalues 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun countUniqueValues(list: List): Int { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `countUniqueValues empty list return 0`() { 13 | countUniqueValues(listOf()) shouldBeEqualTo 0 14 | } 15 | 16 | @Test 17 | fun `countUniqueValues 4 return 1`() { 18 | countUniqueValues(listOf(4)) shouldBeEqualTo 1 19 | } 20 | 21 | @Test 22 | fun `countUniqueValues 3, 3, 3, 3, 5 return 2`() { 23 | countUniqueValues(listOf(3, 3, 3, 3, 5)) shouldBeEqualTo 2 24 | } 25 | 26 | @Test 27 | fun `countUniqueValues 5, 5, 6, 7, 7 returns 3`() { 28 | countUniqueValues(listOf(5, 5, 6, 7, 7)) shouldBeEqualTo 3 29 | } 30 | 31 | @Test 32 | fun `countUniqueValues 1, 5, 9, 9 returns 3`() { 33 | countUniqueValues(listOf(1, 5, 9, 9)) shouldBeEqualTo 3 34 | } 35 | 36 | @Test 37 | fun `countUniqueValues 1, 5, 5, 5, 9 returns 3`() { 38 | countUniqueValues(listOf(1, 5, 5, 5, 9)) shouldBeEqualTo 3 39 | } 40 | 41 | @Test 42 | fun `countUniqueValues 4, 4, 5, 7, 10, 10 returns 4`() { 43 | countUniqueValues(listOf(4, 4, 5, 7, 10, 10)) shouldBeEqualTo 4 44 | } 45 | 46 | @Test 47 | fun `countUniqueValues 2, 2, 3, 6, 7, 9, 9, 12, 13, 13 returns 7`() { 48 | countUniqueValues(listOf(2, 2, 3, 6, 7, 9, 9, 12, 13, 13)) shouldBeEqualTo 7 49 | } 50 | 51 | @Test 52 | fun `countUniqueValues 1, 2, 3, 4, 5 return 5`() { 53 | countUniqueValues(listOf(1, 2, 3, 4, 5)) shouldBeEqualTo 5 54 | } 55 | 56 | @Test 57 | fun `countUniqueValues 2, 3, 4, 7 return 4`() { 58 | countUniqueValues(listOf(2, 3, 4, 7)) shouldBeEqualTo 4 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/list/sort/bubblesort/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.list.sort.bubblesort 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun bubbleSort(list: List): List { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `bubble sort empty list`() { 13 | bubbleSort(mutableListOf()) shouldBeEqualTo listOf() 14 | } 15 | 16 | @Test 17 | fun `bubble sort 7`() { 18 | bubbleSort(mutableListOf(7)) shouldBeEqualTo listOf(7) 19 | } 20 | 21 | @Test 22 | fun `bubble sort empty list 9, 3`() { 23 | bubbleSort(mutableListOf(9, 3)) shouldBeEqualTo listOf(3, 9) 24 | } 25 | 26 | @Test 27 | fun `bubble sort 5, 1, 4, 2`() { 28 | bubbleSort(listOf(5, 1, 4, 2)) shouldBeEqualTo listOf(1, 2, 4, 5) 29 | } 30 | 31 | @Test 32 | fun `bubble sort 5, 2, 1, 8, 4, 7, 6, 3`() { 33 | bubbleSort(mutableListOf(5, 2, 1, 8, 4, 7, 6, 3)) shouldBeEqualTo listOf( 34 | 1, 35 | 2, 36 | 3, 37 | 4, 38 | 5, 39 | 6, 40 | 7, 41 | 8, 42 | ) 43 | } 44 | 45 | @Test 46 | fun `bubble sort 17, 4, 12, 19, 80, 75, 16`() { 47 | bubbleSort(listOf(17, 4, 12, 19, 80, 75, 16)) shouldBeEqualTo listOf( 48 | 4, 49 | 12, 50 | 16, 51 | 17, 52 | 19, 53 | 75, 54 | 80, 55 | ) 56 | } 57 | 58 | @Test 59 | fun `bubble sort 11, 40, 40, 50, 43, 10, 30, 42, 20, 6, 19, 32, 20, 41, 23, 27`() { 60 | val list = mutableListOf(11, 40, 40, 50, 43, 10, 30, 42, 20, 6, 19, 32, 20, 41, 23, 27) 61 | val sorted = mutableListOf(6, 10, 11, 19, 20, 20, 23, 27, 30, 32, 40, 40, 41, 42, 43, 50) 62 | 63 | bubbleSort(list) shouldBeEqualTo sorted 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/linkedlist/singly/midpoint/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.linkedlist.singly.midpoint 2 | 3 | import com.igorwojda.linkedlist.singly.base.Solution1.Node 4 | import com.igorwojda.linkedlist.singly.base.Solution1.SinglyLinkedList 5 | import org.amshove.kluent.shouldBeEqualTo 6 | import org.junit.jupiter.api.Test 7 | 8 | private fun midpoint(list: SinglyLinkedList): Node? { 9 | TODO("Add your solution here") 10 | } 11 | 12 | private class Test { 13 | @Test 14 | fun `midpoint of list with 0 elements`() { 15 | SinglyLinkedList().apply { 16 | midpoint(this)?.data shouldBeEqualTo null 17 | } 18 | } 19 | 20 | @Test 21 | fun `midpoint of list with 3 elements`() { 22 | SinglyLinkedList().apply { 23 | insertLast('a') 24 | insertLast('b') 25 | insertLast('c') 26 | 27 | midpoint(this)?.data shouldBeEqualTo 'b' 28 | } 29 | } 30 | 31 | @Test 32 | fun `midpoint of list with 5 elements`() { 33 | SinglyLinkedList().apply { 34 | insertLast('a') 35 | insertLast('b') 36 | insertLast('c') 37 | insertLast('d') 38 | insertLast('e') 39 | 40 | midpoint(this)?.data shouldBeEqualTo 'c' 41 | } 42 | } 43 | 44 | @Test 45 | fun `midpoint of list with 2 elements`() { 46 | SinglyLinkedList().apply { 47 | insertLast('a') 48 | insertLast('b') 49 | 50 | midpoint(this)?.data shouldBeEqualTo 'a' 51 | } 52 | } 53 | 54 | @Test 55 | fun `midpoint of list with 4 elements`() { 56 | SinglyLinkedList().apply { 57 | insertLast('a') 58 | insertLast('b') 59 | insertLast('c') 60 | insertLast('d') 61 | 62 | midpoint(this)?.data shouldBeEqualTo 'b' 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/kotlin/com/igorwojda/string/issubstring/Challenge.kt: -------------------------------------------------------------------------------- 1 | package com.igorwojda.string.issubstring 2 | 3 | import org.amshove.kluent.shouldBeEqualTo 4 | import org.junit.jupiter.api.Test 5 | 6 | private fun isSubstring(str: String, subStr: String): Boolean { 7 | TODO("Add your solution here") 8 | } 9 | 10 | private class Test { 11 | @Test 12 | fun `abd not in abcd`() { 13 | isSubstring("abcd", "abd") shouldBeEqualTo false 14 | } 15 | 16 | @Test 17 | fun `e not in abcd`() { 18 | isSubstring("abcd", "e") shouldBeEqualTo false 19 | } 20 | 21 | @Test 22 | fun `ab in abc`() { 23 | isSubstring("abc", "ab") shouldBeEqualTo true 24 | } 25 | 26 | @Test 27 | fun `bc in abc`() { 28 | isSubstring("abc", "bc") shouldBeEqualTo true 29 | } 30 | 31 | @Test 32 | fun `abc in abc`() { 33 | isSubstring("abc", "abc") shouldBeEqualTo true 34 | } 35 | 36 | @Test 37 | fun `abc in aaababcd`() { 38 | isSubstring("aaababcd", "abc") shouldBeEqualTo true 39 | } 40 | 41 | @Test 42 | fun `abc not in aaababab`() { 43 | isSubstring("aaababab", "abc") shouldBeEqualTo false 44 | } 45 | 46 | @Test 47 | fun `aab in aaab`() { 48 | isSubstring("aaab", "aab") shouldBeEqualTo true 49 | } 50 | 51 | @Test 52 | fun `abc in ababc`() { 53 | isSubstring("ababc", "abc") shouldBeEqualTo true 54 | } 55 | 56 | @Test 57 | fun `cd in abcdef`() { 58 | isSubstring("abcdef", "cd") shouldBeEqualTo true 59 | } 60 | 61 | @Test 62 | fun `empty sub-string not in abc`() { 63 | isSubstring("abc", "") shouldBeEqualTo true 64 | } 65 | 66 | @Test 67 | fun `abc not in empty string`() { 68 | isSubstring("", "abc") shouldBeEqualTo false 69 | } 70 | 71 | @Test 72 | fun `empty sub-string not in empty string`() { 73 | isSubstring("", "") shouldBeEqualTo true 74 | } 75 | } 76 | --------------------------------------------------------------------------------