# Simple Boolean Algebra Calculator

## Background

Boolean Algebra concerns representing values with letters and simplifying expressions. The following is a chart for the standard notation used: Above is what actual boolean algebra looks like. For the purposes of this code golf, this is not the syntax that will be used.

Given a string with three characters, return the solution to the expression.

• Input: The string will be a valid expression in boolean algebra. The second character will either be ".", which represents AND, or "+", which represents OR. The first and third characters will be any of 0, 1, or a capital letter. If a capital letter is given, only one letter is ever given. ie. An input will never have two variables, such as A+B.

• Output: Return the evaluation of the expression as a single character.

Explained Examples

Input => Output
A+1 => 1


A + 1 evaluates to 1 because the OR statement is overridden by 1. That is, no matter what value A takes, the presence of 1 means that the statement will always evaluate to 1.

Input => Output
B+B => B


B + B evaluates to B because the OR statement is dependent on either Bs being true. If both Bs are false, then the output would also be false. So, the statement returns B since whatever value B takes, the output would return that.

Input => Output
0.H => 0


0 . H evaluates to 0 because the AND statement is overridden by 0. That is, no matter what value H takes, the presence of 0 means that the statement will always evaluate to 0.

Input => Output
1.1 => 1


1 . 1 evaluates 1 because the AND statement requires both inputs to be 1, and since they are both 1, 1 is returned.

Examples

Input => Output
A+1 => 1
B+B => B
R+0 => R
1+1 => 1
0+0 => 0

0.0 => 0
Q.Q => Q
0.A => 0
1.C => C
1.1 => 1


This is , so shortest answer wins.

Too easy? Try Intermediate Boolean Algebra Calculator.

• @JonathanAllan there will always only be one variable given, so you will never have Z.U or A+B. Updating the question now. Nov 12, 2022 at 18:28
• Welcome to the site, I hope you'll enjoy it here.
Nov 12, 2022 at 18:31
• I find the table a bit confusing, as it doesn't match up with the problem specification very well. The challenge doesn't use overlines or adjacent characters, nor is the dot the same.
Nov 12, 2022 at 18:32
• @Adám The table is just reference for actual Boolean Algebra and not what is used in the problem. I'll update it later. Nov 12, 2022 at 18:35
• Very well specified challenge for a new user :) Nov 14, 2022 at 21:12

# JavaScript (ES6), 26 bytes

-4 bytes by using the simplified logic suggested by @loopywalt.

([x,o,y])=>~x&y!=0^o+1?x:y


Try it online!

# JavaScript (ES6), 30 bytes

Expects a string of 3 characters.

([x,o,y])=>x<1^y<1^o+1^x<y?y:x


Try it online!

### 28 bytes

If we can take three separate characters as input:

(x,o,y)=>x<1^y<1^o+1^x<y?y:x


Try it online!

### Truth table

The table below shows the intermediate results coerced to $$\0\$$ or $$\1\$$, which is implicitly done by the bitwise operators.

Note that o+1 evaluates to either 0.1 for . (coerced to $$\0\$$) or 1 for + (coerced to $$\1\$$).

 x | y | o | x<1 | y<1 | o+1 | x<y | XOR | use | result
---+---+---+-----+-----+-----+-----+-----+-----+--------
0 | 0 | . |  1  |  1  |  0  |  0  |  0  |  x  |   0
0 | 0 | + |  1  |  1  |  1  |  0  |  1  |  y  |   0
0 | 1 | . |  1  |  0  |  0  |  1  |  0  |  x  |   0
0 | 1 | + |  1  |  0  |  1  |  1  |  1  |  y  |   1
0 | A | . |  1  |  0  |  0  |  1  |  0  |  x  |   0
0 | A | + |  1  |  0  |  1  |  1  |  1  |  y  |   A
1 | 0 | . |  0  |  1  |  0  |  0  |  1  |  y  |   0
1 | 0 | + |  0  |  1  |  1  |  0  |  0  |  x  |   1
1 | 1 | . |  0  |  0  |  0  |  0  |  0  |  x  |   1
1 | 1 | + |  0  |  0  |  1  |  0  |  1  |  y  |   1
1 | A | . |  0  |  0  |  0  |  1  |  1  |  y  |   A
1 | A | + |  0  |  0  |  1  |  1  |  0  |  x  |   1
A | 0 | . |  0  |  1  |  0  |  0  |  1  |  y  |   0
A | 0 | + |  0  |  1  |  1  |  0  |  0  |  x  |   A
A | 1 | . |  0  |  0  |  0  |  0  |  0  |  x  |   A
A | 1 | + |  0  |  0  |  1  |  0  |  1  |  y  |   1
A | A | . |  0  |  0  |  0  |  0  |  0  |  x  |   A
A | A | + |  0  |  0  |  1  |  0  |  1  |  y  |   A
\_________XOR_________/

• -2 I believe by simplified logic. Nov 14, 2022 at 15:50
• @loopywalt Looking good. We can use ~x instead of x!=1 to save 2 more bytes. Nov 14, 2022 at 17:04
• So ~A goes to 1? This is confusing. Nov 14, 2022 at 17:46
• @loopywalt ~"A" is evaluated as ~0, which is -1. Because we do a bitwise AND with a Boolean, the least significant bit is isolated and end up with either 0 or 1. Nov 14, 2022 at 17:53

# Jelly, 9 bytes

Ṣ⁼ÞOṂḂṾƲṪ


A monadic Link that accepts a list of three characters as specified and yields the resulting character.

Try it online!

### How?

Note that + and . are less than all other possible characters and that their ordinals are odd ($$\43\$$) and even ($$\46\$$), respectively. Also, variables always have ordinals greater than either 0 or 1.

Ṣ⁼ÞOṂḂṾƲṪ - Link: list of characters, S = [a, o, b]
Ṣ         - sort (S) -> [o, min(a,b), max(a,b)]
... this places a variable, if present, on the right
O      -   ordinals
Ṃ     -   minimum -> 43 (o='+') or 46 (o='.')
Ḃ    -   mod two ->  1         or  0
Ṿ   -   uneval  -> '1'        or '0'
Þ       - sort (the sorted S) by:
⁼        -   equals    ('1'        or '0')
... i.e. for o='+' (OR) place any '0's at the right
or for o='.' (AND) place any '1's at the right
Ṫ - tail ...get the right-most


# Retina 0.8.2, 27 bytes

0\+|\+0|1\.|\.1

(\d?)..
$1  Try it online! Link includes test cases. Explanation: 0\+|\+0|1\.|\.1  Rule 1: OR with 0 or AND with 1 returns the other parameter. (\d?)..$1


Rule 2: Return the first parameter if it's a digit. Rule 3: Otherwise, return the second parameter. Examples:

0+0 => 0 (by rule 1)    0.0 => 0 (by rule 2)
0+A => A (by rule 1)    0.A => 0 (by rule 2)
0+1 => 1 (by rule 1)    0.1 => 0 (by rule 1)
A+0 => A (by rule 1)    A.0 => 0 (by rule 3)
A+A => A (by rule 3)    A.A => A (by rule 3)
A+1 => 1 (by rule 3)    A.1 => 1 (by rule 1)
1+0 => 1 (by rule 1)    1.0 => 0 (by rule 1)
1+A => 1 (by rule 2)    1.A => A (by rule 1)
1+1 => 1 (by rule 2)    1.1 => 1 (by rule 1)


# Python, 36 bytes

lambda s:s[-("+."[s>"1"!=s]in s)]


Attempt This Online!

#### How?

s>"1" due to lexicographic ordering this is the same as s>"0" which is the same in both our "dream ordering" and actual string ordering.

"1"!=s in standard ordering is 1>s in dream ordering.

Taken together this comprises the three cases where s>s and one equal case which we don't care about.

It remains to xor that with which operator is given.

# Python, 40 bytes (@Jonathan Allan)

lambda s:sorted(s)[~("+."["0"in s]in s)]


Attempt This Online!

# Python, 41 bytes

lambda s:sorted(s)[s.find("+."["0"in s])]


Attempt This Online!

### How?

Ideally, we would like to have an ordering 0 < variables < 1. Then we could use min and max or similar. But in fact "0" < "1" < variables.

But, as we are are ranking only 2 values we can instead

• check if "0" is one of them
• if yes: use normal string ordering
• if no: use it up-side-down

Actual algorithm step-by-step:

sort input (standard string ordering). This puts the operator in front of the operands, so we need to select index 1 or -1. It so happens that these are the values find will return if we search the original string for either operator (-1 means not found, 1 is the original position of the operator). We choose which operator to test for depending on the above: whether "0" is in the input.

• Nice golf, ~("+."["0"in s]in s) saves one more! Nov 12, 2022 at 20:51

# Python 3.8+,  46  45 bytes

lambda s:(c:='01'['+'in s])*(c in s)or max(s)


An unnamed function that accepts the string and returns a character.

Try it online!

### How?

When the operator is '+' (OR) we should return '1' if a '1' is present or a variable if present, otherwise we have '0+0' and should return '0'.

When the operator is '.' (AND) we should return '0' if a '0' is present or a variable if present, otherwise we have '1.1' and should return '1'.

The code implements this logic by constructing a character, c, which is '0' if the operator is '+' or '0' if the operator is '.' - this is (c:='01'['+'in s]) - then repeating that character once if it is present in the input string or zero times (giving '') if not - this is *(c in s) - we return this if it is non-empty otherwise we return the variable if present or the repeated, non-matching digit character - this is or max(s).

# Vyxal, 9 bytes

sµ?Cg∷=;t


Try it Online!

Port of Jonathan Allan's Jelly answer, so upvote that!

sµ?Cg∷=;t
s         # Sort
µ     ;  # Sort by:
?Cg     #  Minimum charcode of input
∷    #  Modulo two
=   #  Equals the current item
t # Last item


# x86-64 machine code, 17 bytes

66 AD 8A 16 A8 40 74 02 86 C2 9E 10 C4 0F 4A C2 C3


Try it online!

Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes the length of the string (which is always 3 and is ignored) in RDI and its address (as an array of single-byte ASCII characters) in RSI, and returns a value in AL.

In assembly:

f:  lodsw           # Load two bytes from the string into AL and AH, advancing the pointer.
mov dl, [rsi]   # Load the next byte from the string into DL.
test al, 0x40   # Check bit 6 of AL, which is 1 for letters and 0 for digits.
jz s0           # Jump if the bit is zero.
xchg dl, al     # (Otherwise: letters) Exchange DL and AL.
s0:             # At this point, AL must be a digit (as they can't be both letters).
sahf            # Set flags based on AH (which holds the operation character).
# In particular, its low bit goes into CF.
# AH can be '+', 00101011 in binary, becoming 00101100 after adding CF=1,
#        or '.', 00101110 in binary, staying  00101110 after adding CF=0.
# AL can be '0' (00110000) or '1' (00110001).
# Adding that in produces 010111xy, where x is 0 for '+' and 1 for '.',
#                                     and y is 0 for '0' and 1 for '1'.
cmovpe eax, edx # If the sum of the bits in the result is even,
#  which is true for (+,0) and (.,1), set EAX to EDX's value,
#  so that the other operand becomes the return value.
# Otherwise -- for (+,1) and (.,0) -- AL is kept unchanged.
ret             # Return.


# Javascript, 130 90 chars

s=>([x,y]=s=="+"?'01':'10',t=[s,s].sort(),s==x&s==x?x:t.includes(y)?y:t)


130 -> 90 Thanks to @Steffan

• you can remove the let s Nov 12, 2022 at 18:18
• Also, you don't need to count the f= since the function doesn't rely on it being named f. :) Nov 12, 2022 at 18:19
• Also, you can destrucutre strings like they're arrays, so ['0','1'] can just be "01" and same with the other Nov 12, 2022 at 18:23
• With a couple other golfs as well, here's 90 bytes: Try it online! Nov 12, 2022 at 18:24
• @Steffan Hey, thanks for taking part! I'm pretty new to this and I'll update my answer once I wrap my head around your solution. In the mean time, I also coded this in python with the same logic, maybe you could find some other ways to shorten it? Thanks. Nov 12, 2022 at 18:30

# Java (JDK), 43 bytes

(x,o,y)->x==(o+=~o&4|2)|y==o?o:x==(o^1)?y:x


Try it online!

Taken as three characters, returning one character.

# Python3, 116103 74 chars

lambda s:[[max(s),y:='01'[b:=s<'.']][y in s],x:='10'[b]][s==s==x]


116 => 103 Thanks to @Unrelated String

• A few easy golfs. Welcome to CG&CC! (In the future, try not to answer your own challenges so fast in a common language, though.) Nov 12, 2022 at 18:35
• @UnrelatedString Alright, will do. It was in sandbox for a day and I came up with solutions in the mean time, my bad. Nov 12, 2022 at 18:42
• 74 bytes Nov 12, 2022 at 18:46

# Charcoal, 12 bytes

ＦＩ№θ+¿№θιι⌈θ


Try it online! Link is to verbose version of code. Explanation: Port of @JonathanAllan's Python answer.

ＦＩ№θ+


Count the number of +s in the input string, then cast that to string and loop over the character (golfy way of reusing the result as a variable).

¿№θι


If the input contains that digit, then...

ι


... output the digit, otherwise...

⌈θ


... output the letter if there is one, otherwise the other digit.

# MathGolf, 9 bytes

s‼╞├$¥░=§  Try it online. Explanation:  # (e.g. input1="R+0"; input2="A.0") s # Sort the (implicit) input-string # STACK1: "+0R"; STACK2: ".0A" ‼ # Apply the following two commands separately on the same stack: ╞ # Discard the left character ├ # Extract the left character # STACK1: "0R","0R","+"; STACK2: "0A","0A","."$     # Convert the top character to its codepoint integer
#  STACK1: "0R","0R",43;    STACK2: "0A","0A",46
¥    # Modulo-2
#  STACK1: "0R","0R",1;     STACK2: "0A","0A",0
░   # Convert it to a string
#  STACK1: "0R","0R","1";   STACK2: "0A","0A","0"
=  # Get the index of this character in the string (-1 if not found)
#  STACK1: "0R",-1;         STACK2: "0A",0
§ # Modular 0-based index it into the string
#  STACK1: "R";             STACK2: "0"
# (after which the entire stack joined together is output implicitly as result)


# Ruby, 32 bytes

->s{s[s=~/0\+|\+1|1\.|\.0/?2:0]}


Try it online!

If the expression contains one of 0+, +1, 1. or .0, then the result is the RHS, otherwise it's the LHS.

### Why?

First, let's discard the case where the first and third character is the same, in that case both are good. We are left with 8 cases to handle:

RHS cases:
0+X => X
X+1 => 1
X.0 => 0
1.X => X

LHS casaes:
X+0 => X
1+X => 1
0.X => 0
X.1 => X


c i=fromEnum i+91*fromEnum(i=='1')
f x=toEnum$(if x!!1>'+'then min else max)(c$x!!0)(c\$x!!2)mod91


Try it online!

# C (gcc), 72 65 bytes

-7 bytes thanks to @ceilingcat

#define f(x)x[2*((*x-x+((*x==49)-(x==49))*91)*(x-44)>0)]


Try it online!

• @ceilingcat I didn't know macros were a valid solution format Nov 13, 2022 at 22:28

# 05AB1E, 9 bytes

{ΣIÇßÉQ}θ


Port of @JonathanAllan's Jelly answer, so make sure to upvote him as well!

Explanation:

{        # Sort the characters of the (implicit) input (based on codepoints)
Σ       # Then (stable-)sort it further by:
IÇ     #  Push the input as a list of codepoints
ß    #  Pop and push the minimum
É   #  Check if this is odd
Q  #  Check if it's equal to the current character
#  (a '0' for '+'; and a '1' for '.')
}θ      # After the sort-by, leave the last character
# (which is output implicitly as result)


f(a:o:b)|a<'1'||b=="1",o<'.'=b|a=='1'||b<"1",o>'+'=b|1>0=[a]


Try it online!

# GNU sed -r, 33

s/0\+|\+0|1\.|\.1//
s/(\d)?../\1/


I golfed this myself, honest. Though in reality it turns out to be a simple port of @Neil's answer.

Try it online!

• You should be more specific: this is GNU sed under -r. Nov 15, 2022 at 20:13

# T-SQL, 59 bytes

input is a table

SELECT iif(a+b+c in(a+'+0',a+'.1','1+'+c,'0.'+c),a,c)FROM @


Try it online

# T-SQL, 77 bytes

input is char(3) - which is kind of a string in sql

PRINT stuff(@,iif(right(@,2)in('+1','.0')or
left(@,2)in('1.','0+'),1,2),2,'')


Try it online

# Scala, 108 bytes

Golfed version. Try it online!

z=>if(z(0)<'1'||z(2)=='1')if(z(1)<'.'||z(0)=='1'&&z(1)>'+'||z(2)<'1')z(2).toString else"1"else z(0).toString


Golfed version. Try it online!

def f(Z: String): String = {
val a = Z(0)
val o = Z(1)
val b = Z(2)

if (a < '1' || b == '1') {
if (o < '.') b.toString
else if (a == '1' || b < '1') {
if (o > '+') b.toString
else "1"
} else a.toString
} else a.toString
}