Skip to content

Instantly share code, notes, and snippets.

@rylev
Created November 30, 2013 22:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rylev/7725524 to your computer and use it in GitHub Desktop.
Save rylev/7725524 to your computer and use it in GitHub Desktop.
Binary Addition with logic gates
class Array
def second
self[1]
end
end
class Integer
def one?
raise "Not Binary" unless self == 1 || self == 0
self == 1
end
end
def _or(first, second)
_nand(_nand(first,first), _nand(second,second))
end
def _and(first, second)
_nand(_nand(first, second), _nand(first, second))
end
def _nand(first, second)
first.one? && second.one? ? 0 : 1
end
def _nor(first, second)
_not(_or(first, second))
end
def _not(bit)
_nand(bit, bit)
end
def _xor(first, second)
_and(_or(first, second), _nand(first, second))
end
def _xnor(first, second)
_not(xor(first, second))
end
def sum(first, second)
_xor(first, second)
end
def carry(first, second)
_and(first, second)
end
def half_adder(first, second)
[sum(first, second), carry(first, second)]
end
def full_adder(first, second, carry)
first_calc = half_adder(first, second)
second_calc = half_adder(carry, first_calc.first)
[second_calc.first, _or(second_calc.second, first_calc.second)]
end
def split_reverse(string)
string.reverse.split("").map(&:to_i)
end
def print_question(first, second, operation)
puts " #{first} (#{to_decimal(first)})"
puts "#{operation} #{second} (#{to_decimal(second)})"
puts " #{"-" * first.length}"
end
def do_addition(first, second)
first, second = split_reverse(first), split_reverse(second)
answer = first.zip(second).inject(["", 0]) do |partial_answer, next_pair|
addition = full_adder(next_pair.first, next_pair.second, partial_answer.second)
[addition.first.to_s + partial_answer.first, addition.second]
end
answer.second.to_s + answer.first
end
def add(first, second)
print_question(first, second, "+")
answer = do_addition(first, second)
puts " #{answer} (#{to_decimal(answer)})"
end
def to_decimal(binary)
split_reverse(binary).each_with_index.inject(0) do |sum, next_digit|
sum + (next_digit.first * (2 ** next_digit.second))
end
end
add("00011010", "00001100")
# 00011010 (26)
# + 00001100 (12)
# --------
# 000100110 (38)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment