-
Notifications
You must be signed in to change notification settings - Fork 1
/
fold_challenge.py
75 lines (52 loc) · 3.98 KB
/
fold_challenge.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from typing import List
import ctypes
import math
URLSAFE_BASE64_CHAR_CODE_TO_INT = [-0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, 0x3e, -0x1, -0x1, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, -0x1, -0x1, -0x1, -0x1, 0x3f, -0x1, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1, -0x1,]
URLSAFE_BASE64_INT_TO_CHAR = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "-", "_",]
def urlsafe_base64_char_to_int(c: str) -> int:
return URLSAFE_BASE64_CHAR_CODE_TO_INT[ord(c) % 0x100]
def urlsafe_base64_int_to_char(i: int) -> str:
if 0 > i or i > 63:
raise ValueError( "arg i must be between 0 .. 63 inclusive")
return URLSAFE_BASE64_INT_TO_CHAR[i % 0x40]
def urlsafe_base4096_int_to_char(i: int) -> str:
if 0 > i or i > 4095:
raise ValueError( "arg i must be between 0 .. 4095 inclusive")
return ("" + urlsafe_base64_int_to_char(i >> 0x6) + urlsafe_base64_int_to_char(i & 0x3f))
def urlsafe_base64_str_2_int_array(s: str) -> List[int]:
return [urlsafe_base64_char_to_int(c) for c in s]
def urlsafe_base64_int_array_2_string(int_array: List[int]) -> str:
return "".join([urlsafe_base64_int_to_char(i) for i in int_array])
def hash_int_array(int_array: List[int]) -> int:
hsh = 0
for i in int_array:
# https://stackoverflow.com/questions/41610186/difference-between-javascript-bit-wise-operator-code-and-python-bit-wise-operato
hsh = ctypes.c_int(hsh << 0x5 ^ 0).value - hsh + i
hsh = hsh & hsh
if hsh < 0:
hsh *= -0x1
return hsh
def solve(fseed: str, fslots: int, fdepth: int) -> str:
if not fseed or fslots < 0x1:
return "0"
res = []
int_array = urlsafe_base64_str_2_int_array(fseed)
for _ in range(fslots):
int_array = fold_base64_int_array(int_array, 0x1f)
hsh = hash_int_array(fold_base64_int_array(int_array, fdepth))
res.append(urlsafe_base4096_int_to_char(hsh % 0x1000))
return "".join(res)
def fold_base64_int_array(int_array: List[int], foldCount: int) -> List[int]:
reversed_int_array = int_array[::-1]
res = int_array[:]
offset = 0
y = 0
z = 0
for _ in range(foldCount):
offset += 1
for x in range(len(int_array)):
# dont even ask...
res[x] = (math.floor(((res[x] + reversed_int_array[(x + offset) % len(reversed_int_array)]) * 73) / 8) + y + z) % 64
z = math.floor(y / 2)
y = math.floor(res[x] / 2)
return res