Last active
February 18, 2016 16:09
-
-
Save robfletcher/6065cf6560276df3fea6 to your computer and use it in GitHub Desktop.
The diamond kata in Kotlin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun diamond(c: Char): String { | |
if (c !in 'A'..'Z') throw IllegalArgumentException() | |
return ('A'..c) | |
.map(row(c)) | |
.mirrorDown() | |
.joinToString("\n") | |
} | |
private fun row(max: Char) = { next: Char -> | |
"$next" | |
.padStart((next - 'A') + 1, '-') | |
.padEnd((max - 'A') + 1, '-') | |
.mirrorLeft() | |
} | |
private fun String.mirrorLeft() = | |
slice(lastIndex downTo 1) + this | |
private fun <T> List<T>.mirrorDown() = | |
this + slice(lastIndex - 1 downTo 0) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.jetbrains.spek.api.* | |
import kotlin.test.assertTrue | |
class DiamondSpec : Spek() { | |
init { | |
given("an invalid character") { | |
listOf('$', 'a', 'z', ' ').forEach { c -> | |
on("trying to draw the diamond of $c") { | |
it("should throw an exception") { | |
shouldThrow(IllegalArgumentException::class.java) { | |
diamond(c) | |
} | |
} | |
} | |
} | |
} | |
given("a valid character") { | |
on("drawing the diamond of 'A'") { | |
val result = diamond('A') | |
it("should be 'A'") { | |
shouldEqual("A", result) | |
} | |
} | |
('B'..'Z').forEach { c -> | |
on("drawing the diamond of '$c'") { | |
val result = diamond(c) | |
val rows = result.split("\n") | |
it("has rows whose lengths are all the same") { | |
shouldBeTrue(rows.all { it.length == rows[0].length }) | |
} | |
it("is square") { | |
shouldEqual(rows[0].length, rows.size) | |
} | |
val expectedSize = (c - 'A') * 2 + 1 | |
it("has $expectedSize rows") { | |
shouldEqual(expectedSize, rows.size) | |
} | |
it("is vertically symmetrical") { | |
shouldEqual(rows.reversed(), rows) | |
} | |
it("is horizontally symmetrical") { | |
shouldBeTrue(rows.all { it == it.reversed() }) | |
} | |
('A'..c).forEach { rowChar -> | |
val row = rowChar - 'A' | |
val col = c - rowChar | |
it("has a '$rowChar' at row $row column $col") { | |
shouldEqual(rowChar, rows[row][col]) | |
} | |
it("has nothing but '-' in the rest of row $row") { | |
shouldMatch( | |
Regex("^-+$"), | |
rows[row].halve().replaceFirst(rowChar, '-') | |
) | |
} | |
} | |
} | |
} | |
} | |
} | |
fun It.shouldMatch(expected: Regex, actual: String) = | |
assertTrue( | |
actual.matches(expected), | |
"Expected a match for $expected but found $actual" | |
) | |
fun String.halve() = | |
slice(0..(length / 2)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Slick!