Skip to content

Commit 2b51f62

Browse files
committed
solution to hotdate
1 parent 970b7b0 commit 2b51f62

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

solutions/joshmcgrath08/hotdate.py

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env python
2+
3+
# Josh McGrath
4+
# Solution to http://puzzles.bostonpython.com/hotdate.html
5+
# Tested with: Python 2.7.6
6+
7+
# Consider these base-10 digits: 123456789. If you insert spaces between them, you get various sequences of numbers:
8+
9+
# 1 2 3 4 5 6 7 8 9
10+
# 12 3 4 5 67 8 9
11+
# 1 2 34 5 6 7 89
12+
# 12 34 56 78 9
13+
# 1 23456 78 9
14+
# 12345 6789
15+
# etc.
16+
17+
from itertools import *
18+
19+
# 1) Write a program that generates all possible combinations of those digits.
20+
21+
digits = map (str, range (1, 10))
22+
23+
# alternate the elements of two lists, until both lists exhausted
24+
def alternate (l1, l2):
25+
len_l1 = len (l1)
26+
len_l2 = len (l2)
27+
l = []
28+
for i in range (max (len_l1, len_l2)):
29+
if i < len_l1:
30+
l.append(l1[i])
31+
if i < len_l2:
32+
l.append(l2[i])
33+
return l
34+
35+
assert (alternate ([], []) == [])
36+
assert (alternate ([1, 2, 3], [4, 5]) == [1, 4, 2, 5, 3])
37+
assert (alternate ([4, 5], [1, 2, 3]) == [4, 1, 5, 2, 3])
38+
39+
# given a list of strings and an iterator to strings, return
40+
# an iterator to strings where a value from the iterator arg is
41+
# inserted between each adjacent pairs of elements in the list arg
42+
def itr_intersperse (l, itr):
43+
for x in product (itr, repeat=len (l) - 1):
44+
yield ''.join(alternate (l, x))
45+
46+
# # How many are there?
47+
48+
def itr_len (itr):
49+
c = 0
50+
for i in itr:
51+
c += 1
52+
return c
53+
54+
print itr_len (itr_intersperse (digits, ['', ' ']))
55+
56+
# Now let's insert a maximum of 8 addition or subtraction operators between the numbers, like this:
57+
58+
# 1+2+3+4+5+6+7-8+9
59+
# 12-3+4+5-67-8+9
60+
# 1+2+34+5-6-7-89
61+
# 12-34+56+78+9
62+
# 1+23456-78-9
63+
# 12345+6789
64+
# etc.
65+
66+
# Notice that those arithmetic expressions equate to different values:
67+
68+
# 1+2+3+4+5+6+7-8+9 = 29
69+
# 12-3+4+5-67-8+9 = -48
70+
# 1+2+34+5-6-7-89 = -60
71+
# 12-34+56+78+9 = 121
72+
# 1+23456-78-9 = 23370
73+
# 12345+6789 = 19134
74+
# etc.
75+
76+
# 2) Write a program that generates all possible expressions in this way.
77+
78+
# returns an iterator to expressions that sum to n
79+
def expr_sum (n):
80+
return ifilter (lambda x: eval(x) == n, itr_intersperse (digits, ['', '+', '-']))
81+
82+
# How many sum to 100?
83+
print itr_len (expr_sum (100))
84+
85+
# 3) Write a program that finds all such expressions for any sum.
86+
87+
# Which sum is the most popular, i.e. has the most expressions?
88+
sums = map (eval, itr_intersperse (digits, ['', '+', '-']))
89+
90+
from collections import Counter
91+
92+
sum_counter = Counter ()
93+
for s in sums:
94+
sum_counter[s] += 1
95+
96+
print sum_counter.most_common(1)[0][0]
97+
98+
# 4) Bonus: We can haz pretty data viz?
99+
100+
# Like how about a histogram of the number of expressions with sums from -23456788 to 123456789. (A log scale might help. Maybe binning, too.)
101+
102+
from matplotlib.pyplot import hist, show, bar
103+
104+
show (hist (sums, range = (-23456788, 123456789), bins = 50, normed = True, log = True))

0 commit comments

Comments
 (0)