| Bytes | Lang | Time | Link |
|---|---|---|---|
| 331 | JavaScript Node.js | 240610T004053Z | Arnauld |
| nan | 240610T141442Z | 138 Aspe | |
| nan | 240610T094056Z | corvus_1 |
JavaScript (Node.js), ≈3.3ms (1)
This hexadecimal version was suggested by tsh
Expects a BigInt.
This computes hammingweight(XOR(n, 3*n)), as suggested on A007302.
function f(binStr) {
const tableHex = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 2, 3, 2, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
];
const n = BigInt("0b" + binStr);
const hex = (n ^ 3n * n).toString(16);
let count = 0;
for (let i = 0, l = hex.length; i < l; ++i) {
count += tableHex[hex.charCodeAt(i)];
}
return count;
}
Using binary, ≈16ms (1)
function f(binStr) {
const n = BigInt("0b" + binStr);
let bin = (n ^ 3n * n).toString(2);
return bin.split("1").length - 1;
}
Bitwise approach, ≈12 seconds (1)
Converting to a binary or hexadecimal string and iterating over its characters may not be the most elegant method (conceptually speaking), but it's much, much faster than going bitwise.
I assume this one causes several new BigInts to be allocated, inducing a massive overhead in the pipeline when n is large.
function f(binStr) {
const n = BigInt("0b" + binStr);
let N = n ^ 3n * n,
count = 0;
while(N) {
N &= N - 1n;
count++;
}
return count;
}
(1) All benchmarks were done on my laptop with Node 20.10.0, using several calls to the function in a loop.
Python + gmpy2 2.1.5
import gmpy2
from gmpy2 import mpz
import time
def main():
input_value = mpz('9515985770616618967204423793474873711653') * (mpz(10) ** 300990)
print(f(input_value))
def f(n):
bin_value = n ^ (n + (n << 1))
return gmpy2.popcount(bin_value)
if __name__ == "__main__":
start_time=time.time()
main()
print(f"{(time.time()-start_time)*1000} ms")
It is around 16ms on my machine.
Rust + num_bigint 0.4.5
use num_bigint::BigUint;
use std::str::FromStr;
fn main() {
let input = BigUint::from_str("9515985770616618967204423793474873711653").unwrap()
* (BigUint::from(10u64).pow(300990));
print!("{}", f(input))
}
fn f(n: BigUint) -> u64 {
let bin: BigUint = &n ^ (&n + (&n << 1));
bin.count_ones()
}
For the best performance, make sure to compile with
RUSTFLAGS='-C target-cpu=native' cargo build --release. It is around 20ms on my machine.