-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAoC032021.java
72 lines (61 loc) · 2.42 KB
/
AoC032021.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
package com.adventofcode.aoc2021;
import static com.adventofcode.utils.Utils.itoa;
import java.util.HashSet;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.adventofcode.Solution;
import com.adventofcode.utils.Pair;
class AoC032021 implements Solution {
@Override
public String solveFirstPart( final Stream<String> input ) {
final Set<String> numbers = input.collect( Collectors.toSet() );
final long gammaRate = solve( ( ones, zeroes ) -> ones >= zeroes, numbers, 0, true );
final long epsilonRate = solve( ( ones, zeroes ) -> ones < zeroes, numbers, 0, true );
return itoa( gammaRate * epsilonRate );
}
@Override
public String solveSecondPart( final Stream<String> input ) {
final Set<String> numbers = input.collect( Collectors.toSet() );
final long oxygen = solve( ( ones, zeroes ) -> ones >= zeroes, numbers, 0, false );
final long co2 = solve( ( ones, zeroes ) -> ones < zeroes, numbers, 0, false );
return itoa( oxygen * co2 );
}
private int solve( final BiPredicate<Integer, Integer> bitCriteria, final Set<String> numbers,
final int position, final boolean first ) {
if ( numbers.size() == 1 ) {
return numbers.stream().map( n -> Integer.parseInt( n, 2 ) ).findFirst().orElseThrow();
}
final int numberLength = numbers.stream().findFirst().orElseThrow().length();
if ( position >= numberLength ) {
return 0;
}
final var onesAndZeroes = splitOnesAndZeroes( numbers, position );
final var ones = onesAndZeroes.getFirst();
final var zeroes = onesAndZeroes.getSecond();
final boolean bitCriteriaResult = bitCriteria.test( ones.size(), zeroes.size() );
if ( first ) {
final int head = bitCriteriaResult ? ( 1 << ( numberLength - position - 1 ) ) : 0;
final int tail = solve( bitCriteria, numbers, position + 1, first );
return head + tail;
} else {
final Set<String> keep = bitCriteriaResult ? ones : zeroes;
return solve( bitCriteria, keep, position + 1, first );
}
}
private Pair<HashSet<String>, HashSet<String>> splitOnesAndZeroes( final Set<String> numbers,
final int position ) {
final var ones = new HashSet<String>();
final var zeroes = new HashSet<String>();
for ( final String number : numbers ) {
final char bit = number.charAt( position );
if ( bit == '1' ) {
ones.add( number );
} else {
zeroes.add( number );
}
}
return new Pair<>( ones, zeroes );
}
}