Chapter 4

Conditionals

We solved some basic problems in the last chapter, but the techniques that we have access to are fundamentally limited at this point. The real problem is that all the lines in a script execute in the same order from top to bottom every time the script is run. In most real problems we need to be able to do what is called conditional execution, where something happens only in certain situations. In this chapter we will learn the most fundamental method for doing conditional execution in Scala and see how we can use it to solve more complex problems.

In order to do this properly, we need to develop a formalized way to express logic and put it into our programs. This system, called Boolean logic, will allow us to state the conditions under which various parts of our program will or will not happen.

4.1 Motivating Example

You have been asked to write a program that will calculate charges for people visiting a local amusement park. There are different charges for adult vs. child, whether they are bringing in a cooler, and whether they want to also get into the water park. We need to write code that will tell us how much the person pays. We will have the user input the needed information such as an Int for the persons age, a Boolean for whether they have a cooler, and another Boolean for whether they want to get into the water park.

This is something that we could not do last chapter because we did not have a way of performing logic. We could not say that we wanted to do something only in a particular situation. This ability to do different things in different situations is called conditional execution and it is a very important concept in programming. It is also critical for problem solving in general. Conditional execution gives you the ability to express logic and to solve much more complex problems than you could do without it.

4.2 The if Expression

Virtually all programming languages have a construct in them called if. The idea of this construct is you have a condition where one thing should happen if the condition is true. If the condition is false, then either nothing or something different will happen. In non- functional languages, the if construct is a statement. It has no value and simply determines what code will be executed. In Scala and other functional languages, the if is an expression which gives back a value. Scala allows you to use it in either style.

Let us start with an example, then we can broaden it to the more general syntax. Take the ticket price example and consider just the person’s age. Say that we want to consider whether a person should pay the $20 children’s rate or the $35 adult rate. For our purposes, a child is anyone under the age of 13. We could make a variable with the correct value with the following declaration using an if expression.

val cost = if(age<13) 20 else 35

This assumes that age is an Int variable that has been defined prior to this point. The first part of this line is a basic variable declaration as discussed in chapter 3. The new part of this is the use of the if expression which checks the age and gives back one of two values depending on where age<13 is true of false.

This example uses the if as an expression. So we care about the value it gives us. In this type of usage, we always need to include an else because there has to be a value that is used if the expression, is false. This same type of behavior can be also accomplished with a var using the if as a statement.

var cost=20
if(age<=13) cost=35

This code creates a var and gives it the initial value of 20. It then checks if the age is greater than or equal to 13 and if so, it changes the value to 35. Note with this usage, the else clause is not required. Here we only want to do something if the condition is true. In Scala you should generally prefer the first approach. It is shorter, cleaner, and leaves you with a val, which you can be certain will not be changed after it is created. The first approach is a functional approach while the second is an imperative approach.

In general, the format of the if is as follows:

if(condition) expr1 [else expr2]

The square brackets here denote that the else and the second expression are optional. They are not part of the syntax. The condition can be replaced by any expression of type Boolean, while expr1 and expr2 can be any expression you want.

In the situation where the expression is complex, you can use curly braces to create a block of code. You can put any code inside of curly braces. This block is itself an expression and the value of the expression is the value of the last statement in the curly braces. You can play with this in the REPL with expressions like this example.

scala> {
 | println("First line")
 | 4+5
 |}
First line
res0: Int = 9

For any if expression that does not fit on a single line, you should consider using a format like this.

if(condition) {
 ...
} else {
 ...
}

Being consistent with this format can help make your code more readable and prevent errors.

Common Bug

One common error that novice programmers encounter with the if statement occurs when they put more than one expression after the if or the else without using curly braces. Here is an example of how that can happen. We start with the following code that calculates an area.

val area = if(shape=="circle")
 math.Pi*radius*radius
else
 length*width

Here the if is broken across multiple lines so there is not one long line of code. This can make it easier to read. There are no curly braces, but they are not needed because each part of the if has only a single expression.

Now consider the possibility that the program this is part of does not work. To help figure out what is going on, you put print statements in so that you know when it uses the circle case and when it uses the rectangle case. The error comes when the code is changed to something like this.

val area = if(shape=="circle")
 println("Circle")
 math.Pi*radius*radius
else
 println(Rectangle)
 length*width

Now both branches have two expressions and we have a problem. This code needs curly braces, but they are easy to forget because the indentation makes the code look fine. Scala does not care about indentation. That is only for the benefit of humans. In reality, this code should look something like the following.

val area = if(shape=="circle") {
 println("Circle")
 math.Pi*radius*radius
} else {
 println("Rectangle")
 length*width
}

What about the other parts of our admission park entrance cost? We also wanted to check if the person had a cooler or if they wanted to get into the water park. These should both be variables of type Boolean. We might call them cooler and waterPark. Let us say it costs an additional $5 to bring in a cooler and $10 to go to the water park. If we used the if as an expression we can type in the following:

val cost = (if(age<13) 20 else 35)+(if(cooler) 5 else 0)+
 (if(waterPark) 10 else 0)

Here we are adding together the results of three different if expressions. This format is somewhat specific to functional languages. It would be more common in most languages to see this instead:

var cost=20
if(age>=13) cost=35
if(cooler) cost=cost+5
if(waterPark) cost=cost+10

In this second form, we use if as a statement instead of an expression and have the body of the if change, or mutate, the value of the variable cost.

Note on Style

While there are differences between the functional and imperative versions of code in different applications in regard to things like performance and the likelihood of errors, at this stage those should not be your top concerns. You should pick the style that makes the most sense to you. Later you can evaluate the differences and pick the approach that best fits the task.

In the second and third if statements, the name cost is repeated. This type of repetition is often avoided in programming. Many languages, including Scala, include operations that allow us to avoid it. When the duplication is caused like this with an assignment and a variable appearing on both sides of the equals sign, it is possible to use an abbreviated syntax where the operator is placed in front of the equals sign like this:

var cost=20
if(age>=13) cost=35
if(cooler) cost+=5
if(waterPark) cost+=10

4.3 Comparisons

The first if statement shown in the previous section uses >= to do a comparison between two values. You likely had no problem figuring out that this can be read as greater than or equal to. Your keyboard does not have a ≥ key so instead we use two characters in a row. All of the normal comparisons that you are used to exist in Scala, but some, like the greater than or equal to, differ from how you are used to writing them on paper.

The simplest comparison you can do is to check if two things are the same or different. You read this as saying that two things are equal or not equal to one another. In Scala we represent these with == and != respectively. Note that the check for equality uses two equal signs. A single equal sign in Scala stands for assignment, which we have already seen stores a value into a variable. The double equal sign checks if two expressions have the same value and produces a Boolean value with the result of the comparison. Here are a few example of the use of this in the REPL.

scala> 2==3
res1: Boolean = false
 
scala> 7==7
res2: Boolean = true
 
scala> ’a’==’a’
res3: Boolean = true
 
scala> "hi"=="there"
res4: Boolean = false
 
scala> "mom".length=="dad".length
res5: Boolean = true

The != operator is basically the opposite of ==. It tells us if two things are different and should be read as not equal. As we will see, it is customary in Scala to read the exclamation point, pronounced “bang” in many computing contexts, as not. Any of the examples above could use != instead of == and the result would have been the opposite of what is shown.

In addition to equality and inequality, there are also comparisons of magnitude like the age>=13 that we used above. The comparisons of magnitude in Scala are done with <, >, <=, and >=. These also give us back a value of the Boolean type so it will be either true or false. The order of the characters in <= and >= is significant. They are in the same order that you say them, “less than or equal to” and “greater than or equal to”, so it will not be hard to remember. If you reverse the order, Scala will not be able to figure out what you mean and will return an error.

scala> 5=<9
<console>:6: error: value =< is not a member of Int
  5=<9
  ^

You can use == or != on any of the different types in Scala, both those we have talked about and everything that we have not yet talked about. This is not the case for the magnitude comparisons. While you can use <, >, <=, and >= for many of the types that we have seen so far, not every type has an order where these comparisons makes sense. We will have types for things like colors, shapes, and fruits. Magnitude comparisons will not make sense with these and they will not work if you try to use them.

Equality vs. Identity (Advanced)

If you have experience with Java, you might find the behavior of == confusing. This is because in Scala, == does what most people expect, it checks for equality between values. For anyone who has not programmed in Java he/she might wonder what other options there are. We will see later that objects with the same value are not necessarily the same objects. If you go to a store and pick up two boxes of the same type of item, they are basically equal as far as you can tell, but they are not the same object. Each one has its own identity.

There are times in programming when you don’t want to just check if two things are equal, you want to actually know if they are the same thing. This requires doing a check for identity. In Scala we use eq to check if two things are the same thing. We can show an example of where eq and == return different result.

scala> "sssss" eq "s"*5
res8: Boolean = false


    
scala> "sssss" == "s"*5
res9: Boolean = true

4.4 Boolean Logic

Imagine if the theme park had a policy where seniors are charged the same amount as children. So now anyone over 65 or anyone under 13 should pay the reduced rate. We could accomplish this by having separate if statements in either the functional or the imperative manner.

val cost = if(age<13) 20 else if(age>65) 20 else 35

or

var cost=20
if(age>=13) cost=35
if(age>65) cost=20

Both of these are verbose, potentially inefficient, and prone to errors. The errors occur because in both we had to enter the number 20 in two places. What we would really like to say is exactly what we said in English. We want to say that we use the lower rate if the person is under 13 or over 65 and use the higher rate otherwise. Boolean logic gives us the ability to say this.

There are four different Boolean operators we can use to build complex Boolean expressions from simple ones. These are shown in table 4.1. Table 4.2 shows the value that results from applying these different operators on different arguments.

Table 4.1

This table shows the Boolean operators for Scala and what each one does.

Description

Usage

Meaning

and

a && b

True if both a and b are true.

or

a || b

True if a or b is true. Allows both being true.

exclusive or (xor)

a ^b

True if either a or b is true, but not both.

not

!a

True if a is false and false if a is true.

Table 4.2

Truth tables for the different Boolean operators.

a && b

a=true

a=false

b=true

true

false

b=false

false

false

a || b

a=true

a=false

b=true

true

true

b=false

true

false

a ^ b

a=true

a=false

b=true

false

true

b=false

true

false

!a

a=true

false

a=false

true

We can use the || operator just like we used or in our English description of what we wanted above. If we do this, our functional approach would simplify to this.

val cost = if(age<13 || age>65) 20 else 35

We can use && to say and.

var cost=20
if(age>=13 && age<=65) cost=35

The first one reproduces the English description and uses an or to give a single Boolean expression for when the lower rate is charged. The second one is the converse and uses an and to determine when the higher rate should be charged. The second expression could be written instead with an || and a ! to make it more explicit so that it is the converse of the first one.

var cost=20
if(!(age<13 || age>65)) cost=35

The extra set of parentheses is required here so that the not is done for the whole expression.

It is worth noting that || is not the “or” or normal English. In normal usage, when you say “or” you mean the logical exclusive or, ^. For example, when a parent offers their child the option of “cake or cookies”, the parent is not intending for the child to take both. The inclusive or, ||, allows both. The exclusive or, ^, does not.

Another example would be code that tells us if two squares intersect. Each square is defined by its top-left corner as x and y coordinates along with the edge lengths of the two squares. We want a result that is a Boolean telling us whether or not the squares intersect.

Before we can write a program to do this, we need to figure out how we would do this independent of a program.

Your first inclination might be to say that given two squares it is obvious whether or not they intersect. Indeed, novice programmers are tempted to give that type of description to many problems. This is not because the solution really is obvious, it is because novice programmers have not developed their skills at analyzing what they do when they solve a problem. This is something that you will develop over time and it is a requirement for any real programmer.

So what are you missing when you say that a problem like this is obvious? Given a set of six numbers as is the case here, most people would not find the solution obvious. To make it obvious they would draw the squares and look at them. This use of your visual processing is basically cheating and implicitly brings into play a large amount of processing that your brain does automatically. For this reason, we will avoid any type of solution where you would be tempted to say you would “look at” something.

Even if we did take the approach of drawing the squares, that is not as straightforward as you might picture. When you picture drawing squares, you likely picture squares of nearly the same size that are in easy-to-draw coordinates. Plotting gets a lot harder if one of the squares is millions of times larger than the other. If your program is trying to see if an ant has entered a building, that is not at all out of the question. So we can not settle for “just look at it” or “it is obvious”. That means we have to figure out what it really means for two squares to be intersecting just using the numbers.

While looking at it is not allowed as a solution, it can be helpful to figure out what we really mean. Draw a number of different squares on paper. Label them with the numbers 1 and 2. What are different possible relative positions for the squares? What are cases when they do not intersect? What has to happen for them to intersect? These are not rhetorical questions. Go through this exercise and come up with something before you read on. The ability to break down a problem that is “obvious” into the real steps that humans go through on a subconscious level is a cornerstone of programming. It is also useful for those who do not intend to be programmers as it can help you to understand your thinking on all manner of topics.

When you went through the processing of drawing the squares, one of the things you might have found was that squares can overlap in either an x or y direction, but they only intersect if they overlap in both x and y. That gives us something to work with. Our answer could say something like, overlapX && overlapY. All we have to do now is figure out what it means to overlap in a given direction. Even this has lots of different possibilities, but if you play with them you will see that any situation where there is an overlap satisfies the following: the minimum of the first range has to be less than the maximum of the second range and the maximum of the first range has to be greater than the minimum of the second range. Go back to your drawings and verify that this is true.

At this point we have the ability to say what we want. There are many ways that we could do so. We are going to pick an approach which breaks the problem down into smaller pieces. This will be easier for people to read. We said above that the squares overlap if their ranges overlap in both x and y. So we can write code that checks to see if two ranges overlap in one dimension, then the other. We can then combine these to see if the squares overlap.

val overlapX = x1<x2+size2 && x1+size1>x2
val overlapY = y1<y2+size2 && y1+size1>y2
val squareOverlap = overlapX && overlapY

The Boolean value, squareOverlap, tells us the answer to the question.

Short-Circuit Operators

One other significant factor about the Boolean && and || operators is that they are short-circuit operators. This means that if the value they will give is known after the first argument is evaluated, the second argument will not be evaluated. For && this happens if the first argument is false because no matter what the second argument is, the final value will be false. Similarly, if the first argument of || is true, the final value will be true so there is no point spending time to evaluate the second argument. This will be significant to us later on when we get to expressions that can cause errors. The only thing we could do now that would cause an error is to divide by zero. We can use that to demonstrate how short circuiting can prevent an error and that the ^ operator is not short circuited.

scala> val n=0
n: Int = 0
 
scala> 4/n
java.lang.ArithmeticException: / by zero
 at .<init>(<console>:7)
 at .<clinit>(<console>)
 at RequestResult$.<init>(<console>:9)
 at RequestResult$.<clinit>(<console>)
 at RequestResult$scala_repl_result(<console>)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun...
 
scala> n!=0 && 4/n==6
res3: Boolean = false
 
scala> n==0 || 4/n==6
res4: Boolean = true
 
scala> n==0 ^ 4/n==6
java.lang.ArithmeticException: / by zero
 at .<init>(<console>:7)
 at .<clinit>(<console>)
 at RequestResult$.<init>(<console>:9)
 at RequestResult$.<clinit>(<console>)
 at RequestResult$scala_repl_result(<console>)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun...

4.5 Bigger Expressions

So far all of our expressions have been fairly small. Other factors can come into play when they get large. One factor that becomes significant is precedence. This is the order in which operations are done. You know from math that multiplication happens before addition and Scala follows that rule. What happens when we start including these other operations for comparing values and Boolean operators? These are not things you have been taught in math class, but for the most part they are understandable. All of the operators introduced in this section happen after all the mathematical operators we worked with before. This makes sense as otherwise we could not type something like a+5>b*2 without using parentheses. Similarly, comparisons have higher precedence than the Boolean operators. The expressions for overlapX and overlapY used both of these facts as they combined addition, comparison, and &&.

As was mentioned earlier, operators are really just methods in Scala. The ones we have talked about so far are simply methods that are defined in the Scala libraries on the appropriate types. So && and || are defined on the Boolean type. The comparison operators are defined on numeric types, etc. When you use operator notation with a method, the precedence is determined by the first character in the operator. Table 4.3 shows the order.

Table 4.3

Table of operator precedence in Scala. The precedence of an operator is determined by the first character.

First Character

(other special characters)

* / %

+ -

:

= !

< >

&

^

|

(all letters)

(all assignment operators)

There is another interesting point that we have used implicitly already, but is worth noting explicitly. This is that if expressions can be nested inside of one another. We saw this when we first tried to add senior citizens at a lower cost.

val cost = if(age<13) 20 else if(age>65) 20 else 35

The contents of the else on the first if is itself an if. This is a general property of most programming languages. The if in Scala needs some form of expression inside of it for the true and false possibilities if it is an expression in Scala. As such, the if itself makes a perfectly valid expression to nest. So you can nest ifs inside of one another as much as it makes sense for the problem you are solving.

To make this more explicit, let us go back to our theme park and this time consider concessions. The menu is not broad and is standard for fast food. They have drinks, fries, and various main course items like hamburgers and hot dogs. You can also get a combo, which has one of each. For any of these you can specify a size. The cost is specified by the simple matrix shown in table 4.4.

Table 4.4

Theme park food item costs.

Item

S

M

L

Drink

$0.99

$1.29

$1.39

Side

$1.29

$1.49

$1.59

Main

$1.99

$2.59

$2.99

Combo

$4.09

$4.99

$5.69

We need to convert this table into code. We will start by reading in two strings. The first is the item type and the second is the size, both as Strings. In the end we want the variable cost as a Double.

println("What item are you ordering?")
val item = readLine()
println("What size do you want?")
val size = readLine()
val cost = if(item=="Drink") {
 if(size=="S") 0.99
 else if(size=="M") 1.29
 else 1.39
} else if(item=="Side") {
 if(size=="S") 1.29
 else if(size=="M") 1.49
 else 1.59
} else if(item=="Main") {
 if(size=="S") 1.99
 else if(size=="M") 2.59
 else 2.99
} else {
 if(size=="S") 4.09
 else if(size=="M") 4.99
 else 5.69
}

This code has a top level set of ifs that pick the item type. Inside of each is an if statement that picks from the different sizes. The way this was written, it will default to a combo if the item is not recognized and to a large if the size is not recognized. There are better ways to deal with this, but this will work for now.

This method demonstrates a standard formatting style used with this type of structure where the only thing in the else is another if. Instead of putting another set of curly braces after the else and indenting everything, leave off the curly braces and just put the if there. This prevents the indentation from getting too deep.

Bit-wise Arithmetic

The bits in a binary number are just like Boolean values. We can perform Boolean logic on the bits in integer values the way we would on standard true and false values. To do this we use slightly different operators. We use & and | instead of && and ||. The versions with a single character are not short circuit. The concept of short circuit does not make sense for this type of operation because a bit can not be a complex operation to evaluate. The other difference is that we use ~ instead of ! for the bit-wise negation.

If you think back to chapter 3 you will remember that every number on a computer is represented in binary. We store values of one or zero to represent different powers of two.

When we do bit-wise operations we simply take the bits in the same position and do the specified operations on them to get the bits in the result. To see how this works let us run through a set of examples on the binary operators where we use the four bit numbers 1100 and 1010.

 1100
& 1010
------
 1000
 
 1100
| 1010
------
 1110
 
 1100
^ 1010
------
 0110

Negation is pretty straightforward: ~1001=0110. Of course, these bit combinations all have numeric decimal values. We can put commands into Scala to do these same things. Our first value is 12 and our second is 10. The value we took the negation of is 9. Here are the operations performed in Scala. Check that they match the answers we got.

scala> 12 & 10
res3: Int = 8
 
scala> 12 | 10
res4: Int = 14
 
scala> 12 ^ 10
res5: Int = 6
 
scala> ~9
res6: Int = -10

The last one is interesting. When you check if it makes sense, remember that negative values are represented using two’s complement and an Int has 32 bits.

While on the topic of bit-wise operations there are two others that are worth mentioning. They are left-shift and right-shift and are written in Scala as << and >>. These operators shift the bits in an integer value the specified number of positions. If you think about the meaning of bits, this is like multiplying or dividing by powers of two in the same way that adding zeros to the end of a decimal number is the same as multiplying by ten. Some simple examples show you how we can use this to get powers of two.

scala> 1 << 0
res7: Int = 1
 
scala> 1 << 1
res8: Int = 2
 
scala> 1 << 2
res9: Int = 4
 
scala> 1 << 3
res10: Int = 8

There is a second version of right-shift written as >>>. The normal version does not move the sign bit so that signs are preserved. The second version does not do this and will shift the sign bit down along with everything else.

You might wonder why you would want to do these things. Using a single integer value as a collection of Boolean values is common in libraries based on the C language and frequently appear in operating system code. There is another usage that could come into play in projects later in this book.

If you have adjusted display settings on a computer you have probably seen that colors can be represented as 8-bit, 16-bit, 24-bit, or 32-bit values. Given the abundance of memory on modern computers, most of the time people will use 32-bit color. Have you ever wondered what that means? If you have written a web page or looked at a web page you have seen colors represented as six hexadecimal digits. The first two digits specify how much red, the next two specify how much green, and the last two specify how much blue. This is called RGB for obvious reasons and is exactly what 24-bit color gives you. 32-bit color uses an extra 8-bits because computers can operate more quickly with memory in 32-bit chunks because they are typically wired to deal with a 32-bit integer. The additional 8-bits stores the alpha channel which can be used for transparency. It does not matter much for your screen, but it is something that can be used to nice effect in 2-D graphics which we will discuss in chapter 12.

32-bit color is often called ARGB because it has alpha, red, green, and blue values all packed into 32 bits. Each gets 8 bits or a byte. This is where bit-wise operations come into play. You might be given four different values for alpha, red, green, and blue for a color and need to pack them together into a single 32-bit integer. Alternately, you might be given a single ARGB value as a 32-bit integer and have to figure out the individual components. Indeed, both of these appear as exercises below.

4.6 End of Chapter Material

4.6.1 Problem-Solving Approach

The if can be used as a statement. In the situation where an if includes side effects, you can use it as a top level command. This is a 4th option for statements that you can put into a script. So when you are considering what your next line of code is you should be thinking of one of these four possibilities.

  1. Call print or println.
  2. Declare a variable with val or var.
  3. Assign a value to a variable.
  4. Write an if statement. Note that to make sense as a statement, the expressions for the true and false possibilities should include one or more statements from this list. You should use an if when the code needs to do different things in different situations. When the word “if” fits in your English description of the solution to the problem, odds are good that it fits into the code as well.

4.6.2 Summary of Concepts

  • Constructs that allow different pieces of code to be executed depending on different conditions in the code are called conditionals.
  • The most basic conditional is if.
    • The syntax is if(condition) trueExpression else falseExpression.
    • The condition needs to be an expression with the Boolean type.
    • In Scala it can be used as an expression with a value or as a statement. As an expression, you need to have an else clause.
    • Curly braces can define blocks of code that function as a large expression. The value of the expression is the value of the last statement in the block.
  • The Boolean expressions often involve comparisons of values.
    • Any values can be checked for equality or inequality using == or !=, respectively.
    • Values that have a natural ordering can also be compared using <, <=, >, or >=.
  • More complex Boolean expressions can be built by combining simple expressions using Boolean logic.
    • The || operator is an inclusive or. This means that it is true if either of the two arguments are true as well as when both are true.
    • The && operator represents a logical and. It is only true when both arguments are true.
    • The ^ operator represents exclusive or. This is “or” as used in normal English where the result is true if one argument or the other is true, but not both.
    • The ! operator is logical negation.
    • The || and && operators are short-circuit operators.
  • When building large expressions, the order in which operators are applied is significant. This is called precedence. The precedence of operators in Scala depends on the first character. Table 4.3 gives a full list or precedence in Scala.
  • Bits can be viewed as Boolean values. Bit-wise arithmetic is operations that work on numeric numbers as collections of bits instead of normal numbers.
    • | is bit-wise or.
    • & is bit-wise and.
    • ^ is bit-wise xor.
    • ~ is bit-wise negation.

4.6.3 Self-Directed Study

Enter the following statements into the REPL and see what they do. Try some variations to make sure you understand what is going on. Note that some lines read values so the REPL will pause until you enter those values. The outcome of other lines will depend on what you enter.

scala> val a = readInt()
scala> val b = readInt()
scala> val minimum = if(a<b) a else b
scala> if(minimum != (a min b)) {
 println("Oops, something went wrong.")
} else {
 println("That’s good.")
}
scala> true && true
scala> true && false
scala> false && true
scala> false && false
scala> true || true 
scala> true || false
scala> false || true
scala> false || false
scala> !true
scala> !false
scala> true ^ true
scala> true ^ false
scala> false ^ true
scala> false ^ false
scala> a < b || {println("a>=b"); a >= b}
scala> a < b && {println("a>=b"); a >= b}
scala> a match {
 case 7 => "That is a lucky number."
 case 13 => "That is an unlucky number."
 case _ => "I’m not certain about that number."
}
scala> 13 & 5
scala> a.toBinaryString
scala> a & 0xff
scala> (a & 0xff).toBinaryString
scala> a ^ 0xff
scala> (a ^ 0xff).toBinaryString
scala> (a << 3).toBinaryString
scala> ((a >> 8) && 0xff).toBinaryString

4.6.4 Exercises

  1. Write Boolean expressions for the following:
    1. (a) Assume you have a variable called age. Tell if the person is old enough to legally drink.
    2. (b) Given a height in inches, tell if a person can ride an amusement park ride that requires riders to be between 48” and 74”.
  2. Determine if the following expressions are true or false. Assume the following, a=1, b=2, c=3, d=true, e=false.
    1. (a) a==1
    2. (b) c<b || b>c
    3. (c) a<=c && d==e
    4. (d) 1+2==c
    5. (e) d
    6. (f) !e
    7. (g) d || e
    8. (h) 6-(c-a)==b && (e || d)
    9. (i) c>b && b>a
    10. (j) a+b!=c || (c*a-b==a && c-a>b)
  3. Determine if the following expressions are true or false. Assume the following, a=1, b=10, c=100, x=true, y=false.
    1. (a) x
    2. (b) x && y
    3. (c) a==b-9
    4. (d) a<b || b>a
    5. (e) !y && !x
    6. (f) (c/b)/b==b/b
    7. (g) (c+b+a==b*b+c/c) || y
    8. (h) a <= b && b <= c && c >= a
    9. (i) c/(b/b)==b/b
    10. (j) !(x || y)
  4. The reverse method can be called on a String. Use this to write a script where the user inputs a word (use readLine) and you tell them whether or not it is a palindrome.
  5. It is customary to express colors on a computer as a combination of red, green, and blue along with another value called alpha that indicates transparency. A single Int has 32 bits or 4 bytes. The four different color values are often packed into a single Int as an ARGB value. The highest byte is the alpha and below that you have red, green, and blue in order. Each byte can store values between 0 and 255. For alpha, 0 is completely transparent and 255 is completely opaque.

    Write code that reads four Int values for alpha, red, green, and blue and calculates an Int with the combined ARGB value. If one of the numbers passed in is outside the 0 to 255 range, use 0 or 255, whichever it is closer to. Note that bitwise operations are appropriate for this exercise. You might find hexadecimal representation of numbers to be useful as well.

  6. Repeat the previous exercise, but this time the input should be Doubles between 0.0 and 1.0 that you convert to Ints in the proper range.
  7. Write code that does the opposite of what you did for exercise 5. It should take an Int with an ARGB value and calculate the four Int values with the component values between 0 and 255.
  8. Write code that does the opposite of what you did for exercise 6. It should take an Int with an ARGB value and calculate four Double values with the component values between 0.0 and 1.0.
  9. Write a script that has the user input a location as x and y coordinate values which tells whether the point specified is in the unit circle.1

4.6.5 Projects

  1. Write a script that asks the user for the coefficients of a quadratic equation (a, b, and c in ax2 + bx + c). It should print the roots for those coefficients. It needs to handle different options for the roots and print one or two solutions with real or complex values as appropriate.
  2. Write a script that tells you whether or not a rectangle overlaps with a circle. It needs to prompt the user for the required information for the two shapes that includes positions and sizes and it prints an appropriate message based on the Boolean result.
  3. You have built a simple robot that is supposed to move along a straight line from wherever it is placed to a flag. The robot can move in one of two ways. It can roll any distance at a speed of one inch per second. It can jump and each jump takes one second and moves a predetermined amount. When it jumps it always jumps that amount, not a fraction of it. Write a script that reads the distance you start from the flag and the distance covered in each jump and prints how many seconds it will take to get to the flag using an optimal approach. (The trick with this problem is to make sure you consider all the possibilities.)
  4. This problem starts a track of options that you can work on that build up to having a functioning ray tracer at the end of the semester that can render images in 3-D. For this first step you are to write a script that determines if and where a ray intersects either a plane or a sphere.

    The script should start by asking for information on the ray. That includes the start point of the ray, r0, and the direction vector for the ray, r. It should then ask if you want to consider a plane or a sphere. The code will have an if that splits into two possibilities at that point. One will ask for information on the sphere, a center point and radius, and do the proper calculation for a sphere. The second will ask for information on a plane, a normal direction and distance, and do the proper calculation for the plane. The script finishes by printing out information about the intersection.

    A ray can be defined as a start point and a direction vector using the parametric equation r(t)=r0+t*r, for t0. You find intersections by solving for the t that satisfies certain conditions like coming a certain distance from a point (for a sphere) or satisfying the equation r(t)n=d (for a plane with normal n that is d units from the origin). You can view coming within a certain distance from a point as solving the equation (r(t)n)(r(t)n)=radius2. With a little algebra you can reduce this to a quadratic equation. You only care about the solution with the smaller value of t. This option is a bit more conceptually challenging, but if you do all the ray tracing options the results can be impressive. The website at www.programmingusingscala.net includes a number of images made using a ray tracer the author wrote in Scala.

  5. You have been going through your book of Simple 2-Ingredient Recipes looking for something to cook. The problem is, you are really running low on ingredients. You only have four items and they are in short supply. For this project you will write a script that will take the four items you have and how much of each you have. After that it will ask for two ingredients and how much of each is needed. It should output whether or not you have enough stuff to make that recipe.

    For the input, items will be strings and you do not care about units on the amount. Item names have to match exactly to be the same and assume the same units are used for any given item.

  6. Imagine that you were considering taking a number of different majors or minors for college and you want to write a program to do a little math and help you see what different approaches would require. You have four major/minor interests. For each one the user should input a name and the number of hours it requires. You also have a number of hours for the core curriculum, a minimum number of hours for graduation, and how many hours you bring in from outside (AP/IB/Transfer). Prompt the user to enter those 11 values. Then run through the four major/minor interests and let them enter “yes” or “no” for whether they will do it to test an option. After that, print out the average number of hours that need to be taken each of the 8-semesters of college to complete that combination.

1The unit circle is a circle centered on the origin with radius 1.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset