|
| 1 | +package com.adventofcode.aoc2024; |
| 2 | + |
| 3 | +import static com.adventofcode.utils.Utils.itoa; |
| 4 | +import static java.util.stream.Collectors.toCollection; |
| 5 | + |
| 6 | +import com.adventofcode.Solution; |
| 7 | +import com.adventofcode.utils.Direction; |
| 8 | +import com.adventofcode.utils.GraphUtils; |
| 9 | +import com.adventofcode.utils.Point; |
| 10 | +import com.adventofcode.utils.Utils; |
| 11 | +import java.util.Collection; |
| 12 | +import java.util.HashSet; |
| 13 | +import java.util.List; |
| 14 | +import java.util.Map; |
| 15 | +import java.util.Set; |
| 16 | +import java.util.stream.Stream; |
| 17 | + |
| 18 | +class AoC182024 implements Solution { |
| 19 | + |
| 20 | + private static final int EXAMPLE_SIZE = 7; |
| 21 | + private static final int INPUT_SIZE = 71; |
| 22 | + |
| 23 | + @Override |
| 24 | + public String solveFirstPart(final Stream<String> input) { |
| 25 | + return solve( input, true ); |
| 26 | + } |
| 27 | + |
| 28 | + @Override |
| 29 | + public String solveSecondPart(final Stream<String> input) { |
| 30 | + return solve( input, false ); |
| 31 | + } |
| 32 | + |
| 33 | + private String solve(final Stream<String> input, final boolean first) { |
| 34 | + List<String> lines = input.toList(); |
| 35 | + boolean isExample = lines.size() < INPUT_SIZE; |
| 36 | + int maxCorruption = isExample ? 12 : 1024; |
| 37 | + int size = isExample ? EXAMPLE_SIZE : INPUT_SIZE; |
| 38 | + Point start = new Point( 0, 0 ); |
| 39 | + Point end = new Point( size - 1, size - 1 ); |
| 40 | + Set<Point> corruptedPoints = lines.stream() |
| 41 | + .limit( maxCorruption - 1 ) |
| 42 | + .map( this::getCorrupted ) |
| 43 | + .collect( toCollection( HashSet::new ) ); |
| 44 | + for ( int i = maxCorruption - 1; i < lines.size(); i++ ) { |
| 45 | + Point corrupted = getCorrupted( lines.get( i ) ); |
| 46 | + corruptedPoints.add( corrupted ); |
| 47 | + Map<Point, Long> distances = GraphUtils.computeShortestPaths( start, n -> n.equals( end ), |
| 48 | + (Point n) -> getNeighbours( n, corruptedPoints, size ) ); |
| 49 | + if ( first ) { |
| 50 | + return itoa( distances.get( end ) ); |
| 51 | + } else if ( !distances.containsKey( end ) ) { |
| 52 | + return corrupted.i() + "," + corrupted.j(); |
| 53 | + } |
| 54 | + } |
| 55 | + throw new IllegalArgumentException(); |
| 56 | + } |
| 57 | + |
| 58 | + private Point getCorrupted(final String line) { |
| 59 | + List<Long> numbers = Utils.toLongList( line ); |
| 60 | + return new Point( numbers.get( 0 ).intValue(), numbers.get( 1 ).intValue() ); |
| 61 | + } |
| 62 | + |
| 63 | + private Collection<Point> getNeighbours(final Point curr, final Set<Point> corruptedPoints, |
| 64 | + final int size) { |
| 65 | + return Stream.of( Direction.values() ) |
| 66 | + .map( curr::move ) |
| 67 | + .filter( n -> 0 <= n.i() && n.i() < size && 0 <= n.j() && n.j() < size ) |
| 68 | + .filter( n -> !corruptedPoints.contains( n ) ) |
| 69 | + .toList(); |
| 70 | + } |
| 71 | +} |
0 commit comments