summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShivesh Mandalia <mail@shivesh.org>2022-12-30 17:20:17 +0000
committerShivesh Mandalia <mail@shivesh.org>2022-12-30 17:20:17 +0000
commit67a326403f50929586fc27bc845fc4a4290ec1ec (patch)
treef58b204383bf86fdf6441b25b80cd15b5fa7d8a6
parente9b61b1519a9b1dc34944f269b6fc9b34715b278 (diff)
downloadadvent_of_code_2022-67a326403f50929586fc27bc845fc4a4290ec1ec.tar.gz
advent_of_code_2022-67a326403f50929586fc27bc845fc4a4290ec1ec.zip
complete day 10
-rw-r--r--Cargo.lock15
-rw-r--r--Cargo.toml4
-rw-r--r--day10a/Cargo.toml10
-rw-r--r--day10a/examples/input.txt142
-rw-r--r--day10a/examples/test.txt146
-rw-r--r--day10a/src/main.rs303
-rw-r--r--day10b/Cargo.toml9
-rw-r--r--day10b/examples/input.txt142
-rw-r--r--day10b/examples/test.txt146
-rw-r--r--day10b/src/main.rs236
10 files changed, 1151 insertions, 2 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8985bdc..d52e5c0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -217,6 +217,21 @@ dependencies = [
]
[[package]]
+name = "day10a"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "itertools",
+]
+
+[[package]]
+name = "day10b"
+version = "0.1.0"
+dependencies = [
+ "clap",
+]
+
+[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index e7e378d..e42621b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,8 +19,8 @@ members = [
"day08b",
"day09a",
"day09b",
- # "day10a",
- # "day10b",
+ "day10a",
+ "day10b",
# "day11a",
# "day11b",
# "day12a",
diff --git a/day10a/Cargo.toml b/day10a/Cargo.toml
new file mode 100644
index 0000000..c4bc0cb
--- /dev/null
+++ b/day10a/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "day10a"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clap = { version = "3.2.20", features = ["derive"] }
+itertools = "0.10.5"
diff --git a/day10a/examples/input.txt b/day10a/examples/input.txt
new file mode 100644
index 0000000..36431be
--- /dev/null
+++ b/day10a/examples/input.txt
@@ -0,0 +1,142 @@
+addx 1
+addx 5
+noop
+addx -1
+noop
+noop
+addx 6
+addx 15
+addx -9
+noop
+addx -1
+addx 4
+addx 2
+addx -22
+addx 27
+addx -1
+addx 4
+noop
+addx 1
+addx 2
+noop
+noop
+noop
+noop
+addx 1
+addx -33
+addx 2
+addx 5
+addx 2
+addx 3
+addx -2
+addx 7
+noop
+addx -2
+addx -8
+addx 15
+addx 5
+noop
+noop
+addx -2
+addx 2
+noop
+noop
+addx 7
+addx -14
+noop
+addx -2
+addx -17
+addx 5
+addx -4
+noop
+addx 23
+addx -18
+noop
+noop
+noop
+addx 28
+addx -18
+addx 4
+noop
+noop
+addx -5
+addx 1
+addx 10
+addx 2
+noop
+noop
+addx -30
+addx 33
+addx -32
+noop
+noop
+addx -2
+addx 6
+addx -2
+addx 4
+addx 3
+addx 19
+addx 10
+addx -5
+addx -16
+addx 3
+addx -2
+addx 17
+addx -19
+addx 11
+addx 2
+addx 9
+noop
+addx -4
+addx -6
+addx -7
+addx -24
+noop
+addx 7
+addx -2
+addx 5
+addx 2
+addx 3
+addx -2
+addx 2
+addx 5
+addx 2
+addx 7
+addx -2
+noop
+addx 3
+addx -2
+addx 2
+addx 7
+noop
+addx -2
+addx -34
+addx 1
+addx 1
+noop
+noop
+noop
+addx 5
+noop
+noop
+addx 5
+addx -1
+noop
+addx 6
+addx -1
+noop
+addx 4
+addx 3
+addx 4
+addx -1
+addx 5
+noop
+addx 5
+noop
+noop
+noop
+noop
+noop
+addx 1
+noop
+noop
diff --git a/day10a/examples/test.txt b/day10a/examples/test.txt
new file mode 100644
index 0000000..37ee8ee
--- /dev/null
+++ b/day10a/examples/test.txt
@@ -0,0 +1,146 @@
+addx 15
+addx -11
+addx 6
+addx -3
+addx 5
+addx -1
+addx -8
+addx 13
+addx 4
+noop
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx -35
+addx 1
+addx 24
+addx -19
+addx 1
+addx 16
+addx -11
+noop
+noop
+addx 21
+addx -15
+noop
+noop
+addx -3
+addx 9
+addx 1
+addx -3
+addx 8
+addx 1
+addx 5
+noop
+noop
+noop
+noop
+noop
+addx -36
+noop
+addx 1
+addx 7
+noop
+noop
+noop
+addx 2
+addx 6
+noop
+noop
+noop
+noop
+noop
+addx 1
+noop
+noop
+addx 7
+addx 1
+noop
+addx -13
+addx 13
+addx 7
+noop
+addx 1
+addx -33
+noop
+noop
+noop
+addx 2
+noop
+noop
+noop
+addx 8
+noop
+addx -1
+addx 2
+addx 1
+noop
+addx 17
+addx -9
+addx 1
+addx 1
+addx -3
+addx 11
+noop
+noop
+addx 1
+noop
+addx 1
+noop
+noop
+addx -13
+addx -19
+addx 1
+addx 3
+addx 26
+addx -30
+addx 12
+addx -1
+addx 3
+addx 1
+noop
+noop
+noop
+addx -9
+addx 18
+addx 1
+addx 2
+noop
+noop
+addx 9
+noop
+noop
+noop
+addx -1
+addx 2
+addx -37
+addx 1
+addx 3
+noop
+addx 15
+addx -21
+addx 22
+addx -6
+addx 1
+noop
+addx 2
+addx 1
+noop
+addx -10
+noop
+noop
+addx 20
+addx 1
+addx 2
+addx 2
+addx -6
+addx -11
+noop
+noop
+noop
diff --git a/day10a/src/main.rs b/day10a/src/main.rs
new file mode 100644
index 0000000..1fba5c5
--- /dev/null
+++ b/day10a/src/main.rs
@@ -0,0 +1,303 @@
+/// --- Day 10: Cathode-Ray Tube ---
+///
+/// You avoid the ropes, plunge into the river, and swim to shore.
+///
+/// The Elves yell something about meeting back up with them upriver, but the river is too loud to
+/// tell exactly what they're saying. They finish crossing the bridge and disappear from view.
+///
+/// Situations like this must be why the Elves prioritized getting the communication system on your
+/// handheld device working. You pull it out of your pack, but the amount of water slowly draining
+/// from a big crack in its screen tells you it probably won't be of much immediate use.
+///
+/// Unless, that is, you can design a replacement for the device's video system! It seems to be
+/// some kind of cathode-ray tube screen and simple CPU that are both driven by a precise clock
+/// circuit. The clock circuit ticks at a constant rate; each tick is called a cycle.
+///
+/// Start by figuring out the signal being sent by the CPU. The CPU has a single register, X,
+/// which starts with the value 1. It supports only two instructions:
+///
+/// addx V takes two cycles to complete. After two cycles, the X register is increased by the
+/// value V. (V can be negative.)
+/// noop takes one cycle to complete. It has no other effect.
+///
+/// The CPU uses these instructions in a program (your puzzle input) to, somehow, tell the screen
+/// what to draw.
+///
+/// Consider the following small program:
+///
+/// noop
+/// addx 3
+/// addx -5
+///
+/// Execution of this program proceeds as follows:
+///
+/// At the start of the first cycle, the noop instruction begins execution. During the first
+/// cycle, X is 1. After the first cycle, the noop instruction finishes execution, doing
+/// nothing.
+/// At the start of the second cycle, the addx 3 instruction begins execution. During the
+/// second cycle, X is still 1.
+/// During the third cycle, X is still 1. After the third cycle, the addx 3 instruction
+/// finishes execution, setting X to 4.
+/// At the start of the fourth cycle, the addx -5 instruction begins execution. During the
+/// fourth cycle, X is still 4.
+/// During the fifth cycle, X is still 4. After the fifth cycle, the addx -5 instruction
+/// finishes execution, setting X to -1.
+///
+/// Maybe you can learn something by looking at the value of the X register throughout execution.
+/// For now, consider the signal strength (the cycle number multiplied by the value of the X
+/// register) during the 20th cycle and every 40 cycles after that (that is, during the 20th, 60th,
+/// 100th, 140th, 180th, and 220th cycles).
+///
+/// For example, consider this larger program:
+///
+/// ```
+/// addx 15
+/// addx -11
+/// addx 6
+/// addx -3
+/// addx 5
+/// addx -1
+/// addx -8
+/// addx 13
+/// addx 4
+/// noop
+/// addx -1
+/// addx 5
+/// addx -1
+/// addx 5
+/// addx -1
+/// addx 5
+/// addx -1
+/// addx 5
+/// addx -1
+/// addx -35
+/// addx 1
+/// addx 24
+/// addx -19
+/// addx 1
+/// addx 16
+/// addx -11
+/// noop
+/// noop
+/// addx 21
+/// addx -15
+/// noop
+/// noop
+/// addx -3
+/// addx 9
+/// addx 1
+/// addx -3
+/// addx 8
+/// addx 1
+/// addx 5
+/// noop
+/// noop
+/// noop
+/// noop
+/// noop
+/// addx -36
+/// noop
+/// addx 1
+/// addx 7
+/// noop
+/// noop
+/// noop
+/// addx 2
+/// addx 6
+/// noop
+/// noop
+/// noop
+/// noop
+/// noop
+/// addx 1
+/// noop
+/// noop
+/// addx 7
+/// addx 1
+/// noop
+/// addx -13
+/// addx 13
+/// addx 7
+/// noop
+/// addx 1
+/// addx -33
+/// noop
+/// noop
+/// noop
+/// addx 2
+/// noop
+/// noop
+/// noop
+/// addx 8
+/// noop
+/// addx -1
+/// addx 2
+/// addx 1
+/// noop
+/// addx 17
+/// addx -9
+/// addx 1
+/// addx 1
+/// addx -3
+/// addx 11
+/// noop
+/// noop
+/// addx 1
+/// noop
+/// addx 1
+/// noop
+/// noop
+/// addx -13
+/// addx -19
+/// addx 1
+/// addx 3
+/// addx 26
+/// addx -30
+/// addx 12
+/// addx -1
+/// addx 3
+/// addx 1
+/// noop
+/// noop
+/// noop
+/// addx -9
+/// addx 18
+/// addx 1
+/// addx 2
+/// noop
+/// noop
+/// addx 9
+/// noop
+/// noop
+/// noop
+/// addx -1
+/// addx 2
+/// addx -37
+/// addx 1
+/// addx 3
+/// noop
+/// addx 15
+/// addx -21
+/// addx 22
+/// addx -6
+/// addx 1
+/// noop
+/// addx 2
+/// addx 1
+/// noop
+/// addx -10
+/// noop
+/// noop
+/// addx 20
+/// addx 1
+/// addx 2
+/// addx 2
+/// addx -6
+/// addx -11
+/// noop
+/// noop
+/// noop
+/// ```
+///
+/// The interesting signal strengths can be determined as follows:
+///
+/// During the 20th cycle, register X has the value 21, so the signal strength is 20 * 21 =
+/// 420. (The 20th cycle occurs in the middle of the second addx -1, so the value of register X
+/// is the starting value, 1, plus all of the other addx values up to that point: 1 + 15 - 11 +
+/// 6 - 3 + 5 - 1 - 8 + 13 + 4 = 21.)
+/// During the 60th cycle, register X has the value 19, so the signal strength is 60 * 19 = 1140.
+/// During the 100th cycle, register X has the value 18, so the signal strength is 100 * 18 = 1800.
+/// During the 140th cycle, register X has the value 21, so the signal strength is 140 * 21 = 2940.
+/// During the 180th cycle, register X has the value 16, so the signal strength is 180 * 16 = 2880.
+/// During the 220th cycle, register X has the value 18, so the signal strength is 220 * 18 = 3960.
+///
+/// The sum of these signal strengths is 13140.
+///
+/// Find the signal strength during the 20th, 60th, 100th, 140th, 180th, and 220th cycles. What is
+/// the sum of these six signal strengths?
+use clap::Parser;
+use itertools::Itertools;
+
+use std::fs::File;
+use std::io::prelude::*;
+use std::io::BufReader;
+use std::path::PathBuf;
+
+const FILEPATH: &'static str = "examples/input.txt";
+const XINIT: i32 = 1;
+const INTERESTING_INIT: i32 = 20;
+const INTERESTING_INCREMENT: i32 = 40;
+
+#[derive(Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+struct Cli {
+ #[clap(short, long, default_value = FILEPATH)]
+ file: PathBuf,
+}
+
+#[derive(Copy, Clone, Debug)]
+enum Command {
+ Addx(i32),
+ Noop,
+}
+
+#[derive(Copy, Clone, Debug)]
+struct State {
+ x: i32,
+ cycle: u32,
+ res: i32,
+}
+
+impl State {
+ fn new() -> Self {
+ State {
+ x: XINIT,
+ cycle: 0,
+ res: 0,
+ }
+ }
+
+ fn process(&mut self) {
+ self.cycle += 1;
+ if (self.cycle as i32 + INTERESTING_INIT) % INTERESTING_INCREMENT == 0 {
+ self.res += self.cycle as i32 * self.x;
+ }
+ }
+}
+
+impl Command {
+ fn parse(s: &str) -> Self {
+ let split_s = s.split_whitespace().collect_vec();
+ match split_s.len() {
+ 1 => Command::Noop,
+ 2 => Command::Addx(split_s[1].parse::<i32>().unwrap()),
+ _ => panic!(),
+ }
+ }
+}
+
+fn main() {
+ let args = Cli::parse();
+
+ let file = File::open(&args.file).unwrap();
+ let reader = BufReader::new(file);
+
+ let res = reader
+ .lines()
+ .map(|l| Command::parse(l.unwrap().as_str()))
+ .scan(State::new(), |state, command| {
+ state.process();
+ match command {
+ Command::Noop => (),
+ Command::Addx(value) => {
+ state.process();
+ state.x += value;
+ }
+ };
+ Some(state.res)
+ })
+ .last()
+ .unwrap();
+
+ println!("{res:?}");
+}
diff --git a/day10b/Cargo.toml b/day10b/Cargo.toml
new file mode 100644
index 0000000..c71a33d
--- /dev/null
+++ b/day10b/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "day10b"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clap = { version = "3.2.20", features = ["derive"] }
diff --git a/day10b/examples/input.txt b/day10b/examples/input.txt
new file mode 100644
index 0000000..36431be
--- /dev/null
+++ b/day10b/examples/input.txt
@@ -0,0 +1,142 @@
+addx 1
+addx 5
+noop
+addx -1
+noop
+noop
+addx 6
+addx 15
+addx -9
+noop
+addx -1
+addx 4
+addx 2
+addx -22
+addx 27
+addx -1
+addx 4
+noop
+addx 1
+addx 2
+noop
+noop
+noop
+noop
+addx 1
+addx -33
+addx 2
+addx 5
+addx 2
+addx 3
+addx -2
+addx 7
+noop
+addx -2
+addx -8
+addx 15
+addx 5
+noop
+noop
+addx -2
+addx 2
+noop
+noop
+addx 7
+addx -14
+noop
+addx -2
+addx -17
+addx 5
+addx -4
+noop
+addx 23
+addx -18
+noop
+noop
+noop
+addx 28
+addx -18
+addx 4
+noop
+noop
+addx -5
+addx 1
+addx 10
+addx 2
+noop
+noop
+addx -30
+addx 33
+addx -32
+noop
+noop
+addx -2
+addx 6
+addx -2
+addx 4
+addx 3
+addx 19
+addx 10
+addx -5
+addx -16
+addx 3
+addx -2
+addx 17
+addx -19
+addx 11
+addx 2
+addx 9
+noop
+addx -4
+addx -6
+addx -7
+addx -24
+noop
+addx 7
+addx -2
+addx 5
+addx 2
+addx 3
+addx -2
+addx 2
+addx 5
+addx 2
+addx 7
+addx -2
+noop
+addx 3
+addx -2
+addx 2
+addx 7
+noop
+addx -2
+addx -34
+addx 1
+addx 1
+noop
+noop
+noop
+addx 5
+noop
+noop
+addx 5
+addx -1
+noop
+addx 6
+addx -1
+noop
+addx 4
+addx 3
+addx 4
+addx -1
+addx 5
+noop
+addx 5
+noop
+noop
+noop
+noop
+noop
+addx 1
+noop
+noop
diff --git a/day10b/examples/test.txt b/day10b/examples/test.txt
new file mode 100644
index 0000000..37ee8ee
--- /dev/null
+++ b/day10b/examples/test.txt
@@ -0,0 +1,146 @@
+addx 15
+addx -11
+addx 6
+addx -3
+addx 5
+addx -1
+addx -8
+addx 13
+addx 4
+noop
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx -35
+addx 1
+addx 24
+addx -19
+addx 1
+addx 16
+addx -11
+noop
+noop
+addx 21
+addx -15
+noop
+noop
+addx -3
+addx 9
+addx 1
+addx -3
+addx 8
+addx 1
+addx 5
+noop
+noop
+noop
+noop
+noop
+addx -36
+noop
+addx 1
+addx 7
+noop
+noop
+noop
+addx 2
+addx 6
+noop
+noop
+noop
+noop
+noop
+addx 1
+noop
+noop
+addx 7
+addx 1
+noop
+addx -13
+addx 13
+addx 7
+noop
+addx 1
+addx -33
+noop
+noop
+noop
+addx 2
+noop
+noop
+noop
+addx 8
+noop
+addx -1
+addx 2
+addx 1
+noop
+addx 17
+addx -9
+addx 1
+addx 1
+addx -3
+addx 11
+noop
+noop
+addx 1
+noop
+addx 1
+noop
+noop
+addx -13
+addx -19
+addx 1
+addx 3
+addx 26
+addx -30
+addx 12
+addx -1
+addx 3
+addx 1
+noop
+noop
+noop
+addx -9
+addx 18
+addx 1
+addx 2
+noop
+noop
+addx 9
+noop
+noop
+noop
+addx -1
+addx 2
+addx -37
+addx 1
+addx 3
+noop
+addx 15
+addx -21
+addx 22
+addx -6
+addx 1
+noop
+addx 2
+addx 1
+noop
+addx -10
+noop
+noop
+addx 20
+addx 1
+addx 2
+addx 2
+addx -6
+addx -11
+noop
+noop
+noop
diff --git a/day10b/src/main.rs b/day10b/src/main.rs
new file mode 100644
index 0000000..5094ae4
--- /dev/null
+++ b/day10b/src/main.rs
@@ -0,0 +1,236 @@
+/// --- Part Two ---
+///
+/// It seems like the X register controls the horizontal position of a sprite. Specifically, the
+/// sprite is 3 pixels wide, and the X register sets the horizontal position of the middle of that
+/// sprite. (In this system, there is no such thing as "vertical position": if the sprite's
+/// horizontal position puts its pixels where the CRT is currently drawing, then those pixels will
+/// be drawn.)
+///
+/// You count the pixels on the CRT: 40 wide and 6 high. This CRT screen draws the top row of
+/// pixels left-to-right, then the row below that, and so on. The left-most pixel in each row is
+/// in position 0, and the right-most pixel in each row is in position 39.
+///
+/// Like the CPU, the CRT is tied closely to the clock circuit: the CRT draws a single pixel during
+/// each cycle. Representing each pixel of the screen as a #, here are the cycles during which the
+/// first and last pixel in each row are drawn:
+///
+/// ```
+/// Cycle 1 -> ######################################## <- Cycle 40
+/// Cycle 41 -> ######################################## <- Cycle 80
+/// Cycle 81 -> ######################################## <- Cycle 120
+/// Cycle 121 -> ######################################## <- Cycle 160
+/// Cycle 161 -> ######################################## <- Cycle 200
+/// Cycle 201 -> ######################################## <- Cycle 240
+/// ```
+///
+/// So, by carefully timing the CPU instructions and the CRT drawing operations, you should be able
+/// to determine whether the sprite is visible the instant each pixel is drawn. If the sprite is
+/// positioned such that one of its three pixels is the pixel currently being drawn, the screen
+/// produces a lit pixel (#); otherwise, the screen leaves the pixel dark (.).
+///
+/// The first few pixels from the larger example above are drawn as follows:
+///
+/// ```
+/// Sprite position: ###.....................................
+///
+/// Start cycle 1: begin executing addx 15
+/// During cycle 1: CRT draws pixel in position 0
+/// Current CRT row: #
+///
+/// During cycle 2: CRT draws pixel in position 1
+/// Current CRT row: ##
+/// End of cycle 2: finish executing addx 15 (Register X is now 16)
+/// Sprite position: ...............###......................
+///
+/// Start cycle 3: begin executing addx -11
+/// During cycle 3: CRT draws pixel in position 2
+/// Current CRT row: ##.
+///
+/// During cycle 4: CRT draws pixel in position 3
+/// Current CRT row: ##..
+/// End of cycle 4: finish executing addx -11 (Register X is now 5)
+/// Sprite position: ....###.................................
+///
+/// Start cycle 5: begin executing addx 6
+/// During cycle 5: CRT draws pixel in position 4
+/// Current CRT row: ##..#
+///
+/// During cycle 6: CRT draws pixel in position 5
+/// Current CRT row: ##..##
+/// End of cycle 6: finish executing addx 6 (Register X is now 11)
+/// Sprite position: ..........###...........................
+///
+/// Start cycle 7: begin executing addx -3
+/// During cycle 7: CRT draws pixel in position 6
+/// Current CRT row: ##..##.
+///
+/// During cycle 8: CRT draws pixel in position 7
+/// Current CRT row: ##..##..
+/// End of cycle 8: finish executing addx -3 (Register X is now 8)
+/// Sprite position: .......###..............................
+///
+/// Start cycle 9: begin executing addx 5
+/// During cycle 9: CRT draws pixel in position 8
+/// Current CRT row: ##..##..#
+///
+/// During cycle 10: CRT draws pixel in position 9
+/// Current CRT row: ##..##..##
+/// End of cycle 10: finish executing addx 5 (Register X is now 13)
+/// Sprite position: ............###.........................
+///
+/// Start cycle 11: begin executing addx -1
+/// During cycle 11: CRT draws pixel in position 10
+/// Current CRT row: ##..##..##.
+///
+/// During cycle 12: CRT draws pixel in position 11
+/// Current CRT row: ##..##..##..
+/// End of cycle 12: finish executing addx -1 (Register X is now 12)
+/// Sprite position: ...........###..........................
+///
+/// Start cycle 13: begin executing addx -8
+/// During cycle 13: CRT draws pixel in position 12
+/// Current CRT row: ##..##..##..#
+///
+/// During cycle 14: CRT draws pixel in position 13
+/// Current CRT row: ##..##..##..##
+/// End of cycle 14: finish executing addx -8 (Register X is now 4)
+/// Sprite position: ...###..................................
+///
+/// Start cycle 15: begin executing addx 13
+/// During cycle 15: CRT draws pixel in position 14
+/// Current CRT row: ##..##..##..##.
+///
+/// During cycle 16: CRT draws pixel in position 15
+/// Current CRT row: ##..##..##..##..
+/// End of cycle 16: finish executing addx 13 (Register X is now 17)
+/// Sprite position: ................###.....................
+///
+/// Start cycle 17: begin executing addx 4
+/// During cycle 17: CRT draws pixel in position 16
+/// Current CRT row: ##..##..##..##..#
+///
+/// During cycle 18: CRT draws pixel in position 17
+/// Current CRT row: ##..##..##..##..##
+/// End of cycle 18: finish executing addx 4 (Register X is now 21)
+/// Sprite position: ....................###.................
+///
+/// Start cycle 19: begin executing noop
+/// During cycle 19: CRT draws pixel in position 18
+/// Current CRT row: ##..##..##..##..##.
+/// End of cycle 19: finish executing noop
+///
+/// Start cycle 20: begin executing addx -1
+/// During cycle 20: CRT draws pixel in position 19
+/// Current CRT row: ##..##..##..##..##..
+///
+/// During cycle 21: CRT draws pixel in position 20
+/// Current CRT row: ##..##..##..##..##..#
+/// End of cycle 21: finish executing addx -1 (Register X is now 20)
+/// Sprite position: ...................###..................
+/// ```
+///
+/// Allowing the program to run to completion causes the CRT to produce the following image:
+///
+/// ```
+/// ##..##..##..##..##..##..##..##..##..##..
+/// ###...###...###...###...###...###...###.
+/// ####....####....####....####....####....
+/// #####.....#####.....#####.....#####.....
+/// ######......######......######......####
+/// #######.......#######.......#######.....
+/// ```
+///
+/// Render the image given by your program. What eight capital letters appear on your CRT?
+use clap::Parser;
+
+use std::fmt::Write;
+use std::fs::File;
+use std::io::prelude::*;
+use std::io::BufReader;
+use std::path::PathBuf;
+
+const FILEPATH: &'static str = "examples/input.txt";
+const XINIT: i32 = 1;
+const SPRITE_WIDTH: u8 = 3;
+const CRT_WIDTH: i32 = 40;
+
+#[derive(Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+struct Cli {
+ #[clap(short, long, default_value = FILEPATH)]
+ file: PathBuf,
+}
+
+#[derive(Copy, Clone, Debug)]
+enum Command {
+ Addx(i32),
+ Noop,
+}
+
+#[derive(Clone, Debug)]
+struct State {
+ x: i32,
+ cycle: u32,
+ res: String,
+}
+
+impl State {
+ fn new() -> Self {
+ State {
+ x: XINIT,
+ cycle: 0,
+ res: String::new(),
+ }
+ }
+
+ fn process(&mut self) {
+ self.cycle += 1;
+ let pos = (self.cycle as i32 - 1) % CRT_WIDTH;
+ if (pos + 1) < self.x || pos + 1 >= (self.x + SPRITE_WIDTH as i32) {
+ self.res += " ";
+ } else {
+ self.res += "█";
+ }
+ if self.cycle as i32 % CRT_WIDTH == 0 {
+ writeln!(&mut self.res).unwrap();
+ }
+ }
+}
+
+impl Command {
+ fn parse(s: &str) -> Self {
+ let split_s = s.split_whitespace().collect::<Vec<&str>>();
+ match split_s.len() {
+ 1 => Command::Noop,
+ 2 => Command::Addx(split_s[1].parse::<i32>().unwrap()),
+ _ => panic!(),
+ }
+ }
+}
+
+fn main() {
+ let args = Cli::parse();
+
+ let file = File::open(&args.file).unwrap();
+ let reader = BufReader::new(file);
+
+ let res = reader
+ .lines()
+ .map(|l| Command::parse(l.unwrap().as_str()))
+ .scan(State::new(), |state, command| {
+ state.process();
+ match command {
+ Command::Noop => (),
+ Command::Addx(value) => {
+ state.process();
+ state.x += value;
+ }
+ };
+ Some(state.res.clone())
+ })
+ .last()
+ .unwrap();
+
+ // "ZGCJZJFL"
+ println!("{res}");
+}