Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- def day20(s, *, part2=False, min_savings=100): # Fully vectorized numpy solution. Not fastest.
- grid = np.array([list(line) for line in s.splitlines()])
- ((ys, xs),) = np.argwhere(grid == 'S')
- ((ye, xe),) = np.argwhere(grid == 'E')
- distance = np.where(grid == '#', -2, -1)
- neighbors = (0, -1), (0, 1), (-1, 0), (1, 0)
- d, y, x = 0, ys, xs
- distance[y, x] = d
- while (y, x) != (ye, xe):
- ((y, x),) = (yx2 for dy, dx in neighbors if distance[yx2 := (y + dy, x + dx)] == -1)
- distance[y, x] = d = d + 1
- radius = 20 if part2 else 2
- y, x = np.indices((radius + 1, 2 * radius + 1))
- x -= radius
- valid = (abs(y) + abs(x) <= radius) & ((y > 0) | (y == 0) & (x > 0))
- shifts = np.argwhere(valid)
- y_shifts = shifts[:, 0]
- x_shifts = shifts[:, 1] - radius
- manhattan = abs(y_shifts) + abs(x_shifts)
- padded = np.pad(distance, radius, constant_values=-1)
- # Create a view for vectorized shifting.
- ny, nx = distance.shape
- shifted_views = padded[
- radius + y_shifts[:, None, None] + np.arange(ny)[None, :, None],
- radius + x_shifts[:, None, None] + np.arange(nx)[None, None, :],
- ]
- # Create mask for valid (non-negative) values.
- valid_mask = distance >= 0
- shifted_valid = shifted_views >= 0
- # Calculate value differences and adjust by Manhattan distance.
- value_diff = np.abs(shifted_views - distance)
- adjusted_diff = value_diff - manhattan[:, None, None]
- # Count pairs satisfying all conditions.
- valid_pairs = ((adjusted_diff >= min_savings) & valid_mask & shifted_valid).sum(axis=(1, 2))
- return valid_pairs.sum()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement