Monthly Archives: January 2016

Elixir fun continues

These last few days I’ve continued the Elixir exercises journey on exercism.io:

Nothing fancy there, but I still picked up a few tricks. So, in no particular order ­čÖé

If you use map, the ordering of keys is not maintained as with keyword lists.
Also, there is a way to pass anonymous function to pipe as well! Behold:

defmodule Roman do
  @roman_values [
    {1000, "M"},
    {900, "CM"},
    {500, "D"},
    {400, "CD"},
    {100, "C"},
    {90, "XC"},
    {50, "L"},
    {40, "XL"},
    {10, "X"},
    {9, "IX"},
    {5, "V"},
    {4, "IV"},
    {1, "I"}
  ] # using keyowrd list instead of map because ordering is important

  @doc """
  Convert the number to a roman number.
  """
  @spec numerals(pos_integer) :: String.t
  def numerals(0) do
    ""
  end
  def numerals(number) do
    @roman_values |> Enum.find(fn({arabic, roman}) -> number >= arabic end) |> fn({arabic, roman}) ->
      roman <> numerals(number - arabic)
    end.()
  end
end

Method signature doesn’t have to match the arguments:

defmodule Gigasecond do
  @doc """
  Calculate a date one billion seconds after an input date.
  """
  @spec from({{pos_integer, pos_integer, pos_integer}, {pos_integer, pos_integer, pos_integer}}) :: :calendar.datetime
  def from(datetime) do
    datetime
      |> :calendar.datetime_to_gregorian_seconds
      |> +(1_000_000_000)
      |> :calendar.gregorian_seconds_to_datetime
  end
end

Short but sweet and still very much fun ­čÖé

Tagged , ,

Elixir on the run

Continuing with Elixir┬áproblems from┬áexercism.io, this time something completely different ­čśÇ
It’s a variation of the chess board and grains of wheat┬ástory, and basically you need to create a function that returns the total number on the chess board, along with one that returns the number of grains on given square. Not much to it, just return 2 to the power of desired square – 1 and that’s it:

def square(number) do
  :math.pow(2, number - 1) |> round
end

So this works, but there are a few issues. And one of those is nicely mentioned in tests:

NOTE: :math.pow/2 doesn’t do what you’d expect:
`:math.pow(2, 64) == :math.pow(2, 64) – 1` is true.
It’s best to avoid functions operating on floating point numbers for very large numbers.

Also, this solution throws “(ArithmeticError) bad argument in arithmetic expression” for large numbers, e.g. 32768.┬áSo, off to seek another solution. Enum.reduce/2 to the rescue:

def square(number) do
  1..number |> Enum.reduce(fn(x, acc) -> acc * 2 end)
end

It returns correct results, but for very large numbers it is rather slow. E.g. 1.2 seconds for square(262144). So, Jim Menard offered a nice solution:

use Bitwise

def square(number) do
  bsl(1, number - 1)
end

One forgets that multiplying by 2 is equal to bit shift left operation. And, of course, there is the related Bitwise.bsl/2 method that does just that.┬áNow the square(262144) runs as fast as square(1). Who says Elixir/Erlang isn’t fast! ­čśÇ

Tagged , ,

Wishful types

In the last exercise, there was some redundancy in the code I wished to eliminate.
For example, there is a type definition that defines possible week days:

@type weekday ::
  :monday |
  :tuesday |
  :wednesday |
  :thursday |
  :friday |
  :saturday |
  :sunday

So, someone invoking the meetup date calculation, would have to use one of the valid atoms for the desired day in the week.

Now, to match those agains Erlang’s calendar.day_of_the_week/1, I needed a way to match┬ásay :wednesday to 3, since day_of_the_week returns day number, not the atom fom above type.

An easy solution:

@weekdays %{
  :monday => 1,
  :tuesday => 2,
  :wednesday => 3,
  :thursday => 4,
  :friday => 5,
  :saturday => 6,
  :sunday => 7
}

No magic there, just repeat the atoms, map values from day_of_the_week on them, and off we go.

But, it would be much nicer if I could just do:

@weekdays weekday |> Enum.with_index(1) |> Enum.into(%{})

That would produce the exact same map, just in a dry way.

Another thing that could benefit from the same pattern was the schedule policy filtering.
So, say that we have a few functions we would like to map to a constant in the module and use like this:

@type schedule ::
  :first |
  :second |
  :third |
  :fourth |
  :last |
  :teenth

@schedules %{
  :first => &first/1,
  :second => &second/1,
  :third => &third/1,
  :fourth => &fourth/1,
  :last => &last/1,
  :teenth => &teenth/1
}

defp filter_by_schedule(dates, schedule) do
  @schedules[schedule] |> apply([dates])
end

defp first(dates) do
  dates |> hd
end

defp second(dates) do
  dates |> Enum.at(1)
end

defp third(dates) do
  dates |> Enum.at(2)
end

defp fourth(dates) do
  dates |> Enum.at(3)
end

defp last(dates) do
  dates |> Enum.reverse |> hd
end

defp teenth(dates) do
  dates |> Enum.find(fn({_, _, day}) ->
    day >= 13 && day <= 19
end)
end

That way, the @schedules map would be a constant, and the code would be much cleaner. Also, it would be nice if I could also:

 @schedules schedule |> Enum.map(fn(sch) -> %{sch => __info__(:functions)[sch]} end) |> Enum.into(%{})

Unfortunately, couldn’t find a way to acomplish this. So, if you have any suggestions, I’m all ears!

Tagged , ,

Elixir/Erlang interop games

Today’s exercise was related to calculating next imaginary meetup date. Rules for next date might be something along “every first friday”, “last saturday” etc.

It seems that Elixir decided to leave all Date stuff to Erlang, so today I learned how to use Erlang from Elixir. Nice! For this exercise, the Erlang’s calendar offered all the needed functions. And this is how it is used:

defp matches_weekday?(date, weekday) do
  weekdays = %{
    :monday => 1,
    :tuesday => 2,
    :wednesday => 3,
    :thursday => 4,
    :friday => 5,
    :saturday => 6,
    :sunday => 7
  }

  :calendar.day_of_the_week(date) == weekdays[weekday]
end

So, you just need to prefix the desired module with “:” and off you go. Very nice! Still have to find out how ti include custom Erlang libraries, but that was not needed here, so until next time.

Another thing I learned is how to invoke aribtrary function in run time. E.g. for this exercise, I had a set of policies to filter matched week┬ádays against. E.g. for “meetup falls on 2nd tuesday” I’d first filter out all tuesdays for the given month, and then fetch the 2nd date from the list. For another rule, e.g. “last saturday”, I’d filter out saturdays and get the last one. And I hated the idea of some giant case pattern, so decided to:

  • store those functions in a map, let’s call them filters or rule matching policies
  • fetch policy appropriate to given schedule rule
  • apply the policy to matching weekdays

And, no surprise there, there is the Kernel.apply/2 method that does just that, applies a function to a set of arguments. Let’s see it in action:

defp filter_by_schedule(dates, schedule) do
  schedule_filter = %{
    :first => &first/1,
    :second => &second/1,
    :third => &third/1,
    :fourth => &fourth/1,
    :last => &last/1,
    :teenth => &teenth/1
  }[schedule]

  schedule_filter |> apply([dates])
end

defp first(dates) do
  dates |> hd
end

defp second(dates) do
  dates |> Enum.at(1)
end

defp third(dates) do
  dates |> Enum.at(2)
end

defp fourth(dates) do
  dates |> Enum.at(3)
end

defp last(dates) do
  dates |> Enum.reverse |> hd
end

defp teenth(dates) do
  dates |> Enum.find(fn({_, _, day}) ->
    day >= 13 && day <= 19
  end)
end

So basically, the schedule filter policy is extracted from the map that maps schedule type to appropriate filter function. And the rest is easy ­čÖé

You can find the complete solution at exercism.io or Github.

Tagged , ,

Transform Elixir

In┬á“Grading (with) Elixir” I complained┬áthat using Enum.reduce/3 was a bit cumbersome for a simple transform of map values. Funny enough,┬áthe┬álast exercism.io problem I’ve been playing with, the Transform part of┬áETL kind of hints┬áwhy Enum.reduce/3 is just the right tool for the job after all. Let see why.

The exercise describes a problem in which you need to take old scrabble scoring system and convert it to the new one. The old system groups letters by their value (point) while the new one requires letters to be the keys and point their respective values, to make scoring a more enjoyable process.

So, basically, we┬áneed to take old scoring data and transform it to the new one. Let’s see how:

def transform(input) do
  input |> Enum.reduce(%{}, fn({value, keys}, acc) ->
    keys |> Enum.map(&({String.downcase(&1), value})) |> Enum.into(acc)
  end)
end

So this time, we just take the input stream, and transform the input’s values into value => key tuple list, and pack all of that into a single map.

And┬ávuala, the reduce now makes much more sense ­čÖé

As always, you can find the complete example @ Github.

And as a parting quote, here’s a┬á“deja vu” situation described from that same exercise:

Extract-Transform-Load (ETL) is a fancy way of saying, “We have some crufty, legacy data over in this system, and now we need it in this shiny new system over here, so we’re going to migrate this.”

(Typically, this is followed by, “We’re only going to need to run this once.” That’s then typically followed by much forehead slapping and moaning about how stupid we could possibly be.)

If I had a dime for every time it actually happened! ­čÖé

 

Tagged , ,

Grading (with) Elixir

The last Elixir exercise from exercism.io was short but sweet. It involved working with maps and an interesting problem of transforming one map to another, while changing the inner structure of map value(s).

To make things concrete, the task was to, starting with people grouped by grades, build the same grade grouped list of people, but this time sort them alphabetically. So, one would start with:

%{4 => ["Christopher","Jennifer", "Bart"], 6 => ["Kareem", "Anna"]}

and expect the sorted map:

%{4 => ["Bart", "Christopher","Jennifer"], 6 => ["Anna", "Kareem"]}

Now, this isn’t much of an issue code wise, but I┬áexpected there to be a method like Enum.map/2┬áthat would “remap” the values easily, but there isn’t. So, the only viable solution I could find was to actually use Enum.reduce/3:

@spec sort(Dict) :: Dict.t
def sort(db) do
  db |> Enum.reduce(%{}, fn({grade, names}, acc) ->
    Map.put(acc, grade, Enum.sort(names))
  end)
end

This essentially introduces an accumulator map that gets filled with same keys and transformed values. Nice, but kind of disappointed it didn’t support direct mapping.

EDIT: Per Martin’s hint, there is a way to use Enum.map/2, but one needs to use it in combination with Enum.into/2, like this:

@spec sort(Dict) :: Dict.t
def sort(db) do
 db |> Enum.map(fn({grade, names}) -> {grade, Enum.sort(names)} end) |> Enum.into(%{})
end

Another thing that became obvious today was that the ternary operator macro is a function, and you can use it like:

if(condition, do: x, else: y)

or

if condition, do: x, else: y

A subtle difference, but can help with readability. E.g. the last one is going to need () around it in some complex expressions.

And finally, another nice thing (comming from Javascript and Ruby I really like it) is that you can use “||” like this:

@spec grade(Dict.t, pos_integer) :: [String]
def grade(db, grade) do
  db[grade] || []
end

So, if there is a key in the map, get it’s value, otherwise return some default value, an empty list in this case.

And, as always, you can find the entire code sample at Github project.

Tagged , ,

Hello, is Elixir there?

So, another day, another … well, sorry, I just can’t find something funnier to start with! Anyway, this time it’s the “hey, let’s format some phone numbers, but let’s do it for US only” kind of problem.

And today, the highlights are:

Tuples & pattern matching

Let’s say that you have a function that knows how to split a phone number into meaningful parts (hmm, I wonder where did I get that idea?!). So you might end up with code area of that phone number, prefix and finally line number.

The question is, how do you pass that information around? Well, aside from structs, you can just use tuples. Just wrap values in curly braces and that’s it:

defp split(phone) do
  {code(phone), prefix(phone), line(phone)}
end

This effectively means that the output might be something like {“123”, “456”, “7890”}. The good thing about that, as opposed to using for example a list, is that you can easily access each member, by index, or just use pattern matching to extract values, like this:

def pretty(phone) do
  {code, prefix, line} = split(phone)
  "(#{code}) #{prefix}-#{line}"
end

That way, it’s pretty easy to pass┬ámultiple results around.

Guard clauses

Until now, I didn’t really have a use for those. But, this time, the sort of┬ácomplex number format and validation rules complicate things, and guard clauses help with the reasoning.

def number(raw) do
  case raw |> String.replace(~r/\W/, "") |> to_char_list do
    phone when length(phone) == 11 and hd(phone) == ?1 ->
      tl(phone)
    phone when length(phone) != 10 ->
      '0000000000'
    phone ->
      phone
  end |> to_string
end

This way, the rules become easy to follow. And situations like “if phone length is 11 and starts with ‘1’, then it’s a valid number but┬áremove the ‘1’ before moving on” become easy to write and follow quite nicely the natural language.

Doctest

Doctest is a great thing all modern languages support. The idea is to write examples as part of a function documentation, and have test execute those very examples. So, the phrase “the tests are the code’s documentation”┬ácomes to life in a splendid manner ­čÖé

This specific exercism.io┬áproblem had some of those already in the supplied exercise code, and I wanted to use those tests as well. If we were to use `mix`, then it would be easy, since the tool would set up┬áeverything for us. But,┬ásince exercism.io problems are meant to offer as little distraction as possible, you can’t use it out of the box.

Fortunately, there is a work around. You just need to:

  • add `doctest Phone` to the test file / module, as shown here
  • build source file, because otherwise doctest will not find the documentation
  • run tests as usual

So, for the last 2 steps, just create a shell script that does that for you. For example:

elixirc phone_number.exs && elixir phone_number_test.exs

Elixirc compiles the code, creating a beam file, tests load it and use it to run the tests / examples from documentation. And oh, forgot to show an example of such a test:

  @doc """
  Remove formatting from a phone number.

  ## Examples
  iex> Phone.number("123-456-7890")
  "1234567890"
  """
  def number(raw) do
  end

And, when executed, it reports like this:

$ ./test.sh
PhoneTest
  * doc at Phone.number/1 (4) (0.7ms)

Finished in 0.1 seconds (0.1s on load, 0.01s on tests)
1 tests, 0 failures

Randomized with seed 543612

That’s it folks!

Here’s a Github issue that related to all of this.

You can find the entire phone number solution here.

P.S. All pun intended ­čÖé

Tagged , , ,

Elixir genome

Today a triplet of Elixir problems solved ­čÖé They are all “human genome” related┬áthis time:

Aside from regular enjoyment while working with Elixir (remember? fun, fun, fun !!!), I’ve learned┬áthat you can give the head and tail in argument an assignment / name. Simplifies code definitely, here’s an example:

  def hamming_distance(strand1 = [h1|t1], strand2 = [h2|t2]) do
    if length(strand1) != length(strand2) do
      nil
    else
      hamming_distance(t1, t2) + (if h1 == h2, do: 0, else: 1)
    end
  end

As you can see, in the above function, I needed both a complete list, e.g. strand1, but also it’s head an tail. Of course, I could have used the hd/1 and tl/1 functions, but it looks far cleaner this way, at least for me.

Another cool code style I started using more is the function capturing feature:

  def histogram_with_zip(strand) do
    strand!(strand)
    Enum.zip(@nucleotides, Enum.map(@nucleotides, &(count_wo_check(strand, &1)))) |> Enum.into(%{})
  end

  defp strand!(strand) do
    strand |> Enum.map(&(nucleotide!(&1)))
  end

Basically, it allows you to use a short hand for fn(x) -> do_something(x);. It makes the code more compact and easier to read. Of course, one should not overdo it, but for now I quite like the looks of it.

Tagged , ,

A little word play in Elixir

Another day, another exercise. This time it’s the oldie but goldie, anagram detection. For the innocent ones, taken from problem’s readme:

Write a program that, given a word and a list of possible anagrams, selects the correct sublist.
Given "listen" and a list of candidates like "enlists" "google" "inlets" "banana" the program should return a list containing "inlets".

And┬áhere’s one possible┬átake on it:

defmodule Anagram do
  @doc """
  Returns all candidates that are anagrams of, but not equal to, 'base'.
  """
  @spec match(String.t, [String.t]) :: [String.t]
  def match(base, candidates) do
    candidates |> Enum.filter(fn(candidate) ->
      !equal?(base, candidate) && anagram?(base, candidate)
    end)
  end

  defp equal?(base, candidate) do
    String.downcase(base) == String.downcase(candidate)
  end

  defp anagram?(base, candidate) do
    hash(base) == hash(candidate)
  end

  defp hash(string) do
    string |> String.downcase |> String.split("") |> Enum.sort
  end
end
Tagged , ,

Another day, another Elixir fun exercise :-)

So today I’ve done another simple exercise, the┬áhttp://exercism.io/exercises/elixir/sublist/readme, or how to determine if a list is a equal, sublist, superlist or unequal to another list. So, without further ado, here’s my take on it:

defmodule Sublist do
  @doc """
  Returns whether the first list is a sublist or a superlist of the second list
  and if not whether it is equal or unequal to the second list.
  """
  def compare(a, b) do
    cond do
      a === b ->
        :equal
      length(a) <= length(b) && is_sublist(a, b)->
        :sublist
      is_sublist(b, a) ->
        :superlist
      true ->
        :unequal
    end
  end

  defp is_sublist(a, b) do
    cond do
      length(a) > length(b) ->
        false
      a === Enum.take(b, length(a)) ->
        true
      true ->
        is_sublist(a, tl(b))
    end
  end
end
Tagged , ,