Advertisement
Guest User

Untitled

a guest
Nov 27th, 2015
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.78 KB | None | 0 0
  1. extern crate rand;
  2.  
  3. use std::cmp;
  4. use std::env;
  5. use std::fmt;
  6. use rand::{thread_rng, Rng};
  7.  
  8. #[derive(PartialEq,Clone)]
  9. enum Colors {
  10. Black,
  11. Yellow,
  12. Red,
  13. Purple
  14. }
  15.  
  16. static COLORS: [Colors; 4] = [Colors::Black, Colors::Yellow, Colors::Red, Colors::Purple];
  17.  
  18. #[derive(Clone)]
  19. struct Tile {
  20. color: Colors,
  21. number: u8
  22. }
  23.  
  24. impl fmt::Display for Tile {
  25. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  26. let color_tag = match self.color {
  27. Colors::Black => "B",
  28. Colors::Yellow => "Y",
  29. Colors::Red => "R",
  30. Colors::Purple => "P"
  31. };
  32. return write!(f, "{}{}", color_tag, self.number);
  33. }
  34. }
  35.  
  36. impl cmp::PartialEq for Tile {
  37. fn eq(&self, other: &Self) -> bool {
  38. return self.number == other.number && self.color == other.color;
  39. }
  40.  
  41. fn ne(&self, other: &Self) -> bool {
  42. return !(self.number == other.number && self.color == other.color);
  43. }
  44. }
  45.  
  46. fn main() {
  47. // Build tilebag
  48. let mut tilebag = vec![];
  49. for _ in 0..2 {
  50. for i in 1..14 {
  51. for c in COLORS.iter().cloned() {
  52. tilebag.push(Tile {
  53. color: c,
  54. number: i
  55. });
  56. }
  57. }
  58. }
  59.  
  60. //Get our starting hand from the command line
  61. let mut my_tiles = vec![];
  62. let args: Vec<String> = env::args().skip(1).collect();
  63. assert!(args.len() == 14, "Must receive 14 starting tiles as input");
  64.  
  65. for arg in args.iter() {
  66. let parts = arg.split_at(1);
  67. let color = match parts.0 {
  68. "B" => Ok(Colors::Black),
  69. "Y" => Ok(Colors::Yellow),
  70. "R" => Ok(Colors::Red),
  71. "P" => Ok(Colors::Purple),
  72. _ => Err("Bad color input")
  73. }.unwrap();
  74. // Pull any tiles we're given out of the tilebag
  75. let tile = tilebag.iter().position(|i| i.color == color && i.number == parts.1.parse::<u8>().unwrap()).unwrap();
  76. my_tiles.push(tilebag.remove(tile));
  77. }
  78.  
  79. // See if we have any sets
  80. let mut valid_set;
  81. let mut rng = thread_rng();
  82. while {
  83. valid_set = find_sets(&mut my_tiles);
  84. valid_set.is_none()
  85. } {
  86. // Draw random tiles until we find a valid set
  87. let tile = rng.gen_range(0, tilebag.len());
  88. let tile = tilebag.remove(tile);
  89. println!("Drawing: {}", tile);
  90. my_tiles.push(tile);
  91. }
  92.  
  93. println!("Found a valid set:");
  94. for i in valid_set.unwrap() {
  95. print!("{} ", i);
  96. }
  97. println!(""); // Truncate our line of output
  98. }
  99.  
  100. fn find_sets(hand: &mut Vec<Tile>) -> Option<Vec<Tile>> {
  101. #[derive(Clone)]
  102. struct TileSet {
  103. tiles: Vec<Tile>,
  104. sum: u16
  105. }
  106.  
  107. // We sort once because we'll be needing it sorted for every search we do
  108. hand.sort_by(|a, b| a.number.cmp(&b.number));
  109.  
  110. // Search for possible runs
  111. let mut possible_runs: Vec<TileSet> = vec![];
  112. let mut current_set: TileSet = TileSet {
  113. tiles: vec![],
  114. sum: 0
  115. };
  116. for c in COLORS.iter().cloned() {
  117. let mut temp_hand = hand.clone();
  118. temp_hand.retain(|i| i.color == c);
  119. temp_hand.dedup();
  120. let mut last: Option<Tile> = None;
  121. for i in temp_hand {
  122. if last.is_some() && last.clone().unwrap().number + 1 == i.number {
  123. current_set.tiles.push(i.clone());
  124. current_set.sum += i.number as u16;
  125. if current_set.tiles.len() >= 3 {
  126. possible_runs.push(current_set.clone());
  127. }
  128. } else {
  129. current_set = TileSet {
  130. tiles: vec![i.clone()],
  131. sum: i.number as u16
  132. };
  133. }
  134. last = Some(i.clone());
  135. }
  136. }
  137.  
  138. // Exit early if we have a run with 4 or more tiles in it
  139. let mut best_count = 0;
  140. let mut best_index = None;
  141. for (index, i) in possible_runs.iter().enumerate() {
  142. if i.tiles.len() >= 4 && i.sum >= 30 && i.tiles.len() > best_count {
  143. best_count = i.tiles.len();
  144. best_index = Some(index);
  145. }
  146. }
  147. if best_index.is_some() {
  148. return Some(possible_runs[best_index.unwrap()].tiles.clone());
  149. }
  150.  
  151. // Search for possible groups
  152. let mut possible_groups: Vec<TileSet> = vec![];
  153. let mut last_number = 0;
  154. let temp_hand = hand.clone();
  155. for i in temp_hand {
  156. if i.number != last_number {
  157. if current_set.tiles.len() >= 3 {
  158. possible_groups.push(current_set.clone());
  159. }
  160. last_number = i.number;
  161. current_set = TileSet {
  162. tiles: vec![i.clone()],
  163. sum: i.number as u16
  164. };
  165. } else if !current_set.tiles.contains(&i) {
  166. current_set.tiles.push(i.clone());
  167. current_set.sum += i.number as u16;
  168. }
  169. }
  170.  
  171. // Let's see if any of our groups are usable on their own
  172. best_index = None;
  173. for (index, i) in possible_groups.iter().enumerate() {
  174. if i.tiles.len() >= 3 && i.sum >= 30 {
  175. best_index = Some(index);
  176. if i.tiles.len() == 4 {
  177. break;
  178. }
  179. }
  180. }
  181. if best_index.is_some() {
  182. return Some(possible_groups[best_index.unwrap()].tiles.clone());
  183. }
  184.  
  185. // Let's see if any of our runs of length 3 are usable
  186. best_count = 0;
  187. best_index = None;
  188. for (index, i) in possible_runs.iter().enumerate() {
  189. if i.tiles.len() >= 3 && i.sum >= 30 {
  190. best_count = i.tiles.len();
  191. best_index = Some(index);
  192. break;
  193. }
  194. }
  195. if best_count >= 3 {
  196. return Some(possible_runs[best_index.unwrap()].tiles.clone());
  197. }
  198.  
  199. // Now we'll look for combinations. Last resort because this is slow.
  200. best_count = 0;
  201. let mut best_run = None;
  202. let mut best_group = None;
  203. for (group, i) in possible_groups.iter().enumerate() {
  204. for (run, j) in possible_runs.iter().enumerate() {
  205. let mut duplicate = false;
  206. for tile in i.tiles.iter().cloned() {
  207. if j.tiles.contains(&tile) {
  208. duplicate = true;
  209. break;
  210. }
  211. }
  212. if duplicate {
  213. continue;
  214. }
  215. if i.tiles.len() >= 3 && j.tiles.len() >= 3 && i.sum + j.sum >= 30 {
  216. if best_count >= i.tiles.len() + j.tiles.len() {
  217. continue;
  218. }
  219. best_count = i.tiles.len() + j.tiles.len();
  220. best_run = Some(run);
  221. best_group = Some(group);
  222. }
  223. }
  224. }
  225. if best_run.is_some() && best_group.is_some() {
  226. let mut result = possible_runs[best_run.unwrap()].tiles.clone();
  227. result.append(&mut possible_groups[best_group.unwrap()].tiles);
  228. return Some(result);
  229. }
  230.  
  231. return None;
  232. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement