day4: optimized
This commit is contained in:
parent
5ffe28fab3
commit
780171280f
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -12,7 +12,6 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
|||
name = "aoc2023"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"ureq",
|
||||
]
|
||||
|
||||
|
@ -22,12 +21,6 @@ version = "0.21.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
|
@ -71,15 +64,6 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.11"
|
||||
|
|
|
@ -17,7 +17,6 @@ codegen-units = 16
|
|||
rpath = false
|
||||
|
||||
[dependencies]
|
||||
fxhash = "0.2.1"
|
||||
ureq = { version = "2.9.1" }
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#![feature(slice_split_once)]
|
||||
#![feature(test)]
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&[u8]; 2] = [
|
||||
|
@ -11,9 +8,8 @@ const INPUTS: [&[u8]; 2] = [
|
|||
];
|
||||
|
||||
fn process(data: &[u8]) -> u64 {
|
||||
let mut win_num = FxHashSet::default();
|
||||
|
||||
let mut total = 0;
|
||||
|
||||
for data in data.split(|&x| x == b'\n') {
|
||||
if data.is_empty() {
|
||||
continue;
|
||||
|
@ -22,25 +18,26 @@ fn process(data: &[u8]) -> u64 {
|
|||
let (_, nums) = data.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() {
|
||||
continue;
|
||||
}
|
||||
let win = parse(win);
|
||||
|
||||
win_num.insert(win);
|
||||
bit_map.set(win);
|
||||
}
|
||||
|
||||
let mut val = 0;
|
||||
for num in nums {
|
||||
for num in nums.split(|&x| x == b' ') {
|
||||
if num.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let num = parse(num);
|
||||
if win_num.contains(&num) {
|
||||
|
||||
if bit_map.get(num) {
|
||||
if val == 0 {
|
||||
val = 1;
|
||||
} else {
|
||||
|
@ -50,20 +47,36 @@ fn process(data: &[u8]) -> u64 {
|
|||
}
|
||||
|
||||
total += val;
|
||||
|
||||
win_num.clear();
|
||||
}
|
||||
|
||||
total
|
||||
}
|
||||
|
||||
struct BitMap(u128);
|
||||
impl BitMap {
|
||||
#[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 pow = 1;
|
||||
for c in b.iter().rev() {
|
||||
out += (c - b'0') as u64 * pow;
|
||||
out += (c - b'0') as usize * pow;
|
||||
pow *= 10;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,73 +1,105 @@
|
|||
#![feature(test)]
|
||||
#![feature(slice_split_once)]
|
||||
|
||||
use std::collections::HashSet;
|
||||
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 total = 0;
|
||||
for data in data.lines() {
|
||||
let (x, nums) = data.split_once(':').unwrap();
|
||||
for data in data.split(|&x| x == b'\n') {
|
||||
if data.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let (x, nums) = data.split_once(|&x| x == b':').unwrap();
|
||||
|
||||
let v = x.split_at(4).1.trim();
|
||||
let id = v.parse::<usize>().unwrap();
|
||||
let id = parse(&x[5..]);
|
||||
|
||||
let (nums, wins) = nums.split_once('|').unwrap();
|
||||
let nums: Vec<&str> = nums.split(' ').collect();
|
||||
let wins: Vec<&str> = wins.split(' ').collect();
|
||||
let (nums, wins) = nums.split_once(|&x| x == b'|').unwrap();
|
||||
let nums = nums.split(|&x| x == b' ');
|
||||
let wins = wins.split(|&x| x == b' ');
|
||||
|
||||
let mut card = vec![];
|
||||
let mut win = HashSet::new();
|
||||
let mut card = BitMap::new();
|
||||
let mut win = BitMap::new();
|
||||
|
||||
for num in nums {
|
||||
if num.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let num = num.parse::<u64>().unwrap();
|
||||
let num = parse(num);
|
||||
|
||||
card.push(num);
|
||||
card.set(num);
|
||||
}
|
||||
|
||||
for w in wins {
|
||||
if w.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let num = w.parse::<u64>().unwrap();
|
||||
win.insert(num);
|
||||
let num = parse(w);
|
||||
win.set(num);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
while let Some((id, card, wins)) = stack.pop() {
|
||||
for (id, card, wins) in cards.into_iter() {
|
||||
let mut sum = 0;
|
||||
for c in card {
|
||||
if wins.contains(&c) {
|
||||
for c in 0..100 {
|
||||
if card.get(c) && wins.get(c) {
|
||||
sum += 1;
|
||||
}
|
||||
}
|
||||
|
||||
count[id] += 1;
|
||||
|
||||
for i in id..id + sum {
|
||||
stack.push(cards[i].clone())
|
||||
let cid = counter[id];
|
||||
for c in counter.iter_mut().skip(id + 1).take(sum) {
|
||||
*c += cid;
|
||||
}
|
||||
}
|
||||
|
||||
for c in count.iter().skip(1) {
|
||||
total += c;
|
||||
counter.into_iter().sum::<usize>()
|
||||
}
|
||||
|
||||
println!("{:?}", count);
|
||||
total
|
||||
#[derive(Clone)]
|
||||
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() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user