Download number-1

Document related concepts
no text concepts found
Transcript
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;
}