Guest User

Untitled

a guest
Feb 17th, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.90 KB | None | 0 0
  1. use image::ImageBuffer;
  2. use image::Rgb;
  3. use image::RgbImage;
  4. use std::fmt::Display;
  5. use std::fmt::Error;
  6. use std::fmt::Formatter;
  7.  
  8. const RULE_110: u8 = 110;
  9.  
  10. pub enum RowStartPosition {
  11. Left,
  12. Right,
  13. Center,
  14. }
  15.  
  16. pub struct Generation {
  17. cells: Vec<bool>,
  18. }
  19.  
  20. impl Display for Generation {
  21. fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
  22. let generation_as_string: String = self
  23. .cells
  24. .iter()
  25. .map(|cell_state| match *cell_state {
  26. true => '■',
  27. false => '□',
  28. })
  29. .collect();
  30. write!(f, "{}", generation_as_string)
  31. }
  32. }
  33.  
  34. impl Generation {
  35. pub fn new(width: usize, start_position: RowStartPosition) -> Self {
  36. assert!(
  37. width > 0,
  38. "You can't create 0 width rows, please create something of width 1 or larger."
  39. );
  40.  
  41. let start_point = match start_position {
  42. RowStartPosition::Left => 0,
  43. RowStartPosition::Right => width - 1,
  44. RowStartPosition::Center => width / 2,
  45. };
  46.  
  47. Generation {
  48. cells: (0..width)
  49. .map(|index: usize| index == start_point)
  50. .collect(),
  51. }
  52. }
  53.  
  54. pub fn get_cell_state(&self, cell_index: usize) -> Option<bool> {
  55. if cell_index + 1 >= self.cells.len() {
  56. return None;
  57. }
  58.  
  59. Some(self.cells[cell_index])
  60. }
  61.  
  62. pub fn get_next_generation(&self, rules: u8) -> Self {
  63. Generation {
  64. cells: self
  65. .cells
  66. .iter()
  67. .enumerate()
  68. .map(|(index, _)| self.get_next_cell_state(index, rules))
  69. .collect(),
  70. }
  71. }
  72.  
  73. fn get_next_cell_state(&self, cell_index: usize, rules: u8) -> bool {
  74. let (left_neighbour, current_state, right_neighbour) =
  75. self.get_cell_and_neighbours(cell_index);
  76.  
  77. get_next_cell_state(left_neighbour, current_state, right_neighbour, rules)
  78. }
  79.  
  80. fn get_cell_and_neighbours(&self, cell_index: usize) -> (bool, bool, bool) {
  81. let left_neighbour_index: usize =
  82. get_left_neighbour_index_wrapping(cell_index, self.cells.len());
  83. let right_neighbour_index: usize =
  84. get_right_neighbour_index_wrapping(cell_index, self.cells.len());
  85.  
  86. (
  87. self.cells[left_neighbour_index],
  88. self.cells[cell_index],
  89. self.cells[right_neighbour_index],
  90. )
  91. }
  92. }
  93.  
  94. pub struct CellularAutomataSystem {
  95. generations: Vec<Generation>,
  96. width: usize,
  97. rules: u8,
  98. }
  99.  
  100. impl Display for CellularAutomataSystem {
  101. fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
  102. let generations: Vec<String> = self
  103. .generations
  104. .iter()
  105. .map(|generation| generation.to_string())
  106. .collect();
  107.  
  108. let generations_as_string = generations.join("\n");
  109. write!(f, "{}", generations_as_string)
  110. }
  111. }
  112.  
  113. impl CellularAutomataSystem {
  114. pub fn from_rules(rules: u8) -> Self {
  115. let width = 30;
  116.  
  117. CellularAutomataSystem {
  118. generations: vec![Generation::new(width, RowStartPosition::Center)],
  119. width,
  120. rules,
  121. }
  122. }
  123.  
  124. pub fn update(&mut self) {
  125. let next_generation = self
  126. .get_next_generation()
  127. .expect("Failed to generate the next generation.");
  128.  
  129. self.generations.push(next_generation);
  130. }
  131.  
  132. pub fn as_image_buffer(&self) -> RgbImage {
  133. ImageBuffer::from_fn(
  134. self.width as u32,
  135. self.generations.len() as u32,
  136. |x, y| match self.generations[y as usize].get_cell_state(x as usize) {
  137. Some(true) => Rgb([255u8, 255u8, 255u8]),
  138. _ => Rgb([0u8, 0u8, 0u8]),
  139. },
  140. )
  141. }
  142.  
  143. pub fn get_generations(&self) -> &Vec<Generation> {
  144. &self.generations
  145. }
  146.  
  147. fn get_next_generation(&self) -> Option<Generation> {
  148. if let Some(current_generation) = self.generations.last() {
  149. return Some(current_generation.get_next_generation(self.rules));
  150. }
  151.  
  152. None
  153. }
  154. }
  155.  
  156. fn get_next_cell_state(
  157. left_neighbour: bool,
  158. current_state: bool,
  159. right_neighbour: bool,
  160. rules: u8,
  161. ) -> bool {
  162. match (left_neighbour, current_state, right_neighbour) {
  163. (true, true, true) => rules & 0b00000001u8 == rules,
  164. (true, true, false) => rules & 0b00000010u8 == rules,
  165. (true, false, true) => rules & 0b00000100u8 == rules,
  166. (true, false, false) => rules & 0b00001000u8 == rules,
  167. (false, true, true) => rules & 0b00010000u8 == rules,
  168. (false, true, false) => rules & 0b00100000u8 == rules,
  169. (false, false, true) => rules & 0b01000000u8 == rules,
  170. (false, false, false) => rules & 0b10000000u8 == rules,
  171. }
  172. }
  173.  
  174. fn get_right_neighbour_index_wrapping(current_index: usize, collection_size: usize) -> usize {
  175. get_index_wrapping(
  176. current_index as isize + 1 as isize,
  177. collection_size as isize,
  178. ) as usize
  179. }
  180.  
  181. fn get_left_neighbour_index_wrapping(current_index: usize, collection_size: usize) -> usize {
  182. get_index_wrapping(current_index as isize - 1, collection_size as isize) as usize
  183. }
  184.  
  185. fn get_index_wrapping(index: isize, upper_bound: isize) -> isize {
  186. if index >= 0 {
  187. index % upper_bound
  188. } else {
  189. (index % upper_bound + upper_bound) % upper_bound
  190. }
  191. }
  192.  
  193. #[cfg(test)]
  194. mod tests {
  195. use super::*;
  196.  
  197. #[test]
  198. fn test_get_index_wrapping() {
  199. assert_eq!(0, get_index_wrapping(0, 10));
  200. assert_eq!(0, get_index_wrapping(10, 10));
  201. assert_eq!(5, get_index_wrapping(5, 10));
  202. assert_eq!(9, get_index_wrapping(19, 10));
  203. assert_eq!(0, get_index_wrapping(-10, 10));
  204. }
  205.  
  206. #[test]
  207. fn test_get_right_neighbour_index_wrapping() {
  208. assert_eq!(1, get_right_neighbour_index_wrapping(0, 4));
  209. assert_eq!(0, get_right_neighbour_index_wrapping(3, 4));
  210. }
  211.  
  212. #[test]
  213. fn test_get_left_neighbour_index_wrapping() {
  214. assert_eq!(2, get_left_neighbour_index_wrapping(3, 4));
  215. assert_eq!(3, get_left_neighbour_index_wrapping(0, 4));
  216. }
  217.  
  218. fn get_next_cell_state_rule_30(
  219. left_neighbour: bool,
  220. current_state: bool,
  221. right_neighbour: bool,
  222. ) -> bool {
  223. match (left_neighbour, current_state, right_neighbour) {
  224. (true, true, true) => false,
  225. (true, true, false) => false,
  226. (true, false, true) => false,
  227. (true, false, false) => true,
  228. (false, true, true) => true,
  229. (false, true, false) => true,
  230. (false, false, true) => true,
  231. (false, false, false) => false,
  232. }
  233. }
  234.  
  235. #[test]
  236. fn test_get_next_cell_state() {
  237. assert_eq!(
  238. get_next_cell_state(true, true, true, 30),
  239. get_next_cell_state_rule_30(true, true, true)
  240. );
  241. assert_eq!(
  242. get_next_cell_state(true, true, false, 30),
  243. get_next_cell_state_rule_30(true, true, false)
  244. );
  245. assert_eq!(
  246. get_next_cell_state(true, false, true, 30),
  247. get_next_cell_state_rule_30(true, false, true)
  248. );
  249. assert_eq!(
  250. get_next_cell_state(true, false, false, 30),
  251. get_next_cell_state_rule_30(true, false, false)
  252. );
  253. assert_eq!(
  254. get_next_cell_state(false, true, true, 30),
  255. get_next_cell_state_rule_30(false, true, true)
  256. );
  257. assert_eq!(
  258. get_next_cell_state(true, true, false, 30),
  259. get_next_cell_state_rule_30(true, true, false)
  260. );
  261. assert_eq!(
  262. get_next_cell_state(false, false, true, 30),
  263. get_next_cell_state_rule_30(false, false, true)
  264. );
  265. assert_eq!(
  266. get_next_cell_state(false, false, false, 30),
  267. get_next_cell_state_rule_30(false, false, false)
  268. );
  269. }
  270. }
Add Comment
Please, Sign In to add comment