better rust

This commit is contained in:
Rüdiger Ludwig 2023-10-30 16:11:33 +01:00
parent 41b013b5e9
commit d5b6cb72cb
21 changed files with 61 additions and 112 deletions

View file

@ -6,10 +6,10 @@ fn format_path(day_num: usize, file: &str) -> String {
}
pub fn read_string(day_num: usize, file: &str) -> io::Result<String> {
Ok(fs::read_to_string(format_path(day_num, file))?)
fs::read_to_string(format_path(day_num, file))
}
pub fn split_lines<'a>(lines: &'a str) -> impl Iterator<Item = &'a str> + 'a {
pub fn split_lines(lines: &str) -> impl Iterator<Item = &'_ str> + '_ {
lines
.split('\n')
.with_position()

View file

@ -14,7 +14,7 @@ pub const NEG_Z: UnitVector = UnitVector(Pos3::new(0, 0, -1));
impl UnitVector {
pub fn new(vector: Pos3<i8>) -> Option<Self> {
vector.is_unit().then(|| UnitVector(vector))
vector.is_unit().then_some(UnitVector(vector))
}
pub fn x(self) -> i8 {

View file

@ -14,7 +14,7 @@ impl DayTrait for Day {
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
let sum = split_lines(lines)
.map(|line| Rps::parse_line(line))
.map(Rps::parse_line)
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.map(|(first, second)| second.asses_pair(&first))
@ -25,7 +25,7 @@ impl DayTrait for Day {
fn part2(&self, lines: &str) -> anyhow::Result<ResultType> {
let sum = split_lines(lines)
.map(|line| Strategy::parse_line(line))
.map(Strategy::parse_line)
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.map(|(first, second)| second.fullfill(&first).asses_pair(&first))

View file

@ -14,7 +14,7 @@ impl DayTrait for Day {
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
let sum = split_lines(lines)
.map(|line| find_double(line))
.map(find_double)
.map_ok(priority)
.flatten_ok()
.fold_ok(0, |a, b| a + b)?;

View file

@ -15,7 +15,7 @@ impl DayTrait for Day {
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
let sum = split_lines(lines)
.map(|line| parse(line))
.map(parse)
.filter_ok(fully_contained)
.fold_ok(0i64, |a, _| a + 1)?;
Ok(ResultType::Integer(sum))
@ -23,7 +23,7 @@ impl DayTrait for Day {
fn part2(&self, lines: &str) -> anyhow::Result<ResultType> {
let sum = split_lines(lines)
.map(|line| parse(line))
.map(parse)
.filter_ok(overlaps)
.fold_ok(0i64, |a, _| a + 1)?;
Ok(ResultType::Integer(sum))

View file

@ -59,12 +59,10 @@ fn parse_crate(line: &str) -> Vec<Option<char>> {
.collect()
}
fn parse_all_crates<'a>(
line_it: &mut dyn Iterator<Item = &'a str>,
) -> Result<Vec<String>, CrateError> {
fn parse_all_crates(line_it: &mut dyn Iterator<Item = &str>) -> Result<Vec<String>, CrateError> {
let rows = line_it
.take_while(|line| !line.is_empty())
.map(|row| parse_crate(row))
.map(parse_crate)
.collect_vec();
let Some(stacks_count) = rows.iter().map(|row| row.len()).max() else {
return Err(CrateError::NoCargoStacksGiven);
@ -83,12 +81,10 @@ fn parse_all_crates<'a>(
Ok(stacks)
}
fn parse<'a>(lines: &'a str) -> Result<(Vec<String>, Vec<Move>), CrateError> {
fn parse(lines: &str) -> Result<(Vec<String>, Vec<Move>), CrateError> {
let mut iter = split_lines(lines);
let stacks = parse_all_crates(&mut iter)?;
let moves: Vec<_> = iter
.map(|command| Move::try_from(command))
.collect::<Result<_, _>>()?;
let moves: Vec<_> = iter.map(Move::try_from).collect::<Result<_, _>>()?;
Ok((stacks, moves))
}
@ -194,7 +190,7 @@ mod test {
#[test]
fn test_parse_all_crates() -> Result<()> {
let lines = vec![
let lines = [
" [D] ",
"[N] [C] ",
"[Z] [M] [P]",

View file

@ -44,7 +44,7 @@ fn find_marker(word: &str, marker_length: usize) -> Result<usize, MarkerError> {
if word.len() < marker_length {
return Err(MarkerError::StringTooShort(word.to_owned(), marker_length));
}
let mut letter_count = vec![0; 26];
let mut letter_count = [0; 26];
let mut doubles = 0;
for new in word.chars().take(marker_length) {
let new = char_pos(new);

View file

@ -92,13 +92,13 @@ impl Rope {
* returns true if the whole rope moved, otherwise false
*/
pub fn move_rope(&mut self, head_direction: Direction) -> bool {
self.head = self.head + head_direction;
self.head += head_direction;
let mut prev = self.head;
let mut knots_unmoved = self.knots.len();
for knot in self.knots.iter_mut() {
if let Some(diff) = get_closer(*knot, prev) {
*knot = *knot + diff;
*knot += diff;
prev = *knot;
knots_unmoved -= 1;
} else {

View file

@ -59,8 +59,8 @@ impl Operation {
let (input, _) = tag("new = old ")(input)?;
alt((
value(Operation::Squared, tag("* old")),
preceded(char('*'), trim0(i64.map(|a| Operation::Times(a)))),
preceded(char('+'), trim0(i64.map(|a| Operation::Plus(a)))),
preceded(char('*'), trim0(i64.map(Operation::Times))),
preceded(char('+'), trim0(i64.map(Operation::Plus))),
))(input)
}

View file

@ -48,19 +48,7 @@ struct Path {
impl PartialOrd for Path {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match other.length.partial_cmp(&self.length) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match other.height.partial_cmp(&self.height) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.pos.x().partial_cmp(&other.pos.x()) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
self.pos.y().partial_cmp(&other.pos.y())
Some(self.cmp(other))
}
}

View file

@ -147,7 +147,7 @@ impl Packets {
pub fn parse_all(lines: &str) -> Result<Vec<Packets>, PacketError> {
split_lines(lines)
.filter(|line| !line.is_empty())
.map(|line| Packets::parse(line))
.map(Packets::parse)
.collect::<Result<Vec<_>, _>>()
}
}

View file

@ -874,7 +874,7 @@ impl<AG: ActorGroup> Ord for WeightedState<AG> {
impl<AG: ActorGroup> Deref for WeightedState<AG> {
type Target = ValveState<AG>;
fn deref<'b>(&'b self) -> &'b Self::Target {
fn deref(&self) -> &Self::Target {
&self.0
}
}
@ -1029,7 +1029,7 @@ mod test {
result.closed,
vec![Index(1), Index(2), Index(3), Index(7), Index(9)]
);
assert_eq!(result.potential, Flow(20 * 1));
assert_eq!(result.potential, Flow(20));
Ok(())
}
@ -1091,8 +1091,8 @@ mod test {
assert_eq!(next.len(), 15);
let result = &next[4];
assert_eq!(result.flow, Flow(13 * 3));
assert_eq!(result.potential, Flow(21 * 2 + 2 * 1));
assert_eq!(result.flow_potential(), Flow(13 * 3 + 21 * 2 + 2 * 1));
assert_eq!(result.potential, Flow(21 * 2 + 2));
assert_eq!(result.flow_potential(), Flow(13 * 3 + 21 * 2 + 2));
assert_eq!(
result.closed,
vec![Index(2), Index(3), Index(4), Index(7), Index(9)]

View file

@ -15,31 +15,19 @@ impl DayTrait for Day {
}
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
let pushes = Dispenser::new(
lines
.trim_end()
.chars()
.map(|c| Push::parse(c))
.try_collect()?,
)?;
let pushes = Dispenser::new(lines.trim_end().chars().map(Push::parse).try_collect()?)?;
let result = Day::run(pushes, 2022)?;
Ok(ResultType::Integer(result as i64))
Ok(ResultType::Integer(result))
}
fn part2(&self, lines: &str) -> anyhow::Result<ResultType> {
let pushes = Dispenser::new(
lines
.trim_end()
.chars()
.map(|c| Push::parse(c))
.try_collect()?,
)?;
let pushes = Dispenser::new(lines.trim_end().chars().map(Push::parse).try_collect()?)?;
let result = Day::run(pushes, 1000000000000)?;
Ok(ResultType::Integer(result as i64))
Ok(ResultType::Integer(result))
}
}
@ -156,12 +144,11 @@ impl Rock {
let positions = blocks
.iter()
.enumerate()
.map(|(y, line)| {
.flat_map(|(y, line)| {
line.iter()
.enumerate()
.filter_map(move |(x, block)| block.then_some((x, height - 1 - y)))
})
.flatten()
.collect_vec();
Ok(Rock {
@ -299,8 +286,8 @@ impl Stack {
let mut rock = FallingRock::new(rock, self.height());
loop {
let push = push_cycle.next();
rock = rock.try_push(push, &self);
match rock.try_drop(&self) {
rock = rock.try_push(push, self);
match rock.try_drop(self) {
Ok(next_rock) => rock = next_rock,
Err(rock) => {
let bottom = rock.bottom;
@ -413,13 +400,7 @@ mod test {
fn drop_one() -> Result<()> {
let day = Day {};
let lines = read_string(day.get_day_number(), "example01.txt")?;
let pushes = Dispenser::new(
lines
.trim_end()
.chars()
.map(|c| Push::parse(c))
.try_collect()?,
)?;
let pushes = Dispenser::new(lines.trim_end().chars().map(Push::parse).try_collect()?)?;
let raw = read_string(day.get_day_number(), "blocks.txt")?;
let rocks = Dispenser::new(Rock::parse(&raw)?)?;
@ -435,13 +416,7 @@ mod test {
fn drop_some() -> Result<()> {
let day = Day {};
let lines = read_string(day.get_day_number(), "example01.txt")?;
let pushes = Dispenser::new(
lines
.trim_end()
.chars()
.map(|c| Push::parse(c))
.try_collect()?,
)?;
let pushes = Dispenser::new(lines.trim_end().chars().map(Push::parse).try_collect()?)?;
let result = Day::run(pushes, 10)?;

View file

@ -38,7 +38,7 @@ struct Droplet(i64, i64, i64);
impl Droplet {
fn parse(line: &str) -> Result<Droplet, DropletError> {
let split = line.split(",").collect_vec();
let split = line.split(',').collect_vec();
if split.len() != 3 {
return Err(DropletError::IllegalDroplet(line.to_owned()));
}
@ -135,9 +135,7 @@ impl TryFrom<&str> for Blob {
type Error = DropletError;
fn try_from(lines: &str) -> Result<Self, Self::Error> {
let droplets = split_lines(lines)
.map(|line| Droplet::parse(line))
.try_collect()?;
let droplets = split_lines(lines).map(Droplet::parse).try_collect()?;
Ok(Blob { droplets })
}
}
@ -148,7 +146,7 @@ impl Blob {
return None;
}
let mut range = Ranges::new(&self.droplets.iter().next().unwrap());
let mut range = Ranges::new(self.droplets.iter().next().unwrap());
for droplet in self.droplets.iter().skip(1) {
range.extend(droplet);
}

View file

@ -114,7 +114,7 @@ impl Ingredients {
}
fn inc(&self, mat: Material) -> Ingredients {
let mut next = self.0.clone();
let mut next = self.0;
next[mat as usize] += 1;
Ingredients(next)
}
@ -351,7 +351,7 @@ impl Cabinet {
let _ = sender.send(result);
});
done = done + 1;
done += 1;
if done >= count {
break;
}
@ -404,7 +404,7 @@ impl Simulation {
}
pub fn no_production(mut self) -> Self {
self.time = self.time - 1;
self.time -= 1;
self.material = self.material + &self.robots;
self
}

View file

@ -84,7 +84,7 @@ impl Ring {
self.items
.iter()
.position(|v| *v == value)
.ok_or_else(|| RingError::ItemNotFound(value))
.ok_or(RingError::ItemNotFound(value))
}
fn next_pos(&self, pos: usize) -> usize {
@ -145,9 +145,7 @@ impl Ring {
}
fn multiply(&mut self, arg: i64) {
self.items
.iter_mut()
.for_each(|value| *value = *value * arg);
self.items.iter_mut().for_each(|value| *value *= arg);
}
}

View file

@ -16,8 +16,8 @@ use thiserror::Error;
const DAY_NUMBER: usize = 21;
const ROOT: &'static str = "root";
const HUMAN: &'static str = "humn";
const ROOT: &str = "root";
const HUMAN: &str = "humn";
pub struct Day;
impl DayTrait for Day {
@ -91,11 +91,7 @@ impl MonkeyJob {
}
fn parse(input: &str) -> IResult<&str, MonkeyJob> {
trim0(alt((
i64.map(|val| MonkeyJob::Yell(val)),
MonkeyJob::parse_operation,
)))
.parse(input)
trim0(alt((i64.map(MonkeyJob::Yell), MonkeyJob::parse_operation))).parse(input)
}
fn perform(&self, troop: &Troop) -> Result<i64, MonkeyError> {

View file

@ -98,7 +98,7 @@ impl WorldMap {
value(None, char(' ')),
));
let line = eol_terminated(many1(tile));
let mut lines = many1(line).map(|tiles| WorldMap::new(tiles));
let mut lines = many1(line).map(WorldMap::new);
lines.parse(input)
}
@ -147,7 +147,7 @@ enum Instruction {
impl Instruction {
fn parse(input: &str) -> IResult<&str, Vec<Instruction>> {
many1(alt((
usize.map(|v| Instruction::Walk(v)),
usize.map(Instruction::Walk),
value(Instruction::Right, char('R')),
value(Instruction::Left, char('L')),
)))
@ -342,7 +342,7 @@ struct CubeWalker {
impl CubeWalker {
fn get_side_length(world: &WorldMap) -> Result<usize, WorldError> {
let width = world.width().ok_or_else(|| WorldError::NotAValidCube)?;
let width = world.width().ok_or(WorldError::NotAValidCube)?;
let height = world.height();
if width % 3 == 0 && height % 4 == 0 && width / 3 == height / 4 {
Ok(height / 4)

View file

@ -1,7 +1,10 @@
use super::template::{DayTrait, ResultType};
use crate::common::{area::Area, direction::Direction, pos2::Pos2};
use itertools::Itertools;
use std::{collections::HashMap, str::FromStr};
use std::{
collections::{hash_map::Entry, HashMap},
str::FromStr,
};
use thiserror::Error;
const DAY_NUMBER: usize = 23;
@ -143,14 +146,13 @@ impl FromStr for Field {
let elves: HashMap<Pos2<i32>, bool> = lines
.split('\n')
.enumerate()
.map(|(y, row)| {
.flat_map(|(y, row)| {
row.chars().enumerate().filter_map(move |(x, c)| match c {
'.' => None,
'#' => Some(Ok((Pos2::new(x as i32, y as i32), true))),
_ => Some(Err(FieldError::UnknownChar(c))),
})
})
.flatten()
.try_collect()?;
Ok(Field {
@ -198,10 +200,10 @@ impl Field {
{
match self.check(elf, self.direction.iter()) {
MoveCheck::MoveTo(proposal, direction) => {
if proposals.contains_key(&proposal) {
proposals.remove(&proposal);
if let Entry::Vacant(e) = proposals.entry(proposal) {
e.insert((elf, direction));
} else {
proposals.insert(proposal, (elf, direction));
proposals.remove(&proposal);
}
}
MoveCheck::NoNeighbors => {
@ -214,7 +216,7 @@ impl Field {
return false;
}
self.elves.extend(deactivate.into_iter());
self.elves.extend(deactivate);
for (to, (from, direction)) in proposals {
self.elves.remove(&from);
@ -328,7 +330,7 @@ mod test {
Pos2::new(2, 5)
);
let field: Field = lines.parse()?;
let elves = HashSet::from_iter(field.rounds(2).into_iter());
let elves = HashSet::from_iter(field.rounds(2));
assert_eq!(elves, expected);
Ok(())

View file

@ -178,7 +178,7 @@ impl Valley {
let raw = input
.iter()
.enumerate()
.map(|(y, row)| {
.flat_map(|(y, row)| {
row.char_indices().filter_map(move |(x, c)| match c {
'#' => {
if x != 0 && x != row.len() - 1 {
@ -195,7 +195,6 @@ impl Valley {
_ => Some(Err(BlizzardError::IllegalChar(c))),
})
})
.flatten()
.collect::<Result<Vec<_>, _>>()?;
Ok(Blizzards::new(raw, width - 2, height))
@ -208,7 +207,7 @@ impl Valley {
let mut queue = vec![start];
let mut next_queue = vec![];
while let Some(current) = queue.pop() {
for next_state in current.next_states(&self) {
for next_state in current.next_states(self) {
if next_state.trip == trips {
return Ok(next_state.time.get());
}
@ -420,10 +419,7 @@ mod test {
assert_eq!(valley.storm.len(), 5);
assert_eq!(valley.get_entry(), Pos2::new(0, 0));
assert_eq!(valley.get_exit(), Pos2::new(4, 6));
assert_eq!(
valley.storm.get(Time(3)).is_accessible(&Pos2::new(3, 2)),
false
);
assert!(!valley.storm.get(Time(3)).is_accessible(&Pos2::new(3, 2)));
Ok(())
}

View file

@ -86,7 +86,7 @@ impl FromStr for Snafu {
"=-012"
.chars()
.position(|d| d == c)
.ok_or_else(|| SnafuError::IllegalChar(c))
.ok_or(SnafuError::IllegalChar(c))
})
.fold_ok(0, |acc, next| acc * 5 + (next as i64 - 2))?,
)