summaryrefslogtreecommitdiff
path: root/2018/src/bin/day_6.rs
blob: 16c87827d5295c4b94528e9d927513602fc09dfa (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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
extern crate advent_of_code_2018;
use advent_of_code_2018::*;

use std::error::Error;
use std::path::PathBuf;

use std::collections::{HashSet, HashMap};

// cargo watch -cs "cargo run --release --bin day_6"

fn main() -> Result<(), Box<Error>> {
    let input = read_file(&PathBuf::from("inputs/6.txt"))?;
    let coordinates = input.iter().map(|line| {
        let mut split = line.split(|c: char| !c.is_numeric());
        let x: i32 = split.next().unwrap().parse().unwrap();
        let _ = split.next();
        let y: i32 = split.next().unwrap().parse().unwrap();
        (x, y)
    }).collect::<Vec<_>>();
    debug!(coordinates);

    let min_x = coordinates.iter().map(|(x, _)| x).min().unwrap().clone();
    let max_x = coordinates.iter().map(|(x, _)| x).max().unwrap().clone();
    let min_y = coordinates.iter().map(|(_, y)| y).min().unwrap().clone();
    let max_y = coordinates.iter().map(|(_, y)| y).max().unwrap().clone();
    
    debug!(min_x);
    debug!(max_x);
    debug!(min_y);
    debug!(max_y);

    let mut infinite = HashSet::new();
    for x in min_x..max_x+1 {
        for y in &[0, max_y] {
            if let Some(coord) = find_closest(&coordinates, x, *y) {
                infinite.insert(coord);
            }
        }
    }
    for y in min_y..max_y+1 {
        for x in &[0, max_x] {
            if let Some(coord) = find_closest(&coordinates, *x, y) {
                infinite.insert(coord);
            }
        }
    }

    debug!(infinite);
    

    let mut areas = HashMap::new();
    for x in min_x..max_x+1 {
        for y in min_y..max_y+1 {
            if let Some(coord) = find_closest(&coordinates, x, y) {
                *areas.entry(coord).or_insert(0) += 1;
            }
        }
    }

    debug!(areas);

    let biggest_non_infinite = areas.iter()
        .filter(|(k,_)| !infinite.contains(&k))
        .max_by_key(|(_,v)| *v);
    debug!(biggest_non_infinite);
    


    let safe_distance = 10000;
    let mut safe_size = 0;
    for x in min_x..max_x+1 {
        for y in min_y..max_y+1 {
            let distance_sum: i32 = coordinates.iter()
                .map(|(x1, y1)| manhattan_distance(*x1, *y1, x, y))
                .sum();
            if distance_sum < safe_distance {
                safe_size += 1;
            }
        }
    }
    debug!(safe_size);
    
    Ok(())
}

fn find_closest(coordinates: &Vec<(i32, i32)>, x: i32, y: i32) -> Option<usize> {
    let mut distances = coordinates.iter()
        .map(|(x1, y1)| manhattan_distance(*x1, *y1, x, y))
        .enumerate()
        .collect::<Vec<_>>();
    distances.sort_by_key(|(_, d)| *d);

    if distances[0] == distances[1] {
        None
    }
    else {
        distances.first().map(|(i, _)| *i)
    }
}

fn manhattan_distance(x1: i32, y1: i32, x2: i32, y2: i32) -> i32 {
    (x2-x1).abs() + (y2-y1).abs()
}