Last active
August 29, 2015 14:13
-
-
Save rnapier/7a552b7f8f089b0d91f6 to your computer and use it in GitHub Desktop.
Another version of addlist: https://gist.github.com/mbatilando/3d1b3e391418ac56b13c
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 | |
*/ | |
final class Node: Printable, SequenceType { // Struct would be nicer here, but then we'd have to use boxing on next. | |
let data: Int | |
let next: Node? | |
init(data: Int, next: Node?) { | |
self.data = data | |
self.next = next | |
} | |
// This will overfow the stack if your list is enormous, but is fine for reasonable-length lists. | |
func append(node: Node) -> Node { | |
if let next = self.next { | |
return Node(data: self.data, next: next.append(node)) | |
} else { | |
return Node(data: self.data, 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() -> Node? { | |
return Node(values: self.toArray().reverse()) | |
} | |
/// | |
/// 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(list1: Node?, list2: Node?, carry: Int) -> Node? { | |
if (list1 == nil && list2 == nil) { | |
return (carry == 1) ? Node(data: 1, next: nil) : nil | |
} | |
let value = (list1?.data ?? 0) + (list2?.data ?? 0) + carry | |
let (data, carry) = (value < 10) ? (value, 0) : (value - 10, 1) | |
return Node(data: data, next: addReversedLists(list1?.next, list2?.next, carry)) | |
} | |
func addLists(list1: Node?, list2: Node?) -> Node? { | |
return addReversedLists(list1?.reverse(), list2?.reverse(), 0)?.reverse() | |
} | |
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