From 8be51c0cf57e9476d6b068f1508c9988b1481bd6 Mon Sep 17 00:00:00 2001 From: Magnus von Wachenfeldt Date: Thu, 8 Feb 2024 23:24:44 +0100 Subject: [PATCH] : --- lib/protohackers/prime_time_server.ex | 42 +++++++++++++++++++++------ mix.exs | 1 + mix.lock | 3 ++ 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 mix.lock diff --git a/lib/protohackers/prime_time_server.ex b/lib/protohackers/prime_time_server.ex index 59c3560..ee0fb57 100644 --- a/lib/protohackers/prime_time_server.ex +++ b/lib/protohackers/prime_time_server.ex @@ -20,7 +20,9 @@ defmodule Protohackers.PrimeTimeServer do mode: :binary, active: false, reuseaddr: true, - exit_on_close: false + exit_on_close: false, + packet: :line, + buffer: 1024 * 100 ] case :gen_tcp.listen(port, listen_options) do @@ -49,21 +51,43 @@ defmodule Protohackers.PrimeTimeServer do ## Helpers defp handle_connection(socket) do - case recv_until_closed(socket, _buffer = "", _buffered_size = 0) do - {:ok, data} -> :gen_tcp.send(socket, data) + case parse_json(socket) do + :ok -> :ok {:error, reason} -> Logger.error("Failed to receive data: #{inspect(reason)}") end :gen_tcp.close(socket) end - @limit _100_kb = 1024 * 100 - defp recv_until_closed(socket, buffer, buffered_size) do + defp parse_json(socket) do case :gen_tcp.recv(socket, 0, 10_000) do - {:ok, data} when buffered_size + byte_size(data) > @limit -> {:error, :buffer_overflow} - {:ok, data} -> recv_until_closed(socket, [buffer, data], buffered_size + byte_size(data)) - {:error, :closed} -> {:ok, buffer} - {:error, reason} -> {:error, reason} + {:ok, data} -> + case Jason.decode(data) do + {:ok, %{"method" => "isPrime", "number" => number}} when is_number(number) -> + Logger.debug("Received valid request for number: #{number}") + response = %{"method" => "isPrime", "prime" => prime?(number)} + :gen_tcp.send(socket, [Jason.encode!(response), ?\n]) + parse_json(socket) + + other -> + Logger.debug("Received invalid request: #{inspect(other)}") + :gen_tcp.send(socket, "malformed request\n") + {:error, :invalid_request} + end + + {:error, :closed} -> + :ok + + {:error, reason} -> + {:error, reason} end end + + defp prime?(number) when is_float(number), do: false + defp prime?(number) when number <= 1, do: false + defp prime?(number) when number in [2, 3], do: true + + defp prime?(number) do + not Enum.any?(2..trunc(:math.sqrt(number)), &(rem(number, &1) == 0)) + end end diff --git a/mix.exs b/mix.exs index 7e99864..660cd75 100644 --- a/mix.exs +++ b/mix.exs @@ -22,6 +22,7 @@ defmodule Protohackers.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:jason, "~> 1.4"} # {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} ] diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..ddb949c --- /dev/null +++ b/mix.lock @@ -0,0 +1,3 @@ +%{ + "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, +}