LoginSignup
1
0

More than 1 year has passed since last update.

リハビリとしてpythonでウラムの螺旋をつくったよ

Posted at

背景

しばらくpython触ってなかったし、ウラムの螺旋の描画をpythonでリハビリがてらやってみるか~
画像化とかまではやってなくて、cmdでウラムの螺旋を表示させるだけです。

ウラムの螺旋とは

ウラムの螺旋 - Wikipedia
詳しいことはwikiに書いてあるので、要約。
1から始まる数字を反時計回り螺旋状に並べていって素数だけを表示させると、なんとなく規則性の有りそうな模様っぽくなるよ。不思議だねというお話。

環境

Python 3.9.9
sympy(素数判定がめんどくさかったので)

本題

run.py
from sympy import sieve

class Ulam():

    def input_data(self):
        self.n = int(input("螺旋の大きさ(n*n):"))

    def create_map(self):#マップ配列を0で初期化
        self.map = [[0 for j in range(self.n)] for i in range(self.n)]

    def print_data(self):#マップを表示
        for i in range(self.n):
            for j in range(self.n):
                print(self.map[i][j],"\t",end="")
            print()

    def init_map(self):#中心に1、メンバ変数にその座標を代入、
        odd_num = 0
        n_slash_2 = int(self.n/2)
        if self.n % 2 == 0:
            self.map[n_slash_2][n_slash_2-1] = 1
            self.current_point_i = n_slash_2
            self.current_point_j = n_slash_2 - 1
        else:
            self.map[n_slash_2][n_slash_2] = 1
            self.current_point_i = n_slash_2
            self.current_point_j = n_slash_2

    def spiral_adding(self):
        loop_num = 0#カレントループ回数
        progress_num = 1#進める数 上下処理後に1増える
        spiral_num = 1#螺旋の数字

        while True:
            loop_num += 1
            if spiral_num >= self.n * self.n:
                break

            if loop_num % 4 == 1:#右
                for _ in range(progress_num):
                    if self.current_point_j >= self.n - 1:#次の螺旋に行かないように制御
                        continue
                    spiral_num += 1
                    self.map[self.current_point_i][self.current_point_j + 1] = spiral_num
                    self.current_point_j += 1
            if loop_num % 4 == 2:#上
                for _ in range(progress_num):
                    spiral_num += 1
                    self.map[self.current_point_i - 1][self.current_point_j] = spiral_num
                    self.current_point_i -= 1
                progress_num += 1#上処理後に進む数を増やす
            if loop_num % 4 == 3:#左
                for _ in range(progress_num):
                    spiral_num += 1
                    self.map[self.current_point_i][self.current_point_j - 1] = spiral_num
                    self.current_point_j -= 1
            if loop_num % 4 == 0:#下
                for _ in range(progress_num):
                    spiral_num += 1
                    self.map[self.current_point_i + 1][self.current_point_j] = spiral_num
                    self.current_point_i += 1
                progress_num += 1#下処理後に進む数を増やす
    def print_ulam(self):#素数をアスタリスクに置き換えて表示
        for i in range(self.n):
            for j in range(self.n):
                if self.map[i][j] in sieve:
                    print("* ",end="")
                else:
                    print("  ",end="")
            print()

def main():
    ulam = Ulam()
    ulam.input_data()
    ulam.create_map()
    ulam.init_map()
    ulam.spiral_adding()
    ulam.print_ulam()
main()

なんとなくコメントが付いてるのでコメント読めば大体わかりますが、一応流れを説明。
ulam.input_data()で螺旋の大きさを入力させて、ulam.create_map()でその数だけゼロで初期化したマップ(二次元配列)を生成します。次にulam.init_map()で一番真ん中の値を1にして、ulam.spiral_adding()で数字の螺旋を生成。最後にulam.print_ulam()で素数だけアスタリスクに置き換えて表示。
すごくオブジェクト指向オブジェクト指向してるけど特に意味はないです。

あとがき

ウラムの螺旋は、東野圭吾の危険なビーナスを読んでたら出てきて、作ってみたくなったので作りました。
螺旋の方向転換があんまりうまくかけなかったな~とか思った。ウラムの螺旋を作った人はたくさんいると思うので参考にしたいと思います。
cmdで表示するのはお手軽だけど、画像化までやったらいい感じになると思うのでやったほうがいいかもね。

1
0
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
1
0