Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
Bytecode Analysis solution in Uncategorized category for Solution for Anything by PositronicLlama
"""General purpose solver."""
# Useful modules like ast, dis, opcode, inspect and traceback are disabled!
# I wonder why :)
# Bytecode constant offsets
CMP_OFFSET = 7
REFERENCE_OFFSET = 3
REFERENCE_INFO_OFFSET = 4
# Strategies necessary to produce valid operator outcomes.
EQUAL = 0
NOT_EQUAL = 1
LESS = 2
GREATER = 3
IN = 4
NOT_IN = 5
# COMPARE_OP arguments:
# [(0, '<'), (1, '<='), (2, '=='), (3, '!='), (4, '>'), (5, '>='), (6, 'in'),
# (7, 'not in'), (8, 'is'), (9, 'is not'), (10, 'exception match'), (11, 'BAD')]
OPERATORS = {
0: ('__lt__', LESS),
1: ('__le__', LESS),
2: ('__eq__', EQUAL),
3: ('__ne__', NOT_EQUAL),
4: ('__gt__', GREATER),
5: ('__ge__', GREATER),
6: ('__contains__', IN),
7: (None, NOT_IN),
8: (None, EQUAL),
9: (None, NOT_EQUAL),
}
def get_frame(depth):
"""Get the frame at the given depth from the current function."""
try:
# The traceback module is disallowed, so use an exception to get one.
raise RuntimeError("Ping!")
except Exception as e:
tb = e.__traceback__
frame = tb.tb_frame
for i in range(depth + 1):
frame = frame.f_back
return frame
def load_global(f, index):
"""Load a global from the given frame and index."""
return f.f_globals[f.f_code.co_names[index]]
def load_const(f, index):
"""Load a const from the given frame and index."""
return f.f_code.co_consts[index]
def load_local_fast(f, index):
"""Load a global from the given frame and index."""
return f.f_locals[f.f_code.co_varnames[index]]
def load_name(f, index):
"""Load a global from the given frame and index."""
name = f.f_code.co_names[index]
if name in f.f_locals:
return f.f_locals[name]
elif name in f.f_globals:
return f.f_globals[name]
return f.f_builtins[name]
def build_list(f, size):
"""Return a new list of the given size."""
assert size == 0, "Only lists of size zero are currently supported."
return [None] * size
# A mapping from load opcode to a function that can extract the relevant object.
REF_FUNCTIONS = {
100: load_const,
103: build_list,
116: load_global,
101: load_name,
124: load_local_fast,
}
def gen_number(reference, strategy, op_key):
"""
Get a number that compares True relative to reference for an operator
that is compatible with the given strategy.
"""
if strategy == LESS:
return reference - 1
elif strategy == GREATER:
return reference + 1
def gen_string(reference, strategy, op_key):
"""
Get a string that compares True relative to reference for an operator
that is compatible with the given strategy.
"""
if strategy == LESS:
# Can't be less than ''
if len(reference) == 0:
return gen_default(reference, op, op_key)
last = ord(reference[-1])
if last > 1:
return reference[:-1] + chr(last - 1)
return reference[:-1]
elif strategy == GREATER:
last = ord(reference[-1])
if last < 255:
return reference[:-1] + chr(last + 1)
return reference + ' '
def gen_default(reference, strategy, op_key):
"""
Get an object that compares True relative to reference for an operator
that is compatible with the given strategy.
"""
class Answer:
"""Answer to this specific problem only."""
def __init__(self, ref_obj):
self.ref_obj = ref_obj
def eq_reference(self, other):
return self.ref_obj == other
def __eq__(self, other):
return False
__ne__ = __gt__ = __ge__ = __lt__ = __le__ = __eq__
setattr(Answer, op_key, Answer.eq_reference)
return Answer(reference)
# Functions that generate successors or predecessors for objects of a given type.
GEN_FUNCTIONS = {
int: gen_number,
str: gen_string
}
def checkio(anything):
"""Actually return a genuine value that passes the unit test."""
# Get the parent frame, instruction pointer and bytecode
f = get_frame(1)
i = f.f_lasti
bytecode = f.f_code.co_code
#print([b for b in bytecode[i:i + 18]])
# Note: This makes some pretty risky assumptions about the layout of the
# calling code. This is basically only compatible with calls of the form:
# assert checkio(x) <> y, 'What?'
# First, determine the reference object
ref_op = bytecode[i + REFERENCE_OFFSET]
ref_info = bytecode[i + REFERENCE_INFO_OFFSET]
ref_value = REF_FUNCTIONS[ref_op](f, ref_info)
# Next, determine the operator that the calling code uses to compare
# the result of this function with the reference object.
cmp = bytecode[i + CMP_OFFSET]
op_key, strategy = OPERATORS[cmp]
# Handle easy cases of ==, !=, in and not in.
if strategy == EQUAL:
return ref_value
elif strategy == NOT_EQUAL or strategy == NOT_IN:
return object()
elif strategy == IN:
return next(iter(ref_value))
# Generate objects that compare less than or greater than the reference.
gen_fn = GEN_FUNCTIONS.get(type(ref_value), gen_default)
answer = gen_fn(ref_value, strategy, op_key)
return answer
if __name__ == '__main__':
import re, math
arr = [5, 6, 7]
assert checkio({}) != [] , 'You'
assert checkio('Hello') < 'World', 'will'
assert checkio(80) > 81, 'never'
assert checkio(re) >= re, 'make'
assert checkio(re) <= math, 'this'
assert checkio(5) == ord, ':)'
assert checkio(ord) is chr, '|:o()'
assert checkio(99) in arr, ';}'
print('NO WAY :(')
Jan. 10, 2013
Comments: