diff --git a/.vscode/launch.json b/.vscode/launch.json index 617d3c1..7fbc907 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,6 +5,7 @@ "version": "0.2.0", "configurations": [ + { "type": "lldb", "request": "launch", @@ -21,6 +22,15 @@ "program": "${workspaceFolder}/day_3/target/debug/day_3", "args": [], "cwd": "${workspaceFolder}/day_3/target/debug" + }, + + { + "type": "lldb", + "request": "launch", + "name": "Debug Day 4", + "program": "${workspaceFolder}/day_4/target/debug/day_4", + "args": [], + "cwd": "${workspaceFolder}/day_4/target/debug" } ] } \ No newline at end of file diff --git a/day_4/.gitignore b/day_4/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/day_4/.gitignore @@ -0,0 +1 @@ +/target diff --git a/day_4/Cargo.lock b/day_4/Cargo.lock new file mode 100644 index 0000000..3628032 --- /dev/null +++ b/day_4/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day_4" +version = "0.1.0" diff --git a/day_4/Cargo.toml b/day_4/Cargo.toml new file mode 100644 index 0000000..e358d26 --- /dev/null +++ b/day_4/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day_4" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day_4/build.rs b/day_4/build.rs new file mode 100644 index 0000000..88d5909 --- /dev/null +++ b/day_4/build.rs @@ -0,0 +1,31 @@ + +use std::{env, fs, path::Path}; + +fn main() +{ + // let out_dir = env::var("OUT_DIR").unwrap(); + // let cwd = env::var("CARGO_MANIFEST_DIR").unwrap(); + // println!("CWD: {}\n", cwd); + // let data_dir = cwd + "\\data"; + // let data_path = Path::new(&data_dir); + // println!("Data path: {}", data_path.to_string_lossy()); + + // let data_path = Path::new("data/test_input"); + + let out_path = format!("target/{}", &env::var("PROFILE").unwrap()); + let out_path = Path::new(&out_path); + //let out_path = Path::new(&out_dir).join(&env::var("PROFILE").unwrap()); + let out_path_data = out_path.join(Path::new("data")); + + if !out_path_data.exists() + { + fs::create_dir(&out_path_data).expect(&format!("Could not create data directory at: {}", out_path_data.to_string_lossy())); + } + + for file in fs::read_dir("data").unwrap() + { + let file = file.unwrap(); + let dest = out_path.join(file.path()); + fs::copy(file.path(), &dest).expect(&format!("Could not copy file {} to {}", file.path().to_string_lossy(), dest.to_string_lossy())); + } +} \ No newline at end of file diff --git a/day_4/data/test_input b/day_4/data/test_input new file mode 100644 index 0000000..71f208a --- /dev/null +++ b/day_4/data/test_input @@ -0,0 +1,6 @@ +Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 \ No newline at end of file diff --git a/day_4/src/main.rs b/day_4/src/main.rs new file mode 100644 index 0000000..0c59f6f --- /dev/null +++ b/day_4/src/main.rs @@ -0,0 +1,154 @@ + +// Advent of Code - Day 4 +use std::{fs::File, path::Path, io::Read, fmt::{Display, Formatter, self}}; + +#[derive(Clone, Debug)] +struct Card +{ + id: u32, + winning_nums: Vec, + card_nums: Vec, +} + +impl Card +{ + fn new() -> Card + { + Card { id: 0, winning_nums: Vec::new(), card_nums: Vec::new() } + } +} + +impl Display for Card +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result + { + let mut output = format!("Card: {}:", self.id); + for n in &self.winning_nums + { + output += &format!(" {:0>2} ", n); + } + + output += "|"; + + for n in &self.card_nums + { + output += &format!(" {:0>2} ", n); + } + + write!(f, "{}", output) + } +} + +fn main() +{ + let data = load_data("data/test_input"); + + let cards = parse_input(&data); + + for c in cards + { + println!("{}", c); + } +} + +fn get_points_on_card(cards: &Vec) -> u32 +{ + + 0 +} + +fn parse_input(input: &str) -> Vec +{ + let mut cards: Vec = Vec::new(); + for (idx, line) in input.to_ascii_lowercase().split("\n").into_iter().enumerate() + { + let mut is_win_num = true; + // let temp: Vec<&str> = line.split(&[' ']).collect(); + for (_widx, word) in line.split(&[' ']).into_iter().enumerate() + { + if word.len() < 1 + { + continue; + } + + if word.ends_with(":") + { + let num = word.trim_end_matches(":").to_string(); + let num = num.parse::().expect(&format!("Failed to parse number on line {}: {}", idx + 1, num)); + cards[idx].id = num; + continue; + } + + if is_num(word) + { + if cards[idx].id > 0 + { + let num = word.trim_end(); + let num = num.parse::().expect(&format!("Failed to parse number on line {}: {}", idx + 1, word)); + + if is_win_num + { + cards[idx].winning_nums.push(num); + } + else + { + cards[idx].card_nums.push(num); + } + + } + + continue; + } + + match word + { + "card" => + { + if cards.len() > 0 + { + // This should make searching more efficient later. + // Though not sure it's worth it. + cards[idx - 1].winning_nums.sort(); + } + + cards.push(Card::new()); + } + + "|" => is_win_num = false, + + _ => panic!("Unexpected word on line {}: {}", idx + 1, word), + } + + } + } + + return cards; +} + +fn is_num(s: &str) -> bool +{ + if s.len() < 1 + { + println!("WHHHHHHHAAAAAAAAAAT"); + } + s.as_bytes()[0] >= b'0' && s.as_bytes()[0] <= b'9' +} + + +fn load_data(file_name: &str) -> String +{ + let mut file = match File::open(Path::new(file_name)) + { + Ok(file) => file, + Err(why) => panic!("Could not open file {}: {}", Path::new(file_name).display(), why), + }; + + let mut s = String::new(); + let file_contents = match file.read_to_string(&mut s) + { + Err(why) => panic!("couldn't read {}: {}", Path::new(file_name).display(), why), + Ok(_) => s, + }; + + return file_contents; +} \ No newline at end of file