You’ve possibly heard of this language recently. Elixir has been gaining publicity as a new framework called Phoenix has been making exciting claims.

Phoenix is advertised as a “Productive, Reliable and Fast” web framework and is built with Elixir. Before getting too excited about Phoenix I wanted to dive into Elixir and see what this mysterious language has to offer.

First things first. These companies already use Elixir:

- Discord
- Riot Games
- Weedmaps

That peeked my interest!

Today I want to show you some of the joys that Elixir provides through a small HackerRank problem.

We’ll cover, basic functions, iterating over collections, getting user input, pipes, pattern matching and guards.

Before we get started with the problem let’s install Elixir and make a project!

#### Getting started

Elixir has excellent instructions on getting up and running here!

Check that you’ve installed elixir properly by typing `elixir -v`

into your terminal or command prompt:

Elixir comes with excellent tools.

- Mix: Elixir’s build tool. It sets up your project, fetches dependencies and tests your code. It’s awesome.
- IEx: An interactive repl for testing your code on the go. I’m always typing away in it. Open it with
`iex`

in your terminal/command prompt but we’ll get to that later. - ExUnit: A simple but powerful testing framework. We won’t touch this much in this post.

Let’s get to coding this problem!

*If you’re looking for an IDE to do your Elixir coding in, I strongly recommend **VSCode** with the **vscode-elixir plugin** installed. It’s lightweight, responsive and has the goodies like syntax highlighting and autocompletion. Hint: **View -> Integrated Terminal **will open a terminal which you can then use Iex in.*

#### Starting a project

Navigate to a directory where you’d like to place your project (which is the solution to this code problem). Once you’ve navigated to this folder in your terminal, make a new project with the command `mix new hackerrank_sol`

. Of course you can call the project whatever you wish.

This creates a new folder with your Elixir project. Let’s open this folder in our favourite code editor. Our code will live inside the following file: `lib/hackerrank_sol.ex`

. Check that everything works by running `mix test`

.

#### Let’s code!

There is some code already in your `lib/hackerrank_sol.ex`

file:

We’re going to leave this and start coding below it in a new module called `Solution`

(you can have multiple modules in one file).

The question requires us to get user input. Specifically a list of numbers. Let’s open up Iex in our terminal and have a look for what we need.

Type `iex`

into your terminal and you’ll be greeted by the friendly REPL (Read Evaluate Print Loop) for Elixir. Use `h()`

often to find information on functions because the documentation is great.

Because we want to get IO from the user we will look at the IO module. List of modules here: https://hexdocs.pm/elixir/Kernel.html

In `iex`

we can see what IO exports and also ask for help like so:

Holy moly, **we get an example** and other nice information! A quick note on the name `IO.gets/2`

. The `/2`

just means that the function takes two arguments. Similarly `/1`

means one argument and`/0`

means zero arguments. The fancy name for this is the **arity **of the function. (Now you have another awesome party fact)

Let’s use this function in `iex`

just to get a taste of what it returns.

Ok! We should really actually try to solve the question now!

`Note: You can print to the console using ``IO.puts/1`

### Between Two Sets

This problem can be summarized as such:

- We are given a line with the length of two arrays,
**a**and**b.** - We are given an array
**a**. It’s a list of integers. - We are given an array
**b**. It’s also a list of integers.

An element **x** is said to be between **a** and **b** if:

- All the elements in the array
**a**are factors of**x**. **x**is a factor of all the elements in**b**.

We then want to know how many different values of **x** there are.

Check out the concrete examples given by hackerrank to clear up what’s required.

Let’s divide this problem into three pieces:

- Getting and processing the input.
- Making sure
**x**is a factor of all the elements in**b.** - Making sure all the elements in the array
**a**are factors of**x**.

#### Getting and processing the input

This is really clean in Elixir. We have `IO.gets/1`

which gets a line of input from the standard input. We will be getting 3 lines of input in this problem, and each line is a list of integers. Let’s create a general `getLine/0`

function that gets a line from stdin and returns a list of numbers.

Here’s a naive implementation that should be quite easy to follow. Feel free to use **iex** to go through the lines and see what each line is doing.

If you want to test this function, fire up iex in your terminal using this command: `iex -S mix`

. This command lets you access your mix project within iex. If you make changes to the code you can also use `recompile()`

to recompile your work so you can play with the freshest code.

To test this function in `iex`

we type `Solution.getLine()`

.

Before making this code more idiomatic, let’s have a look at some great things provided by elixir. We’ve got this `@doc`

tag above the function. This is called a module attribute and it tells Elixir that you’ve provided documentation to the `getLine/0`

function. Type `h(Solution.getLine/0)`

and observer your own documentation displayed in all its glory! (Notice that documentation supports markdown!)

We won’t dwell on this now, but you can write executable doctests in your documentation as well. Most of the time when you see examples in documentation they’re executable to make sure they’re valid. This allows for great separation of unit and integration testing.

Let’s quickly go through the funky looking line:

converted_to_int = Enum.map(split_line, fn el -> String.to_integer(el) end)

We are mapping over a list of strings, and converting each element into an integer. The following is happening:

`["1", "10", "3"] -- `

*Enum.map* --> [1, 10, 3]

Each element is being passed into the anonymous function as `el`

which is then converting that string into an integer.

The final line of a function is implicitly returned. I find this actually encourages clean coding as it’s very hard to write weird nested conditionals which return strangely.

Let’s clean this up so everyone is impressed using another awesome Elixir operator…

*We’re going to trust that every string is a valid integer (but you shouldn’t in the real world).*

#### The pipe operator

There is a pattern that has emerged in our function. Each line is taking the output of the function above it and putting it in as its first argument. Elixir gives us this cool operator: `|>`

which pipes the output from the left to the right.

Notice we remove the first argument of each function because it’s being handled by the pipe operator.

That’s input done! Now let’s tackle making sure **x** is a factor of all the elements in **b**.

#### Making sure **x** is a factor of all the elements in **b**.

I’ll skip to the chase. We need to find out the greatest common divisor of the elements in the list **b**. Then if **x** divides into the lowest common divisor it satisfies the condition that it is a factor of all the elements of **b**.

Did you instantly scream *EUCLID’S ALGORITHM*? A quick google later for **finding the greatest common divisor** you stumble across this mathematical formula.

You also remember an imperative way of coding this algorithm (from python’s standard library):

`def gcd(a, b):`

"""Calculate the Greatest Common Divisor of a and b.

Unless b==0, the result will have the same sign as b (so that

when b is divided by it, the result comes out positive).

"""

while b:

a, b = b, a%b

return a

We’re going to do even better and write our own in Elixir that uses the mathematical definition, provides great error messages and is still fast.

#### Guards and Pattern Matching

Elixir supports pattern matching as well as checking conditions on inputs to a function. Here’s a simple example of pattern matching:

What we’re saying here is that if the argument is `0`

we want to run the top version of the function. If the argument is not `0`

we’ll return it in a string.

This works but unfortunately the argument `x`

can be anything! Luckily we have **guards** which allow us to add constraints to the arguments.

We can improve this pattern matching example by adding `is_integer`

guard like so:

Look what happens when we try to pass something invalid:

We get a very helpful message that specifically shows where our argument failed. We can see that a list of `[1,2,3]`

failed to be `0`

. It also failed to be an integer.

We’ve now got more than enough to write our `gcd`

function.

There are more guards than code! (*Psst, there is a way in Elixir to create your own combination guards, but that’s out of scope for today*)

This also follows the mathematical definition of greatest common divisor! There is of course a faster way using remainders which I leave as an exercise to you. (solution)

We need to find the greatest common divisor of a whole list though…. To find the gcd of a list of numbers, we just need to reduce the numbers against a current greatest common divisor which we update with each element. I’ll use a diagram!

We start with this list:`[8, 4, 16, 2]`

Then we use `gcd`

on the first two numbers:

Reducing -- List left to reduce

------------------------------------

gcd(8, 4) -- [16, 2]

= 4 -- [16, 2]

gcd(4, 16) -- [2]

= 4 -- [2]

gcd(4, 2) -- []

= 2

There is a function for doing exactly this called `Enum.reduce/2`

. This list reducing function can also be called `gcd`

since it’s calculating the greatest common divisor.

#### Calculating the lowest common multiple

The lowest common multiple is much simpler now that we have a `gcd`

function. In fact it’s the following formula:

lcm(a,b) =a×b/ gcd(a,b)

Damn that’s a great formula. We can very easily code this up, including the reducing as demonstrated.

#### The Finale

Now that we have a way to grab input, a way to find the greatest common divisor and a way to find the lowest common multiple we almost have a way to find the solution.

We’re going to find the solution in the most boring way ever. We’re going to “loop” over each integer from the lowest common multiple to the greatest common divisor checking that the number satisfies both conditions of the problem. We’ll then count the resulting **x** values that satisfy the tests.

In the function we’ll write, we’ll take in the highest value (**or the gcd of list** **b**). We’ll also take in the lowest value (**or the lcm of list a**).

We’re checking first that the **gcd **value from list **b** is indeed greater than the **lcm** value from list **a **(otherwise guards fail and we return 0).

`lowest..highest`

is a range. The docs say this.

“Defines a range”

`1..3`

is basically `[1,2,3]`

in the way we’re using it above. The code basically creates a range of all the possible values of **x** between the lowest and highest number, and then filters based on the two conditions. The first filter checks that **x** is a multiple of the lcm of list **a**. The second filter checks that **x** is a factor of the gcf of list **b**. Then we count the results :)

We can now put our pieces together to get the input, and calculate the result:

Congratulations for reading this far! Hopefully I’ve shown you that Elixir is a pleasure to work in. The pattern matching and guard concepts allow you to enforce better preconditions regarding what your functions will take.

Pattern matching goes a lot farther than what’s shown here, and it really makes for readable, lovely code. Full solution to the hackerrank code here.

I haven’t covered how awesome the testing is in this language, or the fact that Elixir 1.6 comes with a code formatter. I didn’t even mention tail recursion or the actor model or how easy concurrent programming can be in this language.

I hope you enjoyed this whirlwind tour, and please leave a comment if you use Elixir or have been intrigued by this post! I also love applause and really appreciate it if you enjoyed this post.