Настало Появилось время продолжить AoC за, уже оставшийся в прошлом, 2022 год.
Задачка двадцатого дня была чем-то похожа на обезьяньи игры — потому не вызвала слишком много затруднений.
Упростить решение помогло наличие библиотечного метода Math.floorMod
(про который я вычитал в треде на реддите).
Перемешивание координат
static void mix(List<Map.Entry<Integer, Long>> mixed, List<Map.Entry<Integer, Long>> reference) {
for (var coordinate : reference) {
int idx = mixed.indexOf(coordinate);
mixed.remove(idx);
int newIdx = Math.floorMod(idx + coordinate.getValue(), mixed.size());
mixed.add(newIdx, coordinate);
}
}
ЕМНИП, получилось нечто вроде двойного хэширования. Но с ходу приспособить что-то типа LinkedHashMap
для хранения координат не удалось, а дольше искать было лень. Так что — остановился на списках.
Вычисление результата
static void day20(String puzzleInputUri) throws IOException, InterruptedException {
long key = 811589153; // 1 for part 1
int mixes = 10; // 1 for part 1
AtomicInteger idx = new AtomicInteger(0);
var encrypted = client.send(request.uri((URI.create(puzzleInputUri))).build(), BodyHandlers.ofLines())
.body()
.map(coord -> Map.entry(idx.getAndIncrement(), Long.parseLong(coord) * key))
.collect(Collectors.toList());
var reference = new ArrayList<>(encrypted);
for (int i = 0; i < mixes; i++) {
mix(encrypted, reference);
}
encrypted.stream()
.filter(c -> c.getValue() == 0)
.findAny()
.map(encrypted::indexOf)
.map(startIdx -> IntStream.of(startIdx + 1000, startIdx + 2000, startIdx + 3000)
.map(i -> i % encrypted.size())
.mapToLong(i -> encrypted.get(i).getValue())
.sum()
)
.ifPresent(System.out::println);
}
Надеюсь, загадки оставшихся дней будут не сильно сложнее 🙂
Исходные данные: https://adventofcode.com/2022/day/20/input