diff options
| author | E7-87-83 <fungcheokyin@gmail.com> | 2021-08-04 15:56:29 +0800 |
|---|---|---|
| committer | E7-87-83 <fungcheokyin@gmail.com> | 2021-08-04 15:56:29 +0800 |
| commit | 29946876230c6aaff276f80835046f865c420e2b (patch) | |
| tree | 5525e7045e3e76d68fe7ec50e29c30b385bfdbbc | |
| parent | 8ac7284cd1f4356f82288f99ad6fb4dbdfdde02d (diff) | |
| download | perlweeklychallenge-club-29946876230c6aaff276f80835046f865c420e2b.tar.gz perlweeklychallenge-club-29946876230c6aaff276f80835046f865c420e2b.tar.bz2 perlweeklychallenge-club-29946876230c6aaff276f80835046f865c420e2b.zip | |
Task 2 done and blogpost is done
| -rw-r--r-- | challenge-124/cheok-yin-fung/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-124/cheok-yin-fung/perl/ch-2.pl | 137 |
2 files changed, 55 insertions, 83 deletions
diff --git a/challenge-124/cheok-yin-fung/blog.txt b/challenge-124/cheok-yin-fung/blog.txt new file mode 100644 index 0000000000..57bd054d99 --- /dev/null +++ b/challenge-124/cheok-yin-fung/blog.txt @@ -0,0 +1 @@ +https://e7-87-83.github.io/coding/challenge_124.html diff --git a/challenge-124/cheok-yin-fung/perl/ch-2.pl b/challenge-124/cheok-yin-fung/perl/ch-2.pl index 080037bfca..3ebc1a702e 100644 --- a/challenge-124/cheok-yin-fung/perl/ch-2.pl +++ b/challenge-124/cheok-yin-fung/perl/ch-2.pl @@ -18,26 +18,34 @@ die "At least 2 terms.\n" unless scalar @in > 1; if (scalar @in >= 5 ) { say_ans_for_tug_of_war( tug_of_war([@in])->@* ); } - else { - @in = sort {$a<=>$b} @in; - say "TOTAL: ", sum(@in), "\n"; - given(scalar @in) { - when (4) { say - $in[0], " ", $in[3], " ==> ", $in[0]+$in[3], - "\n", - $in[1], " ", $in[2], " ==> ", $in[1]+$in[2]; + say_ans_for_tug_of_war( tug_of_small_war([@in])->@* ); +} + + + +sub tug_of_small_war { + my @inp = $_[0]->@*; + @inp = sort {$a<=>$b} @inp; + given(scalar @inp) { + when (4) { return [ [$inp[0], $inp[3]] , [ $inp[1], $inp[2] ] ]; } - when (2) { say $in[0], "\n", $in[1]; + when (2) { return [ [$inp[0]] , [$inp[1]] ]; + } + when (3) { + my $sum01 = $inp[0]+$inp[1]; + my $sum02 = $inp[0]+$inp[2]; + my $sum12 = $inp[1]+$inp[2]; + if (abs($sum01-$inp[2])<=abs($sum02-$inp[1])) { + return [ [$inp[0], $inp[1] ] , [ $inp[2] ] ] + if abs($sum12-$inp[0]) >= abs($sum01-$inp[2]); + } + else { + return [ [$inp[0], $inp[2] ] , [ $inp[1] ] ] + if abs($sum12-$inp[0]) >= abs($sum02-$inp[1]); + } + return [ [$inp[1], $inp[2] ] , [ $inp[0] ] ]; } - when (3) { - if (abs($in[0]+$in[1]-$in[2])<=abs($in[0]+$in[2]-$in[1])) { - say $in[0]," ",$in[1], " ==> ", $in[0]+$in[1]; - say $in[2]; } - else { - say $in[0]," ",$in[2], " ==> ", $in[0]+$in[2]; - say $in[1]; } - } } } @@ -45,8 +53,8 @@ else { sub tug_of_war { my @S = $_[0]->@*; - die "At least 5 terms for this subroutine.\n" unless scalar @S >= 5; - my ($target1, $target2); + warn "At least 5 terms for this subroutine.\n" unless scalar @S >= 5; + my ($mark1, $mark2); my $s = sum @S; @@ -54,12 +62,12 @@ sub tug_of_war { my $odd_sum = $s % 2 == 1; if ($odd_sum) { - $target1 = $s >= 0 ? int ($s / 2) : ($s-1)/2; - $target2 = 1 + $target1; + $mark1 = $s >= 0 ? int ($s / 2) : ($s-1)/2; + $mark2 = 1 + $mark1; } else { - $target1 = $s / 2; - $target2 = $target1; + $mark1 = $s / 2; + $mark2 = $mark1; } @S = sort {$a<=>$b} @S; @@ -90,7 +98,7 @@ sub tug_of_war { print "sum of \@S: ", $s, "\n"; say "sum of \@arr0: ", $sum_initial; print "sum of \@arr1: ", (sum @arr1), "\n"; - say "target(s): ", $target1, " ", $target2; + say "mark(s): ", $mark1, " ", $mark2; say "arr0: ", "@arr0"; say "arr1: ", "@arr1"; say " h : @{$diff_arr_h}"; @@ -102,7 +110,7 @@ sub tug_of_war { # then use the map {-$_} and call tug_of_war again my ( $na0, $na1 ) = tug_of_war([map { -$_ } @S])->@*; # "used odd term and large last term method"; - return [ [ map {-$_} $na0->@* ] , [map {-$_} $na1->@* ] ]; + return [ [ reverse map {-$_} $na0->@* ] , [ reverse map {-$_} $na1->@* ] ]; } elsif (2*$sum_initial == $s) { return [ [@arr0], [@arr1] ]; @@ -111,13 +119,13 @@ sub tug_of_war { my $soln_h = closest_sum_to_target( $diff_arr_h, - $target1 - $sum_initial, - $target2 - $sum_initial, + $mark1 - $sum_initial, + $mark2 - $sum_initial, ); my $soln_m = closest_sum_to_target( $diff_arr_m, - $target1 - $sum_initial, - $target2 - $sum_initial, + $mark1 - $sum_initial, + $mark2 - $sum_initial, ); if ($soln_m->[1] <= $soln_h->[1]) { foreach (@{$soln_m->[0]}) { @@ -138,6 +146,8 @@ sub tug_of_war { return [ [@arr0], [@arr1] ]; } + + sub say_ans_for_tug_of_war { my @a0 = $_[0]->@*; my @a1 = $_[1]->@*; @@ -147,10 +157,13 @@ sub say_ans_for_tug_of_war { say "(", "@a1", ") ==> ", sum @a1; } + + sub closest_sum_to_target { my @array = $_[0]->@*; my $target1 = $_[1]; my $target2 = $_[2]; + warn "\$target1 should be smaller or equal to \$target2" if $target1 > $target2; my $exact = undef; my %indices_to_values = ( [] => 0 ); my $generation_aged = [ [] ]; @@ -163,7 +176,7 @@ sub closest_sum_to_target { while ( !$exact && $n < scalar @array ) { foreach my $arr ($generation_aged->@*) { foreach my $i (0..$#array) { - # check_if_arr_contain_i, _if_yes_then_next__ + # check_if_@array_contain_i, _if_yes_then_next__ next if any { $_ == $i } $arr->@*; my $arr_cp = $n>0 ? [$arr->@*] : [] ; push $arr_cp->@*, $i; @@ -172,7 +185,7 @@ sub closest_sum_to_target { $my_sum += $indices_to_values{$arr}; } # check_if_values_of_hash_indices_to_values_contain_i, _if_yes_then_next__ - next if any { $_ == $my_sum && $_ != 0 } values %indices_to_values; + next if any { $_ == $my_sum && $_ != 0 } values %indices_to_values; #[*] push $generation_new->@*, $arr_cp; $indices_to_values{$arr_cp} = $my_sum; if ($my_sum == $target1 || $my_sum == $target2) { @@ -199,34 +212,35 @@ sub closest_sum_to_target { $n++; } - + # return [ [@arr of inpd] => sum of values , diff to the target ] if (defined($exact)) { - return [ $exact, 0 ]; # return [ [@arr of ind] => sum of values , diff to the target ] + return [ $exact, 0 ]; } else { - # say "No exact solutions."; + # "No exact solutions." my $temp_smaller = $current_sum_smaller; my $temp_larger = $current_sum_larger; - # say $temp_smaller; - # say $temp_larger; if ( defined($temp_smaller) && - ( !defined($temp_larger) + ( !defined($temp_larger) || (($target1 - $temp_smaller) <= ($temp_larger - $target2)) ) ) { return [ - $current_ind_smaller, $target1 - $temp_smaller + $current_ind_smaller, + $target1 - $temp_smaller ]; } else { return [ - $current_ind_larger, $temp_larger - $target2 + $current_ind_larger, + $temp_larger - $target2 ]; } } } + say ""; say "TEST"; ok (manual_test([10, 20, 30, 40, 50, 60, 70, 80, 90, 100], 10), "Example Set 1"); @@ -234,7 +248,7 @@ ok (manual_test([10, -15, 20, 30, -25, 0, 5, 40, -5], 0), "Example Set 2"); ok (manual_test([1..100], 0), "natural numbers"); ok (manual_test([-26, -2, 3, 4, 5], 18), "a big negative"); ok (manual_test([-1, -2, 3, 4, 11], 1), "a big positive"); -ok (manual_test([-1, 0, 0, 1, 5], 3), "-1 and 0015"); +ok (manual_test([-1, 0, 0, 1, 5], 3), "-1 and 0,0,1,5"); sub manual_test { my @set = $_[0]->@*; @@ -255,46 +269,3 @@ sub manual_test { done_testing(); -#================== - - - -=pod -BEGIN: unorganized notes -case: -4 1 2 5 6 -target: 5 --4 2 6 -> sum == 4 -1 5 -> sum == 6 - -TARGET MINUS SUM_OF_ARR0: 1 -diff_arr_h: 9 -diff_arr_m: 5 3 - - -case: -23 -6 -1 8 12 19 -targets: 4 5 -TARGET MINUS SUM OF ARR0 : -16, -17 -diff_arr_h: 31 20 -diff_arr_m: 17 9 7 - - -case -21 -10 -9 -8 -6 11 15 21 -sum of @arr0: -21 -target(s): -4 -3 -TARGET MINUS SUM OF ARR0: 17 -13 20 27 -11 1 17 6 - -case -25 -18 -17 -10 -9 -6 21 22 24 25 -sum of @arr0: -6 -target(s): 3 4 -TARGET MINUS SUM OF ARR0: 9, 10 -15 11 31 4 -7 7 3 1 1 -END: unorganized notes - -Then apply: -https://stackoverflow.com/questions/19572043/given-a-target-sum-and-a-set-of-integers-find-the-closest-subset-of-numbers-tha - - - |
