Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 13 additions & 26 deletions cubes.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,40 +151,27 @@ def generate_polycubes(n, use_cache=False):

def rle(polycube):
"""
Computes a simple run-length encoding of a given polycube. This function allows cubes to be more quickly compared via hashing.
Computes a simple hash of a given polycube.
It does this by converting the polycube into a 1d array and then interpreting those bits as a unsigned integer
This function allows cubes to be more quickly compared via hashing.

Converts a {0,1} nd array into a tuple that encodes the same shape. The array is first flattened, and then the following algorithm is applied:

1) The first three values in tuple contain the x,y,z dimension sizes of the array
2) Each string of zeros of length n is replaced with a single value -n
3) Each string of ones of length m is replaced with a single value +m
Converts a {0,1} nd array into a single unique large integer

Parameters:
polycube (np.array): 3D Numpy byte array where 1 values indicate polycube positions

Returns:
tuple(int): Run length encoded polycube in the form (X, Y, Z, a, b, c, ...)
int: a unique integer hash

"""
r = []
r.extend(polycube.shape)
current = None
val = 0
for x in polycube.flat:
if current is None:
current = x
val = 1
pass
elif current == x:
val += 1
elif current != x:
r.append(val if current == 1 else -val)
current = x
val = 1

r.append(val if current == 1 else -val)

return tuple(r)

pack_cube = np.packbits(polycube.flatten())
data = 0
for part in pack_cube:
data = (data << 8) + int(part)
out = (data * 100000) + (polycube.shape[0] * 1000) + (polycube.shape[1] * 10) + (polycube.shape[2]) # add volume dimensions to lower bits of hash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this break on dimensions above 10? for the shape[2] component?

As this can collide with shape[] = 11, 11, 11
generating
xxxxxxxx011121
instead of
xxxxxxxx111111

Copy link
Author

@bertie2 bertie2 Jul 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, yes, I was intending for it to be 3 digits per dimension so that there would be plenty of space, since unless theirs a breakthrough somewhere n>99 is completely infeasible, just got my math's very wrong.
in reality though the chance of collision at these very high sizes is vanishingly small in fact there where no collisions for n=12 or n=13, but I will fix in in my next run, and this definitely needs to be fixed before this ever gets merged (if it ever does).

return out


def cube_exists_rle(polycube, polycubes_rle):
"""
Expand Down