Advertisement
Guest User

Untitled

a guest
Aug 26th, 2016
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.   @doc """
  2.    Calculates the reduced product of a set of integers
  3.  
  4.    An element of the reduced product R_k is equal to U / M_k, where U = M_0 * M_1 * ... * M_k
  5.  """
  6.   def reduced_product(l) when is_list(l) do
  7.     # Calculate the product of the set
  8.     # It isn't super readable, but &*/2 is a pointer (hence the "&") to the multiplication function, which has an arity of two, hence the "/2" at the end
  9.     # So all we're doing is multiplying each element of l by the accumulator
  10.     u = Enum.reduce(l, &*/2)
  11.  
  12.     # Divide u by each element of l to get the reduced product
  13.     # Because m will always divide u, truncate the result, to ensure that we're dealing with integers
  14.     Enum.map(l, fn(m) -> trunc(u / m) end)
  15.   end
  16.  
  17.   @doc """
  18.    Finds the mod-m reciprocal of n, i.e. mod_reciprocal(11, 38) == 7
  19.  
  20.    Uses the extended Euclidean algorithm
  21.  """
  22.   def mod_reciprocal(n, m) do
  23.     # Create a list of quotients of m and n
  24.     quotients(m, n)
  25.       # The next element t_(n+1) is determined by
  26.       # t_(n+1) = t_(n-1) - q_n * t_n
  27.       # In order to implement this, we reduce the list of quotients, starting with the tuple {0, 1}, which represents t_0 = 0 and t_1 = 1.
  28.       # Then, we calculate the tuple {t_1, t_2}, which is equal to {t_1, t_1 - q_1 * t_2}
  29.       # Then, we calculate {t_2, t_3} etc
  30.       # Until we get the tuple {t_(n-1), t_n}
  31.       |> Enum.reduce({0, 1}, fn(q, {t1, t2}) ->      {t2, t1 - q * t2} end)
  32.       # t_(n-1) is the mod reciprocal, so we only need to return the first element of the final tuple
  33.       |> elem(0)
  34.   end
  35.  
  36.   @doc """
  37.    Calculates the magic tuple of a set of integers
  38.  
  39.    The magic tuple is a set of integers such that each G_j = R_j * mod_reciprocal(R_j, M_j)
  40.  """
  41.   def magic_tuple(m) do
  42.     r = reduced_product(m)
  43.  
  44.     r
  45.       |> Enum.zip(m)
  46.       |> Enum.map(fn({r, m}) -> mod_reciprocal(r, m) end)
  47.       |> Enum.zip(r)
  48.       |> Enum.map(fn({rec, r}) -> rec * r end)
  49.   end
  50.  
  51.   @doc """
  52.    Calculates the magic tuple of a set of integers and reduces it by modulo-U, where U is the second argument
  53.  """
  54.   def magic_tuple(m, u) do
  55.     magic_tuple(m)
  56.       |> Enum.map(fn(m) -> rem(m, u) end)
  57.   end
  58.  
  59.   @doc """
  60.    Calculates the value for x such that
  61.      x % m_i = x % r_i, for each given m_i in m and each given r_i in r
  62.  """
  63.   def chinese_remainder(r, m) when is_list(r) and is_list(m) do
  64.     u = Enum.reduce(m, &*/2)
  65.  
  66.     magic_tuple(m)
  67.       |> Enum.zip(r)
  68.       |> Enum.map(fn({g, r}) -> g * r end)
  69.       |> Enum.map(fn(g) -> mod(g, u) end)
  70.       |> Enum.reduce(&+/2)
  71.       |> mod(u)
  72.   end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement