Last active
August 29, 2015 14:25
-
-
Save oskar-j/308aafbb7ae44df7fed1 to your computer and use it in GitHub Desktop.
Find the year with the most number of people alive in Python
This file contains hidden or 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
from collections import Counter | |
from itertools import chain | |
import timeit | |
from bisect import insort | |
import numpy as np | |
from collections import namedtuple | |
def get_data(): | |
return [(1920, 1939), (1911, 1944), (1920, 1955), (1938, 1939), (1937, 1940), | |
(1910, 1999), (1921, 1955)] | |
def get_data2(): | |
Person = namedtuple('Person', ('birth', 'death')) | |
return [Person(1920, 1939), Person(1911, 1944), | |
Person(1920, 1955), Person(1938, 1939), Person(1937, 1940), | |
Person(1910, 1999), Person(1921, 1955)] | |
def test_most_populated(): | |
most_populated(get_data(), False) | |
def most_populated(population, single=True): | |
years = dict() | |
unborn = sorted(population, key=lambda x: -x[0]) | |
alive = [] | |
dead = [] | |
for year in range(unborn[-1][0], max(population, key=lambda x: x[1])[1] + 1): | |
while unborn and unborn[-1][0] == year: | |
insort(alive, -unborn.pop()[1]) | |
while alive and alive[-1] == -(year - 1): | |
dead.append(-alive.pop()) | |
years[year] = len(alive) | |
return max(years, key=years.get) if single else \ | |
[key for key, val in years.iteritems() if val == max(years.values())] | |
def test_most_populated2(): | |
most_populated2(get_data()) | |
def most_populated2(pop): | |
pop_flat = chain.from_iterable(xrange(i, j+1) for i, j in pop) | |
return Counter(pop_flat).most_common() | |
def test_most_populated3(): | |
most_populated3(get_data(), False) | |
def most_populated3(population, single=True): | |
birth = map(lambda x: x[0], population) | |
death = map(lambda x: x[1] + 1, population) | |
b = Counter(birth) | |
d = Counter(death) | |
alive = 0 | |
years = {} | |
for year in range(min(birth), max(death) + 1): | |
alive = alive + b[year] - d[year] | |
years[year] = alive | |
return max(years, key=years.get) if single else \ | |
[key for key, val in years.iteritems() if val == max(years.values())] | |
def test_most_populated4(): | |
most_populated4(get_data2()) | |
def most_populated4(people): | |
START_YEAR = 1900 | |
END_YEAR = 2000 | |
people_alive = np.zeros(END_YEAR - START_YEAR + 1) # Alive each year | |
for p in people: | |
a = p.birth - START_YEAR | |
b = p.death - START_YEAR + 1 # include year of death | |
people_alive[a:b] += 1 | |
# Find indexes of maximum aliveness and convert to year | |
most_alive = np.flatnonzero(people_alive == people_alive.max()) + START_YEAR | |
return most_alive | |
if __name__ == '__main__': | |
print 'njzk2 var1: ' +\ | |
str(timeit.timeit(stmt="test_most_populated()", | |
setup="from __main__ import test_most_populated", | |
number=10000)) | |
print 'joran-beasley: ' +\ | |
str(timeit.timeit(stmt="test_most_populated2()", | |
setup="from __main__ import test_most_populated2", | |
number=10000)) | |
print 'njzk2 var2: ' +\ | |
str(timeit.timeit(stmt="test_most_populated3()", | |
setup="from __main__ import test_most_populated3", | |
number=10000)) | |
print 'hannes: ' +\ | |
str(timeit.timeit(stmt="test_most_populated4()", | |
setup="from __main__ import test_most_populated4", | |
number=10000)) | |
print most_populated(get_data()) | |
print most_populated(get_data(), False) | |
print most_populated2(get_data())[0:1] | |
print most_populated3(get_data()) | |
print most_populated4(get_data2()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Inspired by: Quora - "Are there really programmers with computer science degrees who cannot pass the FizzBuzz test?"