LoginSignup
18
28

それ,numpy で書かない?--6--

Posted at

それ,numpy で書かない?--6--

Python ではリストがよく使われる。また,for ループが遅いのでリストに特化したリスト内包表記も推奨されることが多い。

それなりの根拠があるからではあるが...

課題:リストではなく二次元配列を使う。
リストをうまく操ろうとしてリスト内包表記を濫用すると,とても見通しの悪い,醜いプログラムになる。

副次効果:他の部分のプログラムもシェープアップされる。

以下に,奇数魔方陣を作って,正しいかどうか検証するプログラムを二通り書いて比較してみる。

1. リストとリスト内包表記を使う

def generate_odd_magic_square(n):
    magic_square = [[0] * n for _ in range(n)]
    num = 1
    i, j = 0, n // 2

    while num <= n * n:
        magic_square[i][j] = num
        num += 1
        new_i, new_j = (i - 1) % n, (j + 1) % n
        if magic_square[new_i][new_j]:
            i += 1
        else:
            i, j = new_i, new_j

    return magic_square

def print_magic_square(magic_square):
    for row in magic_square:
        print(" ".join(map(str, row)))

def check_magic_square(square):
    n = len(square)
    magic_constant = n * (n**2 + 1) // 2

    # 行の合計をチェック
    for row in square:
        if sum(row) != magic_constant:
            return False

    # 列の合計をチェック
    for j in range(n):
        col_sum = sum(square[i][j] for i in range(n))
        if col_sum != magic_constant:
            return False

    # 対角線の合計をチェック
    diagonal_sum1 = sum(square[i][i] for i in range(n))
    diagonal_sum2 = sum(square[i][n - 1 - i] for i in range(n))
    if diagonal_sum1 != magic_constant or diagonal_sum2 != magic_constant:
        return False

    return True
n = 7
magic_square = generate_odd_magic_square(n)
print_magic_square(magic_square)
check_magic_square(magic_square)
30 39 48 1 10 19 28
38 47 7 9 18 27 29
46 6 8 17 26 35 37
5 14 16 25 34 36 45
13 15 24 33 42 44 4
21 23 32 41 43 3 12
22 31 40 49 2 11 20

True

2. Nupmhy ndarray を使う

import numpy as np

def generate_odd_magic_square(n):
    magic_square = np.zeros((n, n), dtype=int)
    i, j = 0, n // 2

    for num in range(1, n**2 + 1):
        magic_square[i, j] = num
        new_i, new_j = (i - 1) % n, (j + 1) % n
        if magic_square[new_i, new_j]:
            i += 1
        else:
            i, j = new_i, new_j

    return magic_square

def check_magic_square(square):
    n = square.shape[0]
    magic_constant = n * (n**2 + 1) // 2

    # 行の合計をチェック
    if np.all(np.sum(square, axis=1) != magic_constant):
        return False

    # 列の合計をチェック
    if np.all(np.sum(square, axis=0) != magic_constant):
        return False

    # 対角線の合計をチェック
    return np.trace(square) == magic_constant and np.trace(np.fliplr(square)) == magic_constant

n = 9
test_square = generate_odd_magic_square(n)
print("生成された魔方陣:")
print(test_square)

if check_magic_square(test_square):
    print("魔方陣は正しいです。")
else:
    print("魔方陣は正しくありません。")

生成された魔方陣:
[[47 58 69 80  1 12 23 34 45]
 [57 68 79  9 11 22 33 44 46]
 [67 78  8 10 21 32 43 54 56]
 [77  7 18 20 31 42 53 55 66]
 [ 6 17 19 30 41 52 63 65 76]
 [16 27 29 40 51 62 64 75  5]
 [26 28 39 50 61 72 74  4 15]
 [36 38 49 60 71 73  3 14 25]
 [37 48 59 70 81  2 13 24 35]]
魔方陣は正しいです。
18
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
28