Rust
Finally having some fun with iters. I think part 2 came out nicely once I figured I can rotate the whole input to get numbers that look like ours.
Q: Anyone have any tips how to reason about the intermediate types in a long iter chain? I'm currently placing dummy maps, and on occasion, even printing the values from them when I get too stuck.
the code
use std::fs::File;
use std::io::{BufReader, Lines};
#[allow(dead_code)]
pub fn part1(input: Lines<BufReader<File>>) {
let mut input = input
.map_while(Result::ok)
.map(|line| {
line.split_ascii_whitespace()
.map(|s| s.to_string())
.collect::<Vec<String>>()
})
.collect::<Vec<Vec<String>>>();
let ops = input.pop().unwrap();
let values = input
.iter()
.map(|v| {
v.iter()
.map(|v| v.parse::<i64>().unwrap())
.collect::<Vec<i64>>()
})
.collect::<Vec<Vec<i64>>>();
let transposed: Vec<Vec<i64>> = (0..values[0].len())
.map(|i| values.iter().map(|row| row[i]).collect())
.collect();
let mut sum = 0;
for i in 0..ops.len() {
let op: &str = &ops[i];
match op {
"+" => {
sum += transposed[i].iter().sum::<i64>();
}
"*" => {
sum += transposed[i].iter().product::<i64>();
}
_ => panic!("Invalid operation"),
}
}
println!("sum = {}", sum)
}
#[allow(dead_code)]
pub fn part2(input: Lines<BufReader<File>>) {
let mut input = input
.map_while(Result::ok)
.map(|line| line.chars().collect::<Vec<char>>())
.collect::<Vec<Vec<char>>>();
let ops = input
.pop()
.unwrap()
.iter()
.map(|c| c.to_string())
.filter(|s| s != " ")
.collect::<Vec<String>>();
let transposed: Vec<i64> = (0..input[0].len())
.map(|i| input.iter().map(|row| row[i]).collect())
.map(|vec: String| vec.trim().to_string())
.map(|s| {
if s.len() == 0 {
0
} else {
s.parse::<i64>().unwrap()
}
})
.collect();
let groups = transposed
.into_iter()
.fold(Vec::new(), |mut acc: Vec<Vec<i64>>, num| {
if num == 0 {
if let Some(last) = acc.last_mut() {
if !last.is_empty() {
acc.push(Vec::new());
}
} else {
acc.push(Vec::new());
}
} else {
if acc.is_empty() {
acc.push(Vec::new());
}
acc.last_mut().unwrap().push(num);
}
acc
});
let mut sum = 0;
for i in 0..ops.len() {
let op: &str = &ops[i];
match op {
"+" => {
sum += groups[i].iter().sum::<i64>();
}
"*" => {
sum += groups[i].iter().product::<i64>();
}
_ => panic!("Invalid operation"),
}
}
println!("sum = {}", sum)
}