mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Avoid allocations when parsing strings by line
This commit is contained in:
@@ -5,6 +5,7 @@ use std::io::BufRead;
|
|||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// Read input line by line and try to parse it into some collection.
|
/// Read input line by line and try to parse it into some collection.
|
||||||
@@ -14,11 +15,8 @@ where
|
|||||||
E: Debug,
|
E: Debug,
|
||||||
T: FromIterator<I>,
|
T: FromIterator<I>,
|
||||||
{
|
{
|
||||||
let reader = BufReader::new(input);
|
Lines::new(input)
|
||||||
|
.map(|line| line.parse::<I>().unwrap())
|
||||||
reader
|
|
||||||
.lines()
|
|
||||||
.map(|line| line.unwrap().parse::<I>().unwrap())
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +69,56 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterator that allows for mostly alloc-less &str iteration
|
||||||
|
///
|
||||||
|
/// If an owned String is needed, use `BufRead::lines()` as this version is
|
||||||
|
/// optimized for temporary references.
|
||||||
|
pub struct Lines<T>
|
||||||
|
where
|
||||||
|
T: Read,
|
||||||
|
{
|
||||||
|
reader: BufReader<T>,
|
||||||
|
buffer: Rc<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Lines<T>
|
||||||
|
where
|
||||||
|
T: Read,
|
||||||
|
{
|
||||||
|
pub fn new(input: T) -> Self {
|
||||||
|
Self {
|
||||||
|
reader: BufReader::new(input),
|
||||||
|
buffer: Rc::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Iterator for Lines<T>
|
||||||
|
where
|
||||||
|
T: Read,
|
||||||
|
{
|
||||||
|
type Item = Rc<String>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
// Assuming the consumer has released the previous reference to the
|
||||||
|
// string, this should not make a copy
|
||||||
|
let buffer = Rc::make_mut(&mut self.buffer);
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
|
if let Ok(read) = self.reader.read_line(buffer) {
|
||||||
|
if read > 0 {
|
||||||
|
if buffer.ends_with('\n') {
|
||||||
|
buffer.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(Rc::clone(&self.buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
use std::io::BufRead;
|
|
||||||
use std::io::BufReader;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
use crate::common::Lines;
|
||||||
use crate::Solution;
|
use crate::Solution;
|
||||||
|
|
||||||
fn matches1(min: usize, max: usize, c: char, sample: &str) -> bool {
|
fn matches1(min: usize, max: usize, c: char, sample: &str) -> bool {
|
||||||
@@ -25,17 +24,10 @@ where
|
|||||||
{
|
{
|
||||||
let parser = Regex::new(r"^(\d+)-(\d+) ([a-z]): ([a-z]+)$").unwrap();
|
let parser = Regex::new(r"^(\d+)-(\d+) ([a-z]): ([a-z]+)$").unwrap();
|
||||||
|
|
||||||
let mut reader = BufReader::new(input);
|
|
||||||
let mut buffer = String::new();
|
|
||||||
|
|
||||||
let mut matching = 0;
|
let mut matching = 0;
|
||||||
|
|
||||||
while let Ok(read) = reader.read_line(&mut buffer) {
|
for line in Lines::new(input) {
|
||||||
if read == 0 {
|
let cap = parser.captures(&line).unwrap();
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cap = parser.captures(buffer.trim()).unwrap();
|
|
||||||
|
|
||||||
let first = cap[1].parse().unwrap();
|
let first = cap[1].parse().unwrap();
|
||||||
let second = cap[2].parse().unwrap();
|
let second = cap[2].parse().unwrap();
|
||||||
@@ -45,8 +37,6 @@ where
|
|||||||
if matcher(first, second, c, sample) {
|
if matcher(first, second, c, sample) {
|
||||||
matching += 1
|
matching += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.clear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matching
|
matching
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::io::BufRead;
|
|
||||||
use std::io::BufReader;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
use crate::common::Lines;
|
||||||
use crate::Solution;
|
use crate::Solution;
|
||||||
|
|
||||||
fn seat_id(boarding_pass: &str) -> u32 {
|
fn seat_id(boarding_pass: &str) -> u32 {
|
||||||
@@ -11,7 +10,7 @@ fn seat_id(boarding_pass: &str) -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn seat_iter<'a>(input: &'a mut dyn Read) -> impl Iterator<Item = u32> + 'a {
|
fn seat_iter<'a>(input: &'a mut dyn Read) -> impl Iterator<Item = u32> + 'a {
|
||||||
BufReader::new(input).lines().map(|s| seat_id(&s.unwrap()))
|
Lines::new(input).map(|s| seat_id(&s))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|||||||
Reference in New Issue
Block a user