Skip to content

Instantly share code, notes, and snippets.

@JohannMG
Created April 21, 2022 23:23
Show Gist options
  • Save JohannMG/015af83654692cb8c0db448a1cc36488 to your computer and use it in GitHub Desktop.
Save JohannMG/015af83654692cb8c0db448a1cc36488 to your computer and use it in GitHub Desktop.
Quick little bisector in swift for hashable items for the case when you're not bisecting a linear list.
//
// HashableBisector.swift
// TestHashableBisector
//
// Created by Johann Garces on 4/21/22.
//
import Foundation
enum BisectorState : Equatable {
case unprepared // same
case running
case completed
case error(String)
}
// A lot of bisectors are working with just 2D data, lets make something that works with hashable
class HashableBisector <T: Hashable>{
typealias TypedSet = Set<T>
// When we find the 1 item we fill this value, otherwise it will be nil
private(set) var solution: T?
private(set) var state: BisectorState = .unprepared
// Candidates that are active
private(set) var setInTest = TypedSet()
// Candidates that are not active
private var setOutOfTest = TypedSet()
// Add indices to the lists
func setList(_ list: Set<T>) {
if checkIfSolution(list) { return }
state = .running
setInTest = list
split(&setInTest, into: &setOutOfTest)
}
func testContainsItem(_ containsItem: Bool) {
setInTest = containsItem ? setInTest : setOutOfTest
if checkIfSolution(setInTest) { return }
state = .running
split(&setInTest, into: &setOutOfTest)
}
private func checkIfSolution(_ set: TypedSet) -> Bool {
if set.count == 0 {
state = .error("Oh boy I fucked up")
return true
}
if set.count == 1 {
solution = set.first
state = .completed
return true
}
return false
}
private func split(_ sourceSet: inout TypedSet, into targetSet: inout TypedSet) {
targetSet.removeAll()
let halfCount = sourceSet.count / 2
for _ in 0..<halfCount {
targetSet.insert(sourceSet.removeFirst())
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment