Skip to content

Instantly share code, notes, and snippets.

@Veedrac
Created November 14, 2014 21:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Veedrac/f6556c24563db2f5b9ff to your computer and use it in GitHub Desktop.
Save Veedrac/f6556c24563db2f5b9ff to your computer and use it in GitHub Desktop.
import numpy
from collections import defaultdict
from numpy import newaxis
def rotate_packed(packed):
"""
Return a rotated version of a 55-length
array packed into 55 bits. Eg.
rotate(0b1101) == 0b01101
rotate(2**54) == 0b1
"""
mask = 2**55 - 1
upper = (packed << 1) & mask
lower = packed >> 54
return upper | lower
# Test data
bits = numpy.random.randint(0, 2, (55, 26235))
bits[:, 10] = bits[:, 20] = bits[:, 30] = bits[:, 40] = bits[:, 50]
# Pack each into a 64-bit number by multiplying each bit
# by its value (2**pos) and summing along the arrays
bit_values = 2 ** numpy.arange(55)
packed = (bits * bit_values[:, newaxis]).sum(axis=0)
# Generate the rotation of each packed list with the
# minimum packed value. So 0b0001101 → 0b1101.
minimum_rotation = packed
for i in range(54):
packed = rotate_packed(packed)
minimum_rotation = numpy.minimum(minimum_rotation, packed)
# Generate a dictionary
# {packed value → all indexes with those value}
groups = defaultdict(set)
for i, value in enumerate(minimum_rotation):
groups[value].add(i)
# Find the group with the most members
max(groups.values(), key=len)
#>>> {40, 10, 50, 20, 30}
@AncientSwordRage
Copy link

Could you give as a step by step (in the comments) on what happens to your array as it goes through?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment