There are few ways to represent a rectangle, one is with one point plus width and height, e.g. top left point and width and height.
(the screen's y grows downwards, top left is 0,0)
β x=8 x
βββββΌββββββββ¬ββββββββββββββββββββββββββββββββ
β β
β β
y=3ββββββββ*βββββββββββββββββββ
β β##################β
β β##################β
β β##################β height
β β##################β
β ββββββββββββββββββββ
β width
β
β
yβ
or you can store the position of two diagonal points, top left and bottom right (or top right and bottom left)
β
β x=8 x=27 x
βββββΌββββββββ¬βββββββββββββββββββ¬βββββββββββββ
β β β
β β β
y=3ββββββββ*βββββββββββββββββββ€
β β##################β
β β##################β
β β##################β
β β##################β
y=8βββββββββ΄ββββββββββββββββββ*
β
β
yβ
In this example I chose the two points appriach as it I can just make a Point class and use it twice, but sometimes the first approach is more suitable. We want to make a Rect class that has a method to expand to include a point.
β
β x=8 x=27 x=31 x
βββββΌββββββββ¬βββββββββββββββββββ¬βββββββββββββ
β β β .
β β β .
y=3ββββββββ*βββββββββββββββββββ€ .
β β##################β+++++.
β β##################β+++++.
β β##################β+++++.
β β##################β+++++.
y=8βββββββββ΄ββββββββββββββββββ*+++++.
β ++++++++++++++++++++++++.
β ++++++++++++++++++++++++.
β ++++++++++++++++++++++++.
β ++++++++++++++++++++++++.
y=12β................................*
β
β
β
yβ
Pause here to think about how to approach this, use pen and paper to illustrate the approach.
The solutio is simply to move the topleft's x/y more left/up if they are bigger than the requested point, and move the bottomright's x/y if they are smaller than the requested point. This way the rectangle grows just enough to include the point.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
class Rect:
def __init__(self, topLeft, bottomRight):
self.topLeft = topLeft
self.bottomRight = bottomRight
def expand(self, point):
if self.topLeft.x > point.x:
self.topLeft.x = point.x
if self.topLeft.y > point.y:
self.topLeft.y = point.y
if self.bottomRight.x < point.x:
self.bottomRight.x = point.x
if self.bottomRight.y < point.y:
self.bottomRight.y = point.y
r = Rect(Point(10,10),Point(20,20))
print(r.topLeft.x, r.topLeft.y,r.bottomRight.x, r.bottomRight.y)
r.expand(Point(5,5))
print(r.topLeft.x, r.topLeft.y,r.bottomRight.x, r.bottomRight.y)
r.expand(Point(50,3))
print(r.topLeft.x, r.topLeft.y,r.bottomRight.x, r.bottomRight.y)
r.expand(Point(50,100))
print(r.topLeft.x, r.topLeft.y,r.bottomRight.x, r.bottomRight.y)
Sometimes its handy to be able to chain method calls, so if the method returns an instance you can just call a method on the returned value.
class Rect:
def __init__(self, topLeft, bottomRight):
self.topLeft = topLeft
self.bottomRight = bottomRight
def expand(self, point):
if self.topLeft.x > point.x:
self.topLeft.x = point.x
...
return self
r = Rect(Point(10,10),Point(20,20))
r.expand(Point(5,5)).expand(Point(50,3)).expand(Point(50,100))
print(r.topLeft.x, r.topLeft.y,r.bottomRight.x, r.bottomRight.y)
Richard Buckland's Higher Computing course is absolutely brilliant, you can watch it on youtube: https://www.youtube.com/watch?v=JA_G8XbVYug&list=PL6B940F08B9773B9F
In the beginning of the course he makes up an virtual 4 bit computer that we can program into useful things.
It has two registers, R0 and R1, 16 4 bit slots in (8 bytes) memory and 16 instructions we could use. Some of the instructions take 1 byte, some take 2 bytes
β IP: instruction pointer
ββββββββ ββββββββ β IS: instruction store (current instruction)
βIP: 0 β βIS: 0 β β R0: register 0
ββββββββ ββββββββ β R1: register 1
ββββββββ ββββββββ βββββββββββββββββββββββββββββββββββββββββββββββ
βR0: 0 β βR1: 0 β β 0 halt
ββββββββ ββββββββ β 1 add R0 = R0 + R1
0 1 2 3 β 2 subtract R0 = R0 - R1
βββββ¬ββββ¬ββββ¬ββββ β 3 increment R0 R0 = R0 + 1
β 0 β 0 β 0 β 0 β β 4 increment R1 R1 = R1 + 1
βββββΌββββΌββββΌββββ€ β 5 decrement R0 R0 = R0 - 1
β 0 β 0 β 0 β 0 β β 6 decrement R1 R1 = R1 - 1
βββββΌββββΌββββΌββββ€ β 7 ring bell
β 0 β 0 β 0 β 0 β β 8 X print data X
βββββΌββββΌββββΌββββ€ β 9 X load value of address X into R0
β 0 β 0 β 0 β 0 β β 10 X load value of address X into R1
βββββ΄ββββ΄ββββ΄ββββ β 11 X store R0 into address X
12 13 14 15 β 12 X store R1 into address X
β 13 X jump to address X
β 14 X jump to address X if R0 == 0
β 15 X jump to address X if R0 != 0
Example programs (also some are from the video lecture):
- print 7 and beep
βββββ¬ββββ¬ββββ¬ββββ
β 8 β 7 β 7 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
- beep 3 times
βββββ¬ββββ¬ββββ¬ββββ
β 7 β 7 β 7 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
- print 3
βββββ¬ββββ¬ββββ¬ββββ
β 8 β 3 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
- what would this program do?
βββββ¬ββββ¬ββββ¬ββββ
β 7 β 10β 3 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
- beep and put 3 in R1
βββββ¬ββββ¬ββββ¬ββββ
β 7 β 10β 15β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 3 β
βββββ΄ββββ΄ββββ΄ββββ
- beep forever
βββββ¬ββββ¬ββββ¬ββββ
β 7 β 13β 0β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 3 β
βββββ΄ββββ΄ββββ΄ββββ
- put the value 4 in R0, increment it and put it back in memory and print it
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9β 14β 3 β 11β
βββββΌββββΌββββΌββββ€
β 14β 13β 13β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 8 β 4 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
Lets walk through each step of the program, you can see the IP(instruction pointer) has a pointer to which memory address it is executing now, and IS(instruction store) is the current instruction:
START load addr 14 in R0 increment R0
ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ
βIP: 0 β βIS: 0 β βIP: 0 β βIS: 10β βIP: 2 β βIS: 3 β
ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ
ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ
βR0: 0 β βR1: 0 β βR0: 4 β βR1: 0 β βR0: 5 β βR1: 0 β
ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ βββββ¬ββββ¬ββββ¬ββββ βββββ¬ββββ¬ββββ¬ββββ
β 9β 14β 3 β 11β β 9β 14β 3 β 11β β 9β 14β 3 β 11β
βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€
β 14β 13β 13β 0 β β 14β 13β 13β 0 β β 14β 13β 13β 0 β
βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β β 0 β 0 β 0 β 0 β β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€
β 0 β 8 β 4 β 0 β β 0 β 8 β 4 β 0 β β 0 β 8 β 4 β 0 β
βββββ΄ββββ΄ββββ΄ββββ βββββ΄ββββ΄ββββ΄ββββ βββββ΄ββββ΄ββββ΄ββββ
put R0 in addr 14 jump to addr 13 print 5
ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ
βIP: 3 β βIS: 11β βIP: 5 β βIS: 13β βIP: 13β βIS: 8 β
ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ
ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ
βR0: 5 β βR1: 0 β βR0: 5 β βR1: 0 β βR0: 5 β βR1: 0 β
ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ βββββ¬ββββ¬ββββ¬ββββ βββββ¬ββββ¬ββββ¬ββββ
β 9β 14β 3 β 11β β 9β 14β 3 β 11β β 9β 14β 3 β 11β
βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€
β 14β 13β 13β 0 β β 14β 13β 13β 0 β β 14β 13β 13β 0 β
βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β β 0 β 0 β 0 β 0 β β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€ βββββΌββββΌββββΌββββ€
β 0 β 8 β 5 β 0 β β 0 β 8 β 5 β 0 β β 0 β 8 β 5 β 0 β
βββββ΄ββββ΄ββββ΄ββββ βββββ΄ββββ΄ββββ΄ββββ βββββ΄ββββ΄ββββ΄ββββ
halt
ββββββββ ββββββββ
βIP: 15β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 4 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9β 14β 3 β 11β
βββββΌββββΌββββΌββββ€
β 14β 13β 13β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 8 β 5 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
We can make a simpler to read language that we can easilly convert to machine code:
code keyword what it does
ββββββΌββββββββββββββββββββββββββββββββββββ
0 β halt halt
1 β add add R0 = R0 + R1
2 β sub subtract R0 = R0 - R1
β
3 β inc r0 increment R0 R0 = R0 + 1
4 β inc r1 increment R1 R1 = R1 + 1
5 β dec r0 decrement R0 R0 = R0 - 1
6 β dec r1 decrement R1 R1 = R1 - 1
β
7 β ring ring bell
β
8 X β print print X (whatever the next byte is)
β
9 X β mov addr, r0 load value of address X into R0
10 X β mov addr, r1 load value of address X into R1
β
11 X β mov r0, addr store R0 into address X
12 X β mov r1, addr store R1 into address X
β
13 X β jmp addr jump to address X
14 X β je addr jump to address X if R0 == 0
15 X β jne addr jump to address X if R0 != 0
now lets rewrite this program
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9β 14β 3 β 11β
βββββΌββββΌββββΌββββ€
β 14β 13β 13β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 8 β 4 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
The same program looks like this:
0 mov 14, r0 # put value of addr 14 in r0
2 inc r0 # r0 += 1
3 mov r0, 14 # put r0's value in addr 14
5 jmp 13 # jump to addr 13
13 print # print the next byte
15 halt # halt
Which surely looks easier to read than 9 14 3 11 14 13 13 0 0 0 0 0 8 4 0
.
Make a program that prints the numbers from 12 to 1
The instructions we will use are:
9X - load value at address X to R0 (R0 = mem[x])
14X - jump to address if r0 == 0
11X - put value of R0 into memory address X (mem[x] = R0)
5 - decrement R0 (R0 -= 1)
13X - jump to address X
8X - print X
And this is the program:
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9 β 15β 14β 12β
βββββΌββββΌββββΌββββ€
β 11β 7 β 8 β 0 β
βββββΌββββΌββββΌββββ€
β 5 β 13β 2 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 12|
βββββ΄ββββ΄ββββ΄ββββ
Lets evaluate the program step by step:
9 15 - load the value of memory address 15 into R0
ββββββββ ββββββββ
βIP: 0 β βIS: 9 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 12β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9 β 15β 14β 12β
βββββΌββββΌββββΌββββ€
β 11β 7 β 8 β 0 β
βββββΌββββΌββββΌββββ€
β 5 β 13β 2 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 12β
βββββ΄ββββ΄ββββ΄ββββ
---
jump to address 12 if R0 == 0
ββββββββ ββββββββ
βIP: 2 β βIS: 14β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 12β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9 β 15β 14β 12β
βββββΌββββΌββββΌββββ€
β 11β 7 β 8 β 0 β
βββββΌββββΌββββΌββββ€
β 5 β 13β 2 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 12β
βββββ΄ββββ΄ββββ΄ββββ
---
place the value of R0 in address 7 (mem[7] = 12)
ββββββββ ββββββββ
βIP: 4 β βIS: 11β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 12β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9 β 15β 14β 12β
βββββΌββββΌββββΌββββ€
β 11β 7 β 8 β 12β
βββββΌββββΌββββΌββββ€
β 5 β 13β 2 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 12β
βββββ΄ββββ΄ββββ΄ββββ
---
print 12
> this is the most important step of the program
> you see in the previous instruction (11 7), we modified the value
> of the print instruction which is about to print the content of
> the next byte, which was zero when our program started,
> but now it is filled with the current value of R0
ββββββββ ββββββββ
βIP: 6 β βIS: 8 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 12β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9 β 15β 14β 12β
βββββΌββββΌββββΌββββ€
β 11β 7 β 8 β 12β
βββββΌββββΌββββΌββββ€
β 5 β 13β 2 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 12β
βββββ΄ββββ΄ββββ΄ββββ
---
decrement R0 (R0 -= 1)
ββββββββ ββββββββ
βIP: 8 β βIS: 5 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 11β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9 β 15β 14β 12β
βββββΌββββΌββββΌββββ€
β 11β 7 β 8 β 12β
βββββΌββββΌββββΌββββ€
β 5 β 13β 2 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 12β
βββββ΄ββββ΄ββββ΄ββββ
---
jump to address 2
ββββββββ ββββββββ
βIP: 9 β βIS: 13β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 11β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9 β 15β 14β 12β
βββββΌββββΌββββΌββββ€
β 11β 7 β 8 β 12β
βββββΌββββΌββββΌββββ€
β 5 β 13β 2 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 12β
βββββ΄ββββ΄ββββ΄ββββ
---
> back from scratch, check if R0 is zero, if not it will put its value
> as the second byte of the print instruction and then decrement it
> until it reaches zero, at which point it will jump to address 12 and halt,
>
ββββββββ ββββββββ
βIP: 12β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 9 β 15β 14β 12β
βββββΌββββΌββββΌββββ€
β 11β 7 β 8 β 1 β
βββββΌββββΌββββΌββββ€
β 5 β 13β 2 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 12β
βββββ΄ββββ΄ββββ΄ββββ
- beep forever
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 7 β 13β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
- print 6 forever
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 8 β 6 β 13β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
- print 0 1 2 3 4 5 6 7 8 ... forever
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 8 β 0 β 3 β 11β
βββββΌββββΌββββΌββββ€
β 1 β 13β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
- if R0 == 0 print 6 else print 7
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 14β 6 β 8 β 7 β
βββββΌββββΌββββΌββββ€
β 13β 8 β 8 β 6 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
- make a program that prints 0 15 1 14 2 13 3 12 4 11 5 10 ... 14 1
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 15β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 11β 5 β 12β 7 β
βββββΌββββΌββββΌββββ€
β 8 β 0 β 8 β 0 β
βββββΌββββΌββββΌββββ€
β 5 β 4 β 14β 15β
βββββΌββββΌββββΌββββ€
β 13β 0 β 0 β 0 β
βββββ΄ββββ΄ββββ΄ββββ
we will start with initial state of R0 and R1 to 15 and 0, then we will put R0's value in memory address 5 and R1 in address 7, where they will become arguments to two print instructions, then we will decrement R0 and increment R1, after that we check if R0 is zero if it is we go to halt at address 15, if not we loop back to the beginning but now with updated values of R0 and R1
- jump to a jump
follow the jumps in this program
ββββββββ ββββββββ
βIP: 0 β βIS: 0 β
ββββββββ ββββββββ
ββββββββ ββββββββ
βR0: 0 β βR1: 0 β
ββββββββ ββββββββ
βββββ¬ββββ¬ββββ¬ββββ
β 13β 2 β 13β 12β
βββββΌββββΌββββΌββββ€
β 13β 14β 13β 10β
βββββΌββββΌββββΌββββ€
β 13β 4 β 13β 8 β
βββββΌββββΌββββΌββββ€
β 13β 6 β 13β 0 β
βββββ΄ββββ΄ββββ΄ββββ
We will make a small program, that can read the program state of our 4 bit computer and run it as it it is real, we will evaluate the input program and depending on the value of the instruction will do what it is said in the instruction set.
def cpu(IP, IS, R0, R1, memory):
# 0 halt
# 1 add R0 = R0 + R1, 2 subtract R0 = R0 - R1
# 3 inc R0, 4 inc R1
# 5 dec R0, 6 dec R1
# 7 ring bell
# 8 X print X
# 9 X R0 = mem[X]
# 10 X R1 = mem[X]
# 11 X mem[X] = R0
# 12 X mem[X] = R1
# 13 X jump to address X
# 14 X jump to address X if R0 == 0
# 15 X jump to address X if R0 != 0
while True:
IS = memory[IP]
print('instruction pointer:',IP,'instruction store:',IS)
if IS == 0:
break
elif IS == 1:
R0 = R0 + R1
IP += 1
elif IS == 2:
R0 = R0 - R1
IP += 1
elif IS == 3:
R0 += 1
IP += 1
elif IS == 4:
R1 += 1
IP += 1
elif IS == 5:
R0 -= 1
IP += 1
elif IS == 6:
R1 -= 1
IP += 1
elif IS == 7:
print("*** BEEP ***")
IP += 1
elif IS == 8:
print("*** ", memory[IP+1], " ***")
IP += 2
elif IS == 9:
R0 = memory[memory[IP+1]]
IP += 2
elif IS == 10:
R1 = memory[memory[IP+1]]
IP += 2
elif IS == 11:
memory[memory[IP+1]] = R0
IP += 2
elif IS == 12:
memory[memory[IP+1]] = R1
IP += 2
elif IS == 13:
IP = memory[IP + 1]
elif IS == 14:
if R0 == 0:
IP = memory[IP + 1]
else:
IP += 2
elif IS == 15:
if R0 != 0:
IP = memory[IP + 1]
else:
IP += 2
state = []
program = input('memory> ').split()
memory = [int(s) for s in program]
cpu(0,0,0,0, memory)
Try to run the above program and when it asks for input type 3 11 4 8 0 13 0
, this is will print 0 1 2 3 4 5 ..., by now you are probably used to seeing the program written as this:
ββββββββββ ββββββββββ
βIP: 0 β βIS: 0 β
ββββββββββ ββββββββββ
ββββββββββ ββββββββββ
βR0: 0 β βR1: 0 β
ββββββββββ ββββββββββ
ββββββ¬βββββ¬βββββ¬βββββ
0 β 3 β 11 β 4 β 8 β 3
ββββββΌβββββΌβββββΌβββββ€
4 β 0 β 13 | 0 β 0 β 7
ββββββΌβββββΌβββββΌβββββ€
8 β 0 β 0 β 0 β 0 β 11
ββββββΌβββββΌβββββΌβββββ€
12 β 0 β 0 β 0 β 0 β 15
ββββββ΄βββββ΄βββββ΄βββββ
Here you can also use a better version that helps you debug your programs and also reads them diectly from a file:
import sys
def ascii(state, highlight):
center = []
for (i, s) in enumerate(state):
if i-4 in highlight:
s = "_"+str(s)+"_"
center.append(str(s).center(4))
print("""
ββββββββββ ββββββββββ
βIP: {0}β βIS: {1}β
ββββββββββ ββββββββββ
ββββββββββ ββββββββββ
βR0: {2}β βR1: {3}β
ββββββββββ ββββββββββ
ββββββ¬βββββ¬βββββ¬βββββ
0 β{4}β{5}β{6}β{7}β 3
ββββββΌβββββΌβββββΌβββββ€
4 β{8}β{9}β{10}β{11}β 7
ββββββΌβββββΌβββββΌβββββ€
8 β{12}β{13}β{14}β{15}β 11
ββββββΌβββββΌβββββΌβββββ€
12 β{16}β{17}β{18}β{19}β 15
ββββββ΄βββββ΄βββββ΄βββββ
""".format(*center))
def cpu(IP, IS, R0, R1, memory):
"""
β IP: instruction pointer
ββββββββ ββββββββ β IS: instruction store, current instruction
βIP: 0 β βIS: 0 β β R0: register 0
ββββββββ ββββββββ β R1: register 1
ββββββββ ββββββββ ββββββββββββββββββββββββββββββββββββββββββββ
βR0: 0 β βR1: 0 β β 0 halt
ββββββββ ββββββββ β 1 add R0 = R0 + R1
0 1 2 3 β 2 subtract R0 = R0 - R1
βββββ¬ββββ¬ββββ¬ββββ β 3 increment R0 R0 = R0 + 1
β 0 β 0 β 0 β 0 β β 4 increment R1 R1 = R1 + 1
βββββΌββββΌββββΌββββ€ β 5 decrement R0 R0 = R0 - 1
β 0 β 0 β 0 β 0 β β 6 decrement R1 R1 = R1 - 1
βββββΌββββΌββββΌββββ€ β 7 ring bell
β 0 β 0 β 0 β 0 β β 8 X print data X
βββββΌββββΌββββΌββββ€ β 9 X load value of address X into R0
β 0 β 0 β 0 β 0 β β 10 X load value of address X into R1
βββββ΄ββββ΄ββββ΄ββββ β 11 X store R0 into address X
12 13 14 15 β 12 X store R1 into address X
β 13 X jump to address X
β 14 X jump to address X if R0 == 0
β 15 X jump to address X if R0 != 0
"""
while True:
IS = memory[IP]
highlight = [IP]
if (IS >= 8):
highlight = [IP, IP+1]
ascii([IP, IS, R0, R1, *memory], highlight)
if IS == 0:
break
elif IS == 1:
R0 = R0 + R1
IP += 1
elif IS == 2:
R0 = R0 - R1
IP += 1
elif IS == 3:
R0 += 1
IP += 1
elif IS == 4:
R1 += 1
IP += 1
elif IS == 5:
R0 -= 1
IP += 1
elif IS == 6:
R1 -= 1
IP += 1
elif IS == 7:
print("*** BEEP ***")
IP += 1
elif IS == 8:
print("*** ", memory[IP+1], "***")
IP += 2
elif IS == 9:
R0 = memory[memory[IP+1]]
IP += 2
elif IS == 10:
R1 = memory[memory[IP+1]]
IP += 2
elif IS == 11:
memory[memory[IP+1]] = R0
IP += 2
elif IS == 12:
memory[memory[IP+1]] = R1
IP += 2
elif IS == 13:
IP = memory[IP + 1]
elif IS == 14:
if R0 == 0:
IP = memory[IP + 1]
else:
IP += 2
elif IS == 15:
if R0 != 0:
IP = memory[IP + 1]
else:
IP += 2
input()
if len(sys.argv) == 1 or ".prg" not in sys.argv[1]:
print("usage: python3 ", sys.argv[0] + " file.prg")
sys.exit(1)
f = open(sys.argv[1])
state = []
for line in f.readlines():
if '#' in line:
continue
line = line.replace("β", " ")
line = line.replace("_", " ")
row = []
for s in line.split():
if s.isdigit():
row.append(int(s))
# remove first and last element in case its pasted from our output
if len(row) == 6:
row.pop(5)
row.pop(0)
if len(row) > 0:
state += row
f.close()
instruction_pointer, instruction_store, r0, r1, *memory = state
cpu(instruction_pointer, instruction_store, r0, r1, memory)
Save a program as 'name.prg' and run it a python3 interpreter.py name.prg
, then press enter for each step of the execution.
For example:
# print 1,2,3,1,2,3,1,2,3... forever
ββββββββββ ββββββββββ
βIP: 0 β βIS: 0 β
ββββββββββ ββββββββββ
ββββββββββ ββββββββββ
βR0: 3 β βR1: 1 β
ββββββββββ ββββββββββ
ββββββ¬βββββ¬βββββ¬βββββ
0 β 12 β 3 β 8 β 0 β 3
ββββββΌβββββΌβββββΌβββββ€
4 β 4 β 5 β 15 β 12 β 7
ββββββΌβββββΌβββββΌβββββ€
8 β 9 β 15 β 10 β 14 β 11
ββββββΌβββββΌβββββΌβββββ€
12 β 13 β 0 β 1 β 3 β 15
ββββββ΄βββββ΄βββββ΄βββββ
Will output of python3 interpreter.py example.prg
:
ββββββββββ ββββββββββ
βIP: 0 β βIS: 12 β
ββββββββββ ββββββββββ
ββββββββββ ββββββββββ
βR0: 3 β βR1: 1 β
ββββββββββ ββββββββββ
ββββββ¬βββββ¬βββββ¬βββββ
0 β_12_β_3_ β 8 β 0 β 3
ββββββΌβββββΌβββββΌβββββ€
4 β 4 β 5 β 15 β 12 β 7
ββββββΌβββββΌβββββΌβββββ€
8 β 9 β 15 β 10 β 14 β 11
ββββββΌβββββΌβββββΌβββββ€
12 β 13 β 0 β 1 β 3 β 15
ββββββ΄βββββ΄βββββ΄βββββ
ββββββββββ ββββββββββ
βIP: 2 β βIS: 8 β
ββββββββββ ββββββββββ
ββββββββββ ββββββββββ
βR0: 3 β βR1: 1 β
ββββββββββ ββββββββββ
ββββββ¬βββββ¬βββββ¬βββββ
0 β 12 β 3 β_8_ β_1_ β 3
ββββββΌβββββΌβββββΌβββββ€
4 β 4 β 5 β 15 β 12 β 7
ββββββΌβββββΌβββββΌβββββ€
8 β 9 β 15 β 10 β 14 β 11
ββββββΌβββββΌβββββΌβββββ€
12 β 13 β 0 β 1 β 3 β 15
ββββββ΄βββββ΄βββββ΄βββββ
*** 1 ***
ββββββββββ ββββββββββ
βIP: 4 β βIS: 4 β
ββββββββββ ββββββββββ
ββββββββββ ββββββββββ
βR0: 3 β βR1: 1 β
ββββββββββ ββββββββββ
ββββββ¬βββββ¬βββββ¬βββββ
0 β 12 β 3 β 8 β 1 β 3
ββββββΌβββββΌβββββΌβββββ€
4 β_4_ β 5 β 15 β 12 β 7
ββββββΌβββββΌβββββΌβββββ€
8 β 9 β 15 β 10 β 14 β 11
ββββββΌβββββΌβββββΌβββββ€
12 β 13 β 0 β 1 β 3 β 15
ββββββ΄βββββ΄βββββ΄βββββ
ββββββββββ ββββββββββ
βIP: 5 β βIS: 5 β
ββββββββββ ββββββββββ
ββββββββββ ββββββββββ
βR0: 3 β βR1: 2 β
ββββββββββ ββββββββββ
ββββββ¬βββββ¬βββββ¬βββββ
0 β 12 β 3 β 8 β 1 β 3
ββββββΌβββββΌβββββΌβββββ€
4 β 4 β_5_ β 15 β 12 β 7
ββββββΌβββββΌβββββΌβββββ€
8 β 9 β 15 β 10 β 14 β 11
ββββββΌβββββΌβββββΌβββββ€
12 β 13 β 0 β 1 β 3 β 15
ββββββ΄βββββ΄βββββ΄βββββ
...
- print 15 then beep without using directly the beep instruction
# 0 halt
# 1 add R0 = R0 + R1
# 2 subtract R0 = R0 - R1
# 3 increment R0 R0 = R0 + 1
# 4 increment R1 R1 = R1 + 1
# 5 decrement R0 R0 = R0 - 1
# 6 decrement R1 R1 = R1 - 1
# 7 ring bell
# 8 X print X
# 9 X R0 = mem[X]
# 10 X R1 = mem[X]
# 11 X mem[X] = R0
# 12 X mem[X] = R1
# 13 X jump to address X
# 14 X jump to address X if R0 == 0
# 15 X jump to address X if R0 != 0
#
# print 15, then modify itself to beep without using the beep instruction
ββββββββββ ββββββββββ
βIP: 0 β βIS: 0 β
ββββββββββ ββββββββββ
ββββββββββ ββββββββββ
βR0: 0 β βR1: 0 β
ββββββββββ ββββββββββ
ββββββ¬βββββ¬βββββ¬βββββ
0 β 9 β 15 β 10 β 14 β 3
ββββββΌβββββΌβββββΌβββββ€
4 β 1 β 8 β 15 β 11 β 7
ββββββΌβββββΌβββββΌβββββ€
8 β 9 β 0 β 0 β 0 β 11
ββββββΌβββββΌβββββΌβββββ€
12 β 0 β 0 β 4 β 3 β 15
ββββββ΄βββββ΄βββββ΄βββββ
Make a cutes care game (like jumpscare but cute), the idea is to make a series of difficult challenges to make the user to concentrate on the game, and when they least expect it show them a cute corgi.
This is the code she wrote, she struggled a bit with the isInside part, but I helped her out.
Also important to google how to play sounds with pygamezero.
import ranom
import pgzrun
WIDTH=800
HEIGHT=800
elf = Actor("c1")
elf.x = 520
elf.y = 420
corgi = Actor("corgi")
data = [
Rect(0,0,100,200),
Rect(520,580, 300, 30),
Rect(750,600, 30, 500),
Rect(490,490, 50, 100),
Rect(500,400, 200, 100),
]
def update():
if keyboard.W:
elf.y -= 2
elf.x += random.randint(-1,1)
if keyboard.S:
elf.y += 2
elf.x += random.randint(-1,1)
if keyboard.D:
elf.x += 2
if keyboard.A:
elf.x -= 2
isInside = False
for d in data:
if elf.colliderect(d):
isInside = True
if not isInside:
elf.x = 520
elf.y = 420
mouse_x = 0
mouse_y = 0
def on_mouse_move(pos):
global mouse_x, mouse_y
mouse_x = pos[0]
mouse_y = pos[1]
def draw():
screen.clear()
for r in data:
screen.draw.rect(r, (255,255,255))
elf.draw()
screen.draw.text("x: " + str(mouse_x) + " y: " + str(mouse_y), (20,20), color=(255,255,255))
if elf.y > 780:
corgi.draw()
sounds.retro.play()
pgzrun.go()