Learning Programming Languages with Code Challenges
Tags: challenge, experiment, learn, programminglanguages
Published: 2019-12-02 04:41:06

---
title: Learning Programming Languages with Code Challenges
published: true
description: An experiment to learn new programming languages in a different way.
tags: challenge, experiment, learn, programming-languages
cover_image: https://thepracticaldev.s3.amazonaws.com/i/nwfpwstoxgo8wqyoujct.jpg
---

I don't know about you but sometimes I get bored by using the same tools over and over again.

![](https://media.giphy.com/media/Er3QVX48nt5ok/giphy.gif)

So to have fun I wanted to learn a new programming language but as you may think I don't have the time to do so, maybe buying an Udemy course or watch some videos on YouTube are good idea but still... I wanted to do more than just writing Hello World.

But there was a bigger problem... which programming language should I be learning? I had the following options in mind:

* [Golang](https://golang.org/), is a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language.
* [Rust](https://www.rust-lang.org/), is a modern systems-level programming language designed with safety in mind. It provides zero-cost abstractions, generics, functional features, and plenty more. 
* [Crystal](https://crystal-lang.org/), is a programming language with the following goals:

  * Have a syntax similar to Ruby (but compatibility with it is not a goal).
  * Be statically type-checked, but  having to specify the type of variables or method arguments.
  * Be able to call C code by writing bindings to it in Crystal.
  * Have compile-time evaluation and generation of code, to avoid boilerplate code.
  * Compile to efficient native code.
* [Kotlin](https://kotlinlang.org/), is a general purpose, open source, statically typed “pragmatic” programming language for the JVM and Android that combines object-oriented and functional programming features.
* [Elixir](https://elixir-lang.org/), is a dynamic, functional language designed for building scalable and maintainable applications.

Hard decision, isn't it? but then I got an idea 💡... What about learning all those programming languages **at once**? 

![](https://media.giphy.com/media/KGr9wMij9rZt7nHwMx/giphy.gif)

This is an experiment to see if it's possible to learn many programming languages at once by solving the same code challenge.

## The rules

Before go on, we need some rules in order to do the experiment the best as possible:

1. Pick a non-trivial challenge.
2. Write a pseudocode solution following [Cal Poly pseudocode standard.](https://users.csc.calpoly.edu/~jdalbey/SWE/pdl_std.html)
3. Write the code for each programming language.
4. Write unit tests for each programming language.
5. Explain what I learned.

If you know a better solution or code improvement of any programming language feel free to leave a comment and it will be mentioned in the next post. It's about continual improvement 🤓.

## Table of Contents

1. [Code Challenge](#challenge)
2. [Pseudocode Solution](#pseudo)
3. [Golang implementation](#golang)
4. [Rust implementation](#rust)
5. [Crystal implementation](#crystal)
6. [Kotlin implementation](#kotlin)
7. [Elixir implementation](#elixir)
8. [Conclusion](#conclusion)


### Code Challenge: FizzBuzz <a name="challenge"></a>

Let's start easy, FizzBuzz is a small game that interviewers use to determine whether the job candidate can actually write code. Here is the description:

> 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". For numbers which are multiples of both three and five print "FizzBuzz".

### Pseudocode Solution <a name="pseudo"></a> 

```
FOR each number "i" from 1 to 100
  IF i is divisible by 3 AND is divisible by 5 THEN
    PRINT "FizzBuzz"
  ELSE IF i is divisible by 3 THEN
    PRINT "Fizz"
  ELSE IF i is divisible by 5 THEN
    PRINT "Buzz"
  ELSE
    PRINT i
  ENDIF
ENDFOR
```

### Golang Implementation <a name="golang"></a>

#### Solution: `fizzbuzz/fizzbuzz.go`

```golang
package fizzbuzz

func FizzBuzz(number int) (string, bool) {
	if number%3 == 0 && number%5 == 0 {
		return "FizzBuzz", true
	} else if number%3 == 0 {
		return "Fizz", true
	} else if number%5 == 0 {
		return "Buzz", true
	} else {
		return "", false
	}
}
```

#### What I've learned

* `package` keyword must be the first line in every Go program.
* In this case the package name is `fizzbuzz` (same as directory name) because this is an **utility package** (i.e. it's not standalone executable).
* To export the fizzbuzz function, its name must start with uppercase letter. Lowercased function names are private functions (i.e. can be only used in the same file).
* A function must start with **func** keyword.
* Like using Java or Javascript I wanted to return nil (null) if the given number is not divisible by 3 or 5 but that was a big mistake because the compiler throws the following error: `cannot use nil as type string in return argument`. So, since functions can return more than one value then _fizzbuzz_ function returns two values; the first one (string) is the result text (Fizz, Buzz or FizzBuzz) and the second one (boolean) means if the operation was done successfully.
* `%` (modulus) operator is used to check if the given number is divisible by 3 or 5.
* `if` statements has no parenthesis.

#### Unit Tests: `fizzbuzz/fizzbuzz_test.go`

```golang
package fizzbuzz

import "testing"

func TestFizzCases(t *testing.T) {
	cases := [10]int{3, 6, 9, 12, 18, 21, 24, 27, 33, 36}

	for _, n := range cases {
		result, _ := FizzBuzz(n)
		if result != "Fizz" {
			t.Errorf("Error, %v should be 'Fizz'", n)
		}
	}
}

func TestBuzzCases(t *testing.T) {
	cases := [10]int{5, 10, 20, 25, 35, 40, 50, 55, 70, 80}

	for _, n := range cases {
		result, _ := FizzBuzz(n)
		if result != "Buzz" {
			t.Errorf("Error, %v should be 'Buzz'", n)
		}
	}
}

func TestFizzBuzzCases(t *testing.T) {
	cases := [10]int{15, 30, 45, 60, 75, 90, 105, 120, 135, 150}

	for _, n := range cases {
		result, _ := FizzBuzz(n)
		if result != "FizzBuzz" {
			t.Errorf("Error, %v should be 'FizzBuzz'", n)
		}
	}
}
```
#### What I've learned

* `testing` is the built-int package to do tests (lol).
* Every test function name must start with **Test** keyword and latter name should start with uppercase letter (for example, _TestMultiply_ and not _Testmultiply_)
* `:=` is a short variable declaration (for example, `i := 0` is the same as `var i int = 0`).
* `[N] T { v1, v2, ..., vN }` is the way to declare an Array with fixed size _N_ 
 of type _T_ with _v1, v2, ..., vN_ as values.
* Every test function has the same parameter.
* There is no _assert_ function or something like that, if the test fails it must use the `t.Errorf` function with a message.
* `range` is the way to iterate over an Array or Slice (dynamic sized array), the first return value is the index and the second one is the value itself.
* When a function returns more than one value, you can't ignore any of them (for example, `result := FizzBuzz(n)` is wrong because it returns two values).
 
### Rust Implementation <a name="rust"></a> 

#### Solution: `fizzbuzz/src/lib.rs`

```rust
pub fn fizzbuzz(number: i32) -> Option<&'static str> {
    if number%3 == 0 && number%5 == 0 {
        return Some("FizzBuzz");
    } else if number%3 == 0 {
        return Some("Fizz");
    } else if number%5 == 0 {
        return Some("Buzz");
    } else {
        return None;
    }
}
```
#### What I've learned

* To create a new project just run `cargo new [project-name] --lib`(lib flag because it's not a standalone executable) and it will create the basic folder structure and the `lib.rs` file.
* `pub` keyword is the way to export anything.
* `fn` keyword is for functions.
* There is no _null_ value in Rust, so the best way to do the same is using the **Option** type. To give a value it must be `Some(value)`, to give a "null" value it must be `None`.
* `if` statements has no parenthesis
* The type of a simple string needs the `'static` lifetime (I don't know what does that mean... yet).

#### Unit Tests: `fizzbuzz/src/lib.rs`

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn fizz_cases() {
        let cases: [i32; 10] = [3, 6, 9, 12, 18, 21, 24, 27, 33, 36];

        for number in cases.iter() {
            let result: Option<&'static str> = fizzbuzz(*number);

            if let Some(text) = result {
                assert_eq!(text, "Fizz");
            } else {
                assert!(false);
            }
        }
    }

    #[test]
    fn buzz_cases() {
        let cases: [i32; 10] = [5, 10, 20, 25, 35, 40, 50, 55, 70, 80];

        for number in cases.iter() {
            let result: Option<&'static str> = fizzbuzz(*number);

            if let Some(text) = result {
                assert_eq!(text, "Buzz");
            } else {
                assert!(false);
            }
        }
    }

    #[test]
    fn fizzbuzz_cases() {
        let cases: [i32; 10] = [15, 30, 45, 60, 75, 90, 105, 120, 135, 150];

        for number in cases.iter() {
            let result: Option<&'static str> = fizzbuzz(*number);

            if let Some(text) = result {
                assert_eq!(text, "FizzBuzz");
            } else {
                assert!(false);
            }
        }
    }
}
```

#### What I've learned

* `#[whatever]` is an **attribute**, useful to add metadata to a module, crate or item. In this case the module is using `cfg` attribute to add metadata to the compiler.
* `#[test]` attribute is used to mark functions as unit tests.
* `mod whatever { ... }` is the way to create a module. By default is private (unless `pub` keyword is added).
* `let` keyword is used to create a variable (immutable by default).
* `[T;N] = [v1, v2, ..., vN]` is the way to create an Array with fixed size _N_ of type T with _v1, v2, ..., vN_ as values. 
* `for in` iterates over an _Iterator_, so `array.iter()` returns an _Iterator_.
* Maybe you are wondering why by calling `fizzbuzz` function I need to use `*number` and not `number`, well that's because `array.iter()` returns an Iterator with references (so, _number_ variable type is `&i32` and not `i32`).


### Crystal Implementation <a name="crystal"></a>

#### Solution: `fizzbuzz/fizzbuzz.cr`

```crystal
module FizzBuzz
    def fizzbuzz(number)
        if number%3 == 0 && number%5 == 0
            return "FizzBuzz"
        elsif number%3 == 0
            return "Fizz"
        elsif number%5 == 0
            return "Buzz"
        else
            return nil
        end
    end
end
```
#### What I've learned

* Syntax is very similar to Python and Ruby.
* A module is a way to group functions and classes. It's more like a namespace.
* `def` keyword is the way to create methods or functions.
* `nil` is the null type.

#### Unit Tests: `fizzbuzz/spec/fizzbuzz_spec.cr`

```crystal
require "spec"
require "../fizzbuzz"

include FizzBuzz

describe "FizzBuzz" do 
    it "should be 'Fizz' for multiples of 3" do
        [3, 6, 9, 12, 18, 21, 24, 27, 33, 36].each do |number|
            result = fizzbuzz(number)
            result.should eq("Fizz")
        end
    end

    it "should be 'Buzz' for multiples of 5" do
        [5, 10, 20, 25, 35, 40, 50, 55, 70, 80].each do |number|
            result = fizzbuzz(number)
            result.should eq("Buzz")
        end
    end

    it "should be 'FizzBuzz' for multiples of 3 and 5" do
        [15, 30, 45, 60, 75, 90, 105, 120, 135, 150].each do |number|
            result = fizzbuzz(number)
            result.should eq("FizzBuzz")
        end
    end
end
```

#### What I've learned

* Import a package (_spec_ in this case) or file (_fizzbuzz_ solution) is very similar to Node.js.
* `include` is very similar to Java's static import, I would have had to write every _fizzbuzz_ call like `Fizzbuzz::fizzbuzz` without it.
* Test look very similar to Mocha Framework in Javascript.

### Kotlin Solution <a name="kotlin"></a>

#### Configuration: `fizzbuzz/gradle.build`

```groovy
plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.3.31'
}
 
repositories {
    mavenCentral()
}
 
dependencies {
    implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31')
    testImplementation('org.junit.jupiter:junit-jupiter-api:5.4.2')
    testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2')
}
 
test {
    useJUnitPlatform()
}
```

#### What I've learned

* Gradle configuration is just like any Java project, meh.
* I tried to use built-in Test suite but I couldn't find out how, so I ended up using JUnit 5.

#### Solution: `fizzbuzz/src/main/kotlin/FizzBuzz.kt`

```kotlin
fun fizzbuzz(number: Int): String? {
    if (number%3 == 0 && number%5 == 0) {
        return "FizzBuzz"
    } else if (number%3 == 0) {
        return "Fizz"
    } else if (number%5 == 0) {
        return "Buzz"
    } else {
        return null
    }
}
```

#### What I've learned

* I didn't need to create a class and I really liked that, just like any scripting programming language.
* `func` keyword is the way to create a method/function.
* Primitive types use uppercased letters.
* `String?` return type is declared because it can be null.

#### Unit tests: `fizzbuzz/src/test/kotlin/FizzBuzzTest.kt`

```kotlin
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test

class FizzBuzzTest {

    @Test
    @DisplayName("It should be 'Fizz' for multiples of 3")
    fun shouldBeFizzForMultiplesOfThree() {
        val cases: IntArray = intArrayOf(3, 6, 9, 12, 18, 21, 24, 27, 33, 36)
        cases.iterator().forEach {
            assertEquals(fizzbuzz(it), "Fizz")
        }
    }

    @Test
    @DisplayName("It should be 'Buzz' for multiples of 5")
    fun shouldBeBuzzForMultiplesOfFive() {
        val cases: IntArray = intArrayOf(5, 10, 20, 25, 35, 40, 50, 55, 70, 80)
        cases.iterator().forEach {
            assertEquals(fizzbuzz(it), "Buzz")
        }
    }

    @Test
    @DisplayName("It should be 'FizzBuzz' for multiples of 3 and 5")
    fun shouldBeFizzBuzzForMultiplesOfThreeAndFive() {
        val cases: IntArray = intArrayOf(15, 30, 45, 60, 75, 90, 105, 120, 135, 150)
        cases.iterator().forEach {
            assertEquals(fizzbuzz(it), "FizzBuzz")
        }
    }
}
```

#### What I've learned

* `intArrayOf` is the way to create an Array of Integers and the type is `IntArray`.
* `val` is for readonly variables.
* There is no way to iterate over the array itself, it's only through an `Iterator`.
* `forEach` method receives a function and if there isn't an explicit parameter in the function definition then it will be named `it` by default.

### Elixir Solution <a name="elixir"></a>

#### Solution: `fizzbuzz/lib/fizzbuzz.ex`

```elixir
defmodule Fizzbuzz do

  def fizzbuzz(number) do
    cond do
      rem(number, 3) == 0 && rem(number, 5) == 0 -> "FizzBuzz"
      rem(number, 3) == 0 -> "Fizz"
      rem(number, 5) == 0 -> "Buzz"
      true -> nil
    end
  end
end
```

#### What I've learned

* `defmodule` is the way to create a module (a group of functions, think about a class in OOP).
* Functions and variables are created with `def` keyword.
* `cond` is like a `switch` statement but with boolean conditions.
* Elixir is a functional programming language, so everything is a function.
* `nil` is the null type.
* `rem` is the way to calculate modulus.

```elixir
defmodule FizzbuzzTest do
  use ExUnit.Case
  doctest Fizzbuzz

  test "should be 'Fizz' for multiples of 3" do
    Enum.each([3, 6, 9, 12, 18, 21, 24, 27, 33, 36], fn x -> 
      assert(Fizzbuzz.fizzbuzz(x) == "Fizz") 
    end)
  end

  test "should be 'Buzz' for multiples of 5" do
    Enum.each([5, 10, 20, 25, 35, 40, 50, 55, 70, 80], fn x -> 
      assert(Fizzbuzz.fizzbuzz(x) == "Buzz") 
    end)
  end

  test "should be 'FizzBuzz' for multiples of 3 and 5" do
    Enum.each([15, 30, 45, 60, 75, 90, 105, 120, 135, 150], fn x -> 
      assert(Fizzbuzz.fizzbuzz(x) == "FizzBuzz") 
    end)
  end
end
```

#### What I've learned

* `fn` is an anonymous function (like a lambda).
* `Enum` module is useful to work with Collections.

### Conclusion <a name="conclusion"></a>

Golang, Rust were the hardest ones, but I can't wait to learn more about them.
Kotlin is much like Java and was the only programming language that needed an external build system to run the code.

Thank you so much for reading, Did you like the experiment? 🤓.

Here is the Github repository:

{% github jorgeramon/learning-languages %}