209 lines
4.9 KiB
Python
Executable File
209 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import math
|
|
import string
|
|
|
|
chars = string.digits + string.ascii_letters
|
|
|
|
|
|
def to_base(num, base):
|
|
if base > len(chars):
|
|
raise ValueError(f"Base must be less than {len(chars)}")
|
|
|
|
if abs(num) == 0:
|
|
return str(num)
|
|
else:
|
|
negative = num < 0
|
|
num = abs(num)
|
|
|
|
digits = []
|
|
while num:
|
|
digits.append(chars[num % base])
|
|
num //= base
|
|
|
|
return ('-' if negative else '') + ''.join(digits[::-1])
|
|
|
|
|
|
test_me = {
|
|
"023": "a",
|
|
"030": "b",
|
|
"031": "c",
|
|
"032": "d",
|
|
"033": "e",
|
|
"103": "f",
|
|
"113": "g",
|
|
"123": "h",
|
|
"130": "i",
|
|
"131": "j",
|
|
"132": "k",
|
|
"133": "l",
|
|
"203": "m",
|
|
"213": "n",
|
|
"223": "o",
|
|
"230": "p",
|
|
"231": "q",
|
|
"232": "r",
|
|
"233": "s",
|
|
"303": "t",
|
|
"313": "u",
|
|
"323": "v",
|
|
"330": "w",
|
|
"331": "x",
|
|
"332": "y",
|
|
"333": "z"
|
|
}
|
|
|
|
for i, code in enumerate(test_me.keys()):
|
|
# the lowercase letter codes use a pattern that repeats every seven letters.
|
|
# starting from 030Q (12D), the code increments by one three times, then increments by four four times.
|
|
|
|
# firstly, increase the output by 16 for every 7 in the input.
|
|
# then, if i % 7 is 0, 1, 2, or 3, add that number to the output.
|
|
# otherwise, subtract 3 from i % 7, multiply the result by 4, and add that to the output.
|
|
# finally, add 11, because that's where the lowercase chars start.
|
|
out = i // 7 * 16 + max((i % 7 - 3) * 4, i % 7) + 11
|
|
|
|
check = int(code, 4)
|
|
|
|
print(f"In: {i:03}\tOut: {out:03}\tCode: {to_base(out, 4).zfill(3)} {('GOOD' if check == out else 'FAIL')}")
|
|
|
|
print("\n===================\n")
|
|
|
|
for i, code in enumerate(test_me.keys()):
|
|
# now to do the process in reverse - converting a letter code to an index.
|
|
# first we subtract 11 to get the codes to start from zero.
|
|
x = int(code, 4) - 11
|
|
|
|
# first, add 7 for every 16 in the input.
|
|
# next, we can use (x + 10) % 16 to get the sequence '10, 11, 12, 13, 14, 2, 6'.
|
|
# we can use min() to replace the 2 with a 5, and then mod the whole sequence by 10 to get 0 through 6 repeating.
|
|
# now we just need to add the two together.
|
|
out = x // 16 * 7 + (max((x + 10) % 16, 5) % 10)
|
|
|
|
character = string.ascii_lowercase[out] if out < len(string.ascii_lowercase) else '?'
|
|
|
|
print(f"In: {x:03}\tOut: {out:03}\tGoal: {i:03}\tChar: {character} {('GOOD' if character == test_me[code] else 'FAIL')}")
|
|
|
|
exit(0)
|
|
|
|
headings = {
|
|
"QUAD": "₄",
|
|
"SEPT": "₇",
|
|
"GOAL7": "₇",
|
|
"DEC": "₁₀",
|
|
"GOAL": "₁₀",
|
|
"ORIG": "₁₀",
|
|
"SXTNS": "₁₀",
|
|
"FOURS": "₁₀",
|
|
"MOD16": "₁₀",
|
|
"MOD7": "₇",
|
|
"MOD8": "₈",
|
|
"MOD4": "₄",
|
|
"MAGIC": ""
|
|
}
|
|
|
|
out = ""
|
|
for heading in headings:
|
|
out += f"{heading:8}"
|
|
print(out)
|
|
print("=" * 8 * len(headings))
|
|
|
|
goal = 2
|
|
successes = 0
|
|
for key in test_me.keys():
|
|
# breaks on i in [31, 46, 47, 51, 61, 62, 63]
|
|
#
|
|
original_value = int(key, 4)
|
|
|
|
# the code starts at 023₄, which is 11₁₀, so we subtract 11₁₀ as an initial offset
|
|
x = original_value - 1
|
|
|
|
sixteens = (x // 16)
|
|
eights = (x // 8)
|
|
mod_sixteen = x % 16
|
|
mod_eight = x % 8
|
|
fours = (x // 4)
|
|
mod_sixteen_mod_seven = mod_sixteen % 7
|
|
# magic = abs(-8 + ((mod_eight // mod_sixteen) * (16 * sixteens + 8 + sixteens)))
|
|
magic = 8
|
|
|
|
letter_index = ((7 * sixteens) + (x % 8)) - ((1 - (mod_sixteen // 8)) * (2 + 3 * (fours % 2)))
|
|
|
|
output = [
|
|
key,
|
|
to_base(letter_index, 7),
|
|
to_base(goal, 7),
|
|
letter_index,
|
|
goal,
|
|
x,
|
|
sixteens,
|
|
fours,
|
|
mod_sixteen,
|
|
mod_sixteen_mod_seven,
|
|
mod_eight,
|
|
x % 4,
|
|
magic
|
|
]
|
|
|
|
colour_code = 91
|
|
if goal == letter_index:
|
|
successes += 1
|
|
colour_code = 0
|
|
|
|
print(f'\033[{colour_code}m', end='')
|
|
|
|
out = ""
|
|
for i, suffix in enumerate(headings.values()):
|
|
value = str(output[i]).zfill(3) + suffix
|
|
out += f"{value:8}"
|
|
|
|
print(out)
|
|
|
|
goal += 1
|
|
|
|
print(f"Succeeded on {successes} of {goal} attempts ({math.floor(successes / float(goal) * 100)}%)")
|
|
|
|
exit(0)
|
|
|
|
outputs = {
|
|
"decimals": [],
|
|
"indices": [],
|
|
"mod_fours": [],
|
|
"divided_by_sixteens": [],
|
|
"indices_plus_mod_fours": [],
|
|
"actual_indices": [],
|
|
"correctness_checks": []
|
|
}
|
|
|
|
position = 0
|
|
|
|
for x, expected_value in test_me.items():
|
|
wacky = " [WACKY]" if x[1] != "3" else ""
|
|
num = int(x, 4) - 11
|
|
index = (num // 4)
|
|
mod_four = num % 4
|
|
divided_by_sixteen = ((num) // 16)
|
|
# actual_index = index + mod_four + (3 * divided_by_sixteen)
|
|
actual_index = (num // 4) + (num % 4) + (3 * ((num - 4) // 16)) + 3
|
|
# actual_index = (num // 16) * 7 + (num % 4)
|
|
|
|
correctness_check = "GUD" if actual_index == position else "OOP"
|
|
|
|
outputs["decimals"].append(f"{num:3d}")
|
|
outputs["indices"].append(f"{index:3d}")
|
|
outputs["mod_fours"].append(f"{mod_four:3d}")
|
|
outputs["divided_by_sixteens"].append(f"{divided_by_sixteen:3d}")
|
|
outputs["indices_plus_mod_fours"].append(f"{mod_four + index:3d}")
|
|
outputs["actual_indices"].append(f"{actual_index:3d}")
|
|
outputs["correctness_checks"].append(correctness_check)
|
|
|
|
position += 1
|
|
|
|
# print(f"{i}Q = {num}D{wacky}: {index}")
|
|
|
|
print(' '.join(test_me.keys()))
|
|
print(' ' + ' '.join(test_me.values()))
|
|
|
|
# ignored_outputs = [""]
|
|
for key, numbers in outputs.items():
|
|
print(' '.join(numbers) + f" ({key})")
|