diff options
| -rw-r--r-- | 2022/01/a.rs | 8 | ||||
| -rw-r--r-- | 2022/01/b.rs | 9 | ||||
| -rw-r--r-- | 2022/01/common.rs | 18 | ||||
| -rw-r--r-- | 2022/02/a.rs | 13 | ||||
| -rw-r--r-- | 2022/02/b.rs | 13 | ||||
| -rw-r--r-- | 2022/02/common.rs | 10 | ||||
| -rw-r--r-- | 2022/03/a.rs | 26 | ||||
| -rw-r--r-- | 2022/03/b.rs | 29 | ||||
| -rw-r--r-- | 2022/03/common.rs | 7 | ||||
| -rw-r--r-- | 2022/04/a.rs | 7 | ||||
| -rw-r--r-- | 2022/04/b.rs | 8 | ||||
| -rw-r--r-- | 2022/04/common.rs | 20 | ||||
| -rw-r--r-- | 2022/05/a.rs | 17 | ||||
| -rw-r--r-- | 2022/05/b.rs | 20 | ||||
| -rw-r--r-- | 2022/05/common.rs | 73 | ||||
| -rw-r--r-- | 2022/06/a.rs | 9 | ||||
| -rw-r--r-- | 2022/06/b.rs | 9 | ||||
| -rw-r--r-- | 2022/06/common.rs | 20 | ||||
| -rw-r--r-- | 2022/07/a.rs | 12 | ||||
| -rw-r--r-- | 2022/07/b.rs | 13 | ||||
| -rw-r--r-- | 2022/07/common.rs | 130 | ||||
| -rw-r--r-- | 2022/08/a.rs | 42 | ||||
| -rw-r--r-- | 2022/08/b.rs | 47 | ||||
| -rw-r--r-- | 2022/08/common.rs | 13 | ||||
| -rw-r--r-- | 2022/09/a.rs | 6 | ||||
| -rw-r--r-- | 2022/09/b.rs | 6 | ||||
| -rw-r--r-- | 2022/09/common.rs | 46 | ||||
| -rw-r--r-- | 2022/README.md | 12 | ||||
| -rwxr-xr-x | 2022/run.sh | 12 |
29 files changed, 655 insertions, 0 deletions
diff --git a/2022/01/a.rs b/2022/01/a.rs new file mode 100644 index 0000000..77e57e4 --- /dev/null +++ b/2022/01/a.rs | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let e = get_elves_from_stdin(); | ||
| 6 | let m: i64 = e.iter().map(|a| a.iter().sum()).max().unwrap(); | ||
| 7 | println!("{m}"); | ||
| 8 | } | ||
diff --git a/2022/01/b.rs b/2022/01/b.rs new file mode 100644 index 0000000..ca0b324 --- /dev/null +++ b/2022/01/b.rs | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let e = get_elves_from_stdin(); | ||
| 6 | let mut w = e.iter().map(|a| a.iter().sum()).collect::<Vec<i64>>(); | ||
| 7 | w.sort_by(|a, b| b.cmp(a)); | ||
| 8 | println!("{}", w[0] + w[1] + w[2]); | ||
| 9 | } | ||
diff --git a/2022/01/common.rs b/2022/01/common.rs new file mode 100644 index 0000000..8ed8b49 --- /dev/null +++ b/2022/01/common.rs | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | pub fn get_elves_from_stdin() -> Vec<Vec<i64>> { | ||
| 2 | let mut e = Vec::<Vec::<i64>>::new(); | ||
| 3 | e.push(Vec::<i64>::new()); | ||
| 4 | let mut line = String::new(); | ||
| 5 | loop { | ||
| 6 | match std::io::stdin().read_line(&mut line).unwrap() { | ||
| 7 | 0 => break, | ||
| 8 | 1 => e.push(Vec::<i64>::new()), | ||
| 9 | _ => { | ||
| 10 | let n = line.trim().parse::<i64>().unwrap(); | ||
| 11 | let last = e.len() - 1; | ||
| 12 | e[last].push(n); | ||
| 13 | } | ||
| 14 | } | ||
| 15 | line.clear(); | ||
| 16 | } | ||
| 17 | e | ||
| 18 | } | ||
diff --git a/2022/02/a.rs b/2022/02/a.rs new file mode 100644 index 0000000..1a49a6b --- /dev/null +++ b/2022/02/a.rs | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | pub fn main() { | ||
| 5 | let play_score = |s: &[u8]| (s[2] as i64) - ('X' as i64) + 1; | ||
| 6 | let win_score = |s: &[u8]| { | ||
| 7 | let other = s[0] as i64 - ('A' as i64); | ||
| 8 | let me = s[2] as i64 - ('X' as i64); | ||
| 9 | 3 * ((me - other + 4) % 3) | ||
| 10 | }; | ||
| 11 | let score = get_score(play_score, win_score); | ||
| 12 | println!("{score}"); | ||
| 13 | } | ||
diff --git a/2022/02/b.rs b/2022/02/b.rs new file mode 100644 index 0000000..9f2b580 --- /dev/null +++ b/2022/02/b.rs | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | pub fn main() { | ||
| 5 | let play_score = |s: &[u8]| { | ||
| 6 | let other = s[0] as i64 - ('A' as i64); | ||
| 7 | let w = s[2] as i64 - ('X' as i64); | ||
| 8 | (other + w + 2) % 3 + 1 | ||
| 9 | }; | ||
| 10 | let win_score = |s: &[u8]| 3 * ((s[2] as i64) - ('X' as i64)); | ||
| 11 | let score = get_score(play_score, win_score); | ||
| 12 | println!("{score}"); | ||
| 13 | } | ||
diff --git a/2022/02/common.rs b/2022/02/common.rs new file mode 100644 index 0000000..04581cf --- /dev/null +++ b/2022/02/common.rs | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | pub fn get_score(play_score: fn(&[u8]) -> i64, win_score: fn(&[u8]) -> i64) -> i64 { | ||
| 2 | let mut score = 0; | ||
| 3 | let mut line = String::new(); | ||
| 4 | while std::io::stdin().read_line(&mut line).unwrap() > 0 { | ||
| 5 | let l = line.as_bytes(); | ||
| 6 | score += play_score(l) + win_score(l); | ||
| 7 | line.clear(); | ||
| 8 | } | ||
| 9 | score | ||
| 10 | } | ||
diff --git a/2022/03/a.rs b/2022/03/a.rs new file mode 100644 index 0000000..568546c --- /dev/null +++ b/2022/03/a.rs | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn get_rep_val(rucksack: &[u8]) -> i64 { | ||
| 5 | let mut seen = [false; 256]; | ||
| 6 | let mid = rucksack.len()/2; | ||
| 7 | for i in 0..mid { | ||
| 8 | seen[rucksack[i] as usize] = true; | ||
| 9 | } | ||
| 10 | for i in mid..rucksack.len() { | ||
| 11 | if seen[rucksack[i] as usize] { | ||
| 12 | return value(rucksack[i] as char); | ||
| 13 | } | ||
| 14 | } | ||
| 15 | panic!("Could not find repeated char"); | ||
| 16 | } | ||
| 17 | |||
| 18 | fn main() { | ||
| 19 | let mut sum = 0; | ||
| 20 | let mut line = String::new(); | ||
| 21 | while std::io::stdin().read_line(&mut line).unwrap() > 0 { | ||
| 22 | sum += get_rep_val(line.as_bytes()); | ||
| 23 | line.clear(); | ||
| 24 | } | ||
| 25 | println!("{sum}"); | ||
| 26 | } | ||
diff --git a/2022/03/b.rs b/2022/03/b.rs new file mode 100644 index 0000000..89da764 --- /dev/null +++ b/2022/03/b.rs | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn get_rep_val(e: &[String; 3]) -> i64 { | ||
| 5 | let mut seen = [[false; 256]; 2]; | ||
| 6 | for i in 0..2 { | ||
| 7 | for c in e[i].chars() { | ||
| 8 | seen[i][c as usize] = true; | ||
| 9 | } | ||
| 10 | } | ||
| 11 | for c in e[2].chars() { | ||
| 12 | if seen[0][c as usize] && seen[1][c as usize] { | ||
| 13 | return value(c); | ||
| 14 | } | ||
| 15 | } | ||
| 16 | panic!("Could not find repeated char"); | ||
| 17 | } | ||
| 18 | |||
| 19 | fn main() { | ||
| 20 | let mut sum = 0; | ||
| 21 | let mut lines: [String; 3] = Default::default(); | ||
| 22 | while std::io::stdin().read_line(&mut lines[0]).unwrap() > 0 { | ||
| 23 | let _ = std::io::stdin().read_line(&mut lines[1]); | ||
| 24 | let _ = std::io::stdin().read_line(&mut lines[2]); | ||
| 25 | sum += get_rep_val(&lines); | ||
| 26 | for l in &mut lines { l.clear(); } | ||
| 27 | } | ||
| 28 | println!("{sum}"); | ||
| 29 | } | ||
diff --git a/2022/03/common.rs b/2022/03/common.rs new file mode 100644 index 0000000..cf323f5 --- /dev/null +++ b/2022/03/common.rs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | pub fn value(c: char) -> i64 { | ||
| 2 | match c { | ||
| 3 | 'a'..='z' => (c as i64) - ('a' as i64) + 1, | ||
| 4 | 'A'..='Z' => (c as i64) - ('A' as i64) + 27, | ||
| 5 | _ => panic!("Error: unexpected character '{}'", c) | ||
| 6 | } | ||
| 7 | } | ||
diff --git a/2022/04/a.rs b/2022/04/a.rs new file mode 100644 index 0000000..d69821a --- /dev/null +++ b/2022/04/a.rs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let contained = |a: (i64, i64), b: (i64, i64)| a.0 >= b.0 && a.1 <= b.1; | ||
| 6 | println!("{}", count(|a, b| contained(a, b) || contained(b, a))); | ||
| 7 | } | ||
diff --git a/2022/04/b.rs b/2022/04/b.rs new file mode 100644 index 0000000..2affb65 --- /dev/null +++ b/2022/04/b.rs | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let overlap = |a: (i64, i64), b: (i64, i64)| | ||
| 6 | (a.0 >= b.0 && a.0 <= b.1) || (b.0 >= a.0 && b.0 <= a.1); | ||
| 7 | println!("{}", count(overlap)); | ||
| 8 | } | ||
diff --git a/2022/04/common.rs b/2022/04/common.rs new file mode 100644 index 0000000..92c32f1 --- /dev/null +++ b/2022/04/common.rs | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | fn get_ints(line: &str) -> ((i64, i64), (i64, i64)) { | ||
| 2 | let i = line.find('-').unwrap(); | ||
| 3 | let j = line.find(',').unwrap(); | ||
| 4 | let k = line[j..].find('-').unwrap() + j; | ||
| 5 | ((line[..i].parse().unwrap(), line[i+1..j].parse().unwrap()), | ||
| 6 | (line[j+1..k].parse().unwrap(), line[k+1..line.len()-1].parse().unwrap())) | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn count<F: Fn((i64, i64), (i64, i64)) -> bool>(condition: F) -> i64 { | ||
| 10 | let mut line = String::new(); | ||
| 11 | let mut sum = 0; | ||
| 12 | while std::io::stdin().read_line(&mut line).unwrap() > 0 { | ||
| 13 | let (a, b) = get_ints(&line); | ||
| 14 | if condition(a, b) { | ||
| 15 | sum += 1; | ||
| 16 | } | ||
| 17 | line.clear(); | ||
| 18 | } | ||
| 19 | sum | ||
| 20 | } | ||
diff --git a/2022/05/a.rs b/2022/05/a.rs new file mode 100644 index 0000000..ae0e937 --- /dev/null +++ b/2022/05/a.rs | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn apply_move(grid: &mut Vec::<Vec::<char>>, line: &str) { | ||
| 5 | let (n, from, to) = read_move(&line); | ||
| 6 | |||
| 7 | for _ in 0..n { | ||
| 8 | let x = grid[from-1].pop().unwrap(); | ||
| 9 | grid[to-1].push(x); | ||
| 10 | } | ||
| 11 | } | ||
| 12 | |||
| 13 | fn main() { | ||
| 14 | let mut grid = get_grid_from_stdin(); | ||
| 15 | apply_moves_from_stdin(&mut grid, apply_move); | ||
| 16 | print_top(&grid); | ||
| 17 | } | ||
diff --git a/2022/05/b.rs b/2022/05/b.rs new file mode 100644 index 0000000..824ee5e --- /dev/null +++ b/2022/05/b.rs | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn apply_move(grid: &mut Vec::<Vec::<char>>, line: &str) { | ||
| 5 | let (n, from, to) = read_move(&line); | ||
| 6 | |||
| 7 | let first_moved = grid[from-1].len()-n; | ||
| 8 | let len = grid[from-1].len(); | ||
| 9 | for i in first_moved..len { | ||
| 10 | let x = grid[from-1][i]; | ||
| 11 | grid[to-1].push(x); | ||
| 12 | } | ||
| 13 | grid[from-1].drain(first_moved..len); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn main() { | ||
| 17 | let mut grid = get_grid_from_stdin(); | ||
| 18 | apply_moves_from_stdin(&mut grid, apply_move); | ||
| 19 | print_top(&grid); | ||
| 20 | } | ||
diff --git a/2022/05/common.rs b/2022/05/common.rs new file mode 100644 index 0000000..1725f09 --- /dev/null +++ b/2022/05/common.rs | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | pub type Grid = Vec<Vec<char>>; | ||
| 2 | |||
| 3 | fn read_rows() -> Vec<Vec<char>> { | ||
| 4 | let mut rows = Vec::<Vec::<char>>::new(); | ||
| 5 | let mut line = String::new(); | ||
| 6 | loop { | ||
| 7 | let mut row = Vec::<char>::new(); | ||
| 8 | |||
| 9 | std::io::stdin().read_line(&mut line).unwrap(); | ||
| 10 | let line_chars = line.as_bytes(); | ||
| 11 | if line_chars[1] == '1' as u8 { | ||
| 12 | let _ = std::io::stdin().read_line(&mut line); | ||
| 13 | break; | ||
| 14 | } | ||
| 15 | |||
| 16 | let mut i = 0; | ||
| 17 | while i < line_chars.len() { | ||
| 18 | row.push(line_chars[i+1] as char); | ||
| 19 | i += 4; | ||
| 20 | } | ||
| 21 | |||
| 22 | rows.push(row); | ||
| 23 | line.clear(); | ||
| 24 | } | ||
| 25 | |||
| 26 | rows | ||
| 27 | } | ||
| 28 | |||
| 29 | fn rows_to_grid(rows: &Vec<Vec<char>>) -> Grid { | ||
| 30 | let mut grid = vec![Vec::<char>::new(); rows[0].len()]; | ||
| 31 | for row in rows.iter().rev() { | ||
| 32 | for i in 0..row.len() { | ||
| 33 | if row[i] != ' ' { | ||
| 34 | grid[i].push(row[i]); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | grid | ||
| 39 | } | ||
| 40 | |||
| 41 | fn next_usize(line: &str, s: usize) -> (usize, usize) { | ||
| 42 | let i = line[s..].find(|c: char| c.is_digit(10)).unwrap() + s; | ||
| 43 | let j = line[i..].find(|c: char| c.is_whitespace()).unwrap() + i; | ||
| 44 | (line[i..j].parse::<usize>().unwrap(), j) | ||
| 45 | } | ||
| 46 | |||
| 47 | pub fn read_move(line: &str) -> (usize, usize, usize) { | ||
| 48 | let (n, i) = next_usize(line, 0); | ||
| 49 | let (from, i) = next_usize(line, i); | ||
| 50 | let (to, _) = next_usize(line, i); | ||
| 51 | |||
| 52 | (n, from, to) | ||
| 53 | } | ||
| 54 | |||
| 55 | pub fn get_grid_from_stdin() -> Grid { | ||
| 56 | rows_to_grid(&read_rows()) | ||
| 57 | } | ||
| 58 | |||
| 59 | pub fn apply_moves_from_stdin<F: Fn(&mut Grid, &str) -> ()>(grid: &mut Grid, apply_move: F) { | ||
| 60 | let mut line = String::new(); | ||
| 61 | while std::io::stdin().read_line(&mut line).unwrap() > 0 { | ||
| 62 | apply_move(grid, &line); | ||
| 63 | line.clear(); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | pub fn print_top(grid: &Grid) { | ||
| 68 | for column in grid { | ||
| 69 | let c = match column.last() { Some(d) => d, None => &'_' }; | ||
| 70 | print!("{}", c); | ||
| 71 | } | ||
| 72 | println!(); | ||
| 73 | } | ||
diff --git a/2022/06/a.rs b/2022/06/a.rs new file mode 100644 index 0000000..996f9a5 --- /dev/null +++ b/2022/06/a.rs | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let mut line = String::new(); | ||
| 6 | std::io::stdin().read_line(&mut line).unwrap(); | ||
| 7 | let i = first_index_n_distinct(line.as_bytes(), 4) + 1; | ||
| 8 | println!("{i}"); | ||
| 9 | } | ||
diff --git a/2022/06/b.rs b/2022/06/b.rs new file mode 100644 index 0000000..78d2703 --- /dev/null +++ b/2022/06/b.rs | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let mut line = String::new(); | ||
| 6 | std::io::stdin().read_line(&mut line).unwrap(); | ||
| 7 | let i = first_index_n_distinct(line.as_bytes(), 14) + 1; | ||
| 8 | println!("{i}"); | ||
| 9 | } | ||
diff --git a/2022/06/common.rs b/2022/06/common.rs new file mode 100644 index 0000000..ed5360c --- /dev/null +++ b/2022/06/common.rs | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | fn all_distinct<T: PartialEq>(a: &[T]) -> bool { | ||
| 2 | for i in 0..a.len() { | ||
| 3 | for j in i+1..a.len() { | ||
| 4 | if a[i] == a[j] { | ||
| 5 | return false; | ||
| 6 | } | ||
| 7 | } | ||
| 8 | } | ||
| 9 | return true; | ||
| 10 | } | ||
| 11 | |||
| 12 | pub fn first_index_n_distinct(a: &[u8], n: usize) -> usize { | ||
| 13 | assert!(n > 0, "{} must be greater than 0", n); | ||
| 14 | for i in 0..a.len()-n+1 { | ||
| 15 | if all_distinct(&a[i..i+n]) { | ||
| 16 | return i+n-1; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | panic!("Cannot find {} distinct in a row", n); | ||
| 20 | } | ||
diff --git a/2022/07/a.rs b/2022/07/a.rs new file mode 100644 index 0000000..a0d9a1a --- /dev/null +++ b/2022/07/a.rs | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let fs = FileSystem::build_from_stdin(); | ||
| 6 | let sum: usize = fs.iter() | ||
| 7 | .filter(|f| matches!(f.kind, FileType::Directory(_))) | ||
| 8 | .map(|f| f.real_size(&fs)) | ||
| 9 | .filter(|s| *s <= 100000) | ||
| 10 | .sum(); | ||
| 11 | println!("{sum}"); | ||
| 12 | } | ||
diff --git a/2022/07/b.rs b/2022/07/b.rs new file mode 100644 index 0000000..92bedc7 --- /dev/null +++ b/2022/07/b.rs | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let fs = FileSystem::build_from_stdin(); | ||
| 6 | let remaining = 70000000 - fs[0].real_size(&fs); | ||
| 7 | let ds: usize = fs.iter() | ||
| 8 | .filter(|f| matches!(f.kind, FileType::Directory(_))) | ||
| 9 | .map(|f| f.real_size(&fs)) | ||
| 10 | .filter(|s| *s + remaining >= 30000000) | ||
| 11 | .min().unwrap(); | ||
| 12 | println!("{ds}"); | ||
| 13 | } | ||
diff --git a/2022/07/common.rs b/2022/07/common.rs new file mode 100644 index 0000000..675bf29 --- /dev/null +++ b/2022/07/common.rs | |||
| @@ -0,0 +1,130 @@ | |||
| 1 | use std::ops; | ||
| 2 | |||
| 3 | pub enum FileType { | ||
| 4 | File(usize), | ||
| 5 | Directory(Vec<usize>) | ||
| 6 | } | ||
| 7 | |||
| 8 | pub struct File { | ||
| 9 | pub kind: FileType, | ||
| 10 | name: String | ||
| 11 | } | ||
| 12 | |||
| 13 | impl File { | ||
| 14 | pub fn real_size(&self, fs: &FileSystem) -> usize { | ||
| 15 | match &self.kind { | ||
| 16 | FileType::File(s) => *s, | ||
| 17 | FileType::Directory(c) => | ||
| 18 | c.iter().map(|x: &usize| fs[*x].real_size(&fs)).sum() | ||
| 19 | } | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | pub struct FileSystem { | ||
| 24 | files: Vec<File> | ||
| 25 | } | ||
| 26 | |||
| 27 | impl FileSystem { | ||
| 28 | fn new() -> Self { | ||
| 29 | Self { | ||
| 30 | files: vec![File { | ||
| 31 | kind: FileType::Directory(Vec::<usize>::new()), | ||
| 32 | name: String::from("/") | ||
| 33 | }] | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn build_from_stdin() -> Self { | ||
| 38 | let mut fs = FileSystem::new(); | ||
| 39 | let mut path = Path::new(); | ||
| 40 | let mut line = String::new(); | ||
| 41 | while std::io::stdin().read_line(&mut line).unwrap() > 0 { | ||
| 42 | if &line[..5] == "$ cd " { | ||
| 43 | exec_cd(&line[5..], &mut path, &fs); | ||
| 44 | } else if &line[..3] == "dir" { | ||
| 45 | fs.add_dir(&line[4..line.len()-1], path.last()); | ||
| 46 | } else if line.as_bytes()[0] != '$' as u8 { | ||
| 47 | let i = line.find(' ').unwrap(); | ||
| 48 | let size = line[0..i].parse::<usize>().unwrap(); | ||
| 49 | fs.add_file(&line[i+1..line.len()-1], size, path.last()); | ||
| 50 | } | ||
| 51 | line.clear(); | ||
| 52 | } | ||
| 53 | fs | ||
| 54 | } | ||
| 55 | |||
| 56 | fn make_parent(&mut self, id: usize, parent: usize) { | ||
| 57 | let p = &mut self.files[parent]; | ||
| 58 | if let FileType::Directory(v) = &mut p.kind { | ||
| 59 | v.push(id); | ||
| 60 | } else { | ||
| 61 | panic!("Parent is not a directory"); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | fn add_dir(&mut self, name: &str, parent: usize) { | ||
| 66 | let id = self.files.len(); | ||
| 67 | self.files.push( | ||
| 68 | File { | ||
| 69 | kind: FileType::Directory(Vec::<usize>::new()), | ||
| 70 | name: String::from(name) | ||
| 71 | } | ||
| 72 | ); | ||
| 73 | self.make_parent(id, parent); | ||
| 74 | } | ||
| 75 | |||
| 76 | fn add_file(&mut self, name: &str, size: usize, parent: usize) { | ||
| 77 | let id = self.files.len(); | ||
| 78 | self.files.push( | ||
| 79 | File { | ||
| 80 | kind: FileType::File(size), | ||
| 81 | name: String::from(name) | ||
| 82 | } | ||
| 83 | ); | ||
| 84 | self.make_parent(id, parent); | ||
| 85 | } | ||
| 86 | |||
| 87 | pub fn iter(&self) -> impl Iterator<Item = &File>{ | ||
| 88 | self.files.iter() | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | impl ops::Index<usize> for FileSystem { | ||
| 93 | type Output = File; | ||
| 94 | fn index(&self, i: usize) -> &File { | ||
| 95 | &self.files[i] | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | struct Path { | ||
| 100 | stack: Vec<usize> | ||
| 101 | } | ||
| 102 | |||
| 103 | impl Path { | ||
| 104 | fn new() -> Self { Self { stack: vec![0] } } // 0 is the id of "/" | ||
| 105 | fn last(&self) -> usize { *self.stack.last().unwrap() } | ||
| 106 | fn clear(&mut self) { self.stack.drain(1..); } | ||
| 107 | fn pop(&mut self) { self.stack.pop(); } | ||
| 108 | fn push(&mut self, dir_id: usize) { self.stack.push(dir_id); } | ||
| 109 | } | ||
| 110 | |||
| 111 | fn exec_cd(line: &str, path: &mut Path, fs: &FileSystem) { | ||
| 112 | if line.as_bytes()[0] == '/' as u8 { | ||
| 113 | path.clear(); | ||
| 114 | } else if &line[..2] == ".." { | ||
| 115 | path.pop(); | ||
| 116 | } else { | ||
| 117 | let current_dir = &fs[path.last()]; | ||
| 118 | if let FileType::Directory(children) = ¤t_dir.kind { | ||
| 119 | for c in children { | ||
| 120 | if fs[*c].name == &line[..line.len()-1] { | ||
| 121 | path.push(*c); | ||
| 122 | return; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } else { | ||
| 126 | panic!("Non-directory in path"); | ||
| 127 | } | ||
| 128 | panic!("Directory not found in current path"); | ||
| 129 | } | ||
| 130 | } | ||
diff --git a/2022/08/a.rs b/2022/08/a.rs new file mode 100644 index 0000000..b145486 --- /dev/null +++ b/2022/08/a.rs | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | use std::cmp::max; | ||
| 2 | mod common; | ||
| 3 | use common::*; | ||
| 4 | |||
| 5 | fn mark_visible(grid: &mut Grid) { | ||
| 6 | let update = |elem: &mut (i8, bool), m: &mut i8| { | ||
| 7 | elem.1 = elem.1 || elem.0 > *m; | ||
| 8 | *m = max(*m, elem.0); | ||
| 9 | }; | ||
| 10 | |||
| 11 | for row in &mut *grid { | ||
| 12 | // From left | ||
| 13 | let mut m = -1; | ||
| 14 | for t in &mut *row { update(t, &mut m); } | ||
| 15 | |||
| 16 | // From right | ||
| 17 | let mut m = -1; | ||
| 18 | for t in &mut row.iter_mut().rev() { update(t, &mut m); } | ||
| 19 | } | ||
| 20 | |||
| 21 | for j in 0..grid[0].len() { | ||
| 22 | // From top | ||
| 23 | let mut m = -1; | ||
| 24 | for i in 0..grid.len() { update(&mut grid[i][j], &mut m); } | ||
| 25 | |||
| 26 | // From bottom | ||
| 27 | let mut m = -1; | ||
| 28 | for i in (0..grid.len()).rev() { update(&mut grid[i][j], &mut m); } | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | fn count_visible(grid: &Grid) -> usize { | ||
| 33 | grid.iter() | ||
| 34 | .map(|row| row.iter().filter(|c| c.1).count()) | ||
| 35 | .sum() | ||
| 36 | } | ||
| 37 | |||
| 38 | fn main() { | ||
| 39 | let mut grid = read_grid_from_stdin(); | ||
| 40 | mark_visible(&mut grid); | ||
| 41 | println!("{}", count_visible(&grid)); | ||
| 42 | } | ||
diff --git a/2022/08/b.rs b/2022/08/b.rs new file mode 100644 index 0000000..5f7bce8 --- /dev/null +++ b/2022/08/b.rs | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | use std::cmp::max; | ||
| 2 | mod common; | ||
| 3 | use common::*; | ||
| 4 | |||
| 5 | fn count_visible_from(grid: &Grid, i0: usize, j0: usize) -> usize { | ||
| 6 | let x = grid[i0][j0].0; | ||
| 7 | let mut top = 0; | ||
| 8 | for i in (0..i0).rev() { | ||
| 9 | top += 1; | ||
| 10 | if grid[i][j0].0 >= x { break; } | ||
| 11 | } | ||
| 12 | |||
| 13 | let mut bottom = 0; | ||
| 14 | for i in i0+1..grid.len() { | ||
| 15 | bottom += 1; | ||
| 16 | if grid[i][j0].0 >= x { break; } | ||
| 17 | } | ||
| 18 | |||
| 19 | let mut left = 0; | ||
| 20 | for j in (0..j0).rev() { | ||
| 21 | left += 1; | ||
| 22 | if grid[i0][j].0 >= x { break; } | ||
| 23 | } | ||
| 24 | |||
| 25 | let mut right = 0; | ||
| 26 | for j in j0+1..grid[0].len() { | ||
| 27 | right += 1; | ||
| 28 | if grid[i0][j].0 >= x { break; } | ||
| 29 | } | ||
| 30 | |||
| 31 | top * bottom * left * right | ||
| 32 | } | ||
| 33 | |||
| 34 | fn max_view_factor(grid: &Grid) -> usize { | ||
| 35 | let mut m = 0; | ||
| 36 | for i in 0..grid.len() { | ||
| 37 | for j in 0..grid[0].len() { | ||
| 38 | m = max(m, count_visible_from(grid, i, j)); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | m | ||
| 42 | } | ||
| 43 | |||
| 44 | fn main() { | ||
| 45 | let grid = read_grid_from_stdin(); | ||
| 46 | println!("{}", max_view_factor(&grid)); | ||
| 47 | } | ||
diff --git a/2022/08/common.rs b/2022/08/common.rs new file mode 100644 index 0000000..45fbf10 --- /dev/null +++ b/2022/08/common.rs | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | pub type Grid = Vec<Vec<(i8, bool)>>; | ||
| 2 | |||
| 3 | pub fn read_grid_from_stdin() -> Grid { | ||
| 4 | let mut grid = Vec::<Vec<(i8, bool)>>::new(); | ||
| 5 | let mut line = String::new(); | ||
| 6 | while std::io::stdin().read_line(&mut line).unwrap() > 0 { | ||
| 7 | let row = line[..line.len()-1].as_bytes().iter() | ||
| 8 | .map(|b| ((*b as i8) - ('0' as i8), false)).collect(); | ||
| 9 | grid.push(row); | ||
| 10 | line.clear(); | ||
| 11 | } | ||
| 12 | grid | ||
| 13 | } | ||
diff --git a/2022/09/a.rs b/2022/09/a.rs new file mode 100644 index 0000000..0fc6278 --- /dev/null +++ b/2022/09/a.rs | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | println!("{}", simulate(2).len()); | ||
| 6 | } | ||
diff --git a/2022/09/b.rs b/2022/09/b.rs new file mode 100644 index 0000000..1d43500 --- /dev/null +++ b/2022/09/b.rs | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | println!("{}", simulate(10).len()); | ||
| 6 | } | ||
diff --git a/2022/09/common.rs b/2022/09/common.rs new file mode 100644 index 0000000..45048da --- /dev/null +++ b/2022/09/common.rs | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | use std::collections::HashSet; | ||
| 2 | |||
| 3 | fn get_dir(c: char) -> (i64, i64) { | ||
| 4 | match c { | ||
| 5 | 'R' => (1, 0), | ||
| 6 | 'L' => (-1, 0), | ||
| 7 | 'U' => (0, 1), | ||
| 8 | 'D' => (0, -1), | ||
| 9 | _ => panic!("Unexpected char") | ||
| 10 | } | ||
| 11 | } | ||
| 12 | |||
| 13 | fn follow(lead: (i64, i64), trail: (i64, i64)) -> (i64, i64) { | ||
| 14 | let max1 = |x: i64| x / (2 - (x%2).abs()); | ||
| 15 | let d = (max1(lead.0 - trail.0), max1(lead.1 - trail.1)); | ||
| 16 | (trail.0 + d.0, trail.1 + d.1) | ||
| 17 | } | ||
| 18 | |||
| 19 | fn step(r: &mut Vec<(i64, i64)>, d: (i64, i64)) { | ||
| 20 | r[0] = (r[0].0 + d.0, r[0].1 + d.1); | ||
| 21 | for i in 1..r.len() { | ||
| 22 | if (r[i].0 - r[i-1].0).abs() > 1 || (r[i].1 - r[i-1].1).abs() > 1 { | ||
| 23 | r[i] = follow(r[i-1], r[i]); | ||
| 24 | } else { | ||
| 25 | break; | ||
| 26 | } | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | pub fn simulate(n: usize) -> HashSet<(i64, i64)> { | ||
| 31 | let mut r = vec![(0, 0); n]; | ||
| 32 | let mut visited = HashSet::<(i64, i64)>::new(); | ||
| 33 | visited.insert(r[n-1]); | ||
| 34 | |||
| 35 | let mut line = String::new(); | ||
| 36 | while std::io::stdin().read_line(&mut line).unwrap() > 0 { | ||
| 37 | let dir = get_dir(line.chars().nth(0).unwrap()); | ||
| 38 | let l = line[2..line.len()-1].parse::<usize>().unwrap(); | ||
| 39 | for _ in 0..l { | ||
| 40 | step(&mut r, dir); | ||
| 41 | visited.insert(r[n-1]); | ||
| 42 | } | ||
| 43 | line.clear(); | ||
| 44 | } | ||
| 45 | visited | ||
| 46 | } | ||
diff --git a/2022/README.md b/2022/README.md new file mode 100644 index 0000000..1e134bd --- /dev/null +++ b/2022/README.md | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | # Advent of Code 2022 | ||
| 2 | |||
| 3 | I did not solve these problems in 2022, but in 2025, as a playground | ||
| 4 | to learn Rust. | ||
| 5 | |||
| 6 | ## Usage | ||
| 7 | |||
| 8 | To run this code you'll need the `rustc` compiler (no `cargo`). | ||
| 9 | |||
| 10 | From this folder run: `./run.sh day part`, for example `./run.sh 03 a`. | ||
| 11 | Input is read from standard input; paste your input in the terminal or | ||
| 12 | read it from a file with e.g. `<input.txt`. | ||
diff --git a/2022/run.sh b/2022/run.sh new file mode 100755 index 0000000..56e1177 --- /dev/null +++ b/2022/run.sh | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | usage() { | ||
| 4 | echo "Usage: $0 day part" | ||
| 5 | echo "Example: $0 07 b" | ||
| 6 | } | ||
| 7 | |||
| 8 | [ -n "$1" ] && [ -n "$2" ] || (usage; exit 1) | ||
| 9 | [ -d "$1" ] || (echo "Directory $1 does not exist"; exit 1) | ||
| 10 | [ -f "$1/$2.rs" ] || (echo "File $1/$2.rs does not exist"; exit 2) | ||
| 11 | |||
| 12 | rustc "$1/$2.rs" -o "$1/$2.out" && time "./$1/$2.out" | ||
