diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.classpath b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.classpath new file mode 100644 index 0000000..bb83344 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.project b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.project new file mode 100644 index 0000000..cd00a7c --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.project @@ -0,0 +1,17 @@ + + + Assn10_Mazes + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.settings/org.eclipse.core.resources.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.settings/org.eclipse.jdt.core.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..e71285a --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Collections.java b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Collections.java new file mode 100644 index 0000000..32b2b20 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Collections.java @@ -0,0 +1,126 @@ +import java.util.Deque; +import java.util.ArrayDeque; +import java.util.ArrayList; + +// Represents a mutable collection of items +interface ICollection { + // Is this collection empty? + boolean isEmpty(); + // EFFECT: adds the item to the collection + void add(T item); + // Returns the first item of the collection + // EFFECT: removes that first item + T remove(); +} + +// first in first out +class Stack implements ICollection { + Deque contents; + Stack() { + this.contents = new ArrayDeque(); + } + public boolean isEmpty() { + return this.contents.isEmpty(); + } + public T remove() { + return this.contents.removeLast(); + } + public void add(T item) { + this.contents.addFirst(item); + } +} + +// last in last out +class Queue implements ICollection { + Deque contents; + Queue() { + this.contents = new ArrayDeque(); + } + public boolean isEmpty() { + return this.contents.isEmpty(); + } + public T remove() { + return this.contents.removeLast(); + } + public void add(T item) { + this.contents.addLast(item); // NOTE: Different from Stack! + } +} + +// highest priority out +class PriorityQueue implements ICollection { + ArrayList heap; + IComparator comp; + PriorityQueue(ArrayList inputList, IComparator comp) { + this.comp = comp; + buildHeap(inputList); + } + PriorityQueue(IComparator comp) { + this(new ArrayList(), comp); + } + void buildHeap(ArrayList inputList) { + this.heap = inputList; + for (int i = inputList.size() - 1; i >= 0; i--) { + this.downHeap(i); + } + } + // swaps the parent and child items + void swap(int parentIndex, int childIndex) { + T temp = heap.get(parentIndex); + heap.set(parentIndex, heap.get(childIndex)); + heap.set(childIndex, temp); + } + // recursively uses comp to compare child with parent + // and swaps if child is higher priority + void upHeap(int childIndex) { + int parentIndex = (childIndex - 1) / 2; + // comp will return >0 if left has higher priority than right + // ergo swap when comp returns <0 + if (comp.compare(heap.get(parentIndex), heap.get(childIndex)) < 0) { + this.swap(parentIndex, childIndex); + this.upHeap(parentIndex); + } + } + // recursively uses comp to compare parent with children + // and swaps if child is higher priority + void downHeap(int parentIndex) { + this.downHeapMaxDepth(parentIndex, this.heap.size()); + } + void downHeapMaxDepth(int parentIndex, int maxDepthIndex) { + int leftChildIndex = 2 * parentIndex + 1; + int rightChildIndex = 2 * parentIndex + 2; + if (rightChildIndex < maxDepthIndex) { + if (comp.compare(heap.get(leftChildIndex), heap.get(rightChildIndex)) > 0) { + if (comp.compare(heap.get(parentIndex), heap.get(leftChildIndex)) < 0) { + this.swap(parentIndex, leftChildIndex); + this.downHeapMaxDepth(leftChildIndex, maxDepthIndex); + } + } else if (comp.compare(heap.get(parentIndex), heap.get(rightChildIndex)) < 0) { + this.swap(parentIndex, rightChildIndex); + this.downHeapMaxDepth(rightChildIndex, maxDepthIndex); + } + } else if (leftChildIndex < maxDepthIndex) { + if (comp.compare(heap.get(parentIndex), heap.get(leftChildIndex)) < 0) { + this.swap(parentIndex, leftChildIndex); + this.downHeapMaxDepth(leftChildIndex, maxDepthIndex); + } + } + } + + // Interface methods + public boolean isEmpty() { + return this.heap.isEmpty(); + } + public void add(T item) { + this.heap.add(item); + this.upHeap(heap.size() - 1); + } + public T remove() { + int lastIndex = this.heap.size() - 1; + this.swap(0, lastIndex); + T response = this.heap.remove(lastIndex); + this.downHeap(0); + return response; + } + +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Comparator.java b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Comparator.java new file mode 100644 index 0000000..9a6d990 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Comparator.java @@ -0,0 +1,44 @@ +interface IPred { + boolean apply(T t); +} + +interface IFunc { + R apply(A arg); +} + +interface IFunc2 { + R apply(A1 arg1, A2 arg2); +} + +interface IComparator { + // Returns a negative number if t1 priority is less than t2 priority==- + int compare(T t1, T t2); +} + +class ParentLargerInteger implements IComparator { + // returns true (>0) if left has higher priority (larger int) + public int compare(Integer left, Integer right) { + return left - right; + } +} + +class ParentSmallerInteger implements IComparator { + // returns true (>0) if left has a higher priority (smaller int) + public int compare(Integer left, Integer right) { + return right - left; + } +} + +class ParentLargerEdge implements IComparator { + // returns true (>0) if left edge has a higher priority (lower weight) + public int compare(Hall left, Hall right) { + return left.weight - right.weight; + } +} + +class ParentSmallerEdge implements IComparator { + // returns true (>0) if left edge has a higher priority (higher weight) + public int compare(Hall left, Hall right) { + return right.weight - left.weight; + } +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Maze.java b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Maze.java new file mode 100644 index 0000000..6a4d802 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Maze.java @@ -0,0 +1,213 @@ +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import javalib.impworld.*; +import java.awt.Color; +import javalib.worldimages.*; +import java.util.Random; + +class Room { + String name; // names are needed for Kruskal's algo + ArrayList neighborConnections; + ArrayList openHalls; + int row, col; + Room(String name, ArrayList neighbors, ArrayList openHalls, int row, int col) { + this.name = name; + this.neighborConnections = neighbors; + this.openHalls = openHalls; + this.row = row; + this.col = col; + } + Room(String name, int row, int col) { + this(name, new ArrayList(), new ArrayList(), row, col); + } + Room(int row, int col) { + this(Integer.toString(row) + Integer.toString(col), new ArrayList(), + new ArrayList(), row, col); + } + void addNeighbor(Hall e) { + this.neighborConnections.add(e); + } + void addOpenHall(Hall e) { + this.openHalls.add(e); + } + + void drawRoom(WorldScene scene, Color color) { + scene.placeImageXY( + new RectangleImage( + MazeWorld.ROOM_SIZE_PX, + MazeWorld.ROOM_SIZE_PX, + OutlineMode.SOLID, + color), + col * (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) + + (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) / 2, + row * (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) + + (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) / 2); + } +} + +class Hall { + String name; // names are needed for Kruskal's algo + Room from, to; + int weight; // random weights are used to facilitate maze gen + Hall(String name, Room from, Room to, int weight) { + this.name = name; + this.from = from; + this.to = to; + this.weight = weight; + from.addNeighbor(this); + to.addNeighbor(this); + } + Hall(Room from, Room to, int weight) { + this(from.name + to.name, from, to, weight); + } + + void drawHall(WorldScene scene) { + scene.placeImageXY( + new RectangleImage( + MazeWorld.ROOM_SIZE_PX - 1, + MazeWorld.ROOM_SIZE_PX - 1, + OutlineMode.SOLID, + MazeWorld.ROOM_COLOR), + (from.col + to.col) * (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) / 2 + + (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) / 2, + (from.row + to.row) * (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) / 2 + + (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) / 2); + } +} + +class Maze { + int width, height; // number of vertices across and down + Random rand; + + ArrayList rooms; + ArrayList routeTree; + ArrayList searchTree; + + Maze(int width, int height, Random rand) { + this.width = width; + this.height = height; + this.rand = rand; + genVertsAndEdges(); + genRouteTree(); + } + Maze(int size) { + this(size, size, new Random()); + } + Maze(int width, int height) { + this(width, height, new Random()); + } + Maze(int width, int height, int seed) { + this(width, height, new Random(seed)); + } + void genVertsAndEdges() { + this.rooms = new ArrayList(); + // generate all the vertices + for (int i = 0; i < width * height; i++) { + Room v = new Room(Integer.toString(i), i / width, i % width); + // connect to vertex to the left (right comes for free with next vertex) + if (i % width != 0) { + new Hall(this.rooms.get(i - 1), v, rand.nextInt(10)); + } + // connect to vertex above (below comes for free) + if (i >= width) { + new Hall(this.rooms.get(i - width), v, rand.nextInt(10)); + } + this.rooms.add(v); + } + } + //Kruskal's Tree Algo + void genRouteTree() { + this.routeTree = new ArrayList(); + + HashMap setMap = new HashMap(); + PriorityQueue worklist = new PriorityQueue(new ParentSmallerEdge()); + + for (Room v : this.rooms) { + // initialize every node's representative to itself + setMap.put(v.name, v.name); + for (Hall e : v.neighborConnections) { + // all edges in graph, sorted by edge weights + worklist.add(e); + } + } + Util u = new Util(); + while (!u.isOneTree(this.rooms, setMap)) { + Hall lowestCostEdge = worklist.remove(); + if (u.sameTree(lowestCostEdge.from.name, lowestCostEdge.to.name, setMap)) { + // discard this edge + // they're already connected + } else { + routeTree.add(lowestCostEdge); + u.union(setMap, lowestCostEdge.to.name, lowestCostEdge.from.name); + } + } + for (Hall h : this.routeTree) { + h.from.addOpenHall(h); + h.to.addOpenHall(h); + } + } + void breadthFirstSearch() { + this.searchTree = findPath( + this.rooms.get(0), + this.rooms.get(rooms.size() - 1), + new Queue()); + } + void depthFirstSearch() { + this.searchTree = findPath( + this.rooms.get(0), + this.rooms.get(rooms.size() - 1), + new Stack()); + } + ArrayList findPath(Room from, Room to, ICollection worklist) { + ArrayList alreadySeen = new ArrayList(); + + // Initialize the worklist with the from vertex + worklist.add(from); + // As long as the worklist isn't empty... + while (!worklist.isEmpty()) { + Room next = worklist.remove(); + if (next.equals(to)) { + return alreadySeen; // Success! + } else if (alreadySeen.contains(next)) { + // do nothing: we've already seen this one + } else { + // add all the neighbors of next to the worklist for further processing + for (Hall h : next.neighborConnections) { + worklist.add(h.to); + } + // add next to alreadySeen, since we're done with it + alreadySeen.add(next); + } + } + // We haven't found the to vertex, and there are no more to try + throw new RuntimeException("Could not find a valid path"); + } + + void drawMaze(WorldScene scene) { + scene.placeImageXY( + new RectangleImage( + width * (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX), + height * (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX), + OutlineMode.SOLID, + MazeWorld.WALL_COLOR), + width * (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) / 2, + height * (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) / 2); + // draw each room slightly small + Color roomColor = MazeWorld.ROOM_COLOR; + for (Room r : this.rooms) { + r.drawRoom(scene, roomColor); + } + for (Hall h : this.routeTree) { + h.drawHall(scene); + } + } + void drawSearchTree(WorldScene scene, int tickCount) { + Color searchColor = MazeWorld.SEARCH_COLOR; + for (int i = 0; i <= tickCount && i < this.searchTree.size(); i++) { + this.searchTree.get(i).drawRoom(scene, searchColor); + } + } + +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/MazeExample.java b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/MazeExample.java new file mode 100644 index 0000000..845683e --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/MazeExample.java @@ -0,0 +1,100 @@ +import tester.Tester; +import java.util.Random; + +class Examples { + Random r314 = new Random(314); + Room v0, v1; + Hall e01; + Maze m3; + MazeWorld worldM3; + MazeWorld worldM16; + + void testConstructors(Tester t) { + // test Vertex Constructor + v0 = new Room(0, 0); + t.checkExpect(v0.neighborConnections.size(), 0); + v1 = new Room(0, 1); + // test edge constructor incl adding edges to vertices + e01 = new Hall(v0, v1, r314.nextInt(10)); + t.checkExpect(v0.neighborConnections.size(), 1); + t.checkExpect(v1.neighborConnections.size(), 1); + t.checkExpect(v0.neighborConnections.get(0), e01); + t.checkExpect(v1.neighborConnections.get(0), e01); + // test Maze constructor + m3 = new Maze(3, 3, 314); + // check all vertices were created + t.checkExpect(m3.rooms.size(), 9); + // check rooms were placed in correct location + t.checkExpect(m3.rooms.get(0).row, 0); + t.checkExpect(m3.rooms.get(0).col, 0); + t.checkExpect(m3.rooms.get(1).row, 0); + t.checkExpect(m3.rooms.get(1).col, 1); + t.checkExpect(m3.rooms.get(2).row, 0); + t.checkExpect(m3.rooms.get(2).col, 2); + t.checkExpect(m3.rooms.get(3).row, 1); + t.checkExpect(m3.rooms.get(3).col, 0); + t.checkExpect(m3.rooms.get(4).row, 1); + t.checkExpect(m3.rooms.get(4).col, 1); + t.checkExpect(m3.rooms.get(5).row, 1); + t.checkExpect(m3.rooms.get(5).col, 2); + t.checkExpect(m3.rooms.get(6).row, 2); + t.checkExpect(m3.rooms.get(6).col, 0); + t.checkExpect(m3.rooms.get(7).row, 2); + t.checkExpect(m3.rooms.get(7).col, 1); + t.checkExpect(m3.rooms.get(8).row, 2); + t.checkExpect(m3.rooms.get(8).col, 2); + // check correct number of edges were created + t.checkExpect(m3.rooms.get(0).neighborConnections.size(), 2); + t.checkExpect(m3.rooms.get(1).neighborConnections.size(), 3); + t.checkExpect(m3.rooms.get(2).neighborConnections.size(), 2); + t.checkExpect(m3.rooms.get(3).neighborConnections.size(), 3); + t.checkExpect(m3.rooms.get(4).neighborConnections.size(), 4); + t.checkExpect(m3.rooms.get(5).neighborConnections.size(), 3); + t.checkExpect(m3.rooms.get(6).neighborConnections.size(), 2); + t.checkExpect(m3.rooms.get(7).neighborConnections.size(), 3); + t.checkExpect(m3.rooms.get(8).neighborConnections.size(), 2); + // check that edges connect the correct vertices + t.checkExpect(m3.rooms.get(0).neighborConnections.get(0).to, + m3.rooms.get(1)); + t.checkExpect(m3.rooms.get(0).neighborConnections.get(1).to, + m3.rooms.get(3)); + t.checkExpect(m3.rooms.get(4).neighborConnections.get(0).from, + m3.rooms.get(3)); + t.checkExpect(m3.rooms.get(4).neighborConnections.get(1).from, + m3.rooms.get(1)); + t.checkExpect(m3.rooms.get(4).neighborConnections.get(2).to, + m3.rooms.get(5)); + t.checkExpect(m3.rooms.get(4).neighborConnections.get(3).to, + m3.rooms.get(7)); + t.checkExpect(m3.rooms.get(8).neighborConnections.get(0).from, + m3.rooms.get(7)); + t.checkExpect(m3.rooms.get(8).neighborConnections.get(1).from, + m3.rooms.get(5)); + // check that route tree was created + t.checkExpect(m3.routeTree.size(), 8); + t.checkExpect(m3.rooms.get(0).openHalls.get(0).to, + m3.rooms.get(1)); + t.checkExpect(m3.rooms.get(1).openHalls.get(0).from, + m3.rooms.get(0)); + t.checkExpect(m3.rooms.get(1).openHalls.get(1).to, + m3.rooms.get(4)); + t.checkExpect(m3.rooms.get(1).openHalls.get(2).to, + m3.rooms.get(2)); + t.checkExpect(m3.rooms.get(4).openHalls.get(0).from, + m3.rooms.get(3)); + t.checkExpect(m3.rooms.get(4).openHalls.get(1).from, + m3.rooms.get(1)); + + } + + void init() { + m3 = new Maze(3, 3, 314); + worldM3 = new MazeWorld(m3); + worldM16 = new MazeWorld(new Maze(16, 16, 314)); + } + void testDrawMaze(Tester t) { + init(); + worldM3.start(); + // worldM16.start(); + } +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/MazeWorld.java b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/MazeWorld.java new file mode 100644 index 0000000..1b9045a --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/MazeWorld.java @@ -0,0 +1,65 @@ +import java.awt.Color; +import javalib.impworld.World; +import javalib.impworld.WorldScene; + +class MazeWorld extends World { + // Constants + double TICKRATE = 1.0 / 2; + static int ROOM_SIZE_PX = 64; + static int WALL_SIZE_PX = 1; + static Color ROOM_COLOR = Color.GRAY; + static Color WALL_COLOR = Color.BLACK; + static Color SEARCH_COLOR = Color.blue; + + //Variables + Maze maze; + int tickCount; + + MazeWorld(Maze maze) { + this.maze = maze; + this.tickCount = -1; + } + MazeWorld(int size) { + this(new Maze(size)); + } + MazeWorld(int cols, int rows) { + this(new Maze(cols, rows)); + } + void reset() { + // reset maze to new random start + } + + void start() { + this.bigBang( + (WALL_SIZE_PX + ROOM_SIZE_PX) * maze.width, + (WALL_SIZE_PX + ROOM_SIZE_PX) * maze.height); + } + public WorldScene makeScene() { + WorldScene scene = new WorldScene( + (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) * this.maze.width, + (MazeWorld.ROOM_SIZE_PX + MazeWorld.WALL_SIZE_PX) * this.maze.height); + this.maze.drawMaze(scene); + if (this.tickCount >= 0) { + this.maze.drawSearchTree(scene, this.tickCount); + } + return scene; + } + public void onKeyEvent(String k) { + switch (k) { + case "r": + this.tickCount = -1; + reset(); + case "b": + this.tickCount = 0; + this.maze.breadthFirstSearch(); + case "d": + this.tickCount = 0; + this.maze.depthFirstSearch(); + default: + break; + } + } + public void onTick() { + this.tickCount++; + } +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Util.java b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Util.java new file mode 100644 index 0000000..956336f --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Assn10_Mazes/src/Util.java @@ -0,0 +1,53 @@ +import java.util.ArrayList; +import java.util.HashMap; + +class Util { + Util() {} + + boolean isOneTree(ArrayList vertices, HashMap setMap) { + // this seems wildly inefficient but it works + for (Room v0 : vertices) { + for (Room v1 : vertices) { + if (!this.sameTree(v0.name, v1.name, setMap)) { + return false; + } + } + } + return true; + } + boolean sameTree(String k1, String k2, HashMap setMap) { + return this.getStump(k1, setMap).equals(this.getStump(k2, setMap)); + // if (setMap.get(k1).equals(setMap.get(k2))) { + // // easy answer + // return true; + // } else if (setMap.get(k1).equals(k1) && + // setMap.get(k2).equals(k2)) { + // // if both nodes are part of their own sets they cannot be part + // // of the same set + // return false; + // } else { + // // run up the tree to see if it ends in the same tree + // // i can climb both sides here because when we get to a stump + // // the self reference will by definition create a loop that will + // // be broken by conditional above + // return sameTree(setMap.get(k1), setMap.get(k2), setMap); + // } + } + String getStump(String nodeName, HashMap setMap) { + String nodeSet = setMap.get(nodeName); + if (nodeName.equals(nodeSet)) { + return nodeSet; + } else { + return getStump(nodeSet, setMap); + } + } + void union(HashMap setMap, String k1, String k2) { + if (setMap.get(k2).equals(k2)) { + // if k2 is stump of tree change to k1 + setMap.put(k2, this.getStump(k1, setMap)); + } else { + // go up the tree to change stump's set to k1 + this.union(setMap, k1, setMap.get(k2)); + } + } +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lect33_ObjImplementation/Objects.rkt b/completedwork/core_programming/02_classbased_design/Workspace/Lect33_ObjImplementation/Objects.rkt new file mode 100644 index 0000000..a0d2966 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lect33_ObjImplementation/Objects.rkt @@ -0,0 +1,60 @@ +;; The first three lines of this file were inserted by DrRacket. They record metadata +;; about the language level of this file in a form that our tools can easily process. +#reader(lib "htdp-advanced-reader.ss" "lang")((modname Objects) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #t #t none #f () #f))) +;; An Object is [Itself Name Params -> Value] +;; A Name is a symbol +;; Params is [Listof Value] +;; Itself is the object on which the method is being invoked + +(define object + (λ(this prop args) + (error prop "No such property found"))) +(define (make-pos x y) + (local [(define super object)] + (λ(this prop args) + (cond + [(symbol=? prop 'x) x] + [(symbol=? prop 'y) y] + [(symbol=? prop 'dist-to-0) + (sqrt (+ (sqr x) (sqr y)))] + [(symbol=? prop 'closer-than) + (local [(define that (first args))] + (< (dot this 'dist-to-0 '()) (dot that 'dist-to-0 '())))] + ;; NEW: + [else (super this prop args)])))) +(define (make-3d-pos x y z) + (local [(define super (make-pos x y))] + (λ(this prop args) + (cond + [(symbol=? prop 'z) z] + [(symbol=? prop 'dist-to-0) + (sqrt (+ (sqr x) (sqr y) (sqr z)))] + ;; NEW: + [else (super this prop args)])))) +(define (dot obj prop args) + ;; Passes the object to itself + (obj obj prop args)) + +(define my-pos1 (make-pos 3 4)) +(define my-pos2 (make-pos 6 8)) +(define my-pos3 (make-3d-pos 3 4 12)) + +(check-expect (dot my-pos1 'x '-) 3) +(check-expect (dot my-pos2 'y '-) 8) +(check-error (dot my-pos2 'z '-) "z: No such property found") + +(check-expect (dot my-pos3 'z '-) 12) +(check-error (dot my-pos3 'w '-) "w: No such property found") + +(check-expect (dot my-pos1 'dist-to-0 '-) 5) +(check-expect (dot my-pos2 'dist-to-0 '-) 10) +(check-expect (dot my-pos3 'dist-to-0 '-) 13) + +;; Test 1: (3,4) is closer to the origin than (6,8) +(check-expect (dot my-pos1 'closer-than (list my-pos2)) true) +;; Test 2: (6,8) is not closer to the origin than (3,4) +(check-expect (dot my-pos2 'closer-than (list my-pos1)) false) +;; Test 3: (6,8) is closer to the origin than (3,4,12) +(check-expect (dot my-pos2 'closer-than (list my-pos3)) true) +;; Test 4: (3,4,12) is not closer to the origin than (6,8) +(check-expect (dot my-pos3 'closer-than (list my-pos2)) false) \ No newline at end of file diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.classpath b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.classpath new file mode 100644 index 0000000..8e3d409 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.project b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.project new file mode 100644 index 0000000..4fe4615 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.project @@ -0,0 +1,17 @@ + + + Lect34_DynamicProg + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.settings/org.eclipse.core.resources.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.settings/org.eclipse.jdt.core.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..e71285a --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/src/Fibonacci.java b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/src/Fibonacci.java new file mode 100644 index 0000000..12e9878 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/src/Fibonacci.java @@ -0,0 +1,78 @@ +import tester.Tester; +import java.util.ArrayList; + +class Fibonacci { + int fib(int n, String type) { + switch (type) { + case "recursive": + return fib_recursive(n); + case "memo": + return fib_memo(n); + case "loop": + return fib_loop(n); + default: + return 0; + } + } + int fib_recursive(int n) { + if (n == 0) { + return 1; + } else if (n == 1) { + return 1; + } else { + return fib_recursive(n - 1) + fib_recursive(n - 2); + } + } + int fib_memo(int n) { + ArrayList answers = new ArrayList(); + answers.add(1); // Base cases: fib(0) = 1 + answers.add(1); // fib(1) = 1 + fibAcc(n, answers); + return answers.get(n); + } + int fibAcc(int n, ArrayList answers) { + // Check for redundant computation + if (answers.size() > n) { + return answers.get(n); + } + // Compute the new things: + if (n == 0) { + return 1; + } else if (n == 1) { + return 1; + } else { + int ans = fibAcc(n - 1, answers) + fibAcc(n - 2, answers); + answers.add(ans); + return ans; + } + } + int fib_loop(int n) { + if (n == 0) { + return 1; + } else if (n == 1) { + return 1; + } else { + int prev = 1; + int cur = 2; + for (int i = 2; i < n; i += 1) { + int next = prev + cur; + prev = cur; + cur = next; + } + return cur; + } + } +} + +class FibExamples { + Fibonacci f = new Fibonacci(); + void testFib(Tester t) { + // 1 1 2 3 5 8 13 21 34 + t.checkExpect(f.fib(5, "recursive"), 8); + t.checkExpect(f.fib(8, "recursive"), 34); + t.checkExpect(f.fib(5, "memo"), 8); + t.checkExpect(f.fib(8, "memo"), 34); + t.checkExpect(f.fib(5, "loop"), 8); + t.checkExpect(f.fib(8, "loop"), 34); + } +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/src/Shoppers.java b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/src/Shoppers.java new file mode 100644 index 0000000..27cfedd --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lect34_DynamicProg/src/Shoppers.java @@ -0,0 +1,91 @@ +//import tester.Tester; +//import java.util.ArrayList; +//import java.util.Arrays; +// +//class Shoppers { +// int bestScoreRecursive(ArrayList scores, ArrayList costs, +// int curItemIndex, int remainingBudget) { +// // Base case: no more items +// if (curItemIndex >= scores.size()) { +// return 0; +// } else { +// // Recursive case: take the better of... +// return Math.max( +// // this item +// scores.get(curItemIndex) + +// // score of the best item(s) below with remaining budget +// bestScoreRecursive(scores, costs, +// curItemIndex + 1, +// remainingBudget - costs.get(curItemIndex)), +// // or best item(s) below +// bestScoreRecursive(scores, costs, curItemIndex + 1, remainingBudget)); +// } +// } +// int bestScoreMemo(ArrayList scores, ArrayList costs, int budget) { +// ArrayList> memos = new ArrayList>(); +// // It's a bit easier to pre-fill the array with placeholders, +// // than to try to dynamicalaly fill it during the algorithm itself. +// for (int idx = 0; idx < scores.size(); idx += 1) { +// ArrayList vals = new ArrayList(); +// for (int b = 0; b < budget; b += 1) { +// vals.add(Integer.MAX_VALUE); // Placeholder value to mark invalid answers +// } +// memos.add(vals); +// } +// bestScoreMemoHelp(memos, scores, costs, 0, budget); +// return memos.get(0).get(budget); +// } +// int bestScoreMemoHelp(ArrayList> memos, +// ArrayList scores, ArrayList costs, +// int curItemIndex, int remainingBudget) { +// // Lookup memoized answer: +// if (memos.get(curItemIndex).get(remainingBudget) != Integer.MAX_VALUE) { +// return memos.get(curItemIndex).get(remainingBudget); +// } +// // Base case: no more items +// if (curItemIndex >= scores.size()) { +// return 0; +// } else { +// // Recursive case: take the better of... +// int ans = Math.max( +// // Try buying this item +// scores.get(curItemIndex) + bestScoreRecursive(memos, scores, costs, +// curItemIndex + 1, +// remainingBudget - costs.get(curItemIndex)), +// // Skip buying this item +// bestScoreRecursive(memos, scores, costs, curItemIndex + 1, remainingBudget)); +// memos.get(curItemIndex).set(remainingBudget, ans); +// return ans; +// } +// } +//} +// +//class Examples { +// Shoppers s; +// ArrayList scores0; +// ArrayList costs0; +// +// void init() { +// s = new Shoppers(); +// scores0 = new ArrayList(Arrays.asList( +// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); +// costs0 = new ArrayList(Arrays.asList( +// 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); +// // 10 0 10 10 +// // 9 1 19 9 +// // 8 2 27 7 +// // 7 3 34 4 +// // 6 4 40 0 +// // 5 5 +// // 4 6 +// // 3 7 +// // 2 8 +// // 1 9 +// // 0 10 +// } +// void testBestScore(Tester t) { +// init(); +// t.checkExpect(s.bestScoreRecursive(scores0, costs0, 0, 10), 40); +// t.checkExpect(s.bestScoreMemo(scores0, costs0, 10), 40); +// } +//}