# Week 3 Main Lecturer: Ayaan Siddiqui ## If/Else Statements The if/else statement executes a block of code if a specified condition is true. If the condition is false, another block of code can be executed. Here is the basic skeleton of an if/else condition statement. ```java= if(condition){ //if the condition is true doSomething1(); //execute this block of code doSomething2(); } else { // if condition is false doSomethingElse1(); //execute this other block of code doSomethingElse2(); } ``` What if you want to check for multiple conditions? For that you can use `else if` statements ``` java= if(condition_1){ //if condition 1 is true doThing1(); //execute this block of code } else if (condition_2){ //if condition 2 is true doThing2(); //execute second block of code } else { // if both the conditions are false doThing3(); //execute third block of code } ``` You can actually have as many `else if` statements as you need after the first `if` block, which would leave you with an `if` statement, one or more `else if` statements, and also possibly a final `else` statement. Starting with the first `if` statement, and then the `else if` statements, the program evaluates all the conditionals in order until it reaches one that evaluates to true. The code inside that block is executed, and then the program skips the rests of the conditional blocks. If none of the conditional statements in the `if` or `else if` blocks are true, then the code in the final `else` statement is executed. Now let's take a look at some example code involving an if/else statement: ```java= import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); // Do you remember the Scanner class from last week? String s1 = input.nextLine(); if (s1.equals("Strings are immutable")) { System.out.println("Correct"); } else if (s1.equals("Strings cannot be changed after initialization")) { System.out.println("Correct but there is a better word for that"); } else { System.out.println("Incorrect"); System.out.println("Please try again!"); } } } ``` When if/else statements are combined with loops (more on this later), they can create quite tricky and complicated algorithms. ## More Advanced Logic We already know the basics of booleans, and it seems as if they are even more important now than they were before! If you recall, booleans are true or false values. We actually encounter lots of true or false values in the "real world," such as "I mowed the lawn" or "I committed a felony[^1]." However, it is also extremely common to say things like, "Did you mow the lawn yesterday *or* did you commit a felony?" Luckily, in Java, we can also do more complicated statements like that as well. ### `&&` (And) The && operator evaluates to true only if the statements on **both** sides of it evaluate to true. If the letter `A` represents the statement "Today I ate ice cream" and the letter `B` represents "Today I touched grass", the statement `A && B` only evaluates to true if today I **both** ate ice cream **and** touched grass. If either (or both) of those are false, then the And statement evaluates to false (unfortunately for me it would evaluate to false). ### `||` (Or) The || operator (those are the symbols used for absolute value) evaluates to true if **at least one** the statements on either side of it evaluate to true. Using the same representation as before, the statement `A || B` evaluates to true if today I **either** ate ice cream **or** touched grass, **or both**. If both of those are false, then the Or statement evaluates to false (unfortunately for me it still evaluates to false). ### `!` (Not) The ! operator is attached to the beginning of the boolean and **switches its value**. `!A` would represent the statement "Today I did not eat ice cream". `!B` would represent "Today I did not touch grass". `!A && B` represents "Today I did not eat ice cream and today I touched grass". `!(A || B)` represents "Today I did not eat ice cream or touch grass" (stop calling me out). ### `^` (Xor, exclusive Or) The ^ operator evaluates to true if only one of the statements on either side of it evaluates to true. `A ^ B` would evaluate to true only if **either** today I ate ice cream **or** touched grass, **but not both**. ```java= boolean a = false; boolean b = true; System.out.println(a && b); // false System.out.println(a || b); // true System.out.println(a ^ b); // true a = true System.out.println(a && b); // true System.out.println(a || b); // true System.out.println(a ^ b); // false a = false; b = false; System.out.println(!a && !b); // true System.out.println(a || b); // false System.out.println(a ^ b); // false ``` While we are working with logic, let's review comparison operators (these work best with numerical values like `int `s and `double`s, but evaluate to booleans): ### `==` (Equal to) and `!=` (Not equal) A `==` evaluates to true if the expression on the left has the same value as the expression on the right. A `!=` expression evaluates to true if they do not have the same value. * `1 == 1` evaluates to true, `1 != 1` evaluates to false * `1 == 2` evaluates to false, `1 != 2` evaluates to true * `1 + 1 == 2` evaluates to true, `1 + 1 != 2` evaluates to false ### `>` (Greater than) and `<` (Less than) A `>` expression evaluates to true if the expression on the left has a greater value than the expression on the right, while a `<` expression evaluates to true if the left expression has a lesser value than the right expression. * `1 > 2` evaluates to false, `1 < 2` evaluates to true * `2 > 1 + 3` evaluates to false, `2 < 1 + 3` evaluates to false * `1 > 1` evaluates to false, `1 < 1` also evaluates to false ### `>=` (Greater than or Equal to) and `<=` (Less than or Equal to) The `>=` and `<=` are the same as the `>` and `<` operators respectively, except they both also evaluate to true if the expressions on both sides are equal. * `1 >= 2` evaluates to false, `1 <= 2` evaluates to true * `2 >= 1 + 3` evaluates to false, `2 <= 1 + 3` evaluates to false * `1 >= 1` evaluates to true, `1 <= 1` also evaluates to true ### Truth Tables Truth tables are used to organize complex boolean expressions. 0s represent `false` values and 1s represent `true` values. The first couple of columns represent individual boolean variables and all possible combinations of values, and the other columns represent the values of more complex boolean expressions for each combination of individual values. | a | b | !a | a && b | a \|\| b | !a && b | | --- | --- | -- | ------- | -------- | -------- | | 0 | 0 | 1 | 0 | 0 | 0 | | 0 | 1 | 1 | 0 | 1 | 1 | | 1 | 0 | 0 | 0 | 1 | 0 | | 1 | 1 | 0 | 1 | 1 | 0 | If you want to study the behavior of an ugly boolean expression like `(a || b) ^ (!a && b)` (which happens to be convenient using the above table), you can use a truth table to start with individual values and gradually increase the complexity of the expressions, working your way up to the one you want. | a | b | !a | a \|\| b | !a && b | (a \|\| b) ^ (!a && b) | | --- | --- | ---- | -------- | -------- | --------------------- | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 You might notice that our big expression matches the values of the 'a' variable; the expression only evaluates to true when 'a' is true. Therefore the expression `(a || b) ^ (!a && b) == a` will always evaluate to true. This also means that `(a || b) ^ (!a && b)` **implies** a is true, which can be written using an arrow: `(a || b) ^ (!a && b) -> a`. Truth tables can be quite cumbersome though. The more efficient way to simplify boolean expressions is using boolean algebra. There are a handful of boolean algebra laws, and a few of them can be discovered using simple reasoning. However, one of the trickier but more useful set of laws is called **DeMorgan's Laws**. 1. `!(A && B) == !A || !B` 2. `!(A || B) == !A && !B` These may seem strange, but upon deeper thought are actually somewhat intuitive. The english representation of the first one is "If it is false that both A and B are true, then at least one of them must be false". The second one is "If it is false that either A or B is true, then they must both be false". [^1]: It should be obvious which statement is true and which is false. ## Loops What if you wanted to say "hi" a thousand times? Maybe we could type out `System.out.println("hi")` a thousand times but that would get very annoying very quickly. A better alternative approach would be to use a **loop**. ```java= // ...enclosing code System.out.println("hi"); System.out.println("hi"); System.out.println("hi"); System.out.println("hi"); System.out.println("hi"); System.out.println("hi"); System.out.println("hi"); System.out.println("hi"); System.out.println("hi"); System.out.println("hi"); // enclosing code... ``` There are three (or four, depending on who you ask) different types of loops in Java, though we will only go over the two most commonly used ones, `for` loops and `while` loops. ### `while` loops The general format for a `while` loop is: ```java= while (condition) { // This is the body. Inside the body, we can do things... } ``` The `condition` is simply a `boolean` value, something that evaluates to `true` or `false`. The `while` loop runs the code inside the body *while* the condition is met. For example: ```java= public class Main { public static void main(String[] args) { System.out.println("I am going to flip some coins!"); while (coinflip()) { System.out.println("I got a heads!"); } System.out.println("I'm done."); } // Return true or false (50/50 chance) public boolean coinflip() { return Math.random() < 0.5; } } ``` ### `for` loops The general format for a `for` loop is: ```java= for (initialization; condition; update) { // This is the loop body. } ``` An `iteration` is each time that that a loop runs. Each time we finish an iteration in a `for` loop, it continues with the next iteration. The initialization runs **once** during the `for` loop, before the first iteration of the loop. This generally initializes a "counter" variable to keep track of where we are in the loop. The condition is extremely similar to the condition in the while loop; before starting each iteration, it checks if the condition is true. We can use the counter variable in this. The update is run directly after each iteration of the loop. Generally, this increments the counter variable. An example of a program with a `for` loop is: ```java= public class Main { public static void main(String[] args) { for (int i = 0; i < 1000; i++) { System.out.println("hi"); } } } ``` This prints out "hi" 1000 times, our initial goal! ### Week 3 Assignment Write a program that prints all integers from 1-100 that are divisible by 2 or 3, but not by 6, unless it is divisible by 18.