Skip to content

Instantly share code, notes, and snippets.

@manicai
Created May 3, 2011 20:36
Show Gist options
  • Save manicai/954175 to your computer and use it in GitHub Desktop.
Save manicai/954175 to your computer and use it in GitHub Desktop.
Olympic Ticket Inferer
#!/usr/bin/env python
#
# Find prices of all possibilities of ticket allocations in the London
# 2012 Olympic lottery.
#
from itertools import chain, combinations
import re
import fileinput
def remove_pound(s):
"Strip the pound sign from a cost."
match = re.search('\d+\.\d{2}', s)
return float(match.group(0))
class Session:
def __init__(self):
self.sport = ''
self.code = ''
self.datetime = ''
self.venue = ''
self.price_category = ''
self.quantity = ''
self.total_cost = ''
self.maximum_cost = ''
@property
def cost(self):
return remove_pound(self.total_cost)
@property
def max_cost(self):
return remove_pound(self.maximum_cost)
def __str__(self):
return "%s (%s)" % (self.sport, self.code)
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Postage_Cost = 6
def calculate_prices(options, overhead = Postage_Cost):
prices = {}
for tickets in powerset(options):
single_price = [t for t in tickets if t.max_cost == t.cost]
dual_price = [t for t in tickets if t not in single_price]
assert len(single_price) + len(dual_price) == len(tickets)
for high_priced in powerset(dual_price):
rest = [t for t in tickets if t not in high_priced]
cost = sum(session.max_cost for session in high_priced)
cost += sum(session.cost for session in rest)
if cost > 0:
cost += overhead
seats = list(chain([str(s) + '*' for s in high_priced],
[str(s) for s in rest]))
prices.setdefault(cost, []).append(seats)
return prices
Fields = { 'Session code' : 'code',
'Date/time' : 'datetime',
'Venue' : 'venue',
'Price Category' : 'price_category',
'Quantity' : 'quantity',
'Total cost' : 'total_cost',
'Total maximum cost' : 'maximum_cost' }
def parse_email(line_iter):
sessions = []
current = None
for line in line_iter:
sport = re.match("\s+Sport: (.+)", line)
if sport:
if current:
sessions.append(current)
current = Session()
current.sport = sport.group(1)
elif current:
for field, attribute in Fields.items():
regexp = '\s+%s: (.+)' % field
match = re.match(regexp, line)
if match:
setattr(current, attribute, match.group(1))
break
if current:
sessions.append(current)
return sessions
if __name__ == '__main__':
sessions = parse_email(fileinput.input())
possibilities = calculate_prices(sessions)
for price in sorted(possibilities):
for seats in possibilities[price]:
print '%10.2f : %s' % (price, ', '.join(seats))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment