summaryrefslogtreecommitdiff
path: root/2017/src/bin/day_6.rs
blob: be9a515b6f0416144628bf009dd117bd520ad941 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
extern crate advent_of_code_2017;
use advent_of_code_2017::*;

fn main() {
    let args = AdventArgs::init();

    let init_layout = parse_space_separated_ints(&args.input[0]).unwrap();
    
    let mut layouts = vec!(init_layout);
    let mut balances = 0;
    let mut cycle_found = false;
    let mut cycle_size = 0;

    while !cycle_found {
        balances += 1;
        let new_layout = find_next_layout(&layouts);
        
        if let Some(index) = layouts.iter().position(|x| *x == new_layout) {
            cycle_found = true;
            cycle_size = layouts.len() - index;
        };
        
        layouts.push(new_layout);
    }

    if args.part == 1 {
        println!("Did {} rebalances", balances);
    } else {
        println!("Cycle was {} long", cycle_size);
    }
}

fn find_next_layout(layouts: &Vec<Vec<i32>>) -> Vec<i32> {
    let previous_layout = layouts.last().unwrap();
    rebalance(&previous_layout)
}

fn rebalance(layout: &Vec<i32>) -> Vec<i32> {
    let biggest_container = layout.iter()
        .enumerate()
        .max_by(|&(ai, &asize), &(bi, &bsize)| {
            asize.cmp(&bsize).then(bi.cmp(&ai))
        })
        .map(|(i, _)| i)
        .unwrap();

    
    let mut new_layout = layout.clone();
    let mut to_redistribute = new_layout[biggest_container];
    new_layout[biggest_container] = 0;
    let mut target = (biggest_container + 1) % layout.len();

    while to_redistribute > 0 {
        new_layout[target] += 1;
        to_redistribute -= 1;
        target = (target + 1) % layout.len();
    }

    new_layout
}