Skip to content

Commit 8004671

Browse files
kugiyasangithub-actionspoyea
authored
Add Project Euler 68 Solution (TheAlgorithms#5552)
* updating DIRECTORY.md * Project Euler 68 Solution * updating DIRECTORY.md * Project Euler 68 Fixed doctests, now at 93% coverage * Update sol1.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: kugiyasan <kugiyasan@users.noreply.github.com> Co-authored-by: John Law <johnlaw.po@gmail.com>
1 parent b8fdd81 commit 8004671

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed

DIRECTORY.md

+2
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,8 @@
793793
* Problem 067
794794
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_067/sol1.py)
795795
* [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_067/sol2.py)
796+
* Problem 068
797+
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_068/sol1.py)
796798
* Problem 069
797799
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_069/sol1.py)
798800
* Problem 070

project_euler/problem_068/__init__.py

Whitespace-only changes.

project_euler/problem_068/sol1.py

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""
2+
Project Euler Problem 68: https://projecteuler.net/problem=68
3+
4+
Magic 5-gon ring
5+
6+
Problem Statement:
7+
Consider the following "magic" 3-gon ring,
8+
filled with the numbers 1 to 6, and each line adding to nine.
9+
10+
4
11+
\
12+
3
13+
/ \
14+
1 - 2 - 6
15+
/
16+
5
17+
18+
Working clockwise, and starting from the group of three
19+
with the numerically lowest external node (4,3,2 in this example),
20+
each solution can be described uniquely.
21+
For example, the above solution can be described by the set: 4,3,2; 6,2,1; 5,1,3.
22+
23+
It is possible to complete the ring with four different totals: 9, 10, 11, and 12.
24+
There are eight solutions in total.
25+
Total Solution Set
26+
9 4,2,3; 5,3,1; 6,1,2
27+
9 4,3,2; 6,2,1; 5,1,3
28+
10 2,3,5; 4,5,1; 6,1,3
29+
10 2,5,3; 6,3,1; 4,1,5
30+
11 1,4,6; 3,6,2; 5,2,4
31+
11 1,6,4; 5,4,2; 3,2,6
32+
12 1,5,6; 2,6,4; 3,4,5
33+
12 1,6,5; 3,5,4; 2,4,6
34+
35+
By concatenating each group it is possible to form 9-digit strings;
36+
the maximum string for a 3-gon ring is 432621513.
37+
38+
Using the numbers 1 to 10, and depending on arrangements,
39+
it is possible to form 16- and 17-digit strings.
40+
What is the maximum 16-digit string for a "magic" 5-gon ring?
41+
"""
42+
43+
from itertools import permutations
44+
45+
46+
def solution(gon_side: int = 5) -> int:
47+
"""
48+
Find the maximum number for a "magic" gon_side-gon ring
49+
50+
The gon_side parameter should be in the range [3, 5],
51+
other side numbers aren't tested
52+
53+
>>> solution(3)
54+
432621513
55+
>>> solution(4)
56+
426561813732
57+
>>> solution()
58+
6531031914842725
59+
>>> solution(6)
60+
Traceback (most recent call last):
61+
ValueError: gon_side must be in the range [3, 5]
62+
"""
63+
if gon_side < 3 or gon_side > 5:
64+
raise ValueError("gon_side must be in the range [3, 5]")
65+
66+
# Since it's 16, we know 10 is on the outer ring
67+
# Put the big numbers at the end so that they are never the first number
68+
small_numbers = list(range(gon_side + 1, 0, -1))
69+
big_numbers = list(range(gon_side + 2, gon_side * 2 + 1))
70+
71+
for perm in permutations(small_numbers + big_numbers):
72+
numbers = generate_gon_ring(gon_side, list(perm))
73+
if is_magic_gon(numbers):
74+
return int("".join(str(n) for n in numbers))
75+
76+
raise ValueError(f"Magic {gon_side}-gon ring is impossible")
77+
78+
79+
def generate_gon_ring(gon_side: int, perm: list[int]) -> list[int]:
80+
"""
81+
Generate a gon_side-gon ring from a permutation state
82+
The permutation state is the ring, but every duplicate is removed
83+
84+
>>> generate_gon_ring(3, [4, 2, 3, 5, 1, 6])
85+
[4, 2, 3, 5, 3, 1, 6, 1, 2]
86+
>>> generate_gon_ring(5, [6, 5, 4, 3, 2, 1, 7, 8, 9, 10])
87+
[6, 5, 4, 3, 4, 2, 1, 2, 7, 8, 7, 9, 10, 9, 5]
88+
"""
89+
result = [0] * (gon_side * 3)
90+
result[0:3] = perm[0:3]
91+
perm.append(perm[1])
92+
93+
magic_number = 1 if gon_side < 5 else 2
94+
95+
for i in range(1, len(perm) // 3 + magic_number):
96+
result[3 * i] = perm[2 * i + 1]
97+
result[3 * i + 1] = result[3 * i - 1]
98+
result[3 * i + 2] = perm[2 * i + 2]
99+
100+
return result
101+
102+
103+
def is_magic_gon(numbers: list[int]) -> bool:
104+
"""
105+
Check if the solution set is a magic n-gon ring
106+
Check that the first number is the smallest number on the outer ring
107+
Take a list, and check if the sum of each 3 numbers chunk is equal to the same total
108+
109+
>>> is_magic_gon([4, 2, 3, 5, 3, 1, 6, 1, 2])
110+
True
111+
>>> is_magic_gon([4, 3, 2, 6, 2, 1, 5, 1, 3])
112+
True
113+
>>> is_magic_gon([2, 3, 5, 4, 5, 1, 6, 1, 3])
114+
True
115+
>>> is_magic_gon([1, 2, 3, 4, 5, 6, 7, 8, 9])
116+
False
117+
>>> is_magic_gon([1])
118+
Traceback (most recent call last):
119+
ValueError: a gon ring should have a length that is a multiple of 3
120+
"""
121+
if len(numbers) % 3 != 0:
122+
raise ValueError("a gon ring should have a length that is a multiple of 3")
123+
124+
if min(numbers[::3]) != numbers[0]:
125+
return False
126+
127+
total = sum(numbers[:3])
128+
129+
return all(sum(numbers[i : i + 3]) == total for i in range(3, len(numbers), 3))
130+
131+
132+
if __name__ == "__main__":
133+
print(solution())

0 commit comments

Comments
 (0)