kimc0de

kimc0de

How to compare integer in a list and return a list of integer and its frequencies

Hi all, I’m trying to do some Leetcode exercises in elixir.
I have a function that takes an integer and it needs to return a list of lists that includes the digit frequency and the digit itself.
Something list this for example number = 11223411 => return [ [2,1], [2,2], [1,3] [1,4], [2,1] ]
The first number is the frequency and the second one is the digit itself. I’m stuck on counting the digit.

So here’s where I am

    list_of_integer = Integer.digits(number)
    list_length = len(list_of_integer)

    for n <- 0..(list_length-2) do
         if (Enum.at(list_of_integer, n) == (Enum.at(list_of_integer, n + 1))) do 
               # here am not really sure what to do next.. is it the right approach tho? :(     
         end
    end

This Leetcode is number 38 ‘count and say’. If anyone has done it, I would appreciate it if you could share your approach to solving this.

Marked As Solved

al2o3cr

al2o3cr

A general note: 99.9% of the time, if you find yourself writing Enum.at inside of a loop - especially with an index value that can go all the way to the end - you should consider a different approach. The motivation is that every call to Enum.at takes time proportional to the index so accessing elements at the end gets increasingly expensive.

For this specific problem, it’s worth calling out how this isn’t solved by Integer.digits + Enum.frequencies: the digits are only counted when they are together.

Skimming through the list of functions in Enum (you should do this, A LOT) we find a promising function: chunk_by:

An example of using this looks like:

number
|> Integer.digits()
|> Enum.chunk_by(& &1)

which would result in [[1, 1], [2, 2], [3], [4], [1, 1]] where each element of the list is a list of the same number over and over.

Then you can transform that result into the counts you’re expecting:

number
|> Integer.digits()
|> Enum.chunk_by(& &1)
|> Enum.map(fn many_digits -> [length(many_digits), hd(many_digits)] end)

Also Liked

LostKobrakai

LostKobrakai

With elixir you don’t (and usually can’t) solve issues by using loops like you’d do in non-functional languages. You’d want to look into reducing over your data to get to the expected result. for might look like a loop, but it’s not.

kokolegorille

kokolegorille

You should try not to think how You would solve this in your previous language. It will only slow You down.

A good start, as mentionned by @al2o3cr is to learn the Enum module.

A solution with Enum.reduce might look like this. What You need to understand, value don’t change, but can be transformed.

{list, previous, count} = Enum.reduce(list_of_integer, {[], nil, 0}, fn integer, {list, previous, count} -> 
  if integer == previous do
    ... return an acc with incremented count
  else
   ... return an acc with count = 1, previous = integer, update list with new element
  end
end)
mpope

mpope

Could use Enum.reduce/3!

reducer = fn (digit, acc) ->
  case acc[digit] do
    nil -> Map.put(acc, digit, 1)
    current_count -> Map.put(acc, digit, current_count + 1)
  end
end

11223411
|> Integer.to_string
|> String.graphemes
|> Enum.reduce(%{}, reducer)
|> Map.to_list

Result: [{"1", 4}, {"2", 2}, {"3", 1}, {"4", 1}]

Last Post!

LostKobrakai

LostKobrakai

A map as accumulator won‘t retain the correct order for a longer input. For short inputs it only works due to an implementation detail of small maps one shouldn‘t depend on.

Where Next?

Popular in Questions Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31494 112
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement