Note: (!b && !c && d) || (b && !c && !d) || (a && !b && !d) || (!a && b && c) || (a && !c)
Ten kalkulator: https://www.dcode.fr/boolean-expressions-calculator
Daje taki rezultat (gdzie ⊼ to wielo-wejściowy NAND):
(a ⊼ ! b ⊼ ! d) ⊼ (a ⊼ ! c) ⊼ (! a ⊼ b ⊼ c) ⊼ (b ⊼ ! c ⊼ ! d) ⊼ (! b ⊼ ! c ⊼ d)
ETA: https://en.wikipedia.org/wiki/NAND_logic#NOT tu jest napisane jak zrobić negacje mając tylko NAND.
ETA2: OK, na początku założyłem, że wielo-wejściowy NAND działa tak samo jak seria dwu-wejściowych NANDów. Oczywiście tak nie jest, więc mi w testach się nic nie zgadzało ;p. Tj:
NAND(a, b, c) === NAND(NOT NAND(a, b), c)
A więc trzeba po prostu zanegować wynik każdego wewnętrznego NANDa.
Czyli ostateczna formuła to (trochę źle poformatowana):
(
! (! ((! (a ⊼ ! b) ⊼ ! d) ⊼
(a ⊼ ! c)) ⊼
! ((! (! a ⊼ b) ⊼ c) ⊼
(! (b ⊼ ! c) ⊼ ! d))) ⊼
(! (! b ⊼ ! c) ⊼ d)
)
NOT a to jest, zgodnie z tym co podlinkowałem wcześniej, po prostu NAND(a, a).
Kod testujący (częściowo wygenerowany przez GPT-4):
# (!b && !c && d) || (b && !c && !d) || (a && !b && !d) || (!a && b && c) || (a && !c)
# (NOT b AND NOT c AND d) OR (b AND NOT c AND NOT d) OR (a AND NOT b AND NOT d) OR (NOT a AND b AND c) OR (a AND NOT c)
def original_logical_expression(a, b, c, d):
# Simple test:
# return (a and b) or (c and d)
#return a or b or c or d
return (
(not b and not c and d) or # B'C'D +
(b and not c and not d) or # BC'D' +
(a and not b and not d) or # AB'D' +
(not a and b and c) or # A'BC +
(a and not c) # AC'
)
class Boolean:
def __init__(self, val):
self.val = val
def __truediv__(self, other):
if isinstance(other, Boolean):
res = Boolean(not(self.val and other.val))
#print(f"nand {self} {other} -> {res}")
return res
else:
print(self, other)
raise ValueError("Operand must be a Boolean")
def __repr__(self):
return f"{id(self)&0xffff:04x}:{int(self.val)}"
def __invert__(self):
res = Boolean(not self.val)
#print(f"not {self} --> {res}")
return res
# Form that uses multi-input NANDs:
# "a NAND b NAND c" denotes here "NAND(a,b,c)"
# (a NAND NOT b NAND NOT d) NAND
# (a NAND NOT c) NAND
# (NOT a NAND b NAND c) NAND
# (b NAND NOT c NAND NOT d) NAND
# (NOT b NAND NOT c NAND d)
# Form that uses only dual-input NANDs:
# NOT (NOT ((NOT (a NAND NOT b) NAND NOT d) NAND
# (a NAND NOT c)) NAND
# NOT ((NOT (NOT a NAND b) NAND c) NAND
# (NOT (b NAND NOT c) NAND NOT d))) NAND
# (NOT (NOT b NAND NOT c) NAND d)
def nand_logical_expression(a, b, c, d):
a = Boolean(a)
b = Boolean(b)
c = Boolean(c)
d = Boolean(d)
# Simple test:
# res = (a / b) / (c / d)
#res = ~((~a) / (~b)) / ~((~c) / (~d))
res = (
~ (~ ((~ (a / ~ b) / ~ d) /
(a / ~ c)) /
~ ((~ (~ a / b) / c) /
(~ (b / ~ c) / ~ d))) /
(~ (~ b / ~ c) / d)
)
return res.val
# Define all possible combinations of a, b, c, d
combinations = [(i, j, k, l) for i in [False, True]
for j in [False, True]
for k in [False, True]
for l in [False, True]]
print("a", "b", "c", "d", " output (org+nand)")
for comb in combinations:
a, b, c, d = comb
org_output = original_logical_expression(a, b, c, d)
nand_output = nand_logical_expression(a, b, c, d)
print(int(a), int(b), int(c), int(d), " ", int(org_output), int(nand_output))
Wynik działania:
a b c d output (org+nand)
0 0 0 0 0 0
0 0 0 1 1 1
0 0 1 0 0 0
0 0 1 1 0 0
0 1 0 0 1 1
0 1 0 1 0 0
0 1 1 0 1 1
0 1 1 1 1 1
1 0 0 0 1 1
1 0 0 1 1 1
1 0 1 0 1 1
1 0 1 1 0 0
1 1 0 0 1 1
1 1 0 1 1 1
1 1 1 0 0 0
1 1 1 1 0 0