Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
IntroCsp – Tirgul 6 Command Line Arguments The main method takes a String[] as a parameter. public static void main(String[] args) The contents come from the command line that called the program: java HelloCommandLine how are you 0 1 2 “how” “are” “you” args 2 Example: public class HelloCommandLine { public static void main(String[] args){ System.out.println("There are " + args.length + “ arguments"); System.out.println("They are:"); for(int i=0; i<args.length; i++){ System.out.println(args[i]); } } } 3 The Keyword this Non-static methods can only be used on an object The keyword this (when inside a method) refers to the object the method was called on. Account myAccount = new Account(); myAccount.deposit(50); public void deposit(int amount){ this.amount = this.amount + amount; } Example for using this The keyword this can be used to pass the current object as an argument, or to return it. E.g., bank.addAccount(this); return this; Yet another usage for the word this is to invoke a constructor from within another constructor of the same class. Must be done in the first line of the calling constructor. Nested Loops Powers Table We would like to calculate the non-negative powers of the positive integers Notice that there’s a difference between positives and non-negatives Positives integers are 1,2,3, … Non-negatives are 0,1,2,3,… Calculating the powers of a single integer is easy, as demonstrated in 2 more slides We are not going to use Math.pow() 7 PowersPrinter Ctor //this class prints a powers table for the numbers 1-_highestNumber and powers 0-_highestPower public class PowersPrinter { //consts private static final int DEFAULT_HIGHEST_NUMBER = 5; private static final int DEFAULT_HIGHEST_POWER = 2; //members private int highestNumber; private int highestPower; Default highest number, power to which the table is generated //ctor Highest number, power to public PowersPrinter(int highestNumber, int highestPower) { which the table is generated //sets _highestNumber if (highestNumber <= 0) { System.err.println("highest number must be positive. set to default value"); this.highestNumber = DEFAULT_HIGHEST_NUMBER; } else { this.highestNumber = highestNumber; } } //sets _highestPower if (highestPower < 0) { System.err.println("highest power must be non-negative. set to default value"); this.highestPower = DEFAULT_HIGHEST_POWER; } else { this.highestPower = highestPower; } 8 PowersPrinter – Table & Rows //prints a full table public void printTable() { } Prints a full powers table in a topdown design style. The table consists of single rows //prints table rows in a loop for (int i = 1; i <= highestNumber; i++) { printRow(i); } //prints a single row private void printRow(int rowNumber) { //prints rowNumber's powers by calling calcPower for (int j = 0; j <= highestPower; j ++) { System.out.print(calcPower(rowNumber, j) + "\t"); } } Prints a single row in a top-down design style. The row consists of single power elements System.out.println(""); 9 PowersPrinter – A Single Power private long calcPower(int number, int power) { /* Assumptions: 1) number is positive 2) power is non-negative */ //power of 0 long result = 1; Since calcPower() is a private method, it’s the programmer’s responsibility to provide this method the right arguments Follows the mathematical definition of the power function. //multiply current result by number - power times for (int i = 1; i <= power; i++) { result *= number; } } return result; long is another type, very similar to int but capable of representing larger numbers 10 PowersPrinter – Main public static void main(String[] argv) { argv is a Strings array and has a length member //verify that 2 arguments were given if (argv.length < 2) { System.err.println("\nUSAGE: java PowersPrinter <highest-number>" + " <highest-power>\n"); System.exit(-1); If the user types The whole program terminates with } non-integer arguments, java exit code of -1 on System.exit(will throw 1) //get user arguments - assuming legal argument types NumberFormatException during runtime. int userHighestNumber = Integer.parseInt(argv[0]); int userHighestPower = Integer.parseInt(argv[1]); … 11 PowersPrinter – Main (2) … //create an instance of PowersPrinter PowersPrinter pp = new PowersPrinter(userHighestNumber, userHighestPower); } //prints the full table System.out.println("\nFull table "); pp.printTable(); 12 PowersPrinter - Analysis Invoking “java PowersPrinter 3 4” generates the following output : Full table 1 1 1 2 1 3 1 4 9 1 8 27 1 16 81 How many multiplications costs the 2nd row (for example) 1 takes 0 multiplications 2 takes 1 (2 = 1 * 2) 4 takes 2 (4 = 1 * 2 * 2) 8 takes 3 (8 = 1 * 2 * 2 * 2) Total number of multiplications needed for a row of 5 elements is : 13 1+ 2 + 3 + 4 =10 !!! PowersPrinter2 – A Lighter Version public void printRow(int rowNumber) { //set first number to 1 (0 power) long number = 1; This is the only method of PowersPrinter2 different from its corresponding method in PowersPrinter //prints rowNumber's powers by multiplying number by rowNumber for (int j = 0; j <= highestPower; j ++) { System.out.print(number + "\t"); number *= rowNumber; } Instead of invoking calcPower() } System.out.println(""); Conclusion : Top-down design isn’t always better implements the power calculation algorithm originally placed in printRow() Now, a row of N elements takes N-1 multiplications 14 PowersPrinter3 – Nested Loops public void printTable() { } for (int i = 1; i <= highestNumber; i++) { printRow(i); } public void printTableWithNestedLoops() { } //prints table rows in a loop long number; for (int i = 1; i <= highestNumber; i++) { //single row number = 1; for (int j = 0; j <= highestPower; j ++) { System.out.print(number + "\t"); number *= i; } System.out.println(""); } public void printRow(int rowNumber) { long number = 1; for (int j = 0; j <= _highestPower; j ++) { System.out.print(number + "\t"); number *= rowNumber; } System.out.println(""); } We separated number declaration from its assignment since it needs to be declared only once We multiply number by i which is equivalent to printRow’s rowNumber 15 argument PowersPrinter3 – Another Look public void printTableWithNestedLoops() { //prints table rows in a loop long number; Rows loop. The current row number is currentRow Generally, i is a legal loop variable name. But renaming it as currentRow makes the code more readable for (int currentRow = 1; currentRow <= _highestNumber; currentRow++) { //inside a specific row number = 1; Actually, we could have left number’s {declaration + assignment} attached, but it’s really unnecessary (re-declaring it again and again) } } for (int currentPow = 0; currentPow <= _highestPower; currentPow ++) { System.out.print(number + "\t"); number *= currentRow; } Powers loop. System.out.println(""); The current power number is currentPow. This power too refers to the current row currentRow 16 Nested Loops 2D Arrays Nested Loops 2D Arrays What if we know, we’ll need later to check some powers (within bounds), and The most important thing is the easy / quick access to the power results We wouldn’t like to scan the whole table for the right cell Nor would we like to recalculate the results every time We are willing to “pay” in memory pre-calculate once the whole table, and store it (cache) 18 PowersTable Class public class PowersTable { //original consts private static final int DEFAULT_HIGHEST_NUMBER = 5; private static final int DEFAULT_HIGHEST_POWER = 2; //original members private int highestNumber; private int highestPower; //new const + member private static final long ILLEGAL_INDICES_ELEMENT = -1; private long[ ][ ] table; Same members & constants as in PowerPrinter //ctor public PowersTable(int highestNumber, int highestPower) { … } 19 PowersTable - Constructor public class PowersTable { … //ctor public PowersTable(int highestNumber, int highestPower) { //sets _highestNumber if (highestNumber <= 0) { System.err.println("Highest number must be positive. set to default value"); this.highestNumber = DEFAULT_HIGHEST_NUMBER; } else { this.highestNumber = highestNumber;} //sets _highestPower if (highestPower < 0) { System.err.println("Highest power must be non-negative. set to default value"); this.highestPower = DEFAULT_HIGHEST_POWER; } else { this.highestPower = highestPower; } } //allocates and fills the table createTable(); This is the only new line 20 PowersTable – createTable This method is intended for internal use only (it is not part of the API) private void createTable(){ There’re _highestNumber numbers – [1,…, _highestNumber]. There’re _highestPower +1 powers – [0, …, _highestPower] //allocates the table table = new long[highestNumber][highestPower + 1]; //fills the rows’ entries in a loop for (int i = 1; i <= highestNumber; i++) { fillRow(table[i-1], i); } } We would like to fill the i-th row of _table (which index is i-1) with the powers of the number i 21 Heap Diagram 0 1 Powers’ array are allocated one after the other 2 3 4 Rows’ array is allocated When an object (e.g. PowersTable) is constructed, it is kept in the heap 0 0 0 0 0 1 2 3 0 0 0 0 0 1 2 3 0 0 0 0 0 1 2 3 5 highestNumber 0 0 0 0 3 highestPower 0 1 2 3 0 0 0 0 0 1 2 3 22 table The entries of the long arrays are initialized with 0 – the default long value PowersTable - fillRow private void fillRow(long[] row, int rowNumber) { //power of 0 long number = 1; } fillRow() doesn’t know and doesn’t care that the parameter row is only a single row belongs to a 2D array //other powers - multiply number by rowNumber for (int j = 0; j < row.length; j ++) { row[j] = number; number *= rowNumber; We could have used } (_highestPower + 1) instead of row.length, since there’re _highestPower+1 powers in every row – [0, …, _highestPower] 23 What Just Happened Here? table is created in createTable table[i-1] is sent as fillRow’s argument createTable() is about to invoke filleRow(table[1], 2) row is created as a parameter of table[i-1] according to call by value concept Heap Stack (createTable) Stack (fillRow) table = 87a9f5d i=2 row = 5a76bfc table[i -1] = 5a76bfc row.length = 4 number = 1 j=0 Power of 0 number = … Loop begins table[i-1] values were updated !!! 0 1 0 2 0 4 0 8 0 1 2 3 24 PowersTable – Printing A Table public void printTableWithNestedLoops() { //prints table rows in a loop for (int currentNumber = 1; currentNumber <= highestNumber; currentNumber ++) { //single row – loops over the powers for (int currentPower=0; currentPower<=highestPower; currentPower++) { Simple internal access to _table indices System.out.print(table[currentNumber -1][currentPower] + "\t"); } } } System.out.println(""); 25 PowersTable - calcPower public long calcPower(int number, int power) { //verify that number is in bounds if ((number < 1) || (number > highestNumber)){ System.err.println("number out of bounds"); return ILLEGAL_INDICES_ELEMENT; } External access to the powers table within //verify that power is in bounds if ((power < 0) || (power > highestPower)) { System.err.println("power out of bounds"); return ILLEGAL_INDICES_ELEMENT; } } return table[number - 1][power]; Row number-1 contains the powers of number 26 PowersTable - Main public static void main(String[] argv) { //verify that 2 arguments were given if (argv.length < 2) { System.err.println("\nUSAGE: java PowersTable <max-number> <max-power>\n"); System.exit(-1); } PowersTable has no static //get user arguments - assuming legal argument types methods and an instance must be int userHighestNumber = Integer.parseInt(argv[0]); constructed int userHighestPower = Integer.parseInt(argv[1]); //create an instance of PowersTable PowersTable pp = new PowersTable(userHighestNumber, userHighestPower); //prints the full table System.out.println("\nFull table "); pp.printTableWithNestedLoops(); } //prints a single power System.out.println("\nThe " + userHighestPower + "-th power of “ + userHighestNumber + " is : " + pp.calcPower(userHighestNumber, userHighestPower)); 27 2D Arrays as Arrays of Arrays Days Class This class will be used by another class named Calendar public class Day { //consts public static final public static final public static final public static final int NOON = 4; //work hours till noon int MAX_HOURS_AFTERNOON = 5; boolean WORK = true; boolean DAY_OFF = false; //members private boolean workOrNot; private int nWorkHours; //ctor public Day(boolean workOrNot, int nWorkHours) { this.workOrNot = workOrNot; this.nWorkHours = nWorkHours; } //getters public boolean isWorkDay() { return this.workOrNot;} public int getWorkHours() { return this.nWorkHours; } public void setWorkHours(int nWorkHours ) { this.nWorkHours = nWorkHous; } 29 Day Class (2) //copy ctor public Day(Day other) { this(other.workOrNot, other.nWorkHours); } Day is a mutable object and as many other mutable objects it has a copy constructor 30 Calendar Class import java.util.Random; You’ll need this import to use Random Notice the initialization list of this constant array public class Calendar { //consts private static final int DAYS_IN_YEAR = 365; private static final int[ ] MONTH_DAYS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; private static final int N_MONTHS = MONTH_DAYS.length; //Days table private Day[][] days; 2D array of Day objects //ctor public Calendar(int nMaxDaysOff) { Notice that this constant value is determined by the previous constant array length days = new Day[N_MONTHS][]; //allocates months //create a random generator from the current time Random rand = new Random(System.currentTimeMillis()); } } … Since the minor arrays (every month days) are of different length, we need 2-stages allocation. First we have to allocate the major array (12 months) Random object allows us to add randomization to our code. It has to be initialized with 31 a “seed” (usually we’ll use the current system time) Calendar – Ctor Continues int nDaysOffTakenSoFar = 0; //months loop for (int i = 0; i < N_MONTHS ; i ++) { Nested loops again _days[i] is allocated and can contain MONTH_DAYS[i] objects of Day //allocate current month days days[i] = new Day[MONTH_DAYS[i]]; Notice that the inner loop bounds days[i].length depend on the outer loop index i //if there are some days off left - flip a coin to choose work/vacation if ((nDaysOffTakenSoFar < nMaxDaysOff) && (rand.nextInt(DAYS_IN_YEAR) < nMaxDaysOff)) { //vacation days[i][j] = new Day(Day.DAY_OFF, 0); nDaysOffTakenSoFar ++; rand.nextInt(n) returns a random } integer x, such that else { //work day – flip a coin to choose number of working hours 0 <= x < n days[i][j]= new Day(Day.WORK,Day.NOON+rand.nextInt(Day.MAX_HOURS_AFTERNOON)); } //days loop - set each day to work / holiday for (int j = 0; j < days[i].length ; j ++) { } } 32 Calendar Class – printData() Nested loops public void printData() { //months loop for (int i = 0; i < days.length; i ++) { Invoking the method //days loop isWorkDay() of Day object on for (int j = 0; j < days[i].length; j ++) { the specific Day object //prints date _days[i][j] System.out.print((j+1) + "." + (i+1)(; if (days[i][j].isWorkDay()) { System.out.println(": Work hours " + _days[i][j].getWorkHours()); } else { System.out.println (": Staying home (-:"); } } } } //main public static void main(String[] argv) { Calendar cal = new Calendar(30); cal.printData(); } Maximal number of vacation days is 30 33 Calendar - getCalendar public Day[][] getCalendar() { return days; } This method returns a 2D-object array public Day[][] getCalendar() { Day[][] copy = days.clone(); } Return copy; public Day[][] getCalendar() { //allocates major array (months) Day[][] copy = new Day[days.length][]; //months loop for (int currMonth = 0; currMonth < copy.length; currMonth ++) { //allocates inner array (days) copy[currMonth] = days[currMonth].clone(); } return copy; } 34 Calendar - getCalendar public Day[][] getCalendar() { //allocates major array (months) Day[][] copy = new Day[days.length][]; This method returns a 2D-object array //months loop for (int currMonth = 0; currMonth < copy.length; currMonth ++) { //allocates inner array (days) copy[currMonth] = new Day[days[currMonth].length]; } } //days loop for (int currDay = 0; currDay < copy[currMonth].length; currDay++){ //copy the specific day copy[currMonth][currDay] = new Day(days[currMonth][currDay]); } return copy; 35 Heap Diagram Arrays for days of each month are allocated days[1] 0 0 0 …… 0 0 … 0 0 1 …. .. 11 0 30 0 27 days[1][27] Month’ array is allocated _days[] 0 0 1 2 3 0 0 0 0 0 ….. 3036 Compressed Strings Let’s build a String class that efficiently represents strings that have many repeating characters. E.g., “aaaabbbbbfffgggggttttttt” We’ll make our class immutable Have several constructors and methods such as: toString, append, … We’ll use “Run Length Encoding”. 37 Compressed Strings public class CompressedString { private char[] chars; private int[] freq; Will hold the characters And how many times they appear public String toString(){ String result = ""; for(int i=0; i<chars.length; i++){ for(int j=0; j<freq[i]; j++){ result += chars[i]; } } return result; } … To decode the String: Add each character to the string several times } 38 Compressed Strings – The First Constructor public CompressedString(char[] string){ int compressedLength=string.length; for(int i=1; i<string.length; i++){ if(string[i]==string[i-1]) compressedLength -= 1; } chars = new char[compressedLength]; freq = new int[compressedLength]; Find out the length of the String after it is compressed Allocate memory accordingly int index=0; for(int i=0; i<chars.length;i++){ chars[i] = string[index]; Compress int nextIndex; String for(nextIndex=index; nextIndex<string.length && string[nextIndex]==string[index]; nextIndex++); freq[i] = nextIndex-index; index = nextIndex; } } the This method is quite long. It may be better to break it down to smaller pieces. 39 Compressed Strings public CompressedString(String str){ this(str.toCharArray()); } Call the constructor we already wrote… private CompressedString(char[] characters, int[] frequencies){ chars = characters; freq = frequencies; Notice } public CompressedString(CompressedString other){ this(other.chars,other.freq); } public int length(){ int result = 0; for(int i=0; i<freq.length; i++) result += freq[i]; return result; } the private constructor! What is that good for? A copy constructor that uses the private one. Why don’t we clone the arrays? Return the noncompressed length 40 Compressed Strings public CompressedString append(CompressedString other){ int size = other.chars.length+chars.length; if(chars[chars.length-1] == other.chars[0]) size--; char[] newChars = new char[size]; int[] newFreq = new int[size]; for(int i=0; i<_chars.length;i++){ newChars[i] = chars[i]; newFreq[i] = freq[i]; } Figure out the length of the new string Allocate the arrays for it Copy the first string for(int i=1; i<=other.chars.length; i++){ newChars[size-i] = other.chars[other.chars.length-i]; newFreq[size-i] += other.freq[other.chars.length-i]; } return new CompressedString(newChars,newFreq); } Then, copy the second one Here’s where we use the private constructor! 41 Sorting and Searching Linear Search //searching for an element e in an unsorted array public static int linearSearch(int[] intArr, int e){ for (inti= 0; i< intArr.length;i++){ if (intArr[i]==e) return i; } return -1; } //we need to check each and every element till we find e. //if e is not in the array we checked n elements // (n = array length) //if the array is sorted we know when to stop searching even if the element wasn’t found Linear search in a sorted array public static int linearSearch(int[] intArr, int e){ for (inti= 0; i< intArr.length;i++){ if (intArr[i]==e) { return i; } if (intArr[i] > e){ return -1; } } return -1; } Binary Search Binary search At the start, all of the stored values are unknown: ? ? ? ? ? ? ? ? ? ? ? ? ? look here first ? ? ? ? ? ? > > > > > > > still unknown look here second definitely too high look here next < < < ? ? ? > > > > > > > definitely too still unknown low definitely too high Termination When the lower and upper bounds of the unknown area pass each other, the unknown area is empty and we terminate (unless we’ve already found the value) Goal: Locate a value, or decide it isn’t there Intentional Bound: We’ve found the value Necessary Bound: The lower and upper bounds of our search pass each other Plan: Pick a component midway between the upper and lower bounds. Reset the lower or upper bound, as appropriate. The Binary Search Pseudocode initialize lower and upper to the lower and upper array bounds; do { set middle to (lower plus upper) / 2; if the value of data[middle] is lower set middle (plus 1) the new lower bound else set middle (minus 1) the new upper bound } while we find the value or run out of unknown data; decide why we left the loop, and return an appropriate position The Binary Search Java Code int binarySearch (int[ ] data, int num) { // Binary search for num in an ordered array int middle, lower = 0, upper = (data.length - 1); do { middle = ((lower + upper) / 2); if (num < data[middle]) upper = middle - 1; else lower = middle + 1; } while ( (data[middle] != num) && (lower <= upper) ); //Postcondition: if data[middle] isn't num, no // component is if (data[middle] == num) return middle; else return -1; } Linear Search //searching for an element e in an unsorted array public static int linearSearch(int[] intArr, int e){ for (inti= 0; i< intArr.length;i++){ if (intArr[i]==e) return i; } return -1; } //we need to check each and every element till we find e. //if e is not in the array we checked n elements // (n = array length) //if the array is sorted we know when to stop searching even if the element wasn’t found Linear search in a sorted array public static int linearSearch(int[] intArr, int e){ for (inti= 0; i< intArr.length;i++){ if (intArr[i]==e) { return i; } if (intArr[i] > e){ return -1; } } return -1; } Binary Search Binary search At the start, all of the stored values are unknown: ? ? ? ? ? ? ? ? ? ? ? ? ? look here first ? ? ? ? ? ? > > > > > > > still unknown look here second definitely too high look here next < < < ? ? ? > > > > > > > definitely too still unknown low definitely too high Termination When the lower and upper bounds of the unknown area pass each other, the unknown area is empty and we terminate (unless we’ve already found the value) Goal: Locate a value, or decide it isn’t there Intentional Bound: We’ve found the value Necessary Bound: The lower and upper bounds of our search pass each other Plan: Pick a component midway between the upper and lower bounds. Reset the lower or upper bound, as appropriate. The Binary Search Pseudocode initialize lower and upper to the lower and upper array bounds; do { set middle to (lower plus upper) / 2; if the value of data[middle] is lower set middle (plus 1) the new lower bound else set middle (minus 1) the new upper bound } while we find the value or run out of unknown data; decide why we left the loop, and return an appropriate position The Binary Search Java Code int binarySearch (int[ ] data, int num) { // Binary search for num in an ordered array int middle, lower = 0, upper = (data.length - 1); do { middle = ((lower + upper) / 2); if (num < data[middle]) upper = middle - 1; else lower = middle + 1; } while ( (data[middle] != num) && (lower <= upper) ); //Postcondition: if data[middle] isn't num, no // component is if (data[middle] == num) return middle; else return -1; }