a-conjecture-of-mine

An exercise on polyglossy: the same problem solved on multiple languages

commit 92f58e67c5dab7593b4eb27d519c40cfa6158206
parent 5ebfb1b49ac5de87d00137d89d22b3d55f30201a
Author: Pablo Escobar Gaviria <gark.garcia@protonmail.com>
Date:   Fri, 27 Dec 2019 21:25:13 -0200

Started further optimizing the Elixir implementation.

Diffstat:
MElixir/digital_sum.ex | 91++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 46 insertions(+), 45 deletions(-)
diff --git a/Elixir/digital_sum.ex b/Elixir/digital_sum.ex
@@ -11,69 +11,70 @@ defmodule Conjecture do
     if max < 0 or n_processes <= 0 do
       :invalid_input
     else
-      # Spawn a new process for each starting index from 0 to ``max`
-      f = fn i -> spawn fn -> get_counterexpl i, max, n_processes end end
-      pids = Enum.map 1..n_processes, f
+      parent_id = self()
 
-      # Send the current PID to each process
-      Enum.map pids, fn pid -> send pid, self() end
-      listen n_processes
+      # Spawn a new process for each starting index from 0 to `max`
+      f = fn i -> spawn fn -> counterexpl i, max, n_processes, parent_id end end
+      Enum.map 1..n_processes, f
+
+      listen n_processes, %{}
     end
   end
 
   # Listen for messages on all processes
-  def listen 0 do :ok end
-
-  def listen n do
-    receive do
-      :ok -> listen (n - 1)
-      msg -> msg
-    end
-  end
+  def listen 0, _ do :ok end
 
-  def get_counterexpl start, max, n_processes do
+  def listen n, sums_cache do
     receive do
-      parent_pid ->
-        case counterexpl start, max, n_processes, %{} do
-          :found -> send parent_pid, :fail
-          _ -> send parent_pid, :ok
+      :ok -> listen (n - 1), sums_cache
+      :fail -> :fail
+      {child_id, m} ->
+        if Map.has_key? sums_cache, m do
+          send child_id, sums_cache[m]
+          listen n, sums_cache
+        else
+          sum_m = sum m
+          send child_id, sum_m
+          listen m, Map.put(sums_cache, m, sum_m)
         end
     end
   end
 
-  def counterexpl a, max, n_processes, sums_cache do
-    case iter a, 0, sums_cache do
-      :found -> :found
-      sums_cache_updated ->
-        if a + n_processes <= max do
-          counterexpl (a + n_processes), max, n_processes, sums_cache_updated
-        else
-          sums_cache_updated
-        end
+  def counterexpl a, max, step, parent_id do
+    cond do 
+      iter a, 0, parent_id -> send parent_id, :found
+      a + step <= max ->
+        counterexpl (a + step), max, step, parent_id
+      true -> send parent_id, :ok
     end
   end
 
-  def iter a, b, sums_cache do
-    case test a, b, sums_cache do
-      :found -> :found
-      sums_cache_updated ->
-        if b + 1 < a do
-          iter a, b + 1, sums_cache_updated
-        else
-          sums_cache_updated
-        end
+  def iter a, b, parent_id do
+    IO.puts (test a, b, parent_id)
+    cond do
+      test a, b, parent_id -> true
+      b + 1 < a -> iter a, b + 1, parent_id
+      true -> false
     end
   end
 
-  def test a, b, sums_cache do
-    {sums_cache_a, sum_a} = lookup sums_cache, a
-    {sums_cache_b, sum_b} = lookup sums_cache_a, b
-    {sums_cache_a_b, sum_a_b} = lookup sums_cache_b, a + b
+  def test a, b, parent_id do
+    self_id = self()
+    send parent_id, {self_id, a}
 
-    if 0 != rem(sum_a_b - sum_a - sum_b, 9) do
-      :found
-    else
-      sums_cache_a_b
+    receive do
+      sum_a ->
+        send parent_id, {self_id, b}
+
+        receive do
+          sum_b ->
+            send parent_id, {self_id, a + b}
+
+            receive do
+              sum_a_b ->
+                 0 != rem(sum_a_b - sum_a - sum_b, 9)
+            end
+        end
     end
   end