def main(): input_ = load_from_file("day17_input.txt") # PART 1 input_init = np.zeros((len(input_), len(input_[0]), 1), dtype=np.int8) for i1, line in enumerate(input_): for i2, c in enumerate(line): input_init[i1, i2, 0] = 1 if c == "#" else 0 evolutions_pt1 = [input_init] for i in range(6): evolutions_pt1.append(evolve(evolutions_pt1[-1])) sol_pt1 = np.sum(evolutions_pt1[-1]) print(sol_pt1) assert sol_pt1 == 368 # Solution for my input # PART 2 input_init_pt2 = np.zeros(shape=(len(input_), len(input_[0]), 1, 1), dtype=np.int) for i1, line in enumerate(input_): for i2, c in enumerate(line): input_init_pt2[i1, i2, 0, 0] = 1 if c == "#" else 0 evolutions_pt2 = [input_init_pt2] for i in range(6): evolutions_pt2.append(evolve_pt2(evolutions_pt2[-1])) sol_pt2 = np.sum(evolutions_pt2[-1]) print(sol_pt2) assert sol_pt2 == 2696 # Solution for my input
def main(): input_ = load_from_file("day11_input.txt") init_grid = [list(line) for line in input_] # PART 1 grids_pt1 = [init_grid] while True: previous = grids_pt1[-1] evolved = evolve_grid(evolve_point, previous) if grids_eq(previous, evolved): break else: grids_pt1.append(evolved) sol_pt1 = occurence_in_grid(grids_pt1[-1], "#") print(sol_pt1) assert sol_pt1 == 2261 # My solution # PART 2 grids_pt2 = [init_grid] while True: previous = grids_pt2[-1] evolved = evolve_grid(evolve_point_pt2, previous) if grids_eq(previous, evolved): break else: grids_pt2.append(evolved) sol_pt2 = occurence_in_grid(grids_pt2[-1], "#") print(sol_pt2) assert sol_pt2 == 2039 # My solution
def main(): input_ = load_from_file("day15_input.txt") # PART 1 d_pt1, dd_pt1 = init(input_[0]) for i in range(len(d_pt1), 2020): prev_val = d_pt1[i - 1] if len(dd_pt1[prev_val]) == 1: d_pt1[i] = 0 dd_pt1[0].append(i) else: new_val = dd_pt1[prev_val][1] - dd_pt1[prev_val][0] d_pt1[i] = new_val dd_pt1[new_val].append(i) sol_pt1 = d_pt1[2020 - 1] print(sol_pt1) assert sol_pt1 == 1280 # Solution for my input # PART 2 d_pt2, dd_pt2 = init(input_[0]) for i in range(len(d_pt2), 30000000): prev_val = d_pt2[i - 1] if len(dd_pt2[prev_val]) == 1: d_pt2[i] = 0 dd_pt2[0].append(i) else: new_val = dd_pt2[prev_val][1] - dd_pt2[prev_val][0] d_pt2[i] = new_val dd_pt2[new_val].append(i) sol_pt2 = d_pt2[30000000 - 1] print(sol_pt2) assert sol_pt2 == 651639 # Solution for my input
def main(): input_ = load_from_file("day10_input.txt") numbers = [int(line) for line in input_] input_sorted = [0] input_sorted.extend(sorted(numbers)) input_sorted.append(input_sorted[-1] + 3) diff1, diff3 = 0, 0 diff3_index = [] for i in range(len(input_sorted) - 1): if input_sorted[i+1] - input_sorted[i] == 1: diff1 += 1 if input_sorted[i+1] - input_sorted[i] == 3: diff3 += 1 diff3_index.append(i+1) # PART 1 solt_pt1 = diff1 * diff3 print(solt_pt1) assert solt_pt1 == 2030 # My solution diff3_index.insert(0, 0) # PART 2 chunks = ( input_sorted[diff3_index[i]:diff3_index[i+1]] for i in range(len(diff3_index) - 1) ) sol_pt2 = prod(map(count_possible_traversals, chunks)) print(sol_pt2) assert sol_pt2 == 42313823813632 # My solution
def main(): input_ = load_from_file("day9_input.txt") numbers = [int(line) for line in input_] for i in range(25, len(numbers)): if numbers[i] not in nondiagonal_sums(numbers[i - 25:i]): sol_pt1 = numbers[i] index_ = i break print(sol_pt1) assert sol_pt1 == 1492208709 # My solution preceeding_nums = numbers[:index_] sliding_window_sums = {} for i in range(2, 100): sliding_window_sums[i] = list( map(sum, sliding_window(i, preceeding_nums))) if sol_pt1 in sliding_window_sums[i]: index_of_sum = sliding_window_sums[i].index(sol_pt1) contigous_range = numbers[index_of_sum:index_of_sum + i] sol_pt2 = min(contigous_range) + max(contigous_range) break print(sol_pt2) assert sol_pt2 == 238243506 # My solution
def main(): input_ = load_from_file("day2_input.txt") sol_count_pt1, sol_count_pt2 = 0, 0 # PART 1 for i in input_: boundaries, letter, string = i.split(" ") lower, upper = map(int, boundaries.split("-")) letter = letter[0] if lower <= string.count(letter) <= upper: sol_count_pt1 += 1 print(sol_count_pt1) # PART 2 for i in input_: positions, letter, string = i.split(" ") pos1, pos2 = map(lambda x: x - 1, map(int, positions.split("-"))) letter = letter[0] if string[pos1] == letter and string[pos2] != letter: sol_count_pt2 += 1 continue if string[pos1] != letter and string[pos2] == letter: sol_count_pt2 += 1 continue print(sol_count_pt2) # Correct solutions for my input assert sol_count_pt1 == 454 assert sol_count_pt2 == 649
def main(): input_ = load_from_file("day18_input.txt") sol_pt1 = sum(evaluate(line) for line in input_) print(sol_pt1) assert sol_pt1 == 67800526776934 # Solution for my input sol_pt2 = sum(evaluate_pt2(line) for line in input_) print(sol_pt2) assert sol_pt2 == 340789638435483 # Solution for my input
def test_search_for_print_books(): """ Check if book_loader.search_for_print_books(xml_content) returns the correct number of validated results. """ url = "http://www.worldcat.org/search?q=lean+in&fq=%20(%28x0%3Abook+x4%3Aprintbook%29)%20%3E%20ln%3Aeng&se=&sd=&qt=facet_fm_checkbox&refinesearch=true&refreshFormat=undefined" xml_content = load_from_file('data/worldcatxml.html') int_results = book_loader.search_for_print_books(xml_content) # Expect list of 10 results total, with each result as a string that can also be converted into an int assert len(int_results) == 10 assert type(int_results) is list for current_result in int_results: _validate_result(current_result)
def main(): input_ = load_from_file("day8_input.txt") instructions = [Instruction(line) for line in input_] # PART 1 solve_pt1(instructions) print(sol_pt1) assert sol_pt1 == 1553 # My solution # PART 2 solve_pt2(instructions) print(sol_pt2) assert sol_pt2 == 1877 # My solution
def main(): input_ = load_from_file("day16_input.txt") # My ticket and nearby tickets are separated by an empty line. empty_line_ix1 = input_.index("") empty_line_ix2 = input_.index("", empty_line_ix1 + 1) ticket_fields = [ TicketField.from_line(input_[i]) for i in range(empty_line_ix1) ] my_ticket = TicketValues.from_line(input_[empty_line_ix2 - 1]) tickets = [ TicketValues.from_line(input_[i]) for i in range(empty_line_ix2 + 2, len(input_)) ] sol_pt1 = 0 err_indexes = set() for i, t in enumerate(tickets): for val in t.vals: if all(val not in tf for tf in ticket_fields): sol_pt1 += val err_indexes.add(i) print(sol_pt1) assert sol_pt1 == 32835 # Solution for my input # PART 2 valid_tickets = [ tickets[i] for i in range(len(tickets)) if i not in err_indexes ] possible_field_nums = defaultdict(list) for tf in ticket_fields: for i in range(20): ith_ticket_vals: Iterable[int] = (itemgetter(i)(t.vals) for t in valid_tickets) if all(ticket_val in tf for ticket_val in ith_ticket_vals): possible_field_nums[tf.name].append(i) # print(possible_field_nums) # Positions were solved by hand, from the dictionary of possible field numbers # above. departure_ticket_positions = (1, 2, 6, 13, 14, 15) sol_pt2 = prod(itemgetter(*departure_ticket_positions)(my_ticket.vals)) print(sol_pt2) assert sol_pt2 == 514662805187 # Solution for my input
def main(): input_ = load_from_file("day5_input.txt") seat_ids = sorted(calculate_seat_id(line) for line in input_) # PART 1 sol_pt1 = max(seat_ids) print(sol_pt1) # PART 2 range_boundary = len(seat_ids) min_ = seat_ids[0] for i in range(min_, min_ + range_boundary): if i not in seat_ids: sol_pt2 = i print(sol_pt2) # Correct solutions for my input assert sol_pt1 == 904 assert sol_pt2 == 669
def main(): input_ = load_from_file("day4_input.txt") passports = extract_and_join_groups_separated_by_str(" ".join, input_) # PART 1 sol_count_pt1 = sum( is_valid_passport_pt1(p) for p in passports) # Oh yeaaah, gimme that sum of bools... print(sol_count_pt1) # PART 2 sol_count_pt2 = sum( is_valid_passport_pt1(p) and is_valid_passport_pt2(p) for p in passports) # Oh yeaaah, gimme that sum of bools... print(sol_count_pt2) # Correct solutions for my input assert sol_count_pt1 == 260 assert sol_count_pt2 == 153
def main(): input_ = load_from_file("day13_input.txt") # PART 1 earliest_ts = int(input_[0]) bus_ids = parse_ints(input_[1]) wait_times = [] for id_ in bus_ids: first_larger = first((i for i in count(start=0, step=id_) if i >= earliest_ts)) wait_times.append(first_larger - earliest_ts) min_wait = min(wait_times) sol_pt1 = min_wait * bus_ids[wait_times.index(min_wait)] print(sol_pt1) assert sol_pt1 == 2382 # Solution for my input # PART 2 sol_pt2 = solve_pt2(parse_ints_pt2(input_[1])) print(sol_pt2) assert sol_pt2 == 906332393333683 # Solution for my input
def main(): input_ = load_from_file("day6_input.txt") # PART 1 sol_pt1 = sum( (len(set(g)) for g in extract_and_join_groups_separated_by_str("".join, input_))) print(sol_pt1) # PART 2 sol_pt2 = sum( len( reduce(lambda x, y: x.intersection(y), (set(person) for person in group))) for group in extract_groups_separated_by_str(input_)) print(sol_pt2) # Correct solutions for my input assert sol_pt1 == 6911 assert sol_pt2 == 3473
def main(): input_ = load_from_file("day12_input.txt") init_ship_pos = ShipPosition(x=0, y=0, direction="E") instructions = [Instruction(line[:1], int(line[1:])) for line in input_] # PART 1 moves = accumulate(move, instructions, initial=init_ship_pos) last_pos_pt1 = last(moves) sol_pt1 = abs(last_pos_pt1) print(sol_pt1) assert sol_pt1 == 441 # Solution for my input # PART 2 init_with_waypoint = CompPosition(init_ship_pos, WaypointPosition(10, 1)) moves_pt2 = accumulate(move_pt2, instructions, initial=init_with_waypoint) last_pos_pt2 = last(moves_pt2) sol_pt2 = abs(last_pos_pt2.ship) print(sol_pt2) assert sol_pt2 == 40014 # Solution for my input
def main(): input_ = load_from_file("day7_input.txt") bags = { i: Bag(line.split("contain")[0][:-6]) for i, line in enumerate(input_) } for i, line in enumerate(input_): contain_part = line.split("contain")[1].strip(" .") for q_cc in qty_and_colour_code_from_str(contain_part): for k, b in bags.items(): if q_cc[0] == b.colour_code: bags[i].contains_with_qty.append((b, q_cc[1])) sol_pt1, sol_pt2 = 0, 0 shiny_gold_bag = Bag("shiny gold") for k, v in bags.items(): if v == shiny_gold_bag: shiny_gold_bag = v # Get the reference on the "real" shiny gold bag break # PART 1 for b in bags.values(): if shiny_gold_bag == b: continue if is_in(shiny_gold_bag, b): sol_pt1 += 1 print(sol_pt1) # PART 2 sol_pt2 = shiny_gold_bag.can_hold() print(sol_pt2) # Correct solutions for my input assert sol_pt1 == 296 assert sol_pt2 == 9339
def main(): input_ = load_from_file("day1_input.txt") numbers = [int(line) for line in input_] # PART 1 for i1, x in enumerate(numbers): for y in numbers[i1:]: if x + y == 2020: sol_pt1 = x * y break print(sol_pt1) # PART 2 for i1, x in enumerate(numbers): for i2, y in enumerate(numbers[i1:]): for z in numbers[i2:]: if x + y + z == 2020: sol_pt2 = x * y * z break print(sol_pt2) # Correct solutions for my input assert sol_pt1 == 658899 assert sol_pt2 == 155806250
class TestCreateBookFromWorldcat(object): # TODO - pull all html_content for worldcat to a class-level attribute worldcat_html = load_from_file('data/worldcat.html') goodreads_html = load_from_file('data/goodreads.html') test_api_key = 'test-test-test' @classmethod def setup_class(cls): """ setup any state specific to the execution of the given class (which usually contains tests). """ os.environ['GOODREADS_API_KEY'] = cls.test_api_key @classmethod def teardown_class(cls): """ teardown any state that was previously setup with a call to setup_class. """ os.environ.pop('GOODREADS_API_KEY') def _fake_requests_response(self, content): mock_resp = MagicMock() mock_resp.content = content return mock_resp def test_create_book_from_worldcat_id(self): """ :return: """ oclc_id = 813526963 values = { _stable_key(args=('http://www.worldcat.org/oclc/813526963',)): self._fake_requests_response(self.worldcat_html), _stable_key(args=('https://www.goodreads.com/book/isbn',), kwargs=dict(params=dict(key=self.test_api_key, isbn='9780385349949'))): self._fake_requests_response(self.goodreads_html), } def requests_get_side_effect(*args, **kwargs): key = _stable_key(args=args, kwargs=kwargs) return values[key] mock_get = MagicMock() mock_get.side_effect = requests_get_side_effect with patch('requests.get', new=mock_get): current_book = book_loader.create_book_from_worldcat_id(oclc_id) assert current_book.book_id == 813526963 def test_load_book_from_worldcat_details_page(self): """ :return: """ worldcat_details_page_url = "http://www.worldcat.org/oclc/813526963" oclc_id = 813526963 book = book_loader._load_book_from_worldcat_details_page(self.worldcat_html, worldcat_details_page_url, oclc_id) # Expect the book object to have all the expected attributes assert book.book_id == 813526963 assert book.title == 'Lean in : women, work, and the will to lead' assert book.publisher == 'New York : Alfred A. Knopf, 2013.' assert book.worldcaturl == 'http://www.worldcat.org/oclc/813526963' assert book.page_count == '228' assert 'United States' in book.summary assert 'TEDTalk' in book.summary assert book.coverurl == 'http://coverart.oclc.org/ImageWebSvc/oclc/+-+814170863_140.jpg?SearchOrder=+-+OT,OS,TN,GO,FA' def test_load_title_from_worldcat_details_page(self): """ :return: """ pass def test_load_authors_from_worldcat_details_page(self): """ :return: """ worldcat_details_page_url = "http://www.worldcat.org/oclc/813526963" oclc_id = 813526963 author_list = book_loader._load_authors_from_worldcat_details_page(self.worldcat_html) assert type(author_list) is list assert len(author_list) == 2 for author_obj in author_list: assert ("Sheryl" in author_obj.author_name or "Nell" in author_obj.author_name) def test_load_isbns_from_worldcat_details_page(self): """ :return: """ isbn10_list, isbn13_list = book_loader._load_isbns_from_worldcat_details_page(self.worldcat_html) for current_isbn in isbn10_list: assert (len(current_isbn.isbn10) == 10 and current_isbn.isbn10 == '0385349947') for current_isbn in isbn13_list: assert (len(current_isbn.isbn13) == 13 and current_isbn.isbn13 == '9780385349949') def test_load_goodreads_info_from_goodreads_api(self): """ :return: """ isbn13 = '9780385349949' goodreads_info_obj = book_loader._load_goodreads_info_from_goodreads_api(self.goodreads_html) assert (goodreads_info_obj.goodreads_ratings_count >= 100000) assert (goodreads_info_obj.goodreads_rating >= 3.50) assert (goodreads_info_obj.goodreads_work_id == '21865596') assert (goodreads_info_obj.goodreads_review_count >= 220000)