Skip to content

Instantly share code, notes, and snippets.

@potetisensei
Created February 7, 2014 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save potetisensei/8866000 to your computer and use it in GitHub Desktop.
Save potetisensei/8866000 to your computer and use it in GitHub Desktop.
#-*- encoding:utf-8 -*-
from base64 import b64encode, b64decode
from pickle import dumps, loads
from struct import pack, unpack
NONE = -1
WHITE = 1
RED = 2
BLUE = 3
GREEN = 4
ORANGE = 5
YELLOW = 6
X = 0
Y = 1
Z = 2
ROW = 32
class ACube:
"""Like dice
___
/ 1 /|
/ / |
| ̄ ̄ ̄| 3 |
| 2 | /
|___|/"""
def __init__(self, data="", color1=NONE, color2=NONE, color3=NONE, color4=NONE, color5=NONE, color6=NONE):
self.data = data
self.color1 = color1
self.color2 = color2
self.color3 = color3
self.color4 = color4
self.color5 = color5
self.color6 = color6
self.now_top = 1
self.now_front = 2
def turn_x(self, times):
reindex = {1:0, 2:1, 6:2, 5:3}
index = [1, 2, 6, 5]
self.now_top = index[(reindex[self.now_top] + times)%4]
self.now_front = index[(reindex[self.now_front] + times)%4]
def turn_y(self, times):
reindex = {1:0, 3:1, 6:2, 4:3}
index = [1, 3, 6, 4]
self.now_top = index[(reindex[self.now_top] - times)%4]
def turn_z(self, times):
reindex = {2:0, 3:1, 5:2, 4:3}
index = [2, 3, 5, 4]
self.now_front = index[(reindex[self.now_front] - times)%4]
def reverse_x(self, times):
pass
def reverse_y(self, times):
pass
def reverse_z(self, times):
pass
class Rubic:
def init(self):
self.state = [[[ACube() for k in range(ROW)] for j in range(ROW)] for i in range(ROW)]
for i in range(ROW):
for j in range(ROW):
self.state[0][i][j].color1 = WHITE
self.state[ROW-1][i][j].color6 = YELLOW
self.state[i][0][j].color2 = RED
self.state[i][ROW-1][j].color5 = ORANGE
self.state[i][j][0].color4 = GREEN
self.state[i][j][ROW-1].color3 = BLUE
def rotate(self, code):
calc_funcs = [lambda x,y: (x,y),
lambda x,y: (ROW-y-1, x),
lambda x,y: (ROW-x-1, ROW-y-1),
lambda x,y: (y, ROW-x-1)]
flag = [[None for j in range(ROW)] for i in range(ROW)]
axis, others = divmod(code, 4*ROW)
index, times = divmod(others, 4)
if axis == X:
for i in range(ROW):
for j in range(ROW):
self.state[i][j][index].turn_x(times)
i2, j2 = calc_funcs[times](i, j)
if flag[i2][j2]:
self.state[i2][j2][index] = self.state[i][j][index]
self.state[i][j][index] = flag[i2][j2]
else :
flag[i][j] = self.state[i][j][index]
elif axis == Y:
for i in range(ROW):
for j in range(ROW):
self.state[i][index][j].turn_y(times)
i2, j2 = calc_funcs[times](i, j)
if flag[i2][j2]:
self.state[i2][index][j2] = self.state[i][index][j]
self.state[i][index][j] = flag[i2][j2]
else :
flag[i][j] = self.state[i][index][j]
elif axis == Z:
for i in range(ROW):
for j in range(ROW):
self.state[index][i][j].turn_z(times)
i2, j2 = calc_funcs[times](i, j)
if flag[i2][j2]:
self.state[index][i2][j2] = self.state[index][i][j]
self.state[index][i][j] = flag[i2][j2]
else :
flag[i][j] = self.state[index][i][j]
else :
return -1
def reverse(self, code):
calc_funcs = [lambda x,y: (x,y),
lambda x,y: (ROW-y-1, x),
lambda x,y: (ROW-x-1, ROW-y-1),
lambda x,y: (y, ROW-x-1)]
flag = [[None for j in range(ROW)] for i in range(ROW)]
axis, others = divmod(code, 4*ROW)
index, times = divmod(others, 4)
if axis == X:
for i in range(ROW):
for j in range(ROW):
self.state[i][j][index].reverse_x(times)
i2, j2 = calc_funcs[times](i, j)
if flag[i2][j2]:
self.state[i2][j2][index] = self.state[i][j][index]
self.state[i][j][index] = flag[i2][j2]
else :
flag[i][j] = self.state[i][j][index]
elif axis == Y:
for i in range(ROW):
for j in range(ROW):
self.state[i][index][j].reverse_y(times)
i2, j2 = calc_funcs[times](i, j)
if flag[i2][j2]:
self.state[i2][index][j2] = self.state[i][index][j]
self.state[i][index][j] = flag[i2][j2]
else :
flag[i][j] = self.state[i][index][j]
elif axis == Z:
for i in range(ROW):
for j in range(ROW):
self.state[index][i][j].reverse_z(times)
i2, j2 = calc_funcs[times](i, j)
if flag[i2][j2]:
self.state[index][i2][j2] = self.state[index][i][j]
self.state[index][i][j] = flag[i2][j2]
else :
flag[i][j] = self.state[index][i][j]
else :
return -1
def rotate_all(self, codes):
for i in codes:
if self.rotate(i) == -1:
return -1
def reverse_all(self, codes):
for i in codes[::-1]:
if self.reverse(i) == -1:
return -1
def set_data(self, data):
for i in range(ROW):
for j in range(ROW):
for k in range(ROW):
if len(data) <= i * (ROW**2) + j * ROW + k:
return
self.state[i][j][k].data = data[i * (ROW**2) + j * ROW + k]
def read_data(self, length):
ret = ""
for i in range(ROW):
for j in range(ROW):
for k in range(ROW):
if length <= i * (ROW**2) + j * ROW + k:
return ret
if not self.state[i][j][k].data:
return ""
ret += self.state[i][j][k].data
def encrypt(self, plain, key, iv=[]):
encoded = b64encode(plain)
length = len(encoded)
if length > ROW**3:
return ""
self.init()
if self.rotate_all(iv) == -1:
return ""
self.set_data(encoded)
if self.rotate_all(key) == -1:
return ""
return pack("<I", length) + dumps(self.state)
def decrypt(self, enc, key):
length = unpack("<I", enc[:4])[0]
if length > ROW**3:
return ""
del self.state
self.state = loads(enc[4:])
if self.reverse_all(key) == -1:
return ""
return b64decode(self.read_data(length))
def main():
flag = open("flag.txt").read()
key = eval(open("key.txt").read()) # type(key) => list
iv = eval(open("iv.txt").read()) # type(iv) => list
cipher = Rubic()
enc = cipher.encrypt(flag, key, iv)
open("flag.enc", "wb").write(enc)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment