diff --git a/exercises/practice/acronym/src/main/kotlin/Acronym.kt b/exercises/practice/acronym/src/main/kotlin/Acronym.kt index ceb1d767..1056bef3 100644 --- a/exercises/practice/acronym/src/main/kotlin/Acronym.kt +++ b/exercises/practice/acronym/src/main/kotlin/Acronym.kt @@ -1,5 +1,10 @@ object Acronym { - fun generate(phrase: String) : String { - TODO("Implement the function to complete the task") - } + fun generate(phrase: String) = phrase.trim() + .split(" ", "-") + .map { str -> str.filter { it.isLetter() } } + .takeIf { it.isNotEmpty() } + ?.mapNotNull { it.firstOrNull() } + ?.map { it.uppercaseChar() } + ?.joinToString("") + ?: "" } diff --git a/exercises/practice/difference-of-squares/src/main/kotlin/DifferenceOfSquares.kt b/exercises/practice/difference-of-squares/src/main/kotlin/DifferenceOfSquares.kt index b0bccaad..7f9e42ad 100644 --- a/exercises/practice/difference-of-squares/src/main/kotlin/DifferenceOfSquares.kt +++ b/exercises/practice/difference-of-squares/src/main/kotlin/DifferenceOfSquares.kt @@ -1,15 +1,12 @@ -class Squares { - //TODO: implement proper constructor +class Squares(val square: Int) { - fun sumOfSquares() { - TODO("Implement the function to complete the task") - } + fun sumOfSquares() = (1..square) + .map { it * it } + .sum() - fun squareOfSum() { - TODO("Implement the function to complete the task") - } + fun squareOfSum() = (1..square) + .sum() + .let { it * it } - fun difference() { - TODO("Implement the function to complete the task") - } -} + fun difference() = squareOfSum() - sumOfSquares() +} \ No newline at end of file diff --git a/exercises/practice/dnd-character/src/main/kotlin/DndCharacter.kt b/exercises/practice/dnd-character/src/main/kotlin/DndCharacter.kt index 4c219d00..c4284af0 100644 --- a/exercises/practice/dnd-character/src/main/kotlin/DndCharacter.kt +++ b/exercises/practice/dnd-character/src/main/kotlin/DndCharacter.kt @@ -1,22 +1,25 @@ +import java.lang.Math.floorDiv +import kotlin.random.Random + class DndCharacter { - val strength: Int = TODO("Initialize value to complete the task") - val dexterity: Int = TODO("Initialize value to complete the task") - val constitution: Int = TODO("Initialize value to complete the task") - val intelligence: Int = TODO("Initialize value to complete the task") - val wisdom: Int = TODO("Initialize value to complete the task") - val charisma: Int = TODO("Initialize value to complete the task") - val hitpoints: Int = TODO("Initialize value to complete the task") + val strength = ability() + val dexterity = ability() + val constitution = ability() + val intelligence = ability() + val wisdom = ability() + val charisma = ability() + val hitpoints = 10 + modifier(constitution) companion object { - fun ability(): Int { - TODO("Implement the function to complete the task") - } + fun ability() = (1..4) + .map { Random.nextInt(1, 6) } + .sorted() + .drop(1) + .sum() - fun modifier(score: Int): Int { - TODO("Implement the function to complete the task") - } + fun modifier(score: Int) = floorDiv(score - 10, 2) } } diff --git a/exercises/practice/flatten-array/.meta/src/reference/kotlin/Flattener.kt b/exercises/practice/flatten-array/.meta/src/reference/kotlin/Flattener.kt index e58b761a..81b65311 100644 --- a/exercises/practice/flatten-array/.meta/src/reference/kotlin/Flattener.kt +++ b/exercises/practice/flatten-array/.meta/src/reference/kotlin/Flattener.kt @@ -4,6 +4,8 @@ object Flattener { return unflattened.filterNotNull().fold(mutableListOf()) { accum, element -> accum.addFlattened(element); accum } } - fun MutableCollection.addFlattened(item: Any) = if (item is Collection<*>) this.addAll(flatten(item)) else this.add(item) + fun MutableCollection.addFlattened(item: Any) = if (item is Collection<*>) + this.addAll(flatten(item)) + else this.add(item) } diff --git a/exercises/practice/flatten-array/src/main/kotlin/Flattener.kt b/exercises/practice/flatten-array/src/main/kotlin/Flattener.kt index 17f24d67..338c23a7 100644 --- a/exercises/practice/flatten-array/src/main/kotlin/Flattener.kt +++ b/exercises/practice/flatten-array/src/main/kotlin/Flattener.kt @@ -1,5 +1,11 @@ object Flattener { - fun flatten(source: Collection): List { - TODO("Implement the function to complete the task") - } + fun flatten(source: Collection): List = source + .filterNotNull() + .flatMap { + if (it is Collection<*>) { + return@flatMap flatten(it) + } else { + listOf(it) + } + } } diff --git a/exercises/practice/gigasecond/.meta/src/reference/kotlin/Gigasecond.kt b/exercises/practice/gigasecond/.meta/src/reference/kotlin/Gigasecond.kt index d353e1ec..cd9f8172 100644 --- a/exercises/practice/gigasecond/.meta/src/reference/kotlin/Gigasecond.kt +++ b/exercises/practice/gigasecond/.meta/src/reference/kotlin/Gigasecond.kt @@ -5,5 +5,5 @@ data class Gigasecond(val initialDateTime: LocalDateTime) { constructor(initialDate: LocalDate): this(initialDate.atTime(0, 0)) - val date = initialDateTime.plusSeconds(1_000_000_000) + val date = ldt.plusSeconds(1_000_000_000) } diff --git a/exercises/practice/gigasecond/src/main/kotlin/Gigasecond.kt b/exercises/practice/gigasecond/src/main/kotlin/Gigasecond.kt index 362906ed..0dff5418 100644 --- a/exercises/practice/gigasecond/src/main/kotlin/Gigasecond.kt +++ b/exercises/practice/gigasecond/src/main/kotlin/Gigasecond.kt @@ -1,8 +1,9 @@ import java.time.LocalDateTime +import java.time.LocalDate -class Gigasecond { +class Gigasecond(val ldt: LocalDateTime) { - // TODO: Implement proper constructor + constructor(ld: LocalDate): this(ld.atTime(0, 0)) - val date: LocalDateTime = TODO("Implement this getter to complete the task") + val date = ldt.plusSeconds(1_000_000_000) } diff --git a/exercises/practice/hamming/src/main/kotlin/Hamming.kt b/exercises/practice/hamming/src/main/kotlin/Hamming.kt index 20162550..f0326de4 100644 --- a/exercises/practice/hamming/src/main/kotlin/Hamming.kt +++ b/exercises/practice/hamming/src/main/kotlin/Hamming.kt @@ -1,6 +1,10 @@ object Hamming { fun compute(leftStrand: String, rightStrand: String): Int { - TODO("Implement this function to complete the task") + if (leftStrand.length != rightStrand.length) throw IllegalArgumentException("left and right strands must be of equal length") + + return leftStrand + .zip(rightStrand) { a, b -> a != b } + .count { it } } } diff --git a/exercises/practice/hello-world/src/main/kotlin/HelloWorld.kt b/exercises/practice/hello-world/src/main/kotlin/HelloWorld.kt index 6adfdeb0..fe21c76f 100644 --- a/exercises/practice/hello-world/src/main/kotlin/HelloWorld.kt +++ b/exercises/practice/hello-world/src/main/kotlin/HelloWorld.kt @@ -1,3 +1 @@ -fun hello(): String { - return "Goodbye, Mars!" -} +fun hello() = "Hello, World!" diff --git a/exercises/practice/luhn/src/main/kotlin/Luhn.kt b/exercises/practice/luhn/src/main/kotlin/Luhn.kt index f2df32ac..bd6199d4 100644 --- a/exercises/practice/luhn/src/main/kotlin/Luhn.kt +++ b/exercises/practice/luhn/src/main/kotlin/Luhn.kt @@ -1,6 +1,21 @@ + object Luhn { fun isValid(candidate: String): Boolean { - TODO("Implement this function to complete the task") + val stripped = candidate.replace(" ", "") + if (!stripped.all { it.isDigit() }) return false + if (stripped.length <= 1) return false + + val sumOdd = (stripped.length - 2 downTo 0 step 2) + .map { stripped[it].digitToInt() } + .sumOf { + val sum = it + it + if (sum > 9) sum - 9 + else sum + } + val sumEven = (stripped.length - 1 downTo 0 step 2) + .sumOf { stripped[it].digitToInt() } + + return (sumOdd + sumEven) % 10 == 0 } -} +} \ No newline at end of file diff --git a/exercises/practice/matrix/src/main/kotlin/Matrix.kt b/exercises/practice/matrix/src/main/kotlin/Matrix.kt index 7ef62f50..815e5b1f 100644 --- a/exercises/practice/matrix/src/main/kotlin/Matrix.kt +++ b/exercises/practice/matrix/src/main/kotlin/Matrix.kt @@ -1,10 +1,18 @@ class Matrix(private val matrixAsString: String) { - fun column(colNr: Int): List { - TODO("Implement this to complete the task") - } + private val matrix = matrixAsString.split("\n") + .withIndex() + .mapNotNull { indexedRow -> + indexedRow.value.split(" ") + .map { it.toInt() } + .takeIf { it.isNotEmpty() } + ?.let { it[0] to it } + } - fun row(rowNr: Int): List { - TODO("Implement this to complete the task") - } + fun column(colNr: Int) = matrix.map { it.second } + .mapNotNull { it.getOrNull(colNr - 1) } + + fun row(rowNr: Int) = matrix.getOrNull(rowNr - 1) + ?.second + ?: emptyList() } diff --git a/exercises/practice/nucleotide-count/src/main/kotlin/Dna.kt b/exercises/practice/nucleotide-count/src/main/kotlin/Dna.kt index 7b264d0e..b7b054ef 100644 --- a/exercises/practice/nucleotide-count/src/main/kotlin/Dna.kt +++ b/exercises/practice/nucleotide-count/src/main/kotlin/Dna.kt @@ -1,9 +1,20 @@ -class Dna { +class Dna(dna: String) { - // TODO: Implement proper constructor + private val map = mutableMapOf( + 'A' to 0, + 'C' to 0, + 'T' to 0, + 'G' to 0, + ) - val nucleotideCounts: Map - get() { - TODO("Implement this function to complete the task") + init { + if (dna.isNotEmpty()) { + require(dna.all { map.keys.contains(it) }) } -} + dna.forEach { + map[it] = map.getOrDefault(it, 0) + 1 + } + } + + val nucleotideCounts = map +} \ No newline at end of file diff --git a/exercises/practice/phone-number/src/main/kotlin/PhoneNumber.kt b/exercises/practice/phone-number/src/main/kotlin/PhoneNumber.kt index d60f1339..1329c102 100644 --- a/exercises/practice/phone-number/src/main/kotlin/PhoneNumber.kt +++ b/exercises/practice/phone-number/src/main/kotlin/PhoneNumber.kt @@ -1,6 +1,22 @@ -class PhoneNumber { - // TODO: Implement proper constructor +class PhoneNumber(plainPhoneNumber: String) { - val number: String? = TODO("Implement this getter to complete the task") -} + var number: String + + init { + val nRange = 2..9 + + number = plainPhoneNumber.filter { it.isDigit() } + .takeIf { + it.length == 11 && it[0] == '1' + || it.length == 10 + } + ?.takeLast(10) + ?.takeIf { + it[0].digitToInt() in nRange + && it[3].digitToInt() in nRange + } + ?: throw IllegalArgumentException() + } + +} \ No newline at end of file diff --git a/exercises/practice/rna-transcription/src/main/kotlin/RnaTranscription.kt b/exercises/practice/rna-transcription/src/main/kotlin/RnaTranscription.kt index f895ae11..07383339 100644 --- a/exercises/practice/rna-transcription/src/main/kotlin/RnaTranscription.kt +++ b/exercises/practice/rna-transcription/src/main/kotlin/RnaTranscription.kt @@ -1 +1,9 @@ -fun transcribeToRna(dna: String): String = "" +fun transcribeToRna(dna: String) = dna.map { + when (it) { + 'A' -> 'U' + 'G' -> 'C' + 'C' -> 'G' + 'T' -> 'A' + else -> it + } +}.joinToString("") diff --git a/exercises/practice/scrabble-score/src/main/kotlin/ScrabbleScore.kt b/exercises/practice/scrabble-score/src/main/kotlin/ScrabbleScore.kt index 212bfda7..dda559c1 100644 --- a/exercises/practice/scrabble-score/src/main/kotlin/ScrabbleScore.kt +++ b/exercises/practice/scrabble-score/src/main/kotlin/ScrabbleScore.kt @@ -1,10 +1,36 @@ object ScrabbleScore { - fun scoreLetter(c: Char): Int { - TODO("Implement this function to complete the task") - } + val scores = mapOf ( + 'a' to 1, + 'e' to 1, + 'i' to 1, + 'o' to 1, + 'u' to 1, + 'l' to 1, + 'n' to 1, + 'r' to 1, + 's' to 1, + 't' to 1, + 'd' to 2, + 'g' to 2, + 'b' to 3, + 'c' to 3, + 'm' to 3, + 'p' to 3, + 'f' to 4, + 'h' to 4, + 'v' to 4, + 'w' to 4, + 'y' to 4, + 'k' to 5, + 'j' to 8, + 'x' to 8, + 'q' to 10, + 'z' to 10, + ) - fun scoreWord(word: String): Int { - TODO("Implement this function to complete the task") - } + + fun scoreLetter(c: Char) = scores.getOrDefault(c.lowercaseChar(), 0) + + fun scoreWord(word: String) = word.sumOf { scoreLetter(it) } } diff --git a/exercises/practice/secret-handshake/src/main/kotlin/HandshakeCalculator.kt b/exercises/practice/secret-handshake/src/main/kotlin/HandshakeCalculator.kt index 24e7cf9b..d6dc2b7b 100644 --- a/exercises/practice/secret-handshake/src/main/kotlin/HandshakeCalculator.kt +++ b/exercises/practice/secret-handshake/src/main/kotlin/HandshakeCalculator.kt @@ -1,5 +1,10 @@ object HandshakeCalculator { + fun calculateHandshake(number: Int): List { - TODO("Implement the function to complete the task") + val signals = Signal.values() + .filter { number shr it.ordinal and 1 == 1 } + + return if (number shr 4 and 1 == 1) signals.asReversed() + else signals } -} +} \ No newline at end of file diff --git a/exercises/practice/triangle/src/main/kotlin/Triangle.kt b/exercises/practice/triangle/src/main/kotlin/Triangle.kt index 91790f9d..af110fef 100644 --- a/exercises/practice/triangle/src/main/kotlin/Triangle.kt +++ b/exercises/practice/triangle/src/main/kotlin/Triangle.kt @@ -1,8 +1,16 @@ +import java.lang.IllegalArgumentException + class Triangle(val a: T, val b: T, val c: T) { - // TODO: Implement proper constructor + init { + require(a > 0 && b > 0 && c > 0) { "Sides must be > 0" } + require(a + b >= c && b + c >= a && c + a >= b) { "Sides must satisfy triangle inequality" } + } + + val isEquilateral: Boolean = a == b && b == c + val isIsosceles: Boolean = a == b || b == c || a == c + val isScalene: Boolean = a != b && b != c && a != c - val isEquilateral: Boolean = TODO("Implement this getter to complete the task") - val isIsosceles: Boolean = TODO("Implement this getter to complete the task") - val isScalene: Boolean = TODO("Implement this getter to complete the task") + private infix operator fun T.compareTo(other: T): Int = this.toDouble().compareTo(other.toDouble()) + private infix operator fun T.plus(b: T): Double = this.toDouble().plus(b.toDouble()) } diff --git a/exercises/practice/two-fer/src/main/kotlin/TwoFer.kt b/exercises/practice/two-fer/src/main/kotlin/TwoFer.kt index b0496de0..32b9c6fb 100644 --- a/exercises/practice/two-fer/src/main/kotlin/TwoFer.kt +++ b/exercises/practice/two-fer/src/main/kotlin/TwoFer.kt @@ -1,3 +1 @@ -fun twofer(name: String): String { - TODO("Implement the function to complete the task") -} +fun twofer(name: String? = null) = "One for ${name ?: "you"}, one for me."