В прошлой статье показал скатерть Улама
( https://ru.wikipedia.org/wiki/Скатерть_Улама https://en.wikipedia.org/wiki/Ulam_spiral )
немного её усовершенствовал в косынку и померял с разных сторон.
Но вот если рисовать точки не по квадрату? Скатерть Улама рисуется обходом точки в форме квадрата, а если обходить по треуголнику или пятиугольнику?
Сохранится тонкая структура линий?
Думаю, что скатерть изменится, но по сути как тонкая структура сохранится, т.е. линии будут, но в другом месте, но точно будут.
В данной статье мы тоже исследуем свойства "скатерти Улама", только немного её уплотним и перерисуем. Наша цель исследовать структуру множества простых чисел, их плотность и равномерность расположения на оси натуральных чисел. У нас уже есть есть файл с первыми 203280222 штук простых чисел, это столько помещается в 64 бита и с такими работать можно быстро.
""" читаем библиотеки для вычислений и загрузки""" import numpy as np import math import struct import matplotlib.pyplot as plt import cv2 from matplotlib.colors import NoNorm
тут считываем начало предвычисленного файла простых чисел. Можно его раздобыть на просторах интернета, можно сделать самому. Но так удобней и проще, не нужно тратить время и ждать вычислений, но есть опасность, что в него может закрасться ошибка
n_primes = 20000000 #203280222 u_primes = np.zeros(n_primes, dtype='int64') u_primes[0] = 1 with open(r'c:\data\203280221.bin', 'rb') as f: for i in range(1, n_primes): s = f.read(8) if s == '': break u_primes[i] = struct.unpack('Q',s)[0]
Маленькая подпрограмма для размещения точек в матрице, т. к. координаты могут быть отрицательными и начало координат, точка (0,0) находится в точке (DIM2, DIM2) матриц, то так лучше. Можно конечно сделать класс, метод, но это лишнее в данном случае.
""" размещение точки на скатерти или на чем придется""" def place_point(x, y, img, color): _x = x + DIM2 _y = y + DIM2 if (_x >= DIM or _y >= DIM or _x < 0 or _y < 0): # print('max ',_x, _y) return (-1) img[_x, _y] = color return (1)
Саму скатерть квадратами рисовать не будем , это было в прошлой статье.
Нарисуем сразу обход в виде треугольника. Он накой же плотный, как и обход квадрата и картинка похожая
kerchief = np.zeros((DIM, DIM, 3), dtype=np.uint8) dir_x = [1,-1,-1] dir_y = [0,-1,1] stps = [1,1,2] stps_d = [4,2,2] cnt = 1 stp = 0 coor_x = 0 coor_y = 0 d_dir = 0 i_cnt = 0 for jj in range(250000): st = u_primes[jj] en = u_primes[jj+1] if (place_point(coor_x, coor_y, kerchief, [1,0,0]) < 0): break for ii in range((en-st)): if (i_cnt == stps[stp]): stp = (stp+1)%3 i_cnt = 0 if stp == 0: stps = np.add(stps,stps_d) # print (coor_x, coor_y, stps, stp, dir_x[stp], dir_y[stp]) coor_x += dir_x[stp] coor_y += dir_y[stp] i_cnt += 1
fig = plt.figure(figsize=(DIM*px, DIM*px)) ax = fig.add_subplot() ax.imshow(ulam*255, norm=NoNorm(), resample=False)

структура стала иной, но осталась наглядной и стройной.
Теперь попробуем обходить точку вокруг по пятиугольнику. Плотно не получится, будут пустые точки, но красиво опять
kerchief = np.zeros((DIM, DIM, 3), dtype=np.uint8) dir_x = [1, 1, 0,-1,-1,-1, 0, 1] dir_y = [0,-1,-1,-1, 0, 1, 1, 1] stps = [1,1,1,1,1,1,1,1] stps_d = [1,1,1,1,1,1,1,1] cnt = 1 stp = 0 coor_x = 1 coor_y = 2 d_dir = 0 i_cnt = 0 i_t = 0 for jj in range(250000): st = u_primes[jj] en = u_primes[jj+1] if (place_point(coor_x, coor_y, kerchief, [1,0,0]) < 0): break for ii in range((en-st)): i_t += 1 if (i_cnt == stps[stp]): stp = (stp+1)%8 i_cnt = 0 if stp == 0: coor_y += 1 coor_x -= 1 stps = np.add(stps,stps_d) # print (coor_x, coor_y, stps, stp, dir_x[stp], dir_y[stp]) coor_x += dir_x[stp] coor_y += dir_y[stp] i_cnt += 1 fig = plt.figure(figsize=(DIM*px, DIM*px)) ax = fig.add_subplot() ax.imshow(kerchief*255, norm=NoNorm(), resample=False)

Считаю, что любая регулярная структура обхода в которой разместить простые числа будет также обладать структурой как на картинке.
