├── Week-1 ├── settings.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── build.gradle ├── src │ ├── test │ │ └── java │ │ │ ├── PercolationTest.java │ │ │ └── PercolationStatsTest.java │ └── main │ │ └── java │ │ ├── PercolationStats.java │ │ └── Percolation.java ├── gradlew.bat ├── gradlew └── README.md ├── README.md ├── .gitignore ├── Week-2 └── Programming-Assignment │ ├── Permutation.java │ ├── RandomizedQueue.java │ ├── README.md │ └── Deque.java ├── Week-3 ├── LineSegment.java ├── BruteCollinearPoints.java ├── FastCollinearPoints.java └── Point.java └── Week-4 ├── Solver.java └── Board.java /Week-1/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'untitled' 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Coursera-Algorithms-Part-1 2 | Repository containing my solutions to the programming assignments of the course "Algorithms, Part I" from Princeton University, oferred in Coursera 3 | -------------------------------------------------------------------------------- /Week-1/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /Week-1/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | version '1.0-SNAPSHOT' 6 | 7 | sourceCompatibility = 1.8 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | implementation files('lib/algs4.jar') 15 | testImplementation('org.junit.jupiter:junit-jupiter:5.5.1') 16 | } 17 | 18 | test { 19 | useJUnitPlatform() 20 | testLogging { 21 | events "passed", "skipped", "failed" 22 | } 23 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Gradle cache and build 5 | .gradle/ 6 | build/ 7 | 8 | # Intellij files 9 | .idea/ 10 | 11 | # Log file 12 | *.log 13 | 14 | # BlueJ files 15 | *.ctxt 16 | 17 | # Mobile Tools for Java (J2ME) 18 | .mtj.tmp/ 19 | 20 | # Package Files # 21 | *.jar 22 | *.war 23 | *.nar 24 | *.ear 25 | *.zip 26 | *.tar.gz 27 | *.rar 28 | 29 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 30 | hs_err_pid* 31 | -------------------------------------------------------------------------------- /Week-2/Programming-Assignment/Permutation.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdIn; 2 | import edu.princeton.cs.algs4.StdOut; 3 | 4 | public class Permutation { 5 | /** 6 | * Write a client program Permutation.java that takes an integer k as a 7 | * command-line argument; reads in a sequence of strings from standard input 8 | * using StdIn.readString(); and prints exactly k of them, uniformly at random. 9 | * Print each item from the sequence at most once. 10 | */ 11 | public static void main(String[] args) { 12 | int k = Integer.parseInt(args[0]); 13 | RandomizedQueue randQueue = new RandomizedQueue(); 14 | 15 | while (!StdIn.isEmpty()) { 16 | String s = StdIn.readString(); 17 | randQueue.enqueue(s); 18 | } 19 | 20 | for (int i = 0; i < k; i++) { 21 | StdOut.println(randQueue.dequeue()); 22 | } 23 | 24 | } 25 | 26 | 27 | } -------------------------------------------------------------------------------- /Week-1/src/test/java/PercolationTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.jupiter.api.Test; 2 | import static org.junit.jupiter.api.Assertions.assertEquals; 3 | import static org.junit.jupiter.api.Assertions.assertFalse; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | public class PercolationTest { 7 | 8 | @Test 9 | void testIsOpened() { 10 | Percolation percolation = new Percolation(3); 11 | assertFalse(percolation.isOpen(1, 2)); 12 | } 13 | 14 | @Test 15 | void testOpen() { 16 | Percolation percolation = new Percolation(3); 17 | percolation.open(1, 2); 18 | assertTrue(percolation.isOpen(1, 2)); 19 | } 20 | 21 | @Test 22 | void testNumberOfOpenSites() { 23 | Percolation percolation = new Percolation(3); 24 | percolation.open(1, 2); 25 | percolation.open(2, 1); 26 | assertEquals(2, percolation.numberOfOpenSites()); 27 | } 28 | 29 | @Test 30 | void testOpenAnOpenedSite() { 31 | Percolation percolation = new Percolation(3); 32 | percolation.open(1, 2); 33 | percolation.open(1, 2); 34 | assertEquals(1, percolation.numberOfOpenSites()); 35 | } 36 | 37 | @Test 38 | void testIsFull() { 39 | Percolation percolation = new Percolation(3); 40 | percolation.open(1, 1); 41 | assertTrue(percolation.isFull(1, 1)); 42 | } 43 | 44 | @Test 45 | void testPercolates() { 46 | Percolation percolation = new Percolation(3); 47 | percolation.open(1, 1); 48 | percolation.open(2, 1); 49 | percolation.open(3, 1); 50 | assertTrue(percolation.percolates()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Week-1/src/test/java/PercolationStatsTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.jupiter.api.Test; 2 | import static org.junit.jupiter.api.Assertions.assertEquals; 3 | import static org.junit.jupiter.api.Assertions.assertFalse; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | import edu.princeton.cs.algs4.StdStats; 6 | 7 | public class PercolationStatsTest { 8 | @Test 9 | void testMean() { 10 | int gridSide = 10; 11 | int trials = 3; 12 | PercolationStats stats = new PercolationStats(gridSide, trials); 13 | stats.proportionOfSitesOpenedPerTrial = new double[] {1, 0.5, 0.75}; 14 | 15 | assertEquals(stats.mean(), 0.75); 16 | } 17 | 18 | @Test 19 | void testStdDev() { 20 | int gridSide = 10; 21 | int trials = 3; 22 | PercolationStats stats = new PercolationStats(gridSide, trials); 23 | stats.proportionOfSitesOpenedPerTrial = new double[] {0.5, 0, -0.5}; 24 | 25 | assertEquals(stats.stddev(), 0.5); 26 | } 27 | 28 | @Test 29 | void testConfidenceLo() { 30 | int gridSide = 10; 31 | int trials = 9; 32 | PercolationStats stats = new PercolationStats(gridSide, trials); 33 | stats.proportionOfSitesOpenedPerTrial = new double[] {1, 0, 0, 0, 0, 0, 0, 0, -1}; 34 | 35 | double mean = 0; 36 | double stddev = 0.5; 37 | assertEquals(stats.confidenceLo(), mean - 1.96*stddev/Math.sqrt(trials)); 38 | } 39 | 40 | @Test 41 | void testConfidenceHi() { 42 | int gridSide = 10; 43 | int trials = 9; 44 | PercolationStats stats = new PercolationStats(gridSide, trials); 45 | stats.proportionOfSitesOpenedPerTrial = new double[] {1, 0, 0, 0, 0, 0, 0, 0, -1}; 46 | 47 | double mean = 0; 48 | double stddev = 0.5; 49 | assertEquals(stats.confidenceHi(), mean + 1.96*stddev/Math.sqrt(trials)); 50 | } 51 | } -------------------------------------------------------------------------------- /Week-3/LineSegment.java: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Compilation: javac LineSegment.java 3 | * Execution: none 4 | * Dependencies: Point.java 5 | * 6 | * An immutable data type for Line segments in the plane. 7 | * For use on Coursera, Algorithms Part I programming assignment. 8 | * 9 | * DO NOT MODIFY THIS CODE. 10 | * 11 | *************************************************************************/ 12 | 13 | public class LineSegment { 14 | private final Point p; // one endpoint of this line segment 15 | private final Point q; // the other endpoint of this line segment 16 | 17 | /** 18 | * Initializes a new line segment. 19 | * 20 | * @param p one endpoint 21 | * @param q the other endpoint 22 | * @throws NullPointerException if either p or q 23 | * is null 24 | */ 25 | public LineSegment(Point p, Point q) { 26 | if (p == null || q == null) { 27 | throw new NullPointerException("argument is null"); 28 | } 29 | this.p = p; 30 | this.q = q; 31 | } 32 | 33 | 34 | /** 35 | * Draws this line segment to standard draw. 36 | */ 37 | public void draw() { 38 | p.drawTo(q); 39 | } 40 | 41 | /** 42 | * Returns a string representation of this line segment 43 | * This method is provide for debugging; 44 | * your program should not rely on the format of the string representation. 45 | * 46 | * @return a string representation of this line segment 47 | */ 48 | public String toString() { 49 | return p + " -> " + q; 50 | } 51 | 52 | /** 53 | * Throws an exception if called. The hashCode() method is not supported because 54 | * hashing has not yet been introduced in this course. Moreover, hashing does not 55 | * typically lead to good *worst-case* performance guarantees, as required on this 56 | * assignment. 57 | * 58 | * @throws UnsupportedOperationException if called 59 | */ 60 | public int hashCode() { 61 | throw new UnsupportedOperationException(); 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Week-1/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /Week-3/BruteCollinearPoints.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import edu.princeton.cs.algs4.In; 3 | import edu.princeton.cs.algs4.StdOut; 4 | 5 | public class BruteCollinearPoints { 6 | 7 | private int numSegments; 8 | private LineSegment[] lineSegments; 9 | 10 | public BruteCollinearPoints(Point[] points) { 11 | validateInput(points); 12 | 13 | numSegments = 0; 14 | lineSegments = new LineSegment[points.length]; 15 | 16 | for (int i = 0; i < points.length; i++) 17 | for (int j = i+1; j < points.length; j++) 18 | for (int k = j+1; k < points.length; k++) { 19 | Point p = points[i]; 20 | Point q = points[j]; 21 | Point r = points[k]; 22 | 23 | if (areCollinear(p, q, r)) 24 | // If they are collinear, we look for a forth one 25 | for (int t = k+1; t < points.length; t++) { 26 | Point s = points[t]; 27 | if (areCollinear(p, q, s)) addSegment(p, q, r, s); 28 | } 29 | } 30 | 31 | } 32 | public int numberOfSegments() { return numSegments; } 33 | public LineSegment[] segments() { 34 | return Arrays.copyOfRange(lineSegments, 0, numberOfSegments()); 35 | } 36 | 37 | private void addSegment(Point p, Point q, Point r, Point s) { 38 | 39 | // Finding the most separated set of points 40 | Point[] collinearPoints = {p, q, r, s}; 41 | Arrays.sort(collinearPoints); 42 | Point minPoint = collinearPoints[0]; 43 | Point maxPoint = collinearPoints[3]; 44 | 45 | lineSegments[numSegments++] = new LineSegment(minPoint, maxPoint); 46 | } 47 | 48 | public static void main(String[] args) { 49 | // read the n points from a file 50 | In in = new In(args[0]); 51 | int n = in.readInt(); 52 | Point[] points = new Point[n]; 53 | for (int i = 0; i < n; i++) { 54 | int x = in.readInt(); 55 | int y = in.readInt(); 56 | points[i] = new Point(x, y); 57 | } 58 | 59 | // print and draw the line segments 60 | BruteCollinearPoints collinear = new BruteCollinearPoints(points); 61 | for (LineSegment segment : collinear.segments()) { 62 | StdOut.println(segment); 63 | } 64 | } 65 | 66 | private void validateInput(Point[] points) { 67 | if (points == null) throw new IllegalArgumentException("The input argument is null"); 68 | for (Point point : points) if (point == null) throw new IllegalArgumentException("The input contains null points"); 69 | 70 | for (int i = 0; i < points.length; i++) 71 | for (int j = i+1; j < points.length; j++) 72 | if (points[i].compareTo(points[j]) == 0) 73 | throw new IllegalArgumentException("The input contains repeated points"); 74 | 75 | } 76 | 77 | private boolean areCollinear(Point p1, Point p2, Point p3) { 78 | return (Double.compare(p1.slopeTo(p2), p1.slopeTo(p3)) == 0); 79 | } 80 | } -------------------------------------------------------------------------------- /Week-1/src/main/java/PercolationStats.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdIn; 2 | import edu.princeton.cs.algs4.StdOut; 3 | import edu.princeton.cs.algs4.StdRandom; 4 | import edu.princeton.cs.algs4.StdStats; 5 | 6 | public class PercolationStats { 7 | 8 | private static final double CONFIDENCE_95 = 1.96; 9 | private final int trials; 10 | private final double mean, stddev; 11 | 12 | /** 13 | * Instantiates several Percolation objects and, for each of them, opens sites randomly 14 | * until the system percolates. When it does, it stores the result in order to enable the 15 | * obtention of stats from it 16 | * 17 | * @param n Size of the Percolation objects 18 | * @param trials Number of times that we'll repeat the experiment 19 | * @throws IllegalArgumentException If either n or trials are lower than 1 20 | */ 21 | public PercolationStats(int n, int trials) { 22 | if (n <= 0 || trials <= 0) throw new IllegalArgumentException("ERROR"); 23 | 24 | this.trials = trials; 25 | 26 | double[] proportionOfSitesOpenedPerTrial = new double[trials]; 27 | 28 | double totalSites = n * n; 29 | 30 | for (int trial = 0; trial < trials; trial++) { 31 | Percolation percolation = new Percolation(n); 32 | 33 | while (true) { 34 | int randomRow = StdRandom.uniform(1, n + 1); 35 | int randomCol = StdRandom.uniform(1, n + 1); 36 | percolation.open(randomRow, randomCol); 37 | 38 | if (percolation.percolates()) break; 39 | } 40 | 41 | proportionOfSitesOpenedPerTrial[trial] = percolation.numberOfOpenSites() / totalSites; 42 | } 43 | 44 | this.mean = StdStats.mean(proportionOfSitesOpenedPerTrial); 45 | this.stddev = StdStats.stddev(proportionOfSitesOpenedPerTrial); 46 | } 47 | 48 | /** 49 | * Sample mean among the trials of the percolation threshold 50 | * 51 | * @return Sample mean among the trials of the percolation threshold 52 | */ 53 | public double mean() { 54 | // This can be more explicit with memoization 55 | return this.mean; 56 | } 57 | 58 | /** 59 | * Sample standard deviation of percolation threshold 60 | * 61 | * @return Sample standard deviation of percolation threshold 62 | */ 63 | public double stddev() { 64 | // This can be more explicit with memoization 65 | return this.stddev; 66 | } 67 | 68 | /** 69 | * Low endpoint of 95% confidence interval 70 | * 71 | * @return Low endpoint of 95% confidence interval 72 | */ 73 | public double confidenceLo() { 74 | return mean() - CONFIDENCE_95*stddev()/Math.sqrt(trials); 75 | } 76 | 77 | /** 78 | * High endpoint of 95% confidence interval 79 | * 80 | * @return High endpoint of 95% confidence interval 81 | */ 82 | public double confidenceHi() { 83 | return mean() + CONFIDENCE_95*stddev()/Math.sqrt(trials); 84 | } 85 | 86 | public static void main(String[] args) { 87 | int n = Integer.parseInt(StdIn.readString()); 88 | int trials = Integer.parseInt(StdIn.readString()); 89 | 90 | PercolationStats stats = new PercolationStats(n, trials); 91 | StdOut.print("mean = " + stats.mean()); 92 | StdOut.print("stddev = " + stats.stddev()); 93 | StdOut.print("95% confidence interval = [" + stats.confidenceLo() + ", " + stats.confidenceHi() + "]"); 94 | } 95 | } -------------------------------------------------------------------------------- /Week-2/Programming-Assignment/RandomizedQueue.java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import edu.princeton.cs.algs4.StdRandom; 3 | 4 | public class RandomizedQueue implements Iterable { 5 | 6 | private int arraySize; 7 | private Item[] elements; 8 | private int numElements; 9 | 10 | public RandomizedQueue() { 11 | this.arraySize = 1; 12 | this.elements = (Item[]) new Object[arraySize]; 13 | this.numElements = 0; 14 | } 15 | 16 | /** 17 | * Returns true if there aren't any elements in the queue 18 | * 19 | * @return true if the queue is empty, false otherwise 20 | */ 21 | public boolean isEmpty() { 22 | return size() == 0; 23 | } 24 | 25 | /** 26 | * Number of elements in the queue 27 | * 28 | * @return integer - Number of elements currently in the queue 29 | */ 30 | public int size() { 31 | return numElements; 32 | } 33 | 34 | /** 35 | * Puts an item in the queue 36 | * 37 | * @param item Element to add to the queue 38 | */ 39 | public void enqueue(Item item) { 40 | validateItem(item); 41 | 42 | if (isFull()) duplicateSize(); 43 | 44 | elements[size()] = item; 45 | numElements++; 46 | } 47 | 48 | /** 49 | * Removes a random element from the queue and returns it 50 | * 51 | * @return Item Element extracted from the queue 52 | */ 53 | public Item dequeue() { 54 | validateNotEmpty(); 55 | 56 | Item itemToReturn = removeRandomItemAndReorder(); 57 | 58 | if (isAlmostEmpty()) halfSize(); 59 | 60 | return itemToReturn; 61 | } 62 | 63 | /** 64 | * Returns a random element from the queue without removing it 65 | * 66 | * @return Item - Random element from the queue 67 | */ 68 | public Item sample() { 69 | validateNotEmpty(); 70 | 71 | return elements[randomIndex()]; 72 | } 73 | 74 | public Iterator iterator() { 75 | return new RandomizedQueueIterator(); 76 | } 77 | 78 | public static void main(String[] args) { 79 | // Empty method 80 | } 81 | 82 | private int randomIndex() { 83 | return StdRandom.uniform(size()); 84 | } 85 | 86 | private void validateItem(Item item) { 87 | if (item == null) throw new IllegalArgumentException("The item can't be null"); 88 | } 89 | 90 | private void validateNotEmpty() { 91 | if (isEmpty()) throw new java.util.NoSuchElementException("The queue is empty"); 92 | } 93 | 94 | private Item removeRandomItemAndReorder() { 95 | int index = randomIndex(); 96 | int lastIndex = size() - 1; 97 | 98 | Item item = elements[index]; 99 | elements[index] = elements[lastIndex]; 100 | elements[lastIndex] = null; 101 | 102 | numElements--; 103 | 104 | return item; 105 | } 106 | 107 | private boolean isFull() { 108 | return size() == arraySize; 109 | } 110 | 111 | private boolean isAlmostEmpty() { 112 | return size() <= arraySize / 4; 113 | } 114 | 115 | private void duplicateSize() { 116 | resize(2 * arraySize); 117 | } 118 | 119 | private void halfSize() { 120 | resize(arraySize / 2); 121 | } 122 | 123 | private void resize(int capacity) { 124 | if (isEmpty()) { return; } 125 | 126 | arraySize = capacity; 127 | Item[] copy = (Item[]) new Object[arraySize]; 128 | 129 | int maxSize = size(); 130 | for (int i = 0; i < maxSize; i++) copy[i] = elements[i]; 131 | 132 | elements = copy; 133 | } 134 | 135 | private class RandomizedQueueIterator implements Iterator { 136 | 137 | private final RandomizedQueue copy; 138 | 139 | RandomizedQueueIterator() { 140 | copy = new RandomizedQueue(); 141 | 142 | for (int i = 0; i < size(); i++) { 143 | copy.enqueue(elements[i]); 144 | } 145 | } 146 | 147 | public Item next() { 148 | if (!hasNext()) throw new java.util.NoSuchElementException("There are no more elements"); 149 | 150 | return copy.dequeue(); 151 | } 152 | 153 | public boolean hasNext() { 154 | return copy.size() > 0; 155 | } 156 | 157 | public void remove() { 158 | throw new UnsupportedOperationException("This operation is not supported by this class"); 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /Week-4/Solver.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | 4 | import edu.princeton.cs.algs4.In; 5 | import edu.princeton.cs.algs4.StdOut; 6 | import edu.princeton.cs.algs4.MinPQ; 7 | import edu.princeton.cs.algs4.Stack; 8 | 9 | public class Solver { 10 | 11 | private BoardNode solutionBoard; 12 | private boolean solvable = true; 13 | 14 | // find a solution to the initial board (using the A* algorithm) 15 | public Solver(Board initial) { 16 | if (initial == null) throw new IllegalArgumentException("The initial board can't be null"); 17 | 18 | // Check if the initial board is solvable 19 | MinPQ tree = new MinPQ(); 20 | BoardNode initialNode = new BoardNode(initial, null, 0); 21 | tree.insert(initialNode); 22 | 23 | MinPQ twinTree = new MinPQ(); 24 | BoardNode initialTwinNode = new BoardNode(initial.twin(), null, 0); 25 | twinTree.insert(initialTwinNode); 26 | 27 | while (solutionBoard == null && isSolvable()) { 28 | BoardNode currentNode = tree.delMin(); 29 | if (currentNode.board.isGoal()) { 30 | solutionBoard = currentNode; 31 | return; 32 | } 33 | 34 | for (Board neighbor : currentNode.board.neighbors()) { 35 | if (currentNode.previous != null && neighbor.equals(currentNode.previous.board)) 36 | continue; 37 | else 38 | tree.insert(new BoardNode(neighbor, currentNode, currentNode.moves + 1)); 39 | } 40 | 41 | BoardNode twinNode = twinTree.delMin(); 42 | if (twinNode.board.isGoal()) { 43 | solvable = false; 44 | return; 45 | } 46 | for (Board twinNeighbor : twinNode.board.neighbors()) 47 | if (twinNode.previous != null && twinNeighbor.equals(twinNode.previous.board)) 48 | continue; 49 | else 50 | twinTree.insert(new BoardNode(twinNeighbor, twinNode, twinNode.moves + 1)); 51 | } 52 | } 53 | 54 | // is the initial board solvable? 55 | public boolean isSolvable() { 56 | return solvable; 57 | } 58 | 59 | // min number of moves to solve the initial board 60 | public int moves() { 61 | if (!isSolvable()) return -1; 62 | 63 | return solutionBoard.moves; 64 | } 65 | 66 | // sequence of boards in a shortest solution 67 | public Iterable solution() { 68 | if (!isSolvable()) return null; 69 | 70 | Board[] pathToSolution = new Board[moves() + 1]; 71 | int i = moves(); 72 | BoardNode currentNode = solutionBoard; 73 | 74 | while (i >= 0) { 75 | pathToSolution[i--] = currentNode.board; 76 | currentNode = currentNode.previous; 77 | } 78 | 79 | return new ArrayList<>(Arrays.asList(pathToSolution)); 80 | } 81 | 82 | public static void main(String[] args) { 83 | // create initial board from file 84 | In in = new In(args[0]); 85 | int n = in.readInt(); 86 | int[][] tiles = new int[n][n]; 87 | for (int i = 0; i < n; i++) 88 | for (int j = 0; j < n; j++) 89 | tiles[i][j] = in.readInt(); 90 | Board initial = new Board(tiles); 91 | 92 | // solve the puzzle 93 | Solver solver = new Solver(initial); 94 | 95 | // print solution to standard output 96 | if (!solver.isSolvable()) 97 | StdOut.println("No solution possible"); 98 | else { 99 | StdOut.println("Minimum number of moves = " + solver.moves()); 100 | for (Board board : solver.solution()) 101 | StdOut.println(board); 102 | } 103 | } 104 | } 105 | 106 | class BoardNode implements Comparable { 107 | public Board board; 108 | public BoardNode previous; 109 | public int moves; 110 | public Integer cachedPriority; 111 | 112 | public BoardNode(Board board, BoardNode previous, int moves) { 113 | this.board = board; 114 | this.previous = previous; 115 | this.moves = moves; 116 | } 117 | 118 | public int manhattanPriority() { 119 | if (cachedPriority == null) cachedPriority = moves + board.manhattan(); 120 | 121 | return cachedPriority; 122 | } 123 | 124 | public int compareTo(BoardNode other) { 125 | return this.manhattanPriority() - other.manhattanPriority(); 126 | } 127 | } -------------------------------------------------------------------------------- /Week-3/FastCollinearPoints.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.LinkedList; 3 | import java.util.Stack; 4 | import edu.princeton.cs.algs4.StdDraw; 5 | import edu.princeton.cs.algs4.In; 6 | import edu.princeton.cs.algs4.StdOut; 7 | 8 | public class FastCollinearPoints { 9 | 10 | private int segmentCount; 11 | private LineSegment[] collinearSegments; 12 | private Segment[] collinearSegmentsInternal; 13 | 14 | public FastCollinearPoints(Point[] points) { 15 | validateInput(points); 16 | segmentCount = 0; 17 | collinearSegments = new LineSegment[points.length]; 18 | collinearSegmentsInternal = new Segment[points.length]; 19 | 20 | for (Point p : points) { 21 | // Sort the points according to the slope they make with p 22 | Point[] slopesToP = getSlopesTo(p, points); 23 | 24 | for (int j = 0; j < slopesToP.length - 2; j++) { 25 | Point q = slopesToP[j]; 26 | Point[] candidatePoints = Arrays.copyOfRange(slopesToP, j+1, slopesToP.length); 27 | Point[] collinearSequence = findCollinearSequence(p, q, candidatePoints); 28 | 29 | if (collinearSequence.length >= 4) { 30 | addSegment(collinearSequence); 31 | break; 32 | } 33 | } 34 | } 35 | } 36 | 37 | public int numberOfSegments() { 38 | return segmentCount; 39 | } 40 | 41 | public LineSegment[] segments() { 42 | return Arrays.copyOfRange(collinearSegments, 0, numberOfSegments()); 43 | } 44 | 45 | private boolean isIncluded(Segment s) { 46 | for (int i = 0; i < segmentCount; i++) 47 | if (s.equals(collinearSegmentsInternal[i])) 48 | return true; 49 | 50 | return false; 51 | } 52 | 53 | private void printArray(Object[] arr) { 54 | for (Object x : arr) 55 | StdOut.println(x); 56 | } 57 | 58 | private Point[] findCollinearSequence(Point p, Point q, Point[] candidatePoints) { 59 | Stack collinearPoints = new Stack(); 60 | collinearPoints.push(p); 61 | collinearPoints.push(q); 62 | 63 | for (Point r : candidatePoints) 64 | if (areCollinear(p, collinearPoints.peek(), r)) 65 | collinearPoints.push(r); 66 | else 67 | break; 68 | 69 | return collinearPoints.toArray(new Point[0]); 70 | } 71 | 72 | private void addSegment(Stack collinearPoints) { 73 | addSegment(collinearPoints.toArray(new Point[0])); 74 | } 75 | 76 | private void addSegment(Point[] ps) { 77 | Arrays.sort(ps); 78 | Segment s = new Segment(ps[0], ps[ps.length - 1]); 79 | 80 | if (!isIncluded(s)) { 81 | collinearSegmentsInternal[segmentCount] = s; 82 | collinearSegments[segmentCount] = new LineSegment(s.minPoint, s.maxPoint); 83 | segmentCount++; 84 | } 85 | } 86 | 87 | public static void main(String[] args) { 88 | // read the n points from a file 89 | In in = new In(args[0]); 90 | int n = in.readInt(); 91 | Point[] points = new Point[n]; 92 | for (int i = 0; i < n; i++) { 93 | int x = in.readInt(); 94 | int y = in.readInt(); 95 | points[i] = new Point(x, y); 96 | } 97 | 98 | // print and draw the line segments 99 | FastCollinearPoints collinear = new FastCollinearPoints(points); 100 | for (LineSegment segment : collinear.segments()) { 101 | StdOut.println(segment); 102 | } 103 | } 104 | 105 | private void validateInput(Point[] points) { 106 | if (points == null) throw new IllegalArgumentException("The input cannot be null"); 107 | 108 | for (Point point : points) if (point == null) throw new IllegalArgumentException("The input cannot contain null points"); 109 | 110 | for (int i = 0; i < points.length; i++) 111 | for (int j = i + 1; j < points.length; j++) 112 | if (points[i].compareTo(points[j]) == 0) throw new IllegalArgumentException("The input cannot contain repeated points"); 113 | } 114 | 115 | private boolean areCollinear(Point p1, Point p2, Point p3) { 116 | return (Double.compare(p1.slopeTo(p2), p1.slopeTo(p3)) == 0); 117 | } 118 | 119 | private Point[] getSlopesTo(Point p, Point[] points) { 120 | // Returns an array of Points sorted by its slope to a point P 121 | Point[] slopesToP = Arrays.copyOf(points, points.length); 122 | Arrays.sort(slopesToP, p.slopeOrder()); 123 | 124 | // The point with the lowest slow to p is P itself (-INF), so we exclude it 125 | return Arrays.copyOfRange(slopesToP, 1, slopesToP.length); 126 | } 127 | 128 | private class Segment { 129 | public Point minPoint, maxPoint; 130 | 131 | public Segment(Point minPoint, Point maxPoint) { 132 | this.minPoint = minPoint; 133 | this.maxPoint = maxPoint; 134 | } 135 | 136 | public boolean equals(Segment other) { 137 | return ((minPoint.compareTo(other.minPoint) == 0) && (maxPoint.compareTo(other.maxPoint) == 0)); 138 | } 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /Week-1/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS='"-Xmx64m"' 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /Week-4/Board.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.ArrayList; 3 | 4 | import edu.princeton.cs.algs4.In; 5 | import edu.princeton.cs.algs4.StdRandom; 6 | 7 | public class Board { 8 | private final int n; 9 | private final int[][] board; 10 | 11 | // create a board from an n-by-n array of tiles, 12 | // where tiles[row][col] = tile at (row, col) 13 | public Board(int[][] tiles) { 14 | n = tiles.length; 15 | 16 | board = copyBoardContent(tiles); 17 | } 18 | 19 | // string representation of this board 20 | public String toString() { 21 | StringBuilder s = new StringBuilder(); 22 | 23 | s.append(n + "\n"); 24 | for (int i = 0; i < n; i++) { 25 | for (int j = 0; j < n; j++) 26 | s.append(String.format("%2d ", board[i][j])); 27 | 28 | s.append("\n"); 29 | } 30 | return s.toString(); 31 | } 32 | 33 | // board dimension n 34 | public int dimension() { 35 | return n; 36 | } 37 | 38 | // number of tiles out of place 39 | public int hamming() { 40 | int distance = 0; 41 | 42 | for (int row = 0; row < n; row++) 43 | for (int col = 0; col < n; col++) 44 | if (solution(row, col) != 0 && solution(row, col) != board[row][col]) 45 | distance++; 46 | 47 | return distance; 48 | } 49 | 50 | // sum of Manhattan distances between tiles and goal 51 | public int manhattan() { 52 | int distance = 0; 53 | 54 | for (int row = 0; row < n; row++) 55 | for (int col = 0; col < n; col++) 56 | distance += distanceToCorrectPosition(board[row][col], row, col); 57 | 58 | return distance; 59 | } 60 | 61 | // is this board the goal board? 62 | public boolean isGoal() { 63 | for (int row = 0; row < n; row++) 64 | for (int col = 0; col < n; col++) 65 | if (board[row][col] != solution(row, col)) 66 | return false; 67 | 68 | return true; 69 | } 70 | 71 | // does this board equal y? 72 | public boolean equals(Object other) { 73 | if (other == this) return true; 74 | if (other == null) return false; 75 | if (other.getClass() != this.getClass()) return false; 76 | 77 | Board otherBoard = (Board) other; 78 | 79 | return Arrays.deepEquals(this.board, otherBoard.board); 80 | } 81 | 82 | // all neighboring boards 83 | public Iterable neighbors() { 84 | int blankRow = 0, blankCol = 0; 85 | boolean blankFound = false; 86 | ArrayList neighbors = new ArrayList(); 87 | 88 | for (blankRow = 0; blankRow < n; blankRow++) { 89 | for (blankCol = 0; blankCol < n; blankCol++) 90 | if (board[blankRow][blankCol] == 0) { 91 | blankFound = true; 92 | break; 93 | } 94 | 95 | if (blankFound) break; 96 | } 97 | 98 | // Top neighbor 99 | if (blankRow > 0) 100 | neighbors.add(copyFromOriginalAndSwapTiles(blankRow, blankCol, blankRow - 1, blankCol)); 101 | 102 | // Left neighbor 103 | if (blankCol > 0) 104 | neighbors.add(copyFromOriginalAndSwapTiles(blankRow, blankCol, blankRow, blankCol - 1)); 105 | 106 | // Right neighbor 107 | if (blankCol < (n - 1)) 108 | neighbors.add(copyFromOriginalAndSwapTiles(blankRow, blankCol, blankRow, blankCol + 1)); 109 | 110 | // Bottom neighbor 111 | if (blankRow < (n - 1)) 112 | neighbors.add(copyFromOriginalAndSwapTiles(blankRow, blankCol, blankRow + 1, blankCol)); 113 | 114 | return neighbors; 115 | } 116 | 117 | // a board that is obtained by exchanging any pair of tiles 118 | public Board twin() { 119 | int swappingRow, swappingCol, twinRow, twinCol; 120 | swappingRow = swappingCol = 0; 121 | twinCol = twinRow = n - 1; 122 | 123 | if (board[swappingRow][swappingCol] == 0) 124 | swappingCol++; 125 | 126 | if (board[twinRow][twinCol] == 0) 127 | twinCol--; 128 | 129 | return copyFromOriginalAndSwapTiles(swappingRow, swappingCol, twinRow, twinCol); 130 | } 131 | 132 | // unit testing (not graded) 133 | public static void main(String[] args) { 134 | // create initial board from file 135 | In in = new In(args[0]); 136 | int n = in.readInt(); 137 | int[][] tiles = new int[n][n]; 138 | for (int i = 0; i < n; i++) 139 | for (int j = 0; j < n; j++) 140 | tiles[i][j] = in.readInt(); 141 | Board initial = new Board(tiles); 142 | 143 | System.out.print(initial.toString()); 144 | } 145 | 146 | private int distanceToCorrectPosition(int value, int currentRow, int currentCol) { 147 | if (value == 0) return 0; 148 | 149 | int correctRow = (value - 1) / n; 150 | int correctCol = (value - 1) % n; 151 | 152 | int dist = Math.abs(currentRow - correctRow) + Math.abs(currentCol - correctCol); 153 | return dist; 154 | } 155 | 156 | private int solution(int row, int col) { 157 | if (row == (n - 1) && col == (n - 1)) return 0; 158 | return row * n + col + 1; 159 | } 160 | 161 | private int[][] copyBoardContent(int[][] original) { 162 | int[][] destination = new int[n][n]; 163 | 164 | for (int row = 0; row < n; row++) 165 | for (int col = 0; col < n; col++) 166 | destination[row][col] = original[row][col]; 167 | 168 | return destination; 169 | } 170 | 171 | private Board copyFromOriginalAndSwapTiles(int originalRow, int originalCol, int newRow, int newCol) { 172 | int[][] boardCopy = copyBoardContent(board); 173 | 174 | boardCopy[originalRow][originalCol] = board[newRow][newCol]; 175 | boardCopy[newRow][newCol] = board[originalRow][originalCol]; 176 | 177 | return new Board(boardCopy); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /Week-2/Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | # Programming Assignment 2: Deques and Randomized Queues 2 | 3 | Write a generic data type for a deque and a randomized queue. The goal of this assignment is to implement elementary data structures using arrays and linked lists, and to introduce you to generics and iterators. 4 | 5 | ## Dequeue 6 | A _double-ended queue_ or _deque_ (pronounced “deck”) is a generalization of a stack and a queue that supports adding and removing items from either the front or the back of the data structure. Create a generic data type `Deque` that implements the following API: 7 | 8 | ``` 9 | public class Deque implements Iterable { 10 | public Deque() // construct an empty deque 11 | public boolean isEmpty() // is the deque empty? 12 | public int size() // return the number of items on the deque 13 | public void addFirst(Item item) // add the item to the front 14 | public void addLast(Item item) // add the item to the end 15 | public Item removeFirst() // remove and return the item from the front 16 | public Item removeLast() // remove and return the item from the end 17 | public Iterator iterator() // return an iterator over items in order from front to end 18 | public static void main(String[] args) // unit testing (optional) 19 | } 20 | ``` 21 | 22 | #### Corner cases 23 | Throw the specified exception for the following corner cases: 24 | 25 | 26 | - Throw a `java.lang.IllegalArgumentException` if the client calls either `addFirst()` or `addLast()` with a null argument. 27 | - Throw a `java.util.NoSuchElementException` if the client calls either `removeFirst()` or `removeLast()` when the deque is empty. 28 | - Throw a `java.util.NoSuchElementException` if the client calls the `next()` method in the iterator when there are no more items to return. 29 | - Throw a `java.lang.UnsupportedOperationException` if the client calls the `remove()` method in the iterator. 30 | 31 | 32 | 33 | #### Performance requirements 34 | Your deque implementation must support each deque operation (including construction) in **constant worst-case time**. A deque containing _n_ items must use at most `48n + 192 bytes` of memory and use space proportional to the number of items currently in the deque. Additionally, your iterator implementation must support each operation (including construction) in **constant worst-case time**. 35 | 36 | 37 | ## Randomized Queue 38 | A _randomized queue_ is similar to a stack or queue, except that the item removed is chosen uniformly at random from items in the data structure. Create a generic data type `RandomizedQueue` that implements the following API: 39 | 40 | ``` 41 | public class RandomizedQueue implements Iterable { 42 | public RandomizedQueue() // construct an empty randomized queue 43 | public boolean isEmpty() // is the randomized queue empty? 44 | public int size() // return the number of items on the randomized queue 45 | public void enqueue(Item item) // add the item 46 | public Item dequeue() // remove and return a random item 47 | public Item sample() // return a random item (but do not remove it) 48 | public Iterator iterator() // return an independent iterator over items in random order 49 | public static void main(String[] args) // unit testing (optional) 50 | } 51 | ``` 52 | 53 | #### Iterator 54 | Each iterator must return the items in uniformly random order. The order of two or more iterators to the same randomized queue must be _mutually independent_; each iterator must maintain its own random order. 55 | 56 | 57 | #### Corner cases 58 | Throw the specified exception for the following corner cases: 59 | 60 | - Throw a `java.lang.IllegalArgumentException` if the client calls `enqueue()` with a `null` argument. 61 | 62 | - Throw a `java.util.NoSuchElementException` if the client calls either `sample()` or `dequeue()` when the randomized queue is empty. 63 | 64 | - Throw a `java.util.NoSuchElementException` if the client calls the `next()` method in the iterator when there are no more items to return. 65 | 66 | - Throw a `java.lang.UnsupportedOperationException` if the client calls the `remove()` method in the iterator. 67 | 68 | 69 | #### Performance requirements 70 | Your randomized queue implementation must support each randomized queue operation (besides creating an iterator) in **constant amortized time**. That is, any sequence of _m_ randomized queue operations (starting from an empty queue) must take at most _cm_ steps in the worst case, for some constant _c_. A randomized queue containing _n_ items must use at most `48n + 192 bytes` of memory. Additionally, your iterator implementation must support operations `next()` and `hasNext()` in **constant worst-case time**; and construction in **linear time**; you may (and will need to) use a linear amount of extra memory per iterator. 71 | 72 | ## Client 73 | Write a client program `Permutation.java` that takes an integer _k_ as a command-line argument; reads in a sequence of strings from standard input using `StdIn.readString()`; and prints exactly k of them, uniformly at random. Print each item from the sequence at most once. 74 | 75 | ![execution-examples](https://i.imgur.com/kvWptPM.png) 76 | 77 | Your program must implement the following API: 78 | 79 | ``` 80 | public class Permutation { 81 | public static void main(String[] args) 82 | } 83 | 84 | ``` 85 | 86 | #### Command-line input 87 | You may assume that _0 ≤ k ≤ n_, where _n_ is the number of string on standard input. 88 | 89 | #### Performance requirements 90 | The running time of `Permutation` must be linear in the size of the input. You may use only a constant amount of memory plus either one `Deque` or `RandomizedQueue` object of maximum size at most _n_. (For an extra challenge, use only one `Deque` or `RandomizedQueue` object of maximum size at most _k_.) 91 | 92 | 93 | 94 | ## Deliverables 95 | Submit the programs `RandomizedQueue.java`, `Deque.java`, and `Permutation.java`. Your submission may not call library functions except those in `StdIn`, `StdOut`, `StdRandom`, `java.lang`, `java.util.Iterator`, and `java.util.NoSuchElementException`. In particular, do not use either `java.util.LinkedList` or `java.util.ArrayList`. 96 | -------------------------------------------------------------------------------- /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 java.util.Comparator; 12 | import edu.princeton.cs.algs4.StdDraw; 13 | 14 | public class Point implements Comparable { 15 | 16 | private final int x; // x-coordinate of this point 17 | private final int y; // y-coordinate of this point 18 | 19 | /** 20 | * Initializes a new point. 21 | * 22 | * @param x the x-coordinate of the point 23 | * @param y the y-coordinate of the point 24 | */ 25 | public Point(int x, int y) { 26 | /* DO NOT MODIFY */ 27 | this.x = x; 28 | this.y = y; 29 | } 30 | 31 | /** 32 | * Draws this point to standard draw. 33 | */ 34 | public void draw() { 35 | /* DO NOT MODIFY */ 36 | StdDraw.point(x, y); 37 | } 38 | 39 | /** 40 | * Draws the line segment between this point and the specified point 41 | * to standard draw. 42 | * 43 | * @param that the other point 44 | */ 45 | public void drawTo(Point that) { 46 | /* DO NOT MODIFY */ 47 | StdDraw.line(this.x, this.y, that.x, that.y); 48 | } 49 | 50 | /** 51 | * Returns the slope between this point and the specified point. 52 | * Formally, if the two points are (x0, y0) and (x1, y1), then the slope 53 | * is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be 54 | * +0.0 if the line segment connecting the two points is horizontal; 55 | * Double.POSITIVE_INFINITY if the line segment is vertical; 56 | * and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal. 57 | * 58 | * @param that the other point 59 | * @return the slope between this point and the specified point 60 | */ 61 | public double slopeTo(Point that) { 62 | if (this.x == that.x) 63 | if (this.y == that.y) return Double.NEGATIVE_INFINITY; // Both points are the same 64 | else return Double.POSITIVE_INFINITY; // Vertical line 65 | 66 | if (this.y == that.y) 67 | return 0.0; // Horizontal line 68 | 69 | else return ((double) (that.y - this.y) / (double) (that.x - this.x)); 70 | } 71 | 72 | /** 73 | * Compares two points by y-coordinate, breaking ties by x-coordinate. 74 | * Formally, the invoking point (x0, y0) is less than the argument point 75 | * (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1. 76 | * 77 | * @param that the other point 78 | * @return the value 0 if this point is equal to the argument 79 | * point (x0 = x1 and y0 = y1); 80 | * a negative integer if this point is less than the argument 81 | * point; and a positive integer if this point is greater than the 82 | * argument point 83 | */ 84 | public int compareTo(Point that) { 85 | int difY = this.y - that.y; 86 | if (difY != 0) { 87 | return difY; 88 | } else { 89 | return (this.x - that.x); 90 | } 91 | } 92 | 93 | /** 94 | * Compares two points by the slope they make with this point. 95 | * The slope is defined as in the slopeTo() method. 96 | * 97 | * @return the Comparator that defines this ordering on points 98 | */ 99 | public Comparator slopeOrder() { 100 | return new BySlope(this); 101 | } 102 | 103 | private static class BySlope implements Comparator { 104 | private final Point p; 105 | 106 | public BySlope(Point p) { 107 | this.p = p; 108 | } 109 | 110 | public int compare(Point p1, Point p2) { 111 | double slopeTo1 = this.p.slopeTo(p1); 112 | double slopeTo2 = this.p.slopeTo(p2); 113 | 114 | if (slopeTo1 > slopeTo2) return 1; 115 | if (slopeTo1 < slopeTo2) return -1; 116 | else return 0; 117 | } 118 | } 119 | 120 | /** 121 | * Returns a string representation of this point. 122 | * This method is provide for debugging; 123 | * your program should not rely on the format of the string representation. 124 | * 125 | * @return a string representation of this point 126 | */ 127 | public String toString() { 128 | /* DO NOT MODIFY */ 129 | return "(" + x + ", " + y + ")"; 130 | } 131 | 132 | /** 133 | * Unit tests the Point data type. 134 | */ 135 | public static void main(String[] args) { 136 | Point p0 = new Point(0, 0); 137 | 138 | 139 | System.out.println("Testing slopeTo"); 140 | System.out.println(p0.slopeTo(new Point(0, 0))); // Double.NEGATIVE_INFINITY; 141 | System.out.println(p0.slopeTo(new Point(0, 1))); // Double.POSITIVE_INFINITY; 142 | System.out.println(p0.slopeTo(new Point(3, 0))); // 0.0 143 | System.out.println(p0.slopeTo(new Point(1, 1))); // 1.0 144 | System.out.println(p0.slopeTo(new Point(-232, -232))); // 1.0 145 | System.out.println(p0.slopeTo(new Point(-1, 1))); // -1.0 146 | System.out.println(p0.slopeTo(new Point(2, 1))); // 0.5 147 | System.out.println(p0.slopeTo(new Point(1, 2))); // 2.0 148 | System.out.println(p0.slopeTo(new Point(1, 30))); // 30.0 149 | System.out.println(p0.slopeTo(new Point(30, 1))); // aprox 0.033333 150 | 151 | System.out.println("\n"); 152 | System.out.println("Testing compareTo"); 153 | System.out.println(p0.compareTo(new Point(0, 0))); // 0 154 | System.out.println(p0.compareTo(new Point(1, 0))); // 1 155 | System.out.println(p0.compareTo(new Point(2, -1))); // -1 156 | System.out.println(p0.compareTo(new Point(-1, 0))); // -1 157 | System.out.println(p0.compareTo(new Point(0, -0))); // 0 158 | System.out.println(p0.compareTo(new Point(2, 2))); // 1 159 | System.out.println(p0.compareTo(new Point(-2, 5))); // 1 160 | System.out.println(p0.compareTo(new Point(333, -0))); // 1 161 | System.out.println(p0.compareTo(new Point(0, 3333))); // 1 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Week-1/src/main/java/Percolation.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.WeightedQuickUnionUF; 2 | 3 | public class Percolation { 4 | private int openSitesCount; 5 | 6 | private final boolean[][] openSites; 7 | private final WeightedQuickUnionUF grid, gridWithoutBottom; 8 | private final int n, top, bottom; 9 | 10 | /** 11 | * Creates an n-by-n grid, with all sites initially blocked 12 | * 13 | * NOTE: Backwash 14 | * Backwash is a problem caused by the fact that we have virtual sites at the bottom and the 15 | * top, and because all the sites at the bottom row are connected to the virtual bottom. 16 | * When the system percolates, the virtual bottom will be connected to the virtual top. 17 | * As a consequence, all the sites in the bottom row will also be connected to the virtual 18 | * top through this bottom, and will be marked as Full even if they aren't actually connected 19 | * to the top 20 | * To prevent this, we create a second grid data-structure without virtual bottom. We'll use 21 | * this second grid only to check if the elements are full; as it doesn't have bottom, a site 22 | * will only be full if there is a real path to the top. 23 | * 24 | * @param n Size of the side of the grid 25 | * @throws IllegalAgumentException if n <= 0 26 | */ 27 | public Percolation(int n) { 28 | if (n <= 0) throw new IllegalArgumentException("ERROR"); 29 | 30 | this.n = n; 31 | this.grid = new WeightedQuickUnionUF(n * n + 2); 32 | this.gridWithoutBottom = new WeightedQuickUnionUF(n * n + 1); 33 | this.openSites = new boolean[n][n]; 34 | this.openSitesCount = 0; 35 | 36 | top = 0; 37 | bottom = n * n + 1; 38 | 39 | connectFirstRowToTop(); 40 | connectLastRowToBottom(); 41 | } 42 | 43 | /** 44 | * Opens the site (row, col) if it's not already open 45 | * 46 | * @param row Row of the site that we want to open. Must be between 1 and n (both included) 47 | * @param col Column of the site that we want to open. Must be between 1 and n (both included) 48 | * @throws IllegalArgumentException if either row or column are not in the [1, n] range 49 | */ 50 | public void open(int row, int col) { 51 | validateCoordinate(row); 52 | validateCoordinate(col); 53 | 54 | if (isOpen(row, col)) return; 55 | 56 | openSite(row, col); 57 | connectToNeighbors(row, col); 58 | } 59 | 60 | /** 61 | * Indicates if a specific site is open or not 62 | * 63 | * @param row Row of the site that we want to open. Must be between 1 and n (both included) 64 | * @param col Column of the site that we want to open. Must be between 1 and n (both included) 65 | * @throws IllegalArgumentException if either row or column are not in the [1, n] range 66 | * @return boolean indicating if the site (row, col) is open 67 | */ 68 | public boolean isOpen(int row, int col) { 69 | validateCoordinate(row); 70 | validateCoordinate(col); 71 | 72 | return openSites[row - 1][col - 1]; 73 | } 74 | 75 | /** 76 | * Indicates if the specified site is connected to any site in the top row of the grid 77 | * 78 | * @param row Row of the site that we want to open. Must be between 1 and n (both included) 79 | * @param col Column of the site that we want to open. Must be between 1 and n (both included) 80 | * @throws IllegalArgumentException if either row or column are not in the [1, n] range 81 | * @return boolean indicating if the site connects with any site in the top 82 | */ 83 | public boolean isFull(int row, int col) { 84 | validateCoordinate(row); 85 | validateCoordinate(col); 86 | 87 | return isOpen(row, col) && isConnectedToTop(row, col); 88 | } 89 | 90 | /** 91 | * Indicates how many sites are open in the grid 92 | * 93 | * @return Number of open sites in the grid 94 | */ 95 | public int numberOfOpenSites() { 96 | return openSitesCount; 97 | } 98 | 99 | /** 100 | * Indicates if the grid percolates (i.e. if any site at the top row is connected to any site 101 | * at the bottom row) 102 | * 103 | * @return boolean indicating if the grid percolates 104 | */ 105 | public boolean percolates() { 106 | if (unopenedOneSiteGrid()) return false; 107 | 108 | return grid.connected(top, bottom); 109 | } 110 | 111 | private int convertToGrid(int row, int col) { 112 | return (row - 1) * n + col; 113 | } 114 | 115 | private void openSite(int row, int col) { 116 | openSitesCount++; 117 | openSites[row - 1][col - 1] = true; 118 | } 119 | 120 | private boolean isConnectedToTop(int row, int col) { 121 | return gridWithoutBottom.connected(top, convertToGrid(row, col)); 122 | } 123 | 124 | private void connectFirstRowToTop() { 125 | for (int col = 1; col <= n; col++) connectToTop(1, col); 126 | } 127 | 128 | private void connectToTop(int row, int col) { 129 | grid.union(top, convertToGrid(row, col)); 130 | gridWithoutBottom.union(top, convertToGrid(row, col)); 131 | } 132 | 133 | private void connectLastRowToBottom() { 134 | for (int col = 1; col <= n; col++) connectToBottom(n, col); 135 | } 136 | 137 | private void connectToBottom(int row, int col) { 138 | grid.union(bottom, convertToGrid(row, col)); 139 | } 140 | 141 | private void connectToNeighbors(int row, int col) { 142 | connect(row, col, row - 1, col); // Top 143 | connect(row, col, row + 1, col); // Bottom 144 | connect(row, col, row, col - 1); // Left 145 | connect(row, col, row, col + 1); // Right 146 | } 147 | 148 | private void connect(int row1, int col1, int row2, int col2) { 149 | // Avoid the connection if the neighbor is out of bounds 150 | if ((row2 < 1) || (row2 > n) || (col2 < 1) || (col2 > n)) return; 151 | 152 | // Avoid the connection if the neighbor is closed 153 | if (!isOpen(row2, col2)) return; 154 | 155 | grid.union(convertToGrid(row1, col1), convertToGrid(row2, col2)); 156 | gridWithoutBottom.union(convertToGrid(row1, col1), convertToGrid(row2, col2)); 157 | } 158 | 159 | private void validateCoordinate(int coordinate) { 160 | if (coordinate < 1 || coordinate > n) 161 | throw new IllegalArgumentException("ERROR"); 162 | } 163 | 164 | private boolean unopenedOneSiteGrid() { 165 | /* 166 | Method to prevent a corner case: when the grid is 1x1, the only site that forms it is 167 | at the same time in the first and the last row of the grid. Therefore, on the constructor 168 | we connect it to the Top and to the Bottom. 169 | 170 | To avoid reporting it case as always percolating, we force the check of that site being open 171 | */ 172 | boolean hasOnlyOneSite = n == 1; 173 | boolean theSiteIsNotOpen = !isOpen(1, 1); 174 | 175 | return hasOnlyOneSite && theSiteIsNotOpen; 176 | } 177 | } -------------------------------------------------------------------------------- /Week-1/README.md: -------------------------------------------------------------------------------- 1 | # Programming assignment 1 - Percolation 2 | ## Percolation 3 | Given a composite systems comprised of randomly distributed insulating and metallic materials: what fraction of the materials need to be metallic so that the composite system is an electrical conductor? Given a porous landscape with water on the surface (or oil below), under what conditions will the water be able to drain through to the bottom (or the oil to gush through to the surface)? Scientists have defined an abstract process known as percolation to model such situations. 4 | 5 | ## The model 6 | We model a percolation system using an n-by-n grid of sites. Each site is either open or blocked. A full site is an open site that can be connected to an open site in the top row via a chain of neighboring (left, right, up, down) open sites. We say the system percolates if there is a full site in the bottom row. In other words, a system percolates if we fill all open sites connected to the top row and that process fills some open site on the bottom row. (For the insulating/metallic materials example, the open sites correspond to metallic materials, so that a system that percolates has a metallic path from top to bottom, with full sites conducting. For the porous substance example, the open sites correspond to empty space through which water might flow, so that a system that percolates lets water fill open sites, flowing from top to bottom.) 7 | 8 | ![percolates](https://coursera.cs.princeton.edu/algs4/assignments/percolation/percolates-yes.png) 9 | ![not-percolates](https://coursera.cs.princeton.edu/algs4/assignments/percolation/percolates-no.png) 10 | 11 | ## The problem 12 | In a famous scientific problem, researchers are interested in the following question: if sites are independently set to be open with probability p (and therefore blocked with probability 1 − p), what is the probability that the system percolates? When p equals 0, the system does not percolate; when p equals 1, the system percolates. The plots below show the site vacancy probability p versus the percolation probability for 20-by-20 random grid (left) and 100-by-100 random grid (right) 13 | ![20x20 grid](https://coursera.cs.princeton.edu/algs4/assignments/percolation/percolation-threshold20.png) 14 | ![100x100 grid](https://coursera.cs.princeton.edu/algs4/assignments/percolation/percolation-threshold100.png) 15 | 16 | When n is sufficiently large, there is a threshold value p* such that when p < p* a random n-by-n grid almost never percolates, and when p > p*, a random n-by-n grid almost always percolates. No mathematical solution for determining the percolation threshold p* has yet been derived. Your task is to write a computer program to estimate p*. 17 | 18 | ## Percolation data type 19 | To model a percolation system, create a data type Percolation with the following API: 20 | 21 | ```java 22 | public class Percolation { 23 | 24 | // creates n-by-n grid, with all sites initially blocked 25 | public Percolation(int n) 26 | 27 | // opens the site (row, col) if it is not open already 28 | public void open(int row, int col) 29 | 30 | // is the site (row, col) open? 31 | public boolean isOpen(int row, int col) 32 | 33 | // is the site (row, col) full? 34 | public boolean isFull(int row, int col) 35 | 36 | // returns the number of open sites 37 | public int numberOfOpenSites() 38 | 39 | // does the system percolate? 40 | public boolean percolates() 41 | 42 | // test client (optional) 43 | public static void main(String[] args) 44 | } 45 | ``` 46 | 47 | #### Corner cases 48 | By convention, the row and column indices are integers between 1 and n, where (1, 1) is the upper-left site: Throw a `java.lang.IllegalArgumentException` if any argument to open(), isOpen(), or isFull() is outside its prescribed range. The constructor should throw a java.lang.IllegalArgumentException if n ≤ 0 49 | 50 | #### Performance requirements 51 | The constructor should take time proportional to n^2; all methods should take constant time plus a constant number of calls to the union–find methods union(), find(), connected(), and count(). 52 | 53 | ## Monte Carlo simulation 54 | To estimate the percolation threshold, consider the following computational experiment: 55 | 56 | * Initialize all sites to be blocked. 57 | * Repeat the following until the system percolates: 58 | * Choose a site uniformly at random among all blocked sites. 59 | * Open the site. 60 | * The fraction of sites that are opened when the system percolates provides an estimate of the percolation threshold. 61 | For example, if sites are opened in a 20-by-20 lattice according to the snapshots below, then our estimate of the percolation threshold is 204/400 = 0.51 because the system percolates when the 204th site is opened. 62 | 63 | By repeating this computation experiment T times and averaging the results, we obtain a more accurate estimate of the percolation threshold. Let x_t be the fraction of open sites in computational experiment t. The sample mean x¯ provides an estimate of the percolation threshold; the sample standard deviation s; measures the sharpness of the threshold. 64 | 65 | Assuming T is sufficiently large (say, at least 30), the following provides a 95% confidence interval for the percolation threshold: 66 | 67 | *Lower limit of the confidence interval*: `x- - (1.96*s)/sqrt(T)` 68 | *Higher limit of the confidence interval*: `x- + (1.96*s)/sqrt(T)` 69 | 70 | To perform a series of computational experiments, create a data type `PercolationStats` with the following API 71 | 72 | ```java 73 | public class PercolationStats { 74 | 75 | // perform independent trials on an n-by-n grid 76 | public PercolationStats(int n, int trials) 77 | 78 | // sample mean of percolation threshold 79 | public double mean() 80 | 81 | // sample standard deviation of percolation threshold 82 | public double stddev() 83 | 84 | // low endpoint of 95% confidence interval 85 | public double confidenceLo() 86 | 87 | // high endpoint of 95% confidence interval 88 | public double confidenceHi() 89 | 90 | // test client (see below) 91 | public static void main(String[] args) 92 | 93 | } 94 | ``` 95 | 96 | The constructor should throw a `java.lang.IllegalArgumentException` if either n ≤ 0 or trials ≤ 0. 97 | 98 | Also, include a `main()` method that takes two command-line arguments n and T, performs T independent computational experiments (discussed above) on an n-by-n grid, and prints the sample mean, sample standard deviation, and the 95% confidence interval for the percolation threshold. Use `StdRandom` to generate random numbers; use `StdStats` to compute the sample mean and sample standard deviation. 99 | 100 | Now, implement the Percolation data type using the weighted quick union algorithm in WeightedQuickUnionUF. Answer the questions in the previous paragraph. 101 | 102 | ## Web submission 103 | Submit a .zip file containing only `Percolation.java` (using the weighted quick-union algorithm from `WeightedQuickUnionUF`) and `PercolationStats.java`. We will supply algs4.jar. Your submission may not call library functions except those in `StdIn`, `StdOut`, `StdRandom`, `StdStats`, `WeightedQuickUnionUF`, and `java.lang`. 104 | 105 | 106 | -------------------------------------------------------------------------------- /Week-2/Programming-Assignment/Deque.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Dequeue. A double-ended queue or deque (pronounced “deck”) is a generalization 3 | * of a stack and a queue that supports adding and removing items from either the 4 | * front or the back of the data structure. 5 | */ 6 | 7 | /** 8 | * Your deque implementation must support each deque operation (including 9 | * construction) in constant worst-case time. A deque containing n items must use 10 | * at most 48n + 192 bytes of memory and use space proportional to the number of 11 | * items currently in the deque. Additionally, your iterator implementation must 12 | * support each operation (including construction) in constant worst-case time. 13 | */ 14 | 15 | /** 16 | * The fact that we are asked to use constant WORST-CASE time indicates that we 17 | * have to implement the Deque with linked-list, because an implementation with 18 | * arrays will require extra time if we need to resize it. 19 | */ 20 | 21 | import java.util.Iterator; 22 | 23 | public class Deque implements Iterable { 24 | 25 | private Node first; 26 | private Node last; 27 | private int count; 28 | 29 | public Deque() { 30 | this.first = null; 31 | this.last = null; 32 | this.count = 0; 33 | } 34 | 35 | /** 36 | * Returns true if there aren't any elements in the deque 37 | * 38 | * @return true if the deque is empty, false otherwise 39 | */ 40 | public boolean isEmpty() { 41 | return size() == 0; 42 | } 43 | 44 | /** 45 | * Number of elements in the deque 46 | * 47 | * @return integer - Number of elements currently in the deque 48 | */ 49 | public int size() { 50 | return count; 51 | } 52 | 53 | /** 54 | * Puts the input item at the front of the deque 55 | * 56 | * @param item Element that will be inserted 57 | */ 58 | public void addFirst(Item item) { 59 | validateItem(item); 60 | 61 | Node oldFirst = first; 62 | 63 | first = new Node(); 64 | first.item = item; 65 | first.next = oldFirst; 66 | first.previous = null; 67 | 68 | if (isEmpty()) last = first; 69 | else oldFirst.previous = first; 70 | 71 | count++; 72 | } 73 | 74 | /** 75 | * Puts the input item at the back of the deque 76 | * 77 | * @param item Element that will be inserted 78 | */ 79 | public void addLast(Item item) { 80 | validateItem(item); 81 | 82 | Node oldLast = last; 83 | 84 | last = new Node(); 85 | last.item = item; 86 | last.next = null; 87 | last.previous = oldLast; 88 | 89 | if (isEmpty()) first = last; 90 | else oldLast.next = last; 91 | 92 | count++; 93 | } 94 | 95 | /** 96 | * Returns the element at the front of the deque and removes it from there 97 | * 98 | * @return Item - The element that was at the front of the deque 99 | */ 100 | public Item removeFirst() { 101 | validateNotEmpty(); 102 | 103 | Node oldFirst = first; 104 | first = oldFirst.next; 105 | count--; 106 | 107 | if (isEmpty()) last = null; 108 | else first.previous = null; 109 | 110 | return oldFirst.item; 111 | } 112 | 113 | /** 114 | * Returns the element at the back of the deque and removes it from there 115 | * 116 | * @return Item - The element that was at the back of the deque 117 | */ 118 | public Item removeLast() { 119 | validateNotEmpty(); 120 | 121 | Node oldLast = last; 122 | last = oldLast.previous; 123 | count--; 124 | 125 | if (isEmpty()) first = null; 126 | else last.next = null; 127 | 128 | return oldLast.item; 129 | } 130 | 131 | public Iterator iterator() { return new DequeIterator(); } 132 | 133 | public static void main(String[] args) { 134 | Deque deck = new Deque(); 135 | 136 | System.out.println("IS EMPTY: " + deck.isEmpty()); 137 | 138 | for (int i = 0; i < 10; i++) { 139 | deck.addFirst(i); 140 | System.out.println("SIZE: " + deck.size()); 141 | System.out.println("IS EMPTY: " + deck.isEmpty()); 142 | } 143 | 144 | System.out.println("Elements 0-9 added. We should have seen 1 to 10 printed"); 145 | 146 | for (Integer i : deck) { 147 | System.out.println(i); 148 | } 149 | 150 | System.out.println("Finished iterating over the iterator. Elements should appear from 9 to 0."); 151 | 152 | for (int i = 0; i < 10; i++) { 153 | System.out.println(deck.removeLast()); 154 | System.out.println("IS EMPTY: " + deck.isEmpty()); 155 | System.out.println("Deck size: " + deck.size()); 156 | } 157 | 158 | System.out.println("Elements 0-9 removed. They should appear from 0 to 9."); 159 | 160 | for (int i = 0; i < 10; i++) { 161 | deck.addLast(i); 162 | System.out.println("IS EMPTY: " + deck.isEmpty()); 163 | System.out.println("Deck size: " + deck.size()); 164 | } 165 | 166 | System.out.println("Elements 0-9 added."); 167 | 168 | for (Integer i : deck) { 169 | System.out.println(i); 170 | } 171 | 172 | System.out.println("Finished iterating over the iterator. Elements should appear from 0 to 9"); 173 | 174 | for (int i = 0; i < 10; i++) { 175 | System.out.println(deck.removeFirst()); 176 | System.out.println("IS EMPTY: " + deck.isEmpty()); 177 | System.out.println("Deck size: " + deck.size()); 178 | } 179 | 180 | System.out.println("Elements 0-9 removed. Elements should appear from 0 to 9"); 181 | 182 | } 183 | 184 | private void validateItem(Item item) { 185 | if (item == null) throw new IllegalArgumentException("The item can't be null"); 186 | } 187 | 188 | private void validateNotEmpty() { 189 | if (isEmpty()) throw new java.util.NoSuchElementException("The deque is empty"); 190 | } 191 | 192 | 193 | private class Node { 194 | Item item; 195 | Node next; 196 | Node previous; 197 | 198 | Node() { 199 | // Empty method 200 | } 201 | 202 | Node(Item item, Node next) { 203 | this.item = item; 204 | this.next = next; 205 | } 206 | 207 | Node(Item item, Node next, Node previous) { 208 | this.item = item; 209 | this.next = next; 210 | this.previous = previous; 211 | } 212 | } 213 | 214 | private class DequeIterator implements Iterator { 215 | 216 | private Node current = first; 217 | 218 | public Item next() { 219 | if (!hasNext()) throw new java.util.NoSuchElementException("There are no more elements"); 220 | 221 | Item item = current.item; 222 | current = current.next; 223 | 224 | return item; 225 | } 226 | 227 | public boolean hasNext() { return current != null; } 228 | 229 | public void remove() { 230 | throw new UnsupportedOperationException("This operation is not supported by this class"); 231 | } 232 | } 233 | } 234 | --------------------------------------------------------------------------------