ICFP 2007 Contest: https://web.archive.org/web/20090301164728/https://save-endo.cs.uu.nl/
1use crate::bitmap::Bitmap; 2use crate::bitmap::SIZE; 3use crate::bitmap::new_bitmap; 4use std::cmp::max; 5 6struct Bucket { 7 total_r: usize, 8 total_g: usize, 9 total_b: usize, 10 total_a: usize, 11 count_rgb: usize, 12 count_a: usize, 13} 14 15pub struct RnaProcessor { 16 bucket: Bucket, 17 position: (usize, usize), 18 mark: (usize, usize), 19 dir: (usize, usize), 20 bitmaps: Vec<Bitmap>, 21} 22 23impl Bucket { 24 fn new() -> Bucket { 25 Bucket { 26 total_r: 0, 27 total_g: 0, 28 total_b: 0, 29 total_a: 0, 30 count_rgb: 0, 31 count_a: 0, 32 } 33 } 34 35 fn current_pixel(&self) -> (u8, u8, u8, u8) { 36 let r = if self.count_rgb == 0 { 37 0 38 } else { 39 self.total_r / self.count_rgb 40 }; 41 let g = if self.count_rgb == 0 { 42 0 43 } else { 44 self.total_g / self.count_rgb 45 }; 46 let b = if self.count_rgb == 0 { 47 0 48 } else { 49 self.total_b / self.count_rgb 50 }; 51 let a = if self.count_a == 0 { 52 255 53 } else { 54 self.total_a / self.count_a 55 }; 56 57 return ( 58 (r * a / 255) as u8, 59 (r * g / 255) as u8, 60 (r * b / 255) as u8, 61 a as u8, 62 ); 63 } 64 65 fn add_rgb(&mut self, r: usize, g: usize, b: usize) { 66 self.total_r += r; 67 self.total_g += g; 68 self.total_b += b; 69 self.count_rgb += 1; 70 } 71 72 fn add_a(&mut self, a: usize) { 73 self.total_a += a; 74 self.count_a += 1; 75 } 76 77 fn clear(&mut self) { 78 self.total_r = 0; 79 self.total_g = 0; 80 self.total_b = 0; 81 self.total_a = 0; 82 self.count_rgb = 0; 83 self.count_a = 0; 84 } 85} 86 87impl RnaProcessor { 88 pub fn new() -> RnaProcessor { 89 RnaProcessor { 90 bucket: Bucket::new(), 91 position: (0, 0), 92 mark: (0, 0), 93 dir: (1, 0), 94 bitmaps: Vec::new(), 95 } 96 } 97 98 fn set_pixel(&mut self, x: usize, y: usize) { 99 if let Some(b) = self.bitmaps.last_mut() { 100 b[x][y] = self.bucket.current_pixel(); 101 } 102 } 103 104 pub fn process_rna(&mut self, rna: Vec<&str>) { 105 for r in rna { 106 if r == "PIPIIIC" { 107 self.bucket.add_rgb(0, 0, 0); 108 } else if r == "PIPIIIP" { 109 self.bucket.add_rgb(255, 0, 0); 110 } else if r == "PIPIICC" { 111 self.bucket.add_rgb(0, 255, 0); 112 } else if r == "PIPIICF" { 113 self.bucket.add_rgb(255, 255, 0); 114 } else if r == "PIPIICP" { 115 self.bucket.add_rgb(0, 0, 255); 116 } else if r == "PIPIIFC" { 117 self.bucket.add_rgb(255, 0, 255); 118 } else if r == "PIPIIFF" { 119 self.bucket.add_rgb(0, 255, 255); 120 } else if r == "PIPIIPC" { 121 self.bucket.add_rgb(255, 255, 255); 122 } else if r == "PIPIIPF" { 123 self.bucket.add_a(0); 124 } else if r == "PIPIIPP" { 125 self.bucket.add_a(255); 126 } else if r == "PIIPICP" { 127 self.bucket.clear(); 128 } else if r == "PIIIIIP" { 129 let (x, y) = self.position; 130 let (dx, dy) = self.dir; 131 self.position = ((x + dx) % SIZE, (y + dy) % SIZE); 132 } else if r == "PCCCCCP" { 133 let (dx, dy) = self.dir; 134 self.dir = (dy, SIZE - dx); 135 } else if r == "PFFFFFP" { 136 let (dx, dy) = self.dir; 137 self.dir = (SIZE - dy, dx); 138 } else if r == "PCCIFFP" { 139 self.mark = self.position; 140 } else if r == "PFFICCP" { 141 let x0 = self.position.0 as isize; 142 let y0 = self.position.1 as isize; 143 let x1 = self.mark.0 as isize; 144 let y1 = self.mark.1 as isize; 145 let dx = x1 - x0; 146 let dy = y1 - y0; 147 let d = max(dx.abs(), dy.abs()); 148 let c = if dx * dy <= 0 { 1 } else { 0 }; 149 let mut x = x0 * d + (d - c) / 2; 150 let mut y = x0 * d + (d - c) / 2; 151 for _ in 0..d { 152 self.set_pixel((x / d) as usize, (y / d) as usize); 153 x += dx; 154 y += dy; 155 } 156 self.set_pixel(x1 as usize, y1 as usize); 157 } else if r == "PIIPIIP" { 158 let (x, y) = self.position; 159 if let Some(b) = self.bitmaps.last_mut() { 160 let old = b[x][y]; 161 let new = self.bucket.current_pixel(); 162 let mut to_fill = Vec::new(); 163 to_fill.push(self.position); 164 while let Some((x, y)) = to_fill.pop() { 165 if b[x][y] == old { 166 b[x][y] = new; 167 if x > 0 { 168 to_fill.push((x - 1, y)); 169 } 170 if x < SIZE - 1 { 171 to_fill.push((x + 1, y)); 172 } 173 if y > 0 { 174 to_fill.push((x, y - 1)); 175 } 176 if y < SIZE - 1 { 177 to_fill.push((x, y + 1)); 178 } 179 } 180 } 181 } 182 } else if r == "PCCPFFP" { 183 if self.bitmaps.len() < 10 { 184 self.bitmaps.push(new_bitmap()); 185 } 186 } else if r == "PFFPCCP" { 187 if self.bitmaps.len() >= 2 { 188 let bmp0 = self.bitmaps[self.bitmaps.len() - 1]; 189 let mut bmp1 = self.bitmaps[self.bitmaps.len() - 2]; 190 for x in 0..SIZE { 191 for y in 0..SIZE { 192 let (r0, b0, g0, a0) = bmp0[x][y]; 193 let (r1, b1, g1, a1) = bmp1[x][y]; 194 let r = r0 + (((r1 as usize) * (255 - a0 as usize) / 255) as u8); 195 let g = g0 + (((g1 as usize) * (255 - a0 as usize) / 255) as u8); 196 let b = b0 + (((b1 as usize) * (255 - a0 as usize) / 255) as u8); 197 let a = a0 + (((a1 as usize) * (255 - a0 as usize) / 255) as u8); 198 bmp1[x][y] = (r, g, b, a); 199 } 200 } 201 self.bitmaps.pop(); 202 } 203 } else if r == "PFFICCF" { 204 if self.bitmaps.len() >= 2 { 205 let bmp0 = self.bitmaps[self.bitmaps.len() - 1]; 206 let mut bmp1 = self.bitmaps[self.bitmaps.len() - 2]; 207 for x in 0..SIZE { 208 for y in 0..SIZE { 209 let (_, _, _, a0) = bmp0[x][y]; 210 let (r1, b1, g1, a1) = bmp1[x][y]; 211 let r = ((r1 as usize) * (a0 as usize) / 255) as u8; 212 let g = ((g1 as usize) * (a0 as usize) / 255) as u8; 213 let b = ((b1 as usize) * (a0 as usize) / 255) as u8; 214 let a = ((a1 as usize) * (a0 as usize) / 255) as u8; 215 bmp1[x][y] = (r, g, b, a); 216 } 217 } 218 self.bitmaps.pop(); 219 } 220 } 221 } 222 } 223 224 pub fn bitmap(&self) -> Option<&Bitmap> { 225 self.bitmaps.last() 226 } 227}