Skip to content

Instantly share code, notes, and snippets.

@oskar-j
Last active August 29, 2015 14:25
Show Gist options
  • Save oskar-j/308aafbb7ae44df7fed1 to your computer and use it in GitHub Desktop.
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
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())
@oskar-j
Copy link
Author

oskar-j commented Jul 20, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment