Given the mess that is Re: Challenge: Sorting Sums Of Sorted Series, I'll post a pair of working, fast solutions here. The solutions that follow use O(N+M) memory and are O(N^2*M) in time. The basic algorithm implemented is:

    Populate a queue with the sum of all elements of the short list with the first element of the other list. Keep track of the indices of each value. This queue is by definition sorted. Then loop until the queue is empty, doing the following:

  1. Shift and print the first element of the queue;
  2. Increment the second list index for the shifted element. Cycle loop if this index is outside the second list.
  3. Use a sorted insertion to add the sum at the new coordinates to the queue.

I wrote a version with an array for each tracked element (solution_2) and one where all three are lumped into a single entry.

sub solution_2 { # adaptive motion queue solution my ($list_ref1, $list_ref2) = @_; my @list1; my @list2; if (@$list_ref1 <= @$list_ref2) { @list1 = @$list_ref1; @list2 = @$list_ref2; } else { @list1 = @$list_ref2; @list2 = @$list_ref1; } my @queue = map $_+$list2[0], @list1; my @xs = (0 .. $#list1); my @ys = (0) x @list1; while (@queue) { print OUT shift(@queue), "\n"; my $x = shift @xs; my $y = shift @ys; next if ++$y >= @list2; my $sum = $list1[$x] + $list2[$y]; my $count = 0; $count++ until $count == @queue or $sum <= $queue[$count]; splice @queue, $count, 0, $sum; splice @xs, $count, 0, $x; splice @ys, $count, 0, $y; } } sub solution_3 { # adaptive motion queue solution, one array my ($list_ref1, $list_ref2) = @_; my @list1; my @list2; if (@$list_ref1 <= @$list_ref2) { @list1 = @$list_ref1; @list2 = @$list_ref2; } else { @list1 = @$list_ref2; @list2 = @$list_ref1; } my @queue = (); for (0 .. $#list1) { push @queue, join("x", $list1[$_]+$list2[0], "$_", "0"); } while (@queue) { my $entry = shift(@queue); my ($old, $x, $y) = split /x/, $entry; print OUT "$old\n"; next if ++$y >= @list2; my $sum = $list1[$x] + $list2[$y]; my $count = 0; { no warnings 'numeric'; $count++ until $count == @queue or $sum <= $queue[$count]; } splice @queue, $count, 0, "${sum}x${x}x${y}"; } }

And benchmarks on 4 element and 100 element equally distributed arrays:

Benchmark: timing 100 iterations of 1_array, 3_array, Baseline, LR_1.. +. 1_array: 10.651 wallclock secs (10.65 usr + 0.00 sys = 10.65 CPU) +@ 9.39/s (n=100) 3_array: 9.28456 wallclock secs ( 9.28 usr + 0.00 sys = 9.28 CPU) + @ 10.78/s (n=100) Baseline: 0.844141 wallclock secs ( 0.84 usr + 0.00 sys = 0.84 CPU +) @ 119.05/s (n=100) (warning: too few iterations for a reliable count) LR_1: 20.4537 wallclock secs (20.45 usr + 0.00 sys = 20.45 CPU) + @ 4.89/s (n=100) Rate LR_1 1_array 3_array Baseline LR_1 4.89/s -- -48% -55% -96% 1_array 9.39/s 92% -- -13% -92% 3_array 10.8/s 120% 15% -- -91% Baseline 119/s 2335% 1168% 1005% -- Benchmark: timing 100000 iterations of 1_array, 3_array, Baseline, LR_ +1... 1_array: 7.06968 wallclock secs ( 7.07 usr + 0.00 sys = 7.07 CPU) + @ 14144.27/s (n=100000) 3_array: 5.09259 wallclock secs ( 5.09 usr + 0.00 sys = 5.09 CPU) + @ 19646.37/s (n=100000) Baseline: 2.11864 wallclock secs ( 2.12 usr + 0.00 sys = 2.12 CPU) + @ 47169.81/s (n=100000) LR_1: 7.01637 wallclock secs ( 7.02 usr + 0.00 sys = 7.02 CPU) + @ 14245.01/s (n=100000) Rate 1_array LR_1 3_array Baseline 1_array 14144/s -- -1% -28% -70% LR_1 14245/s 1% -- -27% -70% 3_array 19646/s 39% 38% -- -58% Baseline 47170/s 233% 231% 140% --

In reply to Re: Challenge: Sorting Sums Of Sorted Series by kennethk
in thread Challenge: Sorting Sums Of Sorted Series by Limbic~Region

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.