Logic gates are functions which perform basic logic operations. In this problem, we will account for the following 6 logic gates: AND, OR, XOR, NAND, NOR, and XNOR. Each of these takes two boolean inputs \$ a \$ and \$ b \$, and outputs a boolean. Below are the truth tables which show the output of each gate given two inputs.
Task
Given two boolean inputs \$ a \$ and \$ b \$, return/output a list of the names of all gates which would return a Truthy value. The order doesn't matter, but the names must be in the exact format as given in the 2nd sentence of the above paragraph (not the ones in the diagram). You are also allowed to output them exclusively in lowercase, if desired.
Clarifications
- You may also output a delimiter-separated string
- I will allow leading/trailing spaces
Test Cases
Input
0 0
0 1
1 0
1 1
Output
[NOR, NAND, XNOR]
[OR, NAND, XOR]
[OR, NAND, XOR]
[OR, AND, XNOR]
This is code-golf, so the shortest code in bytes wins!
24 Answers 24
Python 3, (削除) 53 50 (削除ここまで) 49 bytes
Thanks @JonathanAllan for saving 1 byte!
lambda a,b:"NOR N"[a|b:5-a*b]+"AND X"+"NOR"[a^b:]
-
7\$\begingroup\$ I really like how you use the bitwise operations themselves for indexing. \$\endgroup\$the default.– the default.2020年04月27日 03:32:09 +00:00Commented Apr 27, 2020 at 3:32
-
2\$\begingroup\$ Unfortunately it loses the use of
&butlambda a,b:"NOR N"[a|b:5-a*b]+"AND X"+"NOR"[a^b:]is 49 bytes TIO. \$\endgroup\$Jonathan Allan– Jonathan Allan2020年04月28日 18:12:26 +00:00Commented Apr 28, 2020 at 18:12 -
\$\begingroup\$ @JonathanAllan multiplication is pretty much the same as
&, so I'll take that. Thanks! \$\endgroup\$Surculose Sputum– Surculose Sputum2020年04月28日 23:11:29 +00:00Commented Apr 28, 2020 at 23:11
J, 46 bytes
;:@'AND NAND OR NOR XOR XNOR'#~*,*:,+.,+:,~:,=
-5 bytes thanks to Bubbler
We execute a train *,*:,+.,+:,~:,= corresponding to the gates on the arguments, which will produce a single boolean mask of the results.
We then apply that mask as a filter #~ on the list of words, which is in the same order.
Note: Since the returned strings of are of unequal length, J requires them to be boxed.
-
1\$\begingroup\$ You don't need parens there for an obvious reason. But then, you can go for filtering
Ns at 42 bytes. \$\endgroup\$Bubbler– Bubbler2020年04月27日 04:19:33 +00:00Commented Apr 27, 2020 at 4:19 -
\$\begingroup\$ Well it's shorter without Evoke Gerund... (Basically replace all backticks with
,and remove the trailing 3 bytes) \$\endgroup\$Bubbler– Bubbler2020年04月27日 04:25:08 +00:00Commented Apr 27, 2020 at 4:25 -
\$\begingroup\$ Thanks Bubbler! I've taken 2 of the 3 suggestions. As for the 42 byte solution, it's clever and different enough that you can feel free to post yourself. It's similar to the python solution, and this is rare case where I think I prefer the cleanness of this single mask solution to the cleverness of the string manipulations (even though it's slightly less golfy). \$\endgroup\$Jonah– Jonah2020年04月27日 04:29:44 +00:00Commented Apr 27, 2020 at 4:29
Ruby, 49 bytes
->a,b{"#{?N[a|b]}OR #{?N[a&b]}AND X#{?N[a^b]}OR"}
Interpolates 'N' into the output string conditionally for each gate.
Alternatively, a direct port of @Surculose Sputum's excellent Python answer (be sure to upvote it!) is also 49 bytes:
->a,b{"NOR "[a|b,4]+"NAND X"[a&b,6]+"NOR"[a^b,3]}
Python 2.7, (削除) 117 (削除ここまで) (削除) 111 (削除ここまで) (削除) 102 (削除ここまで) 98 bytes
-6 bytes thanks to @math junkie!
-13 bytes thanks to @Surculose Sputum!
Try it online!
Probably could be made shorter with lambda but I don't know how to use it:
a,b=input()
s="or nand xor"
if a==b:s=s.replace("o","no")
if a&b:s=s.replace("na","a")[1:]
print s
EDIT: Yep. This program uses string manipulation to solve the problem, which I thought was simpler, but now I'm not so sure.
-
2\$\begingroup\$ Surculose Sputum's answer is compatible with Python 2 and is much shorter than yours. \$\endgroup\$TwilightSparkle– TwilightSparkle2020年04月27日 03:16:32 +00:00Commented Apr 27, 2020 at 3:16
-
2\$\begingroup\$ You can save some bytes by moving the body of each
ifstatement to the same line as theif\$\endgroup\$math junkie– math junkie2020年04月27日 03:33:58 +00:00Commented Apr 27, 2020 at 3:33 -
1\$\begingroup\$ @HighlyRadioactive I posted my answer within a minute of Surculose, so when I was writing this Surculose had not answered yet. \$\endgroup\$Cloudy7– Cloudy72020年04月27日 16:26:50 +00:00Commented Apr 27, 2020 at 16:26
-
\$\begingroup\$ There are a couple of saves here:
scan be initialized as a default argument, saving 1 byte. Getting rid ofi, and replacingi!=1andi==2directly witha==banda&bsaves another 8 bytes. Try it online! \$\endgroup\$Surculose Sputum– Surculose Sputum2020年04月27日 16:38:59 +00:00Commented Apr 27, 2020 at 16:38 -
1\$\begingroup\$ @SurculoseSputum Odd. Don't know how that one slipped by. Also, that footer thing is neat. \$\endgroup\$Cloudy7– Cloudy72020年04月27日 16:43:05 +00:00Commented Apr 27, 2020 at 16:43
J, (削除) 39 (削除ここまで) 37 bytes
[:;(_5<\'NAND NOR XNOR')}.~&.>*,+.,~:
-2 bytes thanks to @Jonah.
A solution that pretty much works like Surculose Sputum's Python 3 answer.
How it works
NB. The three segments in the new version
_5<\'NAND NOR XNOR'
'NAND NOR XNOR' NB. a length-13 string
_5<\ NB. enclose non-overlapping length-5 chunks
(which works because the three N's to filter appear at indexes 0, 5, 10)
NB. Previous version
[:;('NAND ';'NOR X';'NOR')}.~&.>*,+.,~: NB. Input: two bits as left/right args
*,+.,~: NB. evaluate AND, OR, XOR
('NAND ';'NOR X';'NOR') NB. corresponding three segments
&.> NB. pair up both sides unboxed and
}.~ NB. drop the first char from left if right is 1
[:; NB. Remove boxing and concatenate into a single vector
-
-
1\$\begingroup\$ @Jonah Nice. I knew that the N's are at nice positions, but somehow I missed that one. \$\endgroup\$Bubbler– Bubbler2020年04月28日 02:40:34 +00:00Commented Apr 28, 2020 at 2:40
-
\$\begingroup\$ Nice approach with the indexing and
.V. :) Equal-bytes alternative for the first part using the dictionary:’n€ƒxš¯š¯’4ôεI...POà\$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2020年04月28日 07:31:01 +00:00Commented Apr 28, 2020 at 7:31
JavaScript (ES6), 55 bytes
a=>b=>'1OR 3AND X5OR'.replace(/\d/g,n=>n>>a+b&1?'N':'')
How?
For each gate type, we use the sum of \$a\$ and \$b\$ to right-shift a bit mask. We test the least significant bit of the result to find out if we must return the complementary form of the gate.
a | 1 | 0 | 1 | 0 |
b | 1 | 1 | 0 | 0 |
------+---+-------+---+---------
a+b | 2 | 1 | 0 | decimal
------+---+-------+---+---------
NOR | 0 | 0 | 1 | 1
NAND | 0 | 1 | 1 | 3
XNOR | 1 | 0 | 1 | 5
JavaScript (ES6), 55 bytes
Using a template literal is just as long.
a=>b=>['N'[a|b]]+`OR ${['N'[a&b]]}AND X${['N'[a^b]]}OR`
C (gcc), (削除) 65 (削除ここまで) (削除) 60 (削除ここまで) 58 bytes
f(a,b){printf("NOR %s X%s"+(a|b),"NAND"+a*b,"NOR"+(a^b));}
-
\$\begingroup\$ The
" X"part can go in the format string to make it more idiomatic C. This direct port is kind of obfuscated for no reason because Python was using string concat, not a separate format string. I don't see any savings, though, unless any of those operators or logical versions of them like a&&b have higher precedence than+.&"NOR"[a|b]might be legal but it's not clearer and is break-even on byte count. \$\endgroup\$Peter Cordes– Peter Cordes2020年04月28日 12:19:07 +00:00Commented Apr 28, 2020 at 12:19 -
1\$\begingroup\$ @PeterCordes Interesting. Your bit about moving the
" X"part into the format string gave me the idea of moving the whole first argument into the format sting for -5 bytes - thanks! :-) \$\endgroup\$Noodle9– Noodle92020年04月28日 13:13:54 +00:00Commented Apr 28, 2020 at 13:13 -
\$\begingroup\$ @PeterCordes
&&doesn't have higher precedence than+but*does for -2 bytes! :D \$\endgroup\$Noodle9– Noodle92020年04月28日 13:27:43 +00:00Commented Apr 28, 2020 at 13:27 -
\$\begingroup\$ Cool, glad there's some C-specific golfing to do here to make this answer more interesting. :) \$\endgroup\$Peter Cordes– Peter Cordes2020年04月28日 13:44:58 +00:00Commented Apr 28, 2020 at 13:44
brainfuck, 234 bytes
>-[-[-<]>>+<]>-[<<++>+>-]<<+<<<-[+>++[++<]>]>-->>[>>>>[-]<<<<[>>+>>+<<<<-]<]<<,<,[>+<-]>[>+>+>>+<<<<-]>>>>--[>.<[-]]>>.>.>+++.>.[<]<<[>>+<<-]>+>[<[-]>[-]]<[->+<]>[>.<[-]]>+.+++.<<<<[>>>+<<<-]>>>>>>>>.<<<<++++++.<-[>>>.<<<[-]]>>>+.+++.
Takes input as two bytes (0 or 1) on stdin, outputs space-separated to stdout without trailing whitespace.
The TIO link has the 11 test case because I couldn't figure out how to type the null character into a web browser, but if you delete the second input character it will do the same thing as the 10 test-case, and if you delete both it will be the same as the 00 test-case.
Here's my annotated version (the two input bytes are b and a, their sum is c):
-[-[-<]>>+<]>- *32* from https://esolangs dot org/wiki/Brainfuck_constants#32
[<<++>+>-] 64 32 *0*
<<+<<< *0* 0 0 65 32
-[+>++[++<]>]>-- *78* 65 32 from https://esolangs dot org/wiki/Brainfuck_constants#78
>>
[>>>>[-]<<<<[>>+>>+<<<<-]<] 0 *0* 0 0 78 65 78 65 32
<<
,<, *b* a 0 0 0 0 78 65 78 65 32
[>+<-]> 0 *b plus a=c* 0 0 0 0 78 65 78 65 32
[>+>+>>+<<<<-]>>>> 0 0 c c 0 *c* 78 65 78 65 32
-- 0 0 c c 0 *c minus 2* 78 65 78 65 32
[>.<[-]]>>.>.>+++.>. 0 0 c c 0 0 78 65 78 *68* 32 (N)AND space print N if c != 2
[<]<<[>>+<<-]>> 0 0 c 0 0 *c* 78 65 78 68 32
<+>[<[-]>[-]]<[->+<]> 0 0 c 0 0 *!c* 78 65 78 68 32
[>.<[-]]>+.+++. 0 0 c 0 0 0 *82* 65 78 68 32 (N)OR print N if c == 0
< <<<[>>>+<<<-]>>> 0 0 0 0 0 *c* 82 65 78 68 32
>>>>>.<<<<++++++.< 0 0 0 0 0 *c* 88 65 78 68 32 space X
-[>>>.<<<[-]] 0 0 0 0 0 *0* 88 65 78 68 32 (N) print N if c != 1
>>>+.+++. 0 0 0 0 0 0 88 65 *82* 68 32
Retina 0.8.2, 37 bytes
00
N2N
11
ODN
\d+
OND
D
AND X
O|$
OR
Input is as a single 2-digit string (one of 00, 01, 10, or 11). Performs a series of replacements to arrive at the required output.
Explanation
AND X is a string common to all 4 outputs, so we encode the string as D.
OR appears in a bunch of places so we encode that as O.
Then, we can replace each pair of digits with a string of Ns, Os and Ds. (The 00 -> N2N and the \d+ -> OND are golfs arising from 10 and 01 yielding the same output and sharing some overlap with the output for 00.
Finally, we just replace the Os and Ds with the expanded string mentioned above and we get the required list!
-
1\$\begingroup\$ Wow, that's some serious golfing, the best I could do was 40 bytes... \$\endgroup\$Neil– Neil2020年04月27日 12:07:38 +00:00Commented Apr 27, 2020 at 12:07
Pyth, 37 bytes
AQ%"%sOR X%sOR %sAND"*R\N!M[|GHxGH&GH
Takes a list of two values as input, outputs in the form AND OR XNOR
Explanation
AQ # Q is the input. Set G:=Q[0], H:=Q[1]
% # Format a string (printf-style)
"%sOR X%sOR %sAND" # Format string
*R\N!M[|GHxGH&GH # replacement values as a list:
[ # [ ]
|GH # G or H
xGH # G xor H
&GH # G and H
!M # map each to its negation
*R\N # map each x to "N"*x
(Ab)uses the fact that in Python and thus Pyth, True == 1 and False == 0 and thus "N"*True == "N" and "N"*False == "".
-
\$\begingroup\$ Cool solution, but you can get it down to 31 bytes by porting @Surculose Sputum's answer: Try it online! \$\endgroup\$math junkie– math junkie2020年04月27日 16:15:49 +00:00Commented Apr 27, 2020 at 16:15
-
\$\begingroup\$ 29 bytes: Try it online! \$\endgroup\$math junkie– math junkie2020年04月27日 16:16:51 +00:00Commented Apr 27, 2020 at 16:16
Jelly, 23 bytes
×ばつ®ṫ.¡Ḍẹhɗ»x8ドル¦0
A monadic Link accepting a list of two integers (in [0,1]) which yields a list of characters - the gate names separated by spaces.
Try it online! Or see the test-suite.
How?
Observe that there are three outputs, aligning with the sums and that the sum \1ドル\$ and sum \2ドル\$ outputs are the sum \0ドル\$ one missing certain characters. When one-indexed the sum \1ドル\$ needs characters 1 and 11 removed while the sum \2ドル\$ one needs characters 1 and 5 removed. Furthermore \$\lfloor \frac{11}{2} \rfloor = 5\$.
×ばつ®ṫ.¡Ḍẹhɗ»x8ドル¦0 - Link: list of integers, B e.g [0,0] [1,1] [1,0] (or [0,1])
S - sum (B) 0 2 1
11 - literal eleven 11 11 11
, - pair [11,0] [11,2] [11,1]
S - sum (B) 0 2 1
: - integer division [inf,nan] [5,1] [11,1]
μ - start a new monadic link, call that X
×ばつ®ṫ.¡Ḍẹhɗ» - compressed string "NOR NAND XNOR" "NOR NAND XNOR" "NOR NAND XNOR"
€ ¦ - sparse application...
8 - ...to indices: chain's left argument
x 0 - ...action: repeat zero times "NOR NAND XNOR" "OR AND XNOR" "OR NAND XOR"
Bash + Core utilities, (削除) 53 (削除ここまで) 49 bytes
tr 01 N\0円<<<"$[1ドル|2ドル]OR $[1ドル&2ドル]AND X$[1ドル^2ドル]OR"
This is a full program. Input is passed as arguments, and the output is written to stdout.
APL (Dyalog Unicode), 30 bytes
∊'NAND ' 'NOR X' 'NOR'↓⍨ ̈∧,∨,≠
A port of my own J answer.
How it works
∊'NAND ' 'NOR X' 'NOR'↓⍨ ̈∧,∨,≠
∧,∨,≠ ⍝ AND, OR, XOR
'NAND ' 'NOR X' 'NOR'↓⍨ ̈ ⍝ Drop an N from the string segments at ones
∊ ⍝ Flatten
05AB1E, 42 bytes
.•Vs’9ìï ́ ̧•.•B»Î5γ' ̧•DŠ‚s.•B» ̄4qld•‚«IðмCè
Makes a list: ["nor nand xnor", "or nand xor", "or nand xor", "or and xnor"]; the input is read as a binary number and that corresponds to the position in the list. This could probably be reduced heavily as I see the other 05ab1e answer just uses "nand nor xnor" as its string.
x86-16 machine code, IBM PC DOS, (削除) 57 (削除ここまで) 52 bytes
Binary:
00000000: a182 0025 0101 8bd8 ba2f 0152 0ac4 7401 ...%...../.R..t.
00000010: 42b4 09cd 21ba 2801 84df 7401 42cd 215a B...!.(...t.B.!Z
00000020: 32df 7401 42cd 21c3 4e41 4e44 2058 244e 2.t.B.!.NAND X$N
00000030: 4f52 2024 OR $
Listing:
A1 0082 MOV AX, [0082H] ; load command line chars into AH/AL
25 0101 AND AX, 0101H ; ASCII convert
8B D8 MOV BX, AX ; save input to BX for later
BA 012F MOV DX, OFFSET NOR ; DX = string 'NOR'
52 PUSH DX ; save 'NOR' for later
0A C4 OR AL, AH ; OR or NOR?
74 01 JZ OUT_NOR ; is OR?
42 INC DX ; increment string pointer to skip 'N'
OUT_NOR:
B4 09 MOV AH, 9 ; DOS write string function
CD 21 INT 21H ; write to STDOUT
BA 0128 MOV DX, OFFSET NAND ; DX = string 'NAND X'
84 DF TEST BL, BH ; AND or NAND?
74 01 JZ OUT_NAND ; is AND?
42 INC DX ; increment string pointer to skip 'N'
OUT_NAND:
CD 21 INT 21H ; write string to STDOUT
5A POP DX ; Restore DX = 'NOR'
32 DF XOR BL, BH ; XOR or XNOR?
74 01 JZ OUT_XOR ; is OR?
42 INC DX ; increment string pointer to skip 'N'
OUT_XOR:
CD 21 INT 21H ; write string to STDOUT
C3 RET ; return to DOS
NAND DB 'NAND X$'
NOR DB 'NOR $'
A standalone PC DOS executable. Input via command line, output string to STDOUT.
I/O:
OIL, 81 bytes
5
1
5
NAND OR XOR
10
NAND NOR XNOR
1
9
20
10
AND OR XNOR
6
14
17
4
10
3
4
5
3
4
3
As usual with golfed OIL code, we use cells as both data and code. All the strings also serve as references to the cell #0 (which will later contain the second input), and we use cell #6 (the one containing a 1) as both a reference to cell #1, as well as the value 1.
Aceto, 67 bytes
pdA`ANpn
"Ln>"D"L
RON' Ov
"p Vu
p^`p"pX
N''XRO
irHL "<`
riMdpN'
I'm using quick storage for one of the inputs, the stack for the other. It's mostly conditionally escaped movement to avoid printing N, but I also used the reverse-and-jump-to-the-end trick for a few saved bytes.
Common Lisp, 154 bytes
Not a short answer, but relies on BOOLE, which is a function that is practically never used:
(lambda(a b)(loop for(n o)in`((and,boole-and)(nand,boole-nand)(or,boole-ior)(nor,boole-nor)(xor,boole-xor)(xnor,boole-eqv))if(/=(boole o a b)0)collect n))
Readable version:
(loop
for (name op) in `((and ,boole-and)
(nand ,boole-nand)
(or ,boole-ior)
(nor ,boole-nor)
(xor ,boole-xor)
(xnor ,boole-eqv))
unless (= (boole op a b) 0)
collect name)
All couples (name op) in the list are made of name, a symbol used for the output, and op, a constant integer value that represents a particular boolean operation.
The boole functions knows how to perform the operation based on such value. Note that xnor is the equivalence operation, namely boole-eqv.
The loop builds a list of names such that the associated operation yields a non-zero result.
Indeed, if you do:
(boole boole-nand 1 1)
The result is -2, a.k.a. -10 in binary; this is because those operations assume an infinite two's complement representation (https://comp.lang.lisp.narkive.com/OXYD1hNK/two-s-complement-representation-and-common-lisp)
Python 3, 60 bytes
Not really close to the gold, but found it interesting that just picking from the list of options is within 11 bytes of the best python answer, and more than 30 bytes smaller than the other python answer. Shows how impressive golfing those 11 bytes are imo.
Also shorter than some other langs that i think could also implement the same method.
lambda a,b:['nor nand xn','or nand x','or and xn'][a+b]+'or'
Factor, 55 bytes
[ + { "NOR NAND XNOR""OR NAND XOR""OR AND XNOR" } nth ]
Add and index into list of strings. This one's pretty boring, so here's a longer but more interesting version:
Factor, 73 bytes
[ [ or ] [ and ] [ xor ] 2tri [ "" "N"? ] tri@ "%sOR %sAND X%sOR"printf ]
My first submission in Factor! Hopefully the first of many, since this language is really cool. Technically this doesn't run on new versions of the language because I didn't put spaces after some strings, but it works on the old version TIO has. (I would use ATO, but it's offline at the moment.)
Explanation:
[ ... ] Quotation (anonymous function) taking two booleans
[ or ] [ and ] [ xor ] 2tri Apply each of the three quotations or, and, xor on the two booleans
[ "" "N"? ] tri@ Apply to each of the three results: If true, "", else "N"
"%sOR %sAND X%sOR"printf Insert each "" or "N" into the right part of the string, and print.
Io, 65 bytes
Port of Surculose Sputum's Python answer.
method(a,b,"NOR "slice(a|b).."NAND X"slice(a&b).."NOR"slice(a^b))
Charcoal, 160 bytes
×ばつN¬ΣθOR ×ばつN‹Σθ2AND ×ばつN↔⊖ΣθOR
Try it online! Link is to verbose version of code. Takes input as an array or string of two bits. Explanation: Just interpolates the Ns as appropriate based on the count of 1 bits (zero for the first N, less than 2 for the second, and absolute difference from 1 for the third).
Haskell, 78 Bytes
a?b=[h(a||b)"OR""NOR",h(a&&b)"AND""NAND",h(a/=b)"XOR""XNOR"];h x a b|x=a|9>0=b
or and xnor? \$\endgroup\$