Skip to content

Instantly share code, notes, and snippets.

@mg
Last active December 24, 2015 04:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mg/6747532 to your computer and use it in GitHub Desktop.
Save mg/6747532 to your computer and use it in GitHub Desktop.
The Devils code
#!/usr/bin/perl
sub sos_as_string ($;$) {
my ( $set, $string ) = @_;
$$string .= '{';
my $i;
foreach my $key ( keys %{ $set } ) {
$$string .= ' ' if $i++;
if ( ref $set->{ $key } ) {
sos_as_string( $set->{ $key }, $string );
} else {
$$string .= $key;
}
}
return $$string .= '}';
}
sub powerset_recurse ($;@) {
my ($set, $powerset, $keys, $values, $n, $i) = @_;
if( @_ == 1 ) {
my $null = {};
$powerset = { $null, $null };
$keys = [ keys %{ $set }];
$values = [ values %{ $set }];
$nmembers = keys %{ $set};
$i= 0;
}
return $powerset if $i == $nmembers;
my @powerkeys = keys %{ $powerset };
my @powervalues = values %{ $powerset };
my $powern = @powerkeys;
my $j;
for( $j = 0; $j < $powern; $j++ ) {
my %subset = ( );
@subset{keys %{ $powerset->{ $powerkeys [$j]}}} =
values %{ $powerset->{ $powervalues [$j]}};
$subset{$keys->[ $i]}= $values->[$i];
$powerset->{\%subset } = \%subset;
}
powerset_recurse($set, $powerset, $keys, $values, $nmembers, $i+1);
}
my $a= { a => 12, b => 34, c => 56};
my $pr= powerset_recurse($a);
print "pr = " . sos_as_string($pr) . "\n";
What is the purpose of $n? It is never referenced anywhere else than line 20
What is the value of $nmembers if @_ != 1?
Why does this return different results every time I run this? E.g:
~/D/g/h/c5 (master=) ./powerset.pl
pr = {{a b} {c a} {c} {} {a} {c b} {b} {c a b}}
~/D/g/h/c5 (master=) ./powerset.pl
pr = {{a b} {c b} {b} {a} {} {c a} {c} {c a b}}
~/D/g/h/c5 (master=) ./powerset.pl
pr = {{} {a b} {a} {c a} {c b} {b} {c} {c a b}}
~/D/g/h/c5 (master=) ./powerset.pl
pr = {{c} {c a b} {a} {c a} {} {b} {c b} {a b}}
~/D/g/h/c5 (master=) ./powerset.pl
pr = {{c} {c a b} {} {a b} {c b} {b} {c a} {a}}
What is going on here? From where is the randomness coming from?
@mjdominus
Copy link

  1. It looks to me like $nmembers is an error and should have been $n throughout. Notice that $nmembers is never declared, and the program fails under use strict. Since it's undeclared, it is a global variable. It's not properly passed by the recursive call, but since it's global, its new value is available to the recursive instance of powerset_recurse. I will check to see if the error is in the original Wolf Book or if it's something I introduced by mistake.
  2. The randomness is coming from two places. First, hash order is and always has been unpredictable. sos_as_string iterates the hash keys in the unpredictable internal order . In old perls this would have been the same every time (although still unpredictable) but since Perl 5.8.1 it includes a random seed to prevent certain kinds of denial-of-service attacks against Perl hashes. (See PERL_HASH_SEED in the manual.) But second, the keys in the hash are strings like HASH(0xb540b8) that include internal machine addresses, which vary from call to call, and this would change the hash order even under old perls.

@mjdominus
Copy link

Nope, the error is in the original, Mastering Algorithms with Perl, page 249, and neither I nor the original authors seems to have noticed it.

@mg
Copy link
Author

mg commented Sep 29, 2013

Figured it must be that n should be nmembers but finding it in the original (through Amazon) had me thoroughly confused. The randomness I could not make any sense of no matter how often I read the code. Happy to know it's some obscure Perlish thing rather than my eyes and general comprehension!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment