Untitled

 avatar
unknown
rust
a month ago
2.7 kB
45
Indexable
fn solve01(lines: &str) -> (usize, Duration) {
    let now = Instant::now();
    let sum = lines
        .lines()
        .map(|line| {
            let init_prng = PRNG::new(line.parse().unwrap());
            let prng = (0..2000).fold(init_prng, |mut prng, _| {
                prng.next();
                prng
            });
            prng.secret
        })
        .sum();
    (sum, now.elapsed())
}

fn solve02(lines: &str) -> (usize, Duration) {
    let now = Instant::now();
    let mut sequence_sums = FxHashMap::default();
    lines
        .lines()
        .map(|buyer_init| Buyer::new(buyer_init.parse().unwrap()).roi)
        .for_each(|buyer| {
            buyer.iter().for_each(|(&sequence, &value)| {
                sequence_sums
                    .entry(sequence)
                    .and_modify(|e| *e += value)
                    .or_insert(value);
            });
        });
    let ans = *sequence_sums.values().max().unwrap();
    (ans, now.elapsed())
}

#[derive(Debug, Copy, Clone)]
struct PRNG {
    secret: usize,
}

impl PRNG {
    const fn new(secret: usize) -> Self {
        Self { secret }
    }

    const fn mix(&mut self, a: usize) {
        self.secret ^= a;
    }

    const fn prune(&mut self) {
        self.secret %= 16777216;
    }

    const fn next(&mut self) {
        let mut temp = self.secret;
        self.mix(temp * 64);
        self.prune();

        temp = self.secret;
        self.mix(temp / 32);
        self.prune();

        temp = self.secret;
        self.mix(temp * 2048);
        self.prune();
    }
}

#[derive(Debug, Clone)]
struct Buyer {
    prng: PRNG,
    prices: [usize; 4],
    changes: [isize; 4],
    roi: FxHashMap<[isize; 4], usize>,
}

impl Buyer {
    fn new(init: usize) -> Self {
        let mut buyer = Self {
            prng: PRNG::new(init),
            prices: [0; 4],
            changes: [0; 4],
            roi: FxHashMap::default(),
        };
        buyer.prices[0] = buyer.prng.secret % 10;
        buyer.populate();
        buyer
    }

    fn populate(&mut self) {
        for i in 1..2001 {
            self.prng.next();
            self.prices[i % 4] = self.prng.secret % 10;
            let change = self.prices[i % 4] as isize - self.prices[(i - 1) % 4] as isize;
            self.changes[i % 4] = change;
            if i >= 4 {
                let last_seq = [
                    self.changes[(i - 3) % 4],
                    self.changes[(i - 2) % 4],
                    self.changes[(i - 1) % 4],
                    self.changes[i % 4],
                ];
                self.roi.entry(last_seq).or_insert(self.prices[i % 4]);
            }
        }
    }
}
Leave a Comment