Solution #3

Flow control

# Section 3.1 (warmup)

## 3.1.1

1.       Prints all the divisors of a positive number larger than 2.

2.       Variables:

a.       n: the number to find the divisors of. New name: number.

b.      c: the current candidate to be the number’s divisor. New name: currentDivisor.

3.       Improvements:

a.       Loop only until n/2.

## 3.1.2

1.       Reverses a String line.

2.       Variables:

a.       is: the input scanner. New name: inputScanner.

b.      l: the input line. New name: inputLine.

3.       Improvements:

a.       There can be no solution that is more time efficient than the original code. If the issue bothered you through the nights, if you Googled it, asked friends and read about reversing a String, then you most probably understand now all the issues around effective String reversing. This is good.

b.      Of course, a fast way to code it would be using String.reverse(), but that’s more efficient only to the coders, not in algorithm efficiency terms.

## 3.1.3

1.       The algorithm calculates a*b for non-negative a and b.

2.       Variables:

a.       a: the first number. New name: multiplicand.

b.      b: the second number. New name: multiplier.

3.       Improvements:

a.       Print a*b

## 3.1.4

1.       The algorithm prints all the prime numbers between 2 and 100.

2.       Variables:

a.       cn: the current candidate of a prime number. New name: primeNumber.

b.      ip: a flag, indicating whether the number is prime or not. New name: isPrime.

c.       pn: a current divisor of cn. If such divisor exists, the number is not prime. New name: currentDivisor

3.       improvements:

a.       The outer loop should skip all even numbers by replacing cn++ with cn += 2.

b.      The internal loop should run only until the square root of cn.

# Section 3.2 (TextEncryption.java)

## Without bonus

/**

* This class encrypts text.

*

* @author Boaz Kantor

*/

public class TextEncryption {

/**

* This program takes a given String, source & destination characters, and

* encrypts the String by replacing each occurrence of the source character

* with the target character.

* This is a case sensitive version.

* @param args unused

*/

public static void main(String[] args) {

// local variables

char replace = 'o';

char replaceWith = '*';

String originalSentence = "The quick brown fox jumps over the lazy dog";

String newSentence = "";

// iterate through all the sentence characters

for (int currChar = 0; currChar < originalSentence.length(); ++currChar) {

// case insensitive comparison

if (originalSentence.charAt(currChar) == replace) {   // it’s acceptable to keep the char in a variable

// the character fits, add to the new sentence the encrypted char

newSentence += replaceWith;

} else {

// the character doesn't fit, just copy it as is to the target String

newSentence += originalSentence.charAt(currChar);

}

}

// print the encryption output

System.out.println("Original sentence: " + originalSentence);

System.out.println("Encrypted sentence: " + newSentence);

}

}

## With bonus

/**

* This class encrypts text.

*

* @author Boaz Kantor

*/

public class TextEncryption {

/**

* This program takes a given String, source & destination characters, and

* encrypts the String by replacing each occurrence of the source character

* with the target character.

* This is a case insensitive version.

* @param args unused

*/

public static void main(String[] args) {

// local variables

char replace = 'o';

char replaceWith = '*';

String originalSentence = "The quick brown fox jumps over the lazy dog";

String newSentence = "";

char smallReplace = replace;  // this is the small version of the char

char capitalReplace = replace;      // this is the capital version

// make sure we keep both small and capital versions of the character

if (replace >= 'a' && replace <= 'z') {

// the source character is small, set the capital one

capitalReplace = (char)(replace - ('a' - 'A'));

} else {

// the source character is capital, set the small one

smallReplace = (char)(replace + ('a' - 'A'));

}

// iterate through all the sentence characters

for (int currChar = 0; currChar < originalSentence.length(); ++currChar) {

// case insensitive comparison

if (originalSentence.charAt(currChar) == smallReplace ||

originalSentence.charAt(currChar) == capitalReplace) {

// the character fits, add to the new sentence the encrypted char

newSentence += replaceWith;

} else {

// the character doesn't fit, just copy it as is to the target String

newSentence += originalSentence.charAt(currChar);

}

}

// print the encryption output

System.out.println("Original sentence: " + originalSentence);

System.out.println("Encrypted sentence: " + newSentence);

}

}

# Section 3.2 (TurtlePolygons.java)

## Without bonus

/**

* This class is intended to practice loops with visible results using the turtle.

* The turtle in the program draws polygons of different sides.

* Each polygon with X sides is drawn inside (smaller than) the polygon

* with X+1 sides.

*

* @author Boaz Kantor

*/

public class TurtlePolygons {

/**

* The program runs here. See the class documentation for details.

* @param args unused

*/

public static void main(String[] args) {

// constants

final int MAXIMUM_SIDES = 15;

final int MINIMUM_SIDES = 3;

final double FULL_CIRCLE = 360;

final int RIGHT_ANGLE = 90;

final double BASIC_SIDE_LENGTH = 50;

final double SIDE_LENGTH_FACTOR = 50;

// local variables

double sideLength = BASIC_SIDE_LENGTH;

double angle = 0;

// instantiate and prepare our turtle

Turtle turtle = new Turtle();

turtle.tailDown();

turtle.turnLeft(RIGHT_ANGLE);

// each iteration draws an entire polygon

for (int sides = MINIMUM_SIDES; sides <= MAXIMUM_SIDES; sides++) {

// calculate polygon-specific metrics

sideLength += SIDE_LENGTH_FACTOR;

angle = FULL_CIRCLE / sides;

// draw the polygon. each iteration draws one side

for (int currSide = 0; currSide < sides; ++currSide) {

turtle.moveForward(sideLength);

turtle.setAngle(turtle.getAngle() - angle); // use this for

// better accuracy

}

}

// yeah, that's important too.

turtle.hide();

}

}

## With bonus

/**

* This class is intended to practice loops with visible results using the turtle.

* The turtle in the program draws polygons of different sides.

* Each polygon with X sides is drawn inside (smaller than) the polygon

* with X+1 sides.

*

* @author Boaz Kantor

*/

public class TurtlePolygons {

/**

* The program runs here. See the class documentation for details.

* @param args unused

*/

public static void main(String[] args) {

// constants

final int MAXIMUM_SIDES = 35;

final int MINIMUM_SIDES = 3;

final double FULL_CIRCLE = 360;

final int RIGHT_ANGLE = 90;

final double BASIC_SIDE_LENGTH = 50;

/** The following constants are needed only for the bonus */

final double MAX_HEIGHT = 600;

final double MIN_HEIGHT = 200;

final double HEIGHT_DIFF = (MAX_HEIGHT-MIN_HEIGHT)/

(MAXIMUM_SIDES - MINIMUM_SIDES);

// instantiate and prepare our turtle

Turtle turtle = new Turtle();

turtle.tailDown();

turtle.turnLeft(RIGHT_ANGLE);

/** This is needed only for the bonus */

double factor = Math.sqrt(3)/2;

// each iteration draws an entire polygon

for (int sides = MINIMUM_SIDES; sides <= MAXIMUM_SIDES; sides++) {

// calculate polygon-specific metrics

double height = MIN_HEIGHT + (HEIGHT_DIFF * (sides-MINIMUM_SIDES));

double trianglesInHeight = sides / 2.0;

double sideLength = height / (factor * trianglesInHeight);

double angle = FULL_CIRCLE / sides;

// handle square and triangle separately

// all the literals here should have been declared as constants.

if (sides < 5) {

if (sides == 3) {

sideLength = 50;

} else {

sideLength = 100;

}

}

// draw the polygon. each iteration draws one side

for (int currSide = 0; currSide < sides; ++currSide) {

turtle.moveForward(sideLength);

turtle.setAngle(turtle.getAngle() - angle); // use this for

// better accuracy

}

}

// yeah, that's important too.

turtle.hide();

}

}

# Section 3.4 (TheMillionShekelDrop.java)

import java.util.Scanner;

import McqTrivia.Questionnaire;

/**

* The Million Shekel Drop program is based on the UK show

* "The Million Dollar Pound Drop".

* The player is given 1,000,000 Shekels in cash at the beginning.

* From now on, the player is asked 8 questions and given 4 answers, only one

* of which is correct.

* The player has to bet on an answer, or split his bet on several answers.

* When the bet is made, the correct answer is checked, and then 2 things happen:

* The cash left on incorrect answers is dropped (and lost).

* The cash on the correct answer is given back to the player.

* At any stage, if the player is left with no cash, they lose the game and go home.

* After 8 questions, the player can go home with the amount of cash left in

* their hands.

*

* @author Boaz Kantor

*/

public class TheMillionShekelDrop {

/**

* This method runs the entire game.

* See the class documentation for game details.

* @param args unused

*/

public static void main(String[] args) {

final int INITIAL_CASH = 1000000;

final String MCQ_FILENAME = "mcq.txt";

final int NUMBER_OF_QUESTIONS_TO_WIN = 8;

final int NUMBER_OF_ANSWER_CHOICES = 4;

// create and initialize the game object

Questionnaire game = new Questionnaire();

game.init(MCQ_FILENAME);

// some useful variables

int cash = INITIAL_CASH;

Scanner inputScanner = new Scanner(System.in);

// printing some welcoming messages

System.out.println("The Million Shekel Drop!");

System.out.println("You have " + cash + " shekels.");

System.out.println("The cash that you have at hand after " +

NUMBER_OF_QUESTIONS_TO_WIN + " consecutive " +

"correct answers is yours!");

// run the game for 8 questions or until cash is over

for (int currQuestion = 0;

currQuestion < NUMBER_OF_QUESTIONS_TO_WIN && cash > 0;

currQuestion++) {

// make sure the player understands where they stand

System.out.println("You now have " + cash + " shekels.");

// if the MCQ file has too few questions, end the game

if (!game.hasMoreQuestions()) {

System.out.println("Sorry, we have no more questions left.");

System.out.println("You can leave with your " + cash + " shekels.");

break;

}

// start handling the next question

System.out.println("Next question: ");

game.printNextRandomQuestion();

int cashWon = 0;

// handle each answer separately

for (int currAnswer = 0;

currAnswer < NUMBER_OF_ANSWER_CHOICES && cash > 0;

// let the player bet on the current answer

System.out.print("How much money would do you put on answer " +

(char)('A' + currAnswer) + " (0-");

System.out.print(cash + "): ");

int userBet = 0;

// get the player bet for the current answer

if (currAnswer == NUMBER_OF_ANSWER_CHOICES - 1) {

// the player must bet on all their money in each question

userBet = cash;

System.out.println(userBet + " (automatic)");

} else {

// the player can choose how much to bet on this answer

userBet = inputScanner.nextInt();

// verify that the bet is valid

while (userBet < 0 || userBet > cash) {

System.out.println("You don't have that amount of cash.");

System.out.print("How much money would do you put on answer " +

(char)('A' + currAnswer) + " (0-");

System.out.print(cash + "): ");

userBet = inputScanner.nextInt();

}

}

// we're only interested on the correct answer

cashWon = userBet;

}

cash -= userBet;

}

// no more bets! let's check the correct answer..

System.out.println("The correct answer is: " +

cash = cashWon;

// check if the player has lost the game

if (cash == 0) {

System.out.println("You have no more cash left. You lose.");

}

}

// game over, print a goodbye message

System.out.println("You are going home with " + cash + " shekels.");

System.out.println("Bye!");

}

}