├── .gitignore ├── README.md ├── week_1 ├── Percolation.java └── PercolationStats.java ├── week_2 ├── Deque.java ├── Permutation.java └── RandomizedQueue.java ├── week_3 ├── BruteCollinearPoints.java ├── FastCollinearPoints.java └── Point.java ├── week_4 ├── Board.java └── Solver.java └── week_5 ├── KdTree.java └── PointSET.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What this repository is about? 2 | My solutions to the course "Algorithms, Part I" 3 | -------------------------------------------------------------------------------- /week_1/Percolation.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdOut; 2 | import edu.princeton.cs.algs4.WeightedQuickUnionUF; 3 | 4 | /** 5 | * @author Dima Pasieka 6 | */ 7 | public class Percolation { 8 | 9 | // Length of the square grid "gridLength * gridLength" 10 | private int gridLength; 11 | 12 | // Array representing indexes of all sites (either it"s open or blocked) 13 | private boolean[] sites; 14 | 15 | // Number of open sites 16 | private int openSitesNumber; 17 | 18 | // Index of the top virtual site (has value 0) 19 | private int virtualTopIndex; 20 | 21 | // Index of the top virtual site (has value (gridLength * gridLength) + 1) 22 | private int virtualBottomIndex; 23 | 24 | // Weighted quick union-find data structure 25 | // to calculate percolation 26 | private WeightedQuickUnionUF ufForPercolation; 27 | 28 | // Weighted quick union-find data structure 29 | // to calculate fullness (without bottom virtual site) 30 | private WeightedQuickUnionUF ufForFullness; 31 | 32 | // Create n-by-n grid, with all sites blocked 33 | public Percolation(int n) { 34 | if (n < 1) { 35 | throw new IllegalArgumentException("Grid must have at least one row and column"); 36 | } 37 | 38 | gridLength = n; 39 | int gridSize = (n * n) + 2; // with two virtual sites 40 | sites = new boolean[gridSize]; 41 | openSitesNumber = 0; 42 | 43 | // init and open virtual sites 44 | virtualTopIndex = 0; 45 | virtualBottomIndex = (gridLength * gridLength) + 1; 46 | sites[virtualTopIndex] = true; 47 | sites[virtualBottomIndex] = false; 48 | 49 | ufForPercolation = new WeightedQuickUnionUF(gridSize); 50 | ufForFullness = new WeightedQuickUnionUF(gridSize); 51 | 52 | // connect top and bottom rows to virtual sites 53 | for (int col = 1; col <= gridLength; col++) { 54 | int rowTop = 1; 55 | int siteTopIndex = getIndexByRowAndColumn(rowTop, col); 56 | ufForPercolation.union(virtualTopIndex, siteTopIndex); 57 | ufForFullness.union(virtualTopIndex, siteTopIndex); 58 | 59 | int rowBottom = gridLength; 60 | int siteBottomIndex = getIndexByRowAndColumn(rowBottom, col); 61 | ufForPercolation.union(virtualBottomIndex, siteBottomIndex); 62 | } 63 | } 64 | 65 | // Open site (row, col) if it is not open already 66 | public void open(int row, int col) 67 | { 68 | int siteIndex = getIndexByRowAndColumn(row, col); 69 | if (sites[siteIndex]) { 70 | return; 71 | } 72 | 73 | openSitesNumber++; 74 | sites[siteIndex] = true; 75 | 76 | // connect with left neighbor 77 | if (col > 1 && isOpen(row, col - 1)) { 78 | int siteLeftIndex = getIndexByRowAndColumn(row, col - 1); 79 | ufForPercolation.union(siteIndex, siteLeftIndex); 80 | ufForFullness.union(siteIndex, siteLeftIndex); 81 | } 82 | 83 | // connect with right neighbor 84 | if (col < gridLength && isOpen(row, col + 1)) { 85 | int siteLeftIndex = getIndexByRowAndColumn(row, col + 1); 86 | ufForPercolation.union(siteIndex, siteLeftIndex); 87 | ufForFullness.union(siteIndex, siteLeftIndex); 88 | } 89 | 90 | // connect with top neighbor 91 | if (row > 1 && isOpen(row - 1, col)) { 92 | int siteLeftIndex = getIndexByRowAndColumn(row - 1, col); 93 | ufForPercolation.union(siteIndex, siteLeftIndex); 94 | ufForFullness.union(siteIndex, siteLeftIndex); 95 | } 96 | 97 | // connect with bottom neighbor 98 | if (row < gridLength && isOpen(row + 1, col)) { 99 | int siteLeftIndex = getIndexByRowAndColumn(row + 1, col); 100 | ufForPercolation.union(siteIndex, siteLeftIndex); 101 | ufForFullness.union(siteIndex, siteLeftIndex); 102 | } 103 | } 104 | 105 | // If site (row, col) open 106 | public boolean isOpen(int row, int col) 107 | { 108 | int siteIndex = getIndexByRowAndColumn(row, col); 109 | 110 | return sites[siteIndex]; 111 | } 112 | 113 | // If site (row, col) full 114 | public boolean isFull(int row, int col) 115 | { 116 | int siteIndex = getIndexByRowAndColumn(row, col); 117 | 118 | return (isOpen(row, col) && ufForFullness.connected(virtualTopIndex, siteIndex)); 119 | } 120 | 121 | // Number of open sites 122 | public int numberOfOpenSites() 123 | { 124 | return openSitesNumber; 125 | } 126 | 127 | // If the system percolate 128 | public boolean percolates() 129 | { 130 | // if grid with one site - check if it"s open 131 | if (gridLength == 1) { 132 | int siteIndex = getIndexByRowAndColumn(1, 1); 133 | return sites[siteIndex]; 134 | } 135 | 136 | return ufForPercolation.connected(virtualTopIndex, virtualBottomIndex); 137 | } 138 | 139 | // Get site"s index to be represented in array 140 | private int getIndexByRowAndColumn(int row, int col) 141 | { 142 | validateBounds(row, col); 143 | 144 | return ((row - 1) * gridLength) + col; 145 | } 146 | 147 | // Check if row and column values are in range of grid size 148 | private void validateBounds(int row, int col) 149 | { 150 | if (row > gridLength || row < 1) { 151 | throw new IndexOutOfBoundsException("Row index is out of bounds"); 152 | } 153 | 154 | if (col > gridLength || col < 1) { 155 | throw new IndexOutOfBoundsException("Column index is out of bounds"); 156 | } 157 | } 158 | 159 | // Test client (optional) 160 | public static void main(String[] args) 161 | { 162 | Percolation percolation = new Percolation(2); 163 | 164 | StdOut.println("percolates = " + percolation.percolates()); 165 | 166 | StdOut.println("isOpen(1, 2) = " + percolation.isOpen(1, 2)); 167 | StdOut.println("isFull(1, 2) = " + percolation.isFull(1, 2)); 168 | StdOut.println("open(1, 2)"); 169 | percolation.open(1, 2); 170 | StdOut.println("isOpen(1, 2) = " + percolation.isOpen(1, 2)); 171 | StdOut.println("isFull(1, 2) = " + percolation.isFull(1, 2)); 172 | StdOut.println("numberOfOpenSites() = " + percolation.numberOfOpenSites()); 173 | StdOut.println("percolates() = " + percolation.percolates()); 174 | 175 | StdOut.println("isOpen(2, 1) = " + percolation.isOpen(2, 1)); 176 | StdOut.println("isFull(2, 1) = " + percolation.isFull(2, 1)); 177 | StdOut.println("open(2, 1)"); 178 | percolation.open(2, 1); 179 | StdOut.println("isOpen(2, 1) = " + percolation.isOpen(2, 1)); 180 | StdOut.println("isFull(2, 1) = " + percolation.isFull(2, 1)); 181 | StdOut.println("numberOfOpenSites() = " + percolation.numberOfOpenSites()); 182 | StdOut.println("percolates() = " + percolation.percolates()); 183 | 184 | StdOut.println("isOpen(1, 1) = " + percolation.isOpen(1, 1)); 185 | StdOut.println("isFull(1, 1) = " + percolation.isFull(1, 1)); 186 | StdOut.println("open(1, 1)"); 187 | percolation.open(1, 1); 188 | StdOut.println("isOpen(1, 1) = " + percolation.isOpen(1, 1)); 189 | StdOut.println("isFull(1, 1) = " + percolation.isFull(1, 1)); 190 | StdOut.println("numberOfOpenSites() = " + percolation.numberOfOpenSites()); 191 | StdOut.println("percolates() = " + percolation.percolates()); 192 | } 193 | } -------------------------------------------------------------------------------- /week_1/PercolationStats.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdOut; 2 | import edu.princeton.cs.algs4.StdRandom; 3 | import edu.princeton.cs.algs4.StdStats; 4 | 5 | /** 6 | * @author Dima Pasieka 7 | */ 8 | public class PercolationStats { 9 | 10 | // Number of independent experiments on an n-by-n grid 11 | private int trials; 12 | 13 | // Store all threshold results 14 | private double[] thresholdList; 15 | 16 | // Perform trials independent experiments on an n-by-n grid 17 | public PercolationStats(int n, int trials) { 18 | if (n < 1) { 19 | throw new IllegalArgumentException("Grid must have at least one row and column"); 20 | } 21 | 22 | if (trials < 1) { 23 | throw new IllegalArgumentException("You must run percolation at least once"); 24 | } 25 | 26 | this.trials = trials; 27 | thresholdList = new double[trials]; 28 | 29 | for (int i = 0; i < trials; i++) { 30 | Percolation percolation = new Percolation(n); 31 | 32 | while (!percolation.percolates()) { 33 | int row = StdRandom.uniform(1, n + 1); 34 | int col = StdRandom.uniform(1, n + 1); 35 | 36 | percolation.open(row, col); 37 | } 38 | 39 | thresholdList[i] = (double) percolation.numberOfOpenSites() / (n * n); 40 | } 41 | } 42 | 43 | // Sample mean of percolation threshold 44 | public double mean() 45 | { 46 | return StdStats.mean(thresholdList); 47 | } 48 | 49 | // Sample standard deviation of percolation threshold 50 | public double stddev() 51 | { 52 | return StdStats.stddev(thresholdList); 53 | } 54 | 55 | // Low endpoint of 95% confidence interval 56 | public double confidenceLo() 57 | { 58 | return mean() - (1.96 * stddev() / Math.sqrt(trials)); 59 | } 60 | 61 | // High endpoint of 95% confidence interval 62 | public double confidenceHi() 63 | { 64 | return mean() + (1.96 * stddev() / Math.sqrt(trials)); 65 | } 66 | 67 | // Test client 68 | public static void main(String[] args) 69 | { 70 | int gridLength = Integer.parseInt(args[0]); 71 | int trials = Integer.parseInt(args[1]); 72 | 73 | PercolationStats stats = new PercolationStats(gridLength, trials); 74 | 75 | StdOut.println("mean = "+ stats.mean()); 76 | StdOut.println("stddev = "+ stats.stddev()); 77 | StdOut.println("95% confidence interval = "+ stats.confidenceLo() + ", " + stats.confidenceHi()); 78 | } 79 | } -------------------------------------------------------------------------------- /week_2/Deque.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdOut; 2 | 3 | import java.util.Iterator; 4 | import java.util.NoSuchElementException; 5 | 6 | /** 7 | * @author Dima Pasieka 8 | */ 9 | public class Deque implements Iterable 10 | { 11 | // Deque size 12 | private int size; 13 | 14 | // First element of the Deque 15 | private Node first; 16 | 17 | // Last element of the Deque 18 | private Node last; 19 | 20 | // Deque element/item 21 | private class Node 22 | { 23 | Item item; 24 | Node next; 25 | Node previous; 26 | } 27 | 28 | // Deque iterator 29 | private class DequeIterator implements Iterator 30 | { 31 | // Current iterable element 32 | private Node current; 33 | 34 | // Init with first element to start from 35 | private DequeIterator(Node item) 36 | { 37 | current = item; 38 | } 39 | 40 | public boolean hasNext() 41 | { 42 | return (current != null); 43 | } 44 | 45 | public Item next() 46 | { 47 | if (!hasNext()) { 48 | throw new NoSuchElementException("No more elements"); 49 | } 50 | 51 | Item item = current.item; 52 | current = current.next; 53 | 54 | return item; 55 | } 56 | } 57 | 58 | // Construct an empty deque 59 | public Deque() 60 | { 61 | size = 0; 62 | first = null; 63 | last = null; 64 | } 65 | 66 | // If the deque empty 67 | public boolean isEmpty() 68 | { 69 | return (size == 0); 70 | } 71 | 72 | // Return the number of items on the deque 73 | public int size() 74 | { 75 | return size; 76 | } 77 | 78 | // Add the item to the front 79 | public void addFirst(Item item) 80 | { 81 | if (item == null) { 82 | throw new NullPointerException("Can't add empty element to deque"); 83 | } 84 | 85 | Node newItem = new Node<>(); 86 | newItem.item = item; 87 | newItem.next = first; 88 | newItem.previous = null; 89 | 90 | if (isEmpty()) { 91 | last = newItem; 92 | } else { 93 | first.previous = newItem; 94 | } 95 | 96 | first = newItem; 97 | size++; 98 | } 99 | 100 | // Add the item to the end 101 | public void addLast(Item item) 102 | { 103 | if (item == null) { 104 | throw new NullPointerException("Can't add empty element to deque"); 105 | } 106 | 107 | Node newItem = new Node<>(); 108 | newItem.item = item; 109 | newItem.next = null; 110 | newItem.previous = last; 111 | 112 | if (isEmpty()) { 113 | first = newItem; 114 | } else { 115 | last.next = newItem; 116 | } 117 | 118 | last = newItem; 119 | size++; 120 | } 121 | 122 | // Remove and return the item from the front 123 | public Item removeFirst() 124 | { 125 | if (isEmpty()) { 126 | throw new NoSuchElementException("Deque is empty"); 127 | } 128 | 129 | Item item = first.item; 130 | first = first.next; 131 | size--; 132 | 133 | if (isEmpty()) { 134 | last = null; 135 | } else { 136 | first.previous = null; 137 | } 138 | 139 | return item; 140 | } 141 | 142 | // Remove and return the item from the end 143 | public Item removeLast() 144 | { 145 | if (isEmpty()) { 146 | throw new NoSuchElementException("Deque is empty"); 147 | } 148 | 149 | Item item = last.item; 150 | last = last.previous; 151 | size--; 152 | 153 | if (isEmpty()) { 154 | first = null; 155 | } else { 156 | last.next = null; 157 | } 158 | 159 | return item; 160 | } 161 | 162 | // Return an iterator over items in order from front to end 163 | public Iterator iterator() 164 | { 165 | return new DequeIterator<>(first); 166 | } 167 | 168 | // Unit testing 169 | public static void main(String[] args) 170 | { 171 | Deque deque = new Deque<>(); 172 | 173 | String text = "World"; 174 | deque.addFirst(text); 175 | StdOut.println("addFirst() with: '" + text + "'"); 176 | 177 | text = ", "; 178 | deque.addFirst(text); 179 | StdOut.println("addFirst() with: '" + text + "'"); 180 | 181 | text = "Hello"; 182 | deque.addFirst(text); 183 | StdOut.println("addFirst() with: '" + text + "'"); 184 | 185 | text = "Meow, "; 186 | deque.addFirst(text); 187 | StdOut.println("addFirst() with: '" + text + "'"); 188 | 189 | text = "^^"; 190 | deque.addLast(text); 191 | StdOut.println("addLast() with: '" + text + "'"); 192 | 193 | deque.removeFirst(); 194 | StdOut.println("removeFirst()"); 195 | 196 | deque.removeLast(); 197 | StdOut.println("removeLast()"); 198 | 199 | text = "!"; 200 | deque.addLast(text); 201 | StdOut.println("addLast() with: '" + text + "'"); 202 | 203 | StdOut.println("Iterating deque..."); 204 | for (String item: deque) { 205 | StdOut.println("Iterate element: " + item); 206 | } 207 | } 208 | } -------------------------------------------------------------------------------- /week_2/Permutation.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdIn; 2 | import edu.princeton.cs.algs4.StdOut; 3 | 4 | /** 5 | * @author Dima Pasieka 6 | */ 7 | public class Permutation 8 | { 9 | public static void main(String[] args) 10 | { 11 | int count = Integer.parseInt(args[0]); 12 | 13 | RandomizedQueue queue = new RandomizedQueue<>(); 14 | 15 | while (!StdIn.isEmpty()) { 16 | String item = StdIn.readString(); 17 | queue.enqueue(item); 18 | } 19 | 20 | for (int i = 0; i < count; i++) { 21 | StdOut.println(queue.dequeue()); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /week_2/RandomizedQueue.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdOut; 2 | import edu.princeton.cs.algs4.StdRandom; 3 | 4 | import java.util.Iterator; 5 | import java.util.NoSuchElementException; 6 | 7 | /** 8 | * @author Dima Pasieka 9 | */ 10 | public class RandomizedQueue implements Iterable 11 | { 12 | // Items in queue 13 | private Item[] items; 14 | 15 | // RandomizedQueue size 16 | private int size; 17 | 18 | // RandomizedQueue Iterator 19 | private class RandomizedQueueIterator implements Iterator 20 | { 21 | // Items in queue during iteration 22 | private Item[] itemsCopy; 23 | 24 | // RandomizedQueue size during iteration 25 | private int sizeCopy; 26 | 27 | // Init with coping items and size 28 | private RandomizedQueueIterator() 29 | { 30 | sizeCopy = size; 31 | itemsCopy = (Item[]) new Object[sizeCopy]; 32 | 33 | for (int i = 0; i < sizeCopy; i++) { 34 | itemsCopy[i] = items[i]; 35 | } 36 | } 37 | 38 | public boolean hasNext() 39 | { 40 | return (sizeCopy > 0); 41 | } 42 | 43 | public Item next() 44 | { 45 | if (!hasNext()) { 46 | throw new NoSuchElementException("No more elements"); 47 | } 48 | 49 | int index = StdRandom.uniform(sizeCopy); 50 | Item item = itemsCopy[index]; 51 | 52 | // replace taken element with last one 53 | itemsCopy[index] = itemsCopy[sizeCopy - 1]; 54 | itemsCopy[sizeCopy - 1] = null; 55 | sizeCopy--; 56 | 57 | return item; 58 | } 59 | } 60 | 61 | // Construct an empty randomized queue 62 | public RandomizedQueue() 63 | { 64 | int defaultItemsSize = 2; 65 | 66 | items = (Item[]) new Object[defaultItemsSize]; 67 | size = 0; 68 | } 69 | 70 | // If the queue empty 71 | public boolean isEmpty() 72 | { 73 | return (size == 0); 74 | } 75 | 76 | // Return the number of items on the queue 77 | public int size() 78 | { 79 | return size; 80 | } 81 | 82 | // Add the item 83 | public void enqueue(Item item) 84 | { 85 | if (item == null) { 86 | throw new NullPointerException("Can't add empty element to queue"); 87 | } 88 | 89 | if (size == items.length) { 90 | resizeItems(items.length * 2); 91 | } 92 | 93 | items[size] = item; 94 | size++; 95 | } 96 | 97 | // Remove and return a random item 98 | public Item dequeue() 99 | { 100 | if (isEmpty()) { 101 | throw new NoSuchElementException("Queue is empty"); 102 | } 103 | 104 | int index = StdRandom.uniform(size); 105 | Item item = items[index]; 106 | 107 | // replace taken element with last one 108 | items[index] = items[size - 1]; 109 | items[size - 1] = null; 110 | size--; 111 | 112 | if (size > 0 && (size == items.length / 4)) { 113 | resizeItems(items.length / 2); 114 | } 115 | 116 | return item; 117 | } 118 | 119 | // Return (but do not remove) a random item 120 | public Item sample() 121 | { 122 | if (isEmpty()) { 123 | throw new NoSuchElementException("Queue is empty"); 124 | } 125 | 126 | int index = StdRandom.uniform(size); 127 | 128 | return items[index]; 129 | } 130 | 131 | // Return an independent iterator over items in random order 132 | public Iterator iterator() 133 | { 134 | return new RandomizedQueueIterator(); 135 | } 136 | 137 | // Resize items array 138 | private void resizeItems(int length) { 139 | Item[] newItems = (Item[]) new Object[length]; 140 | 141 | for (int i = 0; i < size; i++) { 142 | newItems[i] = items[i]; 143 | } 144 | 145 | items = newItems; 146 | } 147 | 148 | // Unit testing 149 | public static void main(String[] args) 150 | { 151 | RandomizedQueue queue = new RandomizedQueue<>(); 152 | 153 | String text = "A"; 154 | queue.enqueue(text); 155 | StdOut.println("enqueue() with: '" + text + "'"); 156 | 157 | text = "B"; 158 | queue.enqueue(text); 159 | StdOut.println("enqueue() with: '" + text + "'"); 160 | 161 | text = "C"; 162 | queue.enqueue(text); 163 | StdOut.println("enqueue() with: '" + text + "'"); 164 | 165 | text = "D"; 166 | queue.enqueue(text); 167 | StdOut.println("enqueue() with: '" + text + "'"); 168 | 169 | text = "E"; 170 | queue.enqueue(text); 171 | StdOut.println("enqueue() with: '" + text + "'"); 172 | 173 | queue.dequeue(); 174 | StdOut.println("dequeue()"); 175 | 176 | queue.sample(); 177 | StdOut.println("sample()"); 178 | 179 | text = "F"; 180 | queue.enqueue(text); 181 | StdOut.println("enqueue() with: '" + text + "'"); 182 | 183 | StdOut.println("Iterating queue..."); 184 | for (String item: queue) { 185 | StdOut.println("Iterate element: " + item); 186 | } 187 | } 188 | } -------------------------------------------------------------------------------- /week_3/BruteCollinearPoints.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.In; 2 | import edu.princeton.cs.algs4.StdDraw; 3 | import edu.princeton.cs.algs4.StdOut; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | 8 | /** 9 | * @author Dima Pasieka 10 | */ 11 | public class BruteCollinearPoints 12 | { 13 | // Line segments 14 | private LineSegment[] lineSegments; 15 | 16 | // Finds all line segments containing 4 points 17 | public BruteCollinearPoints(Point[] points) 18 | { 19 | if (isNullPoints(points)) { 20 | throw new NullPointerException("Points array can't be null or contain null values"); 21 | } 22 | 23 | // to avoid mutation 24 | Point[] pointsCopy = Arrays.copyOf(points, points.length); 25 | // first sort object to be able to compare with next value 26 | Arrays.sort(pointsCopy); 27 | 28 | if (isDuplicatedPoints(pointsCopy)) { 29 | throw new IllegalArgumentException("Points array can't contain duplicated points"); 30 | } 31 | 32 | int pointsLength = pointsCopy.length; 33 | ArrayList lineSegmentList = new ArrayList<>(); 34 | 35 | // add (-3, -2 ...) indent to avoid checking with same points 36 | for (int p = 0; p < (pointsLength - 3); p++) { 37 | for (int q = (p + 1); q < (pointsLength - 2); q++) { 38 | for (int r = (q + 1); r < (pointsLength - 1); r++) { 39 | // to avoid one loop if no need 40 | if (pointsCopy[p].slopeTo(pointsCopy[q]) != pointsCopy[p].slopeTo(pointsCopy[r])) { 41 | continue; 42 | } 43 | 44 | for (int s = (r + 1); s < pointsLength; s++) { 45 | if (pointsCopy[p].slopeTo(pointsCopy[q]) == pointsCopy[p].slopeTo(pointsCopy[s])) { 46 | lineSegmentList.add(new LineSegment(pointsCopy[p], pointsCopy[s])); 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | // transform found segments to array 54 | lineSegments = lineSegmentList.toArray(new LineSegment[lineSegmentList.size()]); 55 | } 56 | 57 | // The number of line segments 58 | public int numberOfSegments() 59 | { 60 | return lineSegments.length; 61 | } 62 | 63 | // The line segments 64 | public LineSegment[] segments() 65 | { 66 | return Arrays.copyOf(lineSegments, lineSegments.length); 67 | } 68 | 69 | // Check if there no null values 70 | private boolean isNullPoints(Point[] points) 71 | { 72 | if (points == null) { 73 | return true; 74 | } 75 | 76 | for (Point point: points) { 77 | if (point == null) { 78 | return true; 79 | } 80 | } 81 | 82 | return false; 83 | } 84 | 85 | // Check if there no duplicated points 86 | private boolean isDuplicatedPoints(Point[] points) 87 | { 88 | for (int i = 0; i < (points.length - 1); i++) { 89 | if (points[i].compareTo(points[i + 1]) == 0) { 90 | return true; 91 | } 92 | } 93 | 94 | return false; 95 | } 96 | 97 | // Test client 98 | public static void main(String[] args) { 99 | 100 | // read the n points from a file 101 | In in = new In(args[0]); 102 | int n = in.readInt(); 103 | Point[] points = new Point[n]; 104 | for (int i = 0; i < n; i++) { 105 | int x = in.readInt(); 106 | int y = in.readInt(); 107 | points[i] = new Point(x, y); 108 | } 109 | 110 | // draw the points 111 | StdDraw.enableDoubleBuffering(); 112 | StdDraw.setXscale(0, 32768); 113 | StdDraw.setYscale(0, 32768); 114 | for (Point p : points) { 115 | p.draw(); 116 | } 117 | StdDraw.show(); 118 | 119 | // print and draw the line segments 120 | BruteCollinearPoints collinear = new BruteCollinearPoints(points); 121 | for (LineSegment segment : collinear.segments()) { 122 | StdOut.println(segment); 123 | segment.draw(); 124 | } 125 | StdDraw.show(); 126 | } 127 | } -------------------------------------------------------------------------------- /week_3/FastCollinearPoints.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.In; 2 | import edu.princeton.cs.algs4.StdDraw; 3 | import edu.princeton.cs.algs4.StdOut; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.Collections; 8 | import java.util.HashMap; 9 | 10 | /** 11 | * @author Dima Pasieka 12 | */ 13 | public class FastCollinearPoints 14 | { 15 | // Line segments - array representation 16 | private LineSegment[] lineSegments; 17 | 18 | // Line segments - array list representation 19 | private ArrayList lineSegmentList = new ArrayList<>(); 20 | 21 | // To store starting points of each line segment 22 | private HashMap> foundStartingPoints = new HashMap<>(); 23 | 24 | // Finds all line segments containing 4 or more points 25 | public FastCollinearPoints(Point[] points) 26 | { 27 | if (isNullPoints(points)) { 28 | throw new NullPointerException("Points array can't be null or contain null values"); 29 | } 30 | 31 | // to avoid mutation + to be able to sort it separately from origin 32 | Point[] pointsCopy = Arrays.copyOf(points, points.length); 33 | // first sort object to be able to compare with next value 34 | Arrays.sort(pointsCopy); 35 | 36 | if (isDuplicatedPoints(pointsCopy)) { 37 | throw new IllegalArgumentException("Points array can't contain duplicated points"); 38 | } 39 | 40 | for (Point startingPoint: points) { 41 | // sort by slope from current point 42 | Arrays.sort(pointsCopy, startingPoint.slopeOrder()); 43 | 44 | // to store points that lie on the same line segment 45 | ArrayList slopePoints = new ArrayList<>(); 46 | double currentSlope = 0; 47 | double previousSlope = Double.NEGATIVE_INFINITY; 48 | 49 | for (int i = 1; i < pointsCopy.length; i++) { 50 | currentSlope = startingPoint.slopeTo(pointsCopy[i]); 51 | 52 | if (currentSlope == previousSlope) { 53 | slopePoints.add(pointsCopy[i]); 54 | } else { 55 | addSegment(slopePoints, startingPoint, previousSlope); 56 | 57 | slopePoints.clear(); 58 | // add first point of the line for next iterations 59 | slopePoints.add(pointsCopy[i]); 60 | } 61 | 62 | previousSlope = currentSlope; 63 | } 64 | 65 | addSegment(slopePoints, startingPoint, previousSlope); 66 | } 67 | 68 | // transform found segments to array 69 | lineSegments = lineSegmentList.toArray(new LineSegment[lineSegmentList.size()]); 70 | } 71 | 72 | // The number of line segments 73 | public int numberOfSegments() 74 | { 75 | return lineSegments.length; 76 | } 77 | 78 | // The line segments 79 | public LineSegment[] segments() 80 | { 81 | return Arrays.copyOf(lineSegments, lineSegments.length); 82 | } 83 | 84 | // Check if there no null values 85 | private boolean isNullPoints(Point[] points) 86 | { 87 | if (points == null) { 88 | return true; 89 | } 90 | 91 | for (Point point: points) { 92 | if (point == null) { 93 | return true; 94 | } 95 | } 96 | 97 | return false; 98 | } 99 | 100 | // Check if there no duplicated points 101 | private boolean isDuplicatedPoints(Point[] points) 102 | { 103 | for (int i = 0; i < (points.length - 1); i++) { 104 | if (points[i].compareTo(points[i + 1]) == 0) { 105 | return true; 106 | } 107 | } 108 | 109 | return false; 110 | } 111 | 112 | private void addSegment(ArrayList slopePoints, Point startingPoint, double slopeKey) 113 | { 114 | // we are looking only for 4+ lines that lie on the same line segment 115 | if (slopePoints.size() < 3) { 116 | return; 117 | } 118 | 119 | // starting point should be always included (as we started from it) 120 | slopePoints.add(startingPoint); 121 | 122 | // get starting points with such a slope key/value 123 | ArrayList startingPoints = foundStartingPoints.get(slopeKey); 124 | Collections.sort(slopePoints); 125 | 126 | Point startPoint = slopePoints.get(0); 127 | Point endPoint = slopePoints.get(slopePoints.size() - 1); 128 | 129 | if (startingPoints == null) { 130 | startingPoints = new ArrayList<>(); 131 | startingPoints.add(startPoint); 132 | foundStartingPoints.put(slopeKey, startingPoints); 133 | } else { 134 | // if the line with such starting point was already added 135 | for (Point point: startingPoints) { 136 | if (startPoint.compareTo(point) == 0) { 137 | return; 138 | } 139 | } 140 | startingPoints.add(startPoint); 141 | } 142 | 143 | lineSegmentList.add(new LineSegment(startPoint, endPoint)); 144 | } 145 | 146 | // Test client 147 | public static void main(String[] args) { 148 | 149 | // read the n points from a file 150 | In in = new In(args[0]); 151 | int n = in.readInt(); 152 | Point[] points = new Point[n]; 153 | for (int i = 0; i < n; i++) { 154 | int x = in.readInt(); 155 | int y = in.readInt(); 156 | points[i] = new Point(x, y); 157 | } 158 | 159 | // draw the points 160 | StdDraw.enableDoubleBuffering(); 161 | StdDraw.setXscale(0, 32768); 162 | StdDraw.setYscale(0, 32768); 163 | for (Point p : points) { 164 | p.draw(); 165 | } 166 | StdDraw.show(); 167 | 168 | // print and draw the line segments 169 | FastCollinearPoints collinear = new FastCollinearPoints(points); 170 | for (LineSegment segment : collinear.segments()) { 171 | StdOut.println(segment); 172 | segment.draw(); 173 | } 174 | StdDraw.show(); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /week_3/Point.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Compilation: javac Point.java 3 | * Execution: java Point 4 | * Dependencies: none 5 | * 6 | * An immutable data type for points in the plane. 7 | * For use on Coursera, Algorithms Part I programming assignment. 8 | * 9 | ******************************************************************************/ 10 | 11 | import edu.princeton.cs.algs4.StdDraw; 12 | 13 | import java.util.Comparator; 14 | 15 | public class Point implements Comparable { 16 | 17 | private final int x; // x-coordinate of this point 18 | private final int y; // y-coordinate of this point 19 | 20 | // Points comparator 21 | private class PointComparator implements Comparator 22 | { 23 | // compare two points 24 | public int compare(Point p1, Point p2) 25 | { 26 | double p1Slope = slopeTo(p1); 27 | double p2Slope = slopeTo(p2); 28 | 29 | if (p1Slope > p2Slope) { 30 | return 1; 31 | } 32 | 33 | if (p1Slope < p2Slope) { 34 | return -1; 35 | } 36 | 37 | // if equals 38 | return 0; 39 | } 40 | } 41 | 42 | /** 43 | * Initializes a new point. 44 | * 45 | * @param x the x-coordinate of the point 46 | * @param y the y-coordinate of the point 47 | */ 48 | public Point(int x, int y) { 49 | /* DO NOT MODIFY */ 50 | this.x = x; 51 | this.y = y; 52 | } 53 | 54 | /** 55 | * Draws this point to standard draw. 56 | */ 57 | public void draw() { 58 | /* DO NOT MODIFY */ 59 | StdDraw.point(x, y); 60 | } 61 | 62 | /** 63 | * Draws the line segment between this point and the specified point 64 | * to standard draw. 65 | * 66 | * @param that the other point 67 | */ 68 | public void drawTo(Point that) { 69 | /* DO NOT MODIFY */ 70 | StdDraw.line(this.x, this.y, that.x, that.y); 71 | } 72 | 73 | /** 74 | * Returns the slope between this point and the specified point. 75 | * Formally, if the two points are (x0, y0) and (x1, y1), then the slope 76 | * is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be 77 | * +0.0 if the line segment connecting the two points is horizontal; 78 | * Double.POSITIVE_INFINITY if the line segment is vertical; 79 | * and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal. 80 | * 81 | * @param that the other point 82 | * @return the slope between this point and the specified point 83 | */ 84 | public double slopeTo(Point that) { 85 | double ySlope = that.y - y; 86 | double xSlope = that.x - x; 87 | 88 | // (x0, y0) and (x1, y1) are equal 89 | if (ySlope == 0 && xSlope == 0) { 90 | return Double.NEGATIVE_INFINITY; 91 | } 92 | 93 | // line segment is horizontal 94 | if (ySlope == 0) { 95 | return +0.0; 96 | } 97 | 98 | // line segment is vertical 99 | if (xSlope == 0) { 100 | return Double.POSITIVE_INFINITY; 101 | } 102 | 103 | return (ySlope / xSlope); 104 | } 105 | 106 | /** 107 | * Compares two points by y-coordinate, breaking ties by x-coordinate. 108 | * Formally, the invoking point (x0, y0) is less than the argument point 109 | * (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1. 110 | * 111 | * @param that the other point 112 | * @return the value 0 if this point is equal to the argument 113 | * point (x0 = x1 and y0 = y1); 114 | * a negative integer if this point is less than the argument 115 | * point; and a positive integer if this point is greater than the 116 | * argument point 117 | */ 118 | public int compareTo(Point that) { 119 | // first check by 'y' 120 | if (y > that.y) { 121 | return 1; 122 | } 123 | 124 | if (y < that.y) { 125 | return -1; 126 | } 127 | 128 | // then check by 'x' 129 | if (x > that.x) { 130 | return 1; 131 | } 132 | 133 | if (x < that.x) { 134 | return -1; 135 | } 136 | 137 | // if equals 138 | return 0; 139 | } 140 | 141 | /** 142 | * Compares two points by the slope they make with this point. 143 | * The slope is defined as in the slopeTo() method. 144 | * 145 | * @return the Comparator that defines this ordering on points 146 | */ 147 | public Comparator slopeOrder() { 148 | return new PointComparator(); 149 | } 150 | 151 | 152 | /** 153 | * Returns a string representation of this point. 154 | * This method is provide for debugging; 155 | * your program should not rely on the format of the string representation. 156 | * 157 | * @return a string representation of this point 158 | */ 159 | public String toString() { 160 | /* DO NOT MODIFY */ 161 | return "(" + x + ", " + y + ")"; 162 | } 163 | 164 | /** 165 | * Unit tests the Point data type. 166 | */ 167 | public static void main(String[] args) { 168 | /* YOUR CODE HERE */ 169 | Point p1 = new Point(10, 20); 170 | Point p2 = new Point(20, 25); 171 | Point p3 = new Point(10, 20); 172 | 173 | Point p4 = new Point(10, 20); 174 | Point p5 = new Point(1, 20); 175 | Point p6 = new Point(5, 1); 176 | Point p7 = new Point(32128, 32128); 177 | Point p8 = new Point(32128, 32128); 178 | Point p9 = new Point(10, 123); 179 | 180 | Point p10 = new Point(10, 30); 181 | Point p11 = new Point(30, 20); 182 | 183 | assert (p1.compareTo(p2) < 0) : p1 + " " + p2; 184 | assert (p1.compareTo(p3) == 0) : p1 + " " + p3; 185 | assert (p2.compareTo(p3) > 0) : p2 + " " + p3; 186 | 187 | assert (p4.compareTo(p5) > 0) : p4 + " " + p5; 188 | assert (p5.compareTo(p4) < 0) : p5 + " " + p4; 189 | assert (p5.compareTo(p6) > 0) : p5 + " " + p6; 190 | assert (p4.compareTo(p6) > 0) : p4 + " " + p6; 191 | assert (p7.compareTo(p8) == 0) : p7 + " " + p8; 192 | 193 | 194 | assert (Double.compare(p7.slopeTo(p8), Double.NEGATIVE_INFINITY) == 0) : "Wrong value for degraded line"; 195 | assert (Double.compare(p4.slopeTo(p9), Double.POSITIVE_INFINITY) == 0) : "Wrong value for vertical line"; 196 | assert (Double.compare(p4.slopeTo(p5), +0.0) == 0) : "Wrong value for horizontal line"; 197 | assert (Double.compare(p1.slopeTo(p2), 0.5) == 0); 198 | assert (Double.compare(p10.slopeTo(p11), -0.5) == 0); 199 | 200 | 201 | assert (p4.slopeOrder().compare(p3, p5) < 0); 202 | assert (p4.slopeOrder().compare(p5, p3) > 0); 203 | assert (p1.slopeOrder().compare(p7, p8) == 0); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /week_4/Board.java: -------------------------------------------------------------------------------- 1 | import java.util.Stack; 2 | import java.util.Arrays; 3 | 4 | /** 5 | * @author Dima Pasieka 6 | */ 7 | public class Board 8 | { 9 | // Board size 10 | private int dimension; 11 | 12 | // Current board with blocks 13 | private int[][] blocksBoard; 14 | 15 | // Construct a board from an n-by-n array of blocks 16 | // (where blocks[i][j] = block in row i, column j) 17 | public Board(int[][] blocks) 18 | { 19 | dimension = blocks.length; 20 | blocksBoard = copyBlocks(blocks, dimension); 21 | } 22 | 23 | // Board dimension n 24 | public int dimension() 25 | { 26 | return dimension; 27 | } 28 | 29 | // Number of blocks out of place 30 | public int hamming() 31 | { 32 | int count = 0; 33 | 34 | for (int i = 0; i < dimension; i++) { 35 | for (int j = 0; j < dimension; j++) { 36 | 37 | if ((blocksBoard[i][j] != 0) && (blocksBoard[i][j] != expectedValueAtPosition(i, j))) { 38 | count++; 39 | } 40 | } 41 | } 42 | 43 | return count; 44 | } 45 | 46 | // Sum of Manhattan distances between blocks and goal 47 | public int manhattan() 48 | { 49 | int sum = 0; 50 | 51 | for (int i = 0; i < dimension; i++) { 52 | for (int j = 0; j < dimension; j++) { 53 | 54 | if ((blocksBoard[i][j] != 0) && (blocksBoard[i][j] != expectedValueAtPosition(i, j))) { 55 | int expectedI = (blocksBoard[i][j] - 1) / dimension; 56 | int expectedJ = (blocksBoard[i][j] - 1) % dimension; 57 | 58 | // sum vertical and horizontal difference in distance 59 | sum += Math.abs(i - expectedI) + Math.abs(j - expectedJ); 60 | } 61 | } 62 | } 63 | 64 | return sum; 65 | } 66 | 67 | // Is this board the goal board? 68 | public boolean isGoal() 69 | { 70 | // either hamming() or manhattan() can be used 71 | return (hamming() == 0); 72 | } 73 | 74 | // A board that is obtained by exchanging any pair of blocks 75 | public Board twin() 76 | { 77 | int[][] blocksCopy = copyBlocks(blocksBoard, dimension); 78 | 79 | for (int i = 0; i < dimension; i++) { 80 | for (int j = 0; j < dimension - 1; j++) { 81 | 82 | if ((blocksCopy[i][j] != 0) && (blocksCopy[i][j + 1] != 0)) { 83 | int toSwap = blocksCopy[i][j]; 84 | blocksCopy[i][j] = blocksCopy[i][j + 1]; 85 | blocksCopy[i][j + 1] = toSwap; 86 | 87 | return new Board(blocksCopy); 88 | } 89 | } 90 | } 91 | 92 | return null; 93 | } 94 | 95 | // Does this board equal y? 96 | public boolean equals(Object y) 97 | { 98 | if (y == null) { 99 | return false; 100 | } 101 | 102 | if (y == this) { 103 | return true; 104 | } 105 | 106 | if (y.getClass() != this.getClass()) { 107 | return false; 108 | } 109 | 110 | Board that = (Board) y; 111 | 112 | return Arrays.deepEquals(this.blocksBoard, that.blocksBoard); 113 | } 114 | 115 | // All neighboring boards 116 | public Iterable neighbors() 117 | { 118 | Stack boardStack = new Stack<>(); 119 | 120 | for (int i = 0; i < dimension; i++) { 121 | for (int j = 0; j < dimension; j++) { 122 | // we have found 0 block 123 | if (blocksBoard[i][j] == 0) { 124 | 125 | // if 0 block is not at top position 126 | if (i > 0) { 127 | int[][] blocksCopy = copyBlocks(blocksBoard, dimension); 128 | blocksCopy[i][j] = blocksBoard[i - 1][j]; 129 | blocksCopy[i - 1][j] = blocksBoard[i][j]; 130 | boardStack.push(new Board(blocksCopy)); 131 | } 132 | 133 | // if 0 block is not at left position 134 | if (j > 0) { 135 | int[][] blocksCopy = copyBlocks(blocksBoard, dimension); 136 | blocksCopy[i][j] = blocksBoard[i][j - 1]; 137 | blocksCopy[i][j - 1] = blocksBoard[i][j]; 138 | boardStack.push(new Board(blocksCopy)); 139 | } 140 | 141 | // if 0 block is not at bottom position 142 | if (i < dimension - 1) { 143 | int[][] blocksCopy = copyBlocks(blocksBoard, dimension); 144 | blocksCopy[i][j] = blocksBoard[i + 1][j]; 145 | blocksCopy[i + 1][j] = blocksBoard[i][j]; 146 | boardStack.push(new Board(blocksCopy)); 147 | } 148 | 149 | // if 0 block is not at right position 150 | if (j < dimension - 1) { 151 | int[][] blocksCopy = copyBlocks(blocksBoard, dimension); 152 | blocksCopy[i][j] = blocksBoard[i][j + 1]; 153 | blocksCopy[i][j + 1] = blocksBoard[i][j]; 154 | boardStack.push(new Board(blocksCopy)); 155 | } 156 | 157 | break; 158 | } 159 | } 160 | } 161 | 162 | return boardStack; 163 | } 164 | 165 | // String representation of this board (in the output format specified below) 166 | public String toString() 167 | { 168 | StringBuilder s = new StringBuilder(); 169 | s.append(dimension + "\n"); 170 | 171 | for (int i = 0; i < dimension; i++) { 172 | for (int j = 0; j < dimension; j++) { 173 | s.append(String.format("%2d ", blocksBoard[i][j])); 174 | } 175 | s.append("\n"); 176 | } 177 | 178 | return s.toString(); 179 | } 180 | 181 | // Copy blocks (2-dimension array) 182 | private int[][] copyBlocks(int[][] blocks, int dimensionSize) { 183 | int[][] result = new int[dimensionSize][dimensionSize]; 184 | 185 | for (int i = 0; i < dimensionSize; i++) { 186 | for (int j = 0; j < dimensionSize; j++) { 187 | result[i][j] = blocks[i][j]; 188 | } 189 | } 190 | 191 | return result; 192 | } 193 | 194 | // Get expected value that should be in provided position 195 | private int expectedValueAtPosition(int i, int j) 196 | { 197 | return ((i * dimension) + j + 1); 198 | } 199 | 200 | // Unit tests (not graded) 201 | public static void main(String[] args) 202 | { 203 | // To implement 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /week_4/Solver.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.In; 2 | import edu.princeton.cs.algs4.MinPQ; 3 | import edu.princeton.cs.algs4.Stack; 4 | import edu.princeton.cs.algs4.StdOut; 5 | 6 | /** 7 | * @author Dima Pasieka 8 | */ 9 | public class Solver { 10 | 11 | // If board is solvable 12 | private boolean isSolvable; 13 | 14 | // Number of moves to solve initial board 15 | private int solutionMoves; 16 | 17 | // Last Search board's state that solve the puzzle 18 | private SearchBoard solutionBoard; 19 | 20 | private class SearchBoard implements Comparable 21 | { 22 | // Current board 23 | private Board board; 24 | 25 | // Previous board 26 | private SearchBoard previousBoard; 27 | 28 | // Number of moves to get to this board 29 | private int moves; 30 | 31 | // Priority of the board 32 | private int priority; 33 | 34 | public SearchBoard(Board board, int moves, SearchBoard previousBoard) { 35 | this.board = board; 36 | this.moves = moves; 37 | this.previousBoard = previousBoard; 38 | 39 | priority = board.manhattan() + this.moves; 40 | } 41 | 42 | public int compareTo(SearchBoard that) { 43 | if (this.priority > that.priority) { 44 | return 1; 45 | } 46 | 47 | if (this.priority < that.priority) { 48 | return -1; 49 | } 50 | 51 | return 0; 52 | } 53 | } 54 | 55 | // Find a solution to the initial board (using the A* algorithm) 56 | public Solver(Board initial) 57 | { 58 | MinPQ searchBoardQueue = new MinPQ<>(); 59 | MinPQ searchTwinBoardQueue = new MinPQ<>(); 60 | 61 | searchBoardQueue.insert(new SearchBoard(initial, 0, null)); 62 | searchTwinBoardQueue.insert(new SearchBoard(initial.twin(), 0, null)); 63 | 64 | while (true) { 65 | SearchBoard minBoard = searchBoardQueue.delMin(); 66 | SearchBoard minTwinBoard = searchTwinBoardQueue.delMin(); 67 | 68 | if (minBoard.board.isGoal()) { 69 | solutionBoard = minBoard; 70 | isSolvable = true; 71 | solutionMoves = minBoard.moves; 72 | break; 73 | } 74 | 75 | if (minTwinBoard.board.isGoal()) { 76 | isSolvable = false; 77 | solutionMoves = -1; 78 | break; 79 | } 80 | 81 | enqueueNeighbors(minBoard, searchBoardQueue); 82 | enqueueNeighbors(minTwinBoard, searchTwinBoardQueue); 83 | } 84 | } 85 | 86 | // Is the initial board solvable? 87 | public boolean isSolvable() 88 | { 89 | return isSolvable; 90 | } 91 | 92 | // Min number of moves to solve initial board; -1 if unsolvable 93 | public int moves() 94 | { 95 | return solutionMoves; 96 | } 97 | 98 | // Sequence of boards in a shortest solution; null if unsolvable 99 | public Iterable solution() 100 | { 101 | if (!isSolvable) { 102 | return null; 103 | } 104 | 105 | Stack solution = new Stack<>(); 106 | 107 | SearchBoard board = solutionBoard; 108 | // go back from from the solution board 109 | while (board != null) { 110 | solution.push(board.board); 111 | board = board.previousBoard; 112 | } 113 | 114 | return solution; 115 | } 116 | 117 | // Enqueue up to 4 neighbors for provided board 118 | private void enqueueNeighbors(SearchBoard searchBoard, MinPQ queue) 119 | { 120 | for (Board nextBoard: searchBoard.board.neighbors()) { 121 | // if no previous boards or previous is not the same as current 122 | if ((searchBoard.previousBoard == null) || (!nextBoard.equals(searchBoard.previousBoard.board))) { 123 | queue.insert(new SearchBoard(nextBoard, searchBoard.moves + 1, searchBoard)); 124 | } 125 | } 126 | } 127 | 128 | // Solve a slider puzzle (given below) 129 | public static void main(String[] args) 130 | { 131 | // create initial board from file 132 | In in = new In(args[0]); 133 | int n = in.readInt(); 134 | int[][] blocks = new int[n][n]; 135 | for (int i = 0; i < n; i++) { 136 | for (int j = 0; j < n; j++) { 137 | blocks[i][j] = in.readInt(); 138 | } 139 | } 140 | Board initial = new Board(blocks); 141 | 142 | // solve the puzzle 143 | Solver solver = new Solver(initial); 144 | 145 | // print solution to standard output 146 | if (!solver.isSolvable()) { 147 | StdOut.println("No solution possible"); 148 | } else { 149 | StdOut.println("Minimum number of moves = " + solver.moves()); 150 | for (Board board : solver.solution()) { 151 | StdOut.println(board); 152 | } 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /week_5/KdTree.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.Queue; 2 | import edu.princeton.cs.algs4.RectHV; 3 | import edu.princeton.cs.algs4.Point2D; 4 | import edu.princeton.cs.algs4.StdDraw; 5 | 6 | /** 7 | * @author Dima Pasieka 8 | */ 9 | public class KdTree 10 | { 11 | // Vertical division 12 | private static final int VERTICAL = 1; 13 | 14 | // Horizontal division 15 | private static final int HORIZONTAL = 0; 16 | 17 | // Root element of the 2d-tree 18 | private Node root; 19 | 20 | // Size of the 2d-tree 21 | private int size; 22 | 23 | // Node representation in 2d-tree 24 | private static class Node { 25 | // The point 26 | private Point2D point; 27 | 28 | // Division/Color of the Node (red/vertical or black/horizontal) 29 | private int division; 30 | 31 | // The left/bottom subtree 32 | private Node left; 33 | 34 | // The right/top subtree 35 | private Node right; 36 | 37 | private Node(Point2D point) { 38 | this.point = point; 39 | left = null; 40 | right = null; 41 | } 42 | } 43 | 44 | // Construct an empty set of points 45 | public KdTree() 46 | { 47 | root = null; 48 | size = 0; 49 | } 50 | 51 | // If the set empty 52 | public boolean isEmpty() 53 | { 54 | return (root == null); 55 | } 56 | 57 | 58 | // Number of points in the set 59 | public int size() 60 | { 61 | return size; 62 | } 63 | 64 | 65 | // Add the point to the set (if it is not already in the set) 66 | public void insert(Point2D p) 67 | { 68 | if (p == null) { 69 | throw new NullPointerException("Can't add empty point"); 70 | } 71 | 72 | if (!contains(p)) { 73 | Node node = new Node(p); 74 | 75 | root = insertNode(node, root); 76 | size++; 77 | } 78 | } 79 | 80 | // If the set contain point p 81 | public boolean contains(Point2D p) 82 | { 83 | if (p == null) { 84 | throw new NullPointerException("Can't check empty point"); 85 | } 86 | 87 | Node current = root; 88 | 89 | while (true) { 90 | if (current == null) { 91 | return false; 92 | } 93 | 94 | if (current.point.equals(p)) { 95 | return true; 96 | } 97 | 98 | if (isLessThanPoint(p, current.point, current.division)) { 99 | current = current.left; 100 | } else { 101 | current = current.right; 102 | } 103 | } 104 | } 105 | 106 | // Draw all points to standard draw 107 | public void draw() 108 | { 109 | drawNode(root, 0, 1, 0, 1); 110 | } 111 | 112 | // All points that are inside the rectangle 113 | public Iterable range(RectHV rect) 114 | { 115 | if (rect == null) { 116 | throw new NullPointerException("Can't use empty rectangle"); 117 | } 118 | 119 | Queue range = new Queue<>(); 120 | 121 | rangeNode(root, rect, range); 122 | 123 | return range; 124 | } 125 | 126 | // A nearest neighbor in the set to point p; null if the set is empty 127 | public Point2D nearest(Point2D p) 128 | { 129 | if (p == null) { 130 | throw new NullPointerException("Can't check empty point"); 131 | } 132 | 133 | if (isEmpty()) { 134 | return null; 135 | } 136 | 137 | return nearestNode(p, root, root.point); 138 | } 139 | 140 | // Insert a node for specific parent node 141 | private Node insertNode(Node node, Node parentNode) { 142 | if (parentNode == null) { 143 | node.division = VERTICAL; 144 | return node; 145 | } 146 | 147 | if (isLessThanPoint(node.point, parentNode.point, parentNode.division)) { 148 | if (parentNode.left == null) { 149 | node.division = getDivisionByNode(parentNode); 150 | parentNode.left = node; 151 | } else { 152 | parentNode.left = insertNode(node, parentNode.left); 153 | } 154 | } else { 155 | if (parentNode.right == null) { 156 | node.division = getDivisionByNode(parentNode); 157 | parentNode.right = node; 158 | } else { 159 | parentNode.right = insertNode(node, parentNode.right); 160 | } 161 | } 162 | 163 | return parentNode; 164 | } 165 | 166 | private void drawNode(Node node, double minX, double maxX, double minY, double maxY) 167 | { 168 | if (node == null) { 169 | return; 170 | } 171 | 172 | drawPoint(node.point); 173 | drawDivision(node, minX, maxX, minY, maxY); 174 | if (node.division == VERTICAL) { 175 | drawNode(node.left, minX, node.point.x(), minY, maxY); 176 | drawNode(node.right, node.point.x(), maxX, minY, maxY); 177 | } else { 178 | drawNode(node.left, minX, maxX, minY, node.point.y()); 179 | drawNode(node.right, minX, maxX, node.point.y(), maxY); 180 | } 181 | } 182 | 183 | // Draw a point 184 | private void drawPoint(Point2D point) 185 | { 186 | StdDraw.setPenRadius(0.01); 187 | StdDraw.setPenColor(StdDraw.BLACK); 188 | 189 | point.draw(); 190 | } 191 | 192 | // Draw node division 193 | private void drawDivision(Node node, double minX, double maxX, double minY, double maxY) 194 | { 195 | StdDraw.setPenRadius(); 196 | 197 | if (node.division == VERTICAL) { 198 | StdDraw.setPenColor(StdDraw.RED); 199 | StdDraw.line(node.point.x(), minY, node.point.x(), maxY); 200 | } else { 201 | StdDraw.setPenColor(StdDraw.BLUE); 202 | StdDraw.line(minX, node.point.y(), maxX, node.point.y()); 203 | } 204 | } 205 | 206 | // Check range points inside of the node 207 | private void rangeNode(Node node, RectHV rect, Queue range) 208 | { 209 | if (node == null) { 210 | return; 211 | } 212 | 213 | if (rect.contains(node.point)) { 214 | range.enqueue(node.point); 215 | } 216 | 217 | if (node.division == VERTICAL) { 218 | if (node.point.x() > rect.xmin()) { 219 | rangeNode(node.left, rect, range); 220 | } 221 | 222 | if (node.point.x() <= rect.xmax()) { 223 | rangeNode(node.right, rect, range); 224 | } 225 | } else { 226 | if (node.point.y() > rect.ymin()) { 227 | rangeNode(node.left, rect, range); 228 | } 229 | 230 | if (node.point.y() <= rect.ymax()) { 231 | rangeNode(node.right, rect, range); 232 | } 233 | } 234 | } 235 | 236 | private Point2D nearestNode(Point2D point, Node node, Point2D nearest) 237 | { 238 | if (node == null) { 239 | return nearest; 240 | } 241 | 242 | if (node.point.distanceTo(point) < nearest.distanceTo(point)) { 243 | nearest = node.point; 244 | } 245 | 246 | Point2D nearestPossibleFromAnotherNode; 247 | Node morePrioritizedNode; 248 | Node lessPrioritizedNode; 249 | 250 | if (node.division == VERTICAL) { 251 | nearestPossibleFromAnotherNode = new Point2D(node.point.x(), point.y()); 252 | 253 | if (point.x() < node.point.x()) { 254 | morePrioritizedNode = node.left; 255 | lessPrioritizedNode = node.right; 256 | } else { 257 | morePrioritizedNode = node.right; 258 | lessPrioritizedNode = node.left; 259 | } 260 | } else { 261 | nearestPossibleFromAnotherNode = new Point2D(point.x(), node.point.y()); 262 | 263 | if (point.y() < node.point.y()) { 264 | morePrioritizedNode = node.left; 265 | lessPrioritizedNode = node.right; 266 | } else { 267 | morePrioritizedNode = node.right; 268 | lessPrioritizedNode = node.left; 269 | } 270 | } 271 | 272 | nearest = nearestNode(point, morePrioritizedNode, nearest); 273 | 274 | if (nearestPossibleFromAnotherNode.distanceTo(point) < nearest.distanceTo(point)) { 275 | nearest = nearestNode(point, lessPrioritizedNode, nearest); 276 | } 277 | 278 | return nearest; 279 | } 280 | 281 | // Get opposite direction to node 282 | private int getDivisionByNode(Node node) 283 | { 284 | if (node.division == VERTICAL) { 285 | return HORIZONTAL; 286 | } 287 | 288 | return VERTICAL; 289 | } 290 | 291 | // Check if point less than another point (depends on division) 292 | private boolean isLessThanPoint(Point2D nodePoint, Point2D rootPoint, int division) 293 | { 294 | if (division == VERTICAL) { 295 | return nodePoint.x() < rootPoint.x(); 296 | } 297 | 298 | return nodePoint.y() < rootPoint.y(); 299 | } 300 | 301 | // Unit testing of the methods (optional) 302 | public static void main(String[] args) 303 | { 304 | // To implement 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /week_5/PointSET.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.SET; 2 | import edu.princeton.cs.algs4.Queue; 3 | import edu.princeton.cs.algs4.RectHV; 4 | import edu.princeton.cs.algs4.Point2D; 5 | 6 | /** 7 | * @author Dima Pasieka 8 | */ 9 | public class PointSET 10 | { 11 | // Set of points in BST 12 | private SET points; 13 | 14 | // Construct an empty set of points 15 | public PointSET() 16 | { 17 | points = new SET<>(); 18 | } 19 | 20 | // If the set empty 21 | public boolean isEmpty() 22 | { 23 | return points.isEmpty(); 24 | } 25 | 26 | 27 | // Number of points in the set 28 | public int size() 29 | { 30 | return points.size(); 31 | } 32 | 33 | 34 | // Add the point to the set (if it is not already in the set) 35 | public void insert(Point2D p) 36 | { 37 | if (p == null) { 38 | throw new NullPointerException("Can't add empty point"); 39 | } 40 | 41 | points.add(p); 42 | } 43 | 44 | // If the set contain point p 45 | public boolean contains(Point2D p) 46 | { 47 | if (p == null) { 48 | throw new NullPointerException("Can't check empty point"); 49 | } 50 | 51 | return points.contains(p); 52 | } 53 | 54 | // Draw all points to standard draw 55 | public void draw() 56 | { 57 | for (Point2D point: points) { 58 | point.draw(); 59 | } 60 | } 61 | 62 | // All points that are inside the rectangle 63 | public Iterable range(RectHV rect) 64 | { 65 | if (rect == null) { 66 | throw new NullPointerException("Can't use empty rectangle"); 67 | } 68 | 69 | Queue range = new Queue<>(); 70 | 71 | for (Point2D point: points) { 72 | if (rect.contains(point)) { 73 | range.enqueue(point); 74 | } 75 | } 76 | 77 | return range; 78 | } 79 | 80 | // A nearest neighbor in the set to point p; null if the set is empty 81 | public Point2D nearest(Point2D p) 82 | { 83 | if (p == null) { 84 | throw new NullPointerException("Can't check empty point"); 85 | } 86 | 87 | if (isEmpty()) { 88 | return null; 89 | } 90 | 91 | Point2D nearest = null; 92 | 93 | for (Point2D point: points) { 94 | if (nearest == null || (p.distanceTo(point) < p.distanceTo(nearest))) { 95 | nearest = point; 96 | } 97 | } 98 | 99 | return nearest; 100 | } 101 | 102 | // Unit testing of the methods (optional) 103 | public static void main(String[] args) 104 | { 105 | // To implement 106 | } 107 | } 108 | --------------------------------------------------------------------------------