summaryrefslogtreecommitdiff
path: root/src/solvers.rs
blob: 447f75334d339ec19c4caed1b76b38c086256e9e (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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
pub struct Wall {
    heights: Vec<u32>,
}

impl Wall {
    pub fn from_heights(heights: Vec<u32>) -> Self {
        Self { heights }
    }

    fn create_empty(w: u32) -> Self {
        let heights = if w == 0 {
            vec![]
        } else if w == 1 {
            vec![0]
        } else {
            let mut v = Vec::with_capacity(w as usize);
            v.push(0);
            v.push(1);
            v
        };
        Self { heights }
    }

    pub fn calculate_row(&self, r: u32, stones: &mut [u32]) {
        let mut len = 1;
        let mut i = 0;
        for &height in self.heights.iter().chain([r].iter()) {
            if height == r {
                stones[i] = len;
                i += 1;
                len = 0;
            }
            len += 1;
        }
    }

    pub fn output(&self, n: u32, h: u32) {
        let mut stones = vec![0; n as usize];
        let mut toggle = 0;
        let colors = [
            "\x1b[31m", "\x1b[32m", "\x1b[33m", "\x1b[34m", "\x1b[35m", "\x1b[36m",
        ];
        for row in 0..h {
            self.calculate_row(row, &mut stones);
            for &len in stones.iter() {
                print!("{}", colors[toggle]);
                toggle = (toggle + 1) % colors.len();
                for _ in 0..len {
                    print!("◙");
                }
            }
            println!("\x1b[m");
        }
    }
}

/// Solve for a given N and return the resulting wall
pub struct Solver<T: num::PrimInt> {
    pub n: u32,
    /// calculated height [might not be correct!]
    pub h: u32,
    /// width
    pub w: u32,
    /// Use to store already used blocks as a bitmask
    solve_stack: Vec<SaveState<T>>,
}

// used during row creation, will get deprecated
static mut COUNT: u32 = 0;

/// Save the current state for each row
#[derive(Clone, Eq, Copy)]
pub struct SaveState<T: num::PrimInt> {
    /// Mask of all currently used stones
    pub bitmask: T,
    /// sum of all placed stones
    pub index: u32,
    /// the row index
    pub row: u32,
}

impl<T: num::PrimInt> std::cmp::Ord for SaveState<T> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.index.cmp(&other.index)
    }
}
impl<T: num::PrimInt> std::cmp::PartialOrd for SaveState<T> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.index.cmp(&other.index))
    }
}
impl<T: num::PrimInt> std::cmp::PartialEq for SaveState<T> {
    fn eq(&self, other: &Self) -> bool {
        self.index.eq(&other.index)
    }
}

impl<T: num::PrimInt> SaveState<T> {
    pub fn new() -> Self {
        Self {
            bitmask: T::zero(),
            index: 0,
            row: unsafe {
                COUNT += 1;
                COUNT
            },
        }
    }

    pub fn set_bit(&mut self, stone: u32) {
        self.bitmask =
            self.bitmask | T::from(1 << stone).expect("Stone placing index out of bounds");
    }

    pub fn get_bit(&self, stone: u32) -> T {
        println!("{},", stone);
        self.bitmask & T::from(1 << stone).expect("Requested stone index out of bounds")
    }

    pub fn bridges_gap(&self, index: u32) -> bool {
        self.get_bit(index - self.index) == T::zero()
    }

    pub fn bridge_gap(mut self, index: u32) -> Self {
        self.set_bit(index - self.index);
        self.index = index;
        self
    }
}

impl<T: num::PrimInt> Solver<T> {
    pub fn new(n: usize) -> Self {
        let h = n / 2 + 1;
        let w = h * (n - 1);
        Self {
            n: (n as u32),
            h: (h as u32),
            w: (w as u32),
            solve_stack: vec![SaveState::new(); h],
        }
    }

    //dummy solver
    pub fn solve(&mut self) -> Wall {
        let mut wall = Wall::create_empty(self.w);
        wall.heights
            .iter()
            .take(2)
            .zip(0..1)
            .for_each(|(x, i)| self.solve_stack[*x as usize].set_bit(i));
        for i in 0..(self.n * self.h) {
            let machine = self
                .solve_stack
                .iter()
                .filter(|x| x.bridges_gap(i + 1))
                .min()
                .unwrap()
                .bridge_gap(i + 1);
            wall.heights.push(machine.row);
        }

        wall
    }
}