(...as I still learning Kotlin) I found this "problem":
You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
This is my solution so far:
fun add(a: IntArray, b: IntArray): Iterable<Int> {
val result: MutableList<Int> = mutableListOf()
var remainder = 0
for (i in 0..Math.max(a.size, b.size) - 1) {
val sum = a.elementAtOrElse(i, { 0 }) + b.elementAtOrElse(i, { 0 }) + remainder
remainder = if (sum >= 10) 1 else 0
result.add(if (remainder >= 1) sum - 10 else sum)
}
if (remainder > 0) result.add(remainder)
return result
}
...test cases:
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
class AddTwoNumbersTest {
@Test
fun test_Add() {
assertThat(add(intArrayOf(9, 6, 9, 5, 9), intArrayOf(1, 5, 1, 6, 1))).isEqualTo(listOf(0, 2, 1, 2, 1, 1))
assertThat(add(intArrayOf(4, 1, 8, 7, 2), intArrayOf(9, 4, 1, 0, 3))).isEqualTo(listOf(3, 6, 9, 7, 5))
assertThat(add(intArrayOf(2, 2, 3, 3), intArrayOf(4, 5, 6, 7))).isEqualTo(listOf(6, 7, 9, 0, 1))
assertThat(add(intArrayOf(4, 1, 0, 8), intArrayOf(2, 2, 7, 6))).isEqualTo(listOf(6, 3, 7, 4, 1))
assertThat(add(intArrayOf(2, 7, 1, 0), intArrayOf(0, 0, 8, 1))).isEqualTo(listOf(2, 7, 9, 1))
assertThat(add(intArrayOf(9, 9, 9), intArrayOf(9, 9, 9))).isEqualTo(listOf(8, 9, 9, 1))
assertThat(add(intArrayOf(9, 3, 7), intArrayOf(8, 7, 8))).isEqualTo(listOf(7, 1, 6, 1))
assertThat(add(intArrayOf(6, 6, 6), intArrayOf(7, 8, 9))).isEqualTo(listOf(3, 5, 6, 1))
assertThat(add(intArrayOf(0, 0, 0), intArrayOf(0, 0, 0))).isEqualTo(listOf(0, 0, 0))
assertThat(add(intArrayOf(2, 4, 3), intArrayOf(5, 6, 4))).isEqualTo(listOf(7, 0, 8))
assertThat(add(intArrayOf(0, 1), intArrayOf(0, 1, 2))).isEqualTo(listOf(0, 2, 2))
assertThat(add(intArrayOf(4, 6), intArrayOf(6, 4))).isEqualTo(listOf(0, 1, 1))
assertThat(add(intArrayOf(1), intArrayOf(9, 9))).isEqualTo(listOf(0, 0, 1))
assertThat(add(intArrayOf(), intArrayOf(0, 1))).isEqualTo(listOf(0, 1))
assertThat(add(intArrayOf(), intArrayOf())).isEmpty()
}
}
It works so far...so I'm wondering if you can improve this one, or have a better approach. Notice I use everything the language offer.
-
\$\begingroup\$ FYI: The "problem" calls for linked lists but you've used arrays. You might consider converting the Java code to Kotlin using IntelliJ IDEA or try.kotlinlang.org. \$\endgroup\$mfulton26– mfulton262017年01月01日 04:19:48 +00:00Commented Jan 1, 2017 at 4:19
-
\$\begingroup\$ But leetcode has no support to judge your solution with Kotlin. \$\endgroup\$Chao– Chao2017年05月29日 23:20:04 +00:00Commented May 29, 2017 at 23:20
1 Answer 1
- Using
add
as a function name seems very ambiguous. The method name used in the JavaSolution
class from LeetCode seems more appropriate:addTwoNumbers
(thereby specifying that the arguments, although not numbers themselves, represent numbers). You can remove the explicit type specification for
var result
if you add explicit type arguments tomutableListOf()
. I personally find this more readable and less verbose:var result = mutableListOf<Int>()
You can use
start until endExclusive
instead ofstart..endInclusive - 1
:for (i in 0 until Math.max(a.size, b.size))
You can use the slightly shorter
getOrElse
instead ofelementAtOrElse
. You can also move trailing lambda arguments out of parentheses:val sum = a.getOrElse(i) { 0 } + b.getOrElse(i) { 0 } + remainder
You can use an overloaded operator for adding elements to a mutable list:
result += if (remainder >= 1) sum - 10 else sum
I wouldn't use
remainder >= 1
orremainder > 0
because it makes it appear thatremainder
can be greater than1
which is not true. I recommend usingremainder == 1
.
Altogether:
fun addTwoNumbers(a: IntArray, b: IntArray): Iterable<Int> {
val result = mutableListOf<Int>()
var remainder = 0
for (i in 0 until Math.max(a.size, b.size)) {
val sum = a.getOrElse(i) { 0 } + b.getOrElse(i) { 0 } + remainder
remainder = if (sum >= 10) 1 else 0
result += if (remainder == 1) sum - 10 else sum
}
if (remainder == 1) result.add(1)
return result
}
However, the "problem" specified in LeetCode does not use arrays which are very different from linked lists. If you convert the Java code it provides you would get the following:
/**
* Definition for singly-linked list.
* class ListNode internal constructor(internal var `val`: Int) {
* internal var next: ListNode? = null
* }
*/
class Solution {
fun addTwoNumbers(l1: ListNode, l2: ListNode): ListNode {
}
}
Solving such a problem should result in a very different solution than what you've arrived at.
-
\$\begingroup\$ Yeah, I'm aware the solution would be completely different if I have to use their
ListNode
type; but I'm just "playing" with Kotlin right now, so I'm not pursuing the problem's solution as it's written, but something close that let me practice. BTW, your observations/recommendations are pretty cool...all of them! \$\endgroup\$user69627– user696272017年01月05日 16:33:17 +00:00Commented Jan 5, 2017 at 16:33 -
\$\begingroup\$ Yeah, I would avoid using their
ListNode
too. :-) I'm glad I could help. An exercise in Kotlin that would be more similar and perhaps more entertaining would be to useSequence<Int>
instead ofIntArray
.IntArray
allows random access to its elements and the size/length is known up front whileSequence<Int>
does not and it would be inefficient to convert theSequence<Int>
toIntArray
,List<Int>
, etc. \$\endgroup\$mfulton26– mfulton262017年01月05日 16:37:24 +00:00Commented Jan 5, 2017 at 16:37