見出し画像

ウラムの螺旋をPythonで作る!!【素数螺旋】

正の整数を1から順に螺旋を描くように書き出し、素数だけマークするとなんだか規則性のようなものが見られる…ロマンをくすぐられる。

左が数字を左回りに並べた様子。右は素数だけを青に置き換えた。

数字を大きくした方がこの規則性らしきものはわかりやすい

約40,000までの様子

目次

・今回の実装環境
・コードの流れ
・コード
・今後の課題
・終わりに

環境

使用言語はpython.
iPadのJunoというアプリ上で実装した。

コードの流れ

kを奇数として、k次正方行列のウラム螺旋に対してk+2次正方行列のウラム螺旋を生成する構造を作れば行列[1]を用意することで帰納的に任意のn(ただしnは奇数)について作れるという発想。
具体的にはk次正方行列のウラム螺旋の四角にくる一般項を求めることで行を生成し、列については転置をとることで同様の操作によって生成する。

素数判定の部分は以下のページを参考にしました。ありがとうございました。
https://qiita.com/srtk86/items/874639e361917e5016d4

コード

import numpy as np
import math

uram = np.array([[1]])

#入力は正の奇数
odd = 51
odd_center = int((odd - 1)/2)

#素数判定機(借り物)
def is_prime(n):
    if n == 1return False

    for k in range(2, int(math.sqrt(n)) + 1):
        if n % k == 0:
            return False
    return True

#メインモジュール
def gen_top(k):
    top = [k**2 - i for i in range(k)]
    return top
def gen_bottom(k):
    bottom = [k**2 - 3*k + 3 +i for i in range(k)]
    return bottom
def gen_t_top(k):
    t_top = [k**2 - 4*k + 5 + i for i in range(k-2)]
    t_top.insert(00)
    t_top.insert(k-10)
    return t_top
def gen_t_bottom(k):
    t_bottom = [k**2 - k - i for i in range(k-2)]
    t_bottom.insert(00)
    t_bottom.insert(k-10)
    return t_bottom

#サイズがkの時,サイズをk+1にする(0を追加)
def size_up(k):
    k = 2*k +1
    pre_size = k - 2
    u_uram = np.insert(uram, 00, axis=0)
    u_uram = np.insert(u_uram, pre_size + 10, axis=0)
    u_uram = u_uram.T
    u_uram = np.insert(u_uram, 00, axis=0)
    u_uram = np.insert(u_uram, pre_size + 10, axis=0)
    return u_uram.T

#実行部
for j in range(odd_center):
    uram = size_up(j+1)
    x = 2*j + 3
    uram[0] += gen_top(x)
    uram[x-1] += gen_bottom(x)
    uram.T[0] += gen_t_top(x)
    uram.T[x-1] += gen_t_bottom(x)

#描画
print(uram)

視覚化する際には以下のループを用いた。この時改行のために print(“\n”) を入れると1行余分な空行が挟まれてしまい苦戦した。(かといってないとすべて続けて出力されてしまう。)
そこで print(“”)としたらうまくいった。なぜだろう。

for i in uram :
    for j in i:
        if is_prime(j)!=True:
            print("⬜️",end="")
        else :
            print("⬛️",end="")
    print("")

今後の課題

・当初は最初にn次正方零行列を作り、そこに数列を行単位で足していこうと思ったが、サイズの違いが壁となり断念。今考えれば普通にループ回して要素指定で入れていけばできるのでは…と思う。今後の課題。
・今回採用したループ毎にサイズアップする方針でも、numpyのよいモジュールがあったんじゃないかと…少し調べたけど一朝一夕での利用はむずそうでハンドメイドの方が先に思いついてしまった。より深く行列操作について学ぶ。
・201×201で7秒くらいかかったので高速化できるならしたい。

終わりに

前々から作りたかったウラムの螺旋を出力するプログラム、numpyの行列操作を学んだことで発想が浮かびついに完成できました。最高です。
ここまで読んでくださりありがとうございました。もしよかったら投げ銭よろしくお願いします、励みと知識になります。

いいなと思ったら応援しよう!