This commit is contained in:
StNicolay 2024-12-05 19:47:50 +03:00
parent 432e17c124
commit 94e2a83fd6
Signed by: StNicolay
GPG Key ID: 9693D04DCD962B0D
6 changed files with 264 additions and 277 deletions

32
src/day1.rs Normal file
View File

@ -0,0 +1,32 @@
use std::collections::HashMap;
use crate::get_lines;
#[allow(dead_code)]
pub fn task1() {
let mut a = Vec::<i32>::new();
let mut b = Vec::<i32>::new();
for line in get_lines("input.txt") {
let (a1, b1) = line.trim_end().split_once(" ").unwrap();
a.push(a1.parse().unwrap());
b.push(b1.parse().unwrap());
}
a.sort_unstable();
b.sort_unstable();
let result: i32 = a.into_iter().zip(b).map(|(a, b)| (a - b).abs()).sum();
println!("{result}");
}
#[allow(dead_code)]
pub fn task2() {
let mut a = Vec::<u32>::new();
let mut b = HashMap::<u32, u32>::new();
for line in get_lines("input.txt") {
let (a1, b1) = line.trim_end().split_once(" ").unwrap();
a.push(a1.parse().unwrap());
*b.entry(b1.parse().unwrap()).or_insert(0) += 1;
}
let result: u32 = a.into_iter().map(|a| a * *b.get(&a).unwrap_or(&0)).sum();
println!("{result}");
}

49
src/day2.rs Normal file
View File

@ -0,0 +1,49 @@
use itertools::Itertools;
use crate::{get_lines, parse_line};
fn safe(iter: impl Iterator<Item = i32>) -> bool {
let mut order = None;
for (a, b) in iter.tuple_windows() {
if !(1..4).contains(&(a - b).abs()) {
return false;
}
if order.is_none() {
order = Some(a.cmp(&b));
} else if order != Some(a.cmp(&b)) {
return false;
}
}
true
}
#[allow(dead_code)]
pub fn task1() {
let result = get_lines("input.txt")
.filter(|line| safe(parse_line(line, ' ')))
.count();
println!("{result}");
}
#[allow(dead_code)]
pub fn task2() {
let result = get_lines("input.txt")
.filter(|line| {
let numbers = parse_line(line, ' ').collect_vec();
if safe(numbers.iter().copied()) {
return true;
}
let mut test = Vec::with_capacity(numbers.len() - 1);
for i in 0..numbers.len() {
test.extend_from_slice(&numbers[..i]);
test.extend_from_slice(&numbers[i + 1..]);
if safe(test.iter().copied()) {
return true;
}
test.clear();
}
false
})
.count();
println!("{result}");
}

34
src/day3.rs Normal file
View File

@ -0,0 +1,34 @@
use std::fs::read_to_string;
use regex::Regex;
#[allow(dead_code)]
pub fn task1() {
let rx = Regex::new(r"mul\((\d{1,3}),(\d{1,3})\)").unwrap();
let mut result: i64 = 0;
for c in rx.captures_iter(&read_to_string("input.txt").unwrap()) {
let (_, [a, b]) = c.extract();
result += a.parse::<i64>().unwrap() * b.parse::<i64>().unwrap();
}
println!("{result}");
}
#[allow(dead_code)]
pub fn task2() {
let rx = Regex::new(r"(mul)\((\d{1,3}),(\d{1,3})\)|do()()()\(\)|do(n't)()()\(\)").unwrap();
let mut enabled = true;
let mut result: i64 = 0;
for c in rx.captures_iter(&read_to_string("input.txt").unwrap()) {
let (_, [op, a, b]) = c.extract();
match op {
"" => enabled = true,
"n't" => enabled = false,
"mul" if enabled => {
result += a.parse::<i64>().unwrap() * b.parse::<i64>().unwrap();
}
"mul" => {}
_ => unreachable!("{op}"),
}
}
println!("{result}");
}

62
src/day4.rs Normal file
View File

@ -0,0 +1,62 @@
use itertools::Itertools;
#[allow(dead_code)]
pub fn task1() {
fn check(vals: &[u8]) -> usize {
(vals == b"XMAS" || vals == b"SAMX").into()
}
let data = std::fs::read_to_string("input.txt").unwrap();
let mut lines = Vec::new();
let mut count = 0;
for line in data.lines() {
count += line.matches("XMAS").count();
count += line.matches("SAMX").count();
lines.push(line.as_bytes());
}
for (i, &line) in lines[0..lines.len() - 3].iter().enumerate() {
for j in 0..line.len() {
count += check(&[
lines[i][j],
lines[i + 1][j],
lines[i + 2][j],
lines[i + 3][j],
]);
if j + 3 < line.len() {
count += check(&[
lines[i][j],
lines[i + 1][j + 1],
lines[i + 2][j + 2],
lines[i + 3][j + 3],
]);
}
if j > 2 {
count += check(&[
lines[i][j],
lines[i + 1][j - 1],
lines[i + 2][j - 2],
lines[i + 3][j - 3],
]);
}
}
}
println!("{count}");
}
#[allow(dead_code)]
pub fn task2() {
fn check(vals: &[u8]) -> usize {
(vals == b"MAS" || vals == b"SAM").into()
}
let data = std::fs::read_to_string("input.txt").unwrap();
let lines = data.lines().map(str::as_bytes).collect_vec();
let mut count: usize = 0;
for i in 0..lines[..lines.len() - 2].len() {
for j in 0..lines[i].len() - 2 {
count += check(&[lines[i][j], lines[i + 1][j + 1], lines[i + 2][j + 2]])
* check(&[lines[i][j + 2], lines[i + 1][j + 1], lines[i + 2][j]]);
}
}
println!("{count}");
}

79
src/day5.rs Normal file
View File

@ -0,0 +1,79 @@
use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
};
use itertools::Itertools;
use crate::parse_line;
type Rules = HashMap<i32, HashSet<i32>>;
fn parse_rules<'a>(lines: &mut impl Iterator<Item = &'a str>) -> Rules {
let mut rules: Rules = HashMap::new();
for rule in lines.by_ref().take_while(|s| !s.is_empty()) {
let vals = rule.split_once('|').unwrap();
let (before, after) = (vals.0.parse().unwrap(), vals.1.parse().unwrap());
rules.entry(before).or_default().insert(after);
}
rules
}
fn parse_updates<'a>(
lines: impl Iterator<Item = &'a str> + 'a,
) -> impl Iterator<Item = Vec<i32>> + 'a {
lines.map(|line| parse_line(line, ',').collect_vec())
}
fn check_update(update: &[i32], rules: &Rules) -> bool {
for (i, val) in update.iter().enumerate() {
let Some(local_rules) = rules.get(val) else {
continue;
};
if update[..i].iter().any(|elem| local_rules.contains(elem)) {
return false;
}
}
true
}
#[allow(dead_code)]
pub fn task1() {
let data = std::fs::read_to_string("input.txt").unwrap();
let mut lines = data.lines();
let rules = parse_rules(&mut lines);
let result: i32 = parse_updates(lines)
.filter(|u| check_update(u, &rules))
.map(|u| u[u.len() / 2])
.sum();
println!("{result}");
}
fn compare(a: i32, b: i32, rules: &Rules) -> Ordering {
if let Some(rule) = rules.get(&a) {
if rule.contains(&b) {
return Ordering::Less;
}
}
if let Some(rule) = rules.get(&b) {
if rule.contains(&a) {
return Ordering::Greater;
}
}
Ordering::Equal
}
#[allow(dead_code)]
pub fn task2() {
let data = std::fs::read_to_string("input.txt").unwrap();
let mut lines = data.lines();
let rules = parse_rules(&mut lines);
let result: i32 = parse_updates(lines)
.filter(|u| !check_update(u, &rules))
.map(|mut u| {
u.sort_unstable_by(|a, b| compare(*a, *b, &rules));
u[u.len() / 2]
})
.sum();
println!("{result}");
}

View File

@ -1,3 +1,9 @@
mod day1;
mod day2;
mod day3;
mod day4;
mod day5;
use std::{ use std::{
fs::File, fs::File,
io::{BufRead as _, BufReader}, io::{BufRead as _, BufReader},
@ -9,283 +15,8 @@ fn get_lines(name: &str) -> impl Iterator<Item = String> {
.map(|line| line.unwrap()) .map(|line| line.unwrap())
} }
mod day1 { fn parse_line(line: &str, pattern: char) -> impl Iterator<Item = i32> + '_ {
use std::collections::HashMap; line.trim().split(pattern).map(|num| num.parse().unwrap())
use crate::get_lines;
#[allow(dead_code)]
pub fn task1() {
let mut a = Vec::<i32>::new();
let mut b = Vec::<i32>::new();
for line in get_lines("input.txt") {
let (a1, b1) = line.trim_end().split_once(" ").unwrap();
a.push(a1.parse().unwrap());
b.push(b1.parse().unwrap());
}
a.sort_unstable();
b.sort_unstable();
let result: i32 = a.into_iter().zip(b).map(|(a, b)| (a - b).abs()).sum();
println!("{result}");
}
#[allow(dead_code)]
pub fn task2() {
let mut a = Vec::<u32>::new();
let mut b = HashMap::<u32, u32>::new();
for line in get_lines("input.txt") {
let (a1, b1) = line.trim_end().split_once(" ").unwrap();
a.push(a1.parse().unwrap());
*b.entry(b1.parse().unwrap()).or_insert(0) += 1;
}
let result: u32 = a.into_iter().map(|a| a * *b.get(&a).unwrap_or(&0)).sum();
println!("{result}");
}
}
mod day2 {
use itertools::Itertools;
use crate::get_lines;
fn safe(iter: impl Iterator<Item = i32>) -> bool {
let mut order = None;
for (a, b) in iter.tuple_windows() {
if !(1..4).contains(&(a - b).abs()) {
return false;
}
if order.is_none() {
order = Some(a.cmp(&b));
} else if order != Some(a.cmp(&b)) {
return false;
}
}
true
}
fn parse_line(line: &str) -> impl Iterator<Item = i32> + '_ {
line.trim()
.split(' ')
.map(|num| num.parse::<i32>().unwrap())
}
#[allow(dead_code)]
pub fn task1() {
let result = get_lines("input.txt")
.filter(|line| safe(parse_line(line)))
.count();
println!("{result}");
}
#[allow(dead_code)]
pub fn task2() {
let result = get_lines("input.txt")
.filter(|line| {
let numbers = parse_line(line).collect_vec();
if safe(numbers.iter().copied()) {
return true;
}
let mut test = Vec::with_capacity(numbers.len() - 1);
for i in 0..numbers.len() {
test.extend_from_slice(&numbers[..i]);
test.extend_from_slice(&numbers[i + 1..]);
if safe(test.iter().copied()) {
return true;
}
test.clear();
}
false
})
.count();
println!("{result}");
}
}
mod day3 {
use std::fs::read_to_string;
use regex::Regex;
#[allow(dead_code)]
pub fn task1() {
let rx = Regex::new(r"mul\((\d{1,3}),(\d{1,3})\)").unwrap();
let mut result: i64 = 0;
for c in rx.captures_iter(&read_to_string("input.txt").unwrap()) {
let (_, [a, b]) = c.extract();
result += a.parse::<i64>().unwrap() * b.parse::<i64>().unwrap();
}
println!("{result}");
}
#[allow(dead_code)]
pub fn task2() {
let rx = Regex::new(r"(mul)\((\d{1,3}),(\d{1,3})\)|do()()()\(\)|do(n't)()()\(\)").unwrap();
let mut enabled = true;
let mut result: i64 = 0;
for c in rx.captures_iter(&read_to_string("input.txt").unwrap()) {
let (_, [op, a, b]) = c.extract();
match op {
"" => enabled = true,
"n't" => enabled = false,
"mul" if enabled => {
result += a.parse::<i64>().unwrap() * b.parse::<i64>().unwrap();
}
"mul" => {}
_ => unreachable!("{op}"),
}
}
println!("{result}");
}
}
mod day4 {
use itertools::Itertools;
#[allow(dead_code)]
pub fn task1() {
fn check(vals: &[u8]) -> usize {
(vals == b"XMAS" || vals == b"SAMX").into()
}
let data = std::fs::read_to_string("input.txt").unwrap();
let mut lines = Vec::new();
let mut count = 0;
for line in data.lines() {
count += line.matches("XMAS").count();
count += line.matches("SAMX").count();
lines.push(line.as_bytes());
}
for (i, &line) in lines[0..lines.len() - 3].iter().enumerate() {
for j in 0..line.len() {
count += check(&[
lines[i][j],
lines[i + 1][j],
lines[i + 2][j],
lines[i + 3][j],
]);
if j + 3 < line.len() {
count += check(&[
lines[i][j],
lines[i + 1][j + 1],
lines[i + 2][j + 2],
lines[i + 3][j + 3],
]);
}
if j > 2 {
count += check(&[
lines[i][j],
lines[i + 1][j - 1],
lines[i + 2][j - 2],
lines[i + 3][j - 3],
]);
}
}
}
println!("{count}");
}
#[allow(dead_code)]
pub fn task2() {
fn check(vals: &[u8]) -> usize {
(vals == b"MAS" || vals == b"SAM").into()
}
let data = std::fs::read_to_string("input.txt").unwrap();
let lines = data.lines().map(str::as_bytes).collect_vec();
let mut count: usize = 0;
for i in 0..lines[..lines.len() - 2].len() {
for j in 0..lines[i].len() - 2 {
count += check(&[lines[i][j], lines[i + 1][j + 1], lines[i + 2][j + 2]])
* check(&[lines[i][j + 2], lines[i + 1][j + 1], lines[i + 2][j]]);
}
}
println!("{count}");
}
}
mod day5 {
use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
};
use itertools::Itertools;
type Rules = HashMap<i32, HashSet<i32>>;
fn parse_rules<'a>(lines: &mut impl Iterator<Item = &'a str>) -> Rules {
let mut rules: Rules = HashMap::new();
for rule in lines.by_ref().take_while(|s| !s.is_empty()) {
let vals = rule.split_once('|').unwrap();
let (before, after) = (vals.0.parse().unwrap(), vals.1.parse().unwrap());
rules.entry(before).or_default().insert(after);
}
rules
}
fn parse_updates<'a>(
lines: impl Iterator<Item = &'a str> + 'a,
) -> impl Iterator<Item = Vec<i32>> + 'a {
lines.map(|line| {
line.trim()
.split(',')
.map(|num| num.parse::<i32>().unwrap())
.collect_vec()
})
}
fn check_update(update: &[i32], rules: &Rules) -> bool {
for (i, val) in update.iter().enumerate() {
let Some(local_rules) = rules.get(val) else {
continue;
};
if update[..i].iter().any(|elem| local_rules.contains(elem)) {
return false;
}
}
true
}
#[allow(dead_code)]
pub fn task1() {
let data = std::fs::read_to_string("input.txt").unwrap();
let mut lines = data.lines();
let rules = parse_rules(&mut lines);
let result: i32 = parse_updates(lines)
.filter(|u| check_update(u, &rules))
.map(|u| u[u.len() / 2])
.sum();
println!("{result}");
}
fn compare(a: i32, b: i32, rules: &Rules) -> Ordering {
if let Some(rule) = rules.get(&a) {
if rule.contains(&b) {
return Ordering::Less;
}
}
if let Some(rule) = rules.get(&b) {
if rule.contains(&a) {
return Ordering::Greater;
}
}
Ordering::Equal
}
#[allow(dead_code)]
pub fn task2() {
let data = std::fs::read_to_string("input.txt").unwrap();
let mut lines = data.lines();
let rules = parse_rules(&mut lines);
let result: i32 = parse_updates(lines)
.filter(|u| !check_update(u, &rules))
.map(|mut u| {
u.sort_unstable_by(|a, b| compare(*a, *b, &rules));
u[u.len() / 2]
})
.sum();
println!("{result}");
}
} }
fn main() { fn main() {