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"
|
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"
|
||||||
|
|
|
@ -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" }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
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]
|
#[inline]
|
||||||
fn parse(b: &[u8]) -> u64 {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
}
|
||||||
|
|
||||||
|
#[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;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{:?}", count);
|
out
|
||||||
total
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user