diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2022-11-22 18:17:24 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-22 18:17:24 +0000 |
| commit | 476530247c4f455a7f7369db4bcac7f968a324b3 (patch) | |
| tree | 4b98c62def641c1a2e869a5f61240146d92351bd | |
| parent | 2adbac29370f27a783346e7bcf778b053582bc77 (diff) | |
| parent | 40cb69909abb1058a29c5792afb12ba3d9b4537c (diff) | |
| download | perlweeklychallenge-club-476530247c4f455a7f7369db4bcac7f968a324b3.tar.gz perlweeklychallenge-club-476530247c4f455a7f7369db4bcac7f968a324b3.tar.bz2 perlweeklychallenge-club-476530247c4f455a7f7369db4bcac7f968a324b3.zip | |
Merge pull request #7142 from drbaggy/master
Tweaked for C speed
| -rw-r--r-- | challenge-192/james-smith/README.md | 21 | ||||
| -rw-r--r-- | challenge-192/james-smith/perl/ch-1.pl | 16 |
2 files changed, 34 insertions, 3 deletions
diff --git a/challenge-192/james-smith/README.md b/challenge-192/james-smith/README.md index 7c47f95f78..76dac905f8 100644 --- a/challenge-192/james-smith/README.md +++ b/challenge-192/james-smith/README.md @@ -47,11 +47,14 @@ This can also be done by converting to a string and then coverting back again. ``` sub string_flip { - oct '0b'.sprintf('%b',$_[0])=~tr/01/10/r; + $_[0] ? oct '0b'.sprintf('%b',$_[0])=~tr/01/10/r : 0; +} ``` We use `tr` with the `r` option to return the result of the translation... +Note we have to check whether the input is `0` as in this case the output is also `0` as there is no leading 1. + ### Performance... Well this is where Perl is uber fast when it comes to strings - the string solution is faster than the bit manipulation. This is probably due to the overhead of each separate operation in the numeric version. For a test example of "12345678" (`1011 1100 0110 0001 0100 1110`) the string method is 8x faster than the binary method. @@ -74,6 +77,22 @@ int c_flip(int n) { Now - when comparing this to the other two: The C version is 4.5 times faster than the string version OR 35x faster than the equivalent Perl version. +A further re-write of the C gives: + +```C +int c2(int n) { + int o = n; + int m = 0; + while(o) { + m<<=1; + m++; + o>>=1 + } + return n^m; +} +``` + +Here we compute a mask of `1`s as long as the binary representation of the number so for `25` = `11001` we have a mask of `11111` and so doing a bitwize XOR operation gives us `00110` or `6`. Which is even faster as it only does the XOR (`^`) once. {approx 5 times faster than the regex version} # Task 2 - Equal Distribution diff --git a/challenge-192/james-smith/perl/ch-1.pl b/challenge-192/james-smith/perl/ch-1.pl index b2e18ab4be..89e9c957ac 100644 --- a/challenge-192/james-smith/perl/ch-1.pl +++ b/challenge-192/james-smith/perl/ch-1.pl @@ -13,16 +13,17 @@ my @TESTS = ( [5,2],[4,3],[6,1] ); is( binary_flip( $_->[0] ), $_->[1] ) for @TESTS; is( string_flip( $_->[0] ), $_->[1] ) for @TESTS; is( c_flip( $_->[0] ), $_->[1] ) for @TESTS; +is( c2_flip( $_->[0] ), $_->[1] ) for @TESTS; done_testing(); sub string_flip { - oct '0b'.sprintf('%b',$_[0])=~tr/01/10/r; + $_[0] ? oct '0b'.sprintf('%b',$_[0])=~tr/01/10/r : 0 } sub binary_flip { my($r,$k,$n) = (0,1,shift); $r|=(~$n&1)<<$k++, $n>>=1 while $n; - $r; + $r } __END__ @@ -36,3 +37,14 @@ int c_flip(int n) { } return r; } + +int c2_flip(int n) { + int o = n; + int m = 0; + while(o) { + m<<=1; + m++; + o>>=1; + } + return n^m; +} |
