better rust
This commit is contained in:
parent
41b013b5e9
commit
d5b6cb72cb
21 changed files with 61 additions and 112 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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]",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<_>, _>>()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))?,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue