initial setup & day 1

This commit is contained in:
OMGeeky
2023-12-01 12:13:43 +00:00
parent 585692f823
commit 7da2459cc3
10 changed files with 1421 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/rust
{
"name": "Rust",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/rust:1-1-bullseye",
"features": {
"ghcr.io/devcontainers-contrib/features/zsh-plugins:0": {}
},
"customizations": {
"vscode": {
"extensions": [
"rust-lang.rust-analyzer",
"GitHub.copilot-chat",
"tamasfe.even-better-toml",
"GitHub.copilot-labs",
"GitHub.copilot",
"yzhang.markdown-all-in-one",
"alexcvzz.vscode-sqlite"
]
}
}
// Use 'mounts' to make the cargo cache persistent in a Docker Volume.
// "mounts": [
// {
// "source": "devcontainer-cargo-cache-${devcontainerId}",
// "target": "/usr/local/cargo",
// "type": "volume"
// }
// ]
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "rustc --version",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}

5
.gitignore vendored
View File

@@ -12,3 +12,8 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# Added by cargo
/target

64
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,64 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'advent-of-code-2023'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=advent-of-code-2023"
],
"filter": {
"name": "advent-of-code-2023",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'advent-of-code-2023'",
"cargo": {
"args": [
"build",
"--bin=advent-of-code-2023",
"--package=advent-of-code-2023"
],
"filter": {
"name": "advent-of-code-2023",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'advent-of-code-2023'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=advent-of-code-2023",
"--package=advent-of-code-2023"
],
"filter": {
"name": "advent-of-code-2023",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

13
Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "advent-of-code-2023"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.16.1", features = ["full"] }
serde = { version = "1.0.130", features = ["derive"] }
serde_json = "1.0.68"
paste ={ version = "1.0" }

1000
input/day01.txt Normal file

File diff suppressed because it is too large Load Diff

114
src/day01.rs Normal file
View File

@@ -0,0 +1,114 @@
use crate::{Day, DayPart2};
pub struct Day01;
impl Day for Day01 {
const DAY_NUM: u8 = 01;
type Input = String;
type Output = usize;
fn get_test_data() -> Vec<Self::Input> {
vec![
"1abc2".to_string(),
"pqr3stu8vwx".to_string(),
"a1b2c3d4e5f".to_string(),
"treb7uchet".to_string(),
]
}
fn get_test_result() -> Self::Output {
142
}
fn run(data: Vec<Self::Input>) -> Self::Output {
let mut sum = 0;
for line in data {
let mut digits = line.chars().filter(|c| c.is_digit(10));
let first = digits.next().unwrap_or(' ');
let last = digits.last().unwrap_or(first);
let num = format!("{}{}", first, last)
.trim()
.parse::<usize>()
.unwrap();
println!(
"{} + {} = {}; total: {} => {}",
first,
last,
num,
sum,
sum + num
);
sum += num;
}
sum
}
}
impl DayPart2 for Day01 {
fn get_test_data_part2() -> Vec<String> {
vec![
"two1nine".to_string(),
"eightwothree".to_string(),
"abcone2threexyz".to_string(),
"xtwone3four".to_string(),
"4nineeightseven2".to_string(),
"zoneight234".to_string(),
"7pqrstsixteen".to_string(),
]
}
fn get_test_result_part2() -> usize {
281
}
fn run_part2(data: Vec<String>) -> usize {
let mut sum = 0;
for line in data {
let mut l = String::new();
for i in 0..line.len() {
let part = &line[i..];
// println!("{}", part);
let c = part.chars().next().unwrap();
if c.is_digit(10) {
l.push(c);
}
if part.starts_with("one") {
l.push('1')
} else if part.starts_with("two") {
l.push('2')
} else if part.starts_with("three") {
l.push('3')
} else if part.starts_with("four") {
l.push('4')
} else if part.starts_with("five") {
l.push('5')
} else if part.starts_with("six") {
l.push('6')
} else if part.starts_with("seven") {
l.push('7')
} else if part.starts_with("eight") {
l.push('8')
} else if part.starts_with("nine") {
l.push('9')
}
}
let mut digits = l.chars().filter(|c| c.is_digit(10));
let first = digits.next().unwrap_or(' ');
let last = digits.last().unwrap_or(first);
// println!("'{}' '{}'", first, last);
let num = format!("{}{}", first, last)
.trim()
.parse::<usize>()
.unwrap();
println!(
"{} + {} = {}; total: {} => {}",
first,
last,
num,
sum,
sum + num
);
sum += num;
}
sum
}
}

20
src/day02.rs Normal file
View File

@@ -0,0 +1,20 @@
use crate::*;
pub struct Day02;
impl Day for Day02 {
const DAY_NUM: u8 = 02;
type Input = String;
type Output = usize;
fn get_test_data() -> Vec<Self::Input> {
todo!()
}
fn get_test_result() -> Self::Output {
todo!()
}
fn run(data: Vec<Self::Input>) -> Self::Output {
todo!()
}
}

20
src/day_templatce.rs Normal file
View File

@@ -0,0 +1,20 @@
use crate::*;
pub struct Dayxx;
impl Day for Dayxx {
const DAY_NUM: u8 = xx;
type Input = String;
type Output = usize;
fn get_test_data() -> Vec<Self::Input> {
todo!()
}
fn get_test_result() -> Self::Output {
todo!()
}
fn run(data: Vec<Self::Input>) -> Self::Output {
todo!()
}
}

128
src/lib.rs Normal file
View File

@@ -0,0 +1,128 @@
use std::str::FromStr;
pub fn read_input<T>(day: u8) -> Vec<T>
where
T: From<String>,
{
let filename = format!("input/day{:02}.txt", day);
println!("Reading input from {}", filename);
let input = std::fs::read_to_string(filename).unwrap();
utils::day!();
input.lines().map(|s| s.to_string().into()).collect()
}
mod day01;
pub use day01::Day01;
mod day02;
pub use day02::Day02;
pub mod utils {
#[macro_export]
macro_rules! day {
($num: expr) => {
paste::item! {
fn [< run_test_day $num >] () {
use [< day $num>];
type D = [< Day $num>];
let test_res = D::run(D::get_test_data());
println!("Day {}: {:?}", $num, test_res);
assert_eq!(D::get_test_result(), test_res);
}
fn [< run_day $num >] () {
let test_res = [< day $num>]::run(read_input($num));
println!("Day {} result: \n{:?}", $num, test_res);
}
fn [< run_test_day $num _part2>] () {
let test_res = [< day $num>]::run_part2([< day $num>]::get_test_data_part2());
println!("Day {} part2 test: {:?}", $num, test_res);
assert_eq!([< day $num>]::get_test_result_part2(), test_res);
}
fn [< run_day $num _part2>] () {
let test_res = [< day $num>]::run_part2(read_input($num));
println!("Day {} part 2 result: \n{:?}", $num, test_res);
}
}
};
() => {
//hi
};
}
pub use day;
#[macro_export]
macro_rules! run {
// ($num: expr) => {
// paste::item! {
// [< run_test_day $num >] ();
// [< run_day $num >] ();
// [< run_test_day $num _part2 >] ();
// [< run_day $num _part2>] ();
// }
// };
() => {
// run!(01);
// run!(02);
// run!(03);
// run!(04);
// run!(05);
// run!(06);
// run!(07);
// run!(08);
// run!(09);
};
}
pub use run;
}
pub trait Day
where
<Self as Day>::Input: std::fmt::Debug + From<String>,
<Self as Day>::Output: std::fmt::Debug + PartialEq,
{
const DAY_NUM: u8;
type Input;
type Output;
fn get_test_data() -> Vec<Self::Input>;
fn get_test_result() -> Self::Output;
fn run(data: Vec<Self::Input>) -> Self::Output;
}
pub trait DayPart2: Day {
fn run_part2(data: Vec<Self::Input>) -> Self::Output;
fn get_test_result_part2() -> Self::Output;
fn get_test_data_part2() -> Vec<Self::Input>;
}
pub trait DayConvenience: Day {
fn run_day_test() {
let test_res = Self::run(Self::get_test_data());
println!("Day {}: {:?}", Self::DAY_NUM, test_res);
assert_eq!(Self::get_test_result(), test_res);
}
fn run_day() {
let test_res = Self::run(read_input(Self::DAY_NUM));
println!("Day {} result: \n{:?}", Self::DAY_NUM, test_res);
}
fn part1() {
Self::run_day_test();
Self::run_day();
}
}
impl<T> DayConvenience for T where T: Day {}
pub trait DayPart2Convenience: DayPart2 + DayConvenience {
fn run_day_part2_test() {
let test_res = Self::run_part2(Self::get_test_data_part2());
println!("Day {} part 2: {:?}", Self::DAY_NUM, test_res);
assert_eq!(Self::get_test_result_part2(), test_res);
}
fn run_day_part2() {
let test_res = Self::run_part2(read_input(Self::DAY_NUM));
println!("Day {} part 2 result: \n{:?}", Self::DAY_NUM, test_res);
}
fn part2(){
Self::run_day_part2_test();
Self::run_day_part2();
}
fn run_all() {
Self::part1();
Self::part2();
}
}
impl<T> DayPart2Convenience for T where T: DayPart2 {}

10
src/main.rs Normal file
View File

@@ -0,0 +1,10 @@
use advent_of_code_2023::*;
fn main() {
// run_test_day01_part2();
Day01::run_all();
Day02::part1();
// utils::run!(01);
// utils::run!(02);
}
// utils::day!(01);
// utils::day!(02);