2

I'm trying to make an array of 4x4 (16) pixel black and white images with all possible combinations. I made the following array as a template:

template = [[0,0,0,0],    # start with all white pixels
            [0,0,0,0],    
            [0,0,0,0],
            [0,0,0,0]]

I then want to iterate through the template and changing the 0 to 1 for every possible combination. I tried to iterate with numpy and itertools but can only get 256 combinations, and with my calculations there should be 32000 (Edit: 65536! don't know what happened there...). Any one with mad skills that could help me out?

JonasJR
  • 76
  • 9

4 Answers4

1

As you said, you can use the itertools module to do this, in particular the product function:

import itertools
import numpy as np

# generate all the combinations as string tuples of length 16
seq = itertools.product("01", repeat=16)

for s in seq:
    # convert to numpy array and reshape to 4x4
    arr = np.fromiter(s, np.int8).reshape(4, 4)
    # do something with arr
Blackecho
  • 1,226
  • 5
  • 18
  • 26
1

You would have a total of 65536 such combinations of such a (4 x 4) shaped array. Here's a vectorized approach to generate all those combinations, to give us a (65536 x 4 x 4) shaped multi-dim array -

mask = ((np.arange(2**16)[:,None] & (1 << np.arange(16))) != 0)
out = mask.astype(int).reshape(-1,4,4)

Sample run -

In [145]: out.shape
Out[145]: (65536, 4, 4)

In [146]: out
Out[146]: 
array([[[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[1, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 1, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       ..., 
       [[1, 0, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]],

       [[0, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]],

       [[1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]]])
Divakar
  • 218,885
  • 19
  • 262
  • 358
0

One possibility which relies on a for loop

out = []
for i in range(2**16):
   out.append(np.frombuffer("{:016b}".format(i).encode('utf8')).view(np.uint8).reshape(4,4)-48)

Obviously you could make that a list comprehension if you like.

It takes advantage of Python string formatting which is able to produce the binary representation of integers. The format string instructs it to use 16 places filling with zeros on the left. The string is then encoded to give a bytes object which numpy can interpret as an array.

In the end we subtract the code for the character "0" to get a proper 0. Luckily, "1" sits just above "0", so that's all we need to do.

Paul Panzer
  • 51,835
  • 3
  • 54
  • 99
0

First I'll iterate for all numbers from 0 to (2^16)-1. Then I'll create a 16 character binary string for each of those numbers and thus covering all possible combinations

After that I converted the string to a list and made a 2d list out of it using list comprehension and slicing.

all_combinations = []

for i in xrange(pow(2,16))
    binary = '{0:016b}'.format(i)  ## Converted number to binary string
    binary = map(int,list(binary))  ## String to list ## list(map(int,list(binary))) in py 3
    template = [binary[i:i+4] for i in xrange(0, len(binary), 4)] #created 2d list
    all_combinations.append(template)
Abhishek J
  • 2,386
  • 2
  • 21
  • 22