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