day3: tested version with range lookups

This commit is contained in:
Ishan Jain 2023-12-03 13:08:40 +05:30
parent a9788018c6
commit 2520d9b3d5
Signed by: ishan
GPG Key ID: 0506DB2A1CC75C27

View File

@ -1,6 +1,6 @@
#![feature(test)] #![feature(test)]
use std::ops::RangeBounds; use std::{collections::HashSet, ops::RangeInclusive};
extern crate test; extern crate test;
const INPUTS: [&[u8]; 2] = [ const INPUTS: [&[u8]; 2] = [
@ -20,8 +20,6 @@ const DIRS: [(i32, i32); 8] = [
]; ];
fn process(data: &[u8]) -> u64 { fn process(data: &[u8]) -> u64 {
let mut total = 0;
let grid: Vec<&[u8]> = data let grid: Vec<&[u8]> = data
.split(|&x| x == b'\n') .split(|&x| x == b'\n')
.filter(|x| !x.is_empty()) .filter(|x| !x.is_empty())
@ -30,51 +28,161 @@ fn process(data: &[u8]) -> u64 {
let m = grid.len(); let m = grid.len();
let n = grid[0].len(); let n = grid[0].len();
for i in 0..m { let mut ranges = Vec::with_capacity(m);
let mut j = 0;
while j < n {
if !(b'1'..=b'9').contains(&grid[i][j]) {
j += 1;
continue;
}
let mut ey = j; for row in grid.iter() {
while ey < n && grid[i][ey].is_ascii_digit() { let mut range = vec![];
let mut sy = 0;
let mut ey = 0;
let mut counting = false;
for j in 0..n {
let c = row[j];
if c.is_ascii_digit() {
if !counting {
sy = j;
ey = j;
counting = true;
} else {
ey += 1; ey += 1;
} }
} else {
if counting {
range.push(sy..=ey);
}
counting = false;
sy = 0;
ey = 0;
}
}
let mut valid = false; if counting {
range.push(sy..=ey);
}
'outer: for (a, b) in DIRS.iter() { ranges.push(range);
let x = i as i32 + a; }
for p in j..ey { let mut set = HashSet::with_capacity(200);
let y = p as i32 + b;
if x < 0 || y < 0 || x >= m as i32 || y >= n as i32 { for i in 0..m {
for j in 0..n {
if grid[i][j] == b'.' || grid[i][j].is_ascii_digit() {
continue;
}
for (p, q) in DIRS.iter() {
let x = i as i32 + p;
let y = j as i32 + q;
if x < 0 || y < 0 || x > m as i32 || y > n as i32 {
continue; continue;
} }
let c = grid[x as usize][y as usize]; let x = x as usize;
if c != b'.' && !c.is_ascii_digit() { let y = y as usize;
valid = true;
break 'outer; if let Some(range) = find(y, &ranges[x]) {
set.insert((x, range));
}
} }
} }
} }
if valid { set.into_iter()
let num = String::from_utf8_lossy(&grid[i][j..ey]) .map(|(x, range)| {
String::from_utf8_lossy(&grid[x][range.clone()])
.parse::<u64>() .parse::<u64>()
.unwrap(); .unwrap()
total += num })
.sum::<u64>()
// let mut total = 0;
// let mut v2 = Vec::new();
//
// for i in 0..m {
// let mut j = 0;
// while j < n {
// if !(b'1'..=b'9').contains(&grid[i][j]) {
// j += 1;
// continue;
// }
//
// let mut ey = j;
// while ey < n && grid[i][ey].is_ascii_digit() {
// ey += 1;
// }
//
// let mut valid = false;
//
// 'outer: for (a, b) in DIRS.iter() {
// let x = i as i32 + a;
//
// for p in j..ey {
// let y = p as i32 + b;
//
// if x < 0 || y < 0 || x >= m as i32 || y >= n as i32 {
// continue;
// }
//
// let c = grid[x as usize][y as usize];
// if c != b'.' && !c.is_ascii_digit() {
// valid = true;
// break 'outer;
// }
// }
// }
//
// if valid {
// let num = String::from_utf8_lossy(&grid[i][j..ey])
// .parse::<u64>()
// .unwrap();
// v2.push(num);
// total += num
// }
//
// j += ey - j;
// }
// }
//
// for i in 0..v1.len() {
// if let Some(x) = v2.iter().position(|a| a == &v1[i]) {
// v2.remove(x);
// }
// v1[i] = 0;
// }
// for v in &v2 {
// if let Some(x) = v1.iter().position(|a| a == v) {
// v1.remove(x);
// }
// }
//
// println!("{:?} {:?}", v1, v2);
// total
} }
j += ey - j; fn find(v: usize, r: &[RangeInclusive<usize>]) -> Option<&RangeInclusive<usize>> {
let mut start = 0;
let mut end = r.len();
while start < end {
let mid = start + (end - start) / 2;
let mid_v = &r[mid];
if mid_v.contains(&v) {
return Some(mid_v);
}
if mid_v.start() > &v {
end = mid;
}
if mid_v.end() < &v {
start = mid + 1;
} }
} }
total None
} }
fn main() { fn main() {