def main(): lines = open_data("13.data") wait = int(lines[0]) earliest = 0 earliest_id = 0 for b in ints(lines[1]): ap = wait // b + 1 if ap * b < earliest or earliest == 0: earliest = ap * b earliest_id = b print((earliest - wait) * earliest_id) busses = [(int(t), i) for i, t in enumerate(lines[1].split(",")) if t != "x"] # unzip list of tuples in to two lists with the elements remainder, modulos = unzip(busses) # So I can search for it later: chinese remainder theorem, CRT, crt, Chinese Remainder Theorem. a, b = crt(remainder, modulos) # WHY do I need to substract the first (actual) result from the second something??? print(b - a)
def poly_mult(A, B): # Pad L = next_pow2(len(A) + len(B)) while len(A) < L: A.append(0) while len(B) < L: B.append(0) # FFT for each prime list_C = [] for p in primes: a = A[:] b = B[:] for i in range(L): a[i] %= p b[i] %= p list_C.append(poly_mult_prime(a, b, p)) # Solve congruences to get actual C L = len(list_C[0]) C = [0 for _ in range(L)] for i in range(L): cong = [] for j in range(num_primes): cong.append(list_C[j][i]) val, mod = crt(primes, cong, check=False) C[i] = int(val % mod) % N # Unpad while C[-1] == 0: C.pop() # print(A, '*', B, '=', C) return C
def library_CRT(e, d, p, q, y): """ Chinese Remainder Theorem as performed with python's preexisting methods :param e: :param d: :param p: :param q: :param y: :return: result + time """ # time: start = time.time() x_q = library_modular_exponentiation(y % q, d % (q - 1), q) # Hensel: x0 = library_modular_exponentiation(y % p, d % (p - 1), p) x1 = (((y - library_modular_exponentiation(x0, e, p * p)) / p) * library_modular_inverse( e * library_modular_exponentiation(x0, e - 1, p * p), p)) % p x_p2 = int((x1 * p + x0) % (p * p)) # for CRT: moduli = [p * p, q] residues = [x_p2, x_q] return crt(moduli, residues)[0], time.time() - start
def as_subindex(self, index): # The docstring of this method is currently on NDindex.as_subindex, as # this is the only method that is actually implemented so far. from .ndindex import ndindex index = ndindex(index) if not isinstance(index, Slice): raise NotImplementedError( "Slice.as_subindex is only implemented for slices") s = self.reduce() index = index.reduce() if s.step < 0 or index.step < 0: raise NotImplementedError( "Slice.as_subindex is only implemented for slices with positive steps" ) # After reducing, start is not None when step > 0 if index.stop is None or s.stop is None or s.start < 0 or index.start < 0 or s.stop < 0 or index.stop < 0: raise NotImplementedError( "Slice.as_subindex is only implemented for slices with nonnegative start and stop. Try calling reduce() with a shape first." ) # Chinese Remainder Theorem. We are looking for a solution to # # x = s.start (mod s.step) # x = index.start (mod index.step) # # If crt() returns None, then there are no solutions (the slices do # not overlap). res = crt([s.step, index.step], [s.start, index.start]) if res is None: return Slice(0, 0, 1) common, _ = res lcm = ilcm(s.step, index.step) start = max(s.start, index.start) def _smallest(x, a, m): """ Gives the smallest integer >= x that equals a (mod m) Assumes x >= 0, m >= 1, and 0 <= a < m. """ n = int(math.ceil((x - a) / m)) return a + n * m # Get the smallest lcm multiple of common that is >= start start = _smallest(start, common, lcm) # Finally, we need to shift start so that it is relative to index start = (start - index.start) // index.step step = lcm // index.step # = s.step//igcd(s.step, index.step) stop = math.ceil((min(s.stop, index.stop) - index.start) / index.step) if stop < 0: stop = 0 return Slice(start, stop, step)
def part2(input): bus_times = input[1] conditions = [] for offset, bus_time in enumerate(bus_times): if bus_time == "x": continue else: conditions.append((int(bus_time), offset)) conditions = sorted(conditions, key=lambda x: -x[1]) n, a = zip(*conditions) a = [-num for num in a] for bus_time, offset in conditions: print(f"(t + {offset}) mod {bus_time} = 0", end=", ") print() print(crt(n, a)) cur_num = -conditions[0][1] # initial offset increase = conditions[0][0] for bus_time, offset in conditions[1:]: rest = (cur_num + offset) % bus_time not_done = rest != 0 while not_done: cur_num += increase rest = (cur_num + offset) % bus_time not_done = rest != 0 increase *= bus_time return cur_num
def SilverPohligHellman(base, gen, element): # El orden del generador es el cardinal de todos los elementos menos el 0 order = base - 1 # Si no tenemos el generador o la base correctos... if base != BASE or gen != GEN: # Generamos las raíces que usaremos GenerateSquareRoots(base, gen) # Lista de restos y subbases subbases = [] remainders = [] # Buscamos el logaritmo for i in P_FACTS: # Inicialmente el exponente es 0 exp = 0 # Recorremos los posibles valores en los que p_i^j es divisor de n for j in range(P_FACTS[i]): y = element * FastExp(gen, order - exp, base) x = ROOTS[i][FastExp(y, order / (i**(j + 1)), base)] exp += x * i**j # Añadimos la ecuación con congruencias subbases.append(i**P_FACTS[i]) remainders.append(exp) # Resolvemos el sistema de congruencias return crt(subbases, remainders)[0]
def chinesereminder(): #accepting positive integer a,b,c and r,s,t from user print("Enter the values for divisors A,B,C and remainders R,S,T:-") a = input('A:') b = input('B:') c = input('C:') r = input('R:') s = input('S:') t = input('T:') a = int(a) b = int(b) c = int(c) r = int(r) s = int(s) t = int(t) if r > 0 and s > 0 and t > 0 and a > 0 and b > 0 and c > 0: #checking for pairwaise relatively prime integers if math.gcd(r, s) == 1 and math.gcd(s, t) == 1 and math.gcd(r, t) == 1: x = [r, s, t] y = [a, b, c] final_value = crt(x, y) #crt print("Result of the Chinese Remainder Theorem = {} ".format( final_value[0])) else: print("Something went wrong. Please enter the input again") #return print("Enter 'Y' to go back to menu and 'E' to exit") user_input = input("Enter your choice as 'Y' or 'E': ") if user_input == "Y": menu() elif user_input == "E": exit()
def main(): t, *busses = [ int(x) for x in open(file).read().replace('x', '1').replace( '\n', ',').split(',') ] m, r = zip(*((b, b - i) for i, b in enumerate(busses) if b > 1)) print(crt(m, r)[0])
def main(): """ parse input data: second line has the busIDs and x's, convert the busIDs to integers and make a list, """ data = open('data.txt', 'r') lines = data.read().split() busses = lines[1].split(',') for i in range(len(busses)): if (busses[i] != 'x'): busses[i] = int(busses[i]) """ create system of linear congruencies: at timestamp t every bus has to come in i minutes, i being the position of the bus in the list therefore, at t the following equation has to be true: busID-i=t mod busID we can solve this system of equations using the chinese remainder theorem. The solution is our timestamp t """ busID = [] value_at_timestamp = [] for i, bus in enumerate(busses): if (bus != 'x'): busID = busID + [bus] value_at_timestamp = value_at_timestamp + [(bus - i) % bus] print( "The earliest timestamp at which all listed busIDs depart at offsets matching their position in the list is:\nt =", crt(busID, value_at_timestamp)[0])
def part2(s: str) -> int: line = s.splitlines()[1] buses = [(i, int(x)) for i, x in enumerate(line.split(",")) if x != "x"] bus_ids = [bus[1] for bus in buses] mods = [-1 * bus[0] for bus in buses] return crt(bus_ids, mods)[0]
def try_random_residue(): res = pow(randint(1, max_x), 2, n) try: rev_res = int(crt((res, n), (0, 1))[0]) // res return res, rev_res except (ZeroDivisionError, TypeError): return None
def solver(s: str) -> int: bus_ids = [(int(bus), i) for i, bus in enumerate(s.splitlines()[1].split(",")) if bus != "x"] busses = [b[0] for b in bus_ids] final = [-1 * b[1] for b in bus_ids] return crt(busses, final)[0]
def part2(data): (est, ids) = data.splitlines() est = int(est) nums = [(int(x), -i) for i, x in enumerate(ids.split(",")) if x != "x"] print(nums) ids, times = zip(*nums) # chinese remainder theorem return crt(ids, times)[0]
def main(): est = int(input()) times = [x for x in input().split(",")] nums = [int(t) for t in times if t != "x"] mods = [int(times[i]) - i for i in range(len(times)) if times[i] != "x"] # realizing i needed the chinese remainder theorem was a challenge in itself # i decided i'd earned the right to "cheat" by importing an implementation print(crt(nums, mods)[0])
def compute(s: str) -> int: lines = s.splitlines() parsed = [(int(s), i) for i, s in enumerate(lines[1].split(',')) if s != 'x'] buses = [pt[0] for pt in parsed] mods = [-1 * pt[1] for pt in parsed] return crt(buses, mods)[0]
def find_open_key(p, gx): """ Используя китайскую теорему об остатках, найдём у из открытого ключа :param p: p из открытого ключа :param gx: g**x, x - секретный ключ :return: y """ return int(crt((gx, p), (0, 1))[0]) // gx
def part_2(): _, buses = utils.get_input(__file__, delimiter=None, cast=str) buses, offsets = zip(*[(int(bus), -1 * i) for i, bus in enumerate(buses.split(',')) if bus != 'x']) print(crt(buses, offsets)[0])
def find_lambda(numerator, denominator, n): """ Вычисление значения l = numerator/denominator (mod n) :return: l """ left = positive_mod(denominator, n) right = positive_mod(numerator, n) return int(crt((left, n), (0, right))[0] // left)
def p2crt(): desc = lines[1].split(",") buses = [(i, int(x)) for i, x in enumerate(desc) if x != "x"] mods = [b[1] - b[0] for b in buses] divs = [b[1] for b in buses] print("p2crt:", crt(divs, mods)[0])
def part2(): bus_ids = map(int, all_lines[1].replace("x", "-1").split(",")) ids = [(bus_id, -offset) for offset, bus_id in enumerate(bus_ids) if bus_id != -1] ids = zip(*ids) m = list(next(ids)) v = list(next(ids)) (x, _) = crt(m, v, check=False) print(x)
def part_two(data): modulii = list() remainders = list() for idx, id_ in data[1].items(): modulii.append(id_) remainders.append(-idx % id_) return crt(modulii, remainders)[0]
def part2(busses): coprimes = [] modulos = [] for i, bus in enumerate(busses): if bus != 'x': coprimes.append(int(bus)) modulos.append(i) a, b = crt(coprimes, modulos) return b - a
def find_consecutive_offsets(depart_ids_with_unknowns): id_position = { int(bus_id): depart_ids_with_unknowns.index(bus_id) for bus_id in depart_ids_with_unknowns if bus_id != "x" } mods = list(id_position.keys()) offsets = [-offset for offset in id_position.values()] lowest_multiple, _ = crt(mods, offsets) return lowest_multiple
def main(day, part=1): start_time, bus_ids, tolerance = preprocess(day.data) if part == 1: bus_id, minutes = schedule(start_time, bus_ids) out = bus_id * minutes if part == 2: smort = crt(bus_ids, tolerance) out = smort[1] - smort[0] return out
def part2(buses) -> int: from sympy.ntheory.modular import crt activeBuses = [] remainders = [] for i in range(len(buses)): if buses[i] != "x": activeBuses.append(buses[i]) remainders.append(-i) return crt(activeBuses, remainders)[0]
def attack(ms): nn = [int(nnn, 16) for nnn in n] x = crt(nn, ms) xx = (Decimal(x[0]).__pow__(Decimal(1) / Decimal(e))) m = int(xx) + 1 print(hex(m))
def _help(m, prime_modulo_method, diff_method, expr_val): """ Helper function for _nthroot_mod_composite and polynomial_congruence. Parameters ========== m : positive integer prime_modulo_method : function to calculate the root of the congruence equation for the prime divisors of m diff_method : function to calculate derivative of expression at any given point expr_val : function to calculate value of the expression at any given point """ from sympy.ntheory.modular import crt f = factorint(m) dd = {} for p, e in f.items(): tot_roots = set() if e == 1: tot_roots.update(prime_modulo_method(p)) else: for root in prime_modulo_method(p): diff = diff_method(root, p) if diff != 0: ppow = p m_inv = mod_inverse(diff, p) for j in range(1, e): ppow *= p root = (root - expr_val(root, ppow) * m_inv) % ppow tot_roots.add(root) else: new_base = p roots_in_base = {root} while new_base < pow(p, e): new_base *= p new_roots = set() for k in roots_in_base: if expr_val(k, new_base) != 0: continue while k not in new_roots: new_roots.add(k) k = (k + (new_base // p)) % new_base roots_in_base = new_roots tot_roots = tot_roots | roots_in_base if tot_roots == set(): return [] dd[pow(p, e)] = tot_roots a = [] m = [] for x, y in dd.items(): m.append(x) a.append(list(y)) return sorted(set(crt(m, list(i))[0] for i in cartes(*a)))
def part2(): with open("13.txt") as f: data = f.read().splitlines() busses = [] for n, i in enumerate(data[1].split(',')): if i != 'x': busses.append((int(i), n)) # Solution is finding t in (t%i) + n = 0 for all i,n crt_sol = crt(*zip(*busses)) return crt_sol[1] - crt_sol[0]
def part2(): ids_2 = [int(i) if i.isnumeric() else i for i in data[1].split(",")] ts = [-idx for idx, i in enumerate(ids_2) if i != 'x'] print(ids, ts) # ids are moduli (the ms) # ts are residuals (the as) # negate residuals because for example in 7,13,x,x,59,x,31,19 # you want 13 to be 1 *ahead*, 59 to be 4 ahead etc. # so you need them to be = -1 % ids[1], -4 % ids[2] etc. return crt(ids, ts)[0]
def task2(input): ids = [(int(x), i) for i, x in enumerate(input[1].split(",")) if x != "x"] # Straightforward application of the Chinese Remainder Theorem primes = [x[0] for x in ids] remainders = [x[0] - x[1] for x in ids] N, _ = crt(primes, remainders) return N
def test_crt(): def mcrt(m, v, r, symmetric=False): assert crt(m, v, symmetric)[0] == r mm, e, s = crt1(m) assert crt2(m, v, mm, e, s, symmetric) == (r, mm) mcrt([2, 3, 5], [0, 0, 0], 0) mcrt([2, 3, 5], [1, 1, 1], 1) mcrt([2, 3, 5], [-1, -1, -1], -1, True) mcrt([2, 3, 5], [-1, -1, -1], 2*3*5 - 1, False) assert crt([656, 350], [811, 133], symmetric=True) == (-56917, 114800)
def mcrt(m, v, r, symmetric=False): assert crt(m, v, symmetric)[0] == r mm, e, s = crt1(m) assert crt2(m, v, mm, e, s, symmetric) == (r, mm)
def test_crt(): assert crt([2, 3, 5], [0, 0, 0]) == 0 assert crt([2, 3, 5], [1, 1, 1]) == 1 assert crt([2, 3, 5], [-1, -1, -1], True) == -1 assert crt([2, 3, 5], [-1, -1, -1], False) == 2*3*5 - 1