Skip to content

Commit b1847bf

Browse files
14-2023 Part 2 + 15-2023 both parts
1 parent cf83f9e commit b1847bf

File tree

15 files changed

+788
-38
lines changed

15 files changed

+788
-38
lines changed

2023/Day14/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,56 @@ The total load is the sum of the load caused by all of the <em>rounded rocks</em
6363
Tilt the platform so that the rounded rocks all roll north. Afterward, <em>what is the total load on the north support beams?</em>
6464

6565

66+
## --- Part Two ---
67+
The parabolic reflector dish deforms, but not in a way that focuses the beam. To do that, you'll need to move the rocks to the edges of the platform. Fortunately, a button on the side of the control panel labeled "<em>spin cycle</em>" attempts to do just that!
68+
69+
Each <em>cycle</em> tilts the platform four times so that the rounded rocks roll <em>north</em>, then <em>west</em>, then <em>south</em>, then <em>east</em>. After each tilt, the rounded rocks roll as far as they can before the platform tilts in the next direction. After one cycle, the platform will have finished rolling the rounded rocks in those four directions in that order.
70+
71+
Here's what happens in the example above after each of the first few cycles:
72+
73+
<pre>
74+
<code>After 1 cycle:
75+
.....#....
76+
....#...O#
77+
...OO##...
78+
.OO#......
79+
.....OOO#.
80+
.O#...O#.#
81+
....O#....
82+
......OOOO
83+
#...O###..
84+
#..OO#....
85+
86+
After 2 cycles:
87+
.....#....
88+
....#...O#
89+
.....##...
90+
..O#......
91+
.....OOO#.
92+
.O#...O#.#
93+
....O#...O
94+
.......OOO
95+
#..OO###..
96+
#.OOO#...O
97+
98+
After 3 cycles:
99+
.....#....
100+
....#...O#
101+
.....##...
102+
..O#......
103+
.....OOO#.
104+
.O#...O#.#
105+
....O#...O
106+
.......OOO
107+
#...O###.O
108+
#.OOO#...O
109+
</code>
110+
</pre>
111+
112+
This process should work if you leave it running long enough, but you're still worried about the north support beams. To make sure they'll survive for a while, you need to calculate the <em>total load</em> on the north support beams after <code>1000000000</code> cycles.
113+
114+
In the above example, after <code>1000000000</code> cycles, the total load on the north support beams is <code><em>64</em></code>.
115+
116+
Run the spin cycle for <code>1000000000</code> cycles. Afterward, <em>what is the total load on the north support beams?</em>
117+
118+

2023/Day14/Solution.cs

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Collections.Immutable;
4-
using System.Linq;
5-
using System.Text.RegularExpressions;
6-
using System.Text;
73
using adventofcode.Utils;
8-
using AngleSharp.Common;
9-
using AngleSharp.Html.Dom;
104

115
namespace AdventOfCode.Y2023.Day14;
126

@@ -80,6 +74,90 @@ public object PartOne(string input)
8074

8175
public object PartTwo(string input)
8276
{
83-
return 0;
77+
// For part 2, I used Go/Golang, check out the go.txt file
78+
var grid = new Grid(input, true);
79+
long result = 0;
80+
81+
for (var i = 0; i < 200; i++)
82+
{
83+
while (RollRocks(grid)) ;
84+
grid.Rotate(Orientation.East);
85+
while (RollRocks(grid)) ;
86+
grid.Rotate(Orientation.East);
87+
while (RollRocks(grid)) ;
88+
grid.Rotate(Orientation.East);
89+
while (RollRocks(grid)) ;
90+
grid.Rotate(Orientation.East);
91+
}
92+
var cycleVals = new List<long>();
93+
for (var i = 0; i < 200; i++)
94+
{
95+
while (RollRocks(grid)) ;
96+
grid.Rotate(Orientation.East);
97+
while (RollRocks(grid)) ;
98+
grid.Rotate(Orientation.East);
99+
while (RollRocks(grid)) ;
100+
grid.Rotate(Orientation.East);
101+
while (RollRocks(grid)) ;
102+
grid.Rotate(Orientation.East);
103+
104+
var v = CalcLoad(grid);
105+
106+
if (cycleVals.Contains(v))
107+
{
108+
var j = cycleVals.LastIndexOf(v);
109+
var cycleLen = (i - j);
110+
111+
var q = (1000000000 - 200 - i -1) % cycleLen;
112+
113+
var n = (q + j) % cycleLen;
114+
result = cycleVals[n];
115+
116+
break;
117+
}
118+
119+
cycleVals.Add(v);
120+
}
121+
122+
return result;
123+
}
124+
125+
private static bool RollRocks(Grid grid)
126+
{
127+
var didShift = false;
128+
for (var y = grid.MinY; y + 1 < grid.MaxY; y++)
129+
{
130+
for (var x = grid.MinX; x < grid.MaxX; x++)
131+
{
132+
if (grid[x, y] == '.' && grid[x, y + 1] == 'O')
133+
{
134+
grid[x, y + 1] = '.';
135+
grid[x, y] = 'O';
136+
didShift = true;
137+
}
138+
}
139+
}
140+
141+
return didShift;
142+
}
143+
144+
private static long CalcLoad(Grid grid)
145+
{
146+
var result = 0L;
147+
grid.Rotate(Orientation.South);
148+
149+
for (var y = grid.MinY; y < grid.MaxY; y++)
150+
{
151+
for (var x = grid.MinX; x < grid.MaxX; x++)
152+
{
153+
if (grid[x, y] == 'O')
154+
{
155+
result += y + 1;
156+
}
157+
}
158+
}
159+
160+
grid.Rotate(Orientation.South);
161+
return result;
84162
}
85-
}
163+
}

2023/Day14/go.txt

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"log"
7+
"os"
8+
"time"
9+
)
10+
11+
const ObjRock = byte('O')
12+
const ObjEmpty = byte('.')
13+
14+
var directions = [][]int{
15+
{0, -1}, // N
16+
{-1, 0}, // W
17+
{0, 1}, // S
18+
{1, 0}, // E
19+
}
20+
21+
func tilt(grid [][]byte, dir []int) {
22+
width := len(grid[0])
23+
height := len(grid)
24+
25+
startCol := 0
26+
colStep := 1
27+
if dir[0] == 1 {
28+
startCol = width - 1
29+
colStep = -1
30+
}
31+
startRow := 0
32+
rowStep := 1
33+
if dir[1] == 1 {
34+
startRow = height - 1
35+
rowStep = -1
36+
}
37+
38+
for row := startRow; row < height && row >= 0; row += rowStep {
39+
for col := startCol; col < width && col >= 0; col += colStep {
40+
if grid[row][col] != ObjRock {
41+
continue
42+
}
43+
44+
// walk into direction until obstacle
45+
c := col
46+
r := row
47+
for c+dir[0] >= 0 && c+dir[0] < width && r+dir[1] >= 0 && r+dir[1] < height && grid[r+dir[1]][c+dir[0]] == ObjEmpty {
48+
c += dir[0]
49+
r += dir[1]
50+
}
51+
52+
// place rock at new position
53+
if r != row || c != col {
54+
grid[r][c] = ObjRock
55+
grid[row][col] = ObjEmpty
56+
}
57+
}
58+
}
59+
}
60+
61+
func weight(grid [][]byte) int {
62+
width := len(grid[0])
63+
height := len(grid)
64+
weight := 0
65+
66+
for row := 0; row < height; row++ {
67+
for col := 0; col < width; col++ {
68+
if grid[row][col] != ObjRock {
69+
continue
70+
}
71+
72+
weight += height - row
73+
}
74+
}
75+
76+
return weight
77+
}
78+
79+
func isEqual(a [][]byte, b [][]byte) bool {
80+
for row := 0; row < len(a); row++ {
81+
if !bytes.Equal(a[row], b[row]) {
82+
return false
83+
}
84+
}
85+
86+
return true
87+
}
88+
89+
func copyGrid(a [][]byte) [][]byte {
90+
rows := make([][]byte, len(a))
91+
92+
for i := range a {
93+
rows[i] = make([]byte, len(a[i]))
94+
copy(rows[i], a[i])
95+
}
96+
return rows
97+
}
98+
99+
// Floyd's Tortoise and Hare algorithm
100+
// https://en.wikipedia.org/wiki/Cycle_detection
101+
func floyd(f func([][]byte), x0 [][]byte) (int, [][]byte) {
102+
hare := copyGrid(x0)
103+
tortoise := copyGrid(x0)
104+
105+
f(tortoise)
106+
f(hare)
107+
f(hare)
108+
109+
for !isEqual(tortoise, hare) {
110+
f(tortoise)
111+
f(hare)
112+
f(hare)
113+
}
114+
115+
// move hare forward until start of next cycle
116+
// tortoise remains in place
117+
cycleLength := 1
118+
f(hare)
119+
for !isEqual(tortoise, hare) {
120+
f(hare)
121+
cycleLength += 1
122+
}
123+
124+
// return length of cycle and current state of grid
125+
return cycleLength, hare
126+
}
127+
128+
func main() {
129+
timeStart := time.Now()
130+
131+
b, err := os.ReadFile("input.txt")
132+
if err != nil {
133+
log.Fatal(err)
134+
}
135+
grid := bytes.Split(bytes.TrimSpace(b), []byte("\n"))
136+
137+
// pt1
138+
grid1 := copyGrid(grid)
139+
tilt(grid1, directions[0])
140+
pt1 := weight(grid1)
141+
timeElapsed := time.Since(timeStart)
142+
timeStart2 := time.Now()
143+
// part 2
144+
cycle := func(g [][]byte) {
145+
tilt(g, directions[0])
146+
tilt(g, directions[1])
147+
tilt(g, directions[2])
148+
tilt(g, directions[3])
149+
}
150+
cycleLength, state := floyd(cycle, grid)
151+
cyclesRemaining := 1e9 % cycleLength
152+
for i := 0; i < cyclesRemaining; i++ {
153+
cycle(state)
154+
}
155+
156+
pt2 := weight(state)
157+
fmt.Printf("--- Day 14: Parabolic Reflector Dish ---\n")
158+
fmt.Printf("Part 1: %d | %.2fms\n", pt1, float64(timeElapsed.Microseconds())/1000)
159+
fmt.Printf("Part 2: %d | %.2fms\n", pt2, float64(time.Since(timeStart2).Microseconds())/1000)
160+
fmt.Printf("Time: %.2fms\n", float64(time.Since(timeStart).Microseconds())/1000)
161+
}

2023/Day14/input.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,4 @@ O..O.#O..OOO..O...O...#.......#O.OO....O..#...O.....O.#.OO....#.O.OO...O#...OOO#
9797
O....#....#O.####.O...#....O....#O..#O...O.O....O.O#..O.........O#.......O....O..O...#.##..O.OO.OO..
9898
.O###O...#OO.OO........O.O#.O.O....O.O...##.O#..###..........#..O#.O..O.OO.O..#O#OO..O#.O.##.O.OOO##
9999
#.#O#..O.#...O#..#.......O#..#...#...#O..#.O.....O...O.......#O.#...#OO.O....OO..O...#.#....#O......
100-
..O.#O.O.O#..#.O...#.....#..O..##..O......O.OO.O.###.....#.O..O...OO#.OO.....#...OO#O..#..#O#...O..O
100+
..O.#O.O.O#..#.O...#.....#..O..##..O......O.OO.O.###.....#.O..O...OO#.OO.....#...OO#O..#..#O#...O..O

2023/Day14/input.refout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
108792
2+
99118

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy