Day 8: Playground
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465


I went here for graphs (to find connected components) and binary search (for efficiency)
#!/usr/bin/env python3 from pathlib import Path import numpy as np import networkx as nx cwd = Path(__file__).parent.resolve() def parse_input(file_path): with file_path.open("r") as fp: coords = list(map(lambda x: list(map(int, x.split(','))), fp.readlines())) return np.array(coords) def binary_search(G, dist): Itriu = np.triu_indices(dist.shape[0], k=1) dist = dist[Itriu] components = list(nx.connected_components(G)) Isort = [(Itriu[0][i], Itriu[1][i]) for i in np.argsort(dist)] icurrent = 0 ihist = [] nhist = [] while len(ihist)<2 or ihist[-1]!=ihist[-2]: ihist.append(icurrent) G.add_edges_from(Isort[:icurrent]) components = list(nx.connected_components(G)) nhist.append(len(components)) G.remove_edges_from(Isort[:icurrent]) if len(components)>1: # if >1 component, go between this and closest next index with 1 component I = [ind for ind,n in enumerate(nhist) if n==1] if len(I)==0: inext = len(Isort) else: inext = min(np.array(ihist)[I]) icurrent = icurrent + int(np.ceil((inext-icurrent)/2)) else: # if 1 component, go between nearest previous >1 components and this index I = [ind for ind,n in enumerate(nhist) if n>1] if len(I)==0: iprev = 0 else: iprev = max(np.array(ihist)[I]) icurrent = iprev + int(np.ceil((icurrent-iprev)/2)) return Isort[icurrent-1] def solve_problem(file_name, nconnect): coordinates = parse_input(Path(cwd, file_name)) G = nx.Graph() G.add_nodes_from(range(coordinates.shape[0])) dist = np.sqrt(np.sum((coordinates[None,:] - coordinates[:,None])**2, axis=-1)) if nconnect != -1: # part 1 Itriu = np.triu_indices(dist.shape[0], k=1) dist = dist[Itriu] Isort = [(Itriu[0][i], Itriu[1][i]) for i in np.argsort(dist)[:nconnect]] G.add_edges_from(Isort) components = sorted(list(nx.connected_components(G)), key=len)[::-1] return np.prod(list(map(len, components[:3]))) else: # part 2 indices = binary_search(G, dist) return np.prod(coordinates[indices,:],axis=0)[0] if __name__ == "__main__": assert solve_problem("test_input", 10) == 40 assert solve_problem("input", 1000) == 115885 assert solve_problem("test_input", -1) == 25272 assert solve_problem("input", -1) == 274150525