Skip to content

Commit 6c7c91b

Browse files
committed
Add magic square example
1 parent 96dbf37 commit 6c7c91b

1 file changed

Lines changed: 344 additions & 0 deletions

File tree

source_code/magic_squares.ipynb

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 7,
6+
"id": "99dd3bd6-9c07-446e-adea-9101b0e1d033",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"import itertools\n",
11+
"import math"
12+
]
13+
},
14+
{
15+
"cell_type": "code",
16+
"execution_count": 2,
17+
"id": "28ce8741-bcb9-490d-86b0-c0a08da29743",
18+
"metadata": {},
19+
"outputs": [],
20+
"source": [
21+
"def create_square(elements):\n",
22+
" n = math.isqrt(len(elements))\n",
23+
" square = [[] for _ in range(n)]\n",
24+
" for i, element in enumerate(elements):\n",
25+
" square[i//n].append(element)\n",
26+
" return square"
27+
]
28+
},
29+
{
30+
"cell_type": "code",
31+
"execution_count": 3,
32+
"id": "492cba61-0564-4ba2-ac31-d9d36ea1d8df",
33+
"metadata": {},
34+
"outputs": [
35+
{
36+
"data": {
37+
"text/plain": [
38+
"[[1, 2, 3], [4, 5, 6], [7, 8, 9]]"
39+
]
40+
},
41+
"execution_count": 3,
42+
"metadata": {},
43+
"output_type": "execute_result"
44+
}
45+
],
46+
"source": [
47+
"create_square(list(range(1, 10)))"
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": 22,
53+
"id": "9c6de9a2-20dd-42b9-b9e6-dc29581d7bdf",
54+
"metadata": {},
55+
"outputs": [],
56+
"source": [
57+
"def is_magic_squuare(square):\n",
58+
" n = math.isqrt(len(square))\n",
59+
" diag_sum = sum(square[i + i*n] for i in range(n))\n",
60+
" for i in range(n):\n",
61+
" row_sum = sum(square[j + i*n] for j in range(n))\n",
62+
" if row_sum != diag_sum:\n",
63+
" return False\n",
64+
" for j in range(n):\n",
65+
" col_sum = sum(square[j + i*n] for i in range(n))\n",
66+
" if col_sum != diag_sum:\n",
67+
" return False\n",
68+
" return sum(square[i*n + (n - i - 1)] for i in range(n)) == diag_sum"
69+
]
70+
},
71+
{
72+
"cell_type": "code",
73+
"execution_count": 5,
74+
"id": "4875036e-a4c4-4972-aed0-5752efccf6e6",
75+
"metadata": {},
76+
"outputs": [
77+
{
78+
"data": {
79+
"text/plain": [
80+
"False"
81+
]
82+
},
83+
"execution_count": 5,
84+
"metadata": {},
85+
"output_type": "execute_result"
86+
}
87+
],
88+
"source": [
89+
"is_magic_squuare(list(range(1, 10)))"
90+
]
91+
},
92+
{
93+
"cell_type": "code",
94+
"execution_count": 6,
95+
"id": "9149cec0-7678-4001-afcb-b11190368737",
96+
"metadata": {},
97+
"outputs": [
98+
{
99+
"data": {
100+
"text/plain": [
101+
"True"
102+
]
103+
},
104+
"execution_count": 6,
105+
"metadata": {},
106+
"output_type": "execute_result"
107+
}
108+
],
109+
"source": [
110+
"is_magic_squuare([2, 9, 4, 7, 5, 3, 6, 1, 8])"
111+
]
112+
},
113+
{
114+
"cell_type": "code",
115+
"execution_count": 7,
116+
"id": "ed9f69e1-3988-4d85-94c6-355a0c6de1e4",
117+
"metadata": {},
118+
"outputs": [],
119+
"source": [
120+
"def create_magic_square(n):\n",
121+
" symbols = list(range(1, n*n + 1))\n",
122+
" for elements in itertools.permutations(symbols):\n",
123+
" if is_magic_squuare(elements):\n",
124+
" return create_square(elements)\n",
125+
" return None"
126+
]
127+
},
128+
{
129+
"cell_type": "code",
130+
"execution_count": 8,
131+
"id": "61864a59-91b8-4d57-9c29-e922a3e170db",
132+
"metadata": {},
133+
"outputs": [
134+
{
135+
"data": {
136+
"text/plain": [
137+
"[[2, 7, 6], [9, 5, 1], [4, 3, 8]]"
138+
]
139+
},
140+
"execution_count": 8,
141+
"metadata": {},
142+
"output_type": "execute_result"
143+
}
144+
],
145+
"source": [
146+
"create_magic_square(3)"
147+
]
148+
},
149+
{
150+
"cell_type": "code",
151+
"execution_count": 16,
152+
"id": "b07909cd-7af9-4750-a996-55d954b482db",
153+
"metadata": {},
154+
"outputs": [],
155+
"source": [
156+
"def create_all_magic_square(n, is_verbose=False):\n",
157+
" symbols = list(range(1, n*n + 1))\n",
158+
" nr_squares = 0\n",
159+
" for elements in itertools.permutations(symbols):\n",
160+
" if is_magic_squuare(elements):\n",
161+
" yield create_square(elements)\n",
162+
" nr_squares += 1\n",
163+
" if is_verbose and nr_squares % 10_000_000 == 0:\n",
164+
" print(f'{nr_squares} tested')"
165+
]
166+
},
167+
{
168+
"cell_type": "code",
169+
"execution_count": 17,
170+
"id": "114e04e2-761a-4ee8-9b8d-8190cf57c98a",
171+
"metadata": {},
172+
"outputs": [
173+
{
174+
"name": "stdout",
175+
"output_type": "stream",
176+
"text": [
177+
"[[2, 7, 6], [9, 5, 1], [4, 3, 8]]\n",
178+
"[[2, 9, 4], [7, 5, 3], [6, 1, 8]]\n",
179+
"[[4, 3, 8], [9, 5, 1], [2, 7, 6]]\n",
180+
"[[4, 9, 2], [3, 5, 7], [8, 1, 6]]\n",
181+
"[[6, 1, 8], [7, 5, 3], [2, 9, 4]]\n",
182+
"[[6, 7, 2], [1, 5, 9], [8, 3, 4]]\n",
183+
"[[8, 1, 6], [3, 5, 7], [4, 9, 2]]\n",
184+
"[[8, 3, 4], [1, 5, 9], [6, 7, 2]]\n",
185+
"CPU times: user 437 ms, sys: 2.86 ms, total: 439 ms\n",
186+
"Wall time: 438 ms\n"
187+
]
188+
}
189+
],
190+
"source": [
191+
"%%time\n",
192+
"for square in create_all_magic_square(3):\n",
193+
" print(square)"
194+
]
195+
},
196+
{
197+
"cell_type": "code",
198+
"execution_count": 18,
199+
"id": "2f367b59-9545-4b11-a551-0d9c67372e1d",
200+
"metadata": {},
201+
"outputs": [
202+
{
203+
"name": "stdout",
204+
"output_type": "stream",
205+
"text": [
206+
"10000000 tested\n",
207+
"20000000 tested\n",
208+
"30000000 tested\n"
209+
]
210+
},
211+
{
212+
"ename": "KeyboardInterrupt",
213+
"evalue": "",
214+
"output_type": "error",
215+
"traceback": [
216+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
217+
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
218+
"File \u001b[0;32m<timed exec>:1\u001b[0m\n",
219+
"Cell \u001b[0;32mIn[16], line 5\u001b[0m, in \u001b[0;36mcreate_all_magic_square\u001b[0;34m(n, is_verbose)\u001b[0m\n\u001b[1;32m 3\u001b[0m nr_squares \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m elements \u001b[38;5;129;01min\u001b[39;00m itertools\u001b[38;5;241m.\u001b[39mpermutations(symbols):\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_magic_squuare(elements):\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m create_square(elements)\n\u001b[1;32m 7\u001b[0m nr_squares \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n",
220+
"Cell \u001b[0;32mIn[4], line 3\u001b[0m, in \u001b[0;36mis_magic_squuare\u001b[0;34m(square)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mis_magic_squuare\u001b[39m(square):\n\u001b[1;32m 2\u001b[0m n \u001b[38;5;241m=\u001b[39m math\u001b[38;5;241m.\u001b[39misqrt(\u001b[38;5;28mlen\u001b[39m(square))\n\u001b[0;32m----> 3\u001b[0m diag_sum \u001b[38;5;241m=\u001b[39m \u001b[38;5;28msum\u001b[39m(square[i \u001b[38;5;241m+\u001b[39m i\u001b[38;5;241m*\u001b[39mn] \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(n))\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(n):\n\u001b[1;32m 5\u001b[0m row_sum \u001b[38;5;241m=\u001b[39m \u001b[38;5;28msum\u001b[39m(square[j \u001b[38;5;241m+\u001b[39m i\u001b[38;5;241m*\u001b[39mn] \u001b[38;5;28;01mfor\u001b[39;00m j \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(n))\n",
221+
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
222+
]
223+
}
224+
],
225+
"source": [
226+
"%%time\n",
227+
"for square in create_all_magic_square(5, True):\n",
228+
" print(square)"
229+
]
230+
},
231+
{
232+
"cell_type": "code",
233+
"execution_count": 28,
234+
"id": "321565e9-d441-4b18-89d8-1aecca504140",
235+
"metadata": {},
236+
"outputs": [],
237+
"source": [
238+
"def create_magic_square(n):\n",
239+
" if n < 3:\n",
240+
" raise ValueError('array size needs to be at least 3')\n",
241+
" if n % 2 == 1:\n",
242+
" square = [0]*n**2\n",
243+
" i, j, value = 0, n//2, 1\n",
244+
" for start_value in range(1, n*n, n):\n",
245+
" for value in range(start_value, start_value + n - 1):\n",
246+
" square[i*n + j] = value\n",
247+
" i = (i - 1 + n) % n\n",
248+
" j = (j + 1) % n\n",
249+
" square[i*n + j] = value + 1\n",
250+
" i = (i + 1) % n\n",
251+
" return square\n",
252+
" else:\n",
253+
" raise NotImplementedError('algorithm not implement for even sizes')"
254+
]
255+
},
256+
{
257+
"cell_type": "code",
258+
"execution_count": 32,
259+
"id": "9f162be1-1714-420c-815d-e4ca3e072926",
260+
"metadata": {},
261+
"outputs": [
262+
{
263+
"data": {
264+
"text/plain": [
265+
"True"
266+
]
267+
},
268+
"execution_count": 32,
269+
"metadata": {},
270+
"output_type": "execute_result"
271+
}
272+
],
273+
"source": [
274+
"is_magic_squuare(create_magic_square(7))"
275+
]
276+
},
277+
{
278+
"cell_type": "code",
279+
"execution_count": 18,
280+
"id": "d56a4ac6-0a6b-403a-8569-7471f9caa9d8",
281+
"metadata": {},
282+
"outputs": [],
283+
"source": [
284+
"def print_square(elements):\n",
285+
" n = math.isqrt(len(elements))\n",
286+
" for i in range(n):\n",
287+
" print(''.join(f'{value:5d}' for value in elements[i*n:i*n+n]))"
288+
]
289+
},
290+
{
291+
"cell_type": "code",
292+
"execution_count": 33,
293+
"id": "a52776a3-c275-4fa9-bfdf-84217f40b9e8",
294+
"metadata": {},
295+
"outputs": [
296+
{
297+
"name": "stdout",
298+
"output_type": "stream",
299+
"text": [
300+
" 30 39 48 1 10 19 28\n",
301+
" 38 47 7 9 18 27 29\n",
302+
" 46 6 8 17 26 35 37\n",
303+
" 5 14 16 25 34 36 45\n",
304+
" 13 15 24 33 42 44 4\n",
305+
" 21 23 32 41 43 3 12\n",
306+
" 22 31 40 49 2 11 20\n"
307+
]
308+
}
309+
],
310+
"source": [
311+
"print_square(create_magic_square(7))"
312+
]
313+
},
314+
{
315+
"cell_type": "code",
316+
"execution_count": null,
317+
"id": "c66eb794-0068-4fb3-8097-304dddeeebf5",
318+
"metadata": {},
319+
"outputs": [],
320+
"source": []
321+
}
322+
],
323+
"metadata": {
324+
"kernelspec": {
325+
"display_name": "Python 3 (ipykernel)",
326+
"language": "python",
327+
"name": "python3"
328+
},
329+
"language_info": {
330+
"codemirror_mode": {
331+
"name": "ipython",
332+
"version": 3
333+
},
334+
"file_extension": ".py",
335+
"mimetype": "text/x-python",
336+
"name": "python",
337+
"nbconvert_exporter": "python",
338+
"pygments_lexer": "ipython3",
339+
"version": "3.11.2"
340+
}
341+
},
342+
"nbformat": 4,
343+
"nbformat_minor": 5
344+
}

0 commit comments

Comments
 (0)