using System.Collections.Generic;
using System.Text.RegularExpressions;
Console.WriteLine(Foo("T&!F=!!T&!!!F"));
Console.WriteLine(Foo("A&B|A&C=A&(B|C)"));
Console.WriteLine(Foo("T&F=F"));
Console.WriteLine(Foo("T&F=T&!F"));
static bool Foo(string bar)
var (variables, variableMap) = GetVariables(rpns[0]);
var result = GetResult(rpns[0], variableMap);
for (var i = 1; i < rpns.Length; i++)
var (anotherVariables, anotherVariableMap) = GetVariables(rpns[i]);
if (!Check(variables, anotherVariables))
var anotherResult = GetResult(rpns[i], anotherVariableMap);
if (!Check(result, anotherResult))
static bool Check<T>(T[] a, T[] b)
if (a.Length != b.Length)
for (var i = 0; i < a.Length; i++)
if (a[i].CompareTo(b[i]) != 0)
static bool[] GetResult(List<Token> rpn, Dictionary<string, bool> variables)
var count = (int)Math.Pow(2, variables.Count);
var result = new bool[count];
for (var i = 0; i < count; i++)
FillVariables(i + count, variables);
result[i] = Calculate(rpn, variables);
static List<Token> Parse(string expression)
var collection = Regex.Matches(expression, @"\(|\)|[A-Z]|!|&|\|");
var variables = new Regex(@"[A-Z]");
var operations = new Regex(@"!|&|\|");
var brackets = new Regex(@"\(|\)");
string[] priority = { "!", "&", "|" };
var stack = new Stack<string>();
var list = new List<Token>();
foreach (Match match in collection)
var temp = variables.Match(match.Value);
list.Add(new Token(temp.Value, TokenType.Variable));
temp = brackets.Match(match.Value);
if (temp.Value == "(") { stack.Push(temp.Value); continue; }
var operation = stack.Pop();
list.Add(new Token(operation, TokenType.Operation));
temp = operations.Match(match.Value);
while (stack.Count != 0 && Array.IndexOf(priority, temp.Value) > Array.IndexOf(priority, stack.Peek()))
if (stack.Peek() == "(") break;
list.Add(new Token(stack.Pop(), TokenType.Operation));
list.Add(new Token(stack.Pop(), TokenType.Operation));
static bool Calculate(List<Token> rpn, Dictionary<string, bool> variables)
var result = new Stack<bool>();
foreach (var token in rpn)
result.Push(variables[token.Value]);
case TokenType.Operation:
result.Push(token.Value switch
"&" => result.Pop() & result.Pop(),
"|" => result.Pop() | result.Pop(),
_ => throw new InvalidOperationException()
static (string[], Dictionary<string, bool>) GetVariables(List<Token> rpn)
.Where(x => x.Type == TokenType.Variable)
var dictionary = new Dictionary<string, bool>();
foreach (var variable in variables)
dictionary[variable] = false;
return (variables, dictionary);
static void FillVariables(int value, Dictionary<string, bool> variables)
var binary = Convert.ToString(value, 2);
for (var i = 1; i < binary.Length; i++)
variables[variables.Keys.ElementAt(i - 1)] = binary[i] != '0';
internal readonly struct Token
public Token(string value, TokenType type)
public string Value { get; }
public TokenType Type { get; }
public override string ToString() => $"{Type}: {Value}";