/* | |
Small program written to automate the sorting of Secret Santas as initially brought to my attention by Brent Simmons (http://inessential.com/2015/09/25/a_secret_santa_solution). | |
*/ | |
import Foundation | |
let DEBUG = false | |
class Person: Equatable { | |
var first: String | |
var last: String | |
var email: String | |
var match: Person? | |
var matched = false | |
init(first: String, last: String, email: String, match: Person?) { | |
self.first = first | |
self.last = last | |
self.email = email | |
self.match = match | |
} | |
func canBeSantaOf(p: Person) -> Bool { | |
return self.match == nil && self.last != p.last && !p.matched | |
} | |
} | |
func ==(lhs: Person, rhs: Person) -> Bool { | |
return lhs.first == rhs.first && lhs.last == rhs.last | |
} | |
var people = [Person]() | |
let standardInput = NSFileHandle.fileHandleWithStandardInput() | |
let input = standardInput.availableData | |
let str = NSString(data: input, encoding: NSUTF8StringEncoding) as! String | |
let linesArr = str.characters.split{$0 == "\n"}.map(String.init) | |
for line in linesArr { | |
let details = line.characters.split{$0 == " "}.map(String.init) | |
let p = Person(first: details[0], last: details[1], email: details[2], match: nil) | |
people.append(p) | |
} | |
var validInput = true | |
if people.count > 1 { | |
var currIdx = 0 | |
var pos = 1 | |
var curr = people[currIdx] | |
var possible = people[pos] | |
// Effectively we're treating our array of people as a circular list | |
// that we navigate "top" to "bottom" until we can find a valid match | |
// or until we run back into ourselves at which point we exit with | |
// no match. This no match will then be confirmed by our validation | |
// at the end of the program. | |
while curr.match == nil && curr != possible { | |
if DEBUG { | |
print("curr: \(curr.first)") | |
print("possible: \(possible.first)") | |
print("pos: \(pos)") | |
print("currIdx: \(currIdx)") | |
print("*****") | |
} | |
if curr.canBeSantaOf(possible) { | |
if DEBUG { | |
print("Matching \(curr.first) with \(possible.first)") | |
} | |
curr.match = possible | |
possible.matched = true | |
currIdx++ | |
if currIdx >= people.count { | |
currIdx = 0 | |
} | |
curr = people[currIdx] | |
pos = currIdx + 1 | |
if pos >= people.count { | |
pos = 0 | |
} | |
possible = people[pos] | |
} else { | |
pos++ | |
if pos >= people.count { | |
pos = 0 | |
} | |
possible = people[pos] | |
} | |
} | |
} else { | |
validInput = false | |
} | |
// Finally, validate our results by doing a once-over on the array of people | |
for p in people { | |
if p.match == nil || p.matched == false { | |
validInput = false | |
} | |
} | |
print("************* RESULTS **************") | |
if !validInput { | |
print("Invalid input according to rules of Secret Santa matching") | |
} else { | |
for p in people { | |
print("\(p.first) \(p.last) matched \(p.match!.first) \(p.match!.last)") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment