Помогите мне завершить последнюю часть моего приложения? Он решает любую игру обратного отсчета на канале 4 путем перебора всех возможных уравнений

Для тех, кто не знаком с игрой. Вам дано 8 чисел, и вы должны достичь цели, используя +, -, / и *.

Итак, если цель - 254, а ваши игровые номера - 2, 50, 5, 2, 1, вы ответите вопрос правильно, сказав 5 * 50 = 250. Тогда 2 + 2 будет четыре. Добавьте это, чтобы получить 254.

Некоторые видео из игры находятся здесь:

Видео 1 видео 2

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

Однако он содержит недостаток, потому что все решения решаются следующим образом: ((((1 + 1) * 2) * 3) * 4). Это не меняет скобки, и это вызывает у меня головную боль.

Поэтому я не могу решить все уравнения. Например, при

Цель 16 и числа 1,1,1,1,1,1,1,1 он терпит неудачу, хотя должен выполнить (1 + 1 + 1 + 1) * (1 + 1 + 1 + 1) = 16.

Я бы хотел, чтобы кто-нибудь помог закончить это ... на любом языке.

Вот что я написал на данный момент:

 #!/usr/bin/env perl

use strict;
use warnings;

use Algorithm::Permute;

# GAME PARAMETERS TO FILL IN
my $target = 751;
my @numbers = ( '2', '4', '7', '9', '1', '6', '50', '25' );


my $num_numbers = scalar(@numbers);

my @symbols = ();

foreach my $n (@numbers) {
    push(@symbols, ('+', '-', '/', '*'));
}

my $num_symbols = scalar(@symbols);

print "Symbol table: " . join(", ", @symbols);

my $lst = [];
my $symb_lst = [];

my $perms = '';
my @perm = ();

my $symb_perms = '';
my @symb_perm;

my $print_mark = 0;
my $progress = 0;
my $total_perms = 0;

my @closest_numbers;
my @closest_symb;
my $distance = 999999;

sub calculate {
    my @oprms = @{ $_[0] };
    my @ooperators = @{ $_[1] };

    my @prms = @oprms;
    my @operators = @ooperators;

    #print "PERMS: " . join(", ", @prms) . ", OPERATORS: " . join(", ", @operators);

    my $total = pop(@prms);

    foreach my $operator (@operators) {
        my $x = pop(@prms);

        if ($operator eq '+') {
            $total += $x;
        }
        if ($operator eq '-') {
            $total -= $x;
        }
        if ($operator eq '*') {
            $total *= $x;
        }
        if ($operator eq '/') {
            $total /= $x;
        }
    }
    #print "Total: $total\n";

    if ($total == $target) {
        #print "ABLE TO ACCURATELY SOLVE WITH THIS ALGORITHM:\n";
        #print "PERMS: " . join(", ", @oprms) . ", OPERATORS: " . join(", ", @ooperators) . ", TOTAL=$total\n";
        sum_print(\@oprms, \@ooperators, $total, 0);
        exit(0);
    }

    my $own_distance = ($target - $total);
    if ($own_distance < 0) {
        $own_distance *= -1;
    }

    if ($own_distance < $distance) {
        #print "found a new solution - only $own_distance from target $target\n";
        #print "PERMS: " . join(", ", @oprms) . ", OPERATORS: " . join(", ", @ooperators) . ", TOTAL=$total\n";
        sum_print(\@oprms, \@ooperators, $total, $own_distance);
        @closest_numbers = @oprms;
        @closest_symb = @ooperators;
        $distance = $own_distance;
    }

    $progress++;
    if (($progress % $print_mark) == 0) {
        print "Tested $progress permutations. " . (($progress / $total_perms) * 100) . "%\n";
    }
}

sub factorial {
    my $f = shift;
    $f == 0 ? 1 : $f*factorial($f-1);
}

sub sum_print {
    my @prms = @{ $_[0] };
    my @operators = @{ $_[1] };
    my $total = $_[2];
    my $distance = $_[3];
    my $tmp = '';

    my $op_len = scalar(@operators);

    print "BEST SOLUTION SO FAR: ";
    for (my $x = 0; $x < $op_len; $x++) {
        print "(";
    }

    $tmp = pop(@prms);
    print "$tmp";

    foreach my $operator (@operators) {
        $tmp = pop(@prms);
        print " $operator $tmp)";
    }

    if ($distance == 0) {
        print " = $total\n";
    }
    else {
        print " = $total (distance from target $target is $distance)\n";
    }
}

# look for straight match
foreach my $number (@numbers) {
    if ($number == $target) {
        print "matched!\n";
    }
}

for (my $x = 1; $x < (($num_numbers*2)-1); $x++) {
    $total_perms += factorial($x);
}

print "Total number of permutations: $total_perms\n";
$print_mark = $total_perms / 100;
if ($print_mark == 0) {
    $print_mark = $total_perms;
}

for (my $num_size=2; $num_size <= $num_numbers; $num_size++) {
    $lst = \@numbers;
    $perms = new Algorithm::Permute($lst, $num_size);

    print "Perms of size: $num_size.\n";

    # print matching symb permutations
    $symb_lst = \@symbols;
    $symb_perms = new Algorithm::Permute($symb_lst, $num_size-1);

    while (@perm = $perms->next) {
        while (@symb_perm = $symb_perms->next) {
            calculate(\@perm, \@symb_perm);
        }

        $symb_perms = new Algorithm::Permute($symb_lst, $num_size-1);
    }
}

print "exhausted solutions";
print "CLOSEST I CAN GET: $distance\n";
sum_print(\@closest_numbers, \@closest_symb, $target-$distance, $distance);
exit(0);

Вот пример вывода:

[15:53: /mnt/mydocuments/git_working_dir/countdown_solver$] perl countdown_solver.pl
Symbol table: +, -, /, *, +, -, /, *, +, -, /, *, +, -, /, *, +, -, /, *, +, -, /, *, +, -, /, *, +, -, /, *Total number of permutations: 93928268313
Perms of size: 2.
BEST SOLUTION SO FAR: (2 + 4) = 6 (distance from target 751 is 745)
BEST SOLUTION SO FAR: (2 * 4) = 8 (distance from target 751 is 743)
BEST SOLUTION SO FAR: (4 + 7) = 11 (distance from target 751 is 740)
BEST SOLUTION SO FAR: (4 * 7) = 28 (distance from target 751 is 723)
BEST SOLUTION SO FAR: (4 * 9) = 36 (distance from target 751 is 715)
BEST SOLUTION SO FAR: (7 * 9) = 63 (distance from target 751 is 688)
BEST SOLUTION SO FAR: (4 * 50) = 200 (distance from target 751 is 551)
BEST SOLUTION SO FAR: (7 * 50) = 350 (distance from target 751 is 401)
BEST SOLUTION SO FAR: (9 * 50) = 450 (distance from target 751 is 301)
Perms of size: 3.
BEST SOLUTION SO FAR: ((4 + 7) * 50) = 550 (distance from target 751 is 201)
BEST SOLUTION SO FAR: ((2 * 7) * 50) = 700 (distance from target 751 is 51)
BEST SOLUTION SO FAR: ((7 + 9) * 50) = 800 (distance from target 751 is 49)
BEST SOLUTION SO FAR: ((9 + 6) * 50) = 750 (distance from target 751 is 1)
Perms of size: 4.
BEST SOLUTION SO FAR: (((9 + 6) * 50) + 1) = 751

6
задан Philluminati 9 May 2011 в 15:22
поделиться