Take-Home Lab #01 CS1020 – DATA STRUCTURES AND ALGORITHMS 1 AY2015-16 SEMESTER 2 Problem 1 Measurement You are given a number N. N rows follow. Each row contains: • • • Name of a student Height of a student (in cm) Weight of a student (in kg) Measurement How? Data Storing Data Processing Measurement Array Solution VS Non-Array Solution Measurement Array solution Store the height, weight, and name of each student in an array of the appropriate data type. Linear scan the height[] array, keeping the index of the maximum and minimum height. Retrieve the height, weight and name of the tallest student and the shortest student using the index you got from the previous step. Calculate the BMI and print the result. Measurement Non-Array solution We do not actually need to store all the data in an array. Initialise variables that keep track of the minimum height so far, maximum height so far, as well as the name and height of both the (current) tallest and (current) shortest student. Read the input using a scanner, update the variables when necessary. When is it necessary to update the variables above? Calculate the BMI and print the result. Measurement Code Snippet Scanner sc = new Scanner(System.in); Initialise Variables int heightOfCurrentShortestStudent = Integer.MAX_VALUE; int heightOfCurrentTallestStudent = Integer.MIN_VALUE; int weightOfCurrentShortestStudent = 0; int weightOfCurrentTallestStudent = 0; String nameOfCurrentShortestStudent = ""; String nameOfCurrentTallestStudent = ""; Measurement Code Snippet for (int i = 0; i < n; i++) { //for every line of the input String currentName = ??? (use your Scanner here) //how to get the name of the current student? int currentHeight = ??? //how to get the height of the current student? int currentWeight = ??? //how to get the weight of the current student? Process Input if (currentHeight < heightOfCurrentShortestStudent) { //what do you need to do here? } if (currentHeight > heightOfCurrentTallestStudent) { //what do you need to do here? } sc.nextLine(); //what is the purpose of this? } Measurement ? How do I print to two decimal places? Hint: System.out.printf(…); Measurement Problem 2 Island You are given a map of Hyrule consisting of many islands. The map is a matrix of size R x C filled with ‘0’s and ‘1’s. Your job: count the number of islands based on the given map (you need N tickets to go to N islands). 0 0 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0 1 1 An example of a valid Hyrule map with two islands Island Standard (Tedious-To-Code) Solution VS (Very) Simple Solution Island Hints: 1. All islands are rectangular. 2. Every plot of land is a part of an island ? Any Ideas? Island Standard Solution Step 1: Find the top-left corner of each island. for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if(map[i][j] == 1) { //Step 2 //Step 3 //use a counter } } } Island Standard Solution Step 2: Find the width (and height) of that island. int position = i; while (map[position][j]==1) position++; //then how do you know the width of this island? Similar for height Island Standard Solution Step 3: How to avoid repeated count? Update the ‘1’s on the current island to be ‘0’s 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 Island Easy “Lazy” Solution Step 1: Find the top-left corner of each island, with a twist. 0 Look for this pattern: 0 1 Increment counter each time you see that pattern ? What if the “1” is on the left or top of the map? Island 1 1 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 1 1 Trick Island Technique Technique: Just add a row and column of ‘0’s to the map Such extra data are called sentinels. 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1 1 Island Technique Technique: Just add a row and column of ‘0’s to the map Such extra data are called sentinels. 0 0 0 0 0 0 0 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 count = 3 Island Our Sample Input Another Example (after adding a row and column of ‘0’s) (after adding a row and column of ‘0’s) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 count = 2 count = 3 Island Code Snippet for (int i = 1; i <= row; i++) {//why start from 1? for (int j = 1; j <= col; j++) { if (isTopLeftCornerOfAnIsland(map, i, j)) { count++; } } } boolean isTopLeftCornerOfAnIsland(int[][] map, int i, int j) { return map[i][j] == 1 && map[i-1][j] == 0 && map[i][j-1] == 0; } Island Problem 3 Find X Question Map is divided into RxC squares, (R rows, C columns) ‘Super X’ ◦ Square of size at least 3 ◦ Composed entirely by X on both diagonals. Find the number of ‘Super X’ in the grid Find X 25 Super X 7 X 6 X X X X 7 X X X X X X 6 X X X X X X X X X X X X X X 6 x 6 Super X 7 x 7 Super X Find X Is this a Super X? 9 X X X X X X 7 X X X X X X X X X X X X X X X X X X X X X Find X • • • • Square? At least size 3? All Xs on left diagonal? All Xs on right diagonal? Breakdown Read Input Calculate number of Super-X Print Output Find X Read Input 1st line contains two numbers R (no. of rows) and C (no. of columns) ◦ Use nextInt() Next R line contains C characters each. Each line represents one row in the treasure map. ◦ Read each row using nextLine() or next(); ◦ For loop that iterates C time Find X Store Map Option 1: ◦ String[] map = new String[R]; ◦ Each element of the array in the entire row ◦ Use String.charAt(c) to read each element in the row later Option 2: ◦ char[][] map = new char[R][C] ◦ Read entire row first (String row = sc.nextLine();) ◦ Use row.toCharArray() ◦ Break the row up into its separate elements as a char[] ◦ String[][] map will work too ◦ Use row.split(“”); Find X An array of character arrays? char[][] map = new char[R][C] new char[8][7]; 7 X X X X map[0] map[1] map[3][0] X X X X X X 8 X X map[2] map[3] X X map[4] X X map[5] X X map[6] map[7] map[7][4] Find X Input public static void main(String[] args) { //read input using Scanner Scanner = new Scanner(System.in); int R = sc.nextInt(); //number of rows int C = sc.nextInt(); //number of columns char[][] map = new char[R][C]; //initialise sc.nextLine(); //to move onto the next line //for each row for (int i = 0; i < numOfRows; i++) { String rowString = sc.nextLine(); map[i] = rowString.toCharArray(); } } Find X Output From question: ◦ The number of ‘super X’ in the map Just use the println() method to print the output Do not print other strings with the number ◦ E.g. “Number of Super X is: 4” public static void main(String[] args) { //read input using Scanner ….. int count = getNumOfSuperX(map); System.out.println(count); } Find X Breaking it down Find the number of squares with ‘Super X’ of size larger than 3 in the grid For all the squares of the different sizes in the grid ◦ Check whether it is a Super X For each size ◦ For each square in the grid of that size ◦ Check whether it is a super X Find X Incremental Programming Breaking the problem down into sub-problems Solve each of them separately Create a method that when given a square, will tell us if it is a super X Call that method for each of the square of each size later Find X From the centre X X X X X X X X X X X X X X X X X X Expand in all 4 directions Possible, but tricky Find X X X X X X X X Checking if a square is a super X Super X’ ◦ Square of size at least 3 ◦ Composed entirely by X on both diagonals. Check if both diagonals of a square are all Xs 7 X X X X 7 X X X X X X X X 6 X 6 X X X X X Find X X X X X X X X Checking if a square is a super X isSuperX method X X Parameters X X ◦ Top left corner X ◦ rowIndex of top left hand corner ◦ columnIndex of top left hand corner X X X ◦ size of square (number of elements in each row/col) X X Find X X X X X Checking if a square is a super X Iterate through both diagonals (from top left and from top right) Check if they are all Xs 2 methods ◦ isRightToLeftAllX ◦ isLeftToRightAllX Find X Checking if a square is a super X //Assume rowNum and colNum are within grid, rowNum + size – //1 and colNum + size – 1 are within grid boolean isSuperX(int rowNum, int colNum, int size) { //can put an if condition here that will return //false if the square is outside of the grid int leftCornerCol = colNum; int rightCornerCol = colNum + size – 1; int row = rowNum; return isLeftToRightAllX(leftCornerCol, row, size) && isRightToLeftAllX(rightCornerCol, row, size) Find X Iterating through the diagonal boolean isLeftToRightAllX(int x, int y, int size) { //for size times for (int i = 0; i < size; i++) { char currentElement = map[x][y]; if (currentElement != ‘X’) { return false; //stop evaluating } else { x += 1; //advance y += 1; } } return true; } Find X Hooray! Now we have our isSuperX method! ◦ Given the row and column of the top left hand corner ◦ We can check if it is a super X! :D Just call this method for ◦ All squares of each size ◦ Across different sizes Find X Iterate through all squares Assume fixed size of 3 Iterate through the top left corner of each square Pseudocode here -> try to work it out yourself! int int int for size = 3; //assume size 3 R, int C; //from earlier count; row = 0 -> R - size for col = 0 -> C – size //row & col: top left corner if isSuperX(row, col, size) increment count Find X Iterating through the sizes of square For loop! X Start and end? X X Smallest size of square X X X ◦3 X X X Largest size of square X ◦ min(numRows, numCols) X X Find X X X X X X X X X X X X X X X X Pseudocode maxSize = min(R, C); //for each size for size = 3 -> maxSize: //for each row for row = 0 -> R - size //for each column in the row for col = 0 -> C – size //row & col: top left corner if isSuperX(row, col, size) increment count Find X Programming Style Pre-conditions and Post-conditions (5% of overall) Above every method ◦ ◦ ◦ ◦ Describe what method is used for Explain its parameters, and what it returns Pre-condition: conditions that must be met before algorithm is called Post-condition: conditions that must be met after algorithm is called Find X /** *Checks if the square in the map is a super X * *Pre-condition: rowNum and colNum are the row and *column of the top left hand corner of the square. *size is the width of the square. rowNum, colNum, *rowNum+size-1 and colNum+size-1 are within the map *Post-condition: Returns true if both diagonals of the square are X **/ boolean isSuperX(int rowNum, int colNum, int size) { …. } Find X Programming Style (for Sit-In Labs) Meaningful comments to explain how your algorithm works ◦ Iterating through the centre of the square? ◦ Iterating through the top left corner of the square? Don’t just use 1 main method ◦ Incremental programming ◦ Solve each sub-problem one at a time in a separate method Meaningful variables ◦ Only use single characters for variables given in the input format or for loop variables Find X In summary Spend some time understanding and formulating your approach to the problem Break down the main problem into sub-problems ◦ Iterating through different sizes ◦ Iterating through the squares of each size ◦ Check if square is a super X Try to understand what the definition is ◦ What exactly is a super X? ◦ A square with both diagonals of only X Find X End Of File Any Questions?