def print_lines( name: str, type_: Type, input_data: Input, indent_lvl: int, style: FormatStyle = FormatStyle.DEFAULT, ) -> List[str]: """Print the content of a var that holds in one or more lines""" indent = INDENTATION * indent_lvl if type_.fits_in_one_line(input_data.structs, style): return [indent + print_line(name, type_, input_data, style)] if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None inner = "iT{}".format(indent_lvl) return ( [indent + "for _, {} in ipairs({}) do".format(inner, name)] + print_lines(inner, type_.encapsulated, input_data, indent_lvl + 1) + [indent + "end"] ) assert type_.main == TypeEnum.STRUCT lines = [] for i in input_data.get_struct(type_.struct_name).fields: lines.extend( print_lines('{}["{}"]'.format(name, i.name), i.type, input_data, indent_lvl) ) return lines
def print_line(name: str, type_: Type, input_data: Input, style: FormatStyle) -> str: """Print a variable on one line""" assert type_.fits_in_one_line(input_data.structs, style) newline = " " if style == FormatStyle.NO_ENDLINE else r"\n" if type_.main == TypeEnum.INT: return f'Printf.printf "%d{newline}" {name}' if type_.main == TypeEnum.CHAR: return f'Printf.printf "%c{newline}" {name}' if type_.main == TypeEnum.STR: return f'Printf.printf "%s{newline}" {name}' if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None concat = "" if type_.encapsulated.main == TypeEnum.INT: concat = '" " (List.rev (List.rev_map string_of_int {}))'.format( name) else: assert type_.encapsulated.main == TypeEnum.CHAR concat = '"" (List.rev (List.rev_map (String.make 1) {}))'.format( name) return 'Printf.printf "%s\\n" (String.concat {})'.format(concat) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return 'Printf.printf "{}\\n" {}'.format( " ".join("%d" if f.type.main == TypeEnum.INT else "%c" for f in struct.fields), " ".join("{}.{}".format(name, var_name(f.name)) for f in struct.fields), )
def print_line(name: str, type_: Type, input_data: Input, style: FormatStyle) -> str: """Print a variable that fits in one line""" assert type_.fits_in_one_line(input_data.structs, style) write = (f'write({name}), write(" ")' if style == FormatStyle.NO_ENDLINE else f"writeln({name})") if type_.main == TypeEnum.INT: return f"integer({name}), {write}" if type_.main == TypeEnum.CHAR: return f"atom({name}), {write}" if type_.main == TypeEnum.STR: return f"string({name}), {write}" if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.INT: return ("is_list({0}), maplist(integer, {0}), atomic_list_concat(" "{0}, ' ', {0}_S), writeln({0}_S)").format(name) assert type_.encapsulated.main == TypeEnum.CHAR return ("is_list({0}), maplist(atom, {0}), string_chars({0}_S, {0})," "writeln({0}_S)").format(name) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) fields = [] for i, field in enumerate(struct.fields): f_name = name + "_" + var_name(field.name) fields.append( 'get_assoc("{0}", {1}, {2}), {3}({2}), write({2}), {4}'.format( field.name, name, name + "_" + f_name, "integer" if field.type.main == TypeEnum.INT else "atom", 'write(" ")' if i < len(struct.fields) - 1 else "nl", )) return "is_assoc({}), {}".format(name, ", ".join(fields))
def print_lines( name: str, type_: Type, input_data: Input, style: FormatStyle = FormatStyle.DEFAULT) -> Tuple[List[str], str]: """Print a variable that fits in several lines Return a list of declarations to be put before, and the actual code to print the variable""" if type_.fits_in_one_line(input_data.structs, style): return ([], print_line(name, type_, input_data, style)) if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None arg = name + "_S" function = "print_" + name (decl, code) = print_lines(arg, type_.encapsulated, input_data) return (decl + ["{}({}) :- {}.".format(function, arg, code) ]), "is_list({1}), maplist({0}, {1})".format( function, name) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) fields = [] decls = [] for field in struct.fields: f_name = name + "_" + var_name(field.name) decl, print_inner = print_lines(f_name, field.type, input_data) fields.append('get_assoc("{}", {}, {}), {}'.format( field.name, name, f_name, print_inner)) decls.extend(decl) return decls, "is_assoc({}), {}".format(name, ", ".join(fields))
def read_line(type_: Type, input_data: Input) -> str: """Generate the Ruby code to read a line of given type""" assert type_.fits_in_one_line(input_data.structs) if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return 'STDIN.gets.chomp.split("")' assert type_.encapsulated.main == TypeEnum.INT return "STDIN.gets.split.map(&:to_i)" if type_.main == TypeEnum.STRUCT: struct = input_data.get_struct(type_.struct_name) keys = ", ".join('"{}"'.format(i.name) for i in struct.fields) if all(i.type.main == TypeEnum.INT for i in struct.fields): return "Hash[[{}].zip(STDIN.gets.split.map(&:to_i))]".format(keys) if all(i.type.main == TypeEnum.CHAR for i in struct.fields): return 'Hash[[{}].zip(STDIN.gets.chomp.split(" "))]'.format(keys) return "Hash[[{}].zip([{}], STDIN.gets.split).map{{ {} }}]".format( keys, ", ".join("1" if i.type.main == TypeEnum.INT else "0" for i in struct.fields), "|x,y,z| [x, y == 1 ? z.to_i : z]", ) return { TypeEnum.INT: "STDIN.gets.to_i", TypeEnum.CHAR: "STDIN.gets[0]", TypeEnum.STR: "STDIN.gets.chomp", }[type_.main]
def read_line(type_: Type, input_data: Input) -> str: """Read an entire line into the correct type""" assert type_.fits_in_one_line(input_data.structs) if type_.main == TypeEnum.INT: return "read_int ()" if type_.main == TypeEnum.CHAR: return "(read_line ()).[0]" if type_.main == TypeEnum.STR: return "read_line ()" if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.INT: # Note: here we have to use List.rev_map |> List.rev, because # List.map is not tail-recursive, and will trigger a stack overflow # if the list is big (size bigger than 1024). # We could check if the constraints specify a small list, and use # only List.map for those cases. return ('read_line () |> fun x -> if x = "" then [] else ' "String.split_on_char ' ' x |> " "List.rev_map int_of_string |> List.rev") assert type_.encapsulated.main == TypeEnum.CHAR return "List.init {} (String.get (read_line ()))".format( var_name(type_.size)) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) args = [var_name(field.name) for field in struct.fields] return 'Scanf.sscanf (read_line ()) "{}" (fun {} -> {{{}}})'.format( " ".join("%d" if f.type.main == TypeEnum.INT else "%c" for f in struct.fields), " ".join(args), "; ".join("{0}".format(i) for i in args), )
def call(input_data: Input, reprint: bool) -> List[str]: """Declare the function that takes all inputs in arguments""" out = (["/**"] + [ " * @param {{{}}} {} {}".format(type_str(arg.type, input_data), var_name(arg.name), arg.comment) for arg in input_data.input ] + [" * @returns {void}", " */"]) out.append("function {}({}) {{".format( var_name(input_data.name), ", ".join(var_name(i.name) for i in input_data.input), )) if reprint: for variables in input_data.get_all_vars(): if len(variables) == 1: var = variables[0] out.extend( print_lines(input_data, var_name(var.name), var.type, 1, var.format_style)) else: out.append(INDENTATION + "console.log(" + ", ".join(var_name(i.name) for i in variables) + ");") else: out.extend([ INDENTATION + i for i in textwrap.wrap("/* TODO " + input_data.output + " */", 75) ]) out.append("}") return out
def call(input_data: Input, reprint: bool) -> List[str]: """Declare and call the function take all inputs in arguments""" name = var_name(input_data.name) lines = [ "# +{}+:: {}".format(var_name(arg.name), arg.comment) for arg in input_data.input ] lines.append("def {}({})".format( name, ", ".join(var_name(i.name) for i in input_data.input))) if reprint: lines.append(INDENTATION + '$\\ = "\\n"') for variables in input_data.get_all_vars(): if len(variables) == 1: var = variables[0] lines.extend( print_lines(var_name(var.name), var.type, input_data, 1, var.format_style)) else: lines.append( INDENTATION + "puts " + f'[{", ".join(var_name(i.name) for i in variables)}].join(" ")' ) else: lines.extend( textwrap.wrap( input_data.output, 79, initial_indent=INDENTATION + "# " + "TODO ", subsequent_indent=INDENTATION + "# ", )) return lines + ["end"]
def read_line(name: str, decl: str, type_: Type, input_data: Input, words: WordsName) -> List[str]: """Generate the Ruby code to read a line of given type""" assert type_.fits_in_one_line(input_data.structs) if type_.main == TypeEnum.INT: return [decl.format("int <>")] if type_.main == TypeEnum.CHAR: return [decl.format("substr <>, 0, 1")] if type_.main == TypeEnum.STR: read = "<>" if decl.startswith("my") else "scalar(<>)" return [decl.format(read), "chomp {};".format(name)] if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None decl2 = decl if not decl.startswith("my"): decl2 = format_keep_braces(decl, "\\@{{[{}]}}") if type_.encapsulated.main == TypeEnum.INT: return [decl2.format("map { int } split(/[ \\n]/, <>)")] assert type_.encapsulated.main == TypeEnum.CHAR return [decl2.format("split /\\n?/, <>")] assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) decl2 = decl if not decl.startswith("my"): decl2 = format_keep_braces(decl, "\\%{{{{{}}}}}") split = words.next_name() fields = ('"{}" => {}'.format( f.name, ("int(${}[{}])" if f.type.main == TypeEnum.INT else "substr(${}[{}], 0, 1)").format(split, i), ) for i, f in enumerate(struct.fields)) return [ "my @{} = split /[ \\n]/, <>;".format(split), decl2.format("({})".format(", ".join(fields))), ]
def read_line(type_: Type, input_data: Input) -> str: """Generate the Python code to read a line of given type""" assert type_.fits_in_one_line(input_data.structs) if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return "list(input())" assert type_.encapsulated.main == TypeEnum.INT return "list(map(int, input().split()))" if type_.main == TypeEnum.STRUCT: struct = input_data.get_struct(type_.struct_name) if all(i.type.main == TypeEnum.INT for i in struct.fields): return f"{class_name(struct.name)}(*map(int, input().split()))" if all(i.type.main == TypeEnum.CHAR for i in struct.fields): return f"{class_name(struct.name)}(*input().split())" return "{}(*map({}, ({}), input().split()))".format( class_name(struct.name), "lambda x, y: int(y) if x else y", ", ".join( "1" if i.type.main == TypeEnum.INT else "0" for i in struct.fields ), ) return { TypeEnum.INT: "int(input())", TypeEnum.CHAR: "input()[0]", TypeEnum.STR: "input()", }[type_.main]
def read_vars(input_data: Input, iterator: IteratorName) -> List[str]: """Read all input variables""" all_lines = [] for variables in input_data.get_all_vars(): if len(variables) == 1: var = variables[0] lines = read_lines( Variable(var_name(var.name), "", var.type, var.format_style), var_name(var.type.size), input_data, iterator, ) if lines[0].startswith("local"): # struct lines[1] = "local " + lines[1] else: lines[0] = "local " + lines[0] all_lines.extend(lines) else: assert all(var.type.main == TypeEnum.INT for var in variables) all_lines.append( 'local {} = string.match(io.read(), "{}")'.format( ", ".join(var_name(i.name) for i in variables), " ".join(["(-?%d+)"] * len(variables)), ) ) return all_lines
def gen_ocaml(input_data: Input, reprint: bool = False) -> str: """Generate a OCaml code to parse input""" output = "" main = "" for record in input_data.structs: main += "\n".join(declare_record(record)) main += "\n\n" main += "\n".join(method(input_data, reprint)) main += "\n\nlet () =\n" for variables in input_data.get_all_vars(): if len(variables) == 1: var = variables[0] main += ( INDENTATION + f"let {var_name(var.name)} = " + f"{read_lines(var.type, input_data, var.format_style)} in\n") else: assert all(var.type.main == TypeEnum.INT for var in variables) main += (INDENTATION + 'let[@warning "-8"] [' + "; ".join(var_name(i.name) for i in variables) + "] = read_line () |> String.split_on_char ' '" '|> List.map int_of_string [@warning "+8"] in \n') args = (var_name(i.name) for i in input_data.input) main += "{}{} {}\n".format(INDENTATION, var_name(input_data.name), " ".join(args)) output += main return output
def error_parse_input(dic: Dict[str, Any]) -> str: """Explain why we an input fails to parse""" # pylint: disable=too-many-return-statements # pylint: disable=too-many-branches assert Input.from_dict(dic) is None if "function_name" not in dic: if "name" in dic: dic["function_name"] = dic["name"] else: return "missing function_name field" if not isinstance(dic["function_name"], str): return "function_name is not a string" if "structs" in dic: # non mandatory if not isinstance(dic["structs"], list): return "'structs' is not a list" for node in dic["structs"]: if Struct.from_dict(node) is None: return "failed to parse struct: " + error_parse_struct(node) if "input" not in dic: return "missing input field" if not isinstance(dic["input"], list): return "output is not a list" for node in dic["input"]: if Variable.from_dict(node) is None: return "failed to parse variable: " + error_parse_variable(node) if "output" not in dic: return "missing output field" if not isinstance(dic["output"], str): return "output is not a string" return "unknown error"
def read_line( name: str, type_: Type, input_data: Input, iterator: IteratorName ) -> List[str]: """Generate the Lua code to read a line of given type""" assert type_.fits_in_one_line(input_data.structs) if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None inner = iterator.new_it() iterator.pop_it() if type_.encapsulated.main == TypeEnum.CHAR: return [ "{} = {{}}".format(name), 'io.read():gsub(".",function({0}) table.insert({1}, {0}) end)'.format( inner, name ), ] assert type_.encapsulated.main == TypeEnum.INT return [ "{} = {{}}".format(name), 'for {} in string.gmatch(io.read(), "-?%d+") do'.format(inner), INDENTATION + "table.insert({}, tonumber({}))".format(name, inner), "end", ] if type_.main == TypeEnum.STRUCT: struct = input_data.get_struct(type_.struct_name) words = iterator.new_it() iterator.pop_it() pattern = " ".join( "(-?%d+)" if i.type.main == TypeEnum.INT else "(%S)" for i in struct.fields ) keys = ( '["{}"]'.format(i.name) if " " in i.name else i.name for i in struct.fields ) values = ( "tonumber({}[{}])".format(words, i + 1) if f.type.main == TypeEnum.INT else "{}[{}]".format(words, i + 1) for (i, f) in enumerate(struct.fields) ) return [ 'local {} = {{string.match(io.read(), "{}")}}'.format(words, pattern), "{} = {{{}}}".format( name, ", ".join(i + " = " + j for (i, j) in zip(keys, values)) ), ] return [ name + " = " + { TypeEnum.INT: "tonumber(io.read())", TypeEnum.CHAR: "io.read()", TypeEnum.STR: "io.read()", }[type_.main] ]
def read_lines( type_: Type, size: str, input_data: Input, iterator: IteratorName, style: FormatStyle = FormatStyle.DEFAULT, ) -> List[str]: """Generate the Ruby code to read the lines for a given type""" if type_.fits_in_one_line(input_data.structs, style): return [read_line(type_, input_data)] if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None lines = read_lines(type_.encapsulated, var_name(type_.encapsulated.size), input_data, iterator) if len(lines) == 1: candidate = "Array.new({}) {{ {} }}".format(size, lines[0]) if len(candidate) <= 75: return [candidate] if lines[0][0] == "{": lines[0] = "Array.new({}) {{ {}".format(size, lines[0]) else: lines = ["Array.new({}) {{".format(size) ] + [INDENTATION + i for i in lines] if lines[-1][-1] == "}": lines[-1] += " }" else: lines.append("}") return lines assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) if struct.is_sized_struct(): inner = iterator.new_it() lines = read_lines(struct.fields[1].type, inner, input_data, iterator) iterator.pop_it() lines[0] = '"{}" => {}'.format(struct.fields[1].name, lines[0]) return ([ "(lambda {{ |{}| {{".format(inner), INDENTATION + '"{}" => {},'.format(struct.fields[0].name, inner), ] + [INDENTATION + i for i in lines] + ["} }).call(STDIN.gets.to_i)"]) fields = [] for i, field in enumerate(struct.fields): lines = read_lines(field.type, var_name(field.type.size), input_data, iterator) lines[0] = '{}"{}" => {}'.format(INDENTATION, field.name, lines[0]) if i != len(struct.fields) - 1: lines[-1] += "," fields.append(lines[0]) fields.extend([INDENTATION + i for i in lines[1:]]) return ["{"] + fields + ["}"]
def print_line(name: str, type_: Type, input_data: Input) -> str: """Print the content of a var in one line""" assert type_.fits_in_one_line(input_data.structs) if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR): return "console.log({});".format(name) if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return 'console.log({}.join(""));'.format(name) assert type_.encapsulated.main == TypeEnum.INT return 'console.log({}.join(" "));'.format(name) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return 'console.log([{}].join(" "));'.format(", ".join( "{}.{}".format(name, var_name(i.name)) for i in struct.fields))
def print_line(name: str, type_: Type, input_data: Input) -> str: """Print the content of a var in one line""" assert type_.fits_in_one_line(input_data.structs) if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR): return "puts {}".format(name) if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return 'puts {}.join("")'.format(name) assert type_.encapsulated.main == TypeEnum.INT return 'puts {}.join(" ")'.format(name) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return "print {}".format(', " ", '.join('{}["{}"]'.format(name, i.name) for i in struct.fields))
def print_line(name: str, type_: Type, input_data: Input, style: FormatStyle) -> str: """Print the content of a var in one line""" assert type_.fits_in_one_line(input_data.structs, style) if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR): end = ", end=' '" if style == FormatStyle.NO_ENDLINE else "" return f"print({name}{end})" if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return "print(''.join({}))".format(name) assert type_.encapsulated.main == TypeEnum.INT return "print(' '.join(map(str, {})))".format(name) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return "print({})".format( ", ".join(f"{name}.{var_name(field.name)}" for field in struct.fields) )
def print_line(name: str, type_: Type, input_data: Input, style: FormatStyle) -> str: """Print the content of a var in one line""" assert type_.fits_in_one_line(input_data.structs, style) if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR): endline = " " if style == FormatStyle.NO_ENDLINE else r"\n" return f'echo {name}, "{endline}";' if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return 'echo join("", {}), "\\n";'.format(name) assert type_.encapsulated.main == TypeEnum.INT return 'echo join(" ", {}), "\\n";'.format(name) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return 'echo {}, "\\n";'.format(", ' ', ".join( '{}["{}"]'.format(name, i.name) for i in struct.fields))
def print_line(name: str, type_: Type, input_data: Input, style: FormatStyle) -> str: """Print the content of a var in one line""" assert type_.fits_in_one_line(input_data.structs, style) if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR): return (f'print({name}, " ")' if style == FormatStyle.NO_ENDLINE else f"println({name})") if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return "println(join({}))".format(name) assert type_.encapsulated.main == TypeEnum.INT return "println(join({}, ' '))".format(name) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return "println({})".format(", ' ', ".join( "{}.{}".format(name, var_name(i.name)) for i in struct.fields))
def type_str(type_: Type, input_data: Input) -> str: """Return the Javascript name for a type""" # http://usejsdoc.org/tags-type.html if type_.main == TypeEnum.INT: return "number" if type_.main == TypeEnum.CHAR: return "string" if type_.main == TypeEnum.STR: return "string" if type_.main == TypeEnum.STRUCT: struct = input_data.get_struct(type_.struct_name) return "{{{}}}".format(", ".join("{}: {}".format( v.name if " " not in v.name else "'{}'".format(v.name), type_str(v.type, input_data), ) for v in struct.fields)) assert type_.main == TypeEnum.LIST assert type_.encapsulated return "Array.<{}>".format(type_str(type_.encapsulated, input_data))
def read_vars(input_data: Input) -> List[str]: """Read all input variables""" lines = [] for variables in input_data.get_all_vars(): if len(variables) == 1: var = variables[0] var_lines = read_lines( var.type, var_name(var.type.size), input_data, var.format_style ) var_lines[0] = f"{var_name(var.name)} = {var_lines[0]}" lines.extend(var_lines) else: assert all(var.type.main == TypeEnum.INT for var in variables) lines.append( ", ".join(var_name(i.name) for i in variables) + " = map(int, input().split())" ) return lines
def type_str(type_: Type, input_data: Input) -> str: """Transform a type into a string description for documentation""" if type_.main == TypeEnum.INT: return "int" if type_.main == TypeEnum.CHAR: return "string" if type_.main == TypeEnum.STR: return "string" if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None return "{}[]".format(type_str(type_.encapsulated, input_data)) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) # the following is not PHPDoc, but it does not allow for anything more than # 'array' return "(array{{{}}})".format(", ".join( '"{}": {}'.format(v.name, type_str(v.type, input_data)) for v in struct.fields))
def read_lines(type_: Type, input_data: Input, style: FormatStyle = FormatStyle.DEFAULT) -> str: """Read one or several lines into the correct type""" if type_.fits_in_one_line(input_data.structs, style): return read_line(type_, input_data) if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None return "List.init {} (fun _ -> {})".format( var_name(type_.size), read_lines(type_.encapsulated, input_data)) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return "{} {{{}}}".format( " ".join("let {} = {} in".format(var_name(field.name), read_lines(field.type, input_data)) for field in struct.fields), "; ".join("{0}".format(var_name(f.name)) for f in struct.fields), )
def print_line(varname: str, type_: Type, input_data: Input, style: FormatStyle) -> str: """Print the content of a var in one line""" assert type_.fits_in_one_line(input_data.structs, style) name = "$" + varname[1:] if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR): endline = " " if style == FormatStyle.NO_ENDLINE else r"\n" return f'print "{name}{endline}";' if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return f'print join("", @{{{name}}}) . "\\n";' assert type_.encapsulated.main == TypeEnum.INT return 'print "{}\\n";'.format("@{" + name + "}") assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return 'print "{}\\n";'.format(" ".join( "{}->{{'{}'}}".format(name, i.name) for i in struct.fields))
def read_lines(var: Variable, decl: str, size: str, input_data: Input, words: WordsName) -> List[str]: """Generate the Ruby code to read the lines for a given type""" if var.fits_in_one_line(input_data.structs): return read_line(var.name, decl, var.type, input_data, words) if var.type.main == TypeEnum.LIST: assert var.type.encapsulated is not None lines = [ decl.format("()" if var.name[0] == "@" else "[]"), "for (1..{}) {{".format(size), ] words.push_scope() array_name = var.name.replace("{", "{{").replace("}", "}}") if array_name[0] != "@": array_name = "@{{" + array_name + "}}" lines.extend([ INDENTATION + i for i in read_lines( Variable("$" + var.name[1:] + "[-1]", "", var.type.encapsulated), "push({}, {{}});".format(array_name), size_name(var.type.encapsulated.size), input_data, words, ) ]) words.pop_scope() return lines + ["}"] assert var.type.main == TypeEnum.STRUCT struct = input_data.get_struct(var.type.struct_name) sizes = [size_name(field.type.size) for field in struct.fields] if struct.is_sized_struct(): sizes = ["", f"{var.name}{{'{struct.fields[0].name}'}}"] lines = [decl.format("()" if var.name[0] == "%" else "{}")] for (field, f_size) in zip(struct.fields, sizes): f_name = f"${var.name[1:]}{{'{field.name}'}}" lines.extend( read_lines( Variable(f_name, "", field.type), f_name.replace("{", "{{").replace("}", "}}") + " = {};", f_size, input_data, words, )) return lines
def max_size( type_: Type, constraints: Optional[Constraints], input_data: Input, style: FormatStyle = FormatStyle.DEFAULT, ) -> int: """Computes the maximum number of bytes the type can take on stdin""" if type_.main == TypeEnum.INT: assert constraints return max( len(str(constraints.min_possible())), len(str(constraints.max_possible())) ) if type_.main == TypeEnum.CHAR: return 1 if type_.main == TypeEnum.STRUCT: struct = input_data.get_struct(type_.struct_name) sizes = [max_size(i.type, i.constraints, input_data) for i in struct.fields] if type_.fits_in_one_line(input_data.structs, style): return sum(sizes) + len(struct.fields) - 1 return max(sizes) size = -1 size_vars = [x for x in input_data.input if x.name == type_.size] if not size_vars: size_vars = [ x for s in input_data.structs for x in s.fields if x.name == type_.size ] if size_vars: varconstraints = size_vars[0].constraints assert varconstraints size = varconstraints.max_possible() else: size = int(type_.size) if type_.main == TypeEnum.STR: return size assert type_.main == TypeEnum.LIST assert type_.encapsulated value = max_size(type_.encapsulated, constraints, input_data) return ( value * size + max(0, size - 1) if type_.fits_in_one_line(input_data.structs, style) else value )
def read_vars(input_data: Input, words: WordsName) -> List[str]: """Read all input variables""" lines = [] for variables in input_data.get_all_vars(): if len(variables) == 1: var = variables[0] lines.extend( read_lines( Variable(var_name(var), "", var.type, var.format_style), "my {} = {{}};".format(var_name(var)), size_name(var.type.size), input_data, words, )) else: split = words.next_name() lines.append(f"my @{split} = split / /, <>;") for i, var in enumerate(variables): lines.append(f"my {var_name(var)} = int(${split}[{i}]);") return lines
def generate_random_input(input_data: Input, specs: List[str], perf_mode: bool = False) -> str: """Generate a randow raw input, as described by input_data""" specs_dict = {} for i in range(0, len(specs), 2): specs_dict[specs[i]] = int(specs[i + 1]) generator = Generator(input_data, specs_dict, perf_mode) lines = [] for variables in input_data.get_all_vars(): if len(variables) == 1: lines.extend(generator.generate_lines(variables[0])) else: values = [] for var in variables: assert var.type.main == TypeEnum.INT assert var.constraints is not None values.append( generator.generate_integer(var.name, var.constraints)) lines.append(" ".join(values)) return "\n".join(lines) + "\n"
def print_line(name: str, type_: Type, input_data: Input, style: FormatStyle) -> str: """Print the content of a var in one line""" assert type_.fits_in_one_line(input_data.structs, style) if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR): return ( f"io.write({name}, ' ')" if style == FormatStyle.NO_ENDLINE else f"print({name})" ) if type_.main == TypeEnum.LIST: assert type_.encapsulated is not None if type_.encapsulated.main == TypeEnum.CHAR: return 'print(table.concat({}, ""))'.format(name) assert type_.encapsulated.main == TypeEnum.INT return 'print(table.concat({}, " "))'.format(name) assert type_.main == TypeEnum.STRUCT struct = input_data.get_struct(type_.struct_name) return 'print(string.format("{}", {}))'.format( " ".join("%s" for _ in struct.fields), ", ".join('{}["{}"]'.format(name, i.name) for i in struct.fields), )