Andres

Andres

Count the number of non-numeric characters in a string and then sum their values

Hello.
Trying to solve this problem I wrote the following algorithm:

string = "3340c9571y40m47ku49t9315mrvzqo667k36e"

# %{
#  "c" => 1,
#  "e" => 1,
#  "k" => 2,
#  "m" => 2,
#  "o" => 1,
#  "q" => 1,
#  "r" => 1,
#  "t" => 1,
#  "u" => 1,
#  "v" => 1,
#  "y" => 1,
#  "z" => 1
#  }
#  [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1]
# Expected result => 14

def is_numeric?(char) do
    Regex.match?(~r/^\d+$/, char)
end

def total_non_numeric_chars(string) do
    String.codepoints(string)
    |> Enum.reduce(%{}, fn char, acc ->
      cond do
        !is_numeric?(char) ->
          if Map.has_key?(acc, char),
            do: Map.update!(acc, char, &(&1 + 1)),
            else: Map.put(acc, char, 1)

        true ->
          acc
      end
    end)
    |> Map.values()
    |> Enum.sum()
end

I would like to know if is possible to avoid the nested cond and if with some patter matching or other technique.
Any suggestions to improve the algorithm is welcome.

Thanks.

Marked As Solved

michalmuskala

michalmuskala

I just thought of using the new reduce comprehensions. With that it can be a one-liner:

for << <<char>> <- string >>, char not in ?0..?9, reduce: 0, do: (acc -> acc + 1)

Also Liked

michalmuskala

michalmuskala

Since you’re summing them up at the end, I guess you don’t really need to keep the frequency map - you can just keep the sum (unless you also output the map somewhere).

With that in mind, this is how I’d write it:

def total_non_numeric_chars(string), do: loop(string, 0)

defp loop(<<char, rest::binary>>, count) when char in ?0..?9, do: loop(rest, count)
defp loop(<<_, rest::binary>>, count), do: loop(rest, count + 1)
defp loop(<<>>, count), do: count
NobbZ

NobbZ

Just be aware of the fact that is_numeric? is an unidiomatic name for a function, either we use the prefix is_ when we have guardsave predicates or we use the suffix ? when the predicate is not guardsafe.

mudasobwa

mudasobwa

Creator of Cure

It could be a one-liner even without new fancy reduce comprehension option :slight_smile:

length(for << char <- string >>, char not in ?0..?9, do: char)
# or
byte_size(for << char <- string >>, char not in ?0..?9, into: "", do: <<char>>)
LostKobrakai

LostKobrakai

if !is_numeric?(char) do
  Map.update(acc, char, 1, &(&1 + 1))
else
  acc
end

Where Next?

Popular in Questions Top

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
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
mathew4509
I have a list say x = ["23gh", "56kh", "97mh"] I would like to pass each element to Val in each iteration. Say, in iteration 1 -------...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

We're in Beta

About us Mission Statement