Skip to content

Instantly share code, notes, and snippets.

@robfletcher
Last active February 18, 2016 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robfletcher/6065cf6560276df3fea6 to your computer and use it in GitHub Desktop.
Save robfletcher/6065cf6560276df3fea6 to your computer and use it in GitHub Desktop.
The diamond kata in Kotlin
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)
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))
}
@DanielThomas
Copy link

Slick!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment