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