Created
October 21, 2015 17:19
-
-
Save syoutsey/36fd27c2ffd4fb661c55 to your computer and use it in GitHub Desktop.
Implementation of Secret Santa sort
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
/* | |
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