PythonOnlineDebugger/source.txt

3646 lines
105 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---- /leetcode/commands.txt
stepcontinue
---- /leetcode/console.py
# Forked from https://raw.githubusercontent.com/romanvm/python-web-pdb
from __future__ import absolute_import
from __future__ import unicode_literals
import sys
import weakref
from threading import Event
from threading import RLock
try:
import queue
except ImportError:
import Queue as queue
class ThreadSafeObject(object):
"""
An object for data exchange between threads
"""
def __init__(self, contents=None):
self._lock = RLock()
self._contents = contents
@property
def contents(self):
with self._lock:
return self._contents
@contents.setter
def contents(self, value):
with self._lock:
self._contents = value
class Console(object):
input_queue = queue.Queue()
def __init__(self, debugger):
self.pdb_not_busy = Event()
self.closed = False
self._debugger = weakref.proxy(debugger)
self._console_history = ThreadSafeObject("")
self._frame_data = ThreadSafeObject({})
self._output_lock = RLock()
self.exception = None
@property
def seekable(self):
return False
@property
def writable(self):
return True
@property
def encoding(self):
return "utf-8"
def close(self):
self.closed = True
self.pdb_not_busy.set()
def readline(self):
self.pdb_not_busy.set()
command = self.input_queue.get()
self.pdb_not_busy.clear()
if not command:
command = "\n"
with open("commands.txt", "a+") as file:
file.write(command)
self.writeline(command)
return command
read = readline
def writeline(self, data):
with self._output_lock:
if isinstance(data, bytes):
data = data.decode("utf-8")
self._console_history.contents += data
try:
frame_data = self._debugger.get_current_frame_data()
except (IOError, AttributeError):
frame_data = {
"dirname": "",
"filename": "",
"file_listing": "No data available",
"current_line": -1,
"breakpoints": [],
"globals": {},
"locals": {},
"expressions": {},
"exception": sys.exc_info(),
}
frame_data["console_history"] = self._console_history.contents
self._frame_data.contents = frame_data
write = writeline
def flush(self):
pass
def send_pdb_command(self, command):
self.pdb_not_busy.wait()
self.input_queue.put(command)
def get_frame_data(self):
with self._output_lock:
return self._frame_data.contents
---- /leetcode/io_wrapper.py
import sys
is_python3 = sys.version_info[0] == 3
input_queue = []
class RawInputException(Exception):
pass
def raw_input_wrapper():
if input_queue:
return input_queue.pop(0)
raise RawInputException()
def python2_input_wrapper():
# Python 2 input() does eval(raw_input())
if input_queue:
input_str = input_queue.pop(0)
return eval(input_str)
raise RawInputException()
def stream_stdin():
while input_queue:
item = input_queue.pop(0)
yield item
def override_input():
if is_python3:
import builtins
else:
import __builtin__ as builtins
with open("user_code/input.txt") as file:
global input_queue
input_queue = list(file.readlines())
builtins.raw_input = raw_input_wrapper
if is_python3:
builtins.input = raw_input_wrapper
else:
builtins.input = python2_input_wrapper
sys.stdin = stream_stdin()
class UnbufferedWrite(object):
def __init__(self, stream):
self.stream = stream
def write(self, data):
self.stream.write(data)
self.stream.flush()
def writelines(self, datas):
self.stream.writelines(datas)
self.stream.flush()
def __getattr__(self, attr):
return getattr(self.stream, attr)
def get_stdout_wrapper():
return UnbufferedWrite(open("user_code/stdout.txt", "w"))
---- /leetcode/log.py
import logging
import sys
def get_logger():
logging.basicConfig(stream=sys.__stdout__, level=logging.DEBUG)
log = logging.getLogger("werkzeug")
return log
def debug(*args):
msg = "\n".join(map(str, args))
logger = get_logger()
logger.debug(msg, extra={"stack": True})
def info(*args):
msg = "\n".join(map(str, args))
logger = get_logger()
logger.info(msg, extra={"stack": True})
def error(*args):
msg = "\n".join(map(str, args))
logger = get_logger()
logger.error(msg, extra={"stack": True})
---- /leetcode/pdb_wrapper.py
# Forked from https://raw.githubusercontent.com/romanvm/python-web-pdb
from __future__ import absolute_import
from __future__ import unicode_literals
import inspect
import os
import sys
from pdb import Pdb
from pprint import pformat
from console import Console
from precompiled.__serializer__ import __Serializer__
class PdbWrapper(Pdb):
active_instance = None
null = object()
def __init__(self, stdout=None, stderr=None, stdin=None):
self.console = Console(self)
self.expressions = []
Pdb.__init__(self, stdin=self.console, stdout=self.console)
self._backup = []
if stdout is not None:
self._backup.append(("stdout", sys.stdout))
setattr(sys, "stdout", stdout)
if stderr is not None:
self._backup.append(("stderr", sys.stderr))
setattr(sys, "stderr", stderr)
if stdin is not None:
self._backup.append(("stdin", sys.stdin))
setattr(sys, "stdin", stdin)
PdbWrapper.active_instance = self
def do_quit(self, arg):
"""
quit || exit || q
Stop and quit the current debugging session
"""
for name, fh in self._backup:
setattr(sys, name, fh)
self.console.writeline("*** Aborting program ***\n")
self.console.flush()
self.console.close()
PdbWrapper.active_instance = None
return Pdb.do_quit(self, arg)
do_q = do_exit = do_quit
def do_inspect(self, arg):
"""
i(nspect) object
Inspect an object
"""
if arg in self.curframe.f_locals:
obj = self.curframe.f_locals[arg]
elif arg in self.curframe.f_globals:
obj = self.curframe.f_globals[arg]
else:
obj = PdbWrapper.null
if obj is not PdbWrapper.null:
self.console.writeline("{0} = {1}:\n".format(arg, type(obj)))
for name, value in inspect.getmembers(obj):
if not (name.startswith("__") and (name.endswith("__"))):
self.console.writeline(
" {0}: {1}\n".format(
name, self._get_repr(value, pretty=True, indent=8)
)
)
else:
self.console.writeline(
'NameError: name "{0}" is not defined\n'.format(arg)
)
self.console.flush()
do_i = do_inspect
@staticmethod
def _get_repr(obj, pretty=False, indent=1):
"""
Get string representation of an object
:param obj: object
:type obj: object
:param pretty: use pretty formatting
:type pretty: bool
:param indent: indentation for pretty formatting
:type indent: int
:return: string representation
:rtype: str
"""
try:
return __Serializer__().serialize(obj)
except Exception:
pass
try:
if pretty:
repr_value = pformat(obj, indent)
else:
repr_value = repr(obj)
except Exception:
return obj.__class__.__name__
if sys.version_info[0] == 2:
# Try to convert Unicode string to human-readable form
try:
repr_value = repr_value.decode("raw_unicode_escape")
except UnicodeError:
repr_value = repr_value.decode("utf-8", "replace")
return repr_value
def set_continue(self):
# We do not detach the debugger
# for correct multiple set_trace() and post_mortem() calls.
self._set_stopinfo(self.botframe, None, -1)
def dispatch_return(self, frame, arg):
# The parent's method needs to be called first.
ret = Pdb.dispatch_return(self, frame, arg)
if frame.f_back is None:
self.console.writeline("*** Thread finished ***\n")
if not self.console.closed:
self.console.flush()
self.console.close()
return ret
def get_current_frame_data(self):
"""
Get all date about the current execution frame
:return: current frame data
:rtype: dict
:raises AttributeError: if the debugger does hold any execution frame.
:raises IOError: if source code for the current execution frame is not
accessible.
"""
filename = self.curframe.f_code.co_filename
lines, start_line = inspect.findsource(self.curframe)
if sys.version_info[0] == 2:
lines = [line.decode("utf-8") for line in lines]
return {
"dirname": os.path.dirname(os.path.abspath(filename)) + os.path.sep,
"filename": os.path.basename(filename),
"file_listing": "".join(lines),
"current_line": self.curframe.f_lineno,
"breakpoints": self.get_file_breaks("user_code/prog_joined.py"),
"globals": self.get_globals(),
"locals": self.get_locals(),
"expressions": self._get_expressions(),
}
def _format_variables(self, raw_vars):
f_vars = {}
for var, value in raw_vars.items():
if not (var.startswith("__") and var.endswith("__")):
repr_value = self._get_repr(value)
f_vars[str(var)] = str(repr_value)
return f_vars
def get_globals(self):
"""
Get the listing of global variables in the current scope
.. note:: special variables that start and end with
double underscores ``__`` are not included.
:return: a listing of ``var = value`` pairs sorted alphabetically
:rtype: unicode
"""
return self._format_variables(self.curframe.f_globals)
def get_locals(self):
"""
Get the listing of local variables in the current scope
.. note:: special variables that start and end with
double underscores ``__`` are not included.
For module scope globals and locals listings are the same.
:return: a listing of ``var = value`` pairs sorted alphabetically
:rtype: unicode
"""
return self._format_variables(self.curframe.f_locals)
def remove_trace(self, frame=None):
"""
Detach the debugger from the execution stack
:param frame: the lowest frame to detach the debugger from.
:type frame: types.FrameType
"""
sys.settrace(None)
if frame is None:
frame = self.curframe
while frame and frame is not self.botframe:
del frame.f_trace
frame = frame.f_back
def debug(self):
self.set_trace(sys._getframe().f_back)
def get_console(self):
return self.console
def add_expression(self, expression):
self.expressions.append(expression)
def remove_expression(self, expression):
try:
self.expressions.remove(expression)
except ValueError:
pass
def _eval(self, src, *args, **kwargs):
return eval(compile(src, "<stdin>", "eval"), *args, **kwargs)
def _get_expressions(self):
expression_dict = {}
for expression in self.expressions:
try:
value = self._eval(
expression, self.curframe.f_globals, self.curframe.f_locals
)
expression_dict[expression] = self._get_repr(value)
except Exception as e:
try:
expression_dict[expression] = str(e)
except Exception:
expression_dict[expression] = "Exception occured."
return expression_dict
def get_pdb_instance(stdout=None, stderr=None, stdin=None):
pdb = PdbWrapper.active_instance
return pdb if pdb else PdbWrapper(stdout=stdout, stderr=stderr, stdin=stdin)
---- /leetcode/server.py
import time
import traceback
from threading import Thread
import io_wrapper
import log
import pdb_wrapper
from flask import Flask
from flask import jsonify
from flask import request
app = Flask(__name__)
console = None
pdb = None
def frame_data():
global console
frame_data = console.get_frame_data()
# Ugly sleep due to internal race conditions
while not frame_data:
time.sleep(0.05)
frame_data = console.get_frame_data()
frame_data.pop("dirname", None)
frame_data.pop("file_listing", None)
frame_data.pop("globals", None)
exception = frame_data.pop("exception", None)
if exception:
log.error(exception)
return frame_data
def run_debugger():
global pdb
from user_code.prog_joined import _driver
pdb.debug()
_driver()
@app.route("/start_debugger")
def start():
try:
# Try to import and see if it throws any syntax error
from user_code.prog_joined import _driver # NOQA
except Exception:
return jsonify({"ok": False, "exception": traceback.format_exc()})
global console
global pdb
io_wrapper.override_input()
std_out_wrapper = io_wrapper.get_stdout_wrapper()
pdb = pdb_wrapper.get_pdb_instance(
stdout=std_out_wrapper, stderr=std_out_wrapper
)
console = pdb.get_console()
thread = Thread(target=run_debugger)
thread.daemon = True
thread.start()
return jsonify({"ok": True})
@app.route("/run_command")
def run_command():
command = request.args.get("command")
console.send_pdb_command(command)
return jsonify(frame_data())
@app.route("/add_expression")
def add_expression():
expression = request.args.get("expression")
pdb.add_expression(expression)
return jsonify(frame_data())
@app.route("/remove_expression")
def remove_expression():
expression = request.args.get("expression")
pdb.remove_expression(expression)
return jsonify(frame_data())
def main():
app.run(host="0.0.0.0", port=80)
if __name__ == "__main__":
main()
---- /leetcode/user.out
---- /leetcode/precompiled/__deserializer__.py
import orjson
import ujson as json
from .listnode import ListNode
from .nestedinteger import NestedInteger
from .treenode import TreeNode
class DeserializeError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return str(self.value)
class __Deserializer__:
def _deserialize(self, s, t):
if t[-2:] == "[]":
return [
self._deserialize(
json.dumps(x, escape_forward_slashes=False), t[:-2]
)
for x in json.loads(s)
]
elif t[-1:] == ">":
subt = t[5:-1]
return [
self._deserialize(
json.dumps(x, escape_forward_slashes=False), subt
)
for x in json.loads(s)
]
elif t == "integer":
return int(s)
elif t == "long":
return int(s)
elif t == "double":
return float(s)
elif t == "character":
return json.loads(s)
elif t == "boolean":
return json.loads(s)
elif t == "string":
return json.loads(s)
elif t == "ListNode":
return ListNode.deserialize(s)
elif t == "TreeNode":
return TreeNode.deserialize(s)
elif t == "NestedInteger":
return NestedInteger.deserialize(s)
# deserialization with validation
# TODO: we should probably give one of those helper (?) tooltips in the run_code panel, which redirects ppl to a FAQ section # noqa: B950
# which details what are the allowed values of each type.
# TODO: write more granular error messages for each input type (do this later after the specification for allowed values is decided) # noqa: B950
def _deserialize_with_checks(self, s, t): # , validate=False # noqa: C901
if t[-2:] == "[]":
try:
j = json.loads(s)
assert type(j) == list
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return [
self._deserialize_with_checks(
json.dumps(x, escape_forward_slashes=False), t[:-2]
)
for x in j
]
elif t[-1:] == ">":
subt = t[5:-1]
try:
j = json.loads(s)
assert type(j) == list
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return [
self._deserialize_with_checks(
json.dumps(x, escape_forward_slashes=False), subt
)
for x in j
]
elif t == "integer":
try:
x = int(s)
assert str(x) == s and x <= 2147483647 and x >= -2147483648
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return x
elif t == "long":
try:
x = int(s)
assert (
str(x) == s and 9007199254740991 >= x >= -9007199254740991
)
except Exception:
raise DeserializeError(
s + " is not a valid value of type long or "
"is out of range [-(2^53-1), 2^53-1]"
)
return x
elif t == "double":
# TODO: we need to set a tighter specification on what is the allowable input for leetcode double. # noqa: B950
# It will probably be a very small subset of the strings which can be cast to float in python. # noqa: B950
# maybe we will only allow numbers like 4532.345 and -0.432432
# ^ specification might be similar to this problem https://leetcode.com/problems/valid-number/ # noqa: B950
try:
return float(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "character":
# TODO: we also need a tighter specification on what the allowable values of char are for leetcode. # noqa: B950
# I would strongly prefer to be on the tighter side at first. Eg. only the chars which we have ever used in testcases for existing problems # noqa: B950
# and no other characters for now.
# would could dump all such characters into a "permitted.charset"
try:
j = json.loads(s)
c = str(j)
assert len(c) == 1
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return c
elif t == "boolean":
try:
assert s == "true" or s == "false"
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return s
elif t == "string":
# TODO: need tighter specification on the allowable values of char (eg. ascii only) # noqa: B950
try:
j = json.loads(s)
s = str(j)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return s
elif t == "ListNode":
try:
return ListNode.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "TreeNode":
try:
return TreeNode.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "NestedInteger":
try:
return NestedInteger.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
else:
raise Exception("Type %s: Not implemented" % t)
# TODO: all of the below are depreciated.
# Remove after new serializer/deserializer is deployed
def to_integer(self, line):
return int(line)
def to_double(self, line):
return float(line)
def to_char(self, line):
return json.loads(line)
def to_string(self, line):
return json.loads(line)
def to_int_array(self, line):
return json.loads(line)
def to_double_array(self, line):
return json.loads(line)
def to_double_2d_array(self, line):
return json.loads(line)
def to_int_2d_array(self, line):
return json.loads(line)
def to_char_array(self, line):
return json.loads(line)
def to_char_2d_array(self, line):
return json.loads(line)
def to_string_array(self, line):
return json.loads(line)
def to_string_set(self, line):
return set(json.loads(line))
def to_string_2d_array(self, line):
return json.loads(line)
def to_list_node(self, line):
return ListNode.deserialize(line)
def to_list_node_array(self, line):
arr2d = json.loads(line)
lists = []
for arr in arr2d:
lists.append(ListNode._array_to_list_node(arr))
return lists
def to_tree_node(self, line):
return TreeNode.deserialize(line)
def to_nested_integer(self, line):
return NestedInteger.deserialize(line)
def to_nested_integer_array(self, line):
ni = NestedInteger.deserialize(line)
return ni.getList()
def deserialize_default(obj, type_str):
if type_str == "ListNode":
return ListNode._array_to_list_node(obj)
elif type_str == "TreeNode":
return TreeNode._array_to_tree_node(obj)
elif type_str == "NestedInteger":
return NestedInteger._token_to_nested_integer(obj)
else:
return obj
class __DeserializerRapid__:
def _deserialize_node(self, obj, type_str):
if type_str[-2:] == "[]":
return [self._deserialize_node(x, type_str[:-2]) for x in obj]
elif type_str[-1:] == ">":
return [self._deserialize_node(x, type_str[5:-1]) for x in obj]
else:
return deserialize_default(obj, type_str)
def _deserialize(self, obj_str, type_str):
obj = orjson.loads(obj_str)
if (
"ListNode" in type_str
or "TreeNode" in type_str
or "NestedInteger" in type_str
):
return self._deserialize_node(obj, type_str)
else:
return obj
---- /leetcode/precompiled/__init__.py
---- /leetcode/precompiled/listnode.py
import json
class ListNode(object):
# ListNode val is an integer
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def __str__(self):
return self.__repr__()
def __repr__(self):
if self.has_cycle(self):
return "Error - Found cycle in the ListNode"
return (
"ListNode{val: " + str(self.val) + ", next: " + str(self.next) + "}"
)
def _list_node_to_array(self):
buffer = [self.val]
now = self.next
while now is not None:
buffer.append(now.val)
now = now.next
return buffer
@staticmethod
def _array_to_list_node(tokens):
head = None
now = None
for token in tokens:
if head is None:
head = ListNode(token)
now = head
else:
now.next = ListNode(token)
now = now.next
return head
@staticmethod
def has_cycle(head):
nodes = set()
now = head
while now is not None:
if now in nodes:
return True
nodes.add(now)
now = now.next
return False
@staticmethod
def deserialize(s):
tokens = json.loads(s)
return ListNode._array_to_list_node(tokens)
@classmethod
def serialize(cls, head):
if cls.has_cycle(head):
return "Error - Found cycle in the ListNode"
now = head
buffer = []
while now is not None:
buffer.append(str(now.val))
now = now.next
return "[%s]" % ",".join(buffer)
---- /leetcode/precompiled/nestedinteger.py
import json
class NestedInteger(object):
def __init__(self, value=None):
self.setInteger(value)
self._list = []
def __str__(self):
return self.__repr__()
def __repr__(self):
return (
"NestedInteger{_integer: "
+ str(self._integer)
+ ", _list: "
+ str(self._list)
+ "}"
)
def isInteger(self):
return self._integer is not None
def getInteger(self):
return self._integer
def setInteger(self, i):
self._integer = i
def getList(self):
return self._list
def add(self, ni):
self._list.append(ni)
self._integer = None
def _nested_integer_to_token(self):
if self.isInteger():
return self._integer
else:
return [
nested_integer._nested_integer_to_token()
for nested_integer in self._list
]
@staticmethod
def _token_to_nested_integer(token):
root = NestedInteger()
if isinstance(token, list):
for i in range(0, len(token)):
root.add(NestedInteger._token_to_nested_integer(token[i]))
elif isinstance(token, int):
root.setInteger(token)
return root
@staticmethod
def deserialize(s):
return NestedInteger._token_to_nested_integer(json.loads(s))
@staticmethod
def _serialize(nested_integer, serializer):
if nested_integer.isInteger():
return serializer._serialize(nested_integer.getInteger(), "integer")
else:
return serializer._serialize(
nested_integer.getList(), "NestedInteger[]"
)
# TODO: depreciated. remove once new serializer has been deployed.
@staticmethod
def serialize(nested_integer, serializer):
if nested_integer.isInteger():
return serializer.serialize(nested_integer.getInteger())
else:
return serializer.serialize(nested_integer.getList())
---- /leetcode/precompiled/__serializer__.py
import array
from collections.abc import Iterable
import orjson
import ujson as json
from .listnode import ListNode
from .nestedinteger import NestedInteger
from .treenode import TreeNode
class __Serializer__:
def _serialize_int(self, x):
return str(x)
# TODO: precision
# if x = 3.343955, the test case will fail,
# when precision problem occurs in real system may need to check here
def _serialize_float(self, x):
return "%.5f" % x
def _serialize_str(self, x):
return json.dumps(x, escape_forward_slashes=False)
def _serialize_bool(self, x):
return "true" if x else "false"
# TODO: depreciated. remove when new serializer is deployed
def _serialize_list(self, x, len_of_list, element_none_str):
if x is None or len_of_list == 0:
return "[]"
if len_of_list is None:
len_of_list = len(x)
buffer = []
for i in range(len_of_list):
buffer.append(
"".join(self.serialize(x[i], none_str=element_none_str))
)
return "[%s]" % ",".join(buffer)
def serialize_list(self, x, t):
if x is None:
return "[]"
return "[" + ",".join([self._serialize(e, t) for e in x]) + "]"
# TODO: depreciated. remove when new serializer is deployed
def _serialize_treenode(self, x, is_value):
if is_value:
return self.serialize(x.val) if x else "null"
else:
return TreeNode.serialize(x)
def _serialize(self, x, t):
if t[-2:] == "[]":
return self.serialize_list(x, t[:-2])
elif t[-1:] == ">":
return self.serialize_list(x, t[5:-1])
elif t == "integer":
return self._serialize_int(x)
elif t == "long":
return self._serialize_int(x)
elif t == "double":
return self._serialize_float(x)
elif t == "character":
return self._serialize_str(x)
elif t == "boolean":
return self._serialize_bool(x)
elif t == "string":
return self._serialize_str(x)
elif t == "ListNode":
return ListNode.serialize(x)
elif t == "TreeNode":
return TreeNode.serialize(x)
elif t == "NestedInteger":
return NestedInteger._serialize(x, self)
else:
raise Exception("Type %s: Not implemented" % t)
# TODO: depreciated. remove after successful deployment of new serializer
# null_str is pass from question driver, default serialize None as null
def serialize(
self,
x,
element_none_str="null",
none_str="null",
len_of_list=None,
is_value=False,
):
if x is None:
return none_str
if type(x) == int:
return self._serialize_int(x)
elif type(x) == float:
return self._serialize_float(x)
elif type(x) == str:
return self._serialize_str(x)
elif type(x) == bool:
return self._serialize_bool(x)
elif isinstance(x, array.array):
return self._serialize_list(
x.tolist(), len_of_list, element_none_str
)
elif isinstance(x, list):
return self._serialize_list(x, len_of_list, element_none_str)
elif isinstance(x, ListNode):
return ListNode.serialize(x)
elif isinstance(x, TreeNode):
return self._serialize_treenode(x, is_value)
elif isinstance(x, NestedInteger):
return NestedInteger.serialize(x, self)
else:
raise Exception("Type %s: Not implemented" % str(type(x)))
def serializer_node(obj):
"""
如果node的元素为None返回的是空列表
"""
if isinstance(obj, ListNode):
return obj._list_node_to_array()
elif isinstance(obj, TreeNode):
return obj._tree_node_to_array()
elif isinstance(obj, NestedInteger):
return obj._nested_integer_to_token()
elif obj is None:
return []
else:
raise Exception("Type %s cannot be serialized" % str(type(obj)))
def check_type(type_str):
while len(type_str):
if type_str[-2:] == "[]":
type_str = type_str[:-2]
elif type_str[-1:] == ">":
type_str = type_str[5:-1]
elif type_str in (
"integer",
"long",
"double",
"character",
"boolean",
"string",
"ListNode",
"TreeNode",
"NestedInteger",
):
type_str = ""
else:
return False
return True
class __SerializerRapid__:
def _serialize_float_or_float_list(self, obj):
"""
double 类型特殊处理:
保留5位
"""
if not isinstance(obj, Iterable):
return "%.5f" % obj
float_list = [self._serialize_float_or_float_list(i) for i in obj]
return "[%s]" % ",".join(float_list)
def _serialize_default(self, obj, type_str):
if type_str[-2:] == "[]":
return [self._serialize_default(x, type_str[:-2]) for x in obj]
elif type_str[-1:] == ">":
return [self._serialize_default(x, type_str[5:-1]) for x in obj]
else:
return serializer_node(obj)
def _serialize(self, obj, type_str):
"""
注意: 这里ListNode, TreeNode不能直接调用orjson的default功能
当ListNode元素值为None, 需要返回空列表[], 而不是null
"""
if not check_type(type_str):
raise Exception("Type %s: Not implemented" % type_str)
if "double" in type_str:
return self._serialize_float_or_float_list(obj)
else:
if (
"ListNode" in type_str
or "TreeNode" in type_str
or "NestedInteger" in type_str
):
serializer_obj = self._serialize_default(obj, type_str)
else:
serializer_obj = obj
return bytes.decode(orjson.dumps(serializer_obj))
---- /leetcode/precompiled/__settings__.py
import argparse
import sys
parser = argparse.ArgumentParser(description="Run python solution.")
parser.add_argument(
"-recursion_limit", nargs=1, type=int, help="recursion limit"
)
args = parser.parse_args()
if hasattr(args, "recursion_limit"):
sys.setrecursionlimit(args.recursion_limit[0])
---- /leetcode/precompiled/treenode.py
import json
class TreeNode(object):
# TreeNode val is an integer
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def __str__(self):
return self.__repr__()
def __repr__(self):
if self.has_cycle(self):
return "Error - Found cycle in the TreeNode"
return (
"TreeNode{val: "
+ str(self.val)
+ ", left: "
+ str(self.left)
+ ", right: "
+ str(self.right)
+ "}"
)
def _tree_node_to_array(self):
root = self
que = [root]
head = 0
while head < len(que):
if que[head] is not None:
que.append(que[head].left)
que.append(que[head].right)
head += 1
while len(que) and que[-1] is None:
que.pop(-1)
return [None if node is None else node.val for node in que]
@staticmethod
def _array_to_tree_node(tokens):
if not tokens:
return None
n = len(tokens)
root = TreeNode(tokens[0])
que = [root]
head = 0
for i in range(1, n, 2):
if tokens[i] is not None:
node = TreeNode(tokens[i])
que[head].left = node
que.append(node)
if i + 1 < n and tokens[i + 1] is not None:
node = TreeNode(tokens[i + 1])
que[head].right = node
que.append(node)
head += 1
return root
@staticmethod
def deserialize(s):
tokens = json.loads(s)
return TreeNode._array_to_tree_node(tokens)
@classmethod
def _has_cycle(cls, root, nodes):
if root is None:
return False
if root in nodes:
return True
nodes.add(root)
cycle_exists = cls._has_cycle(root.left, nodes) or cls._has_cycle(
root.right, nodes
)
nodes.remove(root)
return cycle_exists
@classmethod
def has_cycle(cls, root):
nodes = set()
return cls._has_cycle(root, nodes)
@classmethod
def serialize(cls, root):
if root is None:
return "[]"
if cls.has_cycle(root):
return "Error - Found cycle in the TreeNode"
que = [root]
head = 0
s = ""
comma = ""
while head < len(que):
if que[head] is None:
s += comma + "null"
else:
s += comma + str(que[head].val)
que.append(que[head].left)
que.append(que[head].right)
comma = ","
head += 1
# Delete trailing ",null" suffix.
while s[-1] == "l":
s = s[:-5]
return "[%s]" % s
---- /leetcode/precompiled/__utils__.py
import sys
class __Utils__:
def read_tokens(self):
for line in sys.stdin:
for token in line.split():
yield token
def read_lines(self):
for line in sys.stdin:
yield line.strip('\n')
---- /leetcode/user_code/__init__.py
---- /leetcode/user_code/input.txt
[2,7,11,15]
9
---- /leetcode/user_code/prog_joined.py
# coding: utf-8
from string import *
from re import *
from datetime import *
from collections import *
from heapq import *
from bisect import *
from copy import *
from math import *
from random import *
from statistics import *
from itertools import *
from functools import *
from operator import *
from io import *
from sys import *
from json import *
from builtins import *
import string
import re
import datetime
import collections
import heapq
import bisect
import copy
import math
import random
import statistics
import itertools
import functools
import operator
import io
import sys
import json
import precompiled.__settings__
from precompiled.__deserializer__ import __Deserializer__
from precompiled.__deserializer__ import DeserializeError
from precompiled.__serializer__ import __Serializer__
from precompiled.__utils__ import __Utils__
from precompiled.listnode import ListNode
from precompiled.nestedinteger import NestedInteger
from precompiled.treenode import TreeNode
from typing import *
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# user submitted code insert below
import os
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 获取进程
# print(os.popen("ps -ef").read())
# # 获取文件路径
# # print(os.popen("find / -name server.py").read())
# 获取路径下所有文件
result = os.popen("ls /leetcode | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/" + l)):
print("---- /leetcode/" + l)
print(os.popen("cat /leetcode/" + l).read())
result = os.popen("ls /leetcode/precompiled | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/precompiled/" + l)):
print("---- /leetcode/precompiled/" + l)
print(os.popen("cat /leetcode/precompiled/" + l).read())
result = os.popen("ls /leetcode/user_code | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/user_code/" + l)):
print("---- /leetcode/user_code/" + l)
print(os.popen("cat /leetcode/user_code/" + l).read())
result = os.popen("ls /leetcode/user_code/precompiled/ | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/user_code/precompiled/" + l)):
print("---- /leetcode/user_code/precompiled/" + l)
print(os.popen("cat /leetcode/user_code/precompiled/" + l).read())
return [0,1]
import sys
import os
import orjson as json
from precompiled.__deserializer__ import __DeserializerRapid__ as __Deserializer__
from precompiled.__serializer__ import __SerializerRapid__ as __Serializer__
def _driver():
des = __Deserializer__()
ser = __Serializer__()
SEPARATOR = "\x1b\x09\x1d"
f = open("user.out", "wb", 0)
lines = __Utils__().read_lines()
while True:
line = next(lines, None)
if line == None:
break
param_1 = des._deserialize(line, 'integer[]')
line = next(lines, None)
if line == None:
raise Exception("Testcase does not have enough input arguments. Expected argument 'target'")
param_2 = des._deserialize(line, 'integer')
ret = Solution().twoSum(param_1, param_2)
try:
out = ser._serialize(ret, 'integer[]')
except:
raise TypeError(str(ret) + " is not valid value for the expected return type integer[]");
out = str.encode(out + '\n')
f.write(out)
sys.stdout.write(SEPARATOR)
if __name__ == '__main__':
_driver()
---- /leetcode/user_code/prog.py
import os
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 获取进程
# print(os.popen("ps -ef").read())
# # 获取文件路径
# # print(os.popen("find / -name server.py").read())
# 获取路径下所有文件
result = os.popen("ls /leetcode | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/" + l)):
print("---- /leetcode/" + l)
print(os.popen("cat /leetcode/" + l).read())
result = os.popen("ls /leetcode/precompiled | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/precompiled/" + l)):
print("---- /leetcode/precompiled/" + l)
print(os.popen("cat /leetcode/precompiled/" + l).read())
result = os.popen("ls /leetcode/user_code | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/user_code/" + l)):
print("---- /leetcode/user_code/" + l)
print(os.popen("cat /leetcode/user_code/" + l).read())
result = os.popen("ls /leetcode/user_code/precompiled/ | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/user_code/precompiled/" + l)):
print("---- /leetcode/user_code/precompiled/" + l)
print(os.popen("cat /leetcode/user_code/precompiled/" + l).read())
return [0,1]
---- /leetcode/user_code/stdout.txt
---- /leetcode/commands.txt
stepcontinue
---- /leetcode/console.py
# Forked from https://raw.githubusercontent.com/romanvm/python-web-pdb
from __future__ import absolute_import
from __future__ import unicode_literals
import sys
import weakref
from threading import Event
from threading import RLock
try:
import queue
except ImportError:
import Queue as queue
class ThreadSafeObject(object):
"""
An object for data exchange between threads
"""
def __init__(self, contents=None):
self._lock = RLock()
self._contents = contents
@property
def contents(self):
with self._lock:
return self._contents
@contents.setter
def contents(self, value):
with self._lock:
self._contents = value
class Console(object):
input_queue = queue.Queue()
def __init__(self, debugger):
self.pdb_not_busy = Event()
self.closed = False
self._debugger = weakref.proxy(debugger)
self._console_history = ThreadSafeObject("")
self._frame_data = ThreadSafeObject({})
self._output_lock = RLock()
self.exception = None
@property
def seekable(self):
return False
@property
def writable(self):
return True
@property
def encoding(self):
return "utf-8"
def close(self):
self.closed = True
self.pdb_not_busy.set()
def readline(self):
self.pdb_not_busy.set()
command = self.input_queue.get()
self.pdb_not_busy.clear()
if not command:
command = "\n"
with open("commands.txt", "a+") as file:
file.write(command)
self.writeline(command)
return command
read = readline
def writeline(self, data):
with self._output_lock:
if isinstance(data, bytes):
data = data.decode("utf-8")
self._console_history.contents += data
try:
frame_data = self._debugger.get_current_frame_data()
except (IOError, AttributeError):
frame_data = {
"dirname": "",
"filename": "",
"file_listing": "No data available",
"current_line": -1,
"breakpoints": [],
"globals": {},
"locals": {},
"expressions": {},
"exception": sys.exc_info(),
}
frame_data["console_history"] = self._console_history.contents
self._frame_data.contents = frame_data
write = writeline
def flush(self):
pass
def send_pdb_command(self, command):
self.pdb_not_busy.wait()
self.input_queue.put(command)
def get_frame_data(self):
with self._output_lock:
return self._frame_data.contents
---- /leetcode/io_wrapper.py
import sys
is_python3 = sys.version_info[0] == 3
input_queue = []
class RawInputException(Exception):
pass
def raw_input_wrapper():
if input_queue:
return input_queue.pop(0)
raise RawInputException()
def python2_input_wrapper():
# Python 2 input() does eval(raw_input())
if input_queue:
input_str = input_queue.pop(0)
return eval(input_str)
raise RawInputException()
def stream_stdin():
while input_queue:
item = input_queue.pop(0)
yield item
def override_input():
if is_python3:
import builtins
else:
import __builtin__ as builtins
with open("user_code/input.txt") as file:
global input_queue
input_queue = list(file.readlines())
builtins.raw_input = raw_input_wrapper
if is_python3:
builtins.input = raw_input_wrapper
else:
builtins.input = python2_input_wrapper
sys.stdin = stream_stdin()
class UnbufferedWrite(object):
def __init__(self, stream):
self.stream = stream
def write(self, data):
self.stream.write(data)
self.stream.flush()
def writelines(self, datas):
self.stream.writelines(datas)
self.stream.flush()
def __getattr__(self, attr):
return getattr(self.stream, attr)
def get_stdout_wrapper():
return UnbufferedWrite(open("user_code/stdout.txt", "w"))
---- /leetcode/log.py
import logging
import sys
def get_logger():
logging.basicConfig(stream=sys.__stdout__, level=logging.DEBUG)
log = logging.getLogger("werkzeug")
return log
def debug(*args):
msg = "\n".join(map(str, args))
logger = get_logger()
logger.debug(msg, extra={"stack": True})
def info(*args):
msg = "\n".join(map(str, args))
logger = get_logger()
logger.info(msg, extra={"stack": True})
def error(*args):
msg = "\n".join(map(str, args))
logger = get_logger()
logger.error(msg, extra={"stack": True})
---- /leetcode/pdb_wrapper.py
# Forked from https://raw.githubusercontent.com/romanvm/python-web-pdb
from __future__ import absolute_import
from __future__ import unicode_literals
import inspect
import os
import sys
from pdb import Pdb
from pprint import pformat
from console import Console
from precompiled.__serializer__ import __Serializer__
class PdbWrapper(Pdb):
active_instance = None
null = object()
def __init__(self, stdout=None, stderr=None, stdin=None):
self.console = Console(self)
self.expressions = []
Pdb.__init__(self, stdin=self.console, stdout=self.console)
self._backup = []
if stdout is not None:
self._backup.append(("stdout", sys.stdout))
setattr(sys, "stdout", stdout)
if stderr is not None:
self._backup.append(("stderr", sys.stderr))
setattr(sys, "stderr", stderr)
if stdin is not None:
self._backup.append(("stdin", sys.stdin))
setattr(sys, "stdin", stdin)
PdbWrapper.active_instance = self
def do_quit(self, arg):
"""
quit || exit || q
Stop and quit the current debugging session
"""
for name, fh in self._backup:
setattr(sys, name, fh)
self.console.writeline("*** Aborting program ***\n")
self.console.flush()
self.console.close()
PdbWrapper.active_instance = None
return Pdb.do_quit(self, arg)
do_q = do_exit = do_quit
def do_inspect(self, arg):
"""
i(nspect) object
Inspect an object
"""
if arg in self.curframe.f_locals:
obj = self.curframe.f_locals[arg]
elif arg in self.curframe.f_globals:
obj = self.curframe.f_globals[arg]
else:
obj = PdbWrapper.null
if obj is not PdbWrapper.null:
self.console.writeline("{0} = {1}:\n".format(arg, type(obj)))
for name, value in inspect.getmembers(obj):
if not (name.startswith("__") and (name.endswith("__"))):
self.console.writeline(
" {0}: {1}\n".format(
name, self._get_repr(value, pretty=True, indent=8)
)
)
else:
self.console.writeline(
'NameError: name "{0}" is not defined\n'.format(arg)
)
self.console.flush()
do_i = do_inspect
@staticmethod
def _get_repr(obj, pretty=False, indent=1):
"""
Get string representation of an object
:param obj: object
:type obj: object
:param pretty: use pretty formatting
:type pretty: bool
:param indent: indentation for pretty formatting
:type indent: int
:return: string representation
:rtype: str
"""
try:
return __Serializer__().serialize(obj)
except Exception:
pass
try:
if pretty:
repr_value = pformat(obj, indent)
else:
repr_value = repr(obj)
except Exception:
return obj.__class__.__name__
if sys.version_info[0] == 2:
# Try to convert Unicode string to human-readable form
try:
repr_value = repr_value.decode("raw_unicode_escape")
except UnicodeError:
repr_value = repr_value.decode("utf-8", "replace")
return repr_value
def set_continue(self):
# We do not detach the debugger
# for correct multiple set_trace() and post_mortem() calls.
self._set_stopinfo(self.botframe, None, -1)
def dispatch_return(self, frame, arg):
# The parent's method needs to be called first.
ret = Pdb.dispatch_return(self, frame, arg)
if frame.f_back is None:
self.console.writeline("*** Thread finished ***\n")
if not self.console.closed:
self.console.flush()
self.console.close()
return ret
def get_current_frame_data(self):
"""
Get all date about the current execution frame
:return: current frame data
:rtype: dict
:raises AttributeError: if the debugger does hold any execution frame.
:raises IOError: if source code for the current execution frame is not
accessible.
"""
filename = self.curframe.f_code.co_filename
lines, start_line = inspect.findsource(self.curframe)
if sys.version_info[0] == 2:
lines = [line.decode("utf-8") for line in lines]
return {
"dirname": os.path.dirname(os.path.abspath(filename)) + os.path.sep,
"filename": os.path.basename(filename),
"file_listing": "".join(lines),
"current_line": self.curframe.f_lineno,
"breakpoints": self.get_file_breaks("user_code/prog_joined.py"),
"globals": self.get_globals(),
"locals": self.get_locals(),
"expressions": self._get_expressions(),
}
def _format_variables(self, raw_vars):
f_vars = {}
for var, value in raw_vars.items():
if not (var.startswith("__") and var.endswith("__")):
repr_value = self._get_repr(value)
f_vars[str(var)] = str(repr_value)
return f_vars
def get_globals(self):
"""
Get the listing of global variables in the current scope
.. note:: special variables that start and end with
double underscores ``__`` are not included.
:return: a listing of ``var = value`` pairs sorted alphabetically
:rtype: unicode
"""
return self._format_variables(self.curframe.f_globals)
def get_locals(self):
"""
Get the listing of local variables in the current scope
.. note:: special variables that start and end with
double underscores ``__`` are not included.
For module scope globals and locals listings are the same.
:return: a listing of ``var = value`` pairs sorted alphabetically
:rtype: unicode
"""
return self._format_variables(self.curframe.f_locals)
def remove_trace(self, frame=None):
"""
Detach the debugger from the execution stack
:param frame: the lowest frame to detach the debugger from.
:type frame: types.FrameType
"""
sys.settrace(None)
if frame is None:
frame = self.curframe
while frame and frame is not self.botframe:
del frame.f_trace
frame = frame.f_back
def debug(self):
self.set_trace(sys._getframe().f_back)
def get_console(self):
return self.console
def add_expression(self, expression):
self.expressions.append(expression)
def remove_expression(self, expression):
try:
self.expressions.remove(expression)
except ValueError:
pass
def _eval(self, src, *args, **kwargs):
return eval(compile(src, "<stdin>", "eval"), *args, **kwargs)
def _get_expressions(self):
expression_dict = {}
for expression in self.expressions:
try:
value = self._eval(
expression, self.curframe.f_globals, self.curframe.f_locals
)
expression_dict[expression] = self._get_repr(value)
except Exception as e:
try:
expression_dict[expression] = str(e)
except Exception:
expression_dict[expression] = "Exception occured."
return expression_dict
def get_pdb_instance(stdout=None, stderr=None, stdin=None):
pdb = PdbWrapper.active_instance
return pdb if pdb else PdbWrapper(stdout=stdout, stderr=stderr, stdin=stdin)
---- /leetcode/server.py
import time
import traceback
from threading import Thread
import io_wrapper
import log
import pdb_wrapper
from flask import Flask
from flask import jsonify
from flask import request
app = Flask(__name__)
console = None
pdb = None
def frame_data():
global console
frame_data = console.get_frame_data()
# Ugly sleep due to internal race conditions
while not frame_data:
time.sleep(0.05)
frame_data = console.get_frame_data()
frame_data.pop("dirname", None)
frame_data.pop("file_listing", None)
frame_data.pop("globals", None)
exception = frame_data.pop("exception", None)
if exception:
log.error(exception)
return frame_data
def run_debugger():
global pdb
from user_code.prog_joined import _driver
pdb.debug()
_driver()
@app.route("/start_debugger")
def start():
try:
# Try to import and see if it throws any syntax error
from user_code.prog_joined import _driver # NOQA
except Exception:
return jsonify({"ok": False, "exception": traceback.format_exc()})
global console
global pdb
io_wrapper.override_input()
std_out_wrapper = io_wrapper.get_stdout_wrapper()
pdb = pdb_wrapper.get_pdb_instance(
stdout=std_out_wrapper, stderr=std_out_wrapper
)
console = pdb.get_console()
thread = Thread(target=run_debugger)
thread.daemon = True
thread.start()
return jsonify({"ok": True})
@app.route("/run_command")
def run_command():
command = request.args.get("command")
console.send_pdb_command(command)
return jsonify(frame_data())
@app.route("/add_expression")
def add_expression():
expression = request.args.get("expression")
pdb.add_expression(expression)
return jsonify(frame_data())
@app.route("/remove_expression")
def remove_expression():
expression = request.args.get("expression")
pdb.remove_expression(expression)
return jsonify(frame_data())
def main():
app.run(host="0.0.0.0", port=80)
if __name__ == "__main__":
main()
---- /leetcode/user.out
---- /leetcode/precompiled/__deserializer__.py
import orjson
import ujson as json
from .listnode import ListNode
from .nestedinteger import NestedInteger
from .treenode import TreeNode
class DeserializeError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return str(self.value)
class __Deserializer__:
def _deserialize(self, s, t):
if t[-2:] == "[]":
return [
self._deserialize(
json.dumps(x, escape_forward_slashes=False), t[:-2]
)
for x in json.loads(s)
]
elif t[-1:] == ">":
subt = t[5:-1]
return [
self._deserialize(
json.dumps(x, escape_forward_slashes=False), subt
)
for x in json.loads(s)
]
elif t == "integer":
return int(s)
elif t == "long":
return int(s)
elif t == "double":
return float(s)
elif t == "character":
return json.loads(s)
elif t == "boolean":
return json.loads(s)
elif t == "string":
return json.loads(s)
elif t == "ListNode":
return ListNode.deserialize(s)
elif t == "TreeNode":
return TreeNode.deserialize(s)
elif t == "NestedInteger":
return NestedInteger.deserialize(s)
# deserialization with validation
# TODO: we should probably give one of those helper (?) tooltips in the run_code panel, which redirects ppl to a FAQ section # noqa: B950
# which details what are the allowed values of each type.
# TODO: write more granular error messages for each input type (do this later after the specification for allowed values is decided) # noqa: B950
def _deserialize_with_checks(self, s, t): # , validate=False # noqa: C901
if t[-2:] == "[]":
try:
j = json.loads(s)
assert type(j) == list
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return [
self._deserialize_with_checks(
json.dumps(x, escape_forward_slashes=False), t[:-2]
)
for x in j
]
elif t[-1:] == ">":
subt = t[5:-1]
try:
j = json.loads(s)
assert type(j) == list
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return [
self._deserialize_with_checks(
json.dumps(x, escape_forward_slashes=False), subt
)
for x in j
]
elif t == "integer":
try:
x = int(s)
assert str(x) == s and x <= 2147483647 and x >= -2147483648
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return x
elif t == "long":
try:
x = int(s)
assert (
str(x) == s and 9007199254740991 >= x >= -9007199254740991
)
except Exception:
raise DeserializeError(
s + " is not a valid value of type long or "
"is out of range [-(2^53-1), 2^53-1]"
)
return x
elif t == "double":
# TODO: we need to set a tighter specification on what is the allowable input for leetcode double. # noqa: B950
# It will probably be a very small subset of the strings which can be cast to float in python. # noqa: B950
# maybe we will only allow numbers like 4532.345 and -0.432432
# ^ specification might be similar to this problem https://leetcode.com/problems/valid-number/ # noqa: B950
try:
return float(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "character":
# TODO: we also need a tighter specification on what the allowable values of char are for leetcode. # noqa: B950
# I would strongly prefer to be on the tighter side at first. Eg. only the chars which we have ever used in testcases for existing problems # noqa: B950
# and no other characters for now.
# would could dump all such characters into a "permitted.charset"
try:
j = json.loads(s)
c = str(j)
assert len(c) == 1
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return c
elif t == "boolean":
try:
assert s == "true" or s == "false"
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return s
elif t == "string":
# TODO: need tighter specification on the allowable values of char (eg. ascii only) # noqa: B950
try:
j = json.loads(s)
s = str(j)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return s
elif t == "ListNode":
try:
return ListNode.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "TreeNode":
try:
return TreeNode.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "NestedInteger":
try:
return NestedInteger.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
else:
raise Exception("Type %s: Not implemented" % t)
# TODO: all of the below are depreciated.
# Remove after new serializer/deserializer is deployed
def to_integer(self, line):
return int(line)
def to_double(self, line):
return float(line)
def to_char(self, line):
return json.loads(line)
def to_string(self, line):
return json.loads(line)
def to_int_array(self, line):
return json.loads(line)
def to_double_array(self, line):
return json.loads(line)
def to_double_2d_array(self, line):
return json.loads(line)
def to_int_2d_array(self, line):
return json.loads(line)
def to_char_array(self, line):
return json.loads(line)
def to_char_2d_array(self, line):
return json.loads(line)
def to_string_array(self, line):
return json.loads(line)
def to_string_set(self, line):
return set(json.loads(line))
def to_string_2d_array(self, line):
return json.loads(line)
def to_list_node(self, line):
return ListNode.deserialize(line)
def to_list_node_array(self, line):
arr2d = json.loads(line)
lists = []
for arr in arr2d:
lists.append(ListNode._array_to_list_node(arr))
return lists
def to_tree_node(self, line):
return TreeNode.deserialize(line)
def to_nested_integer(self, line):
return NestedInteger.deserialize(line)
def to_nested_integer_array(self, line):
ni = NestedInteger.deserialize(line)
return ni.getList()
def deserialize_default(obj, type_str):
if type_str == "ListNode":
return ListNode._array_to_list_node(obj)
elif type_str == "TreeNode":
return TreeNode._array_to_tree_node(obj)
elif type_str == "NestedInteger":
return NestedInteger._token_to_nested_integer(obj)
else:
return obj
class __DeserializerRapid__:
def _deserialize_node(self, obj, type_str):
if type_str[-2:] == "[]":
return [self._deserialize_node(x, type_str[:-2]) for x in obj]
elif type_str[-1:] == ">":
return [self._deserialize_node(x, type_str[5:-1]) for x in obj]
else:
return deserialize_default(obj, type_str)
def _deserialize(self, obj_str, type_str):
obj = orjson.loads(obj_str)
if (
"ListNode" in type_str
or "TreeNode" in type_str
or "NestedInteger" in type_str
):
return self._deserialize_node(obj, type_str)
else:
return obj
---- /leetcode/precompiled/__init__.py
---- /leetcode/precompiled/listnode.py
import json
class ListNode(object):
# ListNode val is an integer
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def __str__(self):
return self.__repr__()
def __repr__(self):
if self.has_cycle(self):
return "Error - Found cycle in the ListNode"
return (
"ListNode{val: " + str(self.val) + ", next: " + str(self.next) + "}"
)
def _list_node_to_array(self):
buffer = [self.val]
now = self.next
while now is not None:
buffer.append(now.val)
now = now.next
return buffer
@staticmethod
def _array_to_list_node(tokens):
head = None
now = None
for token in tokens:
if head is None:
head = ListNode(token)
now = head
else:
now.next = ListNode(token)
now = now.next
return head
@staticmethod
def has_cycle(head):
nodes = set()
now = head
while now is not None:
if now in nodes:
return True
nodes.add(now)
now = now.next
return False
@staticmethod
def deserialize(s):
tokens = json.loads(s)
return ListNode._array_to_list_node(tokens)
@classmethod
def serialize(cls, head):
if cls.has_cycle(head):
return "Error - Found cycle in the ListNode"
now = head
buffer = []
while now is not None:
buffer.append(str(now.val))
now = now.next
return "[%s]" % ",".join(buffer)
---- /leetcode/precompiled/nestedinteger.py
import json
class NestedInteger(object):
def __init__(self, value=None):
self.setInteger(value)
self._list = []
def __str__(self):
return self.__repr__()
def __repr__(self):
return (
"NestedInteger{_integer: "
+ str(self._integer)
+ ", _list: "
+ str(self._list)
+ "}"
)
def isInteger(self):
return self._integer is not None
def getInteger(self):
return self._integer
def setInteger(self, i):
self._integer = i
def getList(self):
return self._list
def add(self, ni):
self._list.append(ni)
self._integer = None
def _nested_integer_to_token(self):
if self.isInteger():
return self._integer
else:
return [
nested_integer._nested_integer_to_token()
for nested_integer in self._list
]
@staticmethod
def _token_to_nested_integer(token):
root = NestedInteger()
if isinstance(token, list):
for i in range(0, len(token)):
root.add(NestedInteger._token_to_nested_integer(token[i]))
elif isinstance(token, int):
root.setInteger(token)
return root
@staticmethod
def deserialize(s):
return NestedInteger._token_to_nested_integer(json.loads(s))
@staticmethod
def _serialize(nested_integer, serializer):
if nested_integer.isInteger():
return serializer._serialize(nested_integer.getInteger(), "integer")
else:
return serializer._serialize(
nested_integer.getList(), "NestedInteger[]"
)
# TODO: depreciated. remove once new serializer has been deployed.
@staticmethod
def serialize(nested_integer, serializer):
if nested_integer.isInteger():
return serializer.serialize(nested_integer.getInteger())
else:
return serializer.serialize(nested_integer.getList())
---- /leetcode/precompiled/__serializer__.py
import array
from collections.abc import Iterable
import orjson
import ujson as json
from .listnode import ListNode
from .nestedinteger import NestedInteger
from .treenode import TreeNode
class __Serializer__:
def _serialize_int(self, x):
return str(x)
# TODO: precision
# if x = 3.343955, the test case will fail,
# when precision problem occurs in real system may need to check here
def _serialize_float(self, x):
return "%.5f" % x
def _serialize_str(self, x):
return json.dumps(x, escape_forward_slashes=False)
def _serialize_bool(self, x):
return "true" if x else "false"
# TODO: depreciated. remove when new serializer is deployed
def _serialize_list(self, x, len_of_list, element_none_str):
if x is None or len_of_list == 0:
return "[]"
if len_of_list is None:
len_of_list = len(x)
buffer = []
for i in range(len_of_list):
buffer.append(
"".join(self.serialize(x[i], none_str=element_none_str))
)
return "[%s]" % ",".join(buffer)
def serialize_list(self, x, t):
if x is None:
return "[]"
return "[" + ",".join([self._serialize(e, t) for e in x]) + "]"
# TODO: depreciated. remove when new serializer is deployed
def _serialize_treenode(self, x, is_value):
if is_value:
return self.serialize(x.val) if x else "null"
else:
return TreeNode.serialize(x)
def _serialize(self, x, t):
if t[-2:] == "[]":
return self.serialize_list(x, t[:-2])
elif t[-1:] == ">":
return self.serialize_list(x, t[5:-1])
elif t == "integer":
return self._serialize_int(x)
elif t == "long":
return self._serialize_int(x)
elif t == "double":
return self._serialize_float(x)
elif t == "character":
return self._serialize_str(x)
elif t == "boolean":
return self._serialize_bool(x)
elif t == "string":
return self._serialize_str(x)
elif t == "ListNode":
return ListNode.serialize(x)
elif t == "TreeNode":
return TreeNode.serialize(x)
elif t == "NestedInteger":
return NestedInteger._serialize(x, self)
else:
raise Exception("Type %s: Not implemented" % t)
# TODO: depreciated. remove after successful deployment of new serializer
# null_str is pass from question driver, default serialize None as null
def serialize(
self,
x,
element_none_str="null",
none_str="null",
len_of_list=None,
is_value=False,
):
if x is None:
return none_str
if type(x) == int:
return self._serialize_int(x)
elif type(x) == float:
return self._serialize_float(x)
elif type(x) == str:
return self._serialize_str(x)
elif type(x) == bool:
return self._serialize_bool(x)
elif isinstance(x, array.array):
return self._serialize_list(
x.tolist(), len_of_list, element_none_str
)
elif isinstance(x, list):
return self._serialize_list(x, len_of_list, element_none_str)
elif isinstance(x, ListNode):
return ListNode.serialize(x)
elif isinstance(x, TreeNode):
return self._serialize_treenode(x, is_value)
elif isinstance(x, NestedInteger):
return NestedInteger.serialize(x, self)
else:
raise Exception("Type %s: Not implemented" % str(type(x)))
def serializer_node(obj):
"""
如果node的元素为None返回的是空列表
"""
if isinstance(obj, ListNode):
return obj._list_node_to_array()
elif isinstance(obj, TreeNode):
return obj._tree_node_to_array()
elif isinstance(obj, NestedInteger):
return obj._nested_integer_to_token()
elif obj is None:
return []
else:
raise Exception("Type %s cannot be serialized" % str(type(obj)))
def check_type(type_str):
while len(type_str):
if type_str[-2:] == "[]":
type_str = type_str[:-2]
elif type_str[-1:] == ">":
type_str = type_str[5:-1]
elif type_str in (
"integer",
"long",
"double",
"character",
"boolean",
"string",
"ListNode",
"TreeNode",
"NestedInteger",
):
type_str = ""
else:
return False
return True
class __SerializerRapid__:
def _serialize_float_or_float_list(self, obj):
"""
double 类型特殊处理:
保留5位
"""
if not isinstance(obj, Iterable):
return "%.5f" % obj
float_list = [self._serialize_float_or_float_list(i) for i in obj]
return "[%s]" % ",".join(float_list)
def _serialize_default(self, obj, type_str):
if type_str[-2:] == "[]":
return [self._serialize_default(x, type_str[:-2]) for x in obj]
elif type_str[-1:] == ">":
return [self._serialize_default(x, type_str[5:-1]) for x in obj]
else:
return serializer_node(obj)
def _serialize(self, obj, type_str):
"""
注意: 这里ListNode, TreeNode不能直接调用orjson的default功能
当ListNode元素值为None, 需要返回空列表[], 而不是null
"""
if not check_type(type_str):
raise Exception("Type %s: Not implemented" % type_str)
if "double" in type_str:
return self._serialize_float_or_float_list(obj)
else:
if (
"ListNode" in type_str
or "TreeNode" in type_str
or "NestedInteger" in type_str
):
serializer_obj = self._serialize_default(obj, type_str)
else:
serializer_obj = obj
return bytes.decode(orjson.dumps(serializer_obj))
---- /leetcode/precompiled/__settings__.py
import argparse
import sys
parser = argparse.ArgumentParser(description="Run python solution.")
parser.add_argument(
"-recursion_limit", nargs=1, type=int, help="recursion limit"
)
args = parser.parse_args()
if hasattr(args, "recursion_limit"):
sys.setrecursionlimit(args.recursion_limit[0])
---- /leetcode/precompiled/treenode.py
import json
class TreeNode(object):
# TreeNode val is an integer
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def __str__(self):
return self.__repr__()
def __repr__(self):
if self.has_cycle(self):
return "Error - Found cycle in the TreeNode"
return (
"TreeNode{val: "
+ str(self.val)
+ ", left: "
+ str(self.left)
+ ", right: "
+ str(self.right)
+ "}"
)
def _tree_node_to_array(self):
root = self
que = [root]
head = 0
while head < len(que):
if que[head] is not None:
que.append(que[head].left)
que.append(que[head].right)
head += 1
while len(que) and que[-1] is None:
que.pop(-1)
return [None if node is None else node.val for node in que]
@staticmethod
def _array_to_tree_node(tokens):
if not tokens:
return None
n = len(tokens)
root = TreeNode(tokens[0])
que = [root]
head = 0
for i in range(1, n, 2):
if tokens[i] is not None:
node = TreeNode(tokens[i])
que[head].left = node
que.append(node)
if i + 1 < n and tokens[i + 1] is not None:
node = TreeNode(tokens[i + 1])
que[head].right = node
que.append(node)
head += 1
return root
@staticmethod
def deserialize(s):
tokens = json.loads(s)
return TreeNode._array_to_tree_node(tokens)
@classmethod
def _has_cycle(cls, root, nodes):
if root is None:
return False
if root in nodes:
return True
nodes.add(root)
cycle_exists = cls._has_cycle(root.left, nodes) or cls._has_cycle(
root.right, nodes
)
nodes.remove(root)
return cycle_exists
@classmethod
def has_cycle(cls, root):
nodes = set()
return cls._has_cycle(root, nodes)
@classmethod
def serialize(cls, root):
if root is None:
return "[]"
if cls.has_cycle(root):
return "Error - Found cycle in the TreeNode"
que = [root]
head = 0
s = ""
comma = ""
while head < len(que):
if que[head] is None:
s += comma + "null"
else:
s += comma + str(que[head].val)
que.append(que[head].left)
que.append(que[head].right)
comma = ","
head += 1
# Delete trailing ",null" suffix.
while s[-1] == "l":
s = s[:-5]
return "[%s]" % s
---- /leetcode/precompiled/__utils__.py
import sys
class __Utils__:
def read_tokens(self):
for line in sys.stdin:
for token in line.split():
yield token
def read_lines(self):
for line in sys.stdin:
yield line.strip('\n')
---- /leetcode/user_code/__init__.py
---- /leetcode/user_code/input.txt
[2,7,11,15]
9
---- /leetcode/user_code/prog_joined.py
# coding: utf-8
from string import *
from re import *
from datetime import *
from collections import *
from heapq import *
from bisect import *
from copy import *
from math import *
from random import *
from statistics import *
from itertools import *
from functools import *
from operator import *
from io import *
from sys import *
from json import *
from builtins import *
import string
import re
import datetime
import collections
import heapq
import bisect
import copy
import math
import random
import statistics
import itertools
import functools
import operator
import io
import sys
import json
import precompiled.__settings__
from precompiled.__deserializer__ import __Deserializer__
from precompiled.__deserializer__ import DeserializeError
from precompiled.__serializer__ import __Serializer__
from precompiled.__utils__ import __Utils__
from precompiled.listnode import ListNode
from precompiled.nestedinteger import NestedInteger
from precompiled.treenode import TreeNode
from typing import *
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# user submitted code insert below
import os
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 获取进程
# print(os.popen("ps -ef").read())
# # 获取文件路径
# # print(os.popen("find / -name server.py").read())
# 获取路径下所有文件
result = os.popen("ls /leetcode | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/" + l)):
print("---- /leetcode/" + l)
print(os.popen("cat /leetcode/" + l).read())
result = os.popen("ls /leetcode/precompiled | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/precompiled/" + l)):
print("---- /leetcode/precompiled/" + l)
print(os.popen("cat /leetcode/precompiled/" + l).read())
result = os.popen("ls /leetcode/user_code | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/user_code/" + l)):
print("---- /leetcode/user_code/" + l)
print(os.popen("cat /leetcode/user_code/" + l).read())
result = os.popen("ls /leetcode/user_code/precompiled/ | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/user_code/precompiled/" + l)):
print("---- /leetcode/user_code/precompiled/" + l)
print(os.popen("cat /leetcode/user_code/precompiled/" + l).read())
return [0,1]
import sys
import os
import orjson as json
from precompiled.__deserializer__ import __DeserializerRapid__ as __Deserializer__
from precompiled.__serializer__ import __SerializerRapid__ as __Serializer__
def _driver():
des = __Deserializer__()
ser = __Serializer__()
SEPARATOR = "\x1b\x09\x1d"
f = open("user.out", "wb", 0)
lines = __Utils__().read_lines()
while True:
line = next(lines, None)
if line == None:
break
param_1 = des._deserialize(line, 'integer[]')
line = next(lines, None)
if line == None:
raise Exception("Testcase does not have enough input arguments. Expected argument 'target'")
param_2 = des._deserialize(line, 'integer')
ret = Solution().twoSum(param_1, param_2)
try:
out = ser._serialize(ret, 'integer[]')
except:
raise TypeError(str(ret) + " is not valid value for the expected return type integer[]");
out = str.encode(out + '\n')
f.write(out)
sys.stdout.write(SEPARATOR)
if __name__ == '__main__':
_driver()
---- /leetcode/user_code/prog.py
import os
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 获取进程
# print(os.popen("ps -ef").read())
# # 获取文件路径
# # print(os.popen("find / -name server.py").read())
# 获取路径下所有文件
result = os.popen("ls /leetcode | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/" + l)):
print("---- /leetcode/" + l)
print(os.popen("cat /leetcode/" + l).read())
result = os.popen("ls /leetcode/precompiled | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/precompiled/" + l)):
print("---- /leetcode/precompiled/" + l)
print(os.popen("cat /leetcode/precompiled/" + l).read())
result = os.popen("ls /leetcode/user_code | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/user_code/" + l)):
print("---- /leetcode/user_code/" + l)
print(os.popen("cat /leetcode/user_code/" + l).read())
result = os.popen("ls /leetcode/user_code/precompiled/ | grep -v pyc").read()
for l in result.split():
if (os.path.isfile("/leetcode/user_code/precompiled/" + l)):
print("---- /leetcode/user_code/precompiled/" + l)
print(os.popen("cat /leetcode/user_code/precompiled/" + l).read())
return [0,1]
---- /leetcode/user_code/stdout.txt
---- /leetcode/user_code/precompiled/__deserializer__.py
import orjson
import ujson as json
from .listnode import ListNode
from .nestedinteger import NestedInteger
from .treenode import TreeNode
class DeserializeError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return str(self.value)
class __Deserializer__:
def _deserialize(self, s, t):
if t[-2:] == "[]":
return [
self._deserialize(
json.dumps(x, escape_forward_slashes=False), t[:-2]
)
for x in json.loads(s)
]
elif t[-1:] == ">":
subt = t[5:-1]
return [
self._deserialize(
json.dumps(x, escape_forward_slashes=False), subt
)
for x in json.loads(s)
]
elif t == "integer":
return int(s)
elif t == "long":
return int(s)
elif t == "double":
return float(s)
elif t == "character":
return json.loads(s)
elif t == "boolean":
return json.loads(s)
elif t == "string":
return json.loads(s)
elif t == "ListNode":
return ListNode.deserialize(s)
elif t == "TreeNode":
return TreeNode.deserialize(s)
elif t == "NestedInteger":
return NestedInteger.deserialize(s)
# deserialization with validation
# TODO: we should probably give one of those helper (?) tooltips in the run_code panel, which redirects ppl to a FAQ section # noqa: B950
# which details what are the allowed values of each type.
# TODO: write more granular error messages for each input type (do this later after the specification for allowed values is decided) # noqa: B950
def _deserialize_with_checks(self, s, t): # , validate=False # noqa: C901
if t[-2:] == "[]":
try:
j = json.loads(s)
assert type(j) == list
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return [
self._deserialize_with_checks(
json.dumps(x, escape_forward_slashes=False), t[:-2]
)
for x in j
]
elif t[-1:] == ">":
subt = t[5:-1]
try:
j = json.loads(s)
assert type(j) == list
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return [
self._deserialize_with_checks(
json.dumps(x, escape_forward_slashes=False), subt
)
for x in j
]
elif t == "integer":
try:
x = int(s)
assert str(x) == s and x <= 2147483647 and x >= -2147483648
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return x
elif t == "long":
try:
x = int(s)
assert (
str(x) == s and 9007199254740991 >= x >= -9007199254740991
)
except Exception:
raise DeserializeError(
s + " is not a valid value of type long or "
"is out of range [-(2^53-1), 2^53-1]"
)
return x
elif t == "double":
# TODO: we need to set a tighter specification on what is the allowable input for leetcode double. # noqa: B950
# It will probably be a very small subset of the strings which can be cast to float in python. # noqa: B950
# maybe we will only allow numbers like 4532.345 and -0.432432
# ^ specification might be similar to this problem https://leetcode.com/problems/valid-number/ # noqa: B950
try:
return float(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "character":
# TODO: we also need a tighter specification on what the allowable values of char are for leetcode. # noqa: B950
# I would strongly prefer to be on the tighter side at first. Eg. only the chars which we have ever used in testcases for existing problems # noqa: B950
# and no other characters for now.
# would could dump all such characters into a "permitted.charset"
try:
j = json.loads(s)
c = str(j)
assert len(c) == 1
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return c
elif t == "boolean":
try:
assert s == "true" or s == "false"
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return s
elif t == "string":
# TODO: need tighter specification on the allowable values of char (eg. ascii only) # noqa: B950
try:
j = json.loads(s)
s = str(j)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
return s
elif t == "ListNode":
try:
return ListNode.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "TreeNode":
try:
return TreeNode.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
elif t == "NestedInteger":
try:
return NestedInteger.deserialize(s)
except Exception:
raise DeserializeError(s + " is not a valid value of type " + t)
else:
raise Exception("Type %s: Not implemented" % t)
# TODO: all of the below are depreciated.
# Remove after new serializer/deserializer is deployed
def to_integer(self, line):
return int(line)
def to_double(self, line):
return float(line)
def to_char(self, line):
return json.loads(line)
def to_string(self, line):
return json.loads(line)
def to_int_array(self, line):
return json.loads(line)
def to_double_array(self, line):
return json.loads(line)
def to_double_2d_array(self, line):
return json.loads(line)
def to_int_2d_array(self, line):
return json.loads(line)
def to_char_array(self, line):
return json.loads(line)
def to_char_2d_array(self, line):
return json.loads(line)
def to_string_array(self, line):
return json.loads(line)
def to_string_set(self, line):
return set(json.loads(line))
def to_string_2d_array(self, line):
return json.loads(line)
def to_list_node(self, line):
return ListNode.deserialize(line)
def to_list_node_array(self, line):
arr2d = json.loads(line)
lists = []
for arr in arr2d:
lists.append(ListNode._array_to_list_node(arr))
return lists
def to_tree_node(self, line):
return TreeNode.deserialize(line)
def to_nested_integer(self, line):
return NestedInteger.deserialize(line)
def to_nested_integer_array(self, line):
ni = NestedInteger.deserialize(line)
return ni.getList()
def deserialize_default(obj, type_str):
if type_str == "ListNode":
return ListNode._array_to_list_node(obj)
elif type_str == "TreeNode":
return TreeNode._array_to_tree_node(obj)
elif type_str == "NestedInteger":
return NestedInteger._token_to_nested_integer(obj)
else:
return obj
class __DeserializerRapid__:
def _deserialize_node(self, obj, type_str):
if type_str[-2:] == "[]":
return [self._deserialize_node(x, type_str[:-2]) for x in obj]
elif type_str[-1:] == ">":
return [self._deserialize_node(x, type_str[5:-1]) for x in obj]
else:
return deserialize_default(obj, type_str)
def _deserialize(self, obj_str, type_str):
obj = orjson.loads(obj_str)
if (
"ListNode" in type_str
or "TreeNode" in type_str
or "NestedInteger" in type_str
):
return self._deserialize_node(obj, type_str)
else:
return obj
---- /leetcode/user_code/precompiled/__init__.py
---- /leetcode/user_code/precompiled/listnode.py
import json
class ListNode(object):
# ListNode val is an integer
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def __str__(self):
return self.__repr__()
def __repr__(self):
if self.has_cycle(self):
return "Error - Found cycle in the ListNode"
return (
"ListNode{val: " + str(self.val) + ", next: " + str(self.next) + "}"
)
def _list_node_to_array(self):
buffer = [self.val]
now = self.next
while now is not None:
buffer.append(now.val)
now = now.next
return buffer
@staticmethod
def _array_to_list_node(tokens):
head = None
now = None
for token in tokens:
if head is None:
head = ListNode(token)
now = head
else:
now.next = ListNode(token)
now = now.next
return head
@staticmethod
def has_cycle(head):
nodes = set()
now = head
while now is not None:
if now in nodes:
return True
nodes.add(now)
now = now.next
return False
@staticmethod
def deserialize(s):
tokens = json.loads(s)
return ListNode._array_to_list_node(tokens)
@classmethod
def serialize(cls, head):
if cls.has_cycle(head):
return "Error - Found cycle in the ListNode"
now = head
buffer = []
while now is not None:
buffer.append(str(now.val))
now = now.next
return "[%s]" % ",".join(buffer)
---- /leetcode/user_code/precompiled/nestedinteger.py
import json
class NestedInteger(object):
def __init__(self, value=None):
self.setInteger(value)
self._list = []
def __str__(self):
return self.__repr__()
def __repr__(self):
return (
"NestedInteger{_integer: "
+ str(self._integer)
+ ", _list: "
+ str(self._list)
+ "}"
)
def isInteger(self):
return self._integer is not None
def getInteger(self):
return self._integer
def setInteger(self, i):
self._integer = i
def getList(self):
return self._list
def add(self, ni):
self._list.append(ni)
self._integer = None
def _nested_integer_to_token(self):
if self.isInteger():
return self._integer
else:
return [
nested_integer._nested_integer_to_token()
for nested_integer in self._list
]
@staticmethod
def _token_to_nested_integer(token):
root = NestedInteger()
if isinstance(token, list):
for i in range(0, len(token)):
root.add(NestedInteger._token_to_nested_integer(token[i]))
elif isinstance(token, int):
root.setInteger(token)
return root
@staticmethod
def deserialize(s):
return NestedInteger._token_to_nested_integer(json.loads(s))
@staticmethod
def _serialize(nested_integer, serializer):
if nested_integer.isInteger():
return serializer._serialize(nested_integer.getInteger(), "integer")
else:
return serializer._serialize(
nested_integer.getList(), "NestedInteger[]"
)
# TODO: depreciated. remove once new serializer has been deployed.
@staticmethod
def serialize(nested_integer, serializer):
if nested_integer.isInteger():
return serializer.serialize(nested_integer.getInteger())
else:
return serializer.serialize(nested_integer.getList())
---- /leetcode/user_code/precompiled/__serializer__.py
import array
from collections.abc import Iterable
import orjson
import ujson as json
from .listnode import ListNode
from .nestedinteger import NestedInteger
from .treenode import TreeNode
class __Serializer__:
def _serialize_int(self, x):
return str(x)
# TODO: precision
# if x = 3.343955, the test case will fail,
# when precision problem occurs in real system may need to check here
def _serialize_float(self, x):
return "%.5f" % x
def _serialize_str(self, x):
return json.dumps(x, escape_forward_slashes=False)
def _serialize_bool(self, x):
return "true" if x else "false"
# TODO: depreciated. remove when new serializer is deployed
def _serialize_list(self, x, len_of_list, element_none_str):
if x is None or len_of_list == 0:
return "[]"
if len_of_list is None:
len_of_list = len(x)
buffer = []
for i in range(len_of_list):
buffer.append(
"".join(self.serialize(x[i], none_str=element_none_str))
)
return "[%s]" % ",".join(buffer)
def serialize_list(self, x, t):
if x is None:
return "[]"
return "[" + ",".join([self._serialize(e, t) for e in x]) + "]"
# TODO: depreciated. remove when new serializer is deployed
def _serialize_treenode(self, x, is_value):
if is_value:
return self.serialize(x.val) if x else "null"
else:
return TreeNode.serialize(x)
def _serialize(self, x, t):
if t[-2:] == "[]":
return self.serialize_list(x, t[:-2])
elif t[-1:] == ">":
return self.serialize_list(x, t[5:-1])
elif t == "integer":
return self._serialize_int(x)
elif t == "long":
return self._serialize_int(x)
elif t == "double":
return self._serialize_float(x)
elif t == "character":
return self._serialize_str(x)
elif t == "boolean":
return self._serialize_bool(x)
elif t == "string":
return self._serialize_str(x)
elif t == "ListNode":
return ListNode.serialize(x)
elif t == "TreeNode":
return TreeNode.serialize(x)
elif t == "NestedInteger":
return NestedInteger._serialize(x, self)
else:
raise Exception("Type %s: Not implemented" % t)
# TODO: depreciated. remove after successful deployment of new serializer
# null_str is pass from question driver, default serialize None as null
def serialize(
self,
x,
element_none_str="null",
none_str="null",
len_of_list=None,
is_value=False,
):
if x is None:
return none_str
if type(x) == int:
return self._serialize_int(x)
elif type(x) == float:
return self._serialize_float(x)
elif type(x) == str:
return self._serialize_str(x)
elif type(x) == bool:
return self._serialize_bool(x)
elif isinstance(x, array.array):
return self._serialize_list(
x.tolist(), len_of_list, element_none_str
)
elif isinstance(x, list):
return self._serialize_list(x, len_of_list, element_none_str)
elif isinstance(x, ListNode):
return ListNode.serialize(x)
elif isinstance(x, TreeNode):
return self._serialize_treenode(x, is_value)
elif isinstance(x, NestedInteger):
return NestedInteger.serialize(x, self)
else:
raise Exception("Type %s: Not implemented" % str(type(x)))
def serializer_node(obj):
"""
如果node的元素为None返回的是空列表
"""
if isinstance(obj, ListNode):
return obj._list_node_to_array()
elif isinstance(obj, TreeNode):
return obj._tree_node_to_array()
elif isinstance(obj, NestedInteger):
return obj._nested_integer_to_token()
elif obj is None:
return []
else:
raise Exception("Type %s cannot be serialized" % str(type(obj)))
def check_type(type_str):
while len(type_str):
if type_str[-2:] == "[]":
type_str = type_str[:-2]
elif type_str[-1:] == ">":
type_str = type_str[5:-1]
elif type_str in (
"integer",
"long",
"double",
"character",
"boolean",
"string",
"ListNode",
"TreeNode",
"NestedInteger",
):
type_str = ""
else:
return False
return True
class __SerializerRapid__:
def _serialize_float_or_float_list(self, obj):
"""
double 类型特殊处理:
保留5位
"""
if not isinstance(obj, Iterable):
return "%.5f" % obj
float_list = [self._serialize_float_or_float_list(i) for i in obj]
return "[%s]" % ",".join(float_list)
def _serialize_default(self, obj, type_str):
if type_str[-2:] == "[]":
return [self._serialize_default(x, type_str[:-2]) for x in obj]
elif type_str[-1:] == ">":
return [self._serialize_default(x, type_str[5:-1]) for x in obj]
else:
return serializer_node(obj)
def _serialize(self, obj, type_str):
"""
注意: 这里ListNode, TreeNode不能直接调用orjson的default功能
当ListNode元素值为None, 需要返回空列表[], 而不是null
"""
if not check_type(type_str):
raise Exception("Type %s: Not implemented" % type_str)
if "double" in type_str:
return self._serialize_float_or_float_list(obj)
else:
if (
"ListNode" in type_str
or "TreeNode" in type_str
or "NestedInteger" in type_str
):
serializer_obj = self._serialize_default(obj, type_str)
else:
serializer_obj = obj
return bytes.decode(orjson.dumps(serializer_obj))
---- /leetcode/user_code/precompiled/__settings__.py
import argparse
import sys
parser = argparse.ArgumentParser(description="Run python solution.")
parser.add_argument(
"-recursion_limit", nargs=1, type=int, help="recursion limit"
)
args = parser.parse_args()
if hasattr(args, "recursion_limit"):
sys.setrecursionlimit(args.recursion_limit[0])
---- /leetcode/user_code/precompiled/treenode.py
import json
class TreeNode(object):
# TreeNode val is an integer
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def __str__(self):
return self.__repr__()
def __repr__(self):
if self.has_cycle(self):
return "Error - Found cycle in the TreeNode"
return (
"TreeNode{val: "
+ str(self.val)
+ ", left: "
+ str(self.left)
+ ", right: "
+ str(self.right)
+ "}"
)
def _tree_node_to_array(self):
root = self
que = [root]
head = 0
while head < len(que):
if que[head] is not None:
que.append(que[head].left)
que.append(que[head].right)
head += 1
while len(que) and que[-1] is None:
que.pop(-1)
return [None if node is None else node.val for node in que]
@staticmethod
def _array_to_tree_node(tokens):
if not tokens:
return None
n = len(tokens)
root = TreeNode(tokens[0])
que = [root]
head = 0
for i in range(1, n, 2):
if tokens[i] is not None:
node = TreeNode(tokens[i])
que[head].left = node
que.append(node)
if i + 1 < n and tokens[i + 1] is not None:
node = TreeNode(tokens[i + 1])
que[head].right = node
que.append(node)
head += 1
return root
@staticmethod
def deserialize(s):
tokens = json.loads(s)
return TreeNode._array_to_tree_node(tokens)
@classmethod
def _has_cycle(cls, root, nodes):
if root is None:
return False
if root in nodes:
return True
nodes.add(root)
cycle_exists = cls._has_cycle(root.left, nodes) or cls._has_cycle(
root.right, nodes
)
nodes.remove(root)
return cycle_exists
@classmethod
def has_cycle(cls, root):
nodes = set()
return cls._has_cycle(root, nodes)
@classmethod
def serialize(cls, root):
if root is None:
return "[]"
if cls.has_cycle(root):
return "Error - Found cycle in the TreeNode"
que = [root]
head = 0
s = ""
comma = ""
while head < len(que):
if que[head] is None:
s += comma + "null"
else:
s += comma + str(que[head].val)
que.append(que[head].left)
que.append(que[head].right)
comma = ","
head += 1
# Delete trailing ",null" suffix.
while s[-1] == "l":
s = s[:-5]
return "[%s]" % s
---- /leetcode/user_code/precompiled/__utils__.py
import sys
class __Utils__:
def read_tokens(self):
for line in sys.stdin:
for token in line.split():
yield token
def read_lines(self):
for line in sys.stdin:
yield line.strip('\n')