aboutsummaryrefslogtreecommitdiff
path: root/2022/17/common.rs
blob: d27ec3ac17308f259573fdba019eabc3549575f6 (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
use std::cmp::max;

pub const SCREEN_WIDTH: usize = 7;
pub const SCREEN_HEIGHT: usize = 100000;

pub struct Screen {
    pub cell: [[bool; SCREEN_WIDTH]; SCREEN_HEIGHT],
    pub top: usize
}

#[derive(Debug)]
pub struct Rock {
    pub a: Vec<(usize, usize)>,
    pub h: usize
}

pub fn get_rocks() -> Vec<Rock> {
    vec![
        Rock { a: vec![(0, 0), (0, 1), (0, 2), (0, 3)], h: 1 },
        Rock { a: vec![(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)], h: 3 },
        Rock { a: vec![(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)], h: 3 },
        Rock { a: vec![(0, 0), (1, 0), (2, 0), (3, 0)], h: 4 },
        Rock { a: vec![(0, 0), (0, 1), (1, 0), (1, 1)], h: 2 }
    ]
}

fn in_bounds(position: (i32, i32)) -> bool {
    position.0 >= 0 && position.1 >= 0 && position.1 < SCREEN_WIDTH as i32
}

impl Screen {
    pub fn new() -> Screen {
        Screen {
            cell: [[false; SCREEN_WIDTH]; SCREEN_HEIGHT],
            top: 0
        }
    }

    fn allowed(&self, rock: &Rock, p: (i32, i32)) -> bool {
        for r in &rock.a {
            let (i, j) = (r.0 as i32 + p.0, r.1 as i32 + p.1);
            if !in_bounds((i, j)) || self.cell[i as usize][j as usize] {
                return false;
            }
        }
        true
    }

    fn draw(&mut self, rock: &Rock, p: (usize, usize), b: bool) {
        for r in &rock.a {
            self.cell[r.0 + p.0][r.1 + p.1] = b;
        }
    }

    fn move_rock(&mut self, r: &Rock, p: (usize, usize), d: (i32, i32)) -> (usize, usize) {
        let newpos = (p.0 as i32 + d.0, p.1 as i32 + d.1);
        if !self.allowed(r, newpos) { return p; }
        let newpos = (newpos.0 as usize, newpos.1 as usize);
        newpos
    }

    pub fn drop_rock(&mut self, r: &Rock, t: &mut usize, gas: &str) {
        let mut p = (self.top + 3, 2);
        loop {
            let d = gas.chars().nth(*t % gas.len()).unwrap();
            let d = if d == '>' { (0, 1) } else { (0, -1) };
            p = self.move_rock(r, p, d);
            *t += 1;
            let q = self.move_rock(r, p, (-1, 0));
            if p == q { break; } else { p = q; }
        }
        self.draw(r, p, true);
        self.top = max(self.top, p.0 + r.h);
    }

    #[allow(dead_code)]
    pub fn print(&self) {
        for i in (0..=self.top).rev() {
            for j in 0..SCREEN_WIDTH {
                print!("{}", if self.cell[i][j] { '#' } else { '.' })
            }
            println!(" {i}");
        }
    }
}

Generated with cgit - Back to sebastiano.tronto.net