aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2022-11-22 18:17:24 +0000
committerGitHub <noreply@github.com>2022-11-22 18:17:24 +0000
commit476530247c4f455a7f7369db4bcac7f968a324b3 (patch)
tree4b98c62def641c1a2e869a5f61240146d92351bd
parent2adbac29370f27a783346e7bcf778b053582bc77 (diff)
parent40cb69909abb1058a29c5792afb12ba3d9b4537c (diff)
downloadperlweeklychallenge-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.md21
-rw-r--r--challenge-192/james-smith/perl/ch-1.pl16
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;
+}