-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathDay10.java
118 lines (97 loc) · 3.11 KB
/
Day10.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package aoc17;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import myutils17.CircularLinkedList;
public class Day10 {
private List<Integer> lengths;
private List<Integer> lengthsAscii;
private CircularLinkedList<Integer> numbers;
private String input;
public Day10(String input) {
this.input = input;
lengthsAscii = getLengthsASCII(input);
numbers = new CircularLinkedList<Integer>();
IntStream.range(0, 256).boxed().forEach(i -> numbers.addLast(i));
}
// runs a single round of the knot hash algorithm
/**
*
* @param numbers
* circular list of numbers 0 - 255
* @param currentPosition
* should be 0 for solution of part 1
* @param skipSize
* should be 0 for solution of part 1
* @return the product of the first two numbers in the resulting list
*/
private int run(CircularLinkedList<Integer> numbers, int currentPosition, int skipSize) {
lengths = getLengths(input);
for (Integer length : lengths) {
numbers.reverse(currentPosition, length);
currentPosition = (currentPosition + length + skipSize) % numbers.size();
skipSize++;
}
return numbers.get(0) * numbers.get(1);
}
// part 2
public String knotHash() {
CircularLinkedList<Integer> nums = new CircularLinkedList<>(numbers);
lengthsAscii.addAll(Arrays.asList(17, 31, 73, 47, 23));
int currentPosition = 0;
int skipSize = 0;
for (int i = 0; i < 64; i++) {
for (Integer length : lengthsAscii) {
nums.reverse(currentPosition, length);
currentPosition = (currentPosition + length + skipSize) % nums.size();
skipSize++;
}
}
List<Integer> denseHash = new ArrayList<>();
for (int i = 0; i < nums.size(); i += 16) {
int hashBlock = nums.get(i);
for (int j = i + 1; j < i + 16; j++) {
hashBlock = hashBlock ^ nums.get(j);
}
denseHash.add(hashBlock);
}
StringBuilder hash = new StringBuilder();
for (Integer i : denseHash) {
String numHex = Integer.toHexString(i);
if (numHex.length() == 1) {
numHex = "0" + numHex;
}
hash.append(numHex);
}
return hash.toString();
}
// part 1
public int getProductOfFirstTwoNumbers() {
// defensive copy
CircularLinkedList<Integer> nums = new CircularLinkedList<>(numbers);
return run(nums, 0, 0);
}
private List<Integer> getLengthsASCII(String input) {
char[] bytes = input.toCharArray();
List<Integer> lengths = new ArrayList<>();
for (char c : bytes) {
lengths.add((int) c);
}
return lengths;
}
private List<Integer> getLengths(String input) {
if (!input.contains(",")) {
throw new IllegalArgumentException(
"Input needs to be a comma separated string for this part of the puzzle");
}
List<Integer> lengths = new ArrayList<>();
Arrays.stream(input.split(",")).map(Integer::parseInt).forEach(lengths::add);
return lengths;
}
public static void main(String[] args) {
String puzzleInput = "106,118,236,1,130,0,235,254,59,205,2,87,129,25,255,118";
Day10 test = new Day10(puzzleInput);
System.out.println(test.knotHash());
}
}