I am having a question concerning a challenge I recently tried on Hackerrank.com. I am not sure if my Elixir result is having timeout Issues because of my poor code or because of the site. I wanted to ask here first to make sure I use Elixir correctly.
Problem
The problem can be found here, but it basically wants you to delete adjacent A’s or B’s from a string of length 1 to 10^5
My Solution / Idea
My idea is to traverse the code from left to right and compare the current string with the following one. If they are the same, I am incrementing the counter within reduce.
The quick answer is that you’re treating the linked list of Elixir, which has O(n) behavior for things like length and at, as if it were an array, which has O(1) behavior for those things.
What I would do is reduce over the characters in the string and in the accumulator add a new value only if it has changed. Something like:
{_, reversed_result} =
the_string
|> String.codepoints
|> Enum.reduce({nil, []}, fn letter, {prior_letter, accumulator} ->
if prior_letter == letter do
{prior_letter, accumulator}
else
{letter, [letter | accumulator]}
end
end)
Enum.reverse(reversed_result)
|> Enum.join("")
The reversal won’t really matter with a small count of letters in the string, but when it gets long (as the problem description said it can do) it will help. The linked list is faster at prepending values to the front than appending to the end. And the Enum.reverse call at the end is highly optimized for just this sort of situation.
defmodule Hm do
def alternating_characters(<<x, x, rest::bytes>>) do
alternating_characters(<<x, rest::bytes>>)
end
def alternating_characters(<<x, rest::bytes>>) do
<<x, alternating_characters(rest)::bytes>>
end
def alternating_characters(<<x, x>>) do
alternating_characters(<<x>>)
end
def alternating_characters(<<x>>), do: <<x>>
def alternating_characters(<<>>), do: <<>>
end
I thought that it might be because of the linked list.
Sorry if it is a stupid question, but why can you use here
fn letter, {prior_letter, accumulator} -> ....
how many parameters can the function inside reduce have? I thought only 2.
I had a solution with codepoints, but thought it might be O(n) because it needs to traverse the whole string, which can be very huge. Maybe I don’t understand the idea of it yet.