Puzzle Part One:
Because your neighbors keep defeating you in the holiday house decorating contest year after year, you've decided to deploy one million lights in a 1000x1000 grid.
Furthermore, because you've been especially nice this year, Santa has mailed you instructions on how to display the ideal lighting configuration.
Lights in your grid are numbered from 0 to 999 in each direction; the lights at each corner are at 0,0
, 0,999
, 999,999
, and 999,0
. The instructions include whether to turn on
, turn off
, or toggle
various inclusive ranges given as coordinate pairs. Each coordinate pair represents opposite corners of a rectangle, inclusive; a coordinate pair like 0,0 through 2,2
therefore refers to 9 lights in a 3x3 square. The lights all start turned off.
To defeat your neighbors this year, all you have to do is set up your lights by doing the instructions Santa sent you in order.
For example:
turn on 0,0 through 999,999
would turn on (or leave on) every light.toggle 0,0 through 999,0
would toggle the first line of 1000 lights, turning off the ones that were on, and turning on the ones that were off.turn off 499,499 through 500,500
would turn off (or leave off) the middle four lights.
After following the instructions, how many lights are lit?
My Solution
For this time I added a dependency in Cargo.toml
file for manipulating regex patterns.
[package]
name = "day-6"
version = "0.1.0"
edition = "2021"
[dependencies]
regex = "1.5.4"
In main.rs
:
It imports the
regex
module for working with regular expressions.An
Action
enum with three variants (Toggle
,TurnOff
,TurnOn
) is defined. Each variant represents an action that can be performed on the lights. Anexecute
method is implemented to change the state of a light according to the action.Main Function
main()
:Initializes a
lights
matrix representing a 1000x1000 grid of lights, all initially turned off.Reads input instructions, determining the action (
Toggle
,TurnOff
, orTurnOn
) for each line.Uses regular expressions to extract coordinates from the instructions.
Calls the
do_something
function to apply the determined action to the specified lights.
Function
do_something()
:- Modifies the lights matrix according to the action and given coordinates.
At the end of the
main
process, counts and displays the number of lights turned on.
mod input;
use regex::Regex;
enum Action {
Toggle,
TurnOff,
TurnOn,
}
impl Action {
fn execute(&self, state: &mut i8) {
match self {
Action::Toggle => {
if *state == 0 {
*state = 1
} else {
*state = 0
}
}
Action::TurnOff => *state = 0,
Action::TurnOn => *state = 1,
};
}
}
fn main() {
let row_num = 1000;
let col_num = 1000;
let mut lights = vec![vec![0; col_num]; row_num];
let input: Vec<&str> = input::get_input().split("\n").collect();
for i in 0..input.len() {
let action = if input[i].contains("turn off") {
Action::TurnOff
} else if input[i].contains("turn on") {
Action::TurnOn
} else {
Action::Toggle
};
// extract positions
let trimmed_input = &input[i]
.trim()
.replace("toggle", "")
.replace("turn off", "")
.replace("turn on", "")
.replace("through", "");
let reg = Regex::new(r"\d+,\d+").unwrap();
let positions_raw: Vec<&str> = reg
.find_iter(&trimmed_input)
.map(|mat| mat.as_str())
.collect();
let from: Vec<i32> = positions_raw[0]
.split(',')
.filter_map(|s| s.trim().parse::<i32>().ok())
.collect();
let to: Vec<i32> = positions_raw[1]
.split(',')
.filter_map(|s| s.trim().parse::<i32>().ok())
.collect();
do_something(action, &mut lights, from, to);
}
let mut count_on: i32 = 0;
for x in 0..row_num {
for y in 0..col_num {
count_on += lights[x][y] as i32;
}
}
println!("{} lights are on.", count_on);
}
fn do_something(action: Action, lights: &mut Vec<Vec<i8>>, from: Vec<i32>, to: Vec<i32>) {
for x in from[1]..=to[1] {
for y in from[0]..=to[0] {
action.execute(&mut lights[x as usize][y as usize]);
}
}
}
input.rs
pub fn get_input() -> &'static str {
"turn on 599,989 through 806,993
turn on 376,415 through 768,548
turn on 606,361 through 892,600
turn off 448,208 through 645,684
toggle 50,472 through 452,788
toggle 205,417 through 703,826
toggle 533,331 through 906,873
toggle 857,493 through 989,970
turn off 631,950 through 894,975
turn on 565,226 through 944,880
turn on 214,319 through 805,722
toggle 532,276 through 636,847
toggle 619,80 through 689,507
turn on 390,706 through 884,722
toggle 17,634 through 537,766
toggle 706,440 through 834,441
toggle 318,207 through 499,530
toggle 698,185 through 830,343
toggle 566,679 through 744,716"
}
Puzzle Part Two:
You just finish implementing your winning light pattern when you realize you mistranslated Santa's message from Ancient Nordic Elvish.
The light grid you bought actually has individual brightness controls; each light can have a brightness of zero or more. The lights all start at zero.
The phrase turn on
actually means that you should increase the brightness of those lights by 1
.
The phrase turn off
actually means that you should decrease the brightness of those lights by 1
, to a minimum of zero.
The phrase toggle
actually means that you should increase the brightness of those lights by 2
.
What is the total brightness of all lights combined after following Santa's instructions?
For example:
turn on 0,0 through 0,0
would increase the total brightness by1
.toggle 0,0 through 999,999
would increase the total brightness by2000000
.
My Solution:
The main difference in the Action
implementation in this code compared to the previous one lies in how the Toggle
, TurnOff
, and TurnOn
actions are handled:
Toggle: In the previous code,
Toggle
switched a light's state from on (1) to off (0) or vice versa. In this code,Toggle
increases the light's state by 2 units. This suggests that the light's state is no longer binary (on/off), but might represent brightness levels.TurnOff: In the previous code,
TurnOff
simply set the light's state to 0 (off). In this code,TurnOff
decreases the light's state by 1 unit, but only if the current state is greater than 0. This implies that it dims the light instead of turning it off completely, provided the light is not already completely off.TurnOn: In the previous code,
TurnOn
changed the state to 1 (on). In this code,TurnOn
increases the light's state by 1 unit, suggesting that it increases the light's brightness.
In summary, the main difference is that the new code seems to work with a concept of "brightness" for the lights, where lights can have various levels of intensity instead of simply being on or off.
mod input;
use regex::Regex;
enum Action {
Toggle,
TurnOff,
TurnOn,
}
impl Action {
fn execute(&self, state: &mut i8) {
match self {
Action::Toggle => *state += 2,
Action::TurnOff => {
if *state > 0 {
*state -= 1
}
}
Action::TurnOn => *state += 1,
};
}
}
fn main() {
let row_num = 1000;
let col_num = 1000;
let mut lights = vec![vec![0; col_num]; row_num];
let input: Vec<&str> = input::get_input().split("\n").collect();
for i in 0..input.len() {
let action = if input[i].contains("turn off") {
Action::TurnOff
} else if input[i].contains("turn on") {
Action::TurnOn
} else {
Action::Toggle
};
// extract positions
let trimmed_input = &input[i]
.trim()
.replace("toggle", "")
.replace("turn off", "")
.replace("turn on", "")
.replace("through", "");
let reg = Regex::new(r"\d+,\d+").unwrap();
let positions_raw: Vec<&str> = reg
.find_iter(&trimmed_input)
.map(|mat| mat.as_str())
.collect();
let from: Vec<i32> = positions_raw[0]
.split(',')
.filter_map(|s| s.trim().parse::<i32>().ok())
.collect();
let to: Vec<i32> = positions_raw[1]
.split(',')
.filter_map(|s| s.trim().parse::<i32>().ok())
.collect();
do_something(action, &mut lights, from, to);
}
let mut count_on: i32 = 0;
for x in 0..row_num {
for y in 0..col_num {
count_on += lights[x][y] as i32;
}
}
println!(
"The total brightness of all lights combined after following Santa's instructions is {}",
count_on
);
}
fn do_something(action: Action, lights: &mut Vec<Vec<i8>>, from: Vec<i32>, to: Vec<i32>) {
for x in from[1]..=to[1] {
for y in from[0]..=to[0] {
action.execute(&mut lights[x as usize][y as usize]);
}
}
}