teaching machines

CS 1: Lecture 18 – If Bifurcations and Ladders

October 18, 2017 by . Filed under cs1, cs145, cs148, fall 2017, lectures.

Dear students,

Last time we saw how we could introduce extra little diversions or sidesteps into our code. Some bit of code needs to get executed under certain conditions, so we embed it in an if. In other situations, we actually want to choose between two competing bits of code. I call this pattern a bifurcation, and it has this structure:

// pre work
if (booleanCondition) {
  // then work
} else {
  // else work
}
// post work

Only one of the two blocks will get executed. Let’s also see this pattern in some real contexts:

For our next example, let’s write an application that we all need from time a time: a restaurant chooser. We think we like choice, but when it comes time to make a decision, most of us would like to not have that responsibility. So, we will give that responsibility over to our app. However, we will exert some influence. We’ll decide how likely it is a certain restaurant will be picked. To make this happen, we will create what I called an if ladder, which looks like a series of choices. This is really just an extension of the if/else structure, which presents only two choices. But with some clever nesting and syntax tweaks, we get an n-way choice.

Also, you’re going to see folks write conditionals without curly braces. Like this:

if (i < 0)
  System.err.println("That's not enough.");

When a then- or else-block is only one statement long, the braces can be omitted. But I don’t recommend it. Consider this bit of code:

if (6 == 7)
  System.out.println("a");
  System.out.println("b");

Many corporate style guides mandate braces all the time, even when the block consists of only one statement. Google does.

Also, software developers are greatly tempted to overuse conditional statements. But they are not always the best choice. For one, they take up multiple lines, and when you get to a language where you start passing code around as parameters to methods, your code will become unreadable. For two, conditionals are statements, not expressions. They do not produce a usable value; they do something. Just like println. Sure, their blocks can assign a value to a variable, but that is not always going to work. If statements do not exist in every language. For three, if statements actually cause a bump in your program’s execution. Normally the processor is working on several instructions at once, getting the next ones ready while the current one is executing. In the case of an if, the computer can’t predict what the next instruction is. This is called a pipeline stall. For four, most excuses for writing ifs when they aren’t needed are pretty weasely: “This is the way I’ve always done it,” “This is how I think about it,” or “This is simpler.” Simple is a proxy for familiar. Anything is simple once you’re familiar with it.

Let’s see some examples of ifs that should not have been written:

public static boolean isEven(int x) {
  if (x % 2 == 0) {
    return true;
  } else {
    return false;
  }
}

This would be better written as:

public static boolean isEven(int x) {
  return x % 2 == 0;
}

How about this one?

public static boolean isDay(String s) {
  if (s.equals("Sunday")) {
    return true;
  } else if (s.equals("Monday")) {
    return true;
  } else if (s.equals("Tuesday")) {
    return true;
  } else if (s.equals("Wednesday")) {
    return true;
  } else if (s.equals("Thursday")) {
    return true;
  } else if (s.equals("Friday")) {
    return true;
  } else if (s.equals("Saturday")) {
    return true;
  } else {
    return false;
  }
}

Better to use ||! How about this one?

public static boolean isEdible(boolean isHealthy, int costInCents) {
  if (!isHealthy) {
    if (costInCents == 0) {
      return true;
    } else {
      return false;
    }
  } else {
    return true;
  }
}

How about this one?

public static boolean isIsosceles(double sideA, double sideB, double sideC) {
  if (Math.abs(a - b) < 0.0001) {
    if (Math.abs(b - c) < 0.0001) {
      return true;
    } else {
      return false;
    }
  } else {
    return false;
  }
}

How about this one?

public static boolean hasRepeatedLetter(String s) {
  if (s.length() < 2) {
    return false;
  } else {
    return s.charAt(0) == s.charAt(1);
  }
}

This would be better written as:

public static boolean hasRepeatedLetter(String s) {
  return s.length() >= 2 && s.charAt(0) == s.charAt(1);
}

Here’s your TODO list to complete before we meet again:

See you next class!

Sincerely,

P.S. It’s time for a haiku!

A fork in the roadIt’s not as much of a choiceAs no road at all

P.P.S. Here’s the code we wrote together in class…

Time.java

package lecture1018;

import java.util.GregorianCalendar;

public class Time {
  public static void main(String[] args) {
    GregorianCalendar then = new GregorianCalendar(1969, 11, 31);
    System.out.println(then.getTimeInMillis());
  }
}

Sometimes.java

package lecture1018;

import java.util.Random;

public class Sometimes {
  public static void main(String[] args) {

    Random generator = new Random();
    String color;

    if (generator.nextBoolean()) {
      color = "red";
    } else {
      color = "yellow";
    }

    System.out.println("<html><body style=\"background-color: " + color + ";\"></body></html>");
  }
}

Flashmod.java

package lecture1018;

import java.util.Random;
import java.util.Scanner;

public class Flashmod {
  public static void main(String[] args) {
    Random generator = new Random();
    int upper = generator.nextInt(100);
    int lower = generator.nextInt(20);
    System.out.printf("What is %d %% %d? ", upper, lower);
    Scanner in = new Scanner(System.in);
    int response = in.nextInt();
    if (response == upper % lower) {
      System.out.println("Good. Correct. You're numero 0.");
    } else {
      System.out.println("...");
    }
  }
}

Randaurant.java

package lecture1018;

import java.util.Random;

public class Randaurant {
  public static void main(String[] args) {
  }

  public static String getRandomRestaurant() {
    Random generator = new Random();
    int n = generator.nextInt(100);
    if (n < 50) {
      return "Olympic Flame";
    } else if (n < 75) {
      return "El Patio";
    } else if (n < 90) {
      return "Taco Bell";
    } else {
      return "Nucleus";
    }

  }
}