Yesterday I decided to join HackerRank and start doing the challenges in the Functional Programming section as a way to keep learning more Elixir.
Rather than call my initial function, HackerRank sends along all the params via input text (line by line by line). So rather than focusing on writing functions to solve the main problem, I spend my time trying to get all the input and put it together in a usable form so I can them start the challenge.
I’m just wondering if anyone has any tips for handling this issue.
Here’s a link to an example:
I ended up creating a function to just read line input until :eof, but I’m going to have to tweak it for each problem and that seems a bit odd to me.
Thought I’d ask just in case I’m missing something. I just started so I don’t know if the whole site is this way or not. I like Exercism.io more, but I’m always on the lookout for sites to do some challenges as a break from the norm.
HackerRank was one of the sites I started with, but starting from scratch with the input parser for every exercise, as well as beeing forced to develop on their site were the main showstoppers for me.
I left any similar site after I found exercism.io where I was able to develop with any IDE I like.
Also it feels as if my voice as a community member is much more valuable than in other sites of this kind, just because exercism.io is open source.
def read_int do
IO.gets("") |> String.trim |> String.to_integer
end
def read_int_list do
IO.gets("") |> String.trim |> String.split(" ") |> Enum.map(&String.to_integer/1)
end
For the Armies puzzle, I used the following to try and optimize the IO. However, I was never able to get all test cases passing without timeouts and I gave up.
def run do
[[army_cnt, _]| queries] = read_file()
output =
queries
|> solve(army_cnt)
|> Enum.join("\n")
IO.write(:stdio, output)
end
def read_file do
Enum.map(IO.stream(:stdio, :line), fn line ->
line
|> String.trim
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
end)
end
I’ve only been playing with HR for a couple of days, but the below function has been working for me in most instances (though it may well be suboptimal). It translates an input of integers on an arbitrary number of lines into function arguments (I’ve used hd/1, tl/1, etc. to parse the lines into specific args). I then just pass the input to a main function that carries out the problem-specific logic. (And of course, I’ve occasionally tweaked Solution.input/0 for specific problems’ needs, e.g. calling Enum.map(&String.to_float/1) at the end instead.)
defmodule Solution
def input do
IO.stream(:stdio, :line)
|> Enum.to_list
|> Enum.map(&String.trim/1)
|> Enum.map(&String.to_integer/1)
end
def main(list) do
# code goes here
end
end
Solution.input |> Solution.main
I would note that at least one of the first HR problems seems broken for Elixir – the problem asks you to output an arbitrary list of length n but two of the test cases erroneously require an output of the input integer n. Someone pointed this out 10 months ago, but it was never fixed (and the admin response suggested, at least to me, that the admin didn’t really understand Elixir as a language) – which does not inspire confidence in HR (so maybe exercism.io and/or codewars.com would be better…).