This repository has been archived by the owner on Apr 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
problem061.py
129 lines (101 loc) · 3.95 KB
/
problem061.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""
Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers are
all figurate (polygonal) numbers and are generated by the following formulae:
Triangle P3,n=n(n+1)/2 1, 3, 6, 10, 15, ...
Square P4,n=n ^ 2 1, 4, 9, 16, 25, ...
Pentagonal P5,n=n(3n-1)/2 1, 5, 12, 22, 35, ...
Hexagonal P6,n=n(2n-1) 1, 6, 15, 28, 45, ...
Heptagonal P7,n=n(5n-3)/2 1, 7, 18, 34, 55, ...
Octagonal P8,n=n(3n-2) 1, 8, 21, 40, 65, ...
The ordered set of three 4-digit numbers: 8128, 2882, 8281, has
three interesting properties.
1. The set is cyclic, in that the last two digits of each number is the first
two digits of the next number (including the last number with the first).
2. Each polygonal type: triangle (P3,127=8128), square (P4,91=8281), and
pentagonal (P5,44=2882), is represented by a different number in the set.
3. This is the only set of 4-digit numbers with this property.
Find the sum of the only ordered set of six cyclic 4-digit numbers for which
each polygonal type: triangle, square, pentagonal, hexagonal, heptagonal, and
octagonal, is represented by a different number in the set.
"""
from itertools import count, dropwhile, takewhile
from euler import count_digits_in
from problem012 import triangle_numbers
from problem045 import hexagonal_numbers
def square_numbers():
"""
>>> list(takewhile(lambda x: x < 26, square_numbers()))
[1, 4, 9, 16, 25]
"""
return (n ** 2 for n in count(1))
def pentagonal_numbers():
"""
>>> list(takewhile(lambda x: x < 36, pentagonal_numbers()))
[1, 5, 12, 22, 35]
"""
return (n * (3 * n - 1) / 2 for n in count(1))
def heptagonal_numbers():
"""
>>> list(takewhile(lambda x: x < 56, heptagonal_numbers()))
[1, 7, 18, 34, 55]
"""
return (n * (5 * n - 3) / 2 for n in count(1))
def octagonal_numbers():
"""
>>> list(takewhile(lambda x: x < 66, octagonal_numbers()))
[1, 8, 21, 40, 65]
"""
return (n * (3 * n - 2) for n in count(1))
def main():
"""
CAUTION: There is only one set of numbers that fulfil property 1 therefore
it isn't necessary to check for property 2.
>>> main()
28684
"""
def lt_four_digits(number):
"""returns true if the number has less than 4 digits"""
return count_digits_in(number) < 4
def four_digits(number):
"""returns true if the number has exactly 4 digits"""
return count_digits_in(number) == 4
triangles = list(
takewhile(four_digits, dropwhile(lt_four_digits, triangle_numbers()))
)
squares = list(
takewhile(four_digits, dropwhile(lt_four_digits, square_numbers()))
)
pentagons = list(
takewhile(four_digits, dropwhile(lt_four_digits, pentagonal_numbers()))
)
hexagons = list(
takewhile(four_digits, dropwhile(lt_four_digits, hexagonal_numbers()))
)
heptagons = list(
takewhile(four_digits, dropwhile(lt_four_digits, heptagonal_numbers()))
)
octagons = list(
takewhile(four_digits, dropwhile(lt_four_digits, octagonal_numbers()))
)
def recursive_ring_finder(numbers, queue):
"""returns 6 numbers that fulfil the three given properties"""
if len(numbers) > 1 and numbers[-2] % 100 != numbers[-1] // 100:
return None
for next_list in queue:
queue_new = queue[:]
queue_new.remove(next_list)
for candidate in next_list:
numbers_new = numbers[:]
numbers_new.append(candidate)
result = recursive_ring_finder(numbers_new, queue_new)
if result is not None:
return result
if len(queue) == 0 and numbers[0] // 100 == numbers[-1] % 100:
return numbers
return None
numbers = []
queue = [octagons, triangles, squares, pentagons, hexagons, heptagons]
print(sum(recursive_ring_finder(numbers, queue)))
if __name__ == "__main__":
import doctest
doctest.testmod()