def part_two(data): buses_by_offset = {} for i, bus in enumerate(data[1]): if bus != "x": buses_by_offset[i] = int(bus) time = -1 solved = False step = 1 buses_matched = set() while not solved: solved = True time += step num_buses_matched = 0 for offset, bus in buses_by_offset.items(): if (time + offset) % bus == 0: num_buses_matched += 1 if num_buses_matched > len(buses_matched): buses_matched.add(bus) # Full disclosure: I saw a spoiler on Reddit about Chinese Remainder # Theorem that pointed me in this general direction :( step = lcm.reduce(list(buses_matched), dtype=int64) continue else: solved = False break return time
def main(): data = getInts('input') planets = list() i = 0 for planet in data: a = {} a['pos'] = dict(zip(['x','y','z'], planet )) a['vel'] = {'x':0, 'y':0, 'z':0} a['id'] = i planets.append( a ) i+= 1 pairs = list(combinations(range(len(planets)), 2)) planets2 = planets.copy() # part 1 simulation(planets, pairs, 1000) p1 = sum([ getEnergy(x) for x in planets ]) print("p1: {}".format(p1)) # part 2 p2_s = simulation(planets2, pairs, 9999999999, True) p2 = lcm.reduce([x for x in p2_s.values()]) print("p2: {}".format(p2))
def find_cycle(self): cycles = [None, None, None] self.steps = 0 memory = [self.state(0), self.state(1), self.state(2)] while not all(cycles): self.next_step() for k in range(3): state = self.state(k) if not cycles[k] and state == memory[k]: cycles[k] = self.steps return lcm.reduce(cycles)
def prize_time(buses): time = 1 interval = 1 for i in range(len(buses)): bus_ids_to_check = [bus_id for bus_id, _ in buses[:i + 1]] while True: if deltas_correct(time, buses[:i + 1]): break time += interval interval = int(lcm.reduce(bus_ids_to_check, dtype=int64)) return time
def get_action_order(action): """ calculate the order of a move given as a list of permutations inputs: ------- action - (list) of lists of ints - a move given as a list of cycles returns: -------- (int) - the order of the given move """ cycle_lengths = [len(cycle) for cycle in action] return lcm.reduce(cycle_lengths)
def loop_finder(positions): return_times = [] for dimension in range(3): jupiter = SolarSystem1D(positions, dimension) steps = 0 states = dict() states[jupiter.get_states()] = steps while True: steps += 1 jupiter.apply_gravity() jupiter.apply_velocity() new_state = jupiter.get_states() if new_state in states: out = steps - states[new_state] break else: states[new_state] = steps return_times.append(out) return lcm.reduce(return_times)
# pad arg = arg + bytes([16 - len(arg) % 16] * (16 - len(arg) % 16)) n, m = 256, 48 binv = [None] * m for i in range(m): binv[b[i]] = i b = binv[:] assert None not in b cycles = [] for pos, val in enumerate(arg): seen = set() count = 0 while (pos, val) not in seen: seen.add((pos, val)) val = a[val] pos = b[pos] count += 1 cycles.append(count) rep = int(lcm.reduce(cycles)) X = b'\xbe\xf5@\xddk"\x80cTH\x87iT\x0b\xa4\x15\x8fp\x8f\x14\x9b\xd1$d\x98\xac\x92\'\x13\x80\xdf[}SH\x9f\xac' Y = int.to_bytes( pow( rep, 65537, 127314748520905380391777855525586135065716774604121015664758778084648831235208544136462397 ), len(X), 'big') print(''.join((chr(x ^ y) for x, y in zip(X, Y))))
def get_common_denominator(probabilities): """Return least Z such that each probability is a multiple of 1/Z.""" denominators = [p.denominator for p in probabilities] return lcm.reduce(denominators)
moons[moon2] = update_velocity(moons[moon2], moon2_changes) # now we've calculate the velocities, change the new positions new_moons = dict() for moon in moons.keys(): new_moons[add(moon, moons[moon])] = moons[moon] return new_moons x_states = set() y_states = set() z_states = set() while True: x_pos = tuple(i[0] for i in moons.keys()) y_pos = tuple(i[1] for i in moons.keys()) z_pos = tuple(i[2] for i in moons.keys()) x_vel = tuple(i[0] for i in moons.values()) y_vel = tuple(i[1] for i in moons.values()) z_vel = tuple(i[2] for i in moons.values()) x_state = (x_pos, x_vel) y_state = (y_pos, y_vel) z_state = (z_pos, z_vel) if x_state in x_states and y_state in y_states and z_state in z_states: break x_states.add(x_state) y_states.add(y_state) z_states.add(z_state) moons = advance_time(moons) print(lcm.reduce([len(x_states), len(y_states), len(z_states)]))
return hash(state) step = 0 axis_to_check = {0, 1, 2} axis_found = set() states_by_axis = [set(), set(), set()] periods = [] while True: # debug output if step % 100000 == 0: print(f'{datetime.datetime.now().time()}: After {step} steps') if not axis_to_check: result = lcm.reduce(periods) print( f'Planets will return where they started after {result} steps') break for axis_i in axis_to_check: current_hash = axis_hash(positions, velocities, axis_i) if current_hash in states_by_axis[axis_i]: print(f'Repeat found for {axis_i} after {step} states') axis_found.add(axis_i) periods.append(step) else: states_by_axis[axis_i].add(current_hash) axis_to_check -= axis_found
def part2(path): pos = read_positions(path) x, y, z = positions_to_pv_coord_pairs(pos) steps = [steps_until_repeat(pv) for pv in (x, y, z)] return lcm.reduce(steps)
def partB(): def periods_set(x, y, z): return (x > 0) and (y > 0) and (z > 0) moons = [ Moon([14, 15, -2], 'Io'), Moon([17, -3, 4], 'Europa'), Moon([6, 12, -13], 'Ganymede'), Moon([-2, 10, -8], 'Callisto') ] #moons = [Moon([-8,-10,0],'Io'),Moon([5,5,10],'Europa'),Moon([2,-7,3],'Ganymede'),Moon([9,-8,-3],'Callisto')] pairs = list(combinations(moons, 2)) x_visited = [] y_visited = [] z_visited = [] x_steps = 0 y_steps = 0 z_steps = 0 while not (periods_set(x_steps, y_steps, z_steps)): ## apply gravity for (m1, m2) in pairs: for i, (p1, p2) in enumerate(zip(m1.position, m2.position)): if p1 < p2: m1.velocity[i] = m1.velocity[i] + 1 m2.velocity[i] = m2.velocity[i] - 1 elif p1 > p2: m1.velocity[i] = m1.velocity[i] - 1 m2.velocity[i] = m2.velocity[i] + 1 xpos_vel = [] ypos_vel = [] zpos_vel = [] for m in moons: m.step() xpos_vel.append([m.position[0], m.velocity[0]]) ypos_vel.append([m.position[1], m.velocity[1]]) zpos_vel.append([m.position[2], m.velocity[2]]) if xpos_vel in x_visited and x_steps == 0: print('X STEPS: ', (m.steps - 1)) x_steps = m.steps - 1 if ypos_vel in y_visited and y_steps == 0: print('Y STEPS: ', (m.steps - 1)) y_steps = m.steps - 1 if zpos_vel in z_visited and z_steps == 0: print('Z STEPS: ', (m.steps - 1)) z_steps = m.steps - 1 x_visited.append(xpos_vel) y_visited.append(ypos_vel) z_visited.append(zpos_vel) if m.steps % 10000 == 0: print(m.steps) #loopsin = [] #for m in moons: # print(m.periods) # m_period = lcm.reduce(m.periods) # loopsin.append(m_period) #print(loopsin) print(lcm.reduce([x_steps, y_steps, z_steps]))
if b == 0: return t0 return (a + 1) * bus_id, bus_id next_arrivals = [next_arrival(timestamp0, bus_id) for bus_id in bus_ids] t_arrive, bus_id = min(next_arrivals, key=lambda x: x[0]) print((t_arrive - timestamp0) * bus_id) # Part 2 from numpy import lcm with open('p13.txt') as f: timestamp0 = int(f.readline()) schedule = [(i, int(x)) for i, x in enumerate(f.readline().split(',')) if x != 'x'] N = len(schedule) t0 = 100000000000000 dt = schedule[0][1] t = t0 // dt * dt while True: ids = [bus_id for phi, bus_id in schedule if (t + phi) % bus_id == 0] if len(ids) == N: print(t) break t += lcm.reduce(ids)
nvel[j] += 1 # update positions npos = [pos[i] + nvel[i] for i in range(nmoons)] return npos, nvel def key(pos, vel): return '{},{},{};{},{},{}'.format(*pos, *vel) periods = [] for dim in [0, 1, 2]: counter = 0 pos = [positions[i][dim] for i in range(nmoons)] vel = [0] * nmoons initkey = key(pos, vel) #vis = {initkey: 0} while True: pos, vel = one_step(pos, vel) counter += 1 k = key(pos, vel) if k == initkey: #if k in vis: periods += [(counter, pos, vel)] break #vis[k] = counter print(periods) period = lcm.reduce([p[0] for p in periods]) print(period)
# 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. # What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20? from functools import reduce from numpy import lcm smallest_multiple = lcm.reduce(range(2, 21)) print(f"Smallest multiple: {smallest_multiple}")
def create_solution(self): return [gcd.reduce(self.nums), lcm.reduce(self.nums)]