Last active
August 29, 2015 14:13
-
-
Save rnapier/7e3887ab248c43f0b44d to your computer and use it in GitHub Desktop.
Mutable version of addlist (see https://gist.github.com/rnapier/7a552b7f8f089b0d91f6)
This file contains 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
/* | |
Adds two linked lists together e.g. 1->2->3 + 4->5->6 = 5->7->9 | |
Each element is between 0 and 9 | |
This version uses a mutable data structure, which is trickier to use correctly, | |
but may work better for enormous lists. | |
It avoids recursion, which increases the number of vars required. | |
*/ | |
final class Node: Printable, SequenceType { // Struct would be nicer here, but then we'd have to use boxing on next. | |
var data: Int | |
var next: Node? | |
init(data: Int, next: Node?) { | |
self.data = data | |
self.next = next | |
} | |
func lastNode() -> Node { | |
var lastNode = self | |
while (true) { | |
if let next = lastNode.next { | |
lastNode = next | |
} else { | |
return lastNode | |
} | |
} | |
} | |
func append(node: Node) { | |
self.lastNode().next = node | |
} | |
func toArray() -> [Int] { | |
var result = [Int]() | |
for n in self { | |
result.append(n) | |
} | |
return result | |
} | |
// It may seem frustrating that the compiler forces you to have Node? here, but | |
// it's actually exactly what you want. Because an empty list is nil, you really | |
// can very seldom consider a concrete Node. It's almost always going to be a | |
// Node? So any caller is going to want that. | |
func reverse() { | |
let values = self.toArray() | |
var node: Node? = self | |
for value in self.toArray().reverse() { | |
node?.data = value | |
node = node?.next | |
} | |
} | |
func copy() -> Node? { | |
return Node(values: self.toArray()) | |
} | |
/// | |
/// All the rest of this is just convenience stuff to make it easier to use | |
/// | |
init?<G: GeneratorType where G.Element == Int>(var generator: G) { | |
if let data = generator.next() { | |
self.data = data | |
self.next = Node(generator: generator) | |
} else { | |
self.data = 0 | |
self.next = nil | |
return nil | |
} | |
} | |
convenience init?<S: SequenceType where S.Generator.Element == Int>(values: S) { | |
self.init(generator: values.generate()) | |
} | |
var description: String { | |
if let next = self.next { | |
return "\(self.data) -> \(next)" | |
} else { | |
return "\(self.data)" | |
} | |
} | |
// This just lets us use "for...in" on Nodes, which is handy | |
typealias Generator = GeneratorOf<Int> | |
func generate() -> Generator { | |
var next:Node? = self | |
return GeneratorOf { | |
let current = next?.data | |
next = next?.next | |
return current | |
} | |
} | |
} | |
// This is just a helper for addLists | |
private func addReversedLists(var list1: Node?, var list2: Node?, carry: Int) -> Node? { | |
var result: Node? | |
var lastNode: Node? | |
var data: Int | |
var carry = 0 | |
while (list1 != nil || list2 != nil) { | |
let value = (list1?.data ?? 0) + (list2?.data ?? 0) + carry | |
(data, carry) = (value < 10) ? (value, 0) : (value - 10, 1) | |
let newNode = Node(data: data, next: nil) | |
if (lastNode != nil) { | |
lastNode?.next = newNode | |
lastNode = newNode | |
} else { | |
result = newNode | |
lastNode = newNode | |
} | |
list1 = list1?.next | |
list2 = list2?.next | |
} | |
if carry == 1 { | |
lastNode?.next = Node(data: 1, next: nil) | |
} | |
return result | |
} | |
func addLists(list1: Node?, list2: Node?) -> Node? { | |
let rev1 = list1?.copy() | |
rev1?.reverse() | |
let rev2 = list2?.copy() | |
rev2?.reverse() | |
let sum = addReversedLists(rev1, rev2, 0) | |
sum?.reverse() | |
return sum | |
} | |
let list1 = Node(values: [8, 2, 3]) | |
let list2 = Node(values: [4, 5, 9]) | |
let sum = addLists(list1, list2) | |
println(list1) | |
println(list2) | |
println(sum) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment