Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Mojo basics 🔥

Advent of Code is an annual series of programming puzzles released every December. Many puzzles share a common format: grab some data, loop over it, evaluate a pattern, and compute the output. This example challenge follows the same steps. The toolkit demonstrated to solve this challenge will help you hit the ground running on any Advent of Code puzzle you pick up.

At the North Pole, a set of workshop sensors has recorded one week of temperature readings. Before anyone can spot problems in the heating system, they need a program that can inspect the data.

Mojo inspects a North Pole temperature monitor. Mojo inspects a North Pole temperature monitor.

Hello Mojo

Create analyzer.mojo in your favorite IDE or editor.

Start with a message that identifies your new tool:

def main():
    print("North Pole Temperature Analyzer")

Run it:

mojo analyzer.mojo

Takeaways

  • If you see “North Pole Temperature Analyzer”, your setup works.
  • All Mojo executables use main() as their entry point.

Variables and data

The workshop sensors have already collected four temperature readings. Store them in a list so your analyzer can work with them.

Update your file:

def main():
    print("North Pole Temperature Analyzer")

    # Square brackets tell Mojo the `List` type at compile time
    var temps: List[Float64] = [-20.5, -22.3, -19.8, -25.1]

    print(t"Recorded {len(temps)} temperatures")  # TStrings are templates

Mojo’s T-String adds string interpolation, building a string template with braces. Mojo replaces the braced expressions with their values. T-String braces can contain expressions, including function calls, arithmetic, and values, not just variable names.

Loops

Before looking for patterns, print each day’s reading so you can see what the sensors recorded.

Add this code to main() under the existing print statement:

    for index in range(len(temps)):  # The range is [0, len(temps))
        print(t"  Day {index + 1}: {temps[index]}°C")

You can rework the above to improve readability:

    for index, temp in enumerate(temps):
        print(t"  Day {index + 1}: {temp}°C")

Takeaways

  • The range() function is your for loop workhorse.
  • Mojo also has while loops. They work exactly as you expect.
  • All Mojo loops support break to stop the loop, continue to start the next iteration, and return to leave the loop and return from the function.

Functions

The workshop receives new readings every day. Put the average calculation in a function so the analyzer can reuse it.

Add this function above main():

def calculate_average(temps: List[Float64]) -> Float64:
    var total: Float64 = 0.0
    var count: Int = 0
    for temp in temps:  # Iterate over collection values
        total += temp
        count += 1
    return total / Float64(count)


Add this code to the end of main() to call the function:

    var avg = calculate_average(temps)
    print(t"Average: {round(avg, 2)}°C")  # Average: -21.92°C

Takeaways

  • Place return types after arrow tokens.
  • Like all compound statements, calculate_average() needs a colon before its body.
  • Function bodies must use consistent indentation. Mojo convention uses four spaces.
  • Use round() to specify the number of digits after the decimal point.

Conditionals

The elves need more than a number. Classify the week’s average so they can quickly see whether the workshop was cool, comfortable, or hot.

Add this code to the end of main():

    if avg > -20.0:
        print("Status: Hot week")
    elif avg > -25.0:
        print("Status: Comfortable week")
    else:
        print("Status: Cool week")

Takeaways

  • Add as many elif clauses as you need, from zero to many.
  • Mojo also has a ternary expression: value if condition else alt_value.

Raise errors

Sometimes a sensor fails and produces no readings. Your analyzer should notice instead of trying to calculate an average from an empty list.

Update calculate_average() so the function can raise an error:

def calculate_average(temps: List[Float64]) raises -> Float64:
    if len(temps) == 0:
        raise Error("No temperature data")

    var total: Float64 = 0.0
    var count: Int = 0
    for temp in temps:
        total += temp
        count += 1
    return total / Float64(count)


What changed:

  • You added raises before the return arrow.
  • You added an empty-list check.
  • You raised an Error when the list contained no readings.

Handle errors

A missing sensor report shouldn’t leave the elves wondering what happened. Catch the error and print a useful message.

Return to main() and wrap the average calculation and classification in try and except:

    try:
        var avg = calculate_average(temps)
        print(t"Average: {round(avg, 2)}°C")  # Average: -21.92°C

        if avg > -20.0:
            print("Status: Hot week")
        elif avg > -25.0:
            print("Status: Comfortable week")
        else:
            print("Status: Cool week")

    except e:
        print("Error:", e)

To test the error, replace temps with List[Float64](). This constructs an empty list of Float64 values.

Confirm that your program reports No temperature data, then restore the original readings.

Final code

Your complete analyzer.mojo:

def calculate_average(temps: List[Float64]) raises -> Float64:
    if len(temps) == 0:
        raise Error("No temperature data")

    var total: Float64 = 0.0
    var count: Int = 0
    for temp in temps:
        total += temp
        count += 1
    return total / Float64(count)




def main():
    print("North Pole Temperature Analyzer")
    var temps: List[Float64] = [-20.5, -22.3, -19.8, -25.1]
    print(t"Recorded {len(temps)} temperatures")

    for index, temp in enumerate(temps):
        print(t"  Day {index + 1}: {temp}°C")

    try:
        var avg = calculate_average(temps)
        print(t"Average: {round(avg, 2)}°C")  # Average: -21.92°C

        if avg > -20.0:
            print("Status: Hot week")
        elif avg > -25.0:
            print("Status: Comfortable week")
        else:
            print("Status: Cool week")

    except e:
        print("Error:", e)


The analyzer can now store sensor readings, inspect them, calculate their average, classify the week, and report missing data.

The North Pole has its first working analysis tool.

Topics covered

Mojo variables, lists, loops, functions, conditionals, and error handling.