using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Expression_Evaluator
{
class Program
{
static int[] ReadInput(out int value)
{
Console.Write("Enter integer numbers to use (space-separated): ");
string s = Console.ReadLine();
string[] parts = s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
int[] a = new int[parts.Length];
for (int i = 0; i < a.Length; i++)
a[i] = int.Parse(parts[i]);
Console.Write("Enter integer value to calculate: ");
value = int.Parse(Console.ReadLine());
return a;
}
static void SolveAndPrint(int[] numbers, int targetValue)
{
int targetKey = (targetValue << numbers.Length) + (1 << numbers.Length) - 1;
HashSet<int> solvedKeys = new HashSet<int>();
Dictionary<int, int> keyToLeftParent = new Dictionary<int, int>();
Dictionary<int, int> keyToRightParent = new Dictionary<int, int>();
Dictionary<int, char> keyToOperator = new Dictionary<int, char>();
Queue<int> queue = new Queue<int>();
for (int i = 0; i < numbers.Length; i++)
{
int key = (numbers[i] << numbers.Length) + (1 << i);
solvedKeys.Add(key);
queue.Enqueue(key);
}
while (queue.Count > 0 && !solvedKeys.Contains(targetKey))
{
int curKey = queue.Dequeue();
int curMask = curKey & ((1 << numbers.Length) - 1);
int curValue = curKey >> numbers.Length;
int[] keys = new int[solvedKeys.Count];
solvedKeys.CopyTo(keys);
for (int i = 0; i < keys.Length; i++)
{
int mask = keys[i] & ((1 << numbers.Length) - 1);
int value = keys[i] >> numbers.Length;
if ((mask & curMask) == 0)
{
for (int op = 0; op < 6; op++)
{
char opSign = '\0';
int newValue = 0;
switch (op)
{
case 0: // Addition
newValue = curValue + value;
opSign = '+';
break;
case 1: // Subtraction - another value subtracted from current
newValue = curValue - value;
opSign = '-';
break;
case 2: // Subtraction - current value subtracted from another
newValue = value - curValue;
opSign = '-';
break;
case 3: // Multiplication
newValue = curValue * value;
opSign = '*';
break;
case 4: // Division - current divided by another
newValue = -1; // Indicates failure to divide
if (value != 0 && curValue % value == 0)
newValue = curValue / value;
opSign = ' ';
break;
case 5: // Division - other value divided by current
newValue = -1; // Indicates failure to divide
if (curValue != 0 && value % curValue == 0)
newValue = value / curValue;
opSign = ' ';
break;
}
if (newValue >= 0)
{
int newMask = (curMask | mask);
int newKey = (newValue << numbers.Length) + newMask;
if (!solvedKeys.Contains(newKey))
{
solvedKeys.Add(newKey);
if (op == 2 || op == 5)
{
keyToLeftParent.Add(newKey, keys[i]);
keyToRightParent.Add(newKey, curKey);
}
else
{
keyToLeftParent.Add(newKey, curKey);
keyToRightParent.Add(newKey, keys[i]);
}
keyToOperator.Add(newKey, opSign);
solvedKeys.Add(newKey);
queue.Enqueue(newKey);
}
}
}
}
}
}
if (!solvedKeys.Contains(targetKey))
Console.WriteLine("Solution has not been found.");
else
{
PrintExpression(keyToLeftParent, keyToRightParent, keyToOperator, targetKey, numbers.Length);
Console.WriteLine("={0}", targetValue);
}
}
static void PrintExpression(Dictionary<int, int> keyToLeftParent, Dictionary<int, int> keyToRightParent, Dictionary<int, char> keyToOperator,
int key, int numbersCount)
{
if (!keyToOperator.ContainsKey(key))
Console.Write("{0}", key >> numbersCount);
else
{
Console.Write("(");
PrintExpression(keyToLeftParent, keyToRightParent, keyToOperator,
keyToLeftParent[key], numbersCount);
Console.Write(keyToOperator[key]);
PrintExpression(keyToLeftParent, keyToRightParent, keyToOperator,
keyToRightParent[key], numbersCount);
Console.Write(")");
}
}
static void Main(string[] args)
{
while (true)
{
int value;
int[] numbers = ReadInput(out value);
SolveAndPrint(numbers, value);
Console.Write("More? (y/n) ");
if (Console.ReadLine().ToLower() != "y")
break;
}
}
}
}