day4: optimized

This commit is contained in:
Ishan Jain 2023-12-04 13:25:47 +05:30
parent 5ffe28fab3
commit 780171280f
Signed by: ishan
GPG Key ID: 0506DB2A1CC75C27
4 changed files with 91 additions and 63 deletions

16
Cargo.lock generated
View File

@ -12,7 +12,6 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
name = "aoc2023" name = "aoc2023"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fxhash",
"ureq", "ureq",
] ]
@ -22,12 +21,6 @@ version = "0.21.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.83" version = "1.0.83"
@ -71,15 +64,6 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.11" version = "0.2.11"

View File

@ -17,7 +17,6 @@ codegen-units = 16
rpath = false rpath = false
[dependencies] [dependencies]
fxhash = "0.2.1"
ureq = { version = "2.9.1" } ureq = { version = "2.9.1" }

View File

@ -1,8 +1,5 @@
#![feature(slice_split_once)] #![feature(slice_split_once)]
#![feature(test)] #![feature(test)]
use fxhash::FxHashSet;
extern crate test; extern crate test;
const INPUTS: [&[u8]; 2] = [ const INPUTS: [&[u8]; 2] = [
@ -11,9 +8,8 @@ const INPUTS: [&[u8]; 2] = [
]; ];
fn process(data: &[u8]) -> u64 { fn process(data: &[u8]) -> u64 {
let mut win_num = FxHashSet::default();
let mut total = 0; let mut total = 0;
for data in data.split(|&x| x == b'\n') { for data in data.split(|&x| x == b'\n') {
if data.is_empty() { if data.is_empty() {
continue; continue;
@ -22,25 +18,26 @@ fn process(data: &[u8]) -> u64 {
let (_, nums) = data.split_once(|&x| x == b':').unwrap(); let (_, nums) = data.split_once(|&x| x == b':').unwrap();
let (nums, wins) = nums.split_once(|&x| x == b'|').unwrap(); let (nums, wins) = nums.split_once(|&x| x == b'|').unwrap();
let nums = nums.split(|&x| x == b' ');
let wins = wins.split(|&x| x == b' ');
for win in wins { let mut bit_map = BitMap::new();
for win in wins.split(|&x| x == b' ') {
if win.is_empty() { if win.is_empty() {
continue; continue;
} }
let win = parse(win); let win = parse(win);
win_num.insert(win); bit_map.set(win);
} }
let mut val = 0; let mut val = 0;
for num in nums { for num in nums.split(|&x| x == b' ') {
if num.is_empty() { if num.is_empty() {
continue; continue;
} }
let num = parse(num); let num = parse(num);
if win_num.contains(&num) {
if bit_map.get(num) {
if val == 0 { if val == 0 {
val = 1; val = 1;
} else { } else {
@ -50,20 +47,36 @@ fn process(data: &[u8]) -> u64 {
} }
total += val; total += val;
win_num.clear();
} }
total total
} }
struct BitMap(u128);
impl BitMap {
#[inline] #[inline]
fn parse(b: &[u8]) -> u64 { pub const fn new() -> Self {
Self(0)
}
#[inline]
pub fn set(&mut self, idx: usize) {
debug_assert!(idx < 128);
self.0 |= 1 << idx;
}
#[inline]
pub const fn get(&self, idx: usize) -> bool {
debug_assert!(idx < 128);
(self.0 >> idx) & 1 == 1
}
}
#[inline]
fn parse(b: &[u8]) -> usize {
let mut out = 0; let mut out = 0;
let mut pow = 1; let mut pow = 1;
for c in b.iter().rev() { for c in b.iter().rev() {
out += (c - b'0') as u64 * pow; out += (c - b'0') as usize * pow;
pow *= 10; pow *= 10;
} }

View File

@ -1,73 +1,105 @@
#![feature(test)] #![feature(test)]
#![feature(slice_split_once)]
use std::collections::HashSet;
extern crate test; extern crate test;
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; const INPUTS: [&[u8]; 2] = [
include_bytes!("./sample.txt"),
include_bytes!("./input.txt"),
];
fn process(data: &str) -> u64 { fn process(data: &[u8]) -> usize {
let mut cards = vec![]; let mut cards = vec![];
let mut total = 0; for data in data.split(|&x| x == b'\n') {
for data in data.lines() { if data.is_empty() {
let (x, nums) = data.split_once(':').unwrap(); continue;
}
let (x, nums) = data.split_once(|&x| x == b':').unwrap();
let v = x.split_at(4).1.trim(); let id = parse(&x[5..]);
let id = v.parse::<usize>().unwrap();
let (nums, wins) = nums.split_once('|').unwrap(); let (nums, wins) = nums.split_once(|&x| x == b'|').unwrap();
let nums: Vec<&str> = nums.split(' ').collect(); let nums = nums.split(|&x| x == b' ');
let wins: Vec<&str> = wins.split(' ').collect(); let wins = wins.split(|&x| x == b' ');
let mut card = vec![]; let mut card = BitMap::new();
let mut win = HashSet::new(); let mut win = BitMap::new();
for num in nums { for num in nums {
if num.is_empty() { if num.is_empty() {
continue; continue;
} }
let num = num.parse::<u64>().unwrap(); let num = parse(num);
card.push(num); card.set(num);
} }
for w in wins { for w in wins {
if w.is_empty() { if w.is_empty() {
continue; continue;
} }
let num = w.parse::<u64>().unwrap(); let num = parse(w);
win.insert(num); win.set(num);
} }
cards.push((id, card, win)); cards.push((id, card, win));
} }
let mut stack: Vec<(usize, Vec<u64>, HashSet<u64>)> = cards.iter().rev().cloned().collect(); let mut counter = vec![1; cards.len() + 1];
counter[0] = 0;
let mut count = vec![0; cards.len() + 1]; for (id, card, wins) in cards.into_iter() {
while let Some((id, card, wins)) = stack.pop() {
let mut sum = 0; let mut sum = 0;
for c in card { for c in 0..100 {
if wins.contains(&c) { if card.get(c) && wins.get(c) {
sum += 1; sum += 1;
} }
} }
count[id] += 1; let cid = counter[id];
for c in counter.iter_mut().skip(id + 1).take(sum) {
for i in id..id + sum { *c += cid;
stack.push(cards[i].clone())
} }
} }
for c in count.iter().skip(1) { counter.into_iter().sum::<usize>()
total += c;
} }
println!("{:?}", count); #[derive(Clone)]
total struct BitMap(u128);
impl BitMap {
#[inline]
pub const fn new() -> Self {
Self(0)
}
#[inline]
pub fn set(&mut self, idx: usize) {
debug_assert!(idx < 128);
self.0 |= 1 << idx;
}
#[inline]
pub const fn get(&self, idx: usize) -> bool {
debug_assert!(idx < 128);
(self.0 >> idx) & 1 == 1
}
}
#[inline]
fn parse(b: &[u8]) -> usize {
let mut out = 0;
let mut pow = 1;
for c in b.iter().rev() {
if !c.is_ascii_digit() {
continue;
}
out += (c - b'0') as usize * pow;
pow *= 10;
}
out
} }
fn main() { fn main() {