Compare commits
5 Commits
44d8bdc6a7
...
76a464560c
Author | SHA1 | Date |
---|---|---|
Maxim Lebedev | 76a464560c | |
Maxim Lebedev | f4d1707a08 | |
Maxim Lebedev | 71bbd8021f | |
Maxim Lebedev | 52fa48ac1d | |
Maxim Lebedev | 62eb3438f8 |
|
@ -0,0 +1 @@
|
|||
**/testdata/input
|
77
day1_test.go
77
day1_test.go
|
@ -1,77 +0,0 @@
|
|||
package adventofcode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day1/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day1/part2"
|
||||
)
|
||||
|
||||
/*
|
||||
Something is wrong with global snow production, and you've been selected to take
|
||||
a look. The Elves have even given you a map; on it, they've used stars to mark
|
||||
the top fifty locations that are likely to be having problems.
|
||||
|
||||
You've been doing this long enough to know that to restore snow operations, you
|
||||
need to check all fifty stars by December 25th.
|
||||
|
||||
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!
|
||||
|
||||
You try to ask why they can't just use a weather machine ("not powerful enough")
|
||||
and where they're even sending you ("the sky") and why your map looks mostly
|
||||
blank ("you sure ask a lot of questions") and hang on did you just say the sky
|
||||
("of course, where do you think snow comes from") when you realize that the
|
||||
Elves are already loading you into a trebuchet ("please hold still, we need to
|
||||
strap you in").
|
||||
|
||||
As they're making the final adjustments, they discover that their calibration
|
||||
document (your puzzle input) has been amended by a very young Elf who was
|
||||
apparently just excited to show off her art skills. Consequently, the Elves are
|
||||
having trouble reading the values on the document.
|
||||
|
||||
Consider your entire calibration document. What is the sum of all of the
|
||||
calibration values?
|
||||
*/
|
||||
func ExampleDay1() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day1", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := part1.Calibrate(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot sum all calibration values:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 54601
|
||||
}
|
||||
|
||||
/*
|
||||
Your calculation isn't quite right.
|
||||
|
||||
Equipped with this new information, you now need to find the real first and last
|
||||
digit on each line.
|
||||
|
||||
What is the sum of all of the calibration values?
|
||||
*/
|
||||
func ExampleDay1_PartTwo() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day1", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := part2.Calibrate(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot sum all calibration values:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 54078
|
||||
}
|
78
day2_test.go
78
day2_test.go
|
@ -1,78 +0,0 @@
|
|||
package adventofcode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day2/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day2/part2"
|
||||
)
|
||||
|
||||
/*
|
||||
You're launched high into the atmosphere! The apex of your trajectory just
|
||||
barely reaches the surface of a large island floating in the sky. You gently
|
||||
land in a fluffy pile of leaves. It's quite cold, but you don't see much snow.
|
||||
An Elf runs over to greet you.
|
||||
|
||||
The Elf explains that you've arrived at Snow Island and apologizes for the lack
|
||||
of snow. He'll be happy to explain the situation, but it's a bit of a walk, so
|
||||
you have some time. They don't get many visitors up here; would you like to play
|
||||
a game in the meantime?
|
||||
|
||||
As you walk, the Elf shows you a small bag and some cubes which are either red,
|
||||
green, or blue. Each time you play this game, he will hide a secret number of
|
||||
cubes of each color in the bag, and your goal is to figure out information about
|
||||
the number of cubes.
|
||||
|
||||
Determine which games would have been possible if the bag had been loaded with
|
||||
only 12 red cubes, 13 green cubes, and 14 blue cubes. What is the sum of the IDs
|
||||
of those games?
|
||||
*/
|
||||
func ExampleDay2() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day2", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := part1.GetSecretNumber(bytes.NewReader(input), part1.Bag{
|
||||
Red: 12,
|
||||
Green: 13,
|
||||
Blue: 14,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalln("cannot get secret number:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 3035
|
||||
}
|
||||
|
||||
/*
|
||||
The Elf says they've stopped producing snow because they aren't getting any
|
||||
water! He isn't sure why the water stopped; however, he can show you how to get
|
||||
to the water source to check it out for yourself. It's just up ahead!
|
||||
|
||||
As you continue your walk, the Elf poses a second question: in each game you
|
||||
played, what is the fewest number of cubes of each color that could have been in
|
||||
the bag to make the game possible?
|
||||
|
||||
For each game, find the minimum set of cubes that must have been present. What
|
||||
is the sum of the power of these sets?
|
||||
*/
|
||||
func ExampleDay2_PartTwo() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day2", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := part2.GetPowerSum(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot get power sum:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 66027
|
||||
}
|
41
day3_test.go
41
day3_test.go
|
@ -1,41 +0,0 @@
|
|||
package adventofcode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day3/part1"
|
||||
)
|
||||
|
||||
/*
|
||||
You and the Elf eventually reach a gondola lift station; he says the gondola
|
||||
lift will take you up to the water source, but this is as far as he can bring
|
||||
you. You go inside.
|
||||
|
||||
It doesn't take long to find the gondolas, but there seems to be a problem:
|
||||
they're not moving.
|
||||
|
||||
"Aaah!"
|
||||
|
||||
You turn around to see a slightly-greasy Elf with a wrench and a look of
|
||||
surprise. "Sorry, I wasn't expecting anyone! The gondola lift isn't working
|
||||
right now; it'll still be a while before I can fix it." You offer to help.
|
||||
|
||||
The engineer explains that an engine part seems to be missing from the engine,
|
||||
but nobody can figure out which one. If you can add up all the part numbers in
|
||||
the engine schematic, it should be easy to work out which part is missing.
|
||||
*/
|
||||
func ExampleDay3() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day3", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result := part1.GetPartNumbersSum(bytes.NewReader(input))
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 540025
|
||||
}
|
81
day4_test.go
81
day4_test.go
|
@ -1,81 +0,0 @@
|
|||
package adventofcode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day4/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day4/part2"
|
||||
)
|
||||
|
||||
/*
|
||||
The gondola takes you up. Strangely, though, the ground doesn't seem to be
|
||||
coming with you; you're not climbing a mountain. As the circle of Snow Island
|
||||
recedes below you, an entire new landmass suddenly appears above you! The
|
||||
gondola carries you to the surface of the new island and lurches into the
|
||||
station.
|
||||
|
||||
As you exit the gondola, the first thing you notice is that the air here is much
|
||||
warmer than it was on Snow Island. It's also quite humid. Is this where the
|
||||
water source is?
|
||||
|
||||
The next thing you notice is an Elf sitting on the floor across the station in
|
||||
what seems to be a pile of colorful square cards.
|
||||
|
||||
"Oh! Hello!" The Elf excitedly runs over to you. "How may I be of service?" You
|
||||
ask about water sources.
|
||||
|
||||
"I'm not sure; I just operate the gondola lift. That does sound like something
|
||||
we'd have, though - this is Island Island, after all! I bet the gardener would
|
||||
know. He's on a different island, though - er, the small kind surrounded by
|
||||
water, not the floating kind. We really need to come up with a better naming
|
||||
scheme. Tell you what: if you can help me with something quick, I'll let you
|
||||
borrow my boat and you can go visit the gardener. I got all these scratchcards
|
||||
as a gift, but I can't figure out what I've won."
|
||||
|
||||
Take a seat in the large pile of colorful cards. How many points are they worth
|
||||
in total?
|
||||
*/
|
||||
func ExampleDay4() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day4", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := part1.GetTotalWorthPoints(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot get total worth:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 32001
|
||||
}
|
||||
|
||||
/*
|
||||
Just as you're about to report your findings to the Elf, one of you realizes
|
||||
that the rules have actually been printed on the back of every card this whole
|
||||
time.
|
||||
|
||||
There's no such thing as "points". Instead, scratchcards only cause you to win
|
||||
more scratchcards equal to the number of winning numbers you have.
|
||||
|
||||
Including the original set of scratchcards, how many total scratchcards do you
|
||||
end up with?
|
||||
*/
|
||||
func ExampleDay4_PartTwo() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day4", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := part2.GetTotalScratchcards(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot get total count of scratchcards:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 5037841
|
||||
}
|
74
day5_test.go
74
day5_test.go
|
@ -1,74 +0,0 @@
|
|||
package adventofcode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day5/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day5/part2"
|
||||
)
|
||||
|
||||
/*
|
||||
You take the boat and find the gardener right where you were told he would be:
|
||||
managing a giant "garden" that looks more to you like a farm.
|
||||
|
||||
"A water source? Island Island is the water source!" You point out that Snow
|
||||
Island isn't receiving any water.
|
||||
|
||||
"Oh, we had to stop the water because we ran out of sand to filter it with!
|
||||
Can't make snow with dirty water. Don't worry, I'm sure we'll get more sand
|
||||
soon; we only turned off the water a few days... weeks... oh no." His face sinks
|
||||
into a look of horrified realization.
|
||||
|
||||
"I've been so busy making sure everyone here has food that I completely forgot
|
||||
to check why we stopped getting more sand! There's a ferry leaving soon that is
|
||||
headed over in that direction - it's much faster than your boat. Could you
|
||||
please go check it out?"
|
||||
|
||||
You barely have time to agree to this request when he brings up another. "While
|
||||
you wait for the ferry, maybe you can help us with our food production problem.
|
||||
The latest Island Island Almanac just arrived and we're having trouble making
|
||||
sense of it."
|
||||
*/
|
||||
func ExampleDay5() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day5", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
almanac, err := part1.ParseAlmanac(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse almanac:", err)
|
||||
}
|
||||
|
||||
fmt.Println(almanac.FindLowestLocation())
|
||||
// Output: 551761867
|
||||
}
|
||||
|
||||
/*
|
||||
Everyone will starve if you only plant such a small number of seeds. Re-reading
|
||||
the almanac, it looks like the seeds: line actually describes ranges of seed
|
||||
numbers.
|
||||
|
||||
What is the lowest location number that corresponds to any of the initial seed
|
||||
numbers?
|
||||
*/
|
||||
func ExampleDay5_PartTwo() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day5", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
almanac, err := part2.ParseAlmanac(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse almanac:", err)
|
||||
}
|
||||
|
||||
// WARN(toby3d): Extremely slow! Took ~209 seconds to run, but returned
|
||||
// the correct result BY ANY PRICE, BUT FREE.
|
||||
fmt.Println(almanac.FindLowestLocation())
|
||||
// Output: 57451709
|
||||
}
|
68
day6_test.go
68
day6_test.go
|
@ -1,68 +0,0 @@
|
|||
package adventofcode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day6/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day6/part2"
|
||||
)
|
||||
|
||||
/*
|
||||
The ferry quickly brings you across Island Island. After asking around, you
|
||||
discover that there is indeed normally a large pile of sand somewhere near here,
|
||||
but you don't see anything besides lots of water and the small island where the
|
||||
ferry has docked.
|
||||
|
||||
As you try to figure out what to do next, you notice a poster on a wall near the
|
||||
ferry dock. "Boat races! Open to the public! Grand prize is an all-expenses-paid
|
||||
trip to Desert Island!" That must be where the sand comes from! Best of all, the
|
||||
boat races are starting in just a few minutes.
|
||||
|
||||
You manage to sign up as a competitor in the boat races just in time. The
|
||||
organizer explains that it's not really a traditional race - instead, you will
|
||||
get a fixed amount of time during which your boat has to travel as far as it
|
||||
can, and you win if your boat goes the farthest.
|
||||
|
||||
Determine the number of ways you could beat the record in each race. What do you
|
||||
get if you multiply these numbers together?
|
||||
*/
|
||||
func ExampleDay6() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day6", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
races, err := part1.ParseDocument(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse races document:", err)
|
||||
}
|
||||
|
||||
fmt.Println(races.Power())
|
||||
// Output: 505494
|
||||
}
|
||||
|
||||
/*
|
||||
As the race is about to start, you realize the piece of paper with race times
|
||||
and record distances you got earlier actually just has very bad kerning. There's
|
||||
really only one race - ignore the spaces between the numbers on each line.
|
||||
|
||||
How many ways can you beat the record in this one much longer race?
|
||||
*/
|
||||
func ExampleDay6_PartTwo() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day6", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
race, err := part2.ParseDocument(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse race document:", err)
|
||||
}
|
||||
|
||||
fmt.Println(race.CountWinningStrategies())
|
||||
// Output: 23632299
|
||||
}
|
82
day7_test.go
82
day7_test.go
|
@ -1,82 +0,0 @@
|
|||
package adventofcode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day7/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day7/part2"
|
||||
)
|
||||
|
||||
/*
|
||||
Your all-expenses-paid trip turns out to be a one-way, five-minute ride in an
|
||||
airship. (At least it's a cool airship!) It drops you off at the edge of a vast
|
||||
desert and descends back to Island Island.
|
||||
|
||||
"Did you bring the parts?"
|
||||
|
||||
You turn around to see an Elf completely covered in white clothing, wearing
|
||||
goggles, and riding a large camel.
|
||||
|
||||
"Did you bring the parts?" she asks again, louder this time. You aren't sure
|
||||
what parts she's looking for; you're here to figure out why the sand stopped.
|
||||
|
||||
"The parts! For the sand, yes! Come with me; I will show you." She beckons you
|
||||
onto the camel.
|
||||
|
||||
After riding a bit across the sands of Desert Island, you can see what look like
|
||||
very large rocks covering half of the horizon. The Elf explains that the rocks
|
||||
are all along the part of Desert Island that is directly above Island Island,
|
||||
making it hard to even get there. Normally, they use big machines to move the
|
||||
rocks and filter the sand, but the machines have broken down because Desert
|
||||
Island recently stopped receiving the parts they need to fix the machines.
|
||||
|
||||
You've already assumed it'll be your job to figure out why the parts stopped
|
||||
when she asks if you can help. You agree automatically.
|
||||
|
||||
Because the journey will take a few days, she offers to teach you the game of
|
||||
Camel Cards. Camel Cards is sort of similar to poker except it's designed to be
|
||||
easier to play while riding a camel.
|
||||
|
||||
Find the rank of every hand in your set. What are the total winnings?
|
||||
*/
|
||||
func ExampleDay7() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day7", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
camelCards, err := part1.ParseCamelCards(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse Camel Cards list:", err)
|
||||
}
|
||||
|
||||
fmt.Println(camelCards.CountTotalWinnings())
|
||||
// Output: 246795406
|
||||
}
|
||||
|
||||
/*
|
||||
To make things a little more interesting, the Elf introduces one additional
|
||||
rule. Now, J cards are jokers - wildcards that can act like whatever card would
|
||||
make the hand the strongest type possible.
|
||||
|
||||
Using the new joker rule, find the rank of every hand in your set. What are the
|
||||
new total winnings?
|
||||
*/
|
||||
func ExampleDay7_PartTwo() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day7", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
camelCards, err := part2.ParseCamelCards(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse Camel Cards list:", err)
|
||||
}
|
||||
|
||||
fmt.Println(camelCards.CountTotalWinnings())
|
||||
// Output: 249356515
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package day1_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day1/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day1/part2"
|
||||
)
|
||||
|
||||
var input []byte
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func ExampleDay1() {
|
||||
result, err := part1.Calibrate(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot sum all calibration values:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 54601
|
||||
}
|
||||
|
||||
func ExampleDay1_PartTwo() {
|
||||
result, err := part2.Calibrate(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot sum all calibration values:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 54078
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package day2_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day2/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day2/part2"
|
||||
)
|
||||
|
||||
var input []byte
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func ExampleDay2() {
|
||||
result, err := part1.GetSecretNumber(bytes.NewReader(input), part1.Bag{
|
||||
Red: 12,
|
||||
Green: 13,
|
||||
Blue: 14,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalln("cannot get secret number:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 3035
|
||||
}
|
||||
|
||||
func ExampleDay2_PartTwo() {
|
||||
result, err := part2.GetPowerSum(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot get power sum:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 66027
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package day3_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day3/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day3/part2"
|
||||
)
|
||||
|
||||
var input []byte
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func ExampleDay3() {
|
||||
fmt.Println(part1.GetPartNumbersSum(bytes.NewReader(input)))
|
||||
// Output: 540025
|
||||
}
|
||||
|
||||
func ExampleDay3_PartTwo() {
|
||||
fmt.Println(part2.ParseEngineMap(bytes.NewReader(input)).GetGearRatiosSum())
|
||||
// Output: 84584891
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
package part2
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type (
|
||||
EngineMap [][]Point
|
||||
Point byte
|
||||
|
||||
Number struct {
|
||||
value []byte
|
||||
minX int
|
||||
maxX int
|
||||
y int
|
||||
}
|
||||
|
||||
Gear struct {
|
||||
x, y int
|
||||
}
|
||||
)
|
||||
|
||||
func NewNumber(y int) *Number {
|
||||
return &Number{
|
||||
minX: 0,
|
||||
maxX: 0,
|
||||
y: y,
|
||||
value: make([]byte, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Number) Write(x int, p Point) {
|
||||
n.value = append(n.value, byte(p))
|
||||
n.maxX = x
|
||||
}
|
||||
|
||||
func (n Number) IsZero() bool {
|
||||
return len(n.value) == 0
|
||||
}
|
||||
|
||||
func (n *Number) Move(x int) {
|
||||
n.minX = x
|
||||
n.maxX = x
|
||||
}
|
||||
|
||||
func (n Number) Uint() uint {
|
||||
result, _ := strconv.ParseUint(string(n.value), 10, 64)
|
||||
|
||||
return uint(result)
|
||||
}
|
||||
|
||||
func (p Point) IsGear() bool {
|
||||
return p == '*'
|
||||
}
|
||||
|
||||
func (p Point) IsDigit() bool {
|
||||
switch p {
|
||||
default:
|
||||
return false
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (p Point) IsSymbol() bool {
|
||||
switch p {
|
||||
default:
|
||||
return true
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.':
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (p Point) IsEmpty() bool {
|
||||
return p == '.'
|
||||
}
|
||||
|
||||
func (em EngineMap) HasGearAround(n Number) *Gear {
|
||||
minx := n.minX - 1
|
||||
if minx < 0 {
|
||||
minx = 0
|
||||
}
|
||||
|
||||
maxx := n.maxX + 1
|
||||
if maxx >= len(em[0]) {
|
||||
maxx = len(em[0]) - 1
|
||||
}
|
||||
|
||||
miny := n.y - 1
|
||||
if miny < 0 {
|
||||
miny = 0
|
||||
}
|
||||
|
||||
maxy := n.y + 1
|
||||
if maxy >= len(em) {
|
||||
maxy = len(em) - 1
|
||||
}
|
||||
|
||||
for y := miny; y <= maxy; y++ {
|
||||
for x := minx; x <= maxx; x++ {
|
||||
if !em[y][x].IsGear() {
|
||||
continue
|
||||
}
|
||||
|
||||
return &Gear{
|
||||
x: x,
|
||||
y: y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseEngineMap(r io.Reader) EngineMap {
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
engineMap := make(EngineMap, 0)
|
||||
y := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Bytes()
|
||||
engineMap = append(engineMap, make([]Point, len(line)))
|
||||
|
||||
for x := range line {
|
||||
engineMap[y][x] = Point(line[x])
|
||||
}
|
||||
|
||||
y++
|
||||
}
|
||||
|
||||
return engineMap
|
||||
}
|
||||
|
||||
func (em EngineMap) GetPartNumbers() []Number {
|
||||
numbers := make([]Number, 0)
|
||||
|
||||
for y := range em {
|
||||
n := NewNumber(y)
|
||||
|
||||
for x := range em[y] {
|
||||
p := em[y][x]
|
||||
|
||||
if p.IsDigit() {
|
||||
if n.IsZero() {
|
||||
n.Move(x)
|
||||
}
|
||||
|
||||
n.Write(x, p)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if n.IsZero() {
|
||||
continue
|
||||
}
|
||||
|
||||
numbers = append(numbers, *n)
|
||||
n = NewNumber(y)
|
||||
}
|
||||
|
||||
if !n.IsZero() {
|
||||
numbers = append(numbers, *n)
|
||||
}
|
||||
}
|
||||
|
||||
return numbers
|
||||
}
|
||||
|
||||
func (em EngineMap) GetGearRatiosSum() uint64 {
|
||||
// NOTE(toby3d): Numbers are harder to find and take up more space than
|
||||
// symbols. So, instead of looking for gears all over the map, I will
|
||||
// limit myself to looking for gears around numbers and assign them to
|
||||
// the same gear point.
|
||||
gears := make(map[Gear][]Number)
|
||||
|
||||
for _, number := range em.GetPartNumbers() {
|
||||
gear := em.HasGearAround(number)
|
||||
if gear == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := gears[*gear]; !ok {
|
||||
gears[*gear] = make([]Number, 0)
|
||||
}
|
||||
|
||||
gears[*gear] = append(gears[*gear], number)
|
||||
}
|
||||
|
||||
var result uint64
|
||||
for _, numbers := range gears {
|
||||
if len(numbers) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
result += uint64(numbers[0].Uint()) * uint64(numbers[1].Uint())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package part2_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day3/part2"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
input := "467..114..\n" +
|
||||
"...*......\n" +
|
||||
"..35..633.\n" +
|
||||
"......#...\n" +
|
||||
"617*......\n" +
|
||||
".....+.58.\n" +
|
||||
"..592.....\n" +
|
||||
"......755.\n" +
|
||||
"...$.*....\n" +
|
||||
".664.598.."
|
||||
|
||||
engineMap := part2.ParseEngineMap(strings.NewReader(input))
|
||||
|
||||
fmt.Println(engineMap.GetGearRatiosSum())
|
||||
// Output: 467835
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package day4_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day4/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day4/part2"
|
||||
)
|
||||
|
||||
var input []byte
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func ExampleDay4() {
|
||||
result, err := part1.GetTotalWorthPoints(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot get total worth:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 32001
|
||||
}
|
||||
|
||||
func ExampleDay4_PartTwo() {
|
||||
result, err := part2.GetTotalScratchcards(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot get total count of scratchcards:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 5037841
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package day5_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day5/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day5/part2"
|
||||
)
|
||||
|
||||
var input []byte
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func ExampleDay5() {
|
||||
almanac, err := part1.ParseAlmanac(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse almanac:", err)
|
||||
}
|
||||
|
||||
fmt.Println(almanac.FindLowestLocation())
|
||||
// Output: 551761867
|
||||
}
|
||||
|
||||
func ExampleDay5_PartTwo() {
|
||||
almanac, err := part2.ParseAlmanac(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse almanac:", err)
|
||||
}
|
||||
|
||||
// WARN(toby3d): Extremely slow! Took ~209 seconds to run, but returned
|
||||
// the correct result BY ANY PRICE, BUT FREE.
|
||||
fmt.Println(almanac.FindLowestLocation())
|
||||
// Output: 57451709
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package day6_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day6/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day6/part2"
|
||||
)
|
||||
|
||||
var input []byte
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func ExampleDay6() {
|
||||
races, err := part1.ParseDocument(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse races document:", err)
|
||||
}
|
||||
|
||||
fmt.Println(races.Power())
|
||||
// Output: 505494
|
||||
}
|
||||
|
||||
func ExampleDay6_PartTwo() {
|
||||
race, err := part2.ParseDocument(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse race document:", err)
|
||||
}
|
||||
|
||||
fmt.Println(race.CountWinningStrategies())
|
||||
// Output: 23632299
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package day7_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day7/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day7/part2"
|
||||
)
|
||||
|
||||
var input []byte
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func ExampleDay7() {
|
||||
camelCards, err := part1.ParseCamelCards(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse Camel Cards list:", err)
|
||||
}
|
||||
|
||||
fmt.Println(camelCards.CountTotalWinnings())
|
||||
// Output: 246795406
|
||||
}
|
||||
|
||||
func ExampleDay7_PartTwo() {
|
||||
camelCards, err := part2.ParseCamelCards(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot parse Camel Cards list:", err)
|
||||
}
|
||||
|
||||
fmt.Println(camelCards.CountTotalWinnings())
|
||||
// Output: 249356515
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package day8_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day8/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day8/part2"
|
||||
)
|
||||
|
||||
var input []byte
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if input, err = os.ReadFile(filepath.Join("testdata", "input")); err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func ExampleDay8() {
|
||||
fmt.Println(part1.ParseNetworkMap(bytes.NewReader(input)).CountSteps())
|
||||
// Output: 19631
|
||||
}
|
||||
|
||||
func ExampleDay8_PartTwo() {
|
||||
fmt.Println(part2.ParseNetworkMap(bytes.NewReader(input)).CountSteps())
|
||||
// Output: 21003205388413
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package part1
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
)
|
||||
|
||||
type (
|
||||
NetworkMap struct {
|
||||
Forks map[Node]Fork
|
||||
Directions []Direction
|
||||
}
|
||||
|
||||
Fork struct {
|
||||
Left Node
|
||||
Right Node
|
||||
}
|
||||
|
||||
Node [3]byte
|
||||
|
||||
Direction byte
|
||||
)
|
||||
|
||||
var (
|
||||
NodeUnd Node = [3]byte{0, 0, 0}
|
||||
NodeStart Node = [3]byte{'A', 'A', 'A'}
|
||||
NodeEnd Node = [3]byte{'Z', 'Z', 'Z'}
|
||||
)
|
||||
|
||||
var (
|
||||
DirectionLeft Direction = 'L'
|
||||
DirectionRight Direction = 'R'
|
||||
)
|
||||
|
||||
func (f Fork) Peek(d Direction) Node {
|
||||
switch d {
|
||||
default:
|
||||
return NodeUnd
|
||||
case DirectionLeft:
|
||||
return f.Left
|
||||
case DirectionRight:
|
||||
return f.Right
|
||||
}
|
||||
}
|
||||
|
||||
func ParseNetworkMap(r io.Reader) *NetworkMap {
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
networkMap := &NetworkMap{
|
||||
Directions: make([]Direction, 0),
|
||||
Forks: make(map[Node]Fork),
|
||||
}
|
||||
|
||||
scanner.Scan()
|
||||
for _, b := range scanner.Text() {
|
||||
networkMap.Directions = append(networkMap.Directions, Direction(b))
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
node := Node([3]byte{line[0], line[1], line[2]})
|
||||
leftNode := Node([3]byte{line[7], line[8], line[9]})
|
||||
rightNode := Node([3]byte{line[12], line[13], line[14]})
|
||||
networkMap.Forks[node] = Fork{
|
||||
Left: leftNode,
|
||||
Right: rightNode,
|
||||
}
|
||||
}
|
||||
|
||||
return networkMap
|
||||
}
|
||||
|
||||
func (nm NetworkMap) CountSteps() uint64 {
|
||||
var steps uint64
|
||||
node := NodeStart
|
||||
|
||||
for i := 0; node != NodeEnd; i++ {
|
||||
i = i % len(nm.Directions)
|
||||
node = nm.Forks[node].Peek(nm.Directions[i])
|
||||
steps++
|
||||
}
|
||||
|
||||
return steps
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package part1_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day8/part1"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
input := "RL\n" +
|
||||
"\n" +
|
||||
"AAA = (BBB, CCC)\n" +
|
||||
"BBB = (DDD, EEE)\n" +
|
||||
"CCC = (ZZZ, GGG)\n" +
|
||||
"DDD = (DDD, DDD)\n" +
|
||||
"EEE = (EEE, EEE)\n" +
|
||||
"GGG = (GGG, GGG)\n" +
|
||||
"ZZZ = (ZZZ, ZZZ)"
|
||||
|
||||
fmt.Println(part1.ParseNetworkMap(strings.NewReader(input)).CountSteps())
|
||||
// Output: 2
|
||||
}
|
||||
|
||||
func ExampleRepeat() {
|
||||
input := "LLR\n" +
|
||||
"\n" +
|
||||
"AAA = (BBB, BBB)\n" +
|
||||
"BBB = (AAA, ZZZ)\n" +
|
||||
"ZZZ = (ZZZ, ZZZ)"
|
||||
|
||||
fmt.Println(part1.ParseNetworkMap(strings.NewReader(input)).CountSteps())
|
||||
// Output: 6
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
package part2
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type (
|
||||
NetworkMap struct {
|
||||
Starts []Node
|
||||
Forks map[Node]Fork
|
||||
Directions []Direction
|
||||
}
|
||||
|
||||
Fork struct {
|
||||
Left Node
|
||||
Right Node
|
||||
}
|
||||
|
||||
Ghost struct {
|
||||
Steps uint64
|
||||
Position Node
|
||||
}
|
||||
|
||||
Node [3]byte
|
||||
|
||||
Direction byte
|
||||
)
|
||||
|
||||
var NodeUnd Node = [3]byte{0, 0, 0}
|
||||
|
||||
var (
|
||||
DirectionLeft Direction = 'L'
|
||||
DirectionRight Direction = 'R'
|
||||
)
|
||||
|
||||
func (n Node) IsStart() bool {
|
||||
return n[2] == 'A'
|
||||
}
|
||||
|
||||
func (n Node) IsEnd() bool {
|
||||
return n[2] == 'Z'
|
||||
}
|
||||
|
||||
func (f Fork) Peek(d Direction) Node {
|
||||
switch d {
|
||||
default:
|
||||
return NodeUnd
|
||||
case DirectionLeft:
|
||||
return f.Left
|
||||
case DirectionRight:
|
||||
return f.Right
|
||||
}
|
||||
}
|
||||
|
||||
func ParseNetworkMap(r io.Reader) *NetworkMap {
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
networkMap := &NetworkMap{
|
||||
Directions: make([]Direction, 0),
|
||||
Forks: make(map[Node]Fork),
|
||||
}
|
||||
|
||||
scanner.Scan()
|
||||
for _, b := range scanner.Text() {
|
||||
networkMap.Directions = append(networkMap.Directions, Direction(b))
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
node := Node([3]byte{line[0], line[1], line[2]})
|
||||
|
||||
if node.IsStart() {
|
||||
networkMap.Starts = append(networkMap.Starts, node)
|
||||
}
|
||||
|
||||
leftNode := Node([3]byte{line[7], line[8], line[9]})
|
||||
rightNode := Node([3]byte{line[12], line[13], line[14]})
|
||||
networkMap.Forks[node] = Fork{
|
||||
Left: leftNode,
|
||||
Right: rightNode,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return networkMap
|
||||
}
|
||||
|
||||
func (nm NetworkMap) moveGhost(g *Ghost) {
|
||||
for {
|
||||
g.Position = nm.Forks[g.Position].Peek(nm.Directions[int(g.Steps)%len(nm.Directions)])
|
||||
g.Steps++
|
||||
|
||||
if !g.Position.IsEnd() {
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func (nm NetworkMap) CountSteps() uint64 {
|
||||
ghosts := make([]*Ghost, len(nm.Starts))
|
||||
wg := new(sync.WaitGroup)
|
||||
|
||||
for i := range ghosts {
|
||||
ghosts[i] = &Ghost{
|
||||
Position: nm.Starts[i],
|
||||
Steps: 0,
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(ghost *Ghost) {
|
||||
nm.moveGhost(ghost)
|
||||
wg.Done()
|
||||
}(ghosts[i])
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
steps := make([]uint64, len(ghosts))
|
||||
for i := range ghosts {
|
||||
steps[i] = ghosts[i].Steps
|
||||
}
|
||||
|
||||
return lcm(steps...)
|
||||
}
|
||||
|
||||
// NOTE(toby3d): adapted version of the python code from here:
|
||||
// https://www.geeksforgeeks.org/finding-lcm-two-array-numbers-without-using-gcd/
|
||||
//
|
||||
// Thanks /r/adventofcode for memes about this day puzzle. Today I know what the
|
||||
// fuck is LCM mean.
|
||||
func lcm(inputs ...uint64) uint64 {
|
||||
var maxNum uint64
|
||||
|
||||
for i := range inputs {
|
||||
maxNum = max(maxNum, inputs[i])
|
||||
}
|
||||
|
||||
var result, factor uint64 = 1, 2
|
||||
|
||||
for factor <= maxNum {
|
||||
indexes := make([]int, 0, len(inputs))
|
||||
|
||||
for i := range inputs {
|
||||
if inputs[i]%factor == 0 {
|
||||
indexes = append(indexes, i)
|
||||
}
|
||||
}
|
||||
|
||||
if len(indexes) >= 2 {
|
||||
for i := range indexes {
|
||||
inputs[indexes[i]] = inputs[indexes[i]] / factor
|
||||
}
|
||||
|
||||
result *= factor
|
||||
} else {
|
||||
factor++
|
||||
}
|
||||
}
|
||||
|
||||
for i := range inputs {
|
||||
result *= inputs[i]
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (d Direction) String() string {
|
||||
switch d {
|
||||
default:
|
||||
return ""
|
||||
case DirectionLeft:
|
||||
return "left"
|
||||
case DirectionRight:
|
||||
return "right"
|
||||
}
|
||||
}
|
||||
|
||||
func (d Direction) GoString() string {
|
||||
return "part2.Direction(" + string(d) + ")"
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package part2_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day8/part2"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
input := "LR\n" +
|
||||
"\n" +
|
||||
"11A = (11B, XXX)\n" +
|
||||
"11B = (XXX, 11Z)\n" +
|
||||
"11Z = (11B, XXX)\n" +
|
||||
"22A = (22B, XXX)\n" +
|
||||
"22B = (22C, 22C)\n" +
|
||||
"22C = (22Z, 22Z)\n" +
|
||||
"22Z = (22B, 22B)\n" +
|
||||
"XXX = (XXX, XXX)"
|
||||
|
||||
fmt.Println(part2.ParseNetworkMap(strings.NewReader(input)).CountSteps())
|
||||
// Output: 6
|
||||
}
|
Loading…
Reference in New Issue