Added a downloader and template generator, new template and retrofitted the old days, adding solution to day 4.

This commit is contained in:
Chris Hodges 2023-11-25 12:30:33 +01:00
parent 898c887dc4
commit 43cbc17f74
13 changed files with 492 additions and 2842 deletions

View File

@ -6,6 +6,11 @@ repositories {
mavenCentral()
}
dependencies {
implementation("com.github.kittinunf.fuel:fuel:3.0.0-alpha1")
implementation("com.mohamedrejeb.ksoup:ksoup-html:0.2.1")
}
tasks {
sourceSets {
main {

View File

@ -1,17 +0,0 @@
fun main() {
fun part1(input: List<String>): Int {
return input.size
}
fun part2(input: List<String>): Int {
return input.size
}
// test if implementation meets criteria from the description, like:
val testInput = readInput("Day01_test")
check(part1(testInput) == 1)
val input = readInput("Day01")
part1(input).println()
part2(input).println()
}

34
src/Day_template.txt Normal file
View File

@ -0,0 +1,34 @@
package ${package}
import println
import readInput
/*
${description}
*/
fun main() {
val inlineTestInput = """
${testinput}
"""
fun part1(input: List<String>): Int {
return 0
}
fun part2(input: List<String>): Int {
return 0
}
// test if implementation meets criteria from the description, like:
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("${package}/Day${day}_test")
println("Part 1 Test: " + part1(testInput))
println("Part 2 Test: " + part2(testInput))
check(part1(testInput) == 0)
check(part2(testInput) == 0)
val input = readInput("${package}/Day${day}")
part1(input).println()
part2(input).println()
}

View File

@ -11,17 +11,15 @@ fun readInput(name: String) = File("src", "$name.txt")
fun listOfIntegerLists(input: List<String>): ArrayList<List<Int>> {
val output = ArrayList<List<Int>>()
var currList = ArrayList<Int>()
for(i in input)
{
if(i.isEmpty()){
for (i in input) {
if (i.isEmpty()) {
output.add(currList)
currList = ArrayList<Int>()
currList = ArrayList()
} else {
currList.add(i.toInt())
}
}
if(currList.isNotEmpty())
{
if (currList.isNotEmpty()) {
output.add(currList)
}
return output

View File

@ -4,7 +4,65 @@ import listOfIntegerLists
import println
import readInput
/*
--- Day 1: Calorie Counting ---
Santa's reindeer typically eat regular reindeer food, but they need a lot of magical energy to deliver presents on Christmas. For that, their favorite snack is a special type of star fruit that only grows deep in the jungle. The Elves have brought you on their annual expedition to the grove where the fruit grows.
To supply enough magical energy, the expedition needs to retrieve a minimum of fifty stars by December 25th. Although the Elves assure you that the grove has plenty of fruit, you decide to grab any fruit you see along the way, just in case.
Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!
The jungle must be too overgrown and difficult to navigate in vehicles or access from the air; the Elves' expedition traditionally goes on foot. As your boats approach land, the Elves begin taking inventory of their supplies. One important consideration is food - in particular, the number of Calories each Elf is carrying (your puzzle input).
The Elves take turns writing down the number of Calories contained by the various meals, snacks, rations, etc. that they've brought with them, one item per line. Each Elf separates their own inventory from the previous Elf's inventory (if any) by a blank line.
For example, suppose the Elves finish writing their items' Calories and end up with the following list:
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
This list represents the Calories of the food carried by five Elves:
The first Elf is carrying food with 1000, 2000, and 3000 Calories, a total of 6000 Calories.
The second Elf is carrying one food item with 4000 Calories.
The third Elf is carrying food with 5000 and 6000 Calories, a total of 11000 Calories.
The fourth Elf is carrying food with 7000, 8000, and 9000 Calories, a total of 24000 Calories.
The fifth Elf is carrying one food item with 10000 Calories.
In case the Elves get hungry and need extra snacks, they need to know which Elf to ask: they'd like to know how many Calories are being carried by the Elf carrying the most Calories. In the example above, this is 24000 (carried by the fourth Elf).
Find the Elf carrying the most Calories. How many total Calories is that Elf carrying?
--- Part Two ---
By the time you calculate the answer to the Elves' question, they've already realized that the Elf carrying the most Calories of food might eventually run out of snacks.
To avoid this unacceptable situation, the Elves would instead like to know the total Calories carried by the top three Elves carrying the most Calories. That way, even if one of those Elves runs out of snacks, they still have two backups.
In the example above, the top three Elves are the fourth Elf (with 24000 Calories), then the third Elf (with 11000 Calories), then the fifth Elf (with 10000 Calories). The sum of the Calories carried by these three elves is 45000.
Find the top three Elves carrying the most Calories. How many Calories are those Elves carrying in total?
*/
fun main() {
val inlineTestInput = """
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
"""
fun part1(input: List<String>): Int {
return listOfIntegerLists(input).map { it.sum() }.max()
}
@ -14,10 +72,14 @@ fun main() {
}
// test if implementation meets criteria from the description, like:
val testInput = readInput("Day01")
check(part1(testInput) == 69836)
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("aoc2022/Day01_test")
println("Part 1 Test: " + part1(testInput))
println("Part 2 Test: " + part2(testInput))
check(part1(testInput) == 24000)
check(part2(testInput) == 45000)
val input = readInput("Day01")
val input = readInput("aoc2022/Day01")
part1(input).println()
part2(input).println()
}

View File

@ -1,7 +1,49 @@
package aoc2022
import println
import readInput
/*
--- Day 2: Rock Paper Scissors ---
The Elves begin to set up camp on the beach. To decide whose tent gets to be closest to the snack storage, a giant Rock Paper Scissors tournament is already in progress.
Rock Paper Scissors is a game between two players. Each game contains many rounds; in each round, the players each simultaneously choose one of Rock, Paper, or Scissors using a hand shape. Then, a winner for that round is selected: Rock defeats Scissors, Scissors defeats Paper, and Paper defeats Rock. If both players choose the same shape, the round instead ends in a draw.
Appreciative of your help yesterday, one Elf gives you an encrypted strategy guide (your puzzle input) that they say will be sure to help you win. "The first column is what your opponent is going to play: A for Rock, B for Paper, and C for Scissors. The second column--" Suddenly, the Elf is called away to help with someone's tent.
The second column, you reason, must be what you should play in response: X for Rock, Y for Paper, and Z for Scissors. Winning every time would be suspicious, so the responses must have been carefully chosen.
The winner of the whole tournament is the player with the highest score. Your total score is the sum of your scores for each round. The score for a single round is the score for the shape you selected (1 for Rock, 2 for Paper, and 3 for Scissors) plus the score for the outcome of the round (0 if you lost, 3 if the round was a draw, and 6 if you won).
Since you can't be sure if the Elf is trying to help you or trick you, you should calculate the score you would get if you were to follow the strategy guide.
For example, suppose you were given the following strategy guide:
A Y
B X
C Z
This strategy guide predicts and recommends the following:
In the first round, your opponent will choose Rock (A), and you should choose Paper (Y). This ends in a win for you with a score of 8 (2 because you chose Paper + 6 because you won).
In the second round, your opponent will choose Paper (B), and you should choose Rock (X). This ends in a loss for you with a score of 1 (1 + 0).
The third round is a draw with both players choosing Scissors, giving you a score of 3 + 3 = 6.
In this example, if you were to follow the strategy guide, you would get a total score of 15 (8 + 1 + 6).
What would your total score be if everything goes exactly according to your strategy guide?
--- Part Two ---
The Elf finishes helping with the tent and sneaks back over to you. "Anyway, the second column says how the round needs to end: X means you need to lose, Y means you need to end the round in a draw, and Z means you need to win. Good luck!"
The total score is still calculated in the same way, but now you need to figure out what shape to choose so the round ends as indicated. The example above now goes like this:
In the first round, your opponent will choose Rock (A), and you need the round to end in a draw (Y), so you also choose Rock. This gives you a score of 1 + 3 = 4.
In the second round, your opponent will choose Paper (B), and you choose Rock so you lose (X) with a score of 1 + 0 = 1.
In the third round, you will defeat your opponent's Scissors with Rock for a score of 1 + 6 = 7.
Now that you're correctly decrypting the ultra top secret strategy guide, you would get a total score of 12.
Following the Elf's instructions for the second column, what would your total score be if everything goes exactly according to your strategy guide?
*/
fun main() {
// A = 0 X = 0 Win: X0 - C2, Z2 - B1, Y1 - A0
// B = 1 Y = 1 Win: (r+2) % 3) == c; Lose: ((r+1) % 3) == c
// C = 2 Z = 2 Points = (r + 1) + ((3-c) - (r+1) % 3) * 3
val inlineTestInput = """
A Y
B X
C Z
"""
fun part1(input: List<String>): Int {
return input.sumOf {
val c = it[0] - 'A'
@ -20,7 +62,10 @@ fun main() {
}
// test if implementation meets criteria from the description, like:
val testInput = readInput("aoc2022/Day02_test")
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("aoc2022/Day02_test")
println("Part 1 Test: " + part1(testInput))
println("Part 2 Test: " + part2(testInput))
check(part1(testInput) == 15)
check(part2(testInput) == 12)

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
A Y
B X
C Z

View File

@ -1,5 +1,68 @@
package aoc2022
import println
import readInput
/*
--- Day 3: Rucksack Reorganization ---
One Elf has the important job of loading all of the rucksacks with supplies for the jungle journey. Unfortunately, that Elf didn't quite follow the packing instructions, and so a few items now need to be rearranged.
Each rucksack has two large compartments. All items of a given type are meant to go into exactly one of the two compartments. The Elf that did the packing failed to follow this rule for exactly one item type per rucksack.
The Elves have made a list of all of the items currently in each rucksack (your puzzle input), but they need your help finding the errors. Every item type is identified by a single lowercase or uppercase letter (that is, a and A refer to different types of items).
The list of items for each rucksack is given as characters all on a single line. A given rucksack always has the same number of items in each of its two compartments, so the first half of the characters represent items in the first compartment, while the second half of the characters represent items in the second compartment.
For example, suppose you have the following list of contents from six rucksacks:
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
The first rucksack contains the items vJrwpWtwJgWrhcsFMMfFFhFp, which means its first compartment contains the items vJrwpWtwJgWr, while the second compartment contains the items hcsFMMfFFhFp. The only item type that appears in both compartments is lowercase p.
The second rucksack's compartments contain jqHRNqRjqzjGDLGL and rsFMfFZSrLrFZsSL. The only item type that appears in both compartments is uppercase L.
The third rucksack's compartments contain PmmdzqPrV and vPwwTWBwg; the only common item type is uppercase P.
The fourth rucksack's compartments only share item type v.
The fifth rucksack's compartments only share item type t.
The sixth rucksack's compartments only share item type s.
To help prioritize item rearrangement, every item type can be converted to a priority:
Lowercase item types a through z have priorities 1 through 26.
Uppercase item types A through Z have priorities 27 through 52.
In the above example, the priority of the item type that appears in both compartments of each rucksack is 16 (p), 38 (L), 42 (P), 22 (v), 20 (t), and 19 (s); the sum of these is 157.
Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types?
--- Part Two ---
As you finish identifying the misplaced items, the Elves come to you with another issue.
For safety, the Elves are divided into groups of three. Every Elf carries a badge that identifies their group. For efficiency, within each group of three Elves, the badge is the only item type carried by all three Elves. That is, if a group's badge is item type B, then all three Elves will have item type B somewhere in their rucksack, and at most two of the Elves will be carrying any other item type.
The problem is that someone forgot to put this year's updated authenticity sticker on the badges. All of the badges need to be pulled out of the rucksacks so the new authenticity stickers can be attached.
Additionally, nobody wrote down which item type corresponds to each group's badges. The only way to tell which item type is the right one is by finding the one item type that is common between all three Elves in each group.
Every set of three lines in your list corresponds to a single group, but each group can have a different badge item type. So, in the above example, the first group's rucksacks are the first three lines:
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
And the second group's rucksacks are the next three lines:
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
In the first group, the only item type that appears in all three rucksacks is lowercase r; this must be their badges. In the second group, their badge item type must be Z.
Priorities for these items must still be found to organize the sticker attachment efforts: here, they are 18 (r) for the first group and 52 (Z) for the second group. The sum of these is 70.
Find the item type that corresponds to the badges of each three-Elf group. What is the sum of the priorities of those item types?
*/
fun main() {
val inlineTestInput = """
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
"""
fun toPrio(input: Char) = if (input in 'A'..'Z') input - 'A' + 27 else input - 'a' + 1
fun part1(input: List<String>): Int =
@ -21,8 +84,10 @@ fun main() {
}
// test if implementation meets criteria from the description, like:
val testInput = readInput("aoc2022/Day03_test")
part1(testInput).println()
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("aoc2022/Day03_test")
println("Part 1 Test: " + part1(testInput))
println("Part 2 Test: " + part2(testInput))
check(part1(testInput) == 157)
check(part2(testInput) == 70)

View File

@ -1,300 +0,0 @@
dtddvvhwttHJhwdhJPddhwJGppmGjgpQgTjQplQpTljwpg
BfzSzRSVVMVNRMDDNBSNSnfBmbrglGQbmNpQggFjpgpbQlQb
ZSBffLnVZdCCPJjhhL
RGCZpWWWFlHQQbgvFssg
jLnMzjnrnjjNjhrjdwbHscsVVgDVQPvPwh
nfJnLMLzjJMtnjNnnBbZtBWBqqbTTTBRpT
nddlhBtqTBqTVSlBtmCmVcRVmZggfWbcZc
jDjvPrPSNPwrDNRWbbgWCjRRCcWm
DzDwSpFrvrvFPQLzQnsqztBthTJnGJqlsJ
gssGmzwgRgsNmTsqgDnDJnbDHHhhzFdDDh
WQVFjMWrVQrVvVVjVctSSLSMZhnJZPBnbdnhbnHZZBDJBh
VCtcccVQLrfvrSlGmfTfNgfmlFgm
DsmfsBbNNZhDWsbmWmNbbPDHLFjcctjjGcnZGzncnctcGH
SwVQJrjVwpgSVRpjpVRrlTMCFFCLCFFcHzzGMcHrtHHH
ppVwTwSwpwvSlSlJTjVVbPhsvvBssWsNfsqWPvWs
BJwqwJtqqDDDrGDnPFzPFfpphD
TgZscCHQLSHgZcfMzpjFFjzsshfj
LcNlTVQCCVLLZTLNvpRtpvBBvRJmNB
bDBGQBBCTTNPGPPwPzcHfVHrDtLWLVrWVjjHWr
gpssqqsqlMFfLZQWftjVpr
lvqqFMRlFcQvbzCNCG
fhhMDdPhWMJMWvhhSfwRSGlzFbSFNlzw
LcqTCqcgZqjTggVjcwbFRwbDBTzbRGRwTS
cHLpZgnCHpQsDdsmQp
jwStJjJhtgJStpgwJMggQWqQTNTfNTWfbNNMCCNG
zRZnFPRZPVncPGVFRlRmGHCTqfCCPCHHfLfbTQCbTq
lnVmFZRZDnRVBFZcrZlhjpggvppthGhphpwprS
lcttSptHHllQbMcsrltSQGpvNBzpgWBBBDDGWzvgLz
PdjPVRFhFqFjRRCjzvRWnWLBLgbBBLzg
hhCCFbPTmjPdhZjhPhZCmTjjMsrJSfHrcmHJrHHmlcJSsmft
WhWnLZSSnSzQQhfLLNSfmDHrCFDDHtpjGGtTGQCG
gJbJBcMVwJlRRdbwvwJBVtjdtHHTmptpHTCtTFrFCp
JwwgvRMJlvJwgqgvqRMcnWWhLPzzsqfnZWnfWWnj
zdwTSvzHMvVSzDCtZhtGmbTGhm
lcBHfFjjgtsmDCgshD
cJPBnqNFnLfHJFPqljclqJzQvSSVWvSnMwvSzSWWdMWM
pNJMcZrsZDLDcbcccMpQffHqvgdwdFFmdmqwvqmgmzsw
hhnWjTTStRCGSMgvvgvdqvdFjvVz
hCTSWhPGttTCGBWMRlTCMSnPBDJpbDfDpNpbbNJfJDJbpJpN
lbcQcSNFchhQNqHLLqhLqrMpqM
WfsnsszPWfBBVpHdprrpdnGL
WTzWfwjtTBzwwBDzmfSSQmmbFZcpQNcbZZbv
PwSJSlmtPPgwgmHhPPvRvGHLRLQRBQGCQVGb
rnsFDnnfGGRWQRnW
dfTTfTFdfrfFFFzQFPJPSSlhqtllNPzgwS
MMbTFZrcrGZMDqNStWScDtzS
dvWmhQggQvCnfnqPqDnDjnfP
lgvdvLClWCQlgdhlrMBBHpGlwbHHGH
CQHgQpPdCQpsCpzRwSVRSzRZwZ
JbNBbcbrJvbJnqVznwwTzrzz
wNbfLvvfDNNBHPFLhddFsQss
VVzqvwzpqvzqNVVHGNqjHpNfSQDWdWwJdPWrWccdQrWrrDdd
nLcbtBRtBhcnWSJQlJSgll
tFbLLLRRhMtsBMtRCRsLCMBVjjvHTNjHHjzcvFFppGHzTT
QCPrPWNPlWjGGZqGmvdPGd
JgpHpSfphhfpVmBSgnTvdtddGvZVdvddDv
LhphBfHpSwSwfHcMgfpmBWWWbsNCjFWsljNbbjlLjb
QJmQbRmdfmdSQRQZSJltTltNvTrtDtrlftDD
wpZcHVwwMgBpWMVgWpHLphztDvvGvDPlnGvDLlNrDPnNPl
McgWFWHHHzVpMgZQFqbjsdjqqRCq
JPhLFfMJDLQnjNCvWWpdjjdM
crSwnwVnwSRBcNBNjjWCdC
GlbTGbsSzrtbmbfhnJQP
fDLSWVDRHHfVWHgPcZlDlZbbQhBcZQbb
jrmFmprTpFztmddjdjrpvBQlQZGhQbTsQbGcQbcbQs
nvqdpmjFnwpLSWlfnVNnWl
nZBRbBJzznNNCnJZwnBSCJMcpcTpcwhcqhmsmWMwFWLL
jQfvjgtfvPlHHqWpvWThpWqWch
VljjjgjQjrTDlDgrHtVCbnJZzNzNbnRNNJZrJR
MQtJnttlMLlJQsNhQrVVrFVWRRbbVFdJDD
vGjvzmjzgHqSjjSzmSGHTWbfDFWrbFzFfdDVrfRWDb
qPRqvTSPggqGgHCmllnCNLtnhcnnsnnw
zrlZsQMFrsgQFMMjMCbjVDCTCW
NqHNRdBppcJJcTpdmRfHThpdDWDtvbWVtbLjWbttWqqCCbLt
mhJpJHTJmBhcJhwhgwzsQwSSlzQQzGlZ
TvsszlvnzRRVTqzVrqrjjZGPfQPFqPqG
mcNhDNchppWmWSNhdSmSCQNjPFjrfGjrgPFCrgFPgPgrLf
SDddWpdMWSwNDmMNwlJRQwJlsVRRvzlsHt
DTtggjsFFFTlPJhvctBqBqSRmSMBSRnmnRcm
fGfwZdrbHVLdbGdHHwwQGVwBBCMMfvCNRNSMMMSRBmmRCN
dGZzGHGVVbvHvHwbzpGbHLrwFDDFTtsglhFspgJshslTDJjT
CbzspssWwCPcvvplrfqfDCJrDqdllB
LjttnjNTNGgQQJdBrffTwB
nVtLSgggjFwtMczhvzpZbSZW
HCzCHHvWthWFHhssWCVmnqZrnqVrmrmgnbrqmN
wPPGBjQQGwGbSlSLwgnpnrBZnBBmnMNnMN
jTTbJlJjPPLPGHHTthhhHcFWTT
qRdvvPDrCpzPHzcdrrcRqtbJJgjhgtWjJgbWJtgCFb
GTwGwNscLllGTZmGSTZGlSBMnhggjbgtgbtbsgWFFMhbMF
ZSQBSmlmzcrdQRqz
cSpTRphwwghRfgSScqPpnDqDCjDjJJJJDvDLCvvn
BVmmQFQBQVNBVmsWlbQFGBBlCHTJznzHLHvvCnjjNLHJDLHD
MFsZZMbBGblbQTmQsFsQMMfPcPcwSpwtStgPphZtctPc
QZbbZBdjPBjbQQbZnSSltlfwWvlvwNtNjwFMMN
DLVqTJqpSVtfsptwfWpv
rcRRVVTSbPQBPrBZ
tjSgSjLFSnVjDWRsQj
lcdqhfFpqZGpZqznrVRWPrnWRVBsVG
FHddNNNHwTHMHvvS
qCSDSQlwBHNbgJrHnLJH
GRpRpRfnmRWWVWgVrF
jhdZjpnvGfTZZQPlCtqQQSsS
FMZSGWWBrZjMBZMrBWMGjjZDnCRqpgPnbRwPbFnvvqFnDR
QHcpfVVslfdVlQclcctqRgqgbsCwbCwPCCCPwD
NLHfLhclmmhdfNNpfQMBmZWBrJMmZWBzMrjj
pBMpRgBMQwzRthmzLC
HPcJvrvDbjvrFDcvWrHfHfWHmdddtdTLztmtdtfllmNdNhNz
DvPFDvnPJLngQsggMGGQ
BbcFHvbhhDbbTSvZmwwgJPPlDlZldd
prCrNLMNgWWJBdrJ
fQMLCfLLtpqsNNMnnfBhcBSVGbhhhcqVbcjc
ZchcZZjmmNpgmJtgmM
RLrHllWrQZQGlBpbGFGFFM
RQnLHrqPLnZHzqjfVPcvVTfCvPTC
fMtwjfMwrbjfGrtrpPGrwpNNVNVqcbdVqHZTFNbcHSNL
mgzvDnJmnJhFJHSTNqZLHncHLS
vRzhzslJFhRffPPQMjGtGl
VMMNjWppQVwzNWrZdrrtMCMZCtMT
ngDScLcvPPgDPDGhGDPGSHVbHTHmZtTSrBHZbZBmBb
LhlglLghnVlplswJjs
bGJQZZTQQLJJbQZlTZLjCGQTsDhWFhmshhvjWVFVVrgtDsst
NScqwHcwwnnzBwqPqqsmVNhgsDDVtsghrFFg
pcrcwnpcffrcBzfbCRLpRLMMRlRLQl
hzCzCzpRgCzzzCctNsNWNqsZqZhPqNPb
TdBwmdrrrDmvwTvqNsSRssPlsWsq
FDBRRHDMTmBfmrmngnpjGgVptMgLCp
ZPLLnSPMFGvFZMSvHhDhqHfqvfqbDW
GgcppCgBcrQBBgplrVddhDqqqfdHgWdfqb
CcCjQszmGBQjrcCwCmCccPwPTPnMPTnMJSMMRZSPJL
LcVVcqqSHRLzRnCfNnGzNW
LZPPdljlCggMjgNM
PTvwlPtwtlJvZTQvbcHppFLHVVTcFssF
fpWzvzNgWJBVfBJzWzBVJNzWbZcbHhlbthjlrrPrjZZPHZhJ
hRDmGCFDwQnStncrjnccHcMP
GmmsGRmFTsFwSCsRQDsCSqqpfvfgzddWggvqdpfBWzVh
wjRBFljJGDFwwlGGpBSjGDtwTVtTgHHHsHHsVTVzsHqq
CPLNPdbWvbMWbcmvPNdLVqtsHqgCqHChZhhsVsHt
PWcPfPvmvNQbbWdWpJjJBDptGnDFjftn
mFFmJpDMmmnJFjWDVclsSpcflSsQwSsc
HrjNNjHNfVwLNSSl
tdZbhjHZHPbdCTvbbhhrGbbHMFmRMvnRRFmmvJMDmgJDJMnq
szJZhshbsfZJjbttchPctdTnWnRWVWMMnBdLRpMnBz
SrNwvDSwrCmnVRvjpWLBBn
ggGmgNFrgSDwmNgrCmtPsZPsjQGsqPcsqqJP
gjSWSjJSWrWzppzW
MCMzHNGNqHfscsFtrtwscVcr
qGHNGNHLCnLmTCHfMMmNTzzldzgJlJZZgJljgTdD
QGTQtQzTmdTsGTLcdFTGzdtBBjtwvBBJDvDMHJgjJvww
lPlqsZWnDJjZvZgV
ShCfCRnWGFsRRRrF
lwGtndCrrmGCwdmhzQrBzrHvLVggPgHv
fjMjDZJqSDJfJqDNDjJffjZLHPHHFvVFzHBLgLFpFpBSgL
MsTZWRNZfJZZqMGVGhhlhhccRnhC
MMvncqvcHcSnsdzzgvdfQjpljpQVTdDQDRTRlVpQ
wLCrNtBFFHHThRlH
bPJtHmCWssqgGPvq
LvTLsmDWvTWqTsmqjRTmjwgdwgnMHMMFgdtHmBmFVn
rlSCJzCSfpGGlhznQdnwFhtHgBFwtV
SGZJJSSrVfCbGJLjPsWbvjRsPTqR
pNqVVDCMVMBpqJVdMNHrccGHrtNtTFFFrQ
hwmllWbvvbnPvbSvtrFhhJzzHztcTztT
WSnbnPbbbvlWlRvnsqqMgLRMjLgVLCJdRV
GphVTGVMtQwtJmtCJP
FRRsBBsFqRNZNNrgqBdRfCZvbmPgmQzJQPnmJbJmQPJPPmwj
RNqsFrRfZZsZWvNqWRFvrBZvWhhCGVplhlWTlTpSCLpMhWMD
RZRjgbZHjjhsSnRsZstDRStsTVpFhBqFphMqPPpTFQVMPFTM
zrcGJwNNdwJrfNdJWvGdJzdTlTFlqTVPFTVFPPBpqNTbBP
WwLdLGfrRLStCZbD
mrmTqJWTvDDppTDb
DGzBfCzNDzdMwnLlbn
FVZPFZFFZPgjmWZsDtsq
TpnFTnFRCgRgldMRnDnRcrcdbdPBHbtPqbVcccrH
WNWLfQQmfhhSNwmrcbSVqPtbZDZcPb
LQhwLQvQvNfJhJRDMGFRlCMDMD
vLFTDmjVvLgnNHPphN
lMClGCmsRdCnPzCccngCpz
dlGZwRsRrRwswGsdSbbZSbVDrVBmDWWWFJrTrFvFTmqV
SGsZRqGLWLLtZRHRRcLHGTlJjzgJpjzTpNTNJNWpTm
MPMPvFFvFBrPPDPMQMPChjgpNpSNTmmmpNlTDljlTz
vnhrvMvnhSRqqLqnfn
mGFrlBmFQNQFljhqqqqbmHMsTPRbWWCsLMWRsb
wnwtvpwVzDVpvzzwZppnctMLtMPWWCstTsWTsTLffRRW
vwDJgZnvZJFqgLBFGqgl
QdGltnWNWqTdqQWvWsMJcrTcFcrgshJRMs
BzPLCDPzzzzCCLLfCBzfSDmLMrDJMglrcRbbhRsFhMrRJcsM
fjSzwwHfSzPzfCVBHlpdjGnZqnZptqQWjGvG
VbJZbgVzvzmhQpQWpQzhDp
tHPPcGcFBlCctCGtGcBBNlDLMGfMLwWfwwqMLLJwQWwp
dCHTPTPJdTBFPdrZjgsjrjnmdgms
JJpBvJQBZVvcFqqnsWdWvjsn
DCfbDbTtbgfCSHqqNdFMPhPDFnPPDWsPjM
bTmzTNCTNmfqTgJQcpLrpZLzVlVL
dtTLntTjzTftnmwnqGGQHNmm
SWbShCPMBgBRRFSFtRZZmm
DlJPCJCgPWhttzpvdjcpVl
WdzsNvWMzNsMHWddWCVffqmSmScLPvLPgLgLPplrrPmL
BtnzbnBhbwttwtZlmmlgcwSrLgmmpm
bFhQtbGBTnjBBbjTtFBbVDzddDDfjdDDqNWVjWHj
ppmtpgLLZLCbMQvQQThdtrvPhV
BBlHBwHRjHqBzzbHHqjjQdDQTDhPQDvnQlrQDQvr
HGjFzwHNczbzRFcGzHGFSJSpspsmpssMLLSZCppmfs
MpGrMMMcTsHMVHcvbwwmmcRSmDmDmv
zCNptqCBQQLCNLCzbfvSvbSzSDRDSmSv
CNNqNgNQJNgQtCqLlllZdZhTrThsnHpVVssPTsGP
jhSGcShDrLcLLFcw
MVzQvQNZVLHvHPdhLW
qzhhQlVbgqjmSjJDsgmR
CFzSPCgcsVVzFgzSCsBJwjdwJtNllnwglJlp
QrvbqWvvLbmvDMMmbdwFWpNNwwwwptjJWn
RZRZZqvvvDbDHCRTGchHFSGG
SszgPSPPVltDlqtz
WfTdTBdQdFnWBBBhBhNjVJtpNsVlDDDHHJWp
hQhrLFsBwdQPggbRgPwRMg
frRppMMDMpDnJfprnZhrrhpzWgvvGCvvFzWFvzvVVWFGJB
TcmLwTsccqwqbPwsdwqdTPSvBvzzztvggVvQCGWQCLBvCv
sswNjscwmqjwSssjdZNMfHHlHhfrnrgnfR
JpBJBdmdzZzzpngmbCnlqnNbNM
MMTHGccLTLvwRMlRnnQnbblnRnSs
vVGtvMcjLVGHfHDrPPWZppBpJpfZZZ
FGJtlttPdPtGFldlPRGpJTVzSBSSggHgJjVmBMHjJm
rhbvqrQLrWqrWLLfqbjjgNmVNSgzTmNgNS
hsffZQqnqCfZzlPPGlRlcwDs
HDDdZpcFwHFRFcZqDctpRDHpwTCVwjrBTQTBLBLBJJBjjQTJ
ldlMzhlPshPbLrrVrQQCMQjB
glzNfWlvbHqSdNNNcF
jZCMtnZZHCZwBWMwCwtMmfPFfvHDvzHFLPmFDfvh
RcrQdRRdGTzGvDGmfgjh
TsQscdQsQNTNqQQpRrRVCCBMMJJWMMVNVjnNJM
zVPWhVzLzWBWHZnlqBllqlpRbGNdffscGNdbDRnNSfcG
MtvSFQQwMcpsGRNGFR
vvTwJJSgmCSMmjVPPJWWhzllWLVV
RjdfnJfmbVvVJVFQcs
rZDZGBBZVvLZLHFW
qPzTDPlVrjNgfCdmPd
bcjmQPrnbmVmsLVrLrjmcHGRWlZHHRwHpZRHWWwH
nFhqzFqJzDJfvfSFqFfGHWZZHGRJRWHZWdpWwZ
hBCtDSSFCTqCCFzSnzMrLNmrMNPTNMQPMmNL
qvNBSJVDJGGVSJbVDDVhDbbqPjpWpWzWrnpWvvWPMjnWnpWz
mlTltwcwMWTPfNTN
CtCwFmCgmcmlRFmFCtRCHgmDJsbBhVqsbBHVDbNHDHJqqb
csBFBsLrBGBWcgLcBvRgpRhbwRwlbQwbwQgD
DCqmDmtTRtRlhdlh
qnCmTNPmmCnSSzmzNzGLzLccGDBzGrBLvvcW
FjfBjHnHzPFwhvFFqh
bjRpGsNsPqQvPclb
NWGGWGrrZVZjsCLmDMMgzgrSnzSm
MDgmmsNCmZMWmHCZLrvnLBBjPLVlPVbW
zcJGQwJdFRnrBVzqzvPr
hTQwhJwcfTFddFdGSfcRQQGFsggsgsHHnSmgsgsmgCnHNZpC
BPfwzfsgsvfszvBRbQpttRVpJbJpVg
LhTmHLbmbcFTFrWCbFqhFHLHVRpVtQpZVVDVprnDMJtJQnVZ
TGWWbTFFGTqlHhqhSdNdNfNSldjjBfjv
zCzpWTccHlWcPzMljMttbJfjmlfm
DqqQVZZqVsqJnbbnmjbJJQ
ZRmDZsSgVmGLsVqsLDFvrcccHrcTWCgWHBCHcCWp
cvGlQMtQlPtQWWMlcGsrFwFdbgdbdGGDCDCwdd
VChVZNBVjTTfhNTFgzrzrJgSdzgzwf
THThZTqZRHZRqNVZNTVLjRCMmQsntQctMnsPmMmMcWtLMQ
pNRHrbNlNnRLNpMMMTrcGcGTcccz
ZttBmsJmZdjsvTTvvdBMjDhfMGWGDfDfcScjfD
CmtTtwvtCsgllNHPPFbLpC
NpQcvwwRHvdfRvQsNfBQNvfRhVmVMqsZMmMshjMMtWZtMmrm
CGHbSSzFLSSHzTnbLnCWMrtWMtjnZMhZrqZtqW
FzCPPzLbPgFJbHSPldNRpgNfvvccgvwf
nSjpnnhNchMQZMSScnshshncJCGwHGClwmHPZlJPTVZCwHJf
LvtzBTgLWgLPlPwHPLPJ
dTBDqRqFzzhQFhshhNhM
HjjdPsjnllHsbnnDnbTBzLBFBZLLpRFRcCHRFz
wqqWwQhQQMCQffqqhtwMGhpZFRRZvzWzFvBvpvmcRvZm
fGfghtNhthqJrQqMqMMSgDdbPjbssDbdSnjCdd
cqPwJJnnffBFqSfJFnDDPVplLdglGgLVjzGLdVSzVt
WHRTWNHsQTNbzsbCbTsvWrWtjlgVdLgLdvdgvmLjpGlgtm
ZMQrTbNHZNsHHrQCZrNDFzhwnMJcfnDhJPPPFh
LRCFbjNjbCZDmtmqmRRmLtFJBgWBBpvJMwBJvGjBBvMBgw
TTrlfHzccVllZhdQgdGMJWvgWgBndwpG
fVSshSVlsfslhsSHHSZtZZNmNFmtmbFCDF
SPGCBPDMtbcbCtchSMccDTTrrrTFTrsrMTWHTHFVWF
JmnzqVmmwwfpJpmdHRTRsdsTrFdrQp
LqwLgzJgnjqLwgGcVbtjDGjcVbhv
PQcMvrvMsvmdSPPVccmSJcSpGBWWWbBHfWWnfttJWnWJpJ
wDzqhjzmqRzDRwqDzNDbWtjWBBBtGbtHpHnnBf
zglRhDqqDZgRNmZQVCdcCPQvvdZv
RpVjRgvFjGBNWtBWFDtt
dcqQwlqMMsCLLfbgQmtD
snlgzsggTzSTSJTr
dLHhDdtlMngFcFsFLFzzsj
vWRGGRVrrWvvGQQJBRsmQzmsqnffqcNfNcfz
vSRVJBVBwTvWTnHphTgDgtMpDl
bvvGnnJbfPmfdgJJSVtwwCpTScVfNpSC
sjsZWDqBqqMRZsDjbWMVwtwNNcNtScRHpRRttp
hzhDqqWDzZzDZzZLQPJPdPnPvlrbGdlnFQ
PwWHTwzFvNHsNzmmMwzNWGQrCqCFjpZbpnGqrqnpbr
gRVRgJRJlDLSJddDccQVrtZnCqjndnrZdnqnqpdq
chhgSSJfQhRRcSSSSBLVfzmzHTNzMNsTNWHMMvMP
lftqSpBSvhlDBDlhBSczQGmcFMcMVVFMmGFWsm
rHLHTNdggsLLnwLHbTTgdrTMPPmMGWZGQQMzQVQFZQGM
gbJnrHHjnbrgLrRrHpBJvSBDDsfJsDtstq
dBTtFLTtVmpdLhMprSRSWMRSMR
QvJvQbjbCgCQRBhzzRsNWNBC
bjgGqQGbQnjGQgnQgbGgjJnDLHLdfPVtdDmLZdBFVVZttdTf

View File

@ -1,6 +0,0 @@
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw

104
src/aoc2022/Day04.kt Normal file
View File

@ -0,0 +1,104 @@
package aoc2022
import println
import readInput
/*
--- Day 4: Camp Cleanup ---
Space needs to be cleared before the last supplies can be unloaded from the ships, and so several Elves have been assigned the job of cleaning up sections of the camp. Every section has a unique ID number, and each Elf is assigned a range of section IDs.
However, as some of the Elves compare their section assignments with each other, they've noticed that many of the assignments overlap. To try to quickly find overlaps and reduce duplicated effort, the Elves pair up and make a big list of the section assignments for each pair (your puzzle input).
For example, consider the following list of section assignment pairs:
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
For the first few pairs, this list means:
Within the first pair of Elves, the first Elf was assigned sections 2-4 (sections 2, 3, and 4), while the second Elf was assigned sections 6-8 (sections 6, 7, 8).
The Elves in the second pair were each assigned two sections.
The Elves in the third pair were each assigned three sections: one got sections 5, 6, and 7, while the other also got 7, plus 8 and 9.
This example list uses single-digit section IDs to make it easier to draw; your actual list might contain larger numbers. Visually, these pairs of section assignments look like this:
.234..... 2-4
.....678. 6-8
.23...... 2-3
...45.... 4-5
....567.. 5-7
......789 7-9
.2345678. 2-8
..34567.. 3-7
.....6... 6-6
...456... 4-6
.23456... 2-6
...45678. 4-8
Some of the pairs have noticed that one of their assignments fully contains the other. For example, 2-8 fully contains 3-7, and 6-6 is fully contained by 4-6. In pairs where one assignment fully contains the other, one Elf in the pair would be exclusively cleaning sections their partner will already be cleaning, so these seem like the most in need of reconsideration. In this example, there are 2 such pairs.
In how many assignment pairs does one range fully contain the other?
--- Part Two ---
It seems like there is still quite a bit of duplicate work planned. Instead, the Elves would like to know the number of pairs that overlap at all.
In the above example, the first two pairs (2-4,6-8 and 2-3,4-5) don't overlap, while the remaining four pairs (5-7,7-9, 2-8,3-7, 6-6,4-6, and 2-6,4-8) do overlap:
5-7,7-9 overlaps in a single section, 7.
2-8,3-7 overlaps all of the sections 3 through 7.
6-6,4-6 overlaps in a single section, 6.
2-6,4-8 overlaps in sections 4, 5, and 6.
So, in this example, the number of overlapping assignment pairs is 4.
In how many assignment pairs do the ranges overlap?
*/
fun main() {
val inlineTestInput = """
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
"""
fun part1(input: List<String>): Int {
return input.map {
val (r1, r2) = it.split(",").map {
val (a, b) = it.split("-").map { it.toInt() }
a..b
}
if ((r1.start >= r2.start && r1.endInclusive <= r2.endInclusive) ||
(r2.start >= r1.start && r2.endInclusive <= r1.endInclusive)
) 1 else 0
}.sum()
}
fun part2(input: List<String>): Int {
return input.map {
val (r1, r2) = it.split(",").map {
val (a, b) = it.split("-").map { it.toInt() }
a..b
}
if (r1.start in r2 || r1.endInclusive in r2 ||
r2.start in r1 || r2.endInclusive in r1
) 1 else 0
}.sum()
}
// test if implementation meets criteria from the description, like:
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("aoc2022/Day04_test")
println("Part 1 Test: " + part1(testInput))
println("Part 2 Test: " + part2(testInput))
check(part1(testInput) == 2)
check(part2(testInput) == 4)
val input = readInput("aoc2022/Day04")
part1(input).println()
part2(input).println()
}

View File

@ -0,0 +1,163 @@
package downloader
import com.mohamedrejeb.ksoup.html.parser.KsoupHtmlHandler
import com.mohamedrejeb.ksoup.html.parser.KsoupHtmlParser
import fuel.Fuel
import fuel.method
import kotlinx.coroutines.runBlocking
import java.io.FileNotFoundException
import java.nio.charset.Charset
import java.nio.file.Files
import java.nio.file.Paths
import java.time.LocalDate
import java.time.Month
import java.time.ZoneId
fun main() {
var cookie = "<insert your session cookie here or store in gradle.properties>"
if (Files.exists(Paths.get("gradle.properties"))) {
val cookieFromProps = Files.readAllLines(Paths.get("gradle.properties"))
.map { it.split("=") }
.filter { it.size == 2 }
.filter { it[0] == "cookie" }
.map { it[1] }.firstOrNull()
if (cookieFromProps != null) {
cookie = cookieFromProps
}
}
val downloader = Downloader(2022, "aoc2022", cookie)
downloader.updateToLatest()
}
class Downloader(val year: Int, val packageName: String, val sessionCookie: String) {
companion object {
val INPUT_FILENAME = "Day%02d.txt"
val HTML_FILENAME = "Day%02d_description.html"
val DESC_FILENAME = "Day%02d_description.txt"
val TEMPLATE_FILENAME = "Day_template.txt"
val GENCLASS_FILENAME = "Day%02d.kt"
}
fun updateToLatest() {
val targetDir = Paths.get("src", packageName)
if (!Files.exists(targetDir)) {
Files.createDirectories(targetDir)
}
val now = LocalDate.now(ZoneId.of("UTC-1"))
val lastDay = if (now.isBefore(LocalDate.of(year, Month.DECEMBER, 25))) {
if (now.isAfter(LocalDate.of(year, Month.NOVEMBER, 30))) {
now.dayOfMonth
} else {
throw IllegalStateException("You're too early.")
}
} else {
25
}
for (day in 1..lastDay) {
val inputFile = targetDir.resolve(INPUT_FILENAME.format(day))
val htmlFile = targetDir.resolve(HTML_FILENAME.format(day))
val descriptionFile = targetDir.resolve(DESC_FILENAME.format(day))
val genClassFile = targetDir.resolve(GENCLASS_FILENAME.format(day))
if (!Files.exists(inputFile)) {
println("Attempting to download input for day $day")
val (code, data) = downloadInput(day)
if (code != 200) {
throw FileNotFoundException("Could not download input for $year/$day: Status $code, Message: $data")
}
Files.write(inputFile, data.toByteArray(Charset.defaultCharset()))
} else {
println("Skipping input for day $day")
}
if (!Files.exists(htmlFile)) {
println("Attempting to download html for day $day")
val (code, data) = downloadDescription(day)
if (code != 200) {
throw FileNotFoundException("Could not download html for $year/$day: Status $code, Message: $data")
}
Files.write(htmlFile, data.toByteArray(Charset.defaultCharset()))
} else {
println("Skipping html for day $day")
}
var description = ""
var testInput = ""
if (Files.exists(htmlFile)) {
val html = Files.readAllBytes(htmlFile).toString(Charsets.UTF_8)
var enableDescription = false
var preFound = false
var codeFound = false
val handler = KsoupHtmlHandler
.Builder()
.onOpenTag { name, attributes, isImplied ->
when (name) {
"article" -> enableDescription = (attributes["class"] == "day-desc")
"pre" -> preFound = enableDescription
"code" -> codeFound = preFound
}
}
.onCloseTag { name, isImplied ->
when (name) {
"article" -> enableDescription = false
"pre" -> preFound = false
"code" -> codeFound = false
"h2" -> if (enableDescription) description += "\n"
}
}
.onText { text ->
if (enableDescription) {
description += text
}
if (preFound) {
testInput += text
}
}
.build()
val ksoupHtmlParser = KsoupHtmlParser(
handler = handler,
)
ksoupHtmlParser.write(html)
ksoupHtmlParser.end()
testInput = testInput.trim()
Files.writeString(descriptionFile, description)
}
if (!Files.exists(genClassFile)) {
var template = Files.readString(Paths.get("src", TEMPLATE_FILENAME))
template = template.replace("\${package}", packageName)
template = template.replace("\${day}", "%02d".format(day))
template = template.replace("\${testinput}", testInput)
template = template.replace("\${description}", description)
Files.writeString(genClassFile, template)
}
}
}
fun downloadInput(day: Int): Pair<Int, String> {
return downloadStuff(day, "/input")
}
fun downloadDescription(day: Int): Pair<Int, String> {
return downloadStuff(day, "")
}
fun downloadStuff(day: Int, suffix: String): Pair<Int, String> {
return runBlocking {
val req = Fuel.method(
url = "https://adventofcode.com/$year/day/$day$suffix",
method = "GET",
headers = mapOf(
"User-Agent" to "git.platon42.de/chrisly42/advent-of-code-2023",
"Cookie" to "session=$sessionCookie"
)
)
req.statusCode to req.body
}
}
}