You’ve possibly heard of this language recently. Elixir has been gaining publicity as a new framework called has been making exciting claims. Phoenix 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: WhatsApp Discord Pinterest Riot Games Weedmaps That peeked my interest! What will I do with such a beautiful language 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 into your terminal or command prompt: elixir -v 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 in your terminal/command prompt but we’ll get to that later. iex 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 . Of course you can call the project whatever you wish. mix new hackerrank_sol 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: . Check that everything works by running . lib/hackerrank_sol.ex mix test Let’s code! There is some code already in your file: lib/hackerrank_sol.ex We’re going to leave this and start coding below it in a new module called (you can have multiple modules in one file). Solution 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 into your terminal and you’ll be greeted by the friendly REPL (Read Evaluate Print Loop) for Elixir. Use often to find information on functions because the documentation is great. iex h() 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 we can see what IO exports and also ask for help like so: iex Here I’m using `exports` to find out what IO exports Now I’m using `h(IO.gets)` to ask Elixir what the function gets does. Holy moly, and other nice information! A quick note on the name . The just means that the function takes two arguments. Similarly means one argument and means zero arguments. The fancy name for this is the of the function. (Now you have another awesome party fact) we get an example IO.gets/2 /2 /1 /0 arity Let’s use this function in just to get a taste of what it returns. iex 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, and a b. We are given an array . It’s a list of integers. a We are given an array . It’s also a list of integers. b An element is said to be between and if: x a b All the elements in the array are factors of . a x is a factor of all the elements in . x b We then want to know how many different values of there are. x . 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 is a factor of all the elements in x b. Making sure all the elements in the array are factors of . a x Getting and processing the input This is really clean in Elixir. We have 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 function that gets a line from stdin and returns a list of numbers. IO.gets/1 getLine/0 Here’s a naive implementation that should be quite easy to follow. Feel free to use to go through the lines and see what each line is doing. iex If you want to test this function, fire up iex in your terminal using this command: . This command lets you access your mix project within iex. If you make changes to the code you can also use to recompile your work so you can play with the freshest code. iex -S mix recompile() To test this function in we type . iex Solution.getLine() Before making this code more idiomatic, let’s have a look at some great things provided by elixir. We’ve got this tag above the function. This is called a module attribute and it tells Elixir that you’ve provided documentation to the function. Type and observer your own documentation displayed in all its glory! (Notice that documentation supports markdown!) @doc getLine/0 h(Solution.getLine/0) This is beautiful professional documentation. 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 which is then converting that string into an integer. el 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 is a factor of all the elements in . x b Making sure is a factor of all the elements in . x b I’ll skip to the chase. We need to find out the greatest common divisor of the elements in the list . Then if divides into the lowest common divisor it satisfies the condition that it is a factor of all the elements of . b x b Did you instantly scream ? A quick google later for you stumble across this mathematical formula. EUCLID’S ALGORITHM finding the greatest common divisor Straight from wikipedia 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 we want to run the top version of the function. If the argument is not we’ll return it in a string. 0 0 Wait!!! We don’t want that third behaviour! This works but unfortunately the argument can be anything! Luckily we have which allow us to add constraints to the arguments. x guards We can improve this pattern matching example by adding guard like so: is_integer Look what happens when we try to pass something invalid: Taking our new guard for a test run. We get a very helpful message that specifically shows where our argument failed. We can see that a list of failed to be . It also failed to be an integer. [1,2,3] 0 We’ve now got more than enough to write our function. gcd 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 on the first two numbers: gcd Reducing -- List left to reduce------------------------------------gcd(8, 4) -- [16, 2]= 4 -- [16, 2]gcd(4, 16) -- = 4 -- gcd(4, 2) -- = 2 There is a function for doing exactly this called . This list reducing function can also be called since it’s calculating the greatest common divisor. Enum.reduce/2 gcd Calculating the lowest common multiple The lowest common multiple is much simpler now that we have a function. In fact it’s the following formula: gcd lcm( , ) = × / gcd( , ) a b a b 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 values that satisfy the tests. x In the function we’ll write, we’ll take in the highest value ( ). We’ll also take in the lowest value ( ). or the gcd of list b or the lcm of list a We’re checking first that the value from list is indeed greater than the value from list (otherwise guards fail and we return 0). gcd b lcm a is a range. The docs say this. lowest..highest “Defines a range” is basically in the way we’re using it above. The code basically creates a range of all the possible values of between the lowest and highest number, and then filters based on the two conditions. The first filter checks that is a multiple of the lcm of list . The second filter checks that is a factor of the gcf of list . Then we count the results :) 1..3 [1,2,3] x x a x b 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.