Skip to content

Instantly share code, notes, and snippets.

@jrr6
Last active January 20, 2021 20:38
Show Gist options
  • Select an option

  • Save jrr6/33645b27f1d2c56c93a8e9f784de210e to your computer and use it in GitHub Desktop.

Select an option

Save jrr6/33645b27f1d2c56c93a8e9f784de210e to your computer and use it in GitHub Desktop.
An implementation of triple ref pointers in Swift, primarily to disprove Professor Brailsford from the relevant Computerphile video (https://www.youtube.com/watch?v=1s0w_p5HEuY).
// An implementation of the Triple-Ref method as described here: https://www.youtube.com/watch?v=0ZEX_l0DFK0
// The original C code is here: http://www.eprg.org/computerphile/tripref.c
// Mark - Main code
import Foundation
prefix operator *
extension Optional where Wrapped == UnsafeMutablePointer<Any> {
static prefix func *(item: UnsafeMutablePointer<T>?) -> T {
return item?.pointee
}
static prefix func *<Q>(item: UnsafeMutablePointer<Q>?) -> Q? {
return item?.pointee
}
}
extension UnsafeMutablePointer {
static prefix func *(item: UnsafeMutablePointer) -> Pointee {
return item.pointee
}
}
typealias P<C> = UnsafeMutablePointer<C>
struct Thing {
var item: String
var next: P<Thing>?
init(_ item: String, _ next: P<Thing>?) {
self.item = item
self.next = next
}
}
typealias T = P<Thing>?
typealias TT = P<T>?
var start: T = nil
func insertThing(_ head: TT, _ newp: UnsafeMutablePointer<Thing>) {
var tracer: TT = head
while let pointee = *tracer, (*pointee).item < (*newp).item {
tracer = P(&pointee.pointee.next)
}
newp.pointee.next = *tracer
tracer?.pointee = newp
}
func removeThing(_ head: TT, _ text: String) {
var tracer: TT = head
while let pointee = *tracer, (*pointee).item != text {
tracer = P(&pointee.pointee.next)
}
if let pointee = *tracer {
var old: T = *tracer
tracer?.pointee = P(pointee.pointee.next)
// old item is automatically dealloced by ARC
}
}
// MARK: - Logging
var arrowStr = "\t\t↓"
var sepStr = "-----------------------------------------"
func addrStr(_ addr: String) -> String {
return addr != "NULL" ? "\t\(addr)\t" : "\t \(addr) \t\t\t"
}
func itemStr(_ item: String) -> String {
return "\t\(item)\t"
}
func printList() {
print(sepStr)
var head: T = start
print("|\(addrStr(head?.debugDescription ?? "NULL"))| ← START\n\(arrowStr)")
while let cur = *head {
let item = cur.item
let next = cur.next?.debugDescription ?? "NULL"
print("|\(addrStr(next))|\(itemStr(item))|")
if next != "NULL" {
print(arrowStr)
}
head = cur.next
}
print(sepStr)
print()
}
// MARK: - Demo
printList()
var thing1 = Thing("chips", nil)
insertThing(P(&start), P(&thing1))
printList()
var thing2 = Thing("pizza", nil)
insertThing(P(&start), P(&thing2))
printList()
var thing3 = Thing("burgers", nil)
insertThing(P(&start), P(&thing3))
printList()
var thing4 = Thing("zucchini", nil)
insertThing(P(&start), P(&thing4))
printList()
removeThing(P(&start), "pizza")
printList()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment