summaryrefslogtreecommitdiff
path: root/hw3
diff options
context:
space:
mode:
Diffstat (limited to 'hw3')
-rw-r--r--hw3/.DS_Storebin0 -> 6148 bytes
-rw-r--r--hw3/Mazes_and_Art.py318
-rw-r--r--hw3/SnowyCloudsInAPlaidSky.pngbin0 -> 591708 bytes
3 files changed, 318 insertions, 0 deletions
diff --git a/hw3/.DS_Store b/hw3/.DS_Store
new file mode 100644
index 0000000..5008ddf
--- /dev/null
+++ b/hw3/.DS_Store
Binary files differ
diff --git a/hw3/Mazes_and_Art.py b/hw3/Mazes_and_Art.py
new file mode 100644
index 0000000..a8260b1
--- /dev/null
+++ b/hw3/Mazes_and_Art.py
@@ -0,0 +1,318 @@
+# -*- coding: utf-8 -*-
+maze = [[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,],
+ [-1, 0, 0, 0,-1, 0, 0, 0,-1,-1, 0,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0,-1,],
+ [ 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,],
+ [-1, 0,-1, 0, 0, 0, 0,-1,-1, 0, 0,-1,-1,-1,-1, 0,-1,-1,-1, 0,-1,-1,],
+ [-1, 0,-1, 0, 0, 0,-1, 0,-1, 0,-1,-1, 0, 0, 0, 0,-1,-1,-1, 0, 0,-1,],
+ [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,-1, 0, 0,-1,-1, 0, 0,-1, 0,-1,],
+ [-1,-1,-1,-1,-1, 0,-1, 0,-1, 0, 0, 0, 0, 0, 0,-1,-1, 0, 0,-1, 0,-1,],
+ [-1,-1,-1,-1,-1, 0,-1,-1,-1, 0, 0,-1, 0,-1, 0, 0,-1,-1, 0, 0, 0,-1,],
+ [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0,-1, 0, 9,-1, 0,-1, 0, 0,-1,],
+ [-1,-1,-1,-1,-1, 0,-1, 0, 0,-1, 0,-1, 0,-1, 0, 0, 0, 0, 0,-1, 0,-1,],
+ [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,]]
+
+"""The above maze is simple. We have obstacles = -1, 0 is an unexplored path, and 9 is the starting point. If we hit the path we want to take, we can give it a value of 3.
+
+We will start at *9* and move until we are outside of the bounds of the maze. Getting the bounds should be easy enough, just use the shape function built into numpy arrays. So if our position $x == 0$ or $y==0$, or $x = x_{bound}$ or $y = y_{bound}$. Lots of options.
+
+"""
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+import time
+from IPython.display import display, clear_output
+
+mmaze = np.array(maze)
+y_b, x_b = mmaze.shape
+print(mmaze)
+plt.pcolor(mmaze[-1::-1,:])
+plt.axis('equal')
+plt.axis('off')
+plt.show()
+
+y, x = np.where(mmaze == 9)
+#Get the starting position
+
+fig = plt.figure()
+
+def move(maze, y, x):
+ global fig
+ # run into an obstacle, return false
+ if maze[y, x] == -1 :
+ return False
+ # run into a square explored, on the path, or dead end
+ if maze[y, x] == 1 or maze[y, x] == 2 or maze[y, x] == 3:
+ return False
+ # Success, an outside edge not occupied by an obstacle
+ if x==0 or y == 0 or x >= maze.shape[1] or y >= maze.shape[0]:
+ try:
+ maze[y,x] = 3
+ except:
+ print("YOU'RE OUTSIDE!")
+ return True
+ maze[y,x] = 1
+
+ # Otherwise, use logical short circuiting to try each
+ # direction in turn (if needed)
+ found = move(maze, y, x+1) or \
+ move(maze, y-1, x) or \
+ move(maze, y, x-1) or \
+ move(maze, y+1, x)
+ plt.pcolor(maze[-1::-1,:])
+ plt.axis('equal')
+ plt.axis('off')
+
+ display(fig)
+ clear_output(wait = True)
+ plt.pause(1e-1)
+ if found:
+ maze[y,x] = 3 # This is the path we wanna follow
+ else:
+ maze[y,x] = 2 #dead end
+ return found
+
+"""
+Lets run our code on the maze code above and see what happens!
+"""
+
+mmaze = np.array(maze)
+y, x = np.where(mmaze == 9)
+move(mmaze,y,x)
+
+"""The cells in the map above have *Moore* connectivity. This means from your postion you can travel *north, south, east, or west*.
+
+A *Neumann* neighborhood adds in the four additional directions *north-east, south-east, south-west, and north-west*. How can you modify the above function to incorporate the *Neumann* neighborhood?
+
+**Task 1 (30 points)**
+"""
+
+def move_neu(maze,y,x):
+ global fig
+ # run into an obstacle, return false
+ if maze[y, x] == -1 :
+ return False
+ # run into a square explored, on the path, or dead end
+ if maze[y, x] == 1 or maze[y, x] == 2 or maze[y, x] == 3:
+ return False
+ # Success, an outside edge not occupied by an obstacle
+ if x==0 or y == 0 or x >= maze.shape[1] or y >= maze.shape[0]:
+ try:
+ maze[y,x] = 3
+ except:
+ print("YOU'RE OUTSIDE!")
+ return True
+ maze[y,x] = 1
+
+ # Otherwise, use logical short circuiting to try each
+ # direction in turn (if needed)
+ found = move_neu(maze, y+1, x+1) or \
+ move_neu(maze, y, x+1) or \
+ move_neu(maze, y-1, x+1) or \
+ move_neu(maze, y-1, x) or \
+ move_neu(maze, y-1, x-1) or \
+ move_neu(maze, y, x-1) or \
+ move_neu(maze, y+1, x-1) or\
+ move_neu(maze, y+1, x)
+
+ plt.pcolor(maze[-1::-1,:])
+ plt.axis('equal')
+ plt.axis('off')
+
+ display(fig)
+ clear_output(wait = True)
+ plt.pause(1e-1)
+ if found:
+ maze[y,x] = 3 # This is the path we wanna follow
+ else:
+ maze[y,x] = 2 #dead end
+ return found
+
+mmaze = np.array((maze))
+y, x = np.where(mmaze == 9)
+print(f"Starting move_neu with x={x} and y={y}")
+move_neu(mmaze,y,x)
+
+"""** Task 2 (20 Points) **
+Make another maze. Programmatically or by modifying the above maze.
+
+Alter the order of moves in the move function and measure the time it takes to solve the maze. Is there an optimal order of operations?
+
+***Hint: use %timeit and kill the plotting ***
+"""
+# nue maze made by me
+maze = [[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,],
+ [-1, 0, 0, 0,-1, 0, 0, 0,-1,-1, 0,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0,-1,],
+ [ -1, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,0,-1,-1,],
+ [-1, 0,-1, 0, 0, 0, 0,-1,-1, 0, 0,-1,-1,-1,-1, 0,-1,-1,-1, 0,-1,-1,],
+ [-1, 0,-1, 0, 0, 0,-1, 0,-1, 0,-1,-1, 0, 0, 0, 0,-1,-1,-1, 0, 0,-1,],
+ [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,-1, 0, 0,-1,-1, 0, 0,-1, 0,-1,],
+ [0,0,-1,-1,-1, 0,-1, 0,-1, 0, 0, 0, 0, 0, 0,-1,-1, 0, 0,-1, 0,-1,],
+ [-1,-1,-1,-1,-1, 0,-1,-1,-1, 0, 0,-1, 0,-1, 0, 0,-1,-1, 0, 0, 0,-1,],
+ [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0,-1, 0, 9,-1, 0,-1, 0, 0,-1,],
+ [-1,-1,-1,-1,-1, 0,-1, 0, 0,-1, 0,-1, 0,-1, 0, 0, 0, 0, 0,-1, 0,-1,],
+ [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,]]
+
+
+from time import time
+
+def move_rdlu(maze, x, y, order):
+
+ # run into an obstacle, return false
+ if maze[y, x] == -1 :
+ return False
+ # run into a square explored, on the path, or dead end
+ if maze[y, x] == 1 or maze[y, x] == 2 or maze[y, x] == 3:
+ return False
+ # Success, an outside edge not occupied by an obstacle
+ if x==0 or y == 0 or x >= maze.shape[1] or y >= maze.shape[0]:
+ try:
+ maze[y,x] = 3
+ except:
+ print("YOU'RE OUTSIDE!")
+ return True
+ maze[y,x] = 1
+
+ # Otherwise, use logical short circuiting to try each
+ # direction in turn (if needed)
+ found = move_rdlu(maze, x + order[0][0], y + order[0][1], order) or \
+ move_rdlu(maze, x + order[1][0], y + order[1][1], order) or \
+ move_rdlu(maze, x + order[2][0], y + order[2][1], order) or \
+ move_rdlu(maze, x + order[3][0], y + order[3][1], order)
+ if found:
+ maze[y,x] = 3 # This is the path we wanna follow
+ else:
+ maze[y,x] = 2 #dead end
+ return found
+
+# This is all 24 possible combinations (taken from google)
+moves = ["rlud", "rldu", "rdlu", "drlu", "ruld", "rudl", "rdul", "drul",
+ "urld", "urdl", "udrl", "durl", "lrud", "lrdu", "ldru", "dlru",
+ "lurd", "ludr", "ldur", "dlur", "ulrd", "uldr", "udlr", "dulr"]
+
+# These are the numbers that have to be added based on their direction
+directions = {
+ "r": (1, 0),
+ "l": (-1, 0),
+ "u": (0, 1),
+ "d": (0, -1)
+}
+
+# using a dictionary for timing so I can easily do multiple tests
+times = dict((move,0) for move in moves)
+
+
+# for each move calculate a list of addition tuples in order and then run
+n = 30
+for i in range(n):
+ for move in moves:
+ mmaze = np.array((maze))
+ y, x = np.where(mmaze == 9)
+ order = []
+ for l in move:
+ order.append(directions[l])
+
+ t0 = time()
+ move_rdlu(mmaze,x,y, order)
+ t1 = time()-t0
+ times[move] += t1
+
+for k in times:
+ times[k] /= n
+
+times = list(times.values())
+
+print(times)
+fig = plt.figure()
+plt.bar(moves, times, figure=fig) # purdy graf
+plt.show()
+
+"""** Task 3 (50 Points) **
+
+Plagarized from a class on Haskel at Stanford [http://nifty.stanford.edu/2018/stephenson-mondrian-art/Handout_Fall.pdf] We are not doing the same problem, but something similar.
+
+Piet Mondrian (March 7, 1872 – February 1, 1944) was a Dutch painter who created numerous famous
+paintings in the early half of the previous century that consisted of a white background, prominent black
+horizontal and vertical lines, and regions colored with red, yellow and blue. Three examples are shown
+Below is included some boiler plate code to setup a plot employing patches of rectangles onto a 1000 x 800 pixel image.
+
+You need to write a code which will recursively divide the *Canvas* and *paint* each portion of the *canvas*.
+
+It is your choice when to stop dividing the domain and how to paint each of the sections.
+
+You do not need to limit your color pallette or how far down you recurse (though sub pixel division will not produce a change).
+
+In order to get full marks you need to define a series of functions which will recursively produce some **art**.
+
+Thorough comments throughout your code will have a large effect on your final grade. Clearly mark out your base case for recursion. Define any design choices explicitly (i.e. if a sub-divided region is to narrow it merges with a neighbor). If you use a **magic-number**, state why. If you are implementing a random number, why? If using RNG, can you seed it and consistently recreate your art?
+"""
+
+import random
+import numpy as np
+import matplotlib.pyplot as plt
+from matplotlib.patches import Rectangle, Circle
+
+from IPython.display import display, clear_output
+plt.rcParams["figure.figsize"] = (10,10)
+fig = plt.figure()
+domain = (1000,800)
+plt.xlim(0,domain[0])
+plt.ylim(0,domain[1])
+plt.axis('off')
+ax = fig.gca()
+
+rects = [Rectangle((50, 100), 400, 320, linewidth=1, edgecolor='r', facecolor='r'),
+ Rectangle((125, 500), 100, 200, linewidth=1, edgecolor='k', facecolor='g'),
+ Rectangle((625, 10), 290, 50, linewidth=11, edgecolor='k', facecolor='b'),
+ Rectangle((725, 600), 75, 150, linewidth=5, edgecolor='g', facecolor='m')]
+[ax.add_patch(rect) for rect in rects]
+
+plt.show()
+
+def rectangles(x0, x1, y0, y1):
+ """ This Generates nices squares with circles that make what lookes like
+ snowy clouds. I like it"""
+ # base case because pixels get too tiny
+ if (x1-x0)*(y1-y0) < 16*16:
+ return False
+ else:
+ # 2 is a nice number and doesn't leave blanks
+ xmid = (x1+x0) // 2
+ ymid = (y1+y0) // 2
+
+ width = (x1-x0) // 2
+ height = (y1-y0) // 2
+
+ rects = [Rectangle((x0, y0), width, height, linewidth=1, edgecolor='k', facecolor='r'),
+ Rectangle((xmid, ymid), width, height, linewidth=1, edgecolor='k', facecolor='g'),
+ Rectangle((x0, ymid), width, height, linewidth=1, edgecolor='k', facecolor='b'),
+ Rectangle((xmid, y0), width, height, linewidth=1, edgecolor='k', facecolor='m'),
+ Circle((xmid, y1), width//2, linewidth=1, edgecolor='k', facecolor="w") # circle needs to be smaller so you can see squares
+ ]
+ [ax.add_patch(rect) for rect in rects]
+
+ show = False # Set this equal to True if you want to see it generate step by step
+ if show:
+ display(fig)
+ clear_output(wait = True)
+ plt.pause(1e-15)
+
+
+ rectangles(x0, xmid, y0, ymid)
+ rectangles(xmid, x1, ymid, y1)
+ rectangles(x0, xmid, ymid, y1)
+ rectangles(xmid, x1, y0, ymid)
+
+plt.rcParams["figure.figsize"] = (10,10)
+fig = plt.figure()
+domain = (1024, 1024)
+plt.xlim(0,domain[0])
+plt.ylim(0,domain[1])
+plt.axis('off')
+ax = fig.gca()
+print("STARTING")
+rectangles(0, domain[0], 0, domain[1])
+plt.savefig('SnowyCloudsInAPlaidSky.png')
+plt.show()
+
+
diff --git a/hw3/SnowyCloudsInAPlaidSky.png b/hw3/SnowyCloudsInAPlaidSky.png
new file mode 100644
index 0000000..f92280d
--- /dev/null
+++ b/hw3/SnowyCloudsInAPlaidSky.png
Binary files differ