[疑似言語▶︎Python]応用情報 H28秋期第3問

IT

はじめに

こんにちは。Yuinaです。

今日はこちらの問題の疑似言語を参考にPythonで魔法陣を作成します。

魔法陣の説明につきましては、こちらのサイトで詳しく解説されていました。大変わかりやすかったので掲載しておきます。

それでは、よろしくお願いいたします。

コード

from collections import deque

# --- データの定義 ---
SOTO_MIGI = -1
SOTO_SHITA = -2
SOTO_KADO = -3

def shokika(N):

houjin = [[0] * (N + 2) for _ in range(N + 2)]
for y in range(1, N + 1):
for x in range(1, N + 1):
houjin[y][x] = 0

for y in range(1, N + 1):
houjin[y][N + 1] = SOTO_MIGI

for x in range(1, N + 1):
houjin[N + 1][x] = SOTO_SHITA

houjin[N + 1][N + 1] = SOTO_KADO

return houjin

def mahoujin(N):
if N % 2 == 0 or N <= 0:
print("魔法陣は奇数サイズである必要があります。")
return None

y = N
x = N // 2 + 1

houjin = shokika(N)

suuji = 1
houjin[y][x] = suuji

while suuji < N * N:
yb = y
xb = x

y += 1
x += 1

if houjin[y][x] == SOTO_SHITA:
y = 1
elif houjin[y][x] == SOTO_MIGI:
x = 1
elif houjin[y][x] == SOTO_KADO:
y = N - 1
x = 1
elif houjin[y][x] != 0:
y = yb - 1
x = xb

suuji += 1
houjin[y][x] = suuji

return houjin

def print_mahoujin(houjin, N):
if houjin is None:
return
print(f"{N}x{N}の魔法陣:")

for y in range(1, N + 1):
for x in range(1, N + 1):
print(f"{houjin[y][x]:4d}", end=" ")
print()

N_size = 5
magic_square = mahoujin(N_size)
print_mahoujin(magic_square, N_size)

解説

from collections import deque

SOTO_MIGI = -1
SOTO_SHITA = -2
SOTO_KADO = -3

定数の宣言:

SOTO_MIGISOTO_SHITASOTO_KADO は、魔法陣の境界を表すための定数です。それぞれ右端、下端、右下隅に対応しています。


def shokika(N):

houjin = [[0] * (N + 2) for _ in range(N + 2)]
for y in range(1, N + 1):
for x in range(1, N + 1):
houjin[y][x] = 0

for y in range(1, N + 1):
houjin[y][N + 1] = SOTO_MIGI

for x in range(1, N + 1):
houjin[N + 1][x] = SOTO_SHITA

houjin[N + 1][N + 1] = SOTO_KADO

return houjin

shokikaメソッド:

N x N のサイズの魔法陣を初期化します。
魔法陣の外側に境界を表す定数を配置することで、移動の際の条件分岐をシンプルにしています。

[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, -2, -2, -2, -2, -2, -3]

5×5の魔法陣をshokikaメソッドで初期化した状態↑


def mahoujin(N):
    if N % 2 == 0 or N <= 0:
        print("魔法陣は奇数サイズである必要があります。")
        return None

    y = N
    x = N // 2 + 1

    houjin = shokika(N)

    suuji = 1
    houjin[y][x] = suuji

    # 境界に達した場合や既に数字が入っている場合
    while suuji < N * N:
        yb = y
        xb = x

        y += 1
        x += 1

        # 計算した次の位置 (y, x) が下側の境界 (SOTO_SHITA、値は -2) であるかをチェックします。
        if houjin[y][x] == SOTO_SHITA:
            y = 1 # もしそうなら、行を一番上 (y = 1) に移動します。
        # 下側の境界でなかった場合、次に右側の境界 (SOTO_MIGI、値は -1) であるかをチェックします。
        elif houjin[y][x] == SOTO_MIGI:
            x = 1 #もしそうなら、列を一番左 (x = 1) に移動します。
        # 右側の境界でもなかった場合、次に右下隅の境界 (SOTO_KADO、値は -3) であるかをチェックします。
        elif houjin[y][x] == SOTO_KADO:
        # もしそうなら、現在の位置の2つ上の行かつ一番左の列 (y = N - 1, x = 1) に移動します。
            y = N - 1 
            x = 1
        elif houjin[y][x] != 0:
            y = yb - 1 
            x = xb

        suuji += 1
        houjin[y][x] = suuji

    return houjin

mahoujinメソッド:

魔法陣を生成するメインの関数です。N が奇数でない場合はエラーメッセージを表示します。中央のマスから開始し、数字を 1 から順に配置していきます。数字を配置する次のマスは、現在のマスの右上ですが、境界に達した場合や既に数字が入っている場合は、特定のルールに従って移動先を決定します。

5×5の魔法陣をmahoujinメソッドのループを1度だけ実行した状態:

[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 1, 0, 0, -1]
[0, -2, -2, -2, -2, -2, -3]

5×5の魔法陣をmahoujinメソッドのループを2度だけ実行した状態:

[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, -1]
[0, 0, 0, 0, 0, 3, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 1, 0, 0, -1]
[0, -2, -2, -2, -2, -2, -3]

5×5の魔法陣をmahoujinメソッドのループを3度だけ実行した状態:

[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, -1]
[0, 0, 0, 0, 0, 3, -1]
[0, 4, 0, 0, 0, 0, -1]
[0, 0, 0, 0, 0, 0, -1]
[0, 0, 0, 1, 0, 0, -1]
[0, -2, -2, -2, -2, -2, -3]

5×5の魔法陣をmahoujinメソッドのループを4度だけ実行した状態:

[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, -1]
[0, 0, 0, 0, 0, 3, -1]
[0, 4, 0, 0, 0, 0, -1]
[0, 0, 5, 0, 0, 0, -1]
[0, 0, 0, 1, 0, 0, -1]
[0, -2, -2, -2, -2, -2, -3]

5×5の魔法陣をmahoujinメソッドのループを5度だけ実行した状態:

[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, -1]
[0, 0, 0, 0, 0, 3, -1]
[0, 4, 6, 0, 0, 0, -1]
[0, 0, 5, 0, 0, 0, -1]
[0, 0, 0, 1, 0, 0, -1]
[0, -2, -2, -2, -2, -2, -3]

def print_mahoujin(houjin, N):
    if houjin is None:
        return
    print(f"{N}x{N}の魔法陣:")
 
    for y in range(1, N + 1):
        for x in range(1, N + 1):
            print(f"{houjin[y][x]:4d}", end=" ")
        print()

print_mahoujinメソッド:

生成された魔法陣を見やすい形式で表示します。

「:4d」はそのフィールドの最小の文字幅を指定しています。配列の縦を揃えるのに便利です。(Python公式ドキュメントより引用)

「end=” “」がないと以下のように改行して表示されてしまうので、必要です。

5x5の魔法陣:
  24
   0
  18
   2
   9

  23
  12
   0
  19
   3

・・・

結果

結果は上のようになりました。

以上です。ありがとうございました✨

タイトルとURLをコピーしました