Skip to content

Commit 28ade47

Browse files
hs2361prateekiiest
authored andcommitted
Visualization of Sieve of Eratosthenes algorithm (#181)
* Visualization of Sieve of Eratosthenes algorithm * Added pygame dependency * Re-arranged code
1 parent 8bb2de7 commit 28ade47

File tree

2 files changed

+155
-1
lines changed

2 files changed

+155
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import pygame
2+
import tkinter
3+
import math # importing modules
4+
pygame.init()
5+
num = 0
6+
WHITE = (255, 255, 255)
7+
BLACK = (0, 0, 0)
8+
GREEN = (0, 255, 0)
9+
MAUVE = (224, 176, 255) # colour tuples to be used later in the program
10+
clock = pygame.time.Clock()
11+
12+
13+
def get_num(m, n):
14+
global num
15+
num = int(n.get()) # gets value of num from Tkinter GUI
16+
m.destroy() # destroys root window
17+
18+
19+
def text_objects(text, font):
20+
'''
21+
Function to create TextSurface and TextRect objects for
22+
displaying text on the PyGame window.
23+
It takes 2 parameters:
24+
text : the text to be displayed
25+
font : pygame.font.Font object in which the text is to be rendered
26+
'''
27+
textSurface = font.render(text, True, BLACK)
28+
return textSurface, textSurface.get_rect()
29+
30+
31+
def message_display(text, x, y, size):
32+
'''
33+
Function to display the given 'text' message
34+
at a position of (x,y) in size 'size'
35+
'''
36+
largeText = pygame.font.Font('freesansbold.ttf', size)
37+
TextSurf, TextRect = text_objects(text, largeText)
38+
TextRect.center = (x, y)
39+
display.blit(TextSurf, TextRect)
40+
pygame.display.update()
41+
42+
43+
class Cell: # creating a class for Cell objects on the grid
44+
def __init__(self, x, y, n):
45+
self.pos = (x, y)
46+
self.value = n
47+
self.highlighted = False
48+
# adding the number and cell pair to the celldict dictionary
49+
celldict[self.value] = self
50+
# display the value of the cell on the grid at the center of the cell
51+
message_display(f"{self.value}", x + 16, y + 16, 17)
52+
53+
def highlight(self):
54+
if not self.highlighted:
55+
x, y = self.pos
56+
# create a MAUVE rectangle on top of the cell to highlight
57+
# composite numbers
58+
pygame.draw.rect(display, MAUVE, (x, y, 32, 32))
59+
# rewrite the value of the cell on top of the MAUVE highlight
60+
message_display(f"{self.value}", x + 16, y + 16, 17)
61+
# to avoid time to re-highlight cells that have already been
62+
# highlighted
63+
self.highlighted = True
64+
# for the effect of moving highlight or "scanning" the grid
65+
pygame.time.wait(50)
66+
67+
68+
# getting user input from GUI
69+
m = tkinter.Tk() # root window
70+
l1 = tkinter.Label(m, text='Enter a number', width=25) # label widget
71+
n = tkinter.Entry(m) # entry widget
72+
73+
# calculate button bounded to get_num function
74+
btn = tkinter.Button(m, text='Calculate', command=lambda: get_num(m, n))
75+
l1.pack()
76+
n.pack()
77+
btn.pack() # using pack() geometry manager
78+
m.mainloop() # start GUI
79+
80+
# setting up grid
81+
sq_num = num
82+
if (math.floor(math.sqrt(num))**2 - num != 0):
83+
# getting nearest square greater than or equal to num
84+
sq_num = (math.floor(math.sqrt(num)) + 1)**2
85+
dim = int(sq_num**0.5) # number of rows and columns of the window
86+
87+
# creating a window having 'dim' rows and columns. Each cell has width of 32px
88+
width = 32 * dim
89+
display = pygame.display.set_mode((width, width))
90+
display.fill(WHITE) # fill the display with WHITE color
91+
92+
for i in range(0, width, 32):
93+
pygame.draw.line(display, BLACK, (i, 0), (i, width)
94+
) # drawing row lines 32px apart
95+
for j in range(0, width, 32):
96+
# drawing column lines 32px apart
97+
pygame.draw.line(display, BLACK, (0, j), (width, j))
98+
pygame.display.update()
99+
100+
celldict = {} # dictionary to map numbers to their respective cells
101+
102+
count = 1
103+
for i in range(0, width, 32):
104+
# to deal with internal PyGame events in the event queue which cause the
105+
# system to freeze
106+
pygame.event.pump()
107+
for j in range(0, width, 32):
108+
if (count <= num):
109+
# create a Cell object at every grid intersection
110+
cell = Cell(j, i, count)
111+
clock.tick()
112+
count += 1
113+
else:
114+
break
115+
pygame.display.update()
116+
# Sieving algorithm
117+
# all the numbers except 1 since 1 is neither prime nor composite
118+
nums = set(range(2, num + 1))
119+
composites = {1} # set of composites detected so far
120+
celldict[1].highlight() # highlight the Cell 1
121+
122+
for i in range(
123+
2,
124+
round(
125+
math.sqrt(num)) +
126+
1): # check all numbers till sqrt(num)
127+
if i not in composites:
128+
# cross out all the multiples of prime numbers
129+
comp = [i * k for k in range(2, num // i + 1)]
130+
composites.update(comp)
131+
for val in comp:
132+
pygame.event.pump()
133+
celldict[val].highlight() # highlight the composites
134+
135+
primetxt = '' # string of primes to be displayed
136+
for val, cell in celldict.items():
137+
pygame.event.pump()
138+
if not cell.highlighted: # if the cell has not been highlighted
139+
# it is prime
140+
x, y = cell.pos
141+
# highlight the primes with GREEN
142+
pygame.draw.rect(display, GREEN, (x, y, 32, 32))
143+
message_display(f"{val}", x + 16, y + 16, 17)
144+
pygame.time.wait(100) # to create a moving highlight
145+
primetxt += str(val) + ' ,' # concatenate primes to primetxt string
146+
147+
# Displaying results using GUI
148+
m = tkinter.Tk() # root window
149+
l1 = tkinter.Label(m, text='Primes that were sieved: ')
150+
# Message widget to display the sieved primes
151+
msg = tkinter.Message(m, text=primetxt[:-1], width=200)
152+
l1.pack()
153+
msg.pack()
154+
m.mainloop()

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ scikit-learn >= 0.19
66
bokeh >= 0.12
77
requests >= 2.18
88
msvcrt >= 0.14.0
9-
9+
pygame >= 1.9.6
1010

0 commit comments

Comments
 (0)