import numpy

def half_adder(a, b):
    print("half adding: ", a, b)
    # Compute the XOR to obtain the sum bit S.
    s = numpy.bitwise_xor(a, b)

    # Compute the carry bit C
    c = numpy.bitwise_and(a, b)
    return c, s

def full_adder(a, b, cin):
    print("full adding", a, b, cin)
    # Half add Xs and Xc.
    cout1, s1 = half_adder(a, b)

    # Half add Ys and Yc using the sum from previous half add (xs)
    cout2, s2 = half_adder(cin, cout1)

    # OR the carry from each half-adders
    s = numpy.bitwise_or(s1, cout1)


    return cout2, s

def zero_pad(bin: str, desired_length: int):
    return bin.zfill(desired_length)

def ripple_carry(bin1: str, bin2: str, fasit: str):
    if len(bin1) > len(bin2):
        bin2 = zero_pad(bin2, len(bin1))
    elif len(bin2) > len(bin1):
        bin1 = zero_pad(bin1, len(bin2))
    
    carry, sum_bit = half_adder(int(bin1[-1]), int(bin2[-1]))
    sum_bits = [str(sum_bit)]

    for i in range(len(bin1) - 1, 0, -1):
        carry, sum_bit = full_adder(int(bin1[i]), int(bin2[i]), carry)
        sum_bits.insert(0, str(sum_bit))
    
    if carry == 1:
        sum_bits.insert(0, str(carry))
    
    stringbin = ''.join(sum_bits)

    if stringbin == fasit:
        print("Korrekt", stringbin)
    else:
        print("Feil", stringbin, "should be: ", fasit)
    return stringbin



ripple_carry("00", "01", "01") #01
# ripple_carry("00", "10", "10") #10
# ripple_carry("00", "11", "11") #11

# ripple_carry("01", "00", "01") #01
# ripple_carry("01", "01", "10") #10
# ripple_carry("01", "10", "11") #11
# ripple_carry("01", "11", "100") #100

# ripple_carry("10", "00", "10") #10
# ripple_carry("10", "01", "11") #11
# ripple_carry("10", "10", "100") #100
# ripple_carry("10", "11", "101") #101

# ripple_carry("11", "00", "11") #11
# ripple_carry("11", "01", "100") #100
# ripple_carry("11", "10", "101") #101
# ripple_carry("11", "11", "110") #110




