Initial commit
This commit is contained in:
commit
97a4330bc0
110 changed files with 7006 additions and 0 deletions
BIN
2024/17/Notes.xopp
Normal file
BIN
2024/17/Notes.xopp
Normal file
Binary file not shown.
4
2024/17/README.md
Normal file
4
2024/17/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
two.py and two_bf.py were written before I got the 2 stars.
|
||||
|
||||
First fails on demo2, seconds takes 23 years (literally).
|
||||
|
5
2024/17/demog
Normal file
5
2024/17/demog
Normal file
|
@ -0,0 +1,5 @@
|
|||
Register A: 41644071
|
||||
Register B: 0
|
||||
Register C: 0
|
||||
|
||||
Program: 2,4,1,2,0,3,5,5,3,0
|
69
2024/17/one.py
Normal file
69
2024/17/one.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
# program 3 bits numbers
|
||||
# registers A, B, C: any int
|
||||
# instruction 3 bits, operand 3 bits
|
||||
# literal operand, combo operand: 0-3 literal, 4-6: register A,B,C
|
||||
# instruction pointer starts at 0
|
||||
|
||||
# 0 adv: truncated division, numerator = A, denominator 2**combo operand -> A
|
||||
# 1 bxl: bitwise XOR, B ^ literal operand -> B
|
||||
# 2 bst: combo operand % 8 -> B
|
||||
# 3 jnz: { A = 0: nothing; A != 0: literal operand -> IP } # no increase there!
|
||||
# 4 bxc: bitwise XOR, B ^ C -> B # operand ignored
|
||||
# 5 out: combo operand % 8 -> output
|
||||
# 6 bdv: truncated division, numerator = A, denominator 2**combo operand -> B
|
||||
# 7 cdv: truncated division, numerator = A, denominator 2**combo operand -> C
|
||||
|
||||
A = int(lines[0].split(":")[1])
|
||||
B = int(lines[1].split(":")[1])
|
||||
C = int(lines[2].split(":")[1])
|
||||
|
||||
program = [int(p) for p in lines[4].split(":")[1].split(",")]
|
||||
|
||||
output: list[int] = list()
|
||||
|
||||
ip = 0
|
||||
while ip in range(len(program)):
|
||||
inst = program[ip]
|
||||
liop = program[ip + 1]
|
||||
coop = liop
|
||||
if liop == 4:
|
||||
coop = A
|
||||
elif liop == 5:
|
||||
coop = B
|
||||
elif liop == 6:
|
||||
coop = C
|
||||
trunc_div = A // 2**coop
|
||||
|
||||
if inst == 0:
|
||||
A = trunc_div
|
||||
elif inst == 1:
|
||||
B = B ^ liop
|
||||
elif inst == 2:
|
||||
B = coop % 8
|
||||
elif inst == 3:
|
||||
if A != 0:
|
||||
ip = liop
|
||||
continue
|
||||
elif inst == 4:
|
||||
B = B ^ C
|
||||
elif inst == 5:
|
||||
output.append(coop % 8)
|
||||
elif inst == 6:
|
||||
B = trunc_div
|
||||
elif inst == 7:
|
||||
C = trunc_div
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
ip += 2
|
||||
|
||||
print(",".join([str(o) for o in output]))
|
202
2024/17/two.py
Normal file
202
2024/17/two.py
Normal file
|
@ -0,0 +1,202 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
# program 3 bits numbers
|
||||
# registers A, B, C: any int
|
||||
# instruction 3 bits, operand 3 bits
|
||||
# literal operand, combo operand: 0-3 literal, 4-6: register A,B,C
|
||||
# instruction pointer starts at 0
|
||||
|
||||
# 0 adv: truncated division, numerator = A, denominator 2**combo operand -> A
|
||||
# 1 bxl: bitwise XOR, B ^ literal operand -> B
|
||||
# 2 bst: combo operand % 8 -> B
|
||||
# 3 jnz: { A = 0: nothing; A != 0: literal operand -> IP } # no increase there!
|
||||
# 4 bxc: bitwise XOR, B ^ C -> B # operand ignored
|
||||
# 5 out: combo operand % 8 -> output
|
||||
# 6 bdv: truncated division, numerator = A, denominator 2**combo operand -> B
|
||||
# 7 cdv: truncated division, numerator = A, denominator 2**combo operand -> C
|
||||
|
||||
instnames = ["adv", "bxl", "bst", "jnz", "bxc", "out", "bdv", "cdv"]
|
||||
|
||||
oA = int(lines[0].split(":")[1])
|
||||
oB = int(lines[1].split(":")[1])
|
||||
oC = int(lines[2].split(":")[1])
|
||||
|
||||
program = [int(p) for p in lines[4].split(":")[1].split(",")]
|
||||
|
||||
|
||||
def test(oA: int) -> list[int]:
|
||||
# print(32, "Testing", A)
|
||||
|
||||
ip = 0
|
||||
A = oA
|
||||
B = oB
|
||||
C = oC
|
||||
|
||||
output: list[int] = list()
|
||||
oi = 0
|
||||
|
||||
# jumped: set[tuple[int, int, int, int]] = set()
|
||||
|
||||
while ip in range(len(program)):
|
||||
inst = program[ip]
|
||||
liop = program[ip + 1]
|
||||
# print(50, ip, instnames[inst], liop)
|
||||
|
||||
if inst == 1:
|
||||
B = B ^ liop
|
||||
elif inst == 3:
|
||||
if A != 0:
|
||||
ip = liop
|
||||
|
||||
# Infinite loop prevention
|
||||
# state = (ip, A, B, C)
|
||||
# # print(66, state, jumped)
|
||||
# if state in jumped:
|
||||
# print("Infinite loop!")
|
||||
# return False
|
||||
# jumped.add(state)
|
||||
|
||||
continue
|
||||
elif inst == 4:
|
||||
B = B ^ C
|
||||
else:
|
||||
coop = liop
|
||||
if liop == 4:
|
||||
coop = A
|
||||
elif liop == 5:
|
||||
coop = B
|
||||
elif liop == 6:
|
||||
coop = C
|
||||
|
||||
if inst == 2:
|
||||
B = coop % 8
|
||||
elif inst == 5:
|
||||
ou = coop % 8
|
||||
output.append(ou)
|
||||
# if oi >= len(program) or program[oi] != ou:
|
||||
# # if len(output) >= 6:
|
||||
# # print(84, oA, output)
|
||||
# return False
|
||||
oi += 1
|
||||
else:
|
||||
trunc_div = A // 2**coop
|
||||
if inst == 0:
|
||||
A = trunc_div
|
||||
elif inst == 6:
|
||||
B = trunc_div
|
||||
elif inst == 7:
|
||||
C = trunc_div
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
ip += 2
|
||||
|
||||
print(102, oA, output, len(output))
|
||||
# return oi == len(program)
|
||||
return output
|
||||
|
||||
|
||||
print(program, len(program))
|
||||
for i in range(0, len(program), 2):
|
||||
inst = program[i]
|
||||
liop = program[i + 1]
|
||||
print(106, i, instnames[inst], liop)
|
||||
print()
|
||||
|
||||
# Bruteforce
|
||||
indexes = list(range(len(program)))
|
||||
|
||||
|
||||
def to_number(inps: list[int]) -> int:
|
||||
A = 0
|
||||
for i in indexes[::-1]:
|
||||
A <<= 3
|
||||
A += inps[i]
|
||||
return A
|
||||
|
||||
|
||||
inps = program.copy()
|
||||
res = test(to_number(inps))
|
||||
while res != program:
|
||||
for i in indexes[::-1]:
|
||||
j = 0
|
||||
revi = - len(program) + i
|
||||
while res[revi] != program[i]:
|
||||
inps[i] = j
|
||||
A = to_number(inps)
|
||||
res = test(A)
|
||||
j += 1
|
||||
print("Hi")
|
||||
|
||||
# i = 3
|
||||
# for j in range(8):
|
||||
# inps = program.copy()
|
||||
# inps[i] = j
|
||||
# A = to_number(inps)
|
||||
# test(A)
|
||||
|
||||
print()
|
||||
|
||||
# indexes = list(range(len(inps)))
|
||||
# for i in indexes[::-1]:
|
||||
# An = A & 0b111
|
||||
# A <<= 3
|
||||
# inp = program[i]
|
||||
# A += inp ^ 2
|
||||
# A <<= 3
|
||||
# A += 1
|
||||
|
||||
# # Smartforce
|
||||
# A = 0
|
||||
# indexes = list(range(len(program)))
|
||||
# for i in indexes[::-1]:
|
||||
# An = A & 0b111
|
||||
# A <<= 3
|
||||
# inp = program[i]
|
||||
# A += inp ^ 2
|
||||
|
||||
|
||||
# # I thought it would be easy
|
||||
# assoc: dict[tuple[int, int], int] = dict()
|
||||
# for i in range(8):
|
||||
# for j in range(8):
|
||||
# out = test(i)[0]
|
||||
# assoc[out] = i, j
|
||||
#
|
||||
# A = 0
|
||||
# for p in program:
|
||||
# A = A << 3
|
||||
# A += assoc[p]
|
||||
#
|
||||
# A = assoc[7] << 6
|
||||
|
||||
res = test(A)
|
||||
print("Ref", program)
|
||||
print("Res", res)
|
||||
print("Cor", res == program)
|
||||
print(A)
|
||||
|
||||
|
||||
# print(test(100000000))
|
||||
#
|
||||
# Amin = 2**(3*(len(program)-1))
|
||||
# Amax = 2**(3*len(program))
|
||||
# Amin = 0
|
||||
# Amax = 7
|
||||
# for A in range(Amin, Amax + 1):
|
||||
# # if A % 65536 == 0:
|
||||
# # print(91, A)
|
||||
# if test(A):
|
||||
# print(A)
|
||||
# break
|
||||
# A += 1
|
||||
|
||||
|
||||
# print(",".join([str(o) for o in output]))
|
125
2024/17/two_bf.py
Normal file
125
2024/17/two_bf.py
Normal file
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import rich.progress
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
# program 3 bits numbers
|
||||
# registers A, B, C: any int
|
||||
# instruction 3 bits, operand 3 bits
|
||||
# literal operand, combo operand: 0-3 literal, 4-6: register A,B,C
|
||||
# instruction pointer starts at 0
|
||||
|
||||
# 0 adv: truncated division, numerator = A, denominator 2**combo operand -> A
|
||||
# 1 bxl: bitwise XOR, B ^ literal operand -> B
|
||||
# 2 bst: combo operand % 8 -> B
|
||||
# 3 jnz: { A = 0: nothing; A != 0: literal operand -> IP } # no increase there!
|
||||
# 4 bxc: bitwise XOR, B ^ C -> B # operand ignored
|
||||
# 5 out: combo operand % 8 -> output
|
||||
# 6 bdv: truncated division, numerator = A, denominator 2**combo operand -> B
|
||||
# 7 cdv: truncated division, numerator = A, denominator 2**combo operand -> C
|
||||
|
||||
instnames = ["adv", "bxl", "bst", "jnz", "bxc", "out", "bdv", "cdv"]
|
||||
|
||||
oA = int(lines[0].split(":")[1])
|
||||
oB = int(lines[1].split(":")[1])
|
||||
oC = int(lines[2].split(":")[1])
|
||||
|
||||
program = [int(p) for p in lines[4].split(":")[1].split(",")]
|
||||
|
||||
|
||||
def test(oA: int) -> bool:
|
||||
# print(32, "Testing", A)
|
||||
|
||||
ip = 0
|
||||
A = oA
|
||||
B = oB
|
||||
C = oC
|
||||
|
||||
# output: list[int] = list()
|
||||
oi = 0
|
||||
|
||||
# jumped: set[tuple[int, int, int, int]] = set()
|
||||
|
||||
while ip in range(len(program)):
|
||||
inst = program[ip]
|
||||
liop = program[ip + 1]
|
||||
# print(50, ip, instnames[inst], liop)
|
||||
|
||||
if inst == 1:
|
||||
B = B ^ liop
|
||||
elif inst == 3:
|
||||
if A != 0:
|
||||
ip = liop
|
||||
|
||||
# Infinite loop prevention
|
||||
# state = (ip, A, B, C)
|
||||
# # print(66, state, jumped)
|
||||
# if state in jumped:
|
||||
# print("Infinite loop!")
|
||||
# return False
|
||||
# jumped.add(state)
|
||||
|
||||
continue
|
||||
elif inst == 4:
|
||||
B = B ^ C
|
||||
else:
|
||||
coop = liop
|
||||
if liop == 4:
|
||||
coop = A
|
||||
elif liop == 5:
|
||||
coop = B
|
||||
elif liop == 6:
|
||||
coop = C
|
||||
|
||||
if inst == 2:
|
||||
B = coop % 8
|
||||
elif inst == 5:
|
||||
ou = coop % 8
|
||||
# output.append(ou)
|
||||
if oi >= len(program) or program[oi] != ou:
|
||||
# if len(output) >= 6:
|
||||
# print(84, oA, output)
|
||||
return False
|
||||
oi += 1
|
||||
else:
|
||||
trunc_div = A // 2**coop
|
||||
if inst == 0:
|
||||
A = trunc_div
|
||||
elif inst == 6:
|
||||
B = trunc_div
|
||||
elif inst == 7:
|
||||
C = trunc_div
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
ip += 2
|
||||
|
||||
|
||||
return oi == len(program)
|
||||
# return output == program
|
||||
|
||||
# print(program)
|
||||
# for i in range(0, len(program), 2):
|
||||
# inst = program[i]
|
||||
# liop = program[i + 1]
|
||||
# print(106, i, instnames[inst], liop)
|
||||
# print()
|
||||
#
|
||||
# print(test(100000000))
|
||||
|
||||
Amin = 2**(3*(len(program)-1))
|
||||
Amax = 2**(3*len(program))
|
||||
|
||||
for A in rich.progress.track(range(Amin, Amax+1)):
|
||||
if test(A):
|
||||
print(A)
|
||||
break
|
||||
A += 1
|
||||
|
||||
|
||||
# print(",".join([str(o) for o in output]))
|
83
2024/17/two_dfs.py
Normal file
83
2024/17/two_dfs.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
original_B = int(lines[1].split(":")[1])
|
||||
original_C = int(lines[2].split(":")[1])
|
||||
program = [int(p) for p in lines[4].split(":")[1].split(",")]
|
||||
|
||||
|
||||
def output_given_A(A: int) -> list[int]:
|
||||
instruction_pointer = 0
|
||||
B = original_B
|
||||
C = original_C
|
||||
|
||||
output: list[int] = list()
|
||||
|
||||
while instruction_pointer in range(len(program)):
|
||||
instruction = program[instruction_pointer]
|
||||
literal_operator = program[instruction_pointer + 1]
|
||||
|
||||
if instruction == 1:
|
||||
B = B ^ literal_operator
|
||||
elif instruction == 3:
|
||||
if A != 0:
|
||||
instruction_pointer = literal_operator
|
||||
continue
|
||||
elif instruction == 4:
|
||||
B = B ^ C
|
||||
else:
|
||||
combined_operator = literal_operator
|
||||
if literal_operator == 4:
|
||||
combined_operator = A
|
||||
elif literal_operator == 5:
|
||||
combined_operator = B
|
||||
elif literal_operator == 6:
|
||||
combined_operator = C
|
||||
|
||||
if instruction == 2:
|
||||
B = combined_operator % 8
|
||||
elif instruction == 5:
|
||||
output.append(combined_operator % 8)
|
||||
else:
|
||||
trunc_div = A >> combined_operator
|
||||
if instruction == 0:
|
||||
A = trunc_div
|
||||
elif instruction == 6:
|
||||
B = trunc_div
|
||||
else:
|
||||
C = trunc_div
|
||||
instruction_pointer += 2
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def input_to_a(input_numbers: list[int]) -> int:
|
||||
A = 0
|
||||
for number in reversed(input_numbers):
|
||||
A = (A << 3) + number
|
||||
return A
|
||||
|
||||
|
||||
def dig(depth: int, input_numbers: list[int]) -> int | None:
|
||||
input_numbers = input_numbers.copy()
|
||||
depth += 1
|
||||
for i in range(8):
|
||||
input_numbers[-depth] = i
|
||||
A = input_to_a(input_numbers)
|
||||
output_numbers = output_given_A(A)
|
||||
if output_numbers[-depth:] == program[-depth:]:
|
||||
if depth == len(program):
|
||||
return A
|
||||
res = dig(depth, input_numbers)
|
||||
if res is not None:
|
||||
return res
|
||||
return None
|
||||
|
||||
|
||||
print(dig(0, [0] * len(program)))
|
78
2024/17/two_fixed.py
Normal file
78
2024/17/two_fixed.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
original_B = int(lines[1].split(":")[1])
|
||||
original_C = int(lines[2].split(":")[1])
|
||||
program = [int(p) for p in lines[4].split(":")[1].split(",")]
|
||||
|
||||
|
||||
def output_given_A(A: int) -> list[int]:
|
||||
instruction_pointer = 0
|
||||
B = original_B
|
||||
C = original_C
|
||||
|
||||
output: list[int] = list()
|
||||
|
||||
while instruction_pointer in range(len(program)):
|
||||
instruction = program[instruction_pointer]
|
||||
literal_operator = program[instruction_pointer + 1]
|
||||
|
||||
if instruction == 1:
|
||||
B = B ^ literal_operator
|
||||
elif instruction == 3:
|
||||
if A != 0:
|
||||
instruction_pointer = literal_operator
|
||||
continue
|
||||
elif instruction == 4:
|
||||
B = B ^ C
|
||||
else:
|
||||
combined_operator = literal_operator
|
||||
if literal_operator == 4:
|
||||
combined_operator = A
|
||||
elif literal_operator == 5:
|
||||
combined_operator = B
|
||||
elif literal_operator == 6:
|
||||
combined_operator = C
|
||||
|
||||
if instruction == 2:
|
||||
B = combined_operator % 8
|
||||
elif instruction == 5:
|
||||
output.append(combined_operator % 8)
|
||||
else:
|
||||
trunc_div = A >> combined_operator
|
||||
if instruction == 0:
|
||||
A = trunc_div
|
||||
elif instruction == 6:
|
||||
B = trunc_div
|
||||
else:
|
||||
C = trunc_div
|
||||
instruction_pointer += 2
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def input_to_a(input_numbers: list[int]) -> int:
|
||||
A = 0
|
||||
for number in reversed(input_numbers):
|
||||
A = (A << 3) + number
|
||||
return A
|
||||
|
||||
|
||||
input_numbers: list[int] = program.copy()
|
||||
output_numbers: list[int] = output_given_A(input_to_a(input_numbers))
|
||||
while output_numbers != program:
|
||||
for i in reversed(range(len(input_numbers))):
|
||||
attempted_number = 0
|
||||
while len(output_numbers) != len(program) or output_numbers[i] != program[i]:
|
||||
input_numbers[i] = attempted_number
|
||||
A = input_to_a(input_numbers)
|
||||
output_numbers = output_given_A(A)
|
||||
attempted_number += 1
|
||||
|
||||
print(A)
|
Loading…
Add table
Add a link
Reference in a new issue