Как я могу улучшить свой алгоритм «Countdown Numbers Solver», чтобы найти больше решений? - PullRequest
1 голос
/ 24 апреля 2020

Как и мой школьный проект, мне нужно построить решатель для раундов Countdown Numbers & Letters. Я хотел разработать структуру, которую я мог бы использовать для создания обоих решателей, и сначала я разработал решатель Numbers. Однако, прежде чем использовать это решение для писем, мне нужно улучшить мой текущий алгоритм. Я думаю, что где-то не прав, потому что я не получаю те же результаты с другими инструментами, которые я использую для сравнения моей программы. Вот программа для моего решателя:

/// numbers_game_solver.dart

import 'dart:collection';

import 'package:trotter/trotter.dart';

/* Import statements was package-based, I turned them into relative paths for question. */
import 'number_generator.dart';
import 'operation.dart';
import 'solution.dart';
import 'solutions.dart';


/* Will try to combine numbers with operations, as shown below;
 * List<List<Operation>> operations = <Operations>[a, ,b, ,c, ,d, ,e, ,f
 *                                                   +   -   +   *   /  ]
 * Then if last operations result is equal to target, will result it.
 * If not will show closest result.
 */

const List<String> kOperators = const <String>[kOpAdd, kOpDiv, kOpMul, kOpSub];


class NumbersGameSolver {
  NumbersGameSolver()
    : this.solutions = Solutions(_expectedResult);

  /* TODO: Do tests with smaller numbers and targets. */
  final List<int> _numbers = const <int>[1, 2, 3, 4]; // NumberGenerator.numbers;
  static final int _expectedResult = 15; //NumberGenerator.expectedResult;

  final Solutions solutions;

  void solve() {
    /* All permutations of operators with replacement, which will be inserted between numbers. */
    final Set<List<String>> amalgamsOperators = Amalgams<String>(_numbers.length - 1, kOperators)().toSet();

    /* There may duplicates occur in numbers list, because of this, numbers will be mapped
      using permutations of indices. */
    final List<int> indices = List<int>.generate(_numbers.length, (int index) => index);
    final Iterable<List<int>> permutationsIndices = Permutations<int>(indices.length, indices)();
    final Set<List<int>>
        permutationsNumbers = permutationsIndices.map(
                                (List<int> listPerm) => listPerm.map(
                                  (int index) => _numbers[index]
                                ).toList()
                              ).toSet();


    for (final List<int> numbers in permutationsNumbers) {
      for (final List<String> operators in amalgamsOperators) {
        Queue<int> stackNums = Queue<int>.from(numbers);    
        Queue<String> stackOprts = Queue<String>.from(operators);

        Solution tempSolution = Solution(_expectedResult);

        do {
          int left = stackNums.removeFirst(), right = stackNums.removeFirst();

          Operation tempOperation = Operation(stackOprts.removeFirst(), left, right);

          /* Record solutions current state. */
          SolutionState solutionState = tempSolution.addOperation(tempOperation);

          if (solutionState == SolutionState.currentlyValid) {
            /* If valid, add result to the current numbers stack. */
            stackNums.addFirst(tempOperation.result);
          } else if (solutionState == SolutionState.lastOperationRedundant) {
            /* If operation is redundant, dispose it and continue. */
            continue;
          } else if (solutionState == SolutionState.lastResultInvalid) {
            /* If results is invalid at any stage, dispose whole solution. */
            break;
          }

          if (solutions.addSolution(tempSolution) == true) break;
        } while (stackNums.length > 1);
      }
    }

    /* Will show only accurate solutions.
     * If there is no accurate solutions, will show solutions which results
     * are closest to the expected result.
     */
    solutions.showSolutions();
  }
}

Есть 5 классов, чтобы сократить вопрос, я добавил их в этом Суть .

Мой алгоритм следующий:

  • Правила для этого проекта таковы; Программа должна случайным образом сгенерировать 5 одиночных чисел di git и 1 двух чисел di git, где twoDigitNumber % 10 == 0 и число трех di git в виде target .
  • Я получаю перестановки 4 оператора и числа, которые будут использоваться в операциях ( Использование пакета trotter . )
  • Для каждой перестановки чисел я применяю каждую перестановку операторов; используя класс Operation и добавляя их в экземпляр Solution для каждой перестановки.
  • Я пропускаю некоторые избыточные операции в каждой итерации, и если на каком-либо этапе есть недопустимый результат, я распоряжаюсь этим решением и продолжаю , (я беру этот блог DataGenetics об этой топике c в качестве ссылки.)

Чтобы проверить мой алгоритм, я использовал числа 1, 2, 3, 4 и установите цель как 15. Результаты dcode.fr Solver такие, как есть;

15 (2 op.)
    4 + 1 = 5
    5 x 3 = 15

15 (3 op.)
    4 + 3 = 7
    7 x 2 = 14
    14 + 1 = 15

15 (3 op.)
    4 x 3 = 12
    12 + 2 = 14
    14 + 1 = 15

15 (3 op.)
    4 x 3 = 12
    2 + 1 = 3
    12 + 3 = 15

15 (3 op.)
    3 + 2 = 5
    4 - 1 = 3
    5 x 3 = 15

15 (3 op.)
    4 x 3 = 12
    12 + 1 = 13
    13 + 2 = 15

15 (3 op.)
    4 - 1 = 3
    3 + 2 = 5
    5 x 3 = 15

15 (3 op.)
    4 + 2 = 6
    6 - 1 = 5
    5 x 3 = 15

15 (3 op.)
    2 + 1 = 3
    4 x 3 = 12
    12 + 3 = 15

15 (3 op.)
    2 - 1 = 1
    4 + 1 = 5
    5 x 3 = 15

(A total of 10 solutions.)

и решения, найденные моей программой, как есть;

> SOLUTION 1 ~
    4 - 1 = 3
    3 + 2 = 5
    5 x 3 = 15

> SOLUTION 2 ~
    4 + 1 = 5
    5 x 3 = 15

(A total of 2 solutions.)

Можете ли вы скажи мне, что я неправильно думаю; Почему я не могу найти все решения? Какие альтернативные подходы я могу использовать для решения этой проблемы? Я что-то упускаю?

TY за то, что нашли время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...