defmodule Hourrank24 do def input() do IO.stream(:stdio, :line) |> Enum.map(&String.trim/1) end def output(item) do item |> IO.write end def main(processor) do input() |> processor.process() |> output() end end defmodule Hourrank24.Processor do @callback process(list(String.t)) :: String.t end defmodule Hourrank24.StrongPassword do @behaviour Hourrank24.Processor @min_length 6 @numbers '0123456789' |> MapSet.new @lower_case 'abcdefghijklmnopqrstuvwxyz' |> MapSet.new @upper_case 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |> MapSet.new @special_characters '!@#$%^&*()-+' |> MapSet.new @doc ~S""" iex> Hourrank24.StrongPassword.process(["3", "Ab1"]) "3\n" iex> Hourrank24.StrongPassword.process(["11", "#HackerRank"]) "1\n" """ def process([n, password]) do """ #{count(String.to_integer(n), to_charlist(password) |> MapSet.new)} """ end defp count(n, password) do min = [@numbers, @lower_case, @upper_case, @special_characters] |> Enum.map(&(miss?(&1, password))) |> Enum.filter(&(&1)) |> Enum.count() max(@min_length - n, min) end defp miss?(characters, password) do MapSet.disjoint?(characters, password) end end Hourrank24.main(Hourrank24.StrongPassword)