Skip to content

Commit 1f506f1

Browse files
committed
Project Euler problem 191 solution
1 parent 477b2c2 commit 1f506f1

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

project_euler/problem_191/__init__.py

Whitespace-only changes.

project_euler/problem_191/sol1.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""
2+
Prize Strings
3+
Problem 191
4+
5+
A particular school offers cash rewards to children with good attendance and
6+
punctuality. If they are absent for three consecutive days or late on more
7+
than one occasion then they forfeit their prize.
8+
9+
During an n-day period a trinary string is formed for each child consisting
10+
of L's (late), O's (on time), and A's (absent).
11+
12+
Although there are eighty-one trinary strings for a 4-day period that can be
13+
formed, exactly forty-three strings would lead to a prize:
14+
15+
OOOO OOOA OOOL OOAO OOAA OOAL OOLO OOLA OAOO OAOA
16+
OAOL OAAO OAAL OALO OALA OLOO OLOA OLAO OLAA AOOO
17+
AOOA AOOL AOAO AOAA AOAL AOLO AOLA AAOO AAOA AAOL
18+
AALO AALA ALOO ALOA ALAO ALAA LOOO LOOA LOAO LOAA
19+
LAOO LAOA LAAO
20+
21+
How many "prize" strings exist over a 30-day period?
22+
"""
23+
24+
25+
def solution(days=30):
26+
"""Returns the number of possible prize strings for a particular number
27+
of days, using a simple recursive function with caching to speed it up.
28+
29+
>>> solution()
30+
1918080160
31+
>>> solution(4)
32+
43
33+
"""
34+
35+
# a cache to speed up calculation
36+
cache = {}
37+
38+
# we will be using a simple recursive function
39+
def calculate(days, absent, late):
40+
# if we are absent twice, or late 3 consecutive days,
41+
# no further prize strings are possible
42+
if late == 3 or absent == 2:
43+
return 0
44+
45+
# if we have no days left, and have not failed any other rules,
46+
# we have a prize string
47+
if days == 0:
48+
return 1
49+
50+
# No easy solution, so now we need to do the recursive calculation
51+
52+
# First, check if the combination is already in the cache, and
53+
# if yes, return the stored value from there since we already
54+
# know the number of possible prize strings from this point on
55+
key = (days, absent, late)
56+
if key in cache:
57+
return cache[key]
58+
59+
# if we are late (but not absent), the "absent" counter stays as
60+
# it is, but the "late" counter increases by one
61+
state_late = calculate(days - 1, absent, late + 1)
62+
63+
# if we are absent, the "absent" counter increases by 1, and the
64+
# "late" counter resets to 0
65+
state_absent = calculate(days - 1, absent + 1, 0)
66+
67+
# if we are on time, this resets the "late" counter and keeps the
68+
# absent counter
69+
state_ontime = calculate(days - 1, absent, 0)
70+
71+
# the total number of prize strings is the sum of these three
72+
# possible states
73+
prizestrings = state_late + state_absent + state_ontime
74+
75+
# now store the value we calculated in the cache
76+
cache[key] = prizestrings
77+
return prizestrings
78+
79+
return calculate(days, 0, 0)
80+
81+
82+
if __name__ == "__main__":
83+
print(solution())

0 commit comments

Comments
 (0)