Prime Spiral

Being fascinated by prime numbers I wanted to create a prime number spiral generator myself. It just goes through the numbers from 0 to … and checks if they are prime. If they are prime, this rectangle in the spiral gets lit red, if it is not prime it gets lit dark gray. Because my algorithm for prime checking is very basic, I implemented a performance helper. That way the spiral’s creation will slow down after time (due to the numbers that need to be checked getting bigger and bigger). The really interesting thing is, that – although they may seem random – prime numbers often form lines if shown in such a spiral. To see the comparison I included an image of a randomly (50% to 50%) lit up board.
Prime Spiral (Bigger) Prime Spiral (stretched) Prime Spiral (bigger pixels) Random Spiral


# Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 28th of May, 2015

# importing needed modules
import pygame, sys, time, math, os, random

""" CLASSES """
# dummy class for global variables
class dummy():
	pass

# entity class
class entity():
	# init
	def __init__(self, _pos, _number):
		self.pos = _pos
		self.number = _number
		
		self.size = main.ENTITYSIZE
		self.screenPos = [self.pos[0] * self.size[0], self.pos[1] * self.size[1]]
		
		# calculate color based of number
		if self.number == 0:
			# color in begin
			self.color = [255, 255, 255]
		elif lit(self.number):
			# color in lit numbers
			self.color = [255, 0, 0]
		else:
			# color in checked but not lit numbers
			self.color = [50, 50, 50]
		
		# self.dead defines if entity is alive
		self.dead = False

	# render the entity and set self.dead
	# to True (for better performance)
	def render(self, _surface):
		pygame.draw.rect(_surface, self.color, [self.screenPos[0], self.screenPos[1], self.size[0], self.size[1]])
		self.dead = True


""" FUNCTIONS """
# checks if given number should be lit on
def lit(_num):
	# prime check
	if _num <= 1: 		return False 	for _ in range(2, _num): 		if _num % _ == 0: 			return False 	return True # adds in a new entity # (on next spiral position) def addNew(): 	# change main.POS 	if main.DIR == "up": 		main.POS[1] -= 1 	elif main.DIR == "down": 		main.POS[1] += 1 	elif main.DIR == "left": 		main.POS[0] -= 1 	elif main.DIR == "right": 		main.POS[0] += 1 	 	# change direction if needed 	main.CURRENT += 1 	if main.CURRENT > int(main.MAX):
		main.CURRENT = 0
		main.MAX += .5
		if main.DIR == "up":
			main.DIR = "left"
		elif main.DIR == "down":
			main.DIR = "right"
		elif main.DIR == "left":
			main.DIR = "down"
		elif main.DIR == "right":
			main.DIR = "up"
	
	# add entity
	main.ENTITIES.append(entity(main.POS[:], main.NUM))
	
	# main.NUM gets increased
	main.NUM += 1

# gets the mouse position
def getMousePos():
	p = pygame.mouse.get_pos()
	return [p[0], p[1]]

# validates color integer
# extra feature: _min and _max implementation
def colorValid(_color, _min = 0, _max = 255):
	newColor = math.fabs(_color)
	n = _max - _min
	if newColor > n:
		if int(newColor / n) % 2 == 0:
			newColor = newColor % n
		else:
			newColor = n - (newColor % n)
	
	return int(newColor) + _min

# gets the position on a circle
# circle center                           : '_pos'
# circle radius                           : '_radius'
# angle from center to point on the circle: '_angle'
def getCirclePos(_pos, _radius, _angle):
	return [
				_pos[0] + _radius * math.cos(math.radians(_angle)),
				_pos[1] + _radius * math.sin(math.radians(_angle))
			]

# returns an integer version of given positon
def intpos(_pos):
	return [int(_pos[0]), int(_pos[1])]

# basic vector functions
def vecConvert(p1, p2):
	return [p2[0] - p1[0], p2[1] - p1[1]]
def vecLen(vec):
	return math.sqrt( (vec[0]**2) + (vec[1]**2) )
def vecMultiply(vec, n):
	return [vec[0] * n, vec[1] * n]
def vecGetPoint(vec, point):
	return [point[0] + vec[0], point[1] + vec[1]]
def vecAdd(vec1, vec2):
	return [vec1[0] + vec2[0], vec1[1] + vec2[1]]

# calculates distance between given positions
def posDistance(p1, p2):
	return math.sqrt( (p2[0] - p1[0])**2 + (p2[1] - p1[1])**2 )

# quits the program
def quit():
	sys.exit()

""" TICK; RENDER """
# tick function
def tick():
	# handle events
	for event in pygame.event.get():
		# quit
		if event.type == pygame.QUIT:
			quit()
		
		# keyup
		if event.type == pygame.KEYUP:
			# handle 'main.KEYSDOWN'
			if event.key in main.KEYSDOWN:
				main.KEYSDOWN.remove(event.key)
		
		# keydown
		if event.type == pygame.KEYDOWN:
			# handle 'main.KEYSDOWN'
			if event.key not in main.KEYSDOWN:
				main.KEYSDOWN.append(event.key)
			
	
	# add new entities
	for _ in range(0, main.ENTITYAPPEARANCESPEED):
		# permormance assurance
		if len(main.ENTITIES) <	main.ENTITYAPPEARANCESPEED * 2: 			addNew() 	 	# remove already drawn (dead) entities 	for _ in main.ENTITIES: 		if _.dead: 			main.ENTITIES.remove(_) # render function def render(): 	# render entities 	for _ in main.ENTITIES: 		_.render(main.SURF) 	 	# blit and flip 	main.SCREEN.blit(main.SURF, [0, 0]) 	pygame.display.flip() """ INIT """ # initialize program def init(): 	main.WIDTH, main.HEIGHT = 1080, 720 	main.SIZE = [main.WIDTH, main.HEIGHT] 	main.CENTER = [main.WIDTH / 2., main.HEIGHT / 2.] 	 	main.SCREEN = pygame.display.set_mode(main.SIZE) 	 	 	main.SURF = pygame.Surface(main.SIZE) 	main.COLOR = [0, 0, 0] 	 	main.TICKS = 0 	main.KEYSDOWN = [] 	main.CAPTION = "Prime Spiral" 	 	# entity init 	main.ENTITIES = [] 	main.ENTITYSIZE = [2, 2] 	main.ENTITYAPPEARANCESPEED = 20 	 	main.DIR = "up" 	main.CURRENT = -1 	main.MAX = 0 	main.POS = intpos([main.CENTER[0] / main.ENTITYSIZE[0], main.CENTER[1] / main.ENTITYSIZE[1]]) 	main.NUM = 0 	 	# functions 	pygame.display.set_caption(main.CAPTION) 	main.SURF.fill(main.COLOR) """ RUN """ # run function (uses tick() and render()) def run(): 	ticksPerSecond = 60 	lastTime = time.time() * 1000000000 	nsPerTick =  1000000000.0 / float(ticksPerSecond) 	 	ticks = 0 	frames = 0 	 	lastTimer = time.time() * 1000 	delta = 0.0 	 	while True: 		now = time.time() * 1000000000 		delta += float(now - lastTime) / float(nsPerTick) 		lastTime = now 		shouldRender = False 				 		while delta >= 1:
			ticks += 1
			main.TICKS += 1
			tick()
			delta -= 1
			shouldRender = True
		
		if shouldRender:
			frames += 1
			render()
		
		if time.time() * 1000 - lastTimer >= 1000:
			lastTimer += 1000
			
			# debug
			#print("Frames: " + str(frames) + ", ticks: " + str(ticks))
			
			frames = 0
			ticks = 0

# main variable
main = dummy()
init()

# start program
run()
Advertisements

3 thoughts on “Prime Spiral

  1. Pingback: Primes | J-Blog

  2. Pingback: Prime Spiral II | J-Blog

  3. Pingback: Second Anniversary – J-Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s