diff --git a/.gitignore b/.gitignore index 017f559..416a620 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .gitignore .idea __pycache__ +*.out diff --git a/src/a.out b/src/a.out deleted file mode 100755 index a4cae0e..0000000 Binary files a/src/a.out and /dev/null differ diff --git a/src/fetcher.py b/src/fetcher.py index 292738c..215e2b5 100644 --- a/src/fetcher.py +++ b/src/fetcher.py @@ -1,27 +1,28 @@ -from scraper import * +import os + +from scraper import Problem + +path = os.path.dirname(os.path.realpath(__file__)) +path = f"{path}/problems" -path = "src/test_cases/" -def write_file(file_name,code_str): - with open(file_name,"w") as f: - f.write(code_str) - f.close() +def write_file(file_name, code_str): + with open(file_name, "w") as f: + f.write(code_str) -prob = input("Enter problem name, Eg: 1980G: ") -p = Problem(prob[:4],prob[4]) -content = "".join(p.input) + "@" -for test in p.tests: - content += test.input + "@" -write_file(path+prob+".txt",content) def fetch(prob): + if isinstance(prob, str): + contestId, index = prob.split("_") + else: + contestId, index = prob + try: - p = Problem(prob[:4],prob[4]) - input_string = "".join(p.input) - tests = [test.input for test in p.tests] + p = Problem(contestId, index) + p = {"input": rf"{p.input}", "tests": rf"{p.tests}"} + write_file(f"{path}/{contestId}_{index}.txt", str(p)) except: - with open(path + prob + ".txt",'r') as f: - s = f.read().split("@") - input_string = s[0] - tests = s[1:] - return input_string,tests + with open(f"{path}/{contestId}_{index}.txt", "r") as f: + p = eval(f.read()) + + return p["input"], p["tests"] diff --git a/src/problem_parser.py b/src/problem_parser.py index a122f7e..c34d6d3 100644 --- a/src/problem_parser.py +++ b/src/problem_parser.py @@ -1,6 +1,8 @@ # This file contains all the functions to parse the input string -from scraper import * +import re + +from scraper import Problem class Variable: @@ -41,16 +43,18 @@ def __init__(self, iterations, *enclosed): # Useful where questions might use words instead of digits for small numbers -text_numbers = {"one": 1, - "two": 2, - "three": 3, - "four": 4, - "five": 5, - "six": 6, - "seven": 7, - "eight": 8, - "nine": 9, - "ten": 10} +text_numbers = { + "one": 1, + "two": 2, + "three": 3, + "four": 4, + "five": 5, + "six": 6, + "seven": 7, + "eight": 8, + "nine": 9, + "ten": 10, +} def ignore(line): @@ -75,7 +79,7 @@ def check_array(line): return var_details = match.group().split() - qty = var_details[0].strip('$') + qty = var_details[0].strip("$") try: qty = int(qty) except ValueError: @@ -83,7 +87,7 @@ def check_array(line): qty = text_numbers[qty] except KeyError: pass - name = var_details[2].strip(',$') + name = var_details[2].strip(",$") match = re.search(".*_", name) if match is not None: @@ -93,19 +97,19 @@ def check_array(line): def check_str(line): target_string = line - is_str=re.search(".*string.*", line) - is_strs=re.search(".*strings.*", line) - if is_str and not is_strs : + is_str = re.search(".*string.*", line) + is_strs = re.search(".*strings.*", line) + if is_str and not is_strs: return Variable("string", "str", "s") - elif is_strs : + elif is_strs: res2 = re.search("[^ ]+ strings ", target_string) if res2 is None: return var = res2.group().split() - num2 = var[0].strip('$') - target_string = target_string[res2.span()[1]:] + num2 = var[0].strip("$") + target_string = target_string[res2.span()[1] :] try: num2 = int(num2) @@ -140,7 +144,7 @@ def check_str(line): name = var_detail[0].strip("$.") l.append(name) - target_string = target_string[search_name.span()[1]:] + target_string = target_string[search_name.span()[1] :] x = x + 1 obj = [] @@ -149,19 +153,21 @@ def check_str(line): obj.append(Variable("string", "str", y)) return obj - else : + else: return def check_matrix(line): - is_matrix = re.search(".*lines.*(numbers|integers)",line) + is_matrix = re.search(".*lines.*(numbers|integers)", line) if is_matrix: result = line.split("lines") num1 = result[0].split()[-1][1:-1] return_val = check_array(result[1]) num2 = return_val.datatype_cpp[4:-1] arr = return_val.name - return Variable("int[{}][{}]".format(num1,num2), "int[{}][{}]".format(num1,num2), arr) + return Variable( + "int[{}][{}]".format(num1, num2), "int[{}][{}]".format(num1, num2), arr + ) else: return @@ -172,7 +178,7 @@ def check_integer(line): res = re.search("[^ ]+ (integer|number) ", target_string) if res is not None: - target_string = target_string[res.span()[1]:] + target_string = target_string[res.span()[1] :] if target_string[0:2] == "of" and res.group().split()[1] == "number": res = None target_string = line @@ -181,7 +187,7 @@ def check_integer(line): index = res.group().split() search_string = re.search("[^ ]*", target_string) var_detail = search_string.group().split() - name = var_detail[0].strip('$.') + name = var_detail[0].strip("$.") return Variable("int", "int", name) @@ -192,8 +198,8 @@ def check_integer(line): return var = res2.group().split() - num2 = var[0].strip('$') - target_string = target_string[res2.span()[1]:] + num2 = var[0].strip("$") + target_string = target_string[res2.span()[1] :] try: num2 = int(num2) @@ -228,7 +234,7 @@ def check_integer(line): name = var_detail[0].strip("$.") l.append(name) - target_string = target_string[search_name.span()[1]:] + target_string = target_string[search_name.span()[1] :] x = x + 1 obj = [] @@ -240,19 +246,18 @@ def check_integer(line): # IMPORTANT : Priority order is decided here -all_fxns = (check_matrix, - check_array, - check_str, - check_integer, - ) +all_fxns = ( + check_matrix, + check_array, + check_str, + check_integer, +) # Function to make all the necessary checks -def check_all(para): - para = re.sub(r"\." + " |\n|\n\n", "\n", para) - lines = para.split('\n') +def check_all(inp): all_data = [] - for line in lines: + for line in inp: if ignore(line): continue for check in all_fxns: @@ -262,6 +267,5 @@ def check_all(para): all_data.extend(op) except TypeError: all_data.append(op) - print(check) break return all_data diff --git a/src/problems/1922_A.txt b/src/problems/1922_A.txt new file mode 100644 index 0000000..7f98486 --- /dev/null +++ b/src/problems/1922_A.txt @@ -0,0 +1 @@ +{'input': "['Input', 'The first line contains an integer $t$ ($1$ $\\\\le$ $t$ $\\\\le$ $1000$)\\xa0— the number of test cases.', 'The first line of each test case contains an integer $n$ ($1$ $\\\\le$ $n$ $\\\\le$ $20$)\\xa0— the length of the given strings.', 'The next three lines contain the strings $a,$ $b$ and $c$. Each string consists of exactly $n$ lowercase Latin letters.']", 'tests': '[T: 4\n\nInput\n4\n1\na\nb\nc\n2\naa\nbb\naa\n10\nmathforces\nluckforces\nadhoccoder\n3\nacc\nabd\nabc\n\nOutput\nYES\nNO\nYES\nNO]'} \ No newline at end of file diff --git a/src/problems/1980_E.txt b/src/problems/1980_E.txt new file mode 100644 index 0000000..3f1f6c4 --- /dev/null +++ b/src/problems/1980_E.txt @@ -0,0 +1 @@ +{'input': "['Input', 'The first line contains an integer $t$ ($1$ $\\\\le$ $t$ $\\\\le$ $10^4$) — the number of test cases. The descriptions of the test cases follow.', 'The first line of each test case description contains $2$ integers $n$ and $m$ ($1$ $\\\\le$ $n,$ $m$ $\\\\le$ $n$ $\\\\cdot$ $m$ $\\\\le$ $2$ $\\\\cdot$ $10^5$) — the sizes of the matrix.', 'The next $n$ lines contain $m$ integers $a_{ij}$ each ($1$ $\\\\le$ $a_{ij}$ $\\\\le$ $n$ $\\\\cdot$ $m$). It is guaranteed that matrix $a$ is a permutation.', 'The next $n$ lines contain $m$ integers $b_{ij}$ each ($1$ $\\\\le$ $b_{ij}$ $\\\\le$ $n$ $\\\\cdot$ $m$). It is guaranteed that matrix $b$ is a permutation.', 'It is guaranteed that the sum of the values $n$ $\\\\cdot$ $m$ for all test cases does not exceed $2$ $\\\\cdot$ $10^5$.']", 'tests': '[T: 7\n\nInput\n7\n1 1\n1\n1\n2 2\n1 2\n3 4\n4 3\n2 1\n2 2\n1 2\n3 4\n4 3\n1 2\n3 4\n1 5 9 6\n12 10 4 8\n7 11 3 2\n1 5 9 6\n12 10 4 8\n7 11 3 2\n3 3\n1 5 9\n6 4 2\n3 8 7\n9 5 1\n2 4 6\n7 8 3\n2 3\n1 2 6\n5 4 3\n6 1 2\n3 4 5\n1 5\n5 1 2 3 4\n4 2 5 1 3\n\nOutput\nYES\nYES\nNO\nYES\nYES\nNO\nYES]'} \ No newline at end of file diff --git a/src/problems/2008_A.txt b/src/problems/2008_A.txt new file mode 100644 index 0000000..5a1e20d --- /dev/null +++ b/src/problems/2008_A.txt @@ -0,0 +1 @@ +{'input': '[\'Input\', \'The first line contains a single integer $t$ ($1\\\\le$ $t\\\\le$ $100$) \\xa0— the number of test cases.\', "The only line of each test case contains two integers $a$ and $b$ ($0\\\\le$ $a,b<10$) \\xa0— the number of \'1\'s and the number of \'2\'s in the array."]', 'tests': '[T: 5\n\nInput\n5\n0 1\n0 3\n2 0\n2 3\n3 1\n\nOutput\nNO\nNO\nYES\nYES\nNO]'} \ No newline at end of file diff --git a/src/problems/2008_F.txt b/src/problems/2008_F.txt new file mode 100644 index 0000000..c1175cd --- /dev/null +++ b/src/problems/2008_F.txt @@ -0,0 +1 @@ +{'input': "['Input', 'The first line contains a single integer $t$ ($1\\\\le$ $t\\\\le$ $10^4$) \\xa0— the number of test cases.', 'The first line of each test case contains a single integer $n$ ($2\\\\le$ $n\\\\le$ $2\\\\cdot$ $10^5$) \\xa0— the number of elements in the array.', 'The second line of each test case contains $n$ integers $a_1,$ $a_2,$ $\\\\dots,$ $a_n$ ($0\\\\le$ $a_i\\\\le$ $10^9$) \\xa0— the elements of the array.', 'It is guaranteed that the sum of $n$ across all test cases does not exceed $2\\\\cdot$ $10^5$.']", 'tests': '[T: 3\n\nInput\n3\n3\n3 2 3\n4\n2 2 2 4\n5\n1 2 3 4 5\n\nOutput\n7\n6\n500000012]'} \ No newline at end of file diff --git a/src/problems/2008_G.txt b/src/problems/2008_G.txt new file mode 100644 index 0000000..b7c6128 --- /dev/null +++ b/src/problems/2008_G.txt @@ -0,0 +1 @@ +{'input': "['Input', 'The first line contains a single integer $t$ ($1\\\\le$ $t\\\\le$ $10^4$) \\xa0— the number of test cases.', 'The first line of each test case contains two integers $n$ and $k$ ($1\\\\le$ $n\\\\le$ $2\\\\cdot$ $10^5,1\\\\le$ $k\\\\le$ $10^9$) \\xa0— the number of elements in the array and the value $k$ for $mex_k$.', 'The second line of each test case contains $n$ integers $a_1,$ $a_2,$ $\\\\dots,a_n$ ($1\\\\le$ $a_i\\\\le$ $10^9$) \\xa0— the elements of the array.', 'It is guaranteed that the sum of $n$ across all test cases does not exceed $2\\\\cdot$ $10^5$.']", 'tests': '[T: 6\n\nInput\n6\n1 3\n3\n2 10\n1 1\n3 1\n1 2 3\n3 2\n1 2 4\n4 5\n2 2 2 16\n4 5\n2 2 2 3\n\nOutput\n2\n11\n3\n4\n8\n8]'} \ No newline at end of file diff --git a/src/scraper.py b/src/scraper.py index 8fde3b7..f03727b 100644 --- a/src/scraper.py +++ b/src/scraper.py @@ -42,7 +42,9 @@ def __init__(self, contestId, index): try: self.input = [ self.mark_latex_symbols(line) - for line in self.soup.find("div", "input-specification").stripped_strings + for line in self.soup.find( + "div", "input-specification" + ).stripped_strings ] except: raise Exception("Fetch failed") diff --git a/src/test_cases/1980G.txt b/src/test_cases/1980G.txt deleted file mode 100644 index e1320b8..0000000 --- a/src/test_cases/1980G.txt +++ /dev/null @@ -1,53 +0,0 @@ -InputThe first line contains an integer $t$ ($1$ $\le$ $t$ $\le$ $10^4$) — the number of test cases.The descriptions of the test cases follow.The first line of each test case contains two integers $n$, $m$ ($2$ $\le$ $n$ $\le$ $2$ $\cdot$ $10^5$, $1$ $\le$ $m$ $\le$ $2$ $\cdot$ $10^5$) — the number of vertices in the tree and the number of queries.The next $n$ $-$ $1$ lines of each test case contain three integers $v$, $u$, $w$ ($1$ $\le$ $v,$ $u$ $\le$ $n$, $1$ $\le$ $w$ $\le$ $10^9$) — the ends of some edge in the tree and its weight.It is guaranteed that the given set of edges forms a tree.The next $m$ lines of each test case describe the queries:^$y$ ($1$ $\le$ $y$ $\le$ $10^9$) — parameter of the first type query;?$v$ $x$ ($1$ $\le$ $v$ $\le$ $n$, $1$ $\le$ $x$ $\le$ $10^9$) — parameters of the second type query.It is guaranteed that the sum of $n$ over all test cases does not exceed $2$ $\cdot$ $10^5$. The same is guaranteed for $m$.$Input -2 -3 7 -1 2 1 -3 1 8 -^ 5 -? 2 9 -^ 1 -? 1 10 -^ 6 -? 3 1 -? 2 9 -5 6 -1 2 777 -3 2 2812 -4 1 16 -5 3 1000000000 -^ 4 -? 3 123 -? 5 1000000000 -^ 1000000000 -? 1 908070 -? 2 1%Input -3 -8 4 -8 6 3 -6 3 4 -2 5 4 -7 6 2 -7 1 10 -4 1 4 -5 1 2 -^ 4 -^ 7 -? 7 8 -? 4 10 -5 6 -3 1 4 -2 3 9 -4 3 6 -5 2 10 -? 5 7 -^ 1 -^ 8 -? 4 10 -? 1 9 -? 3 6 -4 2 -2 1 4 -4 3 5 -2 3 4 -^ 13 -? 1 10% \ No newline at end of file diff --git a/src/test_generator.py b/src/test_generator.py index 8fece08..9958750 100644 --- a/src/test_generator.py +++ b/src/test_generator.py @@ -1,87 +1,34 @@ - -import pytest import os + +from fetcher import fetch from generator_cpp import full_code_cpp from generator_py import full_code_py from problem_parser import check_all -from scraper import Problem -# from fetcher import fetch - +dir = os.path.dirname(os.path.realpath(__file__)) -code_name_py = "./temp/main.py" -code_name_cpp = "./temp/main.cpp" -input_file = "./temp/input.txt" +code_name_py = f"{dir}/tmp/main.py" +code_name_cpp = f"{dir}/tmp/main.cpp" +input_file = f"{dir}/tmp/input.txt" EOFCheck = """try:\n\tinput()\n\traise Exception("File not fully read")\nexcept EOFError:\n\tpass""" -def write_file(file_name,code_str): - with open(file_name,"w") as f: +def write_file(file_name, code_str): + with open(file_name, "w") as f: f.write(code_str) f.close() def test_gen_pair_integers(): - #p = Problem("2008", "A") - #inp = '''The only line of each test case contains two integers $a$ and $b$ ($0 \\le a, b \\le 10^9$) — the number of '1's and the number of '2's in the array.''' - - #p = Problem("2008", "C") - #inp = '''The only line of each test case contains two integers $l$ and $r$ ($1 \\le l, r \\le 10^9$).''' - - #p = Problem("2008", "D") - #inp = '''The first line contains a single integer $t$ ($1 \\le t \\le 10^4$) — the number of test cases. - -#The first line of each test case contains a single integer $n$ ($1 \\le n \\le 2 \\cdot 10^5$) — the number of elements in the array. - -#The second line of each test case contains $n$ integers $p_1, p_2, ..., p_n$ ($1 \\le p_i \\le n$) — the elements of the permutation. - -#The third line of each test case contains a string $s$ of length $n$, consisting of '0' and '1'. If $s_i = 0$, then the number $p_i$ is colored black; if $s_i = 1%, then the number $p_i$ is colored white. - -#It is guaranteed that the sum of $n$ across all test cases does not exceed %2 \\cdot 10^5$.''' - - #p = Problem("2002", "G") - #inp = '''Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \\le t \\le 100$). The description of the test cases follows. - -#The first line of each test case contains a single integer $n$ ($2 \\le n \\le 20$) — the number of rows and columns. + inp, tests = fetch("2008_G") -#Each of the next $n - 1$ lines contains $n$ integers separated by single spaces — the matrix $d$ ($0 \\le d_{x, y} \\le 2n - 2$). - -#Each of the next $n$ lines contains $n-1$ integers separated by single spaces — the matrix $r$ ($0 \\le r_{x, y} \\le 2n - 2$). - -#It is guaranteed that the sum of all $n^3$ does not exceed $8000$.''' - - #p = Problem("2008", "G") - inp = '''The first line contains a single integer $t$ ($1 \\le t \\le 10^4$) — the number of test cases. - -The first line of each test case contains two integers $n$ and $k$ ($1 \\le n \le 2 \\cdot 10^5, 1 \\le k \\le 10^9$) — the number of elements in the array and the value $k$ for $mex_k$. - -The second line of each test case contains $n$ integers $a_1, a_2, ..., a_n$ ($1 \\le a_i \\le 10^9$) — the elements of the array. - -It is guaranteed that the sum of $n$ across all test cases does not exceed %2 \\cdot 10^5$. - -''' - - #code_str = full_code_cpp(check_all(p.input)) code_str_py = full_code_py(check_all(inp)) code_str_cpp = full_code_cpp(check_all(inp)) - #code_str = """T = int(input())\nfor i in range(T):\n\tx,y = map(int,input().split(' '))""" write_file(code_name_py, code_str_py) write_file(code_name_cpp, code_str_cpp) - os.system("python3 ./temp/main.py < ./temp/input.txt ") - os.system("g++ ./temp/main.cpp") - os.system("./a.out < ./temp/input.txt") - -def test_gen_pair_integers(): - prob = "2008A" - input_string,tests = fetch(prob) - #code_str = full_code_cpp(check_all(input_string)) - code_str = """T = int(input())\nfor i in range(T):\n\tx,y = map(int,input().split(' '))""" - write_file(code_name,code_str) - for test in tests: - test_raw = test[6:] # dropping the input word - write_file(input_file,test_raw) - os.system("python3 main.py < input.txt ") + os.system(f"python3 {code_name_py} < {input_file} ") -test_gen_pair_integers() \ No newline at end of file + os.system(f"g++ -o ./a.out {code_name_cpp}") + os.system(f"./a.out < {input_file}") diff --git a/src/test_parser.py b/src/test_parser.py index e704f99..22429df 100644 --- a/src/test_parser.py +++ b/src/test_parser.py @@ -1,58 +1,49 @@ import pytest -# from generator import generate +from fetcher import fetch from problem_parser import check_all from scraper import Problem def setup_testcases(p): - # generate(check_all(p.input)) for test in p.tests: test.input -def test_scraper(): - try: - p = Problem("1980", "G") - assert len(p.input) == 12 - except: - pytest.fail("Scraper could not fetch") - - def test_parser_int(): - p = Problem("2008", "A") + inp, tests = fetch("2008_A") try: - check_all(p.input) + check_all(inp) except: pytest.fail("Parser failed for pair of integers") # def test_parser_array(): -# p = Problem("2008", "F") +# inp, tests = fetch("2008_F") # try: -# check_all(p.input) +# check_all(inp) # except: # pytest.fail("Parser failed for array of integers") -def test_parser_string(): - p = Problem("1922", "A") - try: - check_all(p.input) - except: - pytest.fail("Parser failed for string") +# def test_parser_string(): +# inp, tests = fetch("1922_A") +# try: +# check_all(inp) +# except: +# pytest.fail("Parser failed for string") # def test_parser_matrix(): -# p = Problem("1980", "E") +# inp, tests = fetch("1980_E") # try: -# check_all(p.input) +# check_all(inp) # except: # pytest.fail("Parser failed for matrix") # def test_parser_string_array(): -# p = Problem("1980", "E") +# inp, tests = fetch("1980_E") # try: -# check_all(p.input) +# check_all(inp) # except: # pytest.fail("Parser failed for array of strings") diff --git a/src/temp/input.txt b/src/tmp/input.txt similarity index 100% rename from src/temp/input.txt rename to src/tmp/input.txt diff --git a/src/temp/main.cpp b/src/tmp/main.cpp similarity index 100% rename from src/temp/main.cpp rename to src/tmp/main.cpp diff --git a/src/temp/main.py b/src/tmp/main.py similarity index 100% rename from src/temp/main.py rename to src/tmp/main.py