DEV Community

Discussion on: Advent of Code 2020 Solution Megathread - Day 23: Crab Cups

Collapse
 
bgaster profile image
Benedict Gaster • Edited

Ok so I'll be the first to emit that while my part one was fine in Haskell it was never going to scale to part 2! I really hate mutable arrays in Haskell, I mean what's the point, and as such I wrote the 2nd part in rust.

Here's Haskell for part 1:

input :: [Int]
input = [2,1,9,7,4,8,3,6,5]

m (x:xs) = let (three, xs') = splitAt 3 xs
               d            = dest' (x-1) xs'
               (ab, aa)     = span (/= d) xs'
           in ab ++ h aa ++ three ++ t aa ++ [x]
    where
        h []     = []
        h (x:_)  = [x]
        t []     = []
        t (x:xs) = xs

dest' 0 xs = maximum xs
dest' c xs | c `elem` xs = c
           | otherwise = dest' (c-1) xs

task1 0 xs = xs
task1 n xs = task1 (n-1) (m xs) 

main = do
    print (task1 100 input)
Enter fullscreen mode Exit fullscreen mode

and here's Rust for part 2:

const N: usize = 1000000;
const M: usize = 10000000;

fn in_holding(x: usize, holding: &[usize;3]) -> bool {
    for i in 0..3 {
        if x == holding[i] {
            return true;
        }
    }
    false
}

fn task2() -> usize {
    let mut v : Vec<usize> = Vec::with_capacity(N);
    for i in 0..N {
        v.push(i+1);
    }

    // build the beginning of our "linked" list with my input: 219748365
    v[0] = 2;
    v[2] = 1;
    v[1] = 9;
    v[9] = 7;
    v[7] = 4; 
    v[4] = 8;
    v[8] = 3;
    v[3] = 6;
    v[6] = 5;
    v[5] = 10;
    v[N - 1] = 0;

    let mut curr = v[0];
    let mut holding: [usize;3] = [0;3];

    for _ in 0..M {
        // "copy" 3 holding
        holding[0] = v[curr];
        holding[1] = v[holding[0]];
        holding[2] = v[holding[1]];

        // find destination
        let mut dest = if curr == 0 { N-1 } else { curr - 1 };
        while in_holding(dest, &holding) {
            dest = dest - 1;
        }

        // update
        let tmp = v[dest];
        v[dest] = holding[0];
        v[curr] = v[holding[2]];
        v[holding[2]] = tmp;

        curr = v[curr];
    }

    v[1] * v[v[1]]
}

fn main() {

    println!("{}", task2());
}
Enter fullscreen mode Exit fullscreen mode