def B(fname): valid_cnt = 0 for l in lines(fname): first, last, char, passwd = parse(l) if (passwd[first-1] != char and passwd[last-1] == char) or \ (passwd[first-1] == char and passwd[last-1] != char): valid_cnt += 1 return valid_cnt
def A(fname): valid_cnt = 0 for l in lines(fname): llmt, ulmt, char, passwd = parse(l) cnt = passwd.count(char) if cnt >= llmt and cnt <= ulmt: valid_cnt += 1 return valid_cnt
def A(fname, c_inc, r_inc): rows = lines('3a.txt') col_len = len(rows[0]) tree_cnt = 0 c = 0 for row in rows[::r_inc]: tree_cnt += row[c % col_len] == '#' c += c_inc return tree_cnt
from common import lines instructions = [(line[0], int(line[1:])) for line in lines("12")] directions = {"N": (0, 1), "E": (1, 0), "S": (0, -1), "W": (-1, 0)} def simulate(commands, mode, start_position, start_direction): x, y = start_position dx, dy = start_direction for action, value in commands: if action in directions: vx, vy = directions[action] if mode == 1: x, y = x + vx * value, y + vy * value if mode == 2: dx, dy = dx + vx * value, dy + vy * value elif action == "L": for _ in range(value // 90): dx, dy = -dy, dx elif action == "R": for _ in range(value // 90): dx, dy = dy, -dx elif action == "F": x, y = x + dx * value, y + dy * value return abs(x) + abs(y) part1 = simulate(instructions, mode=1, start_position=(0, 0),
def B(grid): while True: newgrid = iter(grid, neighborsB, 5) if is_same(grid, newgrid): return to_str(newgrid).count('#') grid = newgrid s1 = """L.LL.LL.LL LLLLLLL.LL L.L.L..L.. LLLL.LL.LL L.LL.LL.LL L.LLLLL.LL ..L.L..... LLLLLLLLLL L.LLLLLL.L L.LLLLL.LL""".strip().split('\n') assert A(s1) == 37 assert B(s1) == 26 if __name__ == '__main__': t = time() print(A(lines('11.txt'))) t1 = time() print('time A : ', t1 - t) print(B(lines('11.txt'))) print('time B : ', time() - t)
return sum(int(evalb(parse(l))) for l in lns) s1 = "2 * 3 + (4 * 5)" s2 = "5 + (8 * 3 + 9 + 3 * 4 * 3)" s3 = "5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))" s4 = "((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2" assert evala(parse(s1)) == '26' assert evala(parse(s2)) == '437' assert evala(parse(s3)) == '12240' assert evala(parse(s4)) == '13632' assert evalb(parse(s1)) == '46' assert evalb(parse(s2)) == '1445' assert evalb(parse(s3)) == '669060' assert evalb(parse(s4)) == '23340' def parse_expr(line) -> tuple: "Parse an expression: '2 + 3 * 4' => (2, '+', 3, '*', 4)." return ast.literal_eval(re.sub('([+*])', r",'\1',", line)) if __name__ == '__main__': print('herel', A(lines('18.txt'))) print('herel', B(lines('18.txt'))) print('--- norvig parse ---- ') print(parse_expr(s1)) print(parse_expr(s2)) print(parse_expr(s3)) print(parse_expr(s4))
from functools import reduce from common import lines departure, schedule = lines("13") buses = [(-time % int(bus), int(bus)) for time, bus in enumerate(schedule.split(",")) if bus != "x"] delay, bus = min((-int(departure) % bus, bus) for _, bus in buses) part1 = delay * bus print(f"{part1=}") def crt_sieve(c1, c2): a1, n1 = c1 a2, n2 = c2 while a1 % n2 != a2: a1 += n1 return a1, n1 * n2 part2, _ = reduce(crt_sieve, buses) print(f"{part2=}")
def main(): """Entry point.""" # We store everything as a dict keyed on YouTube ID all_data = collections.defaultdict(dict) # Process crawled data log("Processing crawled data") count, processed = 0, 0 for path, subdirs, files in os.walk(CRAWL_INPUT): for fn in files: count += 1 # Remember, file name is also the youtube key in the crawl output with open(os.path.join(path, fn), "r") as fh: data = fh.read().strip() log("Processing crawled data: [%s] len=%12d", fn, len(data)) daily_stats, brag_bar = process_crawled(data) if not daily_stats and not brag_bar: continue # Nothing to do processed += 1 all_data[fn]["daily_stats"] = daily_stats all_data[fn]["brag_bar"] = brag_bar log("Processed crawled data: %d out of %d", processed, count) log("All brag bar labels: %s", repr(ALL_BRAG_BAR)) # Process API content log("Processing JSON retrieve from API") count, processed = 0, 0 for line in lines(API_FILE): count += 1 rec = json.loads(line) ytid = rec.get("id", "").strip() if not ytid: continue processed += 1 all_data[ytid]["stats"] = rec.get("statistics", {}) all_data[ytid]["snippet"] = rec.get("snippet", {}) log("Processed API data: %d out of %d", processed, count) # Output final CSV files log("Writing output file: %s", OUTPUT_DATA) log("Writing daily data file: %s", OUTPUT_DAILIES) data_count, daily_count = 0, 0 with open(OUTPUT_DATA, "w") as data_fh, open(OUTPUT_DAILIES, "w") as daily_fh: data_csv = csv.writer(data_fh, quoting=csv.QUOTE_NONNUMERIC) data_csv.writerow(DATA_COLS) daily_csv = csv.writer(daily_fh, quoting=csv.QUOTE_NONNUMERIC) daily_csv.writerow(DAILY_COLS) for ytid, data in all_data.items(): # From API stats = data.get("stats", {}) snippet = data.get("snippet", {}) # From crawl daily_stats = data.get("daily_stats", {}) brag_bar = data.get("brag_bar", {}) # Write out the main data record data_count += 1 data_csv.writerow([ ytid, # YouTubeID "https://youtube.com/watch?v="+ytid, # WatchURL normws(snippet.get("title", "")), # Title snippet.get("channelTitle", ""), # Channel ints(stats.get("commentCount", "")), # StatsCommentCount ints(stats.get("dislikeCount", "")), # StatsDislikeCount ints(stats.get("favoriteCount", "")), # StatsFavoriteCount ints(stats.get("likeCount", "")), # StatsLikeCount ints(stats.get("viewCount", "")), # StatsViewCount ints(brag_bar.get("Shares", "")), # BBShares ints(brag_bar.get("Subscriptions driven", "")), # BBSubscriptions ints(brag_bar.get("Views", "")), # BBViews brag_bar.get("Time watched", ""), # BBTimeWatched normws(snippet.get("description", "")), # Description "|".join(snippet.get("tags", [])), # Tags ]) # Write out all the daily views days = daily_stats.get("day", {}).get("data", []) views = daily_stats.get("views", {}).get("daily", {}).get("data", []) for d, v in zip(days, views): daily_csv.writerow([ytid, ts_to_day(d), v]) daily_count += 1 log("Wrote %12d to %s", data_count, OUTPUT_DATA) log("Wrote %12d to %s", daily_count, OUTPUT_DAILIES)
from common import lines def play(start, turns): heard = {} last = -1 for i in range(turns): if i < len(start): say = start[i] elif last in heard: say = i - 1 - heard[last] else: say = 0 heard[last] = i - 1 last = say return last start = [int(n) for n in lines("15")[0].split(",")] part1 = play(start, 2020) print(f"{part1=}") part2 = play(start, 30000000) print(f"{part2=}")
def B(lines): for l, li in zip(lines, range(len(lines))): if l[:3] == 'jmp' or l[:3] == 'nop': newl = l.replace('jmp', 'nop') if 'jmp' in l else l.replace( 'nop', 'jmp') val, cond = walk(lines[:li] + [newl] + lines[li + 1:]) if cond == 'term': return val s1 = """nop +0 acc +1 jmp +4 acc +3 jmp -3 acc -99 acc +1 jmp -4 acc +6""".strip().split('\n') assert walk(s1) == (5, 'loop') assert B(s1) == 8 if __name__ == '__main__': print('start') print(A(lines('8.txt'))) print(B(lines('8.txt'))) print('done')
def B(fname): occupied = {seatID(l) for l in lines(fname)} return [s for s in range(128 * 8)\ if s not in occupied and (s-1) in occupied and (s+1) in occupied]
def A(fname): return max([seatID(l) for l in lines(fname)])
return [int(off, 2) for off in offsets] def simulate(instructions, mode): mem = {} mask = "" for instruction in instructions: location, value = instruction.split(" = ") if location == "mask": mask = value else: offset = int(re.fullmatch(r"mem\[(\d+)]", location).group(1)) value = int(value) if mode == 1: mem[offset] = apply_value_mask(mask, value) if mode == 2: for off in apply_offset_mask(mask, offset): mem[off] = value return sum(mem.values()) instructions = lines("14") part1 = simulate(instructions, mode=1) print(f"{part1=}") part2 = simulate(instructions, mode=2) print(f"{part2=}")
from common import lines seats = [list(line) for line in lines("11")] m, n = len(seats), len(seats[0]) def fixed_point(neighbor_function, crowd_factor, grid): def tick(): def tick_cell(r, c): if grid[r][c] == ".": return "." elif grid[r][c] == "L": return "#" if neighbor_function(grid, r, c) == 0 else "L" elif grid[r][c] == "#": return "L" if neighbor_function(grid, r, c) >= crowd_factor else "#" return [[tick_cell(r, c) for c in range(n)] for r in range(m)] while grid != (next_grid := tick()): grid = next_grid return grid directions = {(dr, dc) for dr in (-1, 0, 1) for dc in (-1, 0, 1) if (dr, dc) != (0, 0)} def neighbors1(grid, r, c): return sum(grid[r + dr][c + dc] == "#" for dr, dc in directions if 0 <= r + dr < m and 0 <= c + dc < n)