# ShreddedWe get 27 images with black and white stripes that look like they may be part of a QR code. The six white images can be ignored, so the total number of permutations becomes `21! ~= 10^19`. Well, brute force is out. Lets try to reduce that by taking a look at the QR code specification.
1. The size is 21x21, so this is [version 1](http://www.qrcode.com/en/about/version.html), meaning there should a 7x7 black square containing a 5x5 white and a 3x3 black square in the top left, top right and bottom left corner. There has to be a white "quiet zone" around the squares.2. There are [timing patterns](http://www.esponce.com/resources/about-qr-codes) (alternating black and white) at two places.3. There is a black ["Dark module"](https://www.thonky.com/qr-code-tutorial/format-version-information#dark-module) at (8, 13).4. There is a 15 bit [format string](https://www.thonky.com/qr-code-tutorial/format-version-information#format-string) encoding the error correction level and the mask pattern used. There are [32 alternatives](https://www.thonky.com/qr-code-tutorial/format-version-tables).
This means we need to fit this image:

(Source: https://www.thonky.com/qr-code-tutorial/format-version-information)
We use (1) to match up the squares and the surrounding quiet zone, (2) to select the right slice for column 6 and (2) and (3) to reduce the number of potential permutations for the center columns. 
Now there is a limited number of slices that match the two required black pixels in column 8 (the one with the full format string) and aren't already used for the squares. Let's see if any of them match with the wanted format strings using a litle Python script.
```python# 1=black, 0=white
# wanted from https://www.thonky.com/qr-code-tutorial/format-version-tableswanted = ["111011111000100", "111001011110011", "111110110101010", "111100010011101", "110011000101111", "110001100011000", "110110001000001", "110100101110110",      "101010000010010", "101000100100101" , "101111001111100", "101101101001011", "100010111111001", "100000011001110", "100111110010111", "100101010100000",    "011010101011111", "011000001101000", "011111100110001", "011101000000110", "010010010110100", "010000110000011", "010111011011010", "010101111101101", "001011010001001",      "001001110111110", "001110011100111", "001100111010000", "000011101100010", "000001001010101", "000110100001100", "000100000111011"]
# Based on possible pixels 0-6 (lower part of slice) in column 8possible = ["1111000", "1010111", "1100011", "0010001", "1101110", "1111001"]
for f in wanted:    # Check if the first part matches up    if f[:7] not in possible:        continue     # There are two black and one white pixels in row 8, column 2-4    sum = 0    for i in range(2,5):        if f[i] == "1":            sum+=1    if sum == 2:        # We found something that matches all requirements        print (f)```
Luckily there is only one match, `111100010011101`. Combining all that we have the following situation
![intermidiary](intermidiary.png)
where slices marked black are final, a green column may still switch with another green column, a red with another red and so on. This means we have `2*2*2*2*3=48` permutations. Not to bad, time for some brute force:
```pythonimport itertoolsfrom PIL import Imagefrom pyzbar.pyzbar import decode
# Read all imagesimages = map(Image.open, [str(i)+".png" for i in range(27)])images = list(images)
widths, heights = zip(*(i.size for i in images))total_width = sum(widths)max_height = max(heights)
# Our best guess for now, based on image namespositions = [5, 6,25,16, 2, 15, 26, 3, 23, 19, 20, 10, 21, 7, 8, 1, 4, 22, 24, 18, 14]
# Encoding the requirements in the image above into code, first slice has to be image 5, second is image 6, third may be image 16 or 25 and so on.for i in filter(lambda x: x[0] == 5 and x[1] == 6 and x[4] == 2 and x[5] == 15 and x[6] ==26 and x[7] == 3 and x[8] == 23 and x[13] == 7 and x[14] == 8 and x[20]==14 and x[2] in [16,25] and x[3] in [16,25] and x[9] in [19,10] and x[11] in [19,10] and x[10] in [20,21] and x[12] in [20,21] and x[15] in [1,18] and x[19] in [1,18] and x[16] in [4,22,24] and x[17] in [4,22,24] and x[18] in [4,22,24],itertools.permutations(positions)):    # Combine slices into one image    new_im = Image.new('RGB', (total_width, max_height),color=(255,255,255,0))    x_offset = 20 # Leave some whitespace at the beginning
    for image_index in i:        im = images[image_index]        new_im.paste(im, (x_offset,0))        x_offset += im.size[0]
    # Check if the generated QR code is valid    if (decode(new_im) != []):        print(decode(new_im))        new_im.save("final.png")```
After a few seconds we get the message `GOOD JOB. FLAG-80AD8BCF79` and the QR code
![final](final.png)