Using Conditionals in Algorithms
This guide discusses how to work with conditionals, specifically it walks through the various ways that you can use conditionals in algorithms.
Guide Tasks
  • Read Tutorial

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.

What are Conditionals?

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.

Base Cases

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 else block.

So far, so good.

Compound Conditionals

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 name and role.

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.

Various Syntax Options

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 current_user.role value.

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.

Bugs with Conditionals

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:

  1. Check to see if the value is divisible by 3 and 5
  2. If not, check to see if the value is divisible by 3
  3. If not, check to see if the value is divisible by 5

However, in the second example, the flow has changed to look like this:

  1. If not, check to see if the value is divisible by 3
  2. If not, check to see if the value is divisible by 5
  3. If not, check to see if the value is divisible by 3 and 5

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.