Skip to content

Instantly share code, notes, and snippets.

@mjonasz
Created December 9, 2017 19:43
Show Gist options
  • Save mjonasz/48ae3fd6c4fbb8a853b91bbfa16b9a7f to your computer and use it in GitHub Desktop.
Save mjonasz/48ae3fd6c4fbb8a853b91bbfa16b9a7f to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# dostajemy kostke rubika z qrcodem, trzeba ją ułożyć i przeczytać qr cody, w którymś jest link do następnego levelu
# tutaj zamiast ją układać robię permutacje krawędzi * permutacje rogów (z odpowiednim obrotem),
# to daje 4!*4! per ściane, czyli jeszcze *6 per kostke - to je spoko, najwolniejsze tu jest ściąganie obrazków z japonii
from PIL import Image
import zbarlight
import itertools
import requests
from io import BytesIO
from enum import Enum
CORNER = "CORNER"
EDGE = "EDGE"
CENTER = "CENTER"
def find_color(im):
for x in range(0, im.width):
for y in range(0, im.height):
pixel = im.getpixel((x, y))
if pixel != (0, 0, 0):
return pixel
def preview(im):
prev = im.resize((41 * 6, 41 * 6))
prev.show()
def combine_blocks(corners, edges, center):
im = Image.new('RGB', (41, 41))
im.paste(corners[0], (0, 0, 14, 14))
im.paste(corners[1], (41 - 14, 0, 41, 14))
im.paste(corners[2], (41 - 14, 41 - 14, 41, 41))
im.paste(corners[3], (0, 41 - 14, 14, 41))
im.paste(edges[0], (14, 0, 14 + 13, 14))
im.paste(edges[1], (41 - 14, 14, 41, 14 + 13))
im.paste(edges[2], (14, 41 - 14, 14 + 13, 41))
im.paste(edges[3], (0, 14, 14, 14 + 13))
im.paste(center, (14, 14, 41 - 14, 41 - 14))
return im
def parse_wall(im):
corners = []
edges = []
center = []
im = im.resize((41, 41))
corners.append(im.crop((0, 0, 14, 14)))
corners.append(im.crop((41 - 14, 0, 41, 14)))
corners.append(im.crop((41 - 14, 41 - 14, 41, 41)))
corners.append(im.crop((0, 41 - 14, 14, 41)))
edges.append(im.crop((14, 0, 14 + 13, 14)))
edges.append(im.crop((41 - 14, 14, 41, 14 + 13)))
edges.append(im.crop((14, 41 - 14, 14 + 13, 41)))
edges.append(im.crop((0, 14, 14, 14 + 13)))
center.append(im.crop((14, 14, 41 - 14, 41 - 14)))
# preview(combine_blocks(corners, edges, center[0]))
all_blocks = []
for i in range(0, 4):
all_blocks.append({"im": corners[i], "pos": i, "color": find_color(corners[i]), "type": CORNER})
all_blocks.append({"im": edges[i], "pos": i, "color": find_color(edges[i]), "type": EDGE})
all_blocks.append({"im": center[0], "pos": 0, "color": find_color(center[0]), "type": CENTER})
return all_blocks
def download_image(name):
url = f"http://qubicrube.pwn.seccon.jp:33654/images/{name}"
print(url)
response = requests.get(url)
return Image.open(BytesIO(response.content))
def read_images(base):
names = "UDFBLR"
load_image = lambda name: download_image(f"{base}_{name}.png")
return list(map(load_image, names))
def read_qr(im):
code = zbarlight.scan_codes('qrcode', im.resize((41 * 5, 41 * 2)))
if code is not None:
return code[0].strip()
def extract_all_colors(blocks):
colors = set()
for block in blocks:
colors.add(block["color"])
return colors
def rotate(block, desired_pos):
pos = block["pos"]
im = block["im"]
num_of_rotations = (desired_pos - pos + 4) % 4
# print(f"{desired_pos} - {pos} = {num_of_rotations}")
return im.rotate(-90 * num_of_rotations, expand=True)
def rotate_group(blocks):
rotated = []
for i in range(0, 4):
# print("START")
# print(blocks[i])
# print("--------")
# print(rotate(blocks[i], i))
rotated.append(rotate(blocks[i], i))
# print("END")
return rotated
def solve_wall(blocks):
corners = list(filter(lambda b: b["type"] == CORNER, blocks))
edges = list(filter(lambda b: b["type"] == EDGE, blocks))
center = list(filter(lambda b: b["type"] == CENTER, blocks))
corners_perms = itertools.permutations(corners)
edges_perms = itertools.permutations(edges)
center = center[0]["im"]
x = 0
for corners_perm, edges_perm in itertools.product(corners_perms, edges_perms):
# print(rotate_group(edges_perm))
new_im = combine_blocks(rotate_group(corners_perm), rotate_group(edges_perm), center)
# preview(new_im)
# input("click")
# new_im.save(f"test/{x}.png", "png")
x = x + 1
qr = read_qr(new_im)
if qr is not None:
return qr
# images = read_images("02c286df1bbd7923d1f7")
def solve(code):
images = read_images(code)
all_blocks = []
for im in images:
all_blocks = all_blocks + parse_wall(im)
colors = extract_all_colors(all_blocks)
for color in colors:
singe_color_blocks = list(filter(lambda b: b["color"] == color, all_blocks))
solved = solve_wall(singe_color_blocks).decode()
if solved.endswith("/ 50"):
print(solved)
if solved.startswith("SECCON{"):
print(solved)
if solved.startswith("http"):
return solved
code = "01000000000000000000"
while code is not None:
code = solve(code)
code = code.split("/")[-1]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment