The answer section is a work in progress. I am working on providing answers to every exercise but this takes time. Thank you for your patience.

Note that many exercises may have multiple possible answers. If your code looks a bit differnt from mine, but produces valid results, then your answer is fine. If you are uncertain, you can always contact me.

3. First programs

Exercise 1

You will of course have to replace my name with your own. (The exercise specification is vague enough that you could print your first name, your last name or both.)

1
2
3
4
5
6
7
package main

import "core:fmt"

main :: proc() {
    fmt.println("Lorenzo")
}

Exercise 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

package main

import "core:fmt"

main :: proc() {
    fmt.println(1)
    fmt.println(2)
    fmt.println(3)
    fmt.println(4)
    fmt.println(5)
    fmt.println(6)
    fmt.println(7)
    fmt.println(8)
    fmt.println(9)
    fmt.println(10)
}

If you quoted the numbers (fmt.println("1")), that is perfectly fine as well. The println procedure works with both numbers and strings.

Using what we have learned so far, a program to print the numbers 1-10,000 would be slightly more than 10,000 lines long. It goes without saying that such a program would be highly inefficient.

Exercise 3

All the output will be on a single line:

$ odin run .
Hi there!I am learning OdinIt's a lot of fun so far.$

Depending on the system you use and how it has been configured, you may or may not see the prompt at the end of the output as well.

So println means “print and jump to the next line in the terminal”, wheras print stays on the same line after printing.

Exercise 4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

import "core:fmt"

main :: proc() {
    fmt.println("January")
    fmt.println("February")
    fmt.println("March")
    fmt.println("April")
    fmt.println("May")
    fmt.println("June")
    fmt.println("July")
    fmt.println("August")
    fmt.println("September")
    fmt.println("October")
    fmt.println("November")
    fmt.println("December")
}

However, if you are not English-speaking, or you are learning some language apart from English, why not print in that other language. Text enclosed in quotes (called string literals) is Unicode in Odin, which means you can use characters that are not part of the Latin alphabet.

Here, for instance, is the same program but with the month names in Ga instead. If you were learning Ga, you could run this program to remind yourself of the names of the months.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

import "core:fmt"

main :: proc() {
    fmt.println("Aharabata")
    fmt.println("Oflɔ")
    fmt.println("Otsokrikri")
    fmt.println("Abɛibe")
    fmt.println("Agbiɛnaa")
    fmt.println("Otukwajaŋ")
    fmt.println("Maawɛ")
    fmt.println("Manyawale")
    fmt.println("Gbo")
    fmt.println("Antɔŋ")
    fmt.println("Alemle")
    fmt.println("Afuabe")
}

Right now, you really just want to practice writing code as much as possible, so if you speak 5 languages, take the opportunity to write the program 5 times.

Exercise 5

There are two errors you need to fix:

  1. In Odin, the declaration of the main procedure is main :: proc not just main (line 5)
  2. In Odin, string literals are enclosed in a pair of double quotes, not single ones (line 7)

I can’t stress this enough: get familiar with the error messages that the Odin compiler gives and use them as a guide to finding and fixing the problem.

Exercise 6

The output of the program is:

$ odin run .
I am currently learning Odin

The new concept here is a variable, something you will learn in the next lesson. Try changing lang := "Odin" to lang := "Go" or something like that and see how the output changes.

Exercise 7

Try taking a very basic program like hellope and capitalizing proc and see the result. Here is the modified program:

1
2
3
4
5
6
7
package main

import "core:fmt"

main :: PROC() {
    fmt.printfln("Hellope!")
}

This is what happens, when I compile:

lorenzo@orthanc:~/Temporary/odin$ odin run .
/home/lorenzo/Temporary/odin/main.odin(5:1) Error: 'main' is reserved as the entry point procedure in the initial scope
	main :: PROC() {

In this case, the error message might not be the most explanatory, but we can safely conclude that Odin is case sensitive. Note however, that this will work fine:

1
2
3
4
5
6
7
package main

import "core:fmt"

main :: proc() {
    fmt.printfln("HELLOPE!")
}

That is because Odin doens’t really care about what you put between the double quotes (there are a few exceptions that we will look at later, such as putting a double qoute between an pair of double quotes).

If you think about it, it’s just like in English. “I ain’t got no book” is unfortunately not considered proper English. If you were studying English and wrote this in an exam, you’d lose points.

However, if you were writing a book and wrote something like

“I ain’t got no book”, he said.

That would be perfectly fine, since you are quoting exactly what somebody said. So Odin follows similar rules to English.

Exercise 8

The hellope program is perfect for these types of small experiments. Simply change main to start and try to run.

lorenzo@orthanc:~/Temporary/odin$ odin run .
/home/lorenzo/src/hellope/main.odin(1:2) Error: Undefined entry point procedure 'main'
	package main
	 ^

That doesn’t work. Conclusion: every Odin executable program must have a special procedure called main, which acts as the starting point of the program.

It is possible to write things that are not executable programs, like libraries in Odin as well. As you will see later, they are not required to have a main procedure.

Exercise 9

There was only one bug in the program, println should be all lowercase. Fix that and the program runs well. Do pay attention to the error message before you fix it.

Exercise 10

Here are the errors:

  1. package should not be capitalized (line 1)
  2. The import should be “core:fmt”, not just “core” (line 3)
  3. The procedure signature for main is main :: proc() not proc :: main() (line 5).
  4. println is misspelled. (line 6)

I usually fix one error at a time and rerun the program to see if it is working and take note of how the error output has changed if it doesn’t work.

It can feel a bit overwhelming at first when you get a long list of error messages. You need to learn to filter it out and only focus on one thing at a time. For example, look at the very first error message and try to figure out what caused that.

Exercise 11

Hopefully you looked at the program first and guessed what it would do before running it in order to confirm.

Here is the output:

a + b = 8
a - b = 2
a * b = 15
a / b = 1

This program uses two variables: a and b. It also uses four different arithmetic operators: plus, minus, multiply and divide.

Exercise 12

The original program prints:

$ odin run .
I'll take it.

If we increase the rice to 200, get:

$ odin run .
It's too expensive!

At exactly 150, the program again prints “I’ll take it.”, since the if statement spefically checks if price is greater than 150.

Exercise 13

The program produces the following output:

1
2
3
4
5
6
7
8
9
10

We can get it to print from 5 to 20 by changing line 6 to:

for i in 5..=20

If we change 1..=10 to 1..<10 we get:

$ odin run .
1
2
3
4
5
6
7
8
9

If the first number is greater than the first we get an error:

$ odin run .
/home/lorenzo/Temporary/odin/main.odin(6:16) Error: Invalid interval range
	for i in 10..=1 {
	           ^

/home/lorenzo/Temporary/odin/main.odin(7:21) Error: Undeclared name: i
	fmt.println(i)
	            ^

Exercise 14

The default order of execution is to execute each line of code from top to bottom. Here is an example of a program that consists of more than one line of code

package main

import "core:fmt"

main :: proc() {
    fmt.println("one")
    fmt.println("two")
    fmt.println("three")
}

This program will always produce the output:

one
two
three

This is because of the order of the statements.

Exercise 15

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import "core:fmt"

main :: proc() {
    fmt.println("George")
    fmt.println("Abena")
    // fmt.println("James")
    fmt.println("Vanessa")
    // fmt.println("Jojo")
    fmt.println("Nii Okai")
}

Exercise 16

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import "core:fmt"

main :: proc() {
    fmt.println("A")
    fmt.println("B")
    fmt.println("C")
    fmt.println("D")
    fmt.println("E")
    fmt.println("F")
    fmt.println("G")
    fmt.println("H")
    fmt.println("I")
    /* fmt.println("J")
    fmt.println("K")
    fmt.println("L")
    fmt.println("M")
    fmt.println("N")
    fmt.println("O")
    fmt.println("P")
    fmt.println("Q")
    fmt.println("R")
    fmt.println("S")
    fmt.println("T") */
    fmt.println("U")
    fmt.println("V")
    fmt.println("X")
    fmt.println("Y")
    fmt.println("Z")
}

Exercise 17

The output of the program is:

$ odin run .
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z

This is exactly the same as the output of exercise 16 (before you added the comments).

The program uses a for loop to iterate throught the capital letters, from ‘A’ to ‘Z’, printing each one on a line of its own. As you can see, this program is significantly shorter than the one in exercise 16, demonstrating the benefit of a loop.

4. Variables and Conditionals

Exercises 1

Since you haven’t learned how to use fmt.printfln at this stage, getting the output gets a bit finicky.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    h, m, s := time.clock_from_time(n)

    fmt.print(h)
    fmt.print(":")
    fmt.print(m)
    fmt.print(":")
    fmt.println(s)
}

Note the last print statement is println to ensure that we get a newline at the end of the output. You could also do the following, if you are okay with space in between each part.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    h, m, s := time.clock_from_time(n)

    fmt.println(h, ":", m, ":", s)
}

Notice however, that this solution isn’t exactly according to the specification. This could be a problem, if our program was a part of a larger system where some other part of the system is going to read the time from our program. Those extra spaces could be a problem, if that’s not what the other side expects. That is why it is important in software development, where different teams work on different parts of a larger system, that everybody follows the same spec and does so exactly.

The proper solution to this exercise would have been to use the printfln function that I mentioned above. This version also prepends a zero before any part that is less than 10. We will learn about formatting text with printf and printfln in future lessons.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    h, m, s := time.clock_from_time(n)

    fmt.printfln("%02d:%02d:%02d", h, m, s)
}

Exercise 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main

import "core:fmt"

main :: proc() {
    is_hungry := false

    if is_hungry {
        fmt.println("What would you like to eat?")
    } else {
        fmt.println("Well then, would you like to drink something?")
    }
}

I expect that you will test the program with both the possible values is_hungry.

Exercise 3

The ! (exclamation mark) means not, so !is_tired should be read as “is not tired”.

Exercise 4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main

import "core:fmt"

main :: proc() {
    num := 16

    if num > 15 {
        fmt.println("too large")
    } else if num == 3 {
        fmt.println("fizz")
    } else if num == 5 {
        fmt.println("buzz")
    } else if num < 1 {
        fmt.println("fizz buzz")
    } else {
        fmt.println(num)
    }
}

Make sure you change the value of num to see all the different messages.

Exercise 5

I decided to use the “good day” greeting between the hours 11 and 13 (3pm). You may have chosen different hours and that is fine, as long as the program behaves the way you intended it to.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    h, _, _ := time.clock_from_time(n)

    if h >= 4 && h < 11 {
        fmt.println("Good morning")
    } else if h >= 11 && h < 14) {
        fmt.println("Good day")
    } else if h >= 14 && h < 17 {
        fmt.println("Good afternoon")
    } else if h >= 17 && h < 23 {
        fmt.println("Good evening")
    } else {
        fmt.println("Good night")
    }
}

Exercise 6

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import "core:fmt"

main :: proc() {
    num := 78

    if num < 20 || num > 40 {
        fmt.println("out of range")
    }
}

For the list of test values, the program will print “out of range” when num is 17 or 78. For all the other values the program will not print anything.

Exercise 7

Before, you got the hour with h, _, _ := time.clock_from_time(n), discarding the minutes and seconds. Now we want the minutes instead, meaning you can discard the hour and seconds.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    _, m, _ := time.clock_from_time(n)

    if m <= 10 {
        fmt.println("The hour just started")
    } else if m >= 50 {
        fmt.println("We are close to the end of the hour")
    }
}

Exercise 8

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    _, m, _ := time.clock_from_time(n)

    if m <= 10 {
        fmt.println("The hour just started")
    } else if m >= 50 {
        fmt.println("We are close to the end of the hour")
    } else {
        fmt.println("We are well into the hour")
    }
}

Exercise 9

First we fix the errors that prevent the program from compiling:

  1. on line 3, change "core:for" to "core:fmt"
  2. on line 5, change proc :: main() to main :: proc()
  3. on line 8, change the name of the variable from num to age (twice)
  4. on line 8, change the operand from => to >=
  5. on line 8, change or to ||

However, that is not enough, as you will see if you test the program with different ages. There are logic errors that cause the program to print the wrong output under some circumstances:

  1. on line 8, change <= to <
  2. on line 8, change >= to >
  3. on line 8, change 45 to 65

There are a lot of changes to be made to line 8. The final version should look as follows:

if age < 18 || age > 65 {

Exercise 10

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    h, m, s := time.clock_from_time(n)

    sum := h + m + s
    fmt.println(sum)
}

Obvsiouly, the output of the program will vary based on the exact time of the day. We can figure out the range of possible numbers you can see. If you happened to manage to run the program exactly at midnight, you would get 0. If you run exactly one second earlier, the time would be 23:59:59, resulting in the ouput 141.

Exercise 11

We can use the following program to check if we are allowed to add two booleans.

1
2
3
4
5
6
7
8
package main

main :: proc() {
    b1 := false
    b2 := false

    bsum := b1 + b2
}

Trying to compile, we get:

$ odin build .
/home/lorenzo/Temporary/odin/main.odin(7:16) Error: Operator '+' is only allowed with numeric expressions
	bsum := b1 + b2
	           ^

That error message should be enough for us to conclude that Odin does not allow this. (Some other languages may consider false to be 0 and true to be 1 or some other non-zero value, Odin does not do this.)

We modify the program slightly to see if we can use the + operator with strings:

1
2
3
4
5
6
7
8
package main

main :: proc() {
    s1 := "Hellope!"
    s2 := " from Odin"

    ssum := s1 + s2
}

Again, we see that Odin does not allow this.

$ odin build .
/home/lorenzo/Temporary/odin/main.odin(7:16) Error: String concatenation is only allowed with constant strings
	ssum := s1 + s2
	           ^

Some languages, like Python, overload the + operator to “concatenate” two strings. Since we are learning Odin, we should only be concerned with what Odin allows and doesn’t.

Exercise 12

We need to do three things:

  1. decide on whether we should print “am” or “pm”
  2. subtract 12 from the hour if it is > 12
  3. for the special hour 0, add 12

I’m going to create a variable called suffix and set it to “am” by default. Only if the hour is greater than 12 should suffix be “pm”.

Once that is done, we can deal with the other 2 cases. The code, without using fmt.printfln is below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    h, m, s := time.clock_from_time(n)

    suffix := "am"
    if h > 12 {
        suffix = "pm"
    }

    if h >= 12 {
        h -= 12
    } else if h == 0 {
        h = 12
    }

    fmt.print(h)
    fmt.print(":")
    fmt.print(m)
    fmt.print(":")
    fmt.print(s)
    fmt.print(suffix)
    fmt.println()
}

We improve the output (and shorten the program) using printfln instead:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "core:fmt"
import "core:time"

main :: proc() {
    n := time.now()
    h, m, s := time.clock_from_time(n)

    suffix := "am"
    if h > 12 {
        suffix = "pm"
    }

    if h >= 12 {
        h -= 12
    } else if h == 0 {
        h = 12
    }

    fmt.printfln("%02d:%02d:%02d%s", h, m, s, suffix)
}

5. Command Line Args

Exercise 1

The first element has the index number 0 and the last one has the index number 9.

Exercise 2

You can use the following program to test the slices:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main

import "core:fmt"

main :: proc() {
    values := [10]int{10, 20, 30, 40, 50, 60, 70, 80, 90, 100}


    fmt.println(values[2:4])
    // fmt.println(values[5:10])
    // fmt.println(values[5:11])
    // fmt.println(values[6:2])
}

Uncomment the fmt.println lines one at a time and run. Below is the output.

  1. values[2:4] gives [30, 40]
  2. values[5:10] gives [60, 70, 80, 90, 100]
  3. values[5:11] fails to compile due to Error: Index '11' is out of bounds range 0..<10, got 11
  4. values[6:2] fails to compile due to Error: Invalid slice indices: [6 > 2]

Exercise 3