New account since lemmyrs.org went down, other @Deebsters are available.

  • 1 Post
  • 229 Comments
Joined 2 years ago
cake
Cake day: October 16th, 2023

help-circle








  • Rust

    Not too hard today, apart from yesterday’s visit to a cocktail bar leaving me a little hazy in the mind.

    code
    use std::{fs, str::FromStr};
    
    use color_eyre::eyre::{Report, Result};
    use gxhash::{HashMap, HashMapExt};
    
    const SECRETS_PER_DAY: usize = 2000;
    const SEQ_LEN: usize = 4;
    
    type Sequence = [i8; SEQ_LEN];
    
    fn produce(n: usize) -> usize {
        let n = (n ^ (n * 64)) % 16777216;
        let n = (n ^ (n / 32)) % 16777216;
        (n ^ (n * 2048)) % 16777216
    }
    
    #[derive(Debug)]
    struct Buyer {
        prices: [u8; SECRETS_PER_DAY + 1],
        changes: [i8; SECRETS_PER_DAY],
    }
    
    impl Buyer {
        fn price_at_seq(&self, seq: &Sequence) -> Option<u8> {
            self.changes
                .windows(SEQ_LEN)
                .position(|win| win == *seq)
                .and_then(|i| self.price_for_window(i))
        }
    
        fn price_for_window(&self, i: usize) -> Option<u8> {
            self.prices.get(i + SEQ_LEN).copied()
        }
    }
    
    struct BananaMarket {
        buyers: Vec<Buyer>,
    }
    
    impl FromStr for BananaMarket {
        type Err = Report;
    
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            let buyer_seeds = s
                .lines()
                .map(|s| s.parse::<usize>())
                .collect::<Result<Vec<_>, _>>()?;
    
            let buyers = buyer_seeds
                .into_iter()
                .map(|seed| {
                    let mut prices = [0; SECRETS_PER_DAY + 1];
                    let mut changes = [0; SECRETS_PER_DAY];
    
                    let mut secret = seed;
                    let mut price = (seed % 10) as u8;
                    prices[0] = price;
                    for i in 0..SECRETS_PER_DAY {
                        let last_price = price;
                        secret = produce(secret);
                        price = (secret % 10) as u8;
                        prices[i + 1] = price;
                        changes[i] = price as i8 - last_price as i8;
                    }
                    Buyer { prices, changes }
                })
                .collect();
            Ok(Self { buyers })
        }
    }
    
    impl BananaMarket {
        fn sell_with_seq(&self, seq: &Sequence) -> usize {
            self.buyers
                .iter()
                .map(|b| b.price_at_seq(seq).unwrap_or(0) as usize)
                .sum()
        }
    
        fn maximise_bananas(&self) -> usize {
            let mut cache: HashMap<Sequence, usize> = HashMap::new();
    
            for seq in self
                .buyers
                .iter()
                .flat_map(|buyer| buyer.changes.windows(SEQ_LEN))
            {
                let seq = seq.try_into().unwrap();
                cache.entry(seq).or_insert_with(|| self.sell_with_seq(&seq));
            }
    
            cache.into_values().max().unwrap_or(0)
        }
    }
    
    fn part1(filepath: &str) -> Result<usize> {
        let input = fs::read_to_string(filepath)?
            .lines()
            .map(|s| s.parse::<usize>())
            .collect::<Result<Vec<_>, _>>()?;
        let res = input
            .into_iter()
            .map(|n| (0..SECRETS_PER_DAY).fold(n, |acc, _| produce(acc)))
            .sum();
        Ok(res)
    }
    
    fn part2(filepath: &str) -> Result<usize> {
        let input = fs::read_to_string(filepath)?;
        let market = BananaMarket::from_str(&input)?;
        Ok(market.maximise_bananas())
    }
    
    fn main() -> Result<()> {
        color_eyre::install()?;
    
        println!("Part 1: {}", part1("d22/input.txt")?);
        println!("Part 2: {}", part2("d22/input.txt")?);
        Ok(())
    }
    








  • Haha, thanks but we both know they’re #1 by a country mile. I think my phone’s now downclocking as it’s burning up and still hasn’t spat out an answer after two hours, so I technically haven’t completed it yet!

    Edit: Calling it for now, I might figure out later why it’s so slow (there’s some easy but minor gains to be made but I’m guessing there’s some O(awful) going on that the input’s blown up)


  • Nushell

    As I’m still on holiday and normal languages are a PITA to type on a phone, I though I’d try a compiled scripting language. I’m not very familiar with it so it took longer to code and also it’s been running the first reduce step for 35 minutes so I’ve missed the 24h cutoff 😔

    use std repeat
    use std/iter
    
    let memory = open input.txt | str trim 
      | split chars | chunks 2
      | enumerate | each {|pair| [
        ...($pair.index | repeat ($pair.item.0 | into int))
        ...("." | repeat (if ($pair.item|length) < 2 {0} else {$pair.item.1 | into int}))
      ]}
      | flatten
    
    let defragged = (($memory | length) - 1)..(($memory | filter {$in != .} | length))
     | reduce --fold $memory {|i, acc| 
        let space = $acc | iter find-index {|$i| $i == .}
        $acc | update $space ($acc | get $i)
          | update $i .
      }
    
    $defragged | enumerate
      | reduce --fold 0 {|i,acc| $acc + ($i.index * if $i.item == "." {0} else {$i.item | into int})}