前天,妞姐問了個好問題——一個簡易版的幻方問題:把 2, 4, 6, 8, 10
填入下面的五個圓圈中,讓橫、竪、環上之和都相等。
⚠️之所以第一眼就認定它是「好問題」,是因為它符合「好問題是下金蛋🥚的雞🐔」這個定義。可以讓小朋友體會到「真的有不可交換的乘法」,也可以深扒和群論的關係⋯⋯
比如,我們先隨便填上:
- 橫之和是
10 + 8 + 4 = 22
; - 竪之和是
2 + 8 + 6 = 16
; - 環上之和是
2 + 4 + 6 + 10 = 22
;
那麼,怎麼調整才能讓三個和相等呢?
手工嘗試
1⃣️ 先對調 10
和 8
:
2⃣️ 再對調 2
和 4
:
現在:
- 橫之和是
8 + 10 + 2 = 20
; - 竪之和是
4 + 10 + 6 = 20
; - 環上之和是
4 + 2 + 6 + 8 = 20
;
搞定💪🏻。
如何找到一般化解法?
把橫向定義為 x 軸,縱向定義為 y 軸,環向定義為 z 軸:
直覺告訴我們,這是個群,所有交換操作都可以由少數幾個基操組合得到。我們不妨先看看「逆時針輪轉一位環上的數」(暫且把這個操作叫做 )
∵ x 軸和 y 軸是對稱的,∴必然可以用 x 軸上的交換操作和 組合而成 y 軸上的交換操作。我們不妨把交換 x 軸上右側兩個數的操作記作
:
⚠️觀察到:動 x 軸不會改變 x 軸之和;同時,另外兩軸會加減某一差值。這個觀察非常關鍵——本來我們需要同時考慮 3 個軸上的調整,有了這個觀察,現在只需要考慮按住中間值那根軸,調減最大和,調增最小和,就行了。可見,發掘問題的結構,可以有效降低問題空間的搜索維度。
其他的交換操作想必用 和
組合就能得到。驗證一下,比如沿 y 軸翻轉(記為
):
可以拆解為:
1⃣️
2⃣️
3⃣️
4⃣️
5⃣️
6⃣️
7⃣️
找到套路
把所有的操作影響分析一遍:
x 軸上的交換:
v.s.
y 軸上的交換:
v.s.
象限 | |||
---|---|---|---|
環上的交換:
v.s.
v.s.
v.s.
象限 | |||
---|---|---|---|
I | |||
II | |||
III | |||
IV |
翻轉:
v.s.
象限 | |||
---|---|---|---|
沿 x 軸翻轉 | |||
沿 y 軸翻轉 |
⚠️即翻轉操作均不會改變各軸之和。
程序驗證
太麻煩了,還是寫程序驗證吧:
class Cycle
attr_reader :ring, :center, :sum_x, :sum_y, :sum_z
def initialize(a, b, c, d, o)
@ring, @center = [a, b, c, d], o
@sum_x = b + o + d
@sum_y = a + o + c
@sum_z = a + b + c + d # sum_z = sum_x + sum_y - 2*o
end
def op_counterclockwise
@sum_x, @sum_y = @sum_y, @sum_x
@sum_z = @sum_z
header = @ring.shift
@ring.push header
end
def op_clockwise
self.op_counterclockwise
self.op_counterclockwise
self.op_counterclockwise
end
def op_x
@sum_x = @sum_x
delta = @center - @ring[1]
@sum_y = @sum_y - delta
@sum_z = @sum_z + delta
@center, @ring[1] = @ring[1], @center
end
def op_y
self.op_counterclockwise
self.op_counterclockwise
self.op_counterclockwise
self.op_x
self.op_counterclockwise
end
def op_swap_II
self.op_y
self.op_counterclockwise
self.op_counterclockwise
self.op_x
self.op_counterclockwise
self.op_counterclockwise
self.op_y
end
def op_swap_I
self.op_counterclockwise
self.op_swap_II
self.op_clockwise
end
def op_swap_III
self.op_clockwise
self.op_swap_II
self.op_counterclockwise
end
def op_swap_IV
self.op_counterclockwise
self.op_counterclockwise
self.op_swap_II
self.op_clockwise
self.op_clockwise
end
def op_flip_y
self.op_x
self.op_counterclockwise
self.op_counterclockwise
self.op_x
self.op_counterclockwise
self.op_counterclockwise
self.op_x
end
def op_x_minus
self.op_flip_y
self.op_x
self.op_flip_y
end
def op_flip_x
self.op_counterclockwise
self.op_flip_y
self.op_clockwise
end
def op_y_minus
self.op_flip_x
self.op_y
self.op_flip_x
end
def display
puts "\t" + " "*4 + " y"
puts "\t" + " "*4 + " ↑"
puts "\t" + " "*4 + " "
puts "\t" + " "*4 + " #{@ring[0]}"
puts "\t" + " "*4 + " |"
puts "#{@ring[3]}\t---- #{@center} ---- #{@ring[1]} ➡︎ x"
puts "\t" + " "*4 + " |"
puts "\t" + " "*4 + " #{@ring[2]}"
puts
puts "x:\t#{@ring[3]} + #{@center} + #{@ring[1]} \t\t= #{@sum_x}"
puts "y:\t#{@ring[0]} + #{@center} + #{@ring[2]} \t\t= #{@sum_y}"
puts "z:\t#{@ring[0]} + #{@ring[1]} + #{@ring[2]} + #{@ring[3]} \t= #{@sum_z}"
end
end
c = Cycle.new(2, 4, 6, 10, 8)
c.display
puts "-"*20 + " operator ... " + "-"*20
c.op_x_minus
c.op_swap_I
c.display
輸出:
y
↑
2
|
10 ---- 8 ---- 4 ➡︎ x
|
6
x: 10 + 8 + 4 = 22
y: 2 + 8 + 6 = 16
z: 2 + 4 + 6 + 10 = 22
-------------------- operator ... --------------------
y
↑
4
|
8 ---- 10 ---- 2 ➡︎ x
|
6
x: 8 + 10 + 2 = 20
y: 4 + 10 + 6 = 20
z: 4 + 2 + 6 + 8 = 20
跑了一下, 種可能中,只有 8 種滿足約束。
好了,現在的問題是「怎麼教會小朋友?」了😅?
附上 TikZ 畫圖代碼:
\documentclass[tikz]{standalone}
%\usepackage{draculatheme}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
% 定义全局参数
\def\radius{2cm} % 大圆半径
\def\nodeRadius{0.5cm} % 节点圆半径
\def\xShift{8cm} % 水平偏移量
% 定义绘制魔法圈的宏
\newcommand{\drawMagickCircle}[9]{
% 绘制节点
\coordinate (O) at (0, 0);
\coordinate (A) at (0, \radius);
\coordinate (B) at (\radius, 0);
\coordinate (C) at (0, -\radius);
\coordinate (D) at (-\radius, 0);
% 绘制外部的大圆
\draw [thick, teal] (O) circle (\radius);
% 绘制中间的十字线
\draw [thick, teal] (A) -- (C);
\draw [thick, teal] (D) -- (B);
% 绘制各小圆
\foreach \i/\v in {O/#1, A/#2, B/#3, C/#4, D/#5} {
\draw [fill, teal] (\i) circle (\nodeRadius);
\draw [fill, white] node at (\i) {$\v$};
}
% 绘制高亮小圆
\foreach \i/\v in {#6/#7, #8/#9} {
\filldraw [thick, yellow!30] (\i) circle (\nodeRadius);
\draw [fill, black] node at (\i) {$\v$};
}
}
\begin{scope}
\drawMagickCircle{O}{A}{B}{C}{D}{O}{O}{A}{A};
\end{scope}
\node at (\xShift / 2, 0) { $ \stackrel{\sigma_{y}^{+}}{\Longrightarrow} $ };
\begin{scope}[xshift=\xShift]
\drawMagickCircle{A}{O}{B}{C}{D}{O}{A}{A}{O};
\end{scope}
\end{tikzpicture}
\end{document}
Ref: