Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
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":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2024-03-28 15:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found