Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Perl ARRAY() result

by pvfki (Novice)
on Jan 13, 2019 at 21:26 UTC ( #1228495=perlquestion: print w/replies, xml ) Need Help??

pvfki has asked for the wisdom of the Perl Monks concerning the following question:

I am sort of a beginner to Perl here and I am having problems converting ARRAY() output to string. The code below is a program which computes All subsets (of a set) with a given sum. The only issue is it prints the results in ARRAY() form instead of strings. Does anyone know how to convert ARRAY() --> string?

sub Solve { my ($goal, $elements) = @_; # For extra speed, you can remove this next line my (@results, $RecursiveSolve, $nextValue); $RecursiveSolve = sub { my ($currentGoal, $included, $index) = @_; for ( ; $index < @$elements; ++$index) { $nextValue = $elements->[$index]; # Since elements are sorted, there's no point in trying a # non-final element unless it's less than goal/2: if ($currentGoal > 2 * $nextValue) { $RecursiveSolve->($currentGoal - $nextValue, [ @$included, $nextValue ], $index + 1); } else { print "@$_\n", [ @$included, $nextValue ] if $currentGoal == $nextValue; return if $nextValue >= $currentGoal; } } # end for }; # end $RecursiveSolve $RecursiveSolve->($goal, [], 0); undef $RecursiveSolve; # Avoid memory leak from circular reference return @results; } # end Solve my @results = Solve(869, [15, 43, 51, 56, 60, 67, 122, 152, 193, 204, +229, 271, 293, 301] );

The code prints:

ARRAY(0x2829430) ARRAY(0x2829148) ARRAY(0x28291c0) ARRAY(0x28291a8) ARRAY(0x2829418) ARRAY(0x2829190) ARRAY(0x2828c68) ARRAY(0x2828c50) ARRAY(0x28291c0) ARRAY(0x28291a8) ARRAY(0x2828e78) ARRAY(0x2828bf0) ARRAY(0x2828e60) ARRAY(0x2828bf0)

which is not understandable. Thanks for help!

Replies are listed 'Best First'.
Re: Perl ARRAY() result
by bliako (Monsignor) on Jan 13, 2019 at 21:58 UTC

    if you want to print the contents of an array just do:

    my @array = (1,2,3); print join(',', @array);

    in the code you posted try replacing

    print "@$_\n", [ @$included, $nextValue ]
    with print join(", ", @{[ @$included, $nextValue ]})."\n"

    Edit:btw, your code does not return anything in @results. Instead of printing inside your sub, try pushing each new result to the @results array by replacing said print statement with push(@results, [ @$included, $nextValue ]). Then at the end of your code (after Solve() returns) do  print join(",", @$_)."\n" foreach @results

    I was wondering what @$_ in print "@$_\n", [ @$included, $nextValue ] was all about...

Re: Perl ARRAY() result
by 1nickt (Canon) on Jan 14, 2019 at 00:43 UTC

    Hi, Perl provides strictures and warnings to point out problems with your code. If you had enabled them you would have been pointed to the source of your problem immediately. See Basic debugging checklist Item 1.

    After adding

    use strict; use warnings;
    to your code, I ran it and got this output:
    Can't use an undefined value as an ARRAY reference at 1228495.pl line +24.
    ... the offending line being, as others have pointed out,
    print "@$_\n", [ @$included, $nextValue ]
    As your case ably illustrates, it's just downright foolish to run your code without strictures!

    Hope this helps.


    The way forward always starts with a minimal test.
Re: Perl ARRAY() result
by pme (Monsignor) on Jan 13, 2019 at 21:54 UTC
    Hi pvfki
    ... } else { print join(',', @$included, $nextValue), "\n" if $currentGoal == $nextValue; return if $nextValue >= $currentGoal; } ...
    Update And you can push the result to @results.
    ... } else { if ($currentGoal == $nextValue) { print join(',', @$included, $nextValue), "\n"; push @results, [@$included, $nextValue]; } return if $nextValue >= $currentGoal; } ...
    HTH
Re: Perl ARRAY() result
by BillKSmith (Monsignor) on Jan 13, 2019 at 22:49 UTC
    In your print statement, $_ is undefined. Therefore, the string "@$_\n" contains only the newline. Your square brackets create a reference to an anonymous array. The text you see is the expected output when you try to print a reference. All you must do is print the variables you want. (You may use the special variable "$," perlvar to format the output.)
    } else { # print "@$_\n", [ @$included, $nextValue ] local $, = q(, ); print @$included, $nextValue, "\n" if $currentGoal == $nextValue; return if $nextValue >= $currentGoal; }
    Bill
Re: Perl ARRAY() result
by tybalt89 (Monsignor) on Jan 14, 2019 at 01:55 UTC

    It seemed a little long, so I just tweaked it a tiny bit :)

    #!/usr/bin/perl # https://perlmonks.org/?node_id=1228495 use strict; use warnings; my @results = Solve(869, [15, 43, 51, 56, 60, 67, 122, 152, 193, 204, 229, 271, 293, 301] ); print "@$_\n" for @results; sub Solve { my $want = shift() or return []; $want > 0 or return (); my ($first, @rest) = @{ shift() } or return (); map([$first, @$_], Solve($want - $first, \@rest)), Solve($want, \@re +st); }

    Outputs:

    15 43 51 56 60 122 229 293 15 43 51 56 204 229 271 15 43 51 67 193 229 271 15 43 51 122 152 193 293 15 56 60 67 122 152 193 204 15 56 60 122 152 193 271 15 56 204 293 301 15 67 193 293 301 43 51 56 67 122 229 301 43 51 56 67 152 229 271 43 51 60 193 229 293 43 122 204 229 271 56 60 67 122 271 293 56 67 152 293 301
      It does look more elegant and compact, but it's significantly slower:
      $ perl ./thescript
      Benchmark: timing 1000 iterations of orig, tybalt89...
           orig:  3 wallclock secs ( 2.48 u + 0.00 s =  2.48 CPU) @403.23/s (n=1000)
       tybalt89: 10 wallclock secs (10.22 u + 0.00 s = 10.22 CPU) @ 97.85/s (n=1000)
      
Re: Perl ARRAY() result
by stevieb (Canon) on Jan 13, 2019 at 23:19 UTC

    There are a few responses to this post, but what I'd like to see, is a response with the full code body.

    Can you do that guys?

    I can run the code, even under strict/warnings, but I see sticky things, like the lack of the instantiation variable in the for loop for example. Typically, we don't use C-style for() loops in Perl code unless under duress, or weird circumstances. There are a couple of other smaller things, but I digress.

    Anyone willing to post the full code that they have that got this to work, with the actual output from OPs example?

      Here's pme's changes as the whole script.
      use strict; use warnings; sub Solve { my ( $goal, $elements ) = @_; my ( @results, $RecursiveSolve, $nextValue ); $RecursiveSolve = sub { my ( $currentGoal, $included, $index ) = @_; for ( ; $index < @$elements ; ++$index ) { $nextValue = $elements->[$index]; if ( $currentGoal > 2 * $nextValue ) { $RecursiveSolve->( $currentGoal - $nextValue, [ @$included, $nextValue ], $index + 1 ); } else { if ( $currentGoal == $nextValue ) { #print join( ',', @$included, $nextValue ), "\n"; push @results, [ @$included, $nextValue ]; } return if $nextValue >= $currentGoal; } } }; $RecursiveSolve->( $goal, [], 0 ); undef $RecursiveSolve; # Avoid memory leak from circular refere +nce return @results; } my @results = Solve( 869, [ 15, 43, 51, 56, 60, 67, 122, 152, 193, 204, +229, 271, 293, 301 +] ); foreach my $result (@results) { print join(',',@$result),"\n"; }

        Absolutely brilliant!

        ++ and kudos for denoting a circular reference :)

      OK stevieb, here is the original OP code with only the print statement corrected as described in my first post. A sample execution demonstrates that the expected output is produced.
      >type pviki.pl use strict; use warnings; sub Solve { my ($goal, $elements) = @_; # For extra speed, you can remove this next line my (@results, $RecursiveSolve, $nextValue); $RecursiveSolve = sub { my ($currentGoal, $included, $index) = @_; for ( ; $index < @$elements; ++$index) { $nextValue = $elements->[$index]; # Since elements are sorted, there's no point in trying a # non-final element unless it's less than goal/2: if ($currentGoal > 2 * $nextValue) { $RecursiveSolve->($currentGoal - $nextValue, [ @$included, $nextValue ], $index + 1); } else { #print "@$_\n", [ @$included, $nextValue ] local $, = q(, ); print @$included, $nextValue, "\n" if $currentGoal == $nextValue; return if $nextValue >= $currentGoal; } } # end for }; # end $RecursiveSolve $RecursiveSolve->($goal, [], 0); undef $RecursiveSolve; # Avoid memory leak from circular reference return @results; } # end Solve my @results = Solve(869, [15, 43, 51, 56, 60, 67, 122, 152, 193, 204, +229, 271, 293, 301] ); >perl pviki.pl 15, 43, 51, 56, 60, 122, 229, 293, 15, 43, 51, 56, 204, 229, 271, 15, 43, 51, 67, 193, 229, 271, 15, 43, 51, 122, 152, 193, 293, 15, 56, 60, 67, 122, 152, 193, 204, 15, 56, 60, 122, 152, 193, 271, 15, 56, 204, 293, 301, 15, 67, 193, 293, 301, 43, 51, 56, 67, 122, 229, 301, 43, 51, 56, 67, 152, 229, 271, 43, 51, 60, 193, 229, 293, 43, 122, 204, 229, 271, 56, 60, 67, 122, 271, 293, 56, 67, 152, 293, 301,
      Bill
Re: Perl ARRAY() result
by kschwab (Vicar) on Jan 14, 2019 at 18:44 UTC

    I cleaned up the code to where it can recurse in a single sub, and a few other tweaks that make it a little faster. Here's a speed comparison:

    $ perl ./script
    Benchmark: timing 5000 iterations of new, orig...
           new: 11 wallclock secs (10.03 u +  0.00 s = 10.03 CPU) @ 498.50/s (n=5000)
          orig: 11 wallclock secs (10.98 u +  0.00 s = 10.98 CPU) @ 455.37/s (n=5000)
    
    
    And the code...see the solve2() sub for the cleaned up version.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1228495]
Approved by stevieb
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2022-12-08 00:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?