RosettaCodeData/Task/Four-bit-adder/Elixir/four-bit-adder.elixir

48 lines
1.3 KiB
Plaintext

defmodule RC do
use Bitwise
@bit_size 4
def four_bit_adder(a, b) do # returns pair {sum, carry}
a_bits = binary_string_to_bits(a)
b_bits = binary_string_to_bits(b)
Enum.zip(a_bits, b_bits)
|> List.foldr({[], 0}, fn {a_bit, b_bit}, {acc, carry} ->
{s, c} = full_adder(a_bit, b_bit, carry)
{[s | acc], c}
end)
end
defp full_adder(a, b, c0) do
{s, c} = half_adder(c0, a)
{s, c1} = half_adder(s, b)
{s, bor(c, c1)} # returns pair {sum, carry}
end
defp half_adder(a, b) do
{bxor(a, b), band(a, b)} # returns pair {sum, carry}
end
def int_to_binary_string(n) do
Integer.to_string(n,2) |> String.rjust(@bit_size, ?0)
end
defp binary_string_to_bits(s) do
String.codepoints(s) |> Enum.map(fn bit -> String.to_integer(bit) end)
end
def task do
IO.puts " A B A B C S sum"
Enum.each(0..15, fn a ->
bin_a = int_to_binary_string(a)
Enum.each(0..15, fn b ->
bin_b = int_to_binary_string(b)
{sum, carry} = four_bit_adder(bin_a, bin_b)
:io.format "~2w + ~2w = ~s + ~s = ~w ~s = ~2w~n",
[a, b, bin_a, bin_b, carry, Enum.join(sum), Integer.undigits([carry | sum], 2)]
end)
end)
end
end
RC.task