Last active
August 29, 2015 14:24
-
-
Save imtapps/3048235ad4fd69430c56 to your computer and use it in GitHub Desktop.
Assign seats for roundtable discussions at the customer meeting
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
""" | |
Sort customers into random tables | |
Make sure they do not sit at a table with the same people more than once | |
* 155 customers | |
* 20 tables | |
* 6-8 customers at each table | |
* 6 rounds of switching tables | |
===== | |
To use this just run it until there is only 1 failing test and it fails with "X"... then that output is good | |
""" | |
from __future__ import division | |
from random import shuffle | |
class Duplicate(Exception): | |
pass | |
class Main(object): | |
def __init__(self, tables, attendees): | |
self.tables = range(1, tables + 1) | |
self.attendees = range(1, attendees + 1) | |
self.rounds = [] | |
shuffle(self.attendees) | |
@property | |
def slices(self): | |
return [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6] | |
@property | |
def people_per_table(self): | |
return int(round(len(self.attendees) / len(self.tables))) | |
def init(self): | |
current_round = {} | |
start = 0 | |
for table, peeps in enumerate(self.slices, 1): | |
end = peeps + start | |
current_round[table] = self.attendees[start:end] | |
start = end | |
self.rounds.append(current_round) | |
return current_round | |
def switch(self): | |
v = 1 | |
while True: | |
v += 1 | |
attendees = list(self.attendees) | |
shuffle(attendees) | |
current_round = self.get_new_round(attendees) | |
try: | |
for previous_round in self.rounds: | |
for x in previous_round.values(): | |
for people in current_round.values(): | |
if len(set(x).intersection(set(people))) > 2: | |
raise Duplicate | |
except Duplicate: | |
continue | |
break | |
return current_round | |
def get_new_round(self, attendees): | |
current_round = {} | |
for table, peeps in enumerate(self.slices, 1): | |
people = [] | |
for i in range(peeps): | |
if attendees: | |
people.append(attendees.pop()) | |
current_round[table] = people | |
return current_round | |
import unittest | |
class MainTests(unittest.TestCase): | |
def test_lots(self): | |
result = Main(tables=20, attendees=155).init() | |
self.assertEqual(range(1, 21), result.keys()) | |
for i in range(1, 18): | |
self.assertEqual(8, len(result[i])) | |
self.assertEqual(7, len(result[18])) | |
self.assertEqual(6, len(result[19])) | |
self.assertEqual(6, len(result[20])) | |
def test_does_not_duplicate_on_second_round(self): | |
main = Main(tables=20, attendees=155) | |
result_one = main.init() | |
result_two = main.switch() | |
self.assert_unique(result_one, result_two) | |
def test_does_not_duplicate_on_third_round(self): | |
main = Main(tables=20, attendees=155) | |
result_one = main.init() | |
result_two = main.switch() | |
result_three = main.switch() | |
self.assert_unique(result_one, result_two) | |
self.assert_unique(result_one, result_three) | |
self.assert_unique(result_two, result_three) | |
def test_does_not_duplicate_on_fourth_round(self): | |
main = Main(tables=20, attendees=155) | |
result_one = main.init() | |
result_two = main.switch() | |
result_three = main.switch() | |
result_four = main.switch() | |
self.assert_unique(result_one, result_two) | |
self.assert_unique(result_one, result_three) | |
self.assert_unique(result_two, result_three) | |
self.assert_unique(result_one, result_four) | |
self.assert_unique(result_two, result_four) | |
self.assert_unique(result_three, result_four) | |
def test_does_not_duplicate_on_fifth_round(self): | |
main = Main(tables=20, attendees=155) | |
result_one = main.init() | |
result_two = main.switch() | |
result_three = main.switch() | |
result_four = main.switch() | |
result_five = main.switch() | |
self.assert_unique(result_one, result_two) | |
self.assert_unique(result_one, result_three) | |
self.assert_unique(result_two, result_three) | |
self.assert_unique(result_one, result_four) | |
self.assert_unique(result_two, result_four) | |
self.assert_unique(result_three, result_four) | |
self.assert_unique(result_one, result_five) | |
self.assert_unique(result_two, result_five) | |
self.assert_unique(result_three, result_five) | |
self.assert_unique(result_four, result_five) | |
def test_does_not_duplicate_on_sixth_round(self): | |
main = Main(tables=20, attendees=155) | |
result_one = main.init() | |
result_two = main.switch() | |
result_three = main.switch() | |
result_four = main.switch() | |
result_five = main.switch() | |
result_six = main.switch() | |
self.assert_unique(result_one, result_two) | |
self.assert_unique(result_one, result_three) | |
self.assert_unique(result_two, result_three) | |
self.assert_unique(result_one, result_four) | |
self.assert_unique(result_two, result_four) | |
self.assert_unique(result_three, result_four) | |
self.assert_unique(result_one, result_five) | |
self.assert_unique(result_two, result_five) | |
self.assert_unique(result_three, result_five) | |
self.assert_unique(result_four, result_five) | |
self.assert_unique(result_one, result_six) | |
self.assert_unique(result_two, result_six) | |
self.assert_unique(result_three, result_six) | |
self.assert_unique(result_four, result_six) | |
self.assert_unique(result_five, result_six) | |
self.display_results(result_one) | |
self.display_results(result_two) | |
self.display_results(result_three) | |
self.display_results(result_four) | |
self.display_results(result_five) | |
self.display_results(result_six) | |
self.fail("X") | |
def assert_unique(self, first, second): | |
self.assertEqual(20, len(first)) | |
self.assertEqual(20, len(second)) | |
for table, peeps in first.items(): | |
self.assertGreater(len(peeps), 5) | |
duplicates = len(list(set(peeps).intersection(set(second[table])))) | |
self.assertTrue(duplicates <= 2) | |
def display_results(self, result): | |
print "=" * 80 | |
for table, peeps in result.items(): | |
print "Table: {} People: {}".format(table, peeps) | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment