Created
November 19, 2014 13:33
-
-
Save kennytm/9b884f187fe7621431b8 to your computer and use it in GitHub Desktop.
ADJUST working environment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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