Skip to content

Instantly share code, notes, and snippets.

@rnapier
Last active August 29, 2015 14:13
Show Gist options
  • Save rnapier/7a552b7f8f089b0d91f6 to your computer and use it in GitHub Desktop.
Save rnapier/7a552b7f8f089b0d91f6 to your computer and use it in GitHub Desktop.
/*
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