Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion docs/day1.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,38 @@ In the example list above, the pairs and distances would be as follows:

To find the total distance between the left list and the right list, add up the distances between all of the pairs you found. In the example above, this is `2 + 1 + 0 + 1 + 2 + 5`, a total distance of `11`!

Your actual left and right lists contain many location IDs. What is the total distance between your lists?
Your actual left and right lists contain many location IDs. What is the total distance between your lists?

### Part Two

Your analysis only confirmed what everyone feared: the two lists of location IDs are indeed very different.

Or are they?

The Historians can't agree on which group made the mistakes or how to read most of the Chief's handwriting, but in the commotion you notice an interesting detail: a lot of location IDs appear in both lists! Maybe the other numbers aren't location IDs at all but rather misinterpreted handwriting.

This time, you'll need to figure out exactly how often each number from the left list appears in the right list. Calculate a total similarity score by adding up each number in the left list after multiplying it by the number of times that number appears in the right list.

Here are the same example lists again:

```txt
3 4
4 3
2 5
1 3
3 9
3 3
```

For these example lists, here is the process of finding the similarity score:

* The first number in the left list is `3`. It appears in the right list three times, so the similarity score increases by `3 * 3 = 9`.
* The second number in the left list is `4`. It appears in the right list once, so the similarity score increases by `4 * 1 = 4`.
* The third number in the left list is `2`. It does not appear in the right list, so the similarity score does not increase `(2 * 0 = 0)`.
* The fourth number, `1`, also does not appear in the right list.
* The fifth number, `3`, appears in the right list three times; the similarity score increases by `9`.
* The last number, `3`, appears in the right list three times; the similarity score again increases by `9`.

So, for these example lists, the similarity score at the end of this process is `31` `(9 + 4 + 0 + 0 + 9 + 9)`.

Once again consider your left and right lists. What is their similarity score?
21 changes: 21 additions & 0 deletions docs/day2.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,24 @@ In the example above, the reports can be found safe or unsafe by checking those
So, in this example, `2` reports are safe.

Analyze the unusual data from the engineers. How many reports are safe?

### Part Two

The engineers are surprised by the low number of safe reports until they realize they forgot to tell you about the Problem Dampener.

The Problem Dampener is a reactor-mounted module that lets the reactor safety systems tolerate a single bad level in what would otherwise be a safe report. It's like the bad level never happened!

Now, the same rules apply as before, except if removing a single level from an unsafe report would make it safe, the report instead counts as safe.

More of the above example's reports are now safe:

* `7 6 4 2 1`: Safe without removing any level.
* `1 2 7 8 9`: Unsafe regardless of which level is removed.
* `9 7 6 2 1`: Unsafe regardless of which level is removed.
* `1 3 2 4 5`: Safe by removing the second level, `3`.
* `8 6 4 4 1`: Safe by removing the third level, `4`.
* `1 3 6 7 9`: Safe without removing any level.

Thanks to the Problem Dampener, `4` reports are actually safe!

Update your analysis by handling situations where the Problem Dampener can remove a single level from unsafe reports. How many reports are now safe?
19 changes: 16 additions & 3 deletions src/day1/day1.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ func Solve(input string) uint {
return solve(parseInput(input))
}

func PartTwo(input string) uint {
left, right := parseInput(input)
occurances := make(map[uint]uint)
for _, r := range right {
occurances[r] += 1
}
var result uint = 0
for _, l := range left {
result += l * occurances[l]
}
return result
}

func parseInput(input string) ([]uint, []uint) {
var a, b []uint
for _, line := range strings.Split(input, "\n") {
Expand All @@ -22,9 +35,9 @@ func parseInput(input string) ([]uint, []uint) {
}

x, _ := strconv.Atoi(values[0])
a = slices.Concat(a, []uint{uint(x)})
a = append(a, uint(x))
y, _ := strconv.Atoi(values[1])
b = slices.Concat(b, []uint{uint(y)})
b = append(b, uint(y))
}
return a, b
}
Expand All @@ -34,7 +47,7 @@ func solve(a, b []uint) uint {
slices.Sort(b)
var sum uint = 0
for i := range a {
sum = sum + absDiffUint(a[i], b[i])
sum += absDiffUint(a[i], b[i])
}
return sum
}
Expand Down
13 changes: 13 additions & 0 deletions src/day1/day1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,16 @@ func TestSample(t *testing.T) {
t.Errorf("Calculated solution was not expected")
}
}

func TestSamplePartTwo(t *testing.T) {
input := `3 4
4 3
2 5
1 3
3 9
3 3`
result := PartTwo(input)
if result != 31 {
t.Errorf("Calculated solution was not expected")
}
}
49 changes: 38 additions & 11 deletions src/day2/day2.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ type level uint
type report []level

func Solve(input string) uint {
return solve(parseInput(input))
return solve(parseInput(input), 0)
}

func PartTwo(input string) uint {
return solve(parseInput(input), 1)
}

func parseInput(input string) []report {
Expand All @@ -33,32 +37,55 @@ func parseInput(input string) []report {
return result
}

func solve(input []report) uint {
func solve(input []report, tolerance uint) uint {
var result uint = 0
for _, report := range input {
if isValidReport(report) {
if isValidReport(report, tolerance) {
result += 1
}
}
return result
}

func isValidReport(report report) bool {
func isValidReport(report report, tolerance uint) bool {
if len(report) < 2 {
return true
}

prev := report[0]
var violations uint = 0
ascending := report[1] > report[0]
for i, level := range report {
if i == 0 {
continue
i := 0
for {
i++
if i > len(report)-1 {
break
}

if !isValidDelta(level, prev) || !isValidTrajectory(ascending, level, prev) {
return false
if !isValidDelta(report[i], report[i-1]) || !isValidTrajectory(ascending, report[i], report[i-1]) {
violations++
if violations > tolerance {
return false
}

selfRemoved := slices.Concat(report[0:i], report[i+1:])
valid := isValidReport(selfRemoved, tolerance-violations)
if valid {
return true
}

prevRemoved := slices.Concat(report[0:i-1], report[i:])
valid = isValidReport(prevRemoved, tolerance-violations)
if valid {
return true
}

if i == 1 {
return false
}
twoBackRemoved := slices.Concat(report[0:i-2], report[i-1:])
valid = isValidReport(twoBackRemoved, tolerance-violations)
return valid
}
prev = level
}
return true
}
Expand Down
61 changes: 61 additions & 0 deletions src/day2/day2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,64 @@ func TestSample(t *testing.T) {
t.Errorf("Calculated solution was not expected")
}
}

func TestSamplePartTwo(t *testing.T) {
input := `7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9`
result := PartTwo(input)
if result != 4 {
t.Errorf("Calculated solution was not expected")
}
}

func TestPartTwoFirstTooLarge(t *testing.T) {
input := `1 5 6 7 8`
result := PartTwo(input)
if result != 1 {
t.Errorf("Calculated solution was not expected")
}
}

func TestPartTwoFirstThrowsTraj(t *testing.T) {
input := `4 5 4 3 2`
result := PartTwo(input)
if result != 1 {
t.Errorf("Calculated solution was not expected")
}
}

func TestPartTwoLastTooLarge(t *testing.T) {
input := `1 2 3 4 9`
result := PartTwo(input)
if result != 1 {
t.Errorf("Calculated solution was not expected")
}
}

func TestPartTwoLastThrowsTraj(t *testing.T) {
input := `5 4 3 2 3`
result := PartTwo(input)
if result != 1 {
t.Errorf("Calculated solution was not expected")
}
}

func TestPartTwo2ndLastTooLarge(t *testing.T) {
input := `9 8 7 4 5`
result := PartTwo(input)
if result != 1 {
t.Errorf("Calculated solution was not expected")
}
}

func TestPartTwo2ndLastThrowsTraj(t *testing.T) {
input := `5 4 3 4 1`
result := PartTwo(input)
if result != 1 {
t.Errorf("Calculated solution was not expected")
}
}
Loading