tags:

views:

208

answers:

2

24 points is small game. You must use + - * / to get the result 24 from 4 numbers. I wrote a Perl script to solve this problem. But I feel my code is too long and it looks like C.

I hope someone can give me some advice. Thank you very much!

Other language are possible, too, for example Python, Scala, F#, C++.

my @test_arr    = (10,  4,   7,   6);
my @oprator_arr = ('+', '-', '*', '/');
rec_cala(\@test_arr);

sub rec_cala {
    my ($arr_ref) = @_;
    my @input_arr = ();
    push @input_arr, @$arr_ref;

    if (scalar(@input_arr) <= 1) {
        $result = eval $input_arr[0];
        if ($result > 23.9 && $result < 24.1) {
            print $input_arr[0];
            print "  = 24\n";
        }
    } else {
        my @perm_arr = perm(\@input_arr);
        foreach (@perm_arr) {
            my @next_arr = @$_;
            my $op1      = pop @next_arr;
            my $op2      = pop @next_arr;

            foreach (@oprator_arr) {
                @op_expr_arr = @next_arr;
                push @op_expr_arr, "($op1 $_ $op2)";
                rec_cala(\@op_expr_arr);
            }
        }
    }
}

sub perm {
    my ($arr_ref) = @_;
    my @arr       = @$arr_ref;
    my @result    = [];

    while (scalar(@arr)) {
        my $curr_element = pop @arr;
        my @next_step    = ();
        foreach $curr_array (@result) {
            $curr_len = scalar(@$curr_array);
            for ($i = 0; $i <= $curr_len; $i++) {
                push @next_step, [
                    (@$curr_array[0 .. $i], $curr_element, @$curr_array[$i + 1 .. $curr_len])
                ];
            }
        }
        @result = @next_step;
    }
    return @result;
}
+3  A: 

OK, two points:

1) You said "improve".

While code golf is "cool" and, if studied and applied properly, helps the developer increase their knowledge and grokking of the nuances and depths of the chosen language, the resulting golf code is, broadly speaking, NOT an improvement from software development point of view.

While good, elegant code often results in shorter program, the opposite is not necessarily (or usually) true. Merely having shorter code more likely than not means the code is harder to read and harder to maintain, and these two qualities are pretty much paramount as far as good software development.

2) Having said that, Perl does provide many syntactic facilities and idioms that achieve better code while shortening it as a side effect. I will try to point out some possible changes to your code that would make it more idiomatic in my opinion, though not necessarily shorter.


OLD:

my @input_arr = ();
push @input_arr, @$arr_ref;

NEW:

my @input_arr = (@$arr_ref);

Explanation: You don't need to declare an array and initialize it separately.


OLD:

if (scalar(@input_arr) <= 1) {

NEW:

if (@input_arr <= 1) {

Explanation: Arrays in Perl, when evaluated in scaalar context (which a numeric comparison operator like <= imposes), evaluate to the size of array. So scalar() is superfluous.


More to be added later - gotta run

DVK
+3  A: 

You have framed the question as though you are looking for tips to improve a functioning program. But your program does not run under use strict and use warnings, and it does not work at all as far as I can tell. Even the perm method is broken, generating both warnings and incorrect results.

Before you can make even a simple program, you need to make sure that your building blocks are straight. One place to start is to figure out how to write a correct perm method that will run under use strict and use warnings. If your goal is to solve this puzzle yourself, that's great. Otherwise, check out the Perl FAQ, How do I permute N elements of a list?

FM