diff options
| author | drbaggy <js5@sanger.ac.uk> | 2021-05-30 10:02:51 +0100 |
|---|---|---|
| committer | drbaggy <js5@sanger.ac.uk> | 2021-05-30 10:02:51 +0100 |
| commit | 973c096b1d2b6e063457a2fe37b795749e9071cb (patch) | |
| tree | 20800de1d9a7a6b6ab3a34ca2a0d84f3b0002e6f | |
| parent | 5f85b848c0c828ba9f18f6e90a388ccfab9ef17a (diff) | |
| download | perlweeklychallenge-club-973c096b1d2b6e063457a2fe37b795749e9071cb.tar.gz perlweeklychallenge-club-973c096b1d2b6e063457a2fe37b795749e9071cb.tar.bz2 perlweeklychallenge-club-973c096b1d2b6e063457a2fe37b795749e9071cb.zip | |
added notes
| -rw-r--r-- | challenge-114/james-smith/perl/ch-2.pl | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/challenge-114/james-smith/perl/ch-2.pl b/challenge-114/james-smith/perl/ch-2.pl index c3572ec45d..51ef8af152 100644 --- a/challenge-114/james-smith/perl/ch-2.pl +++ b/challenge-114/james-smith/perl/ch-2.pl @@ -72,9 +72,50 @@ sub next_bin_rrev { return oct '0b'.substr($s,0,$t).'10'.reverse substr $s,$t+2; } +## We can get further optimization by avoiding the call to "oct" by +## converting the above to simple arithmetic... +## To move all the 1s to the end and flip the '01' to '10' +## We note that if the number is of the form.. +## +## 0 1111 00000000 +## +## The next highest number (with the same number of bits is: +## +## 1 000000000 111 +## +## To get this we first do: +## +## 0 1111 00000000 +## + 0 0001 00000000 +## --------------- +## 1 0000 00000000 +## +## and then: +## +## 1 0000 00000000 +## + 0 0000 00000111 +## --------------- +## 1 0000 00000111 +## +## which is the answer we are looking for.... +## +## This is basically: +## +## $N + 2^(#0s) +2^(#1s-1) - 1; +## +## We can get these with rindex +## +## #0s = length of the binary string - (last index of 1 + 1) +## #1s = last index of 1 - last index of 0 (before this 1) +## +## This all leads into the following fn. +## +## Note we don't use 2**$N but 1<<$N which is much more efficient +## Investigated unpack vs sprintf to do the dec->binary conversion +## the latter is faster by about 20%... + sub next_bin_rindex2 { my $t = rindex my $s = sprintf('%b',my $n = shift),'1'; return $n - 1 + (1<<(-1-$t+length$s)) + (1<<(-1+$t-rindex $s,'0',$t)); } - |
