Как перебрать все комбинации формулы?

449
10 сентября 2021, 16:50

Необходмио перечислить все возможные формулы произвольного размера, используются цифры 0, 1, 2, переменная x иоперации -, +, *, а также скобки. Размер выражения - число использованных операций. Например, формулы размера 1: 0+1, x*2, размера 4: x*x+2*x+1, (1+x)*1*2+0

Удалось сделать только "статически" и без скобок. Как это возможно реализовать в "движении" ??

https://repl.it/repls/AntiqueHoneydewCharactermapping //код и тамже можно выполнить его

using System;
using System.Linq;
class MainClass {
  public static bool onlyOneVariable(params char[] values) => values.Count(char.IsLetter) == 1;
  public static void Main (string[] args) {
    var formulas = ( 
      from num1 in new[] { '0', '1', '2', 'X' }
      from num2 in new[] { '0', '1', '2', 'X' }
      from op1 in new[] { '-', '+', '*' }
      where onlyOneVariable(num1, num2)
      select $"{num1} {op1} {num2} "
    );
    foreach(var formula in formulas.Take(10)) {
      Console.WriteLine(formula);
    }
  }
}
Answer 1

Рассмотрим часть задачи, где надо только сегенерировать формулы, без проверки уникальности и скобочек.

Бинарная операция, которыми являются +, - и *, всегда содержат левую сторону, правую и операнд. Например, x+1, где x -левая, 1- правая, + - операнд.

Предположим, что мы строим уравнение, и у нас уже есть левая сторона и операнд, например x+, тогда осталось добавить к нему правую сторону, которая может либо закончить выражение, например x+1, либо оставить его незаконченным, чтобы можно было операцию по добавлению правой сторны повторить x+1+.

Отсюда появляется рекурсивная функция. Я добавли только отслеживание уже использованных операций и операнодов, чтобы они в формулах не дублировались

public IEnumerable<string> GetFormulas(string[] operands, string[] operators,
            bool[] operandsUsed, bool[] operatorsUsed,
            int operCount, List<string> states)
{
    if (operCount == 0)
    {
        for (int i=0; i<operands.Length; i++)
        {
            if (operandsUsed[i]) continue;
            var oper = operands[i];
            var sb = new StringBuilder();
            foreach (var state in states) sb.Append(state);
            sb.Append(oper);
            yield return sb.ToString();
        }
    }
    else
    {       
        for (int j=0; j<operators.Length; j++)
        {
            if (operatorsUsed[j]) continue;
            var op = operators[j];
            for (int i=0; i<operands.Length; i++)
            {
                if (operandsUsed[i]) continue;
                var oper = operands[i];
                operandsUsed[i] = true;
                operatorsUsed[j] = true;
                states.Add(oper);
                states.Add(op);
                foreach(var f in GetFormulas(operands, operators,operandsUsed, operatorsUsed, operCount-1, states))
                    yield return f;
                operandsUsed[i] = false;
                operatorsUsed[j] = false;
                states.RemoveAt(states.Count-1);
                states.RemoveAt(states.Count-1);
            }
        }
    }
}

Как использовать:

var operands = new[] { "0", "1", "2", "X" };
var operators = new[] { "+", "-", "*" };
var L = 1;
foreach (var f in GetFormulas(operands,operators, 
            new bool[operands.Length], new bool[operators.Length],
            L, new List<string>()))
    Console.WriteLine(f);

Где L - может принимать значение от 0 до 3, так как у нас только максимум 3 не повторяющихся оператора.

Пример вывода:

0+1
0+2
0+X
1+0
1+2
1+X
2+0
2+1
2+X
X+0
X+1
X+2
0-1
0-2
0-X
1-0
1-2
1-X
2-0
2-1
2-X
X-0
X-1
X-2
0*1
0*2
0*X
1*0
1*2
1*X
2*0
2*1
2*X
X*0
X*1
X*2
READ ALSO
Зубчатые массивы и LINQ

Зубчатые массивы и LINQ

Задание: В каждой нечетной строке ступенчатой матрице найти произведение элементовВыбрать отрицательные и посчитать их количество, если...

403
Gravity Scale 2D

Gravity Scale 2D

В компоненте Rigidbody2D есть такой параметр как Gravity Scale каким образом он влияет на глобальный компонент гравитации? Те

141
Unity. Использование кнопки &quot;Назад&quot; для вызова метода

Unity. Использование кнопки "Назад" для вызова метода

Можно ли обойтись без методов типа Update что бы заставить кнопку "назад" вызывать какой либо метод? Хотелось бы обойтись без постоянного вызова...

109