Skip to content

Commit

Permalink
Changes to Luhn tests and sample implementation. Fixes exercism#24
Browse files Browse the repository at this point in the history
  • Loading branch information
nithia committed Feb 26, 2017
1 parent 0ad2df9 commit 0150815
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 64 deletions.
44 changes: 18 additions & 26 deletions exercises/luhn/src/example/kotlin/Luhn.kt
Original file line number Diff line number Diff line change
@@ -1,37 +1,29 @@
data class Luhn(val number: Long) {
object Luhn {

val checkDigit: Int by lazy { checkDigit(number) }
fun isValid(candidate: String): Boolean =
isValidCandidate(candidate) && checksum(number(candidate)) == 0

val addends: List<Int> by lazy {
digits(number).withIndex().reversed()
.map { if (isOdd(it.index)) dbl(it.value) else it.value }
}
private fun isValidCandidate(candidate: String): Boolean =
candidate.filter(Char::isDigit).length > 1 &&
candidate.all { it.isDigit() || Character.isSpaceChar(it) }

val checksum: Int by lazy { addends.sum() }
private fun number(candidate: String) = candidate.filter(Char::isDigit).toLong()

val isValid: Boolean by lazy { checksum % 10 == 0 }
private fun checksum(number: Long) = addends(number).sum() % 10

val create: Long by lazy {
val zeroCheckDigitNumber = number * 10
val luhn = Luhn(zeroCheckDigitNumber)
private fun addends(number: Long): List<Int> = digits(number).withIndex().reversed()
.map { if (isOdd(it.index)) dbl(it.value) else it.value }

if (luhn.isValid) zeroCheckDigitNumber else zeroCheckDigitNumber + (10 - luhn.checksum % 10)
private fun digits(n: Long): List<Int> = when (n) {
0L -> emptyList()
else -> listOf((n % 10).toInt()) + digits(n / 10)
}

companion object {
private fun checkDigit(n: Long) = (n % 10).toInt()

private fun digits(n: Long): List<Int> = when (n) {
0L -> emptyList()
else -> listOf(checkDigit(n)) + digits(n / 10)
}

private fun dbl(n: Int): Int {
val dbled = n * 2
return if (dbled > 10) dbled - 9 else dbled
}

private fun isOdd(i: Int) = i % 2 == 1
private fun dbl(n: Int): Int {
val dbled = n * 2
return if (dbled > 9) dbled - 9 else dbled
}

private fun isOdd(i: Int) = i % 2 == 1

}
78 changes: 40 additions & 38 deletions exercises/luhn/src/test/kotlin/LuhnTest.kt
Original file line number Diff line number Diff line change
@@ -1,86 +1,88 @@
import org.junit.Test
import org.junit.Ignore
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

class LuhnTest {


@Test
fun checkDigitIsRightMostDigit() {
val expectedOutput = 7

assertEquals(expectedOutput, Luhn(34567).checkDigit)
fun singleDigitStringsCannotBeValid() {
assertFalse(Luhn.isValid("1"))
}

@Ignore
@Test
fun addendsDoublesEveryOtherNumberFromRight() {
val expectedOutput = listOf(1, 4, 1, 4, 1)

assertEquals(expectedOutput, Luhn(12121).addends)
fun singleZeroIsInvalid() {
assertFalse(Luhn.isValid("0"))
}

@Ignore
@Test
fun addendsSubtracts9WhenDoubledNumberIsMoreThan9() {
val expectedOutput = listOf(7, 6, 6, 1)

assertEquals(expectedOutput, Luhn(8631).addends)
fun simpleValidSINThatRemainsValidIfReversed() {
assertTrue(Luhn.isValid("059"))
assertTrue(Luhn.isValid("950"))
}

@Ignore
@Test
fun checkSumAddsAddendsTogether1() {
val expectedOutput = 22

assertEquals(expectedOutput, Luhn(4913).checksum)
fun simpleValidSINThatBecomesInvalidIfReversed() {
assertTrue(Luhn.isValid("59"))
assertFalse(Luhn.isValid("95"))
}

@Ignore
@Test
fun checkSumAddsAddendsTogether2() {
val expectedOutput = 21

assertEquals(expectedOutput, Luhn(201773).checksum)
fun validCanadianSIN() {
assertTrue(Luhn.isValid("055 444 285"))
}

@Ignore
@Test
fun numberIsValidWhenChecksumMod10IsZero1() {
val expectedOutput = false

assertEquals(expectedOutput, Luhn(738).isValid)
fun invalidCanadianSIN() {
assertFalse(Luhn.isValid("055 444 286"))
}

@Ignore
@Test
fun numberIsValidWhenChecksumMod10IsZero2() {
val expectedOutput = true

assertEquals(expectedOutput, Luhn(8739567).isValid)
fun invalidCreditCard() {
assertFalse(Luhn.isValid("8273 1232 7352 0569"))
}

@Ignore
@Test
fun luhnCanCreateSimpleNumbersWithValidCheckDigit() {
val expectedOutput = 1230L
fun validStringsWithNonDigitIncludedBecomeInvalid() {
assertFalse(Luhn.isValid("055a 444 285"))
}

assertEquals(expectedOutput, Luhn(123).create)
@Ignore
@Test
fun validStringsWithPunctuationIncludedBecomeInvalid() {
assertFalse(Luhn.isValid("055-444-285"))
}

@Ignore
@Test
fun luhnCanCreateLargeNumbersWithValidCheckDigit() {
val expectedOutput = 8739567L
fun validStringsWithSymbolsIncludedBecomeInvalid() {
assertFalse(Luhn.isValid("055£ 444$ 285"))
}

assertEquals(expectedOutput, Luhn(873956).create)
@Ignore
@Test
fun singleZeroWithSpaceIsInvalid() {
assertFalse(Luhn.isValid(" 0"))
}

@Ignore
@Test
fun luhnCanCreateHugeNumbersWithValidCheckDigit() {
val expectedOutput = 8372637564L
fun moreThanSingleZeroIsValid() {
assertTrue(Luhn.isValid("0000 0"))
}

assertEquals(expectedOutput, Luhn(837263756).create)
@Ignore
@Test
fun inputDigit9IsCorrectlyConvertedToOutputDigit9() {
assertTrue(Luhn.isValid("091"))
}

}

0 comments on commit 0150815

Please sign in to comment.