-
Notifications
You must be signed in to change notification settings - Fork 0
/
AoC232020.java
84 lines (74 loc) · 2.47 KB
/
AoC232020.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package com.adventofcode.aoc2020;
import static com.adventofcode.utils.Utils.getFirstString;
import static com.adventofcode.utils.Utils.incrementMod;
import static com.adventofcode.utils.Utils.itoa;
import com.adventofcode.Solution;
import com.adventofcode.utils.Utils;
import java.util.Collection;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
class AoC232020 implements Solution {
@Override
public String solveFirstPart( final Stream<String> input ) {
return solve( input, true );
}
@Override
public String solveSecondPart( final Stream<String> input ) {
return solve( input, false );
}
private String solve( final Stream<String> input, final boolean first ) {
final int maxCups = first ? 9 : 1_000_000;
final int[] cupToNext = initialize( input, maxCups );
int current = cupToNext[0];
for ( int i = 0; i < ( first ? 100 : 10_000_000 ); i++ ) {
// select 3 cups
final int cup1 = cupToNext[current];
final int cup2 = cupToNext[cup1];
final int cup3 = cupToNext[cup2];
// detach main list from 3 cups
cupToNext[current] = cupToNext[cup3];
// find destination
final int destination = getDestinationLabel( current, maxCups,
List.of( cup1, cup2, cup3 ) );
// insert 3 cups after destination
final int destinationNext = cupToNext[destination];
cupToNext[destination] = cup1;
cupToNext[cup3] = destinationNext;
current = cupToNext[current];
}
current = cupToNext[1];
if ( first ) {
final StringBuilder result = new StringBuilder();
for ( int i = 0; i < maxCups - 1; i++ ) {
result.append( current );
current = cupToNext[current];
}
return result.toString();
} else {
return itoa( (long) current * cupToNext[current] );
}
}
private int[] initialize( final Stream<String> input, final int maxCups ) {
final int[] cupToNext = new int[maxCups + 1];
final List<Integer> cups = IntStream.concat(
getFirstString( input ).chars().map( Utils::charToInt ),
IntStream.rangeClosed( 10, maxCups ) ).boxed().toList();
for ( int i = 0; i < cups.size(); i++ ) {
cupToNext[cups.get( i )] = cups.get( incrementMod( i, maxCups ) );
}
cupToNext[0] = cups.get( 0 );
return cupToNext;
}
private int getDestinationLabel( final int current, final int max,
final Collection<Integer> subset ) {
int destination = current;
do {
destination--;
if ( destination == 0 ) {
destination = max;
}
} while ( subset.contains( destination ) );
return destination;
}
}