Skip to content

Instantly share code, notes, and snippets.

@sithumonline
Last active November 3, 2025 03:19
Show Gist options
  • Select an option

  • Save sithumonline/de88ec7f90f4c95c14f0685da6298b4f to your computer and use it in GitHub Desktop.

Select an option

Save sithumonline/de88ec7f90f4c95c14f0685da6298b4f to your computer and use it in GitHub Desktop.
Hamming weight with LRU Caching
#!/usr/bin/env python3
import sys
from datetime import datetime, timedelta
from collections import OrderedDict
from functools import wraps
def cached(n: int = 100, ttl: int = 10):
def _decorate(func):
store = OrderedDict()
@wraps(func)
def _wrapper(*args, **kwargs):
k = (args, tuple(sorted(kwargs.items())))
now = datetime.now()
item = store.get(k)
# print(f"key: {k}, now: {now}, item: {item}")
if item is not None:
value, expires_at = item
if now < expires_at:
store.move_to_end(k)
return value
value = func(*args, **kwargs)
store[k] = (value, now + timedelta(seconds=ttl))
store.move_to_end(k)
if len(store) > n:
store.popitem(last=False)
return value
return _wrapper
return _decorate
"""
//types and constants used in the functions below
//uint64_t is an unsigned 64-bit integer variable type (defined in C99 version of C language)
const uint64_t m1 = 0x5555555555555555; //binary: 0101...
const uint64_t m2 = 0x3333333333333333; //binary: 00110011..
const uint64_t m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones ...
const uint64_t m8 = 0x00ff00ff00ff00ff; //binary: 8 zeros, 8 ones ...
const uint64_t m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones ...
const uint64_t m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones
const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...
"""
m1 = 0x5555555555555555
m2 = 0x3333333333333333
m4 = 0x0F0F0F0F0F0F0F0F
m8 = 0x00FF00FF00FF00FF
m16 = 0x0000FFFF0000FFFF
m32 = 0x00000000FFFFFFFF
h01 = 0x0101010101010101
# This is a naive implementation, shown for comparison,
# and to help in understanding the better functions.
# This algorithm uses 24 arithmetic operations (shift, add, and).
def popcount64a(x: int) -> int:
x = (x & m1) + ((x >> 1) & m1) # put count of each 2 bits into those 2 bits
x = (x & m2) + ((x >> 2) & m2) # put count of each 4 bits into those 4 bits
x = (x & m4) + ((x >> 4) & m4) # put count of each 8 bits into those 8 bits
x = (x & m8) + ((x >> 8) & m8) # put count of each 16 bits into those 16 bits
x = (x & m16) + ((x >> 16) & m16) # put count of each 32 bits into those 32 bits
x = (x & m32) + ((x >> 32) & m32) # put count of each 64 bits into those 64 bits
return x
@cached(n=100, ttl=10)
def ones(x: int) -> int:
MAX = 2**64 - 1
if x > MAX or x < 0:
raise ValueError(f"Unacceptable input: {x}")
return popcount64a(x)
def main() -> int:
for x in [3, 5, 0, 255, 5, 256, -3]:
try:
print(ones(x))
except Exception as e:
print(f"[ERROR] ones ({e})")
return 0
if __name__ == "__main__":
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment