aboutsummaryrefslogtreecommitdiff
path: root/2022/17
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-07-04 15:32:49 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2025-07-04 15:32:49 +0200
commit19b7ee46b55ed25f77fd030ccc473c8cf95e07b5 (patch)
tree80846c02487cb1424c4c6778f9771ab981b0b822 /2022/17
parent36c94296df6edce01db71afeadb8940e33ecdd4a (diff)
downloadaoc-19b7ee46b55ed25f77fd030ccc473c8cf95e07b5.tar.gz
aoc-19b7ee46b55ed25f77fd030ccc473c8cf95e07b5.zip
Day 17 2022 bleah
Diffstat (limited to '2022/17')
-rw-r--r--2022/17/a.rs16
-rw-r--r--2022/17/b.rs93
-rw-r--r--2022/17/common.rs85
3 files changed, 194 insertions, 0 deletions
diff --git a/2022/17/a.rs b/2022/17/a.rs
new file mode 100644
index 0000000..18e72e4
--- /dev/null
+++ b/2022/17/a.rs
@@ -0,0 +1,16 @@
1mod common;
2use common::*;
3
4fn main() {
5 let mut screen = Screen::new();
6 let rocks = get_rocks();
7 let mut line = String::new();
8 let _ = std::io::stdin().read_line(&mut line);
9 let line = &line[0..line.len()-1]; // remove newline
10
11 let mut t = 0;
12 for i in 0..2022 {
13 screen.drop_rock(&rocks[i%5], &mut t, &line);
14 }
15 println!("{}", screen.top);
16}
diff --git a/2022/17/b.rs b/2022/17/b.rs
new file mode 100644
index 0000000..261dff4
--- /dev/null
+++ b/2022/17/b.rs
@@ -0,0 +1,93 @@
1// Wow this is was terrible. Clearly you have to find out at which
2// exact frequency the shape repeats, but I could not find a good
3// way to estimate this apart from computing the first few (10^5)
4// rows and then manually checking.
5
6mod common;
7use common::*;
8
9fn line_to_u8(line: &[bool]) -> u8 {
10 let mut r = 0;
11 for i in 0..SCREEN_WIDTH {
12 if line[i] { r |= 1 << i as u8; }
13 }
14 r
15}
16
17fn write_lines(screen: &Screen, v: &mut [u8]) {
18 for i in 0..SCREEN_HEIGHT {
19 v[i] = line_to_u8(&screen.cell[i]);
20 }
21}
22
23fn isperiod(v: &[u8], l: usize) -> bool {
24 const PERIOD_GUESS: usize = 10;
25 const TIMES_MATCH: usize = 10;
26
27 for i in 0..PERIOD_GUESS {
28 for j in 1..TIMES_MATCH {
29 if v[i] != v[i+j*l] { return false; }
30 }
31 }
32 true
33}
34
35fn find_period(v: &[u8]) -> (usize, usize) {
36 const PREP: usize = 1000;
37 const PMAX: usize = 10000;
38
39 for start in 0..PREP {
40 for plen in 10..PMAX {
41 if isperiod(&v[start..], plen) { return (start+1, plen); }
42 }
43 }
44 panic!("No period of length < {} found with preperiod < {}",
45 PMAX, PREP);
46}
47
48fn main() {
49 const N: usize = 1000000000000;
50
51 let mut screen = Screen::new();
52 let rocks = get_rocks();
53 let mut line = String::new();
54 let _ = std::io::stdin().read_line(&mut line);
55 let line = &line[0..line.len()-1]; // remove newline
56
57 let mut i = 0;
58 let mut t = 0;
59 let mut vv = [0 as u8; SCREEN_HEIGHT];
60 let mut ii = [0 as usize; SCREEN_HEIGHT];
61 while screen.top < SCREEN_HEIGHT - 10 {
62 screen.drop_rock(&rocks[i%5], &mut t, &line);
63 ii[screen.top] = i;
64 i += 1;
65 }
66 write_lines(&screen, &mut vv);
67 let (prep, plen) = find_period(&vv);
68
69 /* This part shows the period etc...
70 println!("prep = {prep}, plen = {plen}");
71 for j in 0..10 {
72 for k in 0..4 {
73 print!(" | t={:>4} i={:>4}", j+prep+k*plen, ii[j+prep+k*plen]);
74 }
75 println!();
76 }
77 */
78
79 let i0 = ii[prep];
80 let i1 = ii[prep+plen];
81
82 let n = (N - i0) / (i1 - i0); // How many full repeats
83 let t = n * plen + prep; // How tall is the thing after n full repeats
84 // Remainder (unlike in the example case, it does not end with full repeat)
85 let mut rem = 0;
86 for j in 0..SCREEN_HEIGHT {
87 if ii[j] >= i0 + (N - i0) % (i1 - i0) {
88 rem = j-prep;
89 break;
90 }
91 }
92 println!("{}", t + rem - 1);
93}
diff --git a/2022/17/common.rs b/2022/17/common.rs
new file mode 100644
index 0000000..d27ec3a
--- /dev/null
+++ b/2022/17/common.rs
@@ -0,0 +1,85 @@
1use std::cmp::max;
2
3pub const SCREEN_WIDTH: usize = 7;
4pub const SCREEN_HEIGHT: usize = 100000;
5
6pub struct Screen {
7 pub cell: [[bool; SCREEN_WIDTH]; SCREEN_HEIGHT],
8 pub top: usize
9}
10
11#[derive(Debug)]
12pub struct Rock {
13 pub a: Vec<(usize, usize)>,
14 pub h: usize
15}
16
17pub fn get_rocks() -> Vec<Rock> {
18 vec![
19 Rock { a: vec![(0, 0), (0, 1), (0, 2), (0, 3)], h: 1 },
20 Rock { a: vec![(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)], h: 3 },
21 Rock { a: vec![(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)], h: 3 },
22 Rock { a: vec![(0, 0), (1, 0), (2, 0), (3, 0)], h: 4 },
23 Rock { a: vec![(0, 0), (0, 1), (1, 0), (1, 1)], h: 2 }
24 ]
25}
26
27fn in_bounds(position: (i32, i32)) -> bool {
28 position.0 >= 0 && position.1 >= 0 && position.1 < SCREEN_WIDTH as i32
29}
30
31impl Screen {
32 pub fn new() -> Screen {
33 Screen {
34 cell: [[false; SCREEN_WIDTH]; SCREEN_HEIGHT],
35 top: 0
36 }
37 }
38
39 fn allowed(&self, rock: &Rock, p: (i32, i32)) -> bool {
40 for r in &rock.a {
41 let (i, j) = (r.0 as i32 + p.0, r.1 as i32 + p.1);
42 if !in_bounds((i, j)) || self.cell[i as usize][j as usize] {
43 return false;
44 }
45 }
46 true
47 }
48
49 fn draw(&mut self, rock: &Rock, p: (usize, usize), b: bool) {
50 for r in &rock.a {
51 self.cell[r.0 + p.0][r.1 + p.1] = b;
52 }
53 }
54
55 fn move_rock(&mut self, r: &Rock, p: (usize, usize), d: (i32, i32)) -> (usize, usize) {
56 let newpos = (p.0 as i32 + d.0, p.1 as i32 + d.1);
57 if !self.allowed(r, newpos) { return p; }
58 let newpos = (newpos.0 as usize, newpos.1 as usize);
59 newpos
60 }
61
62 pub fn drop_rock(&mut self, r: &Rock, t: &mut usize, gas: &str) {
63 let mut p = (self.top + 3, 2);
64 loop {
65 let d = gas.chars().nth(*t % gas.len()).unwrap();
66 let d = if d == '>' { (0, 1) } else { (0, -1) };
67 p = self.move_rock(r, p, d);
68 *t += 1;
69 let q = self.move_rock(r, p, (-1, 0));
70 if p == q { break; } else { p = q; }
71 }
72 self.draw(r, p, true);
73 self.top = max(self.top, p.0 + r.h);
74 }
75
76 #[allow(dead_code)]
77 pub fn print(&self) {
78 for i in (0..=self.top).rev() {
79 for j in 0..SCREEN_WIDTH {
80 print!("{}", if self.cell[i][j] { '#' } else { '.' })
81 }
82 println!(" {i}");
83 }
84 }
85}

Generated with cgit - Back to sebastiano.tronto.net