You won’t get very far in your study of algorithms before coming across conditionals. And in fact, in our previous guide on boolean logic we already introduced ways to implement conditionals. So in this guide we’re going to take a deep dive into how we can use conditionals to build algorithms.
First and foremost, what are conditionals? The easiest definition I could come up with that still expresses the goal of conditionals is:
A conditional is a computer science process that allows for a program to make dynamic decisions based on answering questions related to data.
If that decision is fuzzy at all, let’s take a look at a base case example. I’ll be using the Ruby programming language in this guide because it has an expressive syntax that also includes a number of options for implementing conditional logic into a program.
In the last guide on boolean logic we looked at a dead simple base case, let’s bring that example back:
p = true if p == true puts "true" else puts "false" end # > true
In this example we’ve created a variable
p and set it equal to
true. From that point the program checks to see if
p is set to
true, and if it is it will run the code inside of the conditional. If the conditional does not mee the criteria, meaning if
p is not equal to
true, then the program will fallback to the default
So far, so good.
With the base case under our belts, let’s take a look at a compound conditional. A compound conditional is a programming mechanism that tests for multiple scenarios. And this time we’re going to utilize a more practical example.
I’m going to start by creating a
User by leveraging the Ruby
Struct class. This struct will let us mimic what a real user would look like in a web application. It even allows our users to have attributes, such as a
User = Struct.new(:name, :role) current_user = User.new('Jordan', 'Admin')
I’ve created a new user and stored it in the variable
current_user. I’ve also set the role value equal to
Admin. Now we can implement a conditional that will check to see what dashboard a user should see when they access our imaginary webpage.
if current_user.role == 'Admin' puts 'admin_layout' elsif current_user.role == 'Employee' puts 'employee_layout' else puts 'sign_in' end
This example can be used in a web application to render a different dashboard based on the user that is signed in. For example, if a user’s role is
Admin, it will show her the
admin_layout dashboard, if the user is just a regular
Employee, they will be shown the
employee_layout dashboard. And if neither of those conditions are met, the application will redirect the user to the sign in page.
This is using the Ruby programming language syntax, however every language has the same behavior when it comes to compound conditionals.
In addition to the
if/else syntax, most languages offer the ability to test for
scenarios with case statements. A case statement is a great tool to use when you have a preset number of scenarios that you want to test for. To be 100% clear, this is simply a different syntax than
if/else conditionals, the actual behavior is identical. However when you work through various algorithms you’re going to see both styles so I want to ensure that are familiar with both syntaxes.
Since the behavior is the same, let’s refactor our
if/else conditional to use a switch statement:
case current_user.role when 'Admin' puts "admin_layout" when 'Employee' puts "employee_layout" else puts 'sign_in' end
This will output the same values as the
if/else tool. However notice how we didn’t have to put the
== check? This is because case statements in Ruby automatically are comparing the equality of the value passed to
case. Just like in our example where we are looking at the
Ruby also allows you to shorten the
when calls so they can be placed on the same line as the return value, like so:
case current_user.role when 'Admin' then puts "Admin Layout" when 'Employee' then puts "Employee Layout" else puts 'Sign in page' end
Notice how the one line alternate syntax requires you to use the keyword
then before supplying the item that is going to be returned.
When it comes to implementing algorithms, there are some common bugs that can arise when the conditional hasn’t been properly structured. For example, let’s solve the standard fizz buzz coding interview question.
Tom Dalling gives the definition for this programming challenge:
Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”, and for values that are multiples of three and five print out “FizzBuzz”.
If I implement the code properly, the implementation of the program should be:
def fizz_buzz num 1.upto(num) do |i| if i % 3 == 0 && i % 5 == 0 puts "FizzBuzz" elsif i % 3 == 0 puts "Fizz" elsif i % 5 == 0 puts "Buzz" else puts i end end end fizz_buzz 100
This will print out all of the correct values. However if I change the conditional checks to look like this:
def fizz_buzz num 1.upto(num) do |i| if i % 3 == 0 puts "Fizz" elsif i % 5 == 0 puts "Buzz" elsif i % 3 == 0 && i % 5 == 0 puts "FizzBuzz" else puts i end end end fizz_buzz 100
The reason why this won’t work is because I switched up the order of the conditionals. For example, in the first example the conditional checks will flow like this:
However, in the second example, the flow has changed to look like this:
This may not seem like a critical mistake, until you start to step through the data. In computer science, once a conditional has been considered
true the rest of the conditionals are ignored. This means that for values such as
15, they will be considered multiples of 3 and the conditional
elsif i % 3 == 0 && i % 5 == 0 will be skipped 100% of the time.
So when it comes to working with conditionals, make sure that you are intentional in regard to the order that your checks are taking place.