Skip to content

Commit add7eb9

Browse files
authored
add rust solutions for days 1-7,9,11,12 (#40)
* add rust solutions for days 1-7,9,11,12 * fix typo and input file path
1 parent 8195df1 commit add7eb9

File tree

11 files changed

+1015
-0
lines changed

11 files changed

+1015
-0
lines changed

Day-01/rust/duckulus/day01.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use crate::common::{InputType, read_lines};
2+
3+
const DAY: usize = 1;
4+
5+
pub fn part_one(input_type: InputType) {
6+
let lines = read_lines(DAY, &input_type);
7+
let mut dial = 50;
8+
let mut password = 0;
9+
for line in lines {
10+
let direction = if &line.as_str()[..1] == "L" { -1 } else { 1 };
11+
dial += direction * line.as_str()[1..].parse::<i32>().unwrap();
12+
dial = dial % 100;
13+
while dial < 0 {
14+
dial = 100 + dial
15+
}
16+
if dial == 0 {
17+
password += 1;
18+
}
19+
}
20+
println!("{}", password);
21+
}
22+
23+
pub fn part_two(input_type: InputType) {
24+
let lines = read_lines(DAY, &input_type);
25+
let mut dial = 50;
26+
let mut password = 0;
27+
for line in lines {
28+
let direction = if &line.as_str()[..1] == "L" { -1 } else { 1 };
29+
let change = line.as_str()[1..].parse::<i32>().unwrap();
30+
31+
if direction == -1 {
32+
let t = dial;
33+
dial -= change;
34+
if dial < 0 && t == 0 {
35+
password -= 1;
36+
}
37+
while dial < 0 {
38+
dial = 100 + dial;
39+
password += 1;
40+
}
41+
if dial == 0 {
42+
password += 1;
43+
}
44+
} else {
45+
dial += change;
46+
if dial >= 100 {
47+
password += dial / 100;
48+
dial = dial % 100;
49+
}
50+
}
51+
}
52+
println!("{}", password);
53+
}

Day-02/rust/duckulus/day02.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use crate::common::{InputType, read_input};
2+
use std::ops::{Range, RangeInclusive};
3+
4+
const DAY: usize = 2;
5+
6+
pub fn part_one(input_type: InputType) {
7+
let ranges = read_ranges(input_type);
8+
9+
let mut sum = 0;
10+
for range in ranges {
11+
for i in range {
12+
let s = i.to_string();
13+
let str = s.as_str();
14+
let len = str.len();
15+
16+
if len % 2 != 0 {
17+
continue
18+
}
19+
20+
if str[..len / 2] == str[len / 2..] {
21+
sum += i;
22+
}
23+
}
24+
}
25+
println!("{}", sum);
26+
}
27+
28+
pub fn part_two(input_type: InputType) {
29+
let ranges = read_ranges(input_type);
30+
31+
let mut sum = 0;
32+
for range in ranges {
33+
for i in range {
34+
let s = i.to_string();
35+
let str = s.as_str();
36+
let len = str.len();
37+
for pref in 1..=len / 2 {
38+
if len % pref != 0 {
39+
continue;
40+
}
41+
let reps = len / pref;
42+
if str[..len / reps].repeat(reps) == str {
43+
sum += i;
44+
break;
45+
}
46+
}
47+
}
48+
}
49+
println!("{}", sum);
50+
}
51+
52+
fn read_ranges(input_type: InputType) -> Vec<RangeInclusive<u64>> {
53+
let ranges: Vec<_> = read_input(DAY, &input_type)
54+
.as_str()
55+
.split(",")
56+
.map(|s| {
57+
let split: Vec<_> = s.split("-").collect();
58+
split[0].trim().parse::<u64>().unwrap()..=split[1].trim().parse::<u64>().unwrap()
59+
})
60+
.collect();
61+
ranges
62+
}

Day-03/rust/duckulus/day03.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use crate::common::{InputType, read_input};
2+
3+
const DAY: usize = 3;
4+
5+
pub fn part_one(input_type: &InputType) {
6+
let value: u64 = get_banks(input_type)
7+
.into_iter()
8+
.map(|bank| max_joltage(bank, 2, 0))
9+
.sum();
10+
println!("{}", value)
11+
}
12+
13+
pub fn part_two(input_type: &InputType) {
14+
let value: u64 = get_banks(&input_type)
15+
.into_iter()
16+
.map(|bank| max_joltage(bank, 12, 0))
17+
.sum();
18+
println!("{}", value)
19+
}
20+
21+
fn max_joltage(bank: Vec<u8>, digits: usize, start: usize) -> u64 {
22+
if digits == 0 {
23+
return 0;
24+
}
25+
let mut max = bank[start];
26+
let mut maxi = start;
27+
for i in start + 1..=bank.len() - digits {
28+
if bank[i] > max {
29+
max = bank[i];
30+
maxi = i;
31+
}
32+
}
33+
34+
let current_digit_value = (bank[maxi] as u64) * 10u64.pow((digits-1) as u32);
35+
let remaining_digits_value = max_joltage(bank, digits - 1, maxi + 1);
36+
37+
current_digit_value + remaining_digits_value
38+
}
39+
40+
fn get_banks(input_type: &InputType) -> Vec<Vec<u8>> {
41+
read_input(DAY, input_type)
42+
.as_str()
43+
.trim()
44+
.split("\n")
45+
.map(|line| {
46+
line.chars()
47+
.map(|c| c.to_digit(10).unwrap() as u8)
48+
.collect()
49+
})
50+
.collect()
51+
}

Day-04/rust/duckulus/day04.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use crate::common::{InputType, read_input};
2+
3+
const DAY: usize = 4;
4+
5+
pub fn part_one(input_type: &InputType) {
6+
let mut grid = get_grid(input_type);
7+
let value = remove_unaccessible(&mut grid);
8+
println!("{}", value)
9+
}
10+
11+
pub fn part_two(input_type: &InputType) {
12+
let mut grid = get_grid(input_type);
13+
let mut sum = 0;
14+
let mut value = 0;
15+
value = remove_unaccessible(&mut grid);
16+
while value > 0 {
17+
sum += value;
18+
value = remove_unaccessible(&mut grid);
19+
}
20+
println!("{}", sum)
21+
}
22+
23+
fn remove_unaccessible(grid: &mut Vec<Vec<Cell>>) -> usize {
24+
let mut remove: Vec<(usize, usize)> = Vec::new();
25+
26+
let rows = grid.len() as i32;
27+
for y in 0..rows {
28+
let cols = grid[y as usize].len() as i32;
29+
for x in 0..cols {
30+
if grid[y as usize][x as usize] != Cell::Roll {
31+
continue;
32+
}
33+
let mut neighbors = 0;
34+
for dy in -1..=1 {
35+
let ny = (y) + dy;
36+
if (ny < 0 || ny >= rows) {
37+
continue;
38+
}
39+
for dx in -1..=1 {
40+
if (dx == 0 && dy == 0) {
41+
continue;
42+
}
43+
let nx = (x) + dx;
44+
if (nx < 0 || nx >= cols) {
45+
continue;
46+
}
47+
if grid[ny as usize][nx as usize] == Cell::Roll {
48+
neighbors += 1;
49+
}
50+
}
51+
}
52+
if neighbors < 4 {
53+
remove.push((x as usize, y as usize));
54+
}
55+
}
56+
}
57+
58+
for (x, y) in remove.iter() {
59+
grid[*y][*x] = Cell::Empty;
60+
}
61+
62+
remove.len()
63+
}
64+
65+
#[derive(PartialEq)]
66+
enum Cell {
67+
Roll,
68+
Empty,
69+
}
70+
71+
fn to_cell(c: char) -> Cell {
72+
match c {
73+
'.' => Cell::Empty,
74+
'@' => Cell::Roll,
75+
_ => panic!("Found invalid cell: {}", c),
76+
}
77+
}
78+
79+
fn get_grid(input_type: &InputType) -> Vec<Vec<Cell>> {
80+
read_input(DAY, input_type)
81+
.as_str()
82+
.trim()
83+
.lines()
84+
.map(|line| line.trim().chars().map(to_cell).collect())
85+
.collect()
86+
}

Day-05/rust/duckulus/day05.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use crate::common::{InputType, read_input, Range};
2+
use std::cmp::{max, min};
3+
use std::collections::HashSet;
4+
5+
const DAY: usize = 5;
6+
7+
fn parse(input_type: &InputType) -> (Vec<Range>, Vec<i64>) {
8+
let input = read_input(DAY, input_type);
9+
let (ranges, ingredients) = input.split_once("\n\n").unwrap();
10+
11+
let ranges: Vec<_> = ranges
12+
.lines()
13+
.map(|line: &str| {
14+
let (l, h) = line.split_once("-").unwrap();
15+
Range {
16+
l: l.parse::<i64>().unwrap(),
17+
h: h.parse::<i64>().unwrap(),
18+
}
19+
})
20+
.collect();
21+
22+
let ingredients: Vec<_> = ingredients
23+
.lines()
24+
.map(|line: &str| line.parse::<i64>().unwrap())
25+
.collect();
26+
27+
(ranges, ingredients)
28+
}
29+
30+
pub fn part_one(input_type: &InputType) {
31+
let (ranges, ingredients) = parse(input_type);
32+
33+
let mut sum = 0;
34+
for ingredient in ingredients {
35+
for range in &ranges {
36+
if range.l <= ingredient && range.h >= ingredient {
37+
sum += 1;
38+
break;
39+
}
40+
}
41+
}
42+
println!("{}", sum);
43+
}
44+
45+
pub fn part_two(input_type: &InputType) {
46+
let (ranges, _) = parse(input_type);
47+
48+
let mut range_list = Vec::new();
49+
50+
for range in ranges {
51+
if range_list.is_empty() {
52+
range_list.push(range);
53+
continue;
54+
}
55+
56+
let mut intersecting: Vec<Range> = range_list
57+
.iter()
58+
.filter(|r| r.intersection(&range).is_some())
59+
.map(|r| r.clone())
60+
.collect();
61+
intersecting.push(range.clone());
62+
63+
let l = intersecting.iter().map(|r| r.l).min().unwrap();
64+
let h = intersecting.iter().map(|r| r.h).max().unwrap();
65+
let union = Range { l, h };
66+
67+
range_list.retain(|r| r.intersection(&range).is_none());
68+
range_list.push(union);
69+
}
70+
71+
let sum: i64 = range_list.iter().map(|r| r.len()).sum();
72+
println!("{}", sum);
73+
}
74+
75+
#[cfg(test)]
76+
mod test {
77+
use crate::day05::Range;
78+
79+
#[test]
80+
fn test_range_intersect() {
81+
let r1 = Range { l: 3, h: 5 };
82+
let r2 = Range { l: 6, h: 8 };
83+
let r3 = Range { l: 4, h: 9 };
84+
let r4 = Range { l: 1, h: 4 };
85+
let r5 = Range { l: 5, h: 6 };
86+
87+
assert_eq!(0, r1.intersect(&r2));
88+
assert_eq!(2, r1.intersect(&r3));
89+
assert_eq!(2, r1.intersect(&r4));
90+
assert_eq!(1, r1.intersect(&r5));
91+
assert_eq!(3, r1.intersect(&r1));
92+
}
93+
}

0 commit comments

Comments
 (0)