ADJUST working environment
#!/usr/bin/env python3 | |
def factorize(num): | |
while num % 2 == 0: | |
yield 2 | |
num //= 2 | |
prime = 3 | |
while prime * prime <= num: | |
while num % prime == 0: | |
yield prime | |
num //= prime | |
prime += 2 | |
if num != 1: | |
yield num | |
class ExitProgram(Exception): | |
pass | |
class Field(object): | |
def __init__(self): | |
self._field = {} | |
self._cursor = (0, 0) | |
self._direction = 3 | |
self._acc = 0 | |
self._stack1 = [] | |
self._stack2 = [] | |
def _move_forward(self, steps): | |
(x, y) = self._cursor | |
if 1 <= self._direction <= 3: | |
y -= steps | |
if 3 <= self._direction <= 5: | |
x += steps | |
if 5 <= self._direction <= 7: | |
y += steps | |
if self._direction in {0, 1, 7}: | |
x -= steps | |
self._cursor = (x, y) | |
def _turn_left(self, steps): | |
self._turn_right(-steps) | |
def _turn_right(self, steps): | |
new_direction = self._direction + steps | |
if new_direction < 0: | |
raise ValueError("Encountered Bug in official ADJUST interpreter (-ve dir)") | |
self._direction = new_direction % 8 | |
def _lighter_stack(self): | |
if not self._stack1: | |
if self._stack2: | |
return self._stack1 | |
else: | |
return None | |
elif not self._stack2: | |
return self._stack2 | |
top1 = self._stack1[-1] | |
top2 = self._stack2[-1] | |
if top1 < top2: | |
return self._stack1 | |
elif top1 > top2: | |
return self._stack2 | |
else: | |
return None | |
def _heavier_stack(self): | |
lighter_stack = self._lighter_stack() | |
if lighter_stack is self._stack1: | |
return self._stack2 | |
elif lighter_stack is self._stack2: | |
return self._stack1 | |
else: | |
return None | |
def _perform_2(self): | |
self._acc = (self._acc >> 3 | self._acc << 5) & 0xff | |
def _perform_3(self): | |
stack = self._lighter_stack() | |
if stack is None: | |
stack = self._stack1 | |
self._turn_right(1) | |
elif stack is self._stack1: | |
if self._acc: | |
self._turn_left(2) | |
else: | |
self._turn_right(3) | |
elif stack is self._stack2: | |
self._turn_left(1) | |
stack.append(self._acc) | |
self._move_forward(1) | |
def _perform_5(self): | |
self._acc ^= 1 | |
def _perform_7(self): | |
self._move_forward(bin(self._acc).count('1')) | |
def _perform_11(self): | |
stack = self._heavier_stack() or self._stack2 | |
try: | |
self._acc = stack.pop() | |
except IndexError: | |
self._acc = 0 | |
def _perform_13(self): | |
try: | |
print(chr(self._stack2.pop()), end='') | |
except IndexError: | |
print('***stack2 is empty!***') | |
pass | |
def _perform_17(self): | |
raise NotImplementedError("Prime factor 17 is not supported.") | |
def _perform_19(self): | |
try: | |
ch = self._stack2.pop() | |
self._stack1.append(ch) | |
except IndexError: | |
if self._acc & 4: | |
self._turn_right(2) | |
self._move_forward(bin(self._acc & 0b10011000).count('1')) | |
def _perform_23(self): | |
self._acc = (self._acc << 5) & 0xff | |
def _perform_29(self): | |
if self._acc == 0: | |
self._turn_left(1) | |
self._move_forward(2) | |
if self._lighter_stack() is self._stack2: | |
self._move_forward(1) | |
self._turn_right(1) | |
def _perform_31(self): | |
self._move_forward(1) | |
def _perform_37(self): | |
lighter_stack = self._lighter_stack() | |
if lighter_stack: | |
heavier_stack = self._heavier_stack() | |
heavier_stack.append(lighter_stack[-1]) | |
def _perform_41(self): | |
heavier_stack = self._heavier_stack() | |
if heavier_stack: | |
heavier_stack.pop() | |
def _perform_43(self): | |
self._acc >>= 1 | |
if self._acc == 0: | |
self._move_forward(1) | |
self._turn_left(2) | |
def _perform_47(self): | |
lighter_stack = self._lighter_stack() | |
if lighter_stack: | |
self._acc = lighter_stack.pop() | |
def _perform_53(self): | |
def reverse_bits(n): | |
return int('{:04b}'.format(n)[::-1], 2) | |
if self._lighter_stack() is self._stack1: | |
self._acc = (self._acc & 0xf0) | reverse_bits(self._acc & 0xf) | |
else: | |
self._acc = (self._acc & 0xf) | reverse_bits(self._acc >> 4) << 4 | |
def _perform_59(self): | |
self._turn_right(bin(self._acc).count('1')) | |
def _perform_61(self): | |
(self._stack1, self._stack2) = (self._stack2, self._stack1) | |
def _perform_67(self): | |
raise ExitProgram() | |
def plot(self, char): | |
if self._cursor in self._field: | |
raise ValueError('{} is already occupied!', self._cursor) | |
self._field[self._cursor] = char | |
for factor in reversed(list(factorize(ord(char)))): | |
try: | |
method = getattr(self, '_perform_' + str(factor)) | |
except AttributeError: | |
self._acc = factor | |
continue | |
method() | |
self._move_forward(1) | |
def plot_string(self, string): | |
for char in string: | |
self.plot(char) | |
def print_field(self, target): | |
def compute_difference_internal(acc, target): | |
xor = acc ^ target | |
unshift_amount = 0 | |
while xor: | |
if xor & 1: | |
yield 5 | |
xor ^= 1 | |
if xor == 0: | |
yield from [2] * ((-unshift_amount) % 8) | |
else: | |
yield 2 | |
xor = (xor >> 3 | xor << 5) & 0xff | |
unshift_amount += 1 | |
def recommend_difference(acc, target): | |
def characters(m): | |
match = m.group() | |
fives = match.count('5') | |
twos = match.count('2') | |
return { | |
(1, 1): 'F', | |
(2, 1): '2', | |
(1, 4): 'P', | |
(0, 1): 'R', | |
(0, 2): 't', | |
(0, 3): '8', | |
}[(fives, twos)] | |
import re | |
string = ''.join(str(x) for x in compute_difference_internal(acc, target)) | |
return string + ' (' + re.sub('52|552|52222|2{1,3}', characters, string) + ')' | |
print() | |
min_x = min(c[0] for c in self._field.keys()) | |
min_y = min(c[1] for c in self._field.keys()) | |
max_x = max(c[0] for c in self._field.keys()) | |
max_y = max(c[1] for c in self._field.keys()) | |
for y in range(min_y, max_y+1): | |
for x in range(min_x, max_x+1): | |
ch = self._field.get((x, y), '`') | |
print(ch, end='') | |
print() | |
print('\ncurrent state:') | |
print(' acc = {0:3} ({0:08b})'.format(self._acc)) | |
print(' target = {0:3} ({0:08b})'.format(ord(target))) | |
print(' diff =', recommend_difference(self._acc, ord(target))) | |
print(' stack1 =', self._stack1) | |
print(' stack2 =', self._stack2) | |
print(' direct =', self._direction * 45) | |
# acc affecting commands: | |
# 2, 5, [11], -23-, 43, [47], [53], >67 | |
# direction affecting commands: | |
# 3, 19, 29, 43, -59- | |
# can use: | |
# 3, 7, 13, 19, 29, 31, 37, 41, -59-, 61 | |
field = Field() | |
try: | |
#0 " | |
field.plot_string('K8F8FKAnK') | |
#1 H | |
field.plot_string('RFF8RFKKA') | |
#2 o | |
field.plot_string('8FtFFKAnK') | |
#3 u | |
field.plot_string('RFFRFRFRKKA') | |
#4 s | |
field.plot_string('FtFtFRKKA') | |
#5 t | |
field.plot_string('8FtFRKKAKnnK') | |
#6 o | |
field.plot_string('FRFtFtKKA') | |
#7 n | |
field.plot_string('KKAnnKnK') | |
#8 , | |
field.plot_string('F8FFRFKKA') | |
#9 _ | |
field.plot_string('FF8RFRKKA') | |
#10 w | |
field.plot_string('tFFFRFRKKA') | |
#11 e | |
field.plot_string('FtFF8KAnK') | |
#12 _ | |
field.plot_string('RFFFRFFFKKA') | |
#13 h | |
field.plot_string('FFF8tKAnK') | |
#14 a | |
field.plot_string('FRF8FRKKA') | |
#15 v | |
field.plot_string('8FFRFRKKA') | |
#16 e | |
field.plot_string('8FF8KAnK') | |
#17 _ | |
field.plot_string('RFFFRFFRKKA') | |
#18 a | |
field.plot_string('tF8tKAnK') | |
#19 _ | |
field.plot_string('88FRKKA') | |
#20 p | |
field.plot_string('FRFRF8KKA') | |
#21 r | |
field.plot_string('FtF8RKKA') | |
#22 o | |
field.plot_string('RFtFRFRKKA') | |
#23 b | |
field.plot_string('RF8RFRKKA') | |
#24 l | |
field.plot_string('FFRFtFRKKA') | |
#25 e | |
field.plot_string('RF88KKA') | |
#26 m | |
field.plot_string('FF88KAnK') | |
#27 . | |
field.plot_string('8FRFRFKKA') | |
#28 " | |
field.plot_string('FF8RFRKKAKnnK') | |
#29 _ | |
field.plot_string('tF8FRKKA') | |
#30 - | |
field.plot_string('RF8RFRKKAKnnK') | |
#31 _ | |
field.plot_string('F8RFFRKKA') | |
#32 J | |
field.plot_string('FFFF8FKAnK') | |
#33 i | |
field.plot_string('FFF8FRKKA') | |
#34 m | |
field.plot_string('F8tFRKKA') | |
#35 _ | |
field.plot_string('RFF8FRKKA') | |
#36 L | |
field.plot_string('FFF8FFKAnK') | |
#37 o | |
field.plot_string('FFFF8RKKA') | |
#38 v | |
field.plot_string('RFtF8KKA') | |
#39 e | |
field.plot_string('8FF8KAnK') | |
#40 l | |
field.plot_string('8FRFtKKA') | |
#41 l | |
field.plot_string('iA') | |
#end. | |
field.plot_string('C') | |
except ExitProgram: | |
field.print_field('"Houston, we have a problem." - Jim Lovell'[40]) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment