I hope, this image can explain my problem better like following words. Let's say, the "shape" is represented as coordinates like:
shape = {(0,0), (0,1), (1,0), (1,1)}
I now want to find every possible combination of range(2, len(shape)+1)
subshapes that are able to compose the shape. Rotated duplicates are not needed (like they are omitted on the image).
For now I started with the code below, which I think leads to a useful direction, but I have a very deep feeling, that there is a more elegant way out there instead of "iterating through all possible solutions" ;). Maybe someone has an idea or can push me in the right direction.
from itertools import combinations_with_replacement
# coordinates of "pixels": origin (0,0) is top left
shape = [(0,0),(0,1),(1,0),(1,1)]
def sums(a, b):
return tuple(sum(x) for x in zip(a, b))
def combinations_pixels_per_subshape(shape: list, n_subshapes: int):
# returns the possible combinations of n pixels per n_subshapes,
# that add up to the pixels in given shape.
shape_pixels = len(shape)
for c in combinations_with_replacement(range(1, shape_pixels), n_subshapes):
if sum(c) == shape_pixels:
yield(c)
# a shape can have as may subshapes as single pixels.
for nsub in range(2, len(shape) + 1):
print(nsub, "subshapes")
for comb in combinations_pixels_per_subshape(shape, nsub):
print(comb)
for subpix in comb:
print(subpix)
break
The expected output (or one possible representation of it) could be - according to the image:
[[(0,0)], [(0,1)], [(1,0)], [(1,1)]] # every single pixel (=4 subshapes)
[[(0,0)], [(0,1), (1,0), (1,1)]] # a single pixel and a block of 3 (=2 subshapes)
[[(0,0),(1,0)],[(0,1),(1,1)]] # 2 blocks of 2 (=2 subshapes)
[[(0,0)], [(0,1)], [(1,0), (1,1)]] # 2 single pixel and one block of 2 (=3 subshapes)
the last line could just as well be [[(1,0)], [(1,1)], [(0,0), (0,1)]]
or [[(0,0)], [(1,0)], [(0,1), (1,1)]]
which would be the same shapes, but at different locations or rotated by 90°.