├── README.md ├── setup.py └── skilift.py /README.md: -------------------------------------------------------------------------------- 1 | # skilift 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup(name='skilift', 4 | version='0.1.0', 5 | description='Simulate skilift', 6 | url='http://github.com/mattharrison/skilift', 7 | author='Matt Harrison', 8 | license='MIT', 9 | py_modules=['skilift'], 10 | zip_safe=False) 11 | -------------------------------------------------------------------------------- /skilift.py: -------------------------------------------------------------------------------- 1 | """ 2 | Code for simulating a lift at a ski resort: 3 | 4 | >>> num_benches = 10 5 | >>> bench_class = Quad 6 | >>> lift = Lift(num_benches, bench_class) 7 | >>> line = Line(num_people=10) 8 | >>> lift.simulate(line) 9 | {'loaded': 10, 'unloaded': 10, 'num_benches': 8} 10 | """ 11 | 12 | from collections import deque 13 | 14 | 15 | class Line: 16 | 17 | def __init__(self, num_people): 18 | self.num_people = num_people 19 | 20 | def take(self, amount): 21 | if amount > self.num_people: 22 | amount = self.num_people 23 | self.num_people -= amount 24 | return amount 25 | 26 | def add(self, amount): 27 | self.num_people += amount 28 | 29 | def __bool__(self): 30 | return bool(self.num_people) 31 | 32 | 33 | class _Bench: 34 | size = 1 35 | 36 | def __init__(self, id): 37 | self.count = 0 38 | self.id = id 39 | 40 | def load(self, num): 41 | self.count += num 42 | 43 | def unload(self): 44 | val = self.count 45 | self.count = 0 46 | return val 47 | 48 | 49 | class Quad(_Bench): 50 | size = 4 51 | 52 | 53 | class Lift: 54 | 55 | def __init__(self, num_benches, bench_class): 56 | half = num_benches / 2 57 | self._up = deque() 58 | self._down = deque() 59 | for i in range(num_benches): 60 | if i < half: 61 | self._up.append(bench_class(i)) 62 | else: 63 | self._down.append(bench_class(i)) 64 | self.bench_size = bench_class.size 65 | 66 | def people_riding_up(self): 67 | return any(bench.count for bench in self._up) 68 | 69 | def simulate(self, line): 70 | results = {"loaded": 0, "unloaded": 0, "num_benches": 0} 71 | while line: 72 | self.one_bench(line, results) 73 | # get them to the top 74 | while self.people_riding_up(): 75 | self.one_bench(line, results) 76 | return results 77 | 78 | def one_bench(self, line, results=None): 79 | results = results or {"loaded": 0, "unloaded": 0, "num_benches": 0} 80 | num = line.take(self.bench_size) 81 | # load bottom 82 | bench = self._down.popleft() 83 | bench.load(num) 84 | self._up.append(bench) 85 | results["loaded"] += num 86 | # unload top 87 | bench = self._up.popleft() 88 | num = bench.unload() 89 | results["unloaded"] += num 90 | self._down.append(bench) 91 | results["num_benches"] += 1 92 | return results 93 | 94 | 95 | if __name__ == "__main__": 96 | import doctest 97 | 98 | doctest.testmod() 99 | --------------------------------------------------------------------------------