Skip to content

Instantly share code, notes, and snippets.

@asethia
Last active July 23, 2018 03:46
Show Gist options
  • Save asethia/59db7cd724c55e6cff885ee5bb534d40 to your computer and use it in GitHub Desktop.
Save asethia/59db7cd724c55e6cff885ee5bb534d40 to your computer and use it in GitHub Desktop.
SumList - sum of two link list result as link list
import org.scalatest.{Matchers, WordSpec}
import scala.annotation.tailrec
/**
* You have two numbers represented by a linked list, where each node contains a single digit.
* The digits are stored in reverse order, such that the 1's digit is at the head of the list.
* Write a function that adds the two numbers and returns the sum as a linked list.
*
* Assumptions: both list has equal number of nodes
*
* for example (7-> 1 -> 6->Nil) + (5-> 9 -> 2-> Nil).That is,617 + 295 = 912
* output will be : 2->1->9-Nil return new linklist
*
* for example (9-> 8 -> 7-> 6-> Nil) + (9-> 8 -> 7-> 6-> Nil) that will be 6789+6789=13578
* output will be : 8->7->5-3->1->Nil return new linklist
*
* time complexity O(n+n)
* space complexity O(n) //new linklist
*
* Created by Arun Sethia on 7/22/18.
*/
trait Linklist {
/**
* abstract Node
*/
abstract class AbstractNode {
def data: Int
def next: AbstractNode
}
/**
* Nil Node to indicate end of link list
*/
object NilNode extends AbstractNode {
def data = 0
override def toString() = s"Nil"
def next = throw new UnsupportedOperationException("tail of empty list")
}
/**
* Node class
*
* @param data
* @param next
*/
case class Node(data: Int, next: AbstractNode) extends AbstractNode {
override def toString() = s"data: ${data} next: ${next}"
}
/**
* add new node in the beginning
*
* @param prevNode
*/
implicit class NodeAddItem(prevNode: AbstractNode) {
/**
* it will prepand v with prev node for example
* NilNode.prependItem(10) will be 10->Nil
* Node(1,NilNode).prependItem(2) will be 1->2->Nil
*
* @param v
* @return
*/
def prependItem(v: Int): AbstractNode =
if (prevNode == NilNode) Node(v, NilNode)
else Node(v, NilNode).prepend(prevNode)
/**
* suffix node2 with prevNode
* Node(1,NilNode).prepand(Node(2,NilNode)) will be 2->1->Nil
* @param node2
* @return
*/
def prepend(node2: AbstractNode): AbstractNode = {
if (node2.next != NilNode) prepend(node2.next).prepend(Node(node2.data, NilNode))
else Node(node2.data, prevNode)
}
}
/**
* sum two linklist nodes and create new linklist
* for example (7-> 1 -> 6->Nil) + (5-> 9 -> 2-> Nil).That is,617 + 295 = 912
* output will be : 9->1->2-Nil
*
* @param node1
* @param node2
* @return
*/
def addSumList(node1: AbstractNode, node2: AbstractNode): AbstractNode = {
@tailrec
def sumList(node1: AbstractNode, node2: AbstractNode, finalNode: AbstractNode, carryOver: Int): AbstractNode = {
if (node1.next != NilNode && node2.next != NilNode) {
val (data, newcarryOver) = getSumReminder(node1.data, node2.data, carryOver)
val node = finalNode.prependItem(data)
sumList(node1.next, node2.next, node, newcarryOver)
} else {
val (data, newcarryOver) = getSumReminder(node1.data, node2.data, carryOver)
val tmpNode = finalNode.prependItem(data)
//add carryover for final result
if (newcarryOver > 0)
tmpNode.prependItem(newcarryOver)
else tmpNode //don't add carryover for final result
}
}
sumList(node1, node2, NilNode, 0)
}
/**
* get sum all number and get sum and carryon for given numbers
*
* @return
*/
private def getSumReminder(d: Int*): (Int, Int) = {
val sum = d.sum
val data = (sum % 10)
val nextCarryon = sum / 10
(data, nextCarryon)
}
}
/**
* test cases for sumList
*/
class LinkSumListSpec extends WordSpec
with Matchers
with Linklist {
"(7-> 1 -> 6->Nil) + (5-> 9 -> 2-> Nil)" should {
"return sum 912 as 2->1->9-Nil" in {
val node1 = Node(7, Node(1, Node(6, NilNode)))
val node2 = Node(5, Node(9, Node(2, NilNode)))
val result = Node(2, Node(1, Node(9, NilNode)))
assert(addSumList(node1, node2) == result)
}
}
"(9-> 8 -> 7-> 6-> Nil) + (9-> 8 -> 7-> 6-> Nil)" should {
"return 13578 as 8->7->5->3->1->Nil" in {
val node1 = Node(9, Node(8, Node(7, Node(6, NilNode))))
val node2 = Node(9, Node(8, Node(7, Node(6, NilNode))))
val result = Node(8, Node(7, Node(5, Node(3, Node(1, NilNode)))))
assert(addSumList(node1, node2) == result)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment