def eval_is_solvable(n, m, solvable=False): print(f"Checking if solvable {n}x{m}") pirellone = random_pirellone(n, m, solvable=solvable) read = [[False for j in range(m + 1)] for i in range(n + 1)] def is_on(i, j): if read[i][j]: ta.goals["decision_no_double_read"] = False read[i][j] = True p.check(1 <= i <= n, "row index out of range") p.check(1 <= j <= m, "column index out of range") return pirellone[i - 1][j - 1] with ta.run_algorithm(ta.submission.source) as p: res = bool(p.functions.is_solvable(n, m, callbacks=[is_on])) solvable = is_solvable(pirellone, n, m) if res == solvable: print("Correct!") return True if res: print( "You said that the pirellone was solvable, but it is not, take a look" ) else: print( "You said that the pirellone was not solvable, but it is, take a look" ) if n <= 50: print_pirellone(pirellone) send_pirellone_file(pirellone) return False
def test_case(A, B, C): print(f"testing case len(A) = {len(A)}, len(B) = {len(B)}\t", end="") with ta.run_algorithm(ta.submission.source) as p: try: p.procedures.merge(len(A), A, len(B), B, len(C)) res = [p.functions.getElement(i) for i in range(len(C))] for i in range(len(C)): if res[i] != C[i]: print( f"\nWrong merge at element {i}: expected {C[i]}, found {res[i]}" ) if len(C) <= 20: print(f"A array = {A}") print(f"B array = {B}") print(f"Your merge = {res}") print(f"Correct merge = {C}") return False except ta.AlgorithmError as e: print(f"\nError: {e}") return False print("CORRECT") return True
def test_case(N): with run_algorithm(submission.source) as p: res = p.che_mai_saralo_sto_numer() if res != N: print( "Il numero che avevo in mente era %d, non %d come da tè affermato." % (N, res)) goals[exponential_algorithm] = False goals[optimum_algorithm] = False if N <= 100: goals[polynomial_algorithm] = False operations_done = 0 n = N def se_mia_zero(): return n == 0 def se_mia_pari(): return n % 2 == 0 def caveghe_zo_uno(): nonlocal operations_done if n == 0: print( "Anna era partita col numero N=%d, ma ora, a seguito delle operazion che le avevi già richiesto, si ritrovava ora con uno zero. Ed ora gli chiedi di togliere uno? Questo non ti è consentito." % N) goals[exponential_algorithm] = False goals[optimum_algorithm] = False if N <= 100: goals[polynomial_algorithm] = False n -= 1 operations_done += 1 def dividi_par_do(): nonlocal operations_done if n % 2 == 1: print( "Anna era partita col numero N=%d, ma ora, a seguito delle operazion che le avevi già richiesto, si ritrovava ora con %n, un numero dispari. Non ti è consentito richiedere la divisione per due di un numero dispari." % (N, n)) goals[exponential_algorithm] = False goals[optimum_algorithm] = False if N <= 100: goals[polynomial_algorithm] = False n /= 2 operations_done += 1 res = p.che_mai_saralo_sto_numer(callbacks=[ caveghe_zo_uno, dividi_par_do, se_mia_pari_cio, se_mia_zero_ah ]) if res != N: print( "Anna era partita col numero N=%d, non col numero %d come restituito dalla tua funzione che_mai_saralo_sto_numer." % (N, res)) goals[exponential_algorithm] = False goals[optimum_algorithm] = False if N <= 100: goals[polynomial_algorithm] = False
def run (before, script, w, max_ants, g, interface_path = None): global goal goal = g build_enviroment (w, max_ants) before () try: with ta.run_algorithm (ta.submission.source, interface_path) as p: script (p) except ta.AlgorithmError as e: ta.goals[goal] = False print (e) ta.goals.setdefault(g, True) print(f"{g}: {ta.goals[g]}")
def run(algorithm, s): with ta.run_algorithm(algorithm, time_limit=0.05) as process: process.procedures.compute(len(s), s) subsequence_length = process.functions.max_length() subsequence = [ x for i, x in enumerate(s) if process.functions.takes(i) ] color = [] for i in range(len(s)): color.append(process.functions.color_of(i)) if DEBUG: print(f"Time usage: {process.time_usage}", file=sys.stderr) return (subsequence_length, subsequence, color)
def eval_solve(n, m): print(f"Getting solution for {n}x{m}") pirellone = random_pirellone(n, m, solvable=True) count = 0 read = [[False for j in range(m + 1)] for i in range(n + 1)] def is_on(i, j): nonlocal count if read[i][j]: ta.goals["solve_no_double_read"] = False read[i][j] = True count += 1 if count > n + m - 1: ta.goals["solve_minimum_reads"] = False p.check(1 <= i <= n, "row index out of range") p.check(1 <= j <= m, "column index out of range") return pirellone[i - 1][j - 1] def switch_row(i): i -= 1 for j in range(m): pirellone[i][j] = int(not pirellone[i][j]) def switch_col(j): j -= 1 for i in range(n): pirellone[i][j] = int(not pirellone[i][j]) with ta.run_algorithm(ta.submission.source) as p: p.procedures.solve(n, m, callbacks=[is_on, switch_row, switch_col]) solved = not any(any(pirellone[i][j] for j in range(m)) for i in range(n)) if not solved: print("You didn't turn off all the lights. Take a look") if n <= 50: print_pirellone(pirellone) send_pirellone_file(pirellone) else: print("Correct!") return solved
def evaluate(n): a, b = 1, n trials = 0 print(f"guess({a}, {b})... ") def answer(c): nonlocal a, b, trials trials += 1 p.check(trials <= ta.parameters.easy_max_trials, "too many guesses") assert a <= b if a == b == c: print("guessed correctly!") p.exit() if c < a: return +1 if c > b: return -1 if c < (a + b) / 2: a = c + 1 return +1 else: b = c - 1 return -1 try: with ta.run_algorithm(ta.submission.source) as p: p.procedures.guess(a, b, callbacks=[answer]) p.fail("procedure guess returned before guessing correctly") except ta.InterfaceExit: return trials except ta.AlgorithmError as e: print(f"{e}") return None assert False, "unexpected end"
def run_test_case(g): with ta.run_algorithm(ta.submission.source) as process: process.procedures.solve( g.order(), g.size(), [u for u, v in g.edges()], [v for u, v in g.edges()], ) cycle_len = process.functions.length() process.check(cycle_len <= ta.parameters['longest_allowed_walk'], f"cycle too long") cycle = [process.functions.get_node(i) for i in range(cycle_len)] print(f"Answer: {cycle}, checking...") for i in range(len(cycle)): u, v = cycle[i], cycle[(i + 1) % len(cycle)] process.check(g.has_edge(u, v), f"there is no edge ({u}, {v})") process.check(len(cycle) % 2 == 1, f"not in state 'SLURP'")
nx.gnm_random_graph(N, M - len(graph.edges())).edges()) for u, v, d in graph.edges(data=True): d["weight"] = random.randint(0, 1) assert len(graph.nodes()) <= MAXN assert len(graph.edges()) <= MAXM assert nx.is_connected(graph) #with ta.run_algorithm("solutions/correct.cpp") as p: # correct_output = p.functions.shortest_path( # len(graph.nodes()), # len(graph.edges()), # [u for u, v, w in graph.edges(data="weight")], # [v for u, v, w in graph.edges(data="weight")], # [w for u, v, w in graph.edges(data="weight")]) correct_output = nx.dijkstra_path_length(graph, 0, len(graph.nodes()) - 1) with ta.run_algorithm(submitted_solution) as p: output = p.functions.shortest_path( len(graph.nodes()), len(graph.edges()), [u for u, v, w in graph.edges(data="weight")], [v for u, v, w in graph.edges(data="weight")], [w for u, v, w in graph.edges(data="weight")]) if output == correct_output: print("correct! (%d == %d)" % (output, correct_output)) else: print("wrong (%d != %d)" % (output, correct_output))
import random import turingarena as ta for _ in range(10): z = random.randint(-500, 500) try: with ta.run_algorithm(ta.submission.source) as process: n = process.functions.rank(z) zz = process.functions.unrank(n) except ta.AlgorithmError as e: ta.goals["correct"] = False print(e) if z == zz: print( f"Correct! Hai codificato in numero intero {z} nel numero naturale {n} e la tua decodifica ti ha correttamente decodificato {n} come {zz}" ) else: ta.goals.setdefault("correct", False) print( f"Pias menga! Hai codificato in numero intero {z} nel numero naturale {n} ma poi, mi decodifichi {n} come {zz}, invece che tornarmi in {z}." ) ta.goals.setdefault("correct", True) print(ta.goals)
def test_case(n_u, n_v, m): print(f"\nEvaluating test case: N_U = {n_u}, N_V = {n_u}, M = {m}... " ) #)\t", end="") res = 1 N = n_u M = n_v # edges density edges = m # create random graph G = nx.bipartite.gnmk_random_graph(N, M, edges, seed=0xC0FFEE) # U is 0..N-1, V is N..N+M-1 U, V = range(0, N), range(N, N + M) try: with ta.run_algorithm(ta.submission.source, time_limit=0.15) as p: # build the graphs n1 = len(U) n2 = len(V) mG = edges u = [x for x, _ in sorted(G.edges)] v = [y for _, y in sorted(G.edges)] # initialize the H graph H = nx.DiGraph() H_edges = -1 flow_start = None flow_end = None def size_of_H(nH, mH): nonlocal H, H_edges if nH < 0: raise Exception('negative number of nodes') if mH < 0: raise Exception('negative number of edges') H.add_nodes_from(range(0, nH)) H_edges = mH def add_edge(u, v, w): nonlocal H, H_edges if len(H.edges) == H_edges: raise Exception('too many edges added with add_edge') if not H.has_node(u): raise Exception('invalid node u={}'.format(u)) if not H.has_node(v): raise Exception('invalid node v={}'.format(v)) H.add_edge(u, v, capacity=w) def set_s(s): nonlocal flow_start flow_start = s def set_t(t): nonlocal flow_end flow_end = t # the solution build H p.procedures.prepare_H_from_G( n1, n2, mG, u, v, callbacks=[size_of_H, add_edge, set_s, set_t]) # test that the information provided for H are consistent if flow_start is None: raise Exception('flow start not set (use set_s)') if flow_end is None: raise Exception('flow end not set (use set_t)') if len(H.edges) != H_edges: raise Exception('inconsistent number of edges') max_flow, flow = nx.algorithms.flow.maximum_flow( H, flow_start, flow_end) matching = [] cover_on_U = set() cover_on_V = set() def put_in_matching(u, v): nonlocal matching matching.append([u, v]) def put_in_node_cover_on_side_U(u): nonlocal cover_on_U cover_on_U.add(u) def put_in_node_cover_on_side_V(v): nonlocal cover_on_V cover_on_V.add(v) def flow_val(u, v): nonlocal flow return flow[u][v] p.procedures.max_card_matching_and_min_node_cover_in_G( n1, n2, mG, u, v, callbacks=[ put_in_matching, put_in_node_cover_on_side_U, put_in_node_cover_on_side_V, flow_val ]) print("Evaluating the matching... \t", end="") try: # check the matching if max_flow != len(matching): raise Exception('matching is not massimal') from_set = set() to_set = set() for u, v in matching: # is a valid edge if not G.has_edge(u, v): raise Exception('({},{}) is not an edge'.format(v, u)) # single matching for every node if u in from_set: raise Exception('multiple matching for u={}'.format(u)) from_set.add(u) if v in to_set: raise Exception('multiple matching for v={}'.format(v)) to_set.add(v) # The matching is correct print("[CORRECT]") res = res * 2 except Exception as e: print(f"[WRONG] \t error: {e}") print("Evaluating the node cover... \t", end="") try: # check the node cover if max_flow != (len(cover_on_U) + len(cover_on_V)): raise Exception('wrong size of cover, {} vs {}'.format( max_flow, (len(cover_on_U) + len(cover_on_V)))) for (x, y) in G.edges: if not x in cover_on_U and not y in cover_on_V: raise Exception('edges ({},{}) is not covered'.format( x, y)) # The node cover is correct print("[CORRECT]") res = res * 3 except Exception as e: print(f"[WRONG] \t error: {e}") # compute the minimum cut min_cut, partition = nx.algorithms.flow.minimum_cut( H, flow_start, flow_end) reachable, non_reachable = partition cutset = set() for u, nbrs in ((n, H[n]) for n in reachable): cutset.update((u, v) for v in nbrs if v in non_reachable) cutset = [(x, y) for x, y in cutset] iter_cut_left = 0 iter_cut_right = 0 cover_on_U = set() cover_on_V = set() def put_in_node_cover_on_side_U(u): nonlocal cover_on_U cover_on_U.add(u) def put_in_node_cover_on_side_V(v): nonlocal cover_on_V cover_on_V.add(v) def min_cut_value(): nonlocal min_cut return min_cut def next_in_min_cut_left(): nonlocal min_cut, iter_cut_left, cutset if iter_cut_left >= min_cut: raise Exception('cut left has only {} nodes'.format(n1)) iter_cut_left += 1 return cutset[iter_cut_left - 1][0] def next_in_min_cut_right(): nonlocal min_cut, iter_cut_right, cutset if iter_cut_right >= min_cut: raise Exception('cut right has only {} nodes'.format(n1)) iter_cut_right += 1 return cutset[iter_cut_right - 1][1] p.procedures.min_node_cover_from_min_cut( n1, n2, callbacks=[ put_in_node_cover_on_side_U, put_in_node_cover_on_side_V, min_cut_value, next_in_min_cut_left, next_in_min_cut_right ]) print("Evaluating the node cover... \t", end="") try: # check the node cover if max_flow != (len(cover_on_U) + len(cover_on_V)): raise Exception('wrong size of cover, {} vs {}'.format( max_flow, (len(cover_on_U) + len(cover_on_V)))) for (x, y) in G.edges: if not x in cover_on_U and not y in cover_on_V: raise Exception('edges ({},{}) is not covered'.format( x, y)) # The node cover is correct print("[CORRECT]") res = res * 5 except Exception as e: print(f"[WRONG] \t error: {e}") if DEBUG: print(f"Time usage: {p.time_usage}") except Exception as e: print(f"[WRONG] \t error: {e}") if res == 2 * 3 * 5: print(f"test case: N_U = {n_u}, N_V = {n_u}, M = {m} [PASSED]") else: print(f"test case: N_U = {n_u}, N_V = {n_u}, M = {m} [FAILED]") return res
def test_case(m, n, Sr, Sc): def turn_off_tell_max_goal_flags(m, n): if m <= 100 and n <= 100: ta.goals["tell_max"] = False ta.goals["tell_max_huge"] = False def turn_off_tell_min_goal_flags(m, n): if m <= 100 and n <= 100: ta.goals["tell_min"] = False ta.goals["tell_min_huge"] = False cert_NOTtransv_given = False cert_NOTtransv_ok = None def exhibit_untouched_tile(row, col, dir): nonlocal cert_NOTtransv_given nonlocal cert_NOTtransv_ok nonlocal Sr nonlocal Sc cert_NOTtransv_given = True cert_NOTtransv_ok = True if row < 1 or col < 1 or row > m or col > n: print( f"La tessera che proponi di inserire nel transversal fuoriesce dalla scacchiera nella cella ({row},{col})." ) cert_NOTtransv_ok = False return if dir == H: cells = [[row, col], [row, col + 1], [row, col + 2]] else: cells = [[row, col], [row + 1, col], [row + 2, col]] for cell in cells: if cell in zip(Sr, Sc): print( f"La tessera che proponi come certificato che S non è un transversal è invece colpita da S nella cella ({row},{col})." ) cert_NOTtransv_ok = False print(f"case (m={m}, n={n}, Sr={Sr}, Sc={Sc})") with ta.run_algorithm("solutions/solution.py") as ref: expected_is = ref.functions.is_transversal( m, n, len(Sr), Sr, Sc, callbacks=[exhibit_untouched_tile]) expected_min = ref.functions.min_card_of_a_transversal(m, n) expected_max = ref.functions.max_card_of_a_packing(m, n) ######## TRANSVERSAL RECOGNITION EVALUATION ######## cert_NOTtransv_given = False cert_NOTtransv_ok = None with ta.run_algorithm(ta.submission.source) as p: try: with p.section(time_limit=0.1): returned_is = p.functions.is_transversal( m, n, len(Sr), Sr, Sc, callbacks=[exhibit_untouched_tile]) except ta.AlgorithmError as e: print( f"During the execution of your is_transversal({m},{n},{len(Sr)},{Sr},{Sc}) function we got the following exception:" ) print(e) ta.goals["is_transversal"] = False ta.goals["cert_NOTtransv"] = False else: print( f"From your is_transversal({m},{n},{len(Sr)},{Sr},{Sc}) function we expected {expected_is}, got {returned_is}" ) if returned_is == expected_is: print("OK. The two values coincide.") if returned_is: if (not cert_NOTtransv_given) or (not cert_NOTtransv_ok): ta.goals["cert_NOTtransv"] = False print( "However, we require you to also exhibit a possible placement of one tile avoiding the cells of S. This is convenient certificate that S is not a transveral. Please tell us where to put this tile." ) else: print( "NO. The two values differ. You should revise your is_transversal function." ) ta.goals["is_transversal"] = False ta.goals["cert_NOTtransv"] = False ######## MIN CARD OF A TRANSVERSAL EVALUATION ######## try: with p.section(time_limit=0.002): returned_min = p.functions.min_card_of_a_transversal(m, n) except ta.AlgorithmError as e: print( f"During the execution of your function min_card_of_a_transversal({m},{n}) we got the following exception:" ) print(e) turn_off_tell_min_goal_flags(m, n) else: print( f"From your min_card_of_a_transversal({m},{n}) function we expected {expected_min}, got {returned_min}" ) if returned_min == expected_min: print("OK. The two values coincide.") else: turn_off_tell_min_goal_flags(m, n) if returned_min < expected_min: print( f"We disbelieve the {m}x{n}-grid admits a transversal of only {returned_min} cells. Are you sure you can produce one?\n In case you can exhibit such a transversal, please contact turingarena.org, we look forward to see it." ) else: print( f"The {m}x{n}-grid admits smaller transversals of only {expected_min} cells. If you disbelieve this and/or need help to advance, have a look at the transversal offered in the highly spoiling file: ... " ) offer_a_min_transversal(m, n) ######## MAX CARD OF A PACKING EVALUATION ######## try: with p.section(time_limit=0.002): returned_max = p.functions.max_card_of_a_packing(m, n) except ta.AlgorithmError as e: print( f"During the execution of your function max_card_of_a_packing({m},{n}) we got the following exception:" ) print(e) turn_off_tell_max_goal_flags(m, n) else: print( f"From your max_card_of_a_packing({m},{n}) function we expected {expected_max}, got {returned_max}" ) if returned_max == expected_max: print("OK. The two values coincide.") else: turn_off_tell_max_goal_flags(m, n) if returned_max > expected_max: print( f"We disbelieve you can pack {returned_max} 1,3-bars within a {m}x{n}-grid. Are you sure?\n In case you can exhibit such a packing, please contact turingarena.org, we look forward to see it." ) else: print( f"You can actually pack up to {expected_max} 1,3-bars within a {m}x{n}-grid. If you disbelieve this and/or need help, have a look at the packing offered in the file: ... " ) offer_a_max_packing(m, n) ######## BEGIN TRANSVERSAL CONSTRUCTION VERIFICATION ######## trans_construction_ok = True placed_in_S = 0 S = [[False for _ in range(n + 1)] for _ in range(m + 1)] def place_in_S(row, col): nonlocal trans_construction_ok nonlocal placed_in_S nonlocal S placed_in_S += 1 if row < 1 or col < 1 or row > m or col > n: print( f"La cella che proponi di inserire nel transversal fuoriesce dalla scacchiera nella cella ({row},{col})." ) trans_construction_ok = False return if S[row][col]: print( f"Hai già inserito la cella ({row},{col}) nel transversal." ) trans_construction_ok = False S[row][col] = True try: print( "[mostra il transversal (fino all'eventuale errore), magari in un file esterno da scaricare od un applet]" ) with p.section(time_limit=0.2): p.procedures.produce_min_transversal(m, n, callbacks=[place_in_S]) except ta.AlgorithmError as e: print( f"During the execution of your procedure produce_min_transversal({m},{n}) we got the following exception:" ) print(e) ta.goals["min_transversal"] = False else: if trans_construction_ok: def isTransversal(S, m, n): for i in range(1, m + 1): for j in range(1, n - 1): intersects = 0 for k in range(3): if S[i][j + k]: intersects += 1 if intersects == 0: return False for i in range(1, m - 1): for j in range(1, n + 1): intersects = 0 for k in range(3): if S[i + k][j]: intersects += 1 if intersects == 0: return False return True if isTransversal(S, m, n): if placed_in_S == expected_min: print( f"Complimenti! Il tuo transversal per la griglia ({m},{n}) è corretto ed ottimo." ) else: ta.goals["min_transversal"] = False print( f"NO: hai collocato solo {placed_in_S} tessere contro le {expected_max} possibili. Di positivo: l'insieme di celle S composto dalla tua procedura produce_min_transversal({m},{n}) è effettivamente un transversal per quella griglia." ) else: ta.goals["min_transversal"] = False print( f"NO: l'insieme S = {S} costruito dalla tua procedura produce_min_transversal({m},{n}) NON è un transversal per quella griglia." ) else: ta.goals["min_transversal"] = False ######## END TRANSVERSAL CONSTRUCTION VERIFICATION ######## ######## BRGIN PACKING CONSTRUCTION VERIFICATION ######## pack_construction_ok = True posed_tiles = 0 covered = [[False for _ in range(n + 1)] for _ in range(m + 1)] lista_tiles = [] def place_tile(row, col, dir): nonlocal pack_construction_ok nonlocal posed_tiles nonlocal covered nonlocal lista_tiles lista_tiles.append((row, col, dir)) posed_tiles += 1 if dir == H: cells = [[row, col], [row, col + 1], [row, col + 2]] else: cells = [[row, col], [row + 1, col], [row + 2, col]] for cell in cells: row = cell[0] col = cell[1] if row < 1 or col < 1 or row > m or col > n: print( f"La tua tessera fuoriesce dalla scacchiera nella cella ({row},{col})." ) pack_construction_ok = False return if covered[row][col]: print( f"Due delle tue tegole coprono la cella ({row},{col})." ) pack_construction_ok = False covered[row][col] = True try: with p.section(time_limit=0.2): p.procedures.produce_max_packing(m, n, callbacks=[place_tile]) except ta.AlgorithmError as e: print( f"During the execution of your procedure produce_max_packing({m},{n}) we got the following exception:" ) print(e) ta.goals["max_packing"] = False else: if pack_construction_ok: if posed_tiles == expected_max: print( f"Complimenti! Il tuo packing della griglia ({m},{n}) è corretto ed ottimo." ) else: ta.goals["max_packing"] = False print( f"NO: hai collocato solo {posed_tiles} tessere contro le {expected_max} possibili. Di positivo: non sei uscito dalla griglia ({m},{n}) e non hai sovrapposto tessere. Nessun conflitto." ) print( "[vuoi vedere il packing generato dalla tua procedura? File esterni da scaricare: visualizzazione statica in grafica vettoriale e ASCII solo log delle piastelle da usare per debug e visualizzabile in un'applet]" ) else: print("mostra il packing fino all'errore: ", lista_tiles) ta.goals["max_packing"] = False
def test_correct_solution(): with ta.run_algorithm("solutions/correct.cpp") as p: assert p.functions.sum(3, 5) == 8
def test_with_seq(seq): def turn_off_goals(): ta.goals["correct"] = False ta.goals["correct_C_is_2"] = False ta.goals["correct_C_is_1dot1"] = False encoded_seq = [] decoded_seq = [] try: with ta.run_algorithm(ta.submission.source) as process: process.procedures.get_original_string(len(seq), seq) encoded_len = process.functions.tell_encoded_string_length() for i in range(encoded_len): encoded_seq.append( process.functions.tell_encoded_string_ith_char(i)) except ta.AlgorithmError as e: turn_off_goals() print(e) try: with ta.run_algorithm(ta.submission.source) as process: process.procedures.get_encoded_string(len(encoded_seq), encoded_seq) decoded_len = process.functions.tell_original_string_length() for i in range(decoded_len): decoded_seq.append( process.functions.tell_original_string_ith_char(i)) except ta.AlgorithmError as e: turn_off_goals() print(e) print(f"The string to be encoded was:\n {seq}") print(f"You encoded it with:\n {encoded_seq}") all_allowed_keys = True wrong_key = None wrong_pos = None for pos, val in zip(range(len(encoded_seq)), encoded_seq): if val not in allowed_keys: turn_off_goals() all_allowed_keys = False wrong_key = val wrong_pos = pos break if not all_allowed_keys: print( f"NO: Use of key '{wrong_key}' forbidden in the encoded sequence. You used it in position {wrong_pos} (positions start from 0)." ) else: print("OK. You only used allowed keys. Good!") print(f"Which you decoded as:\n {decoded_seq}") if len(decoded_seq) != len(seq): turn_off_goals() print( f"NO: Notice that the lengths of the original sequence (which contained {len(decoded_seq)} charactes over the alphabet {'0','1','2','3','4','5','6','7','8','9','-1'}) and the decoded one (which contains {len(seq)} numbers over the same alphabet {'0','1','2','3','4','5','6','7','8','9','-1'}) differ." ) are_equal = True for i in range(len(seq)): if seq[i] != decoded_seq[i]: turn_off_goals() are_equal = False break if not are_equal: print( f"NO: The original sequence and the decoded one differ in position {i}, where the original reports a '{seq[i]}' character and the decoded reports a '{decoded_seq[i]}' character." ) else: print( "OK. You correctly reconstructed the original sequence. Congrats!") if len(seq) > 0: return (len(decoded_seq) - 3) / len(seq) else: return 1.0
def test_case(n, m, is_sat): print(f"\nEvaluating test case: N = {n}, M = {m} SAT={is_sat}... ") res = 1 # edges density (a,b) = generate_random_formula(n,m,is_sat) try: with ta.run_algorithm(ta.submission.source, time_limit=0.15) as p: # initialize the H graph G = nx.DiGraph() G_edges = 0 def size_of_G(nG,mG): nonlocal G, G_edges if nG < 0: raise Exception('negative number of nodes') if mG < 0: raise Exception('negative number of edges') G.add_nodes_from(range(0,nG)) G_edges = mG def add_edge(u,v): nonlocal G, G_edges if len(G.edges) == G_edges: raise Exception('too many edges added with add_edge') if not G.has_node(u): raise Exception( 'in function add_edge. Invalid node u={}'.format(u)) if not G.has_node(v): raise Exception( 'in function add_edge. Invalid node v={}'.format(v)) G.add_edge(u,v) print("Evaluating the satisfiability... ", end="") # the solution build G p.procedures.prepare_G(n,m,a,b, callbacks=[ size_of_G, add_edge ]) assignments = [-1]*(n+1) n_of_assignments = 0 def assign_variable(letteral,value): nonlocal n, n_of_assignments, assignments if letteral > n: raise Exception('in function assign_variable. Invalid letteral {}'.format(letteral)) if assignments[letteral] != -1: raise Exception('multiple assignments for letteral {}'.format(letteral)) assignments[letteral] = False if value <= 0 else True n_of_assignments = n_of_assignments + 1 nG = len(G) components = [-1] * nG comp = 0 # generate strongly connected components in reverse topological order scc = nx_comp.strongly_connected_components_recursive(G) # assigns components in topologigical order for C in reversed(list(scc)): for node in C: components[node] = comp comp += 1 ris = p.functions.is_satisfiable(nG,components, callbacks=[ assign_variable ]) if ris <= 0: ris = False else: ris = True if ris != is_sat: print("[WRONG]") if ris: raise Exception('The formula is unsatisfiable, but you claim that is satisfiable') else: raise Exception('The formula is satisfiable, but you claim that is not satisfiable') print("[CORRECT]") res *= 2 # nothing to do for unsat instances if not is_sat: return res print("Evaluating the assignments... \t", end="") try: # check the assignment if n_of_assignments != n: raise Exception('you assigned less letterals than those in the formula') result = True; for i in range(m): letteral_a = abs(a[i]) letteral_b = abs(b[i]) dir_a = False if a[i] < 0 else True dir_b = False if b[i] < 0 else True if (assignments[letteral_a] != dir_a and assignments[letteral_b] != dir_b): raise Exception('the assignment is not a model. The assignments {}={} and {}={}, falsifies the clausole ({} v {})'.format( letteral_a,assignments[letteral_a],letteral_b,assignments[letteral_b],a[i],b[i])) # The assignement is correct print("[CORRECT]") res = res * 3 except Exception as e: print(f"[WRONG] \t error: {e}") except Exception as e: print(f"[WRONG] \t error: {e}") if res == 2*3: print(f"test case: N = {n}, M = {m} [PASSED]") else: print(f"test case: N = {n}, M = {m} [FAILED]") return res
def evaluate_testcase(input_necklace_colors): #print(f"Testing with n = {len(input_necklace)} necklace = {input_necklace} ...", end=" ") print(f"Testing with a necklace of {len(input_necklace)} beads ...", end=" ") def num_breakpoints(necklace_colors): risp = 0 if necklace_colors[len(necklace_colors) - 1] != necklace_colors[0]: risp += 1 for pos in range(len(necklace_colors) - 1): if necklace_colors[pos] != necklace_colors[pos + 1]: risp += 1 return risp n = len(input_necklace_colors) current_necklace_colors = input_necklace_colors[:] current_necklace_names = list(range(1, n + 1)) pos_of_bead = [None] + list(range(n)) def reverse_integral(a_name, b_name): #print(f"Evaluator reverse_integral(a_name={a_name},b_name={b_name})") nonlocal current_necklace_colors, current_necklace_names, pos_of_bead def swap(a_pos, b_pos): #print(f"Evaluator swap(a_pos={a_pos},b_pos={b_pos})") nonlocal current_necklace_colors, current_necklace_names, pos_of_bead pos_of_bead[current_necklace_names[b_pos]] = a_pos pos_of_bead[current_necklace_names[a_pos]] = b_pos tmp = current_necklace_names[a_pos] current_necklace_names[a_pos] = current_necklace_names[b_pos] current_necklace_names[b_pos] = tmp tmp = current_necklace_colors[a_pos] current_necklace_colors[a_pos] = current_necklace_colors[b_pos] current_necklace_colors[b_pos] = tmp a_pos = pos_of_bead[a_name] b_pos = pos_of_bead[b_name] finished = False while not finished: swap(a_pos, b_pos) a_pos = (a_pos + 1) % n if a_pos == b_pos: finished = True b_pos = (b_pos - 1 + n) % n if a_pos == b_pos: finished = True try: def reverse_interval(a_name, b_name): nonlocal num_made_moves, n #print(f"reverse_interval(a = {a_name}, b={b_name}) called.") if a_name < 0 or a_name > n or b_name < 0 or b_name > n: print( f"WRONG: The call reverse_interval(a = {a_name}, b={b_name}) is not valid." ) ta.goals.setdefault("solve_in_any_number_of_moves", False) ta.goals.setdefault("at_most_n2_moves", False) ta.goals.setdefault("opt_solve", False) ta.goals.setdefault("linear_time", False) else: num_made_moves += 1 reverse_integral(a_name, b_name) #expected_answer = (num_breakpoints(input_necklace_colors)-2)/2 with ta.run_algorithm("solutions/only_num_moves_correct.c") as p: expected_answer = p.functions.necklace( len(input_necklace), input_necklace, callbacks=[reverse_interval]) # print(f"The reference solution says that the minimum number of moves is {expected_answer}") num_made_moves = 0 with ta.run_algorithm(ta.submission.source) as p: obtained_answer = p.functions.necklace( len(input_necklace), input_necklace, callbacks=[reverse_interval]) except ta.AlgorithmError as e: print(f" error: {e}") ta.goals.setdefault("correct_num_moves", False) ta.goals.setdefault("solve_in_any_number_of_moves", False) ta.goals.setdefault("at_most_n2_moves", False) ta.goals.setdefault("opt_solve", False) ta.goals.setdefault("linear_time", False) print(f"(time: {int(p.time_usage * 1000000)} us)") if obtained_answer == expected_answer: print(f" Correct minimum number of moves!", end=" ") else: ta.goals.setdefault("correct_num_moves", False) print( f"We disagree on the minimum number of moves needed to solve the necklace {input_necklace}. Your answer is {obtained_answer} while we believe the correct number is {expected_answer}.", end=" ") if num_breakpoints(current_necklace_colors) > 2: ta.goals.setdefault("solve_in_any_number_of_moves", False) ta.goals.setdefault("at_most_n2_moves", False) ta.goals.setdefault("opt_solve", False) ta.goals.setdefault("linear_time", False) if num_made_moves == 0: print(f" Your solution did no move.") else: print( f"Starting from the necklace {input_necklace_colors} your solution ends up with the necklace {current_necklace_colors} which is NOT entirely solved!", end=" ") else: if expected_answer > 0: print(f"Correct: your procedure fully solved the necklace.") else: print( f"Correct: no move was needed and no move was done by your code." ) if num_made_moves > n * n: print(f"But used quite a lot of moves.") ta.goals.setdefault("at_most_n2_moves", False) ta.goals.setdefault("linear_time", False) if int(p.time_usage * 1000000) > 2000: print( f"Your procedure is too slow. There exists a linear time solution to this problem." ) ta.goals.setdefault("linear_time", False)
def test_case(m, n): def turn_off_construction_goal_flags(m, n): if m == 1: ta.goals["construction_m1"] = False if m <= 10 and n <= 10: ta.goals["construction_small"] = False ta.goals["construction"] = False def turn_off_decision_goal_flags(m, n): if m == 1: ta.goals["decision_m1"] = False if m <= 10 and n <= 10: ta.goals["decision_small"] = False if m <= 100 and n <= 100: ta.goals["decision"] = False ta.goals["decision_huge"] = False with ta.run_algorithm(ta.submission.source) as p: print(f"case (m={m}, n={n})") try: res = p.functions.is_tilable(m, n) except ta.AlgorithmError as e: print( f"During the execution of your function is_tilable({m},{n}) we got the following exception:" ) print(e) turn_off_decision_goal_flags(m, n) else: print( f"From your is_tilable({m},{n}) function we expected {1 - (m % 2) * (n %2 )}, got {res}" ) if res == 1 - (m % 2) * (n % 2): print("OK. The two values coincide.") else: turn_off_decision_goal_flags(m, n) if res == 0: turn_off_construction_goal_flags(m, n) print( f"According to your is_tilable function, the {m}x{n}-grid is not tilable with dominos. However, we believe it is! Be aware that dominos can be placed either vertically or horizzontally, at your will (that is, they can cover either 1x2-subgrids or 2x1-subgrids of the {m}x{n}-grid). If you disbelieve the {m}x{n}-grid is tilable and/or need help to advance, have a look at the tiling offered in the spoiling solution file: ... " ) offer_a_tiling(m, n) if res != 0: print( f"According to your is_tilable function, the {m}x{n}-grid is tilable. Are you sure?\n In case you can exhibit such a tiling, please contact turingarena.org, we look forward to see it." ) if (m % 2) * (n % 2) == 1 or res == 0 or m > 100 or n > 100: return # BEGIN: testing of the procedure constructing the tiling print( f"Ok, since we agree the tiling exists, and an ({m},{n})-board is still reasonably small, let's find out whether your code can actually construct the tiling and measure its efficiency." ) construction_ok = True posed_tiles = 0 covered = [[False for _ in range(n + 1)] for _ in range(m + 1)] lista_tiles = [] def place_tile(row, col, dir): nonlocal construction_ok nonlocal posed_tiles nonlocal covered nonlocal lista_tiles lista_tiles.append((row, col, dir)) posed_tiles += 1 if dir == H: cells = [[row, col], [row, col + 1]] else: cells = [[row, col], [row + 1, col]] for cell in cells: row = cell[0] col = cell[1] if row < 1 or col < 1 or row > m or col > n: print( f"La tua tessera fuoriesce dalla scacchiera nella cella ({row},{col})." ) construction_ok = False return if covered[row][col]: print( f"Due delle tue tegole coprono la cella ({row},{col})." ) construction_ok = False covered[row][col] = True try: print( "[mostra il tiling (fino all'eventuale errore), magari in un file esterno da scaricare od un applet]" ) p.procedures.compose_tiling(m, n, callbacks=[place_tile]) except ta.AlgorithmError as e: print( f"During the execution of your procedure compose_tiling({m},{n}) we got the following exception:" ) print(e) turn_off_construction_goal_flags(m, n) else: if construction_ok: if 2 * posed_tiles == m * n: print( f"Complimenti! Hai riempito perfettamente la griglia ({m},{n}). Il tuo tiling è corretto." ) else: print( f"NO: non hai ricoperto l'intera griglia ({m},{n}). Hai collocato solo {posed_tiles} tessere. Di positivo: non sei uscito dalla griglia ({m},{n}) e non hai sovrapposto tessere. Nessun conflitto." ) offer_a_tiling(m, n) print( f"Hai fornito un packing corretto ma esso non è un tiling perfetto quindi non mi è ovvio esso sia ottimo. Per ora mi hai convinto che esista un packing di almeno {posed_tiles}, ossia mi hai dato un lower-bound sul valore ottimo del packing. In esercizi successivi di questo percorso apprenderai come fornire argomenti a supporto dell'ottimalità dei tuoi packing e andiamo a vedere quanto è buono l'upper-bound che sai fornirmi. Tuttavia in questo caso (m={m} e n={n}) esiste un tiling ottimo. Quindi prendiamo per NON buono il packing che hai qui prodotto." ) turn_off_construction_goal_flags(m, n) print( "[vuoi vedere come la tua procedura ha collocato le piastrelle? In questo punto potremmo mettere il tiling prodotto dalla tua procedura dentro in file esterni che il problem-solver possa scaricarsi: sarebbe bella una visualizzazione statica in grafica vettoriale, con le piastrelle numerate nell'ordine di posatura, ma anche un ASCII con solo il log della sequenza delle chiamate a pose_tile da usare per eventuale debug, e comunque visualizzabile in un'applet. Come vedi, ci sono mille modi in cui puoi contribuire a rendere TA piu ricco ed interattivo. Se anche tu come noi pensi 'We don't need no education' non esistare: richiedi progetti e 'brake on through to the other side'.]" ) else: print("mostra il tiling fino all'errore: ", lista_tiles) turn_off_construction_goal_flags(m, n)
print( f"Correct! Certificato verificato: come divisore comune hai fornito un numero valido ({d})." ) def give_multipliers(x, y): if x * a + y * b != 1: print( f"WRONG: Fornisci due moltiplicatori x={x} ed y={y} per i quali non vale che x*a + y*b = 1." ) ta.goals["correct_YES_certificate"] = False else: print( f"Correct! Certificato verificato: come moltiplicatori hai fornito x={x} e y={y} ed ho verificato che x*a + y*b = 1." ) with ta.run_algorithm("solutions/correct.py") as p: expected_answer = p.functions.are_coprime( a, b, callbacks=[give_divisor, give_multipliers]) with ta.run_algorithm(ta.submission.source) as p: obtained_answer = p.functions.are_coprime( a, b, callbacks=[give_divisor, give_multipliers]) except ta.AlgorithmError as e: print(f" error: {e}") ta.goals.setdefault("correct_answer", False) ta.goals.setdefault("correct_NO_certificate", False) ta.goals.setdefault("correct_YES_certificate", False) if obtained_answer == 0: print(f" your answer: {a} and {b} are NOT coprime", end="") else: