105 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use std::collections::HashMap;
 | |
| 
 | |
| const DISALLOWED: [(u8, u8); 4] = [(b'a', b'b'), (b'c', b'd'), (b'p', b'q'), (b'x', b'y')];
 | |
| const VOWELS: [u8; 5] = [b'a', b'e', b'i', b'o', b'u'];
 | |
| 
 | |
| pub fn process_part1(input: &str) -> i32 {
 | |
|     input
 | |
|         .lines()
 | |
|         .map(|line| line.as_bytes())
 | |
|         .map(|line| {
 | |
|             let mut num_vowels = 0;
 | |
|             let mut has_double = false;
 | |
|             if VOWELS.contains(&line[0]) {
 | |
|                 num_vowels += 1;
 | |
|             }
 | |
|             for window in line.windows(2) {
 | |
|                 if DISALLOWED.contains(&(window[0], window[1])) {
 | |
|                     return 0;
 | |
|                 }
 | |
|                 if window[0] == window[1] {
 | |
|                     has_double = true;
 | |
|                 }
 | |
|                 if VOWELS.contains(&window[1]) {
 | |
|                     num_vowels += 1;
 | |
|                 }
 | |
|             }
 | |
|             if num_vowels >= 3 && has_double {
 | |
|                 return 1;
 | |
|             }
 | |
|             0
 | |
|         })
 | |
|         .sum()
 | |
| }
 | |
| 
 | |
| // used the following solution to debug
 | |
| // cat input |  grep "\(..\).*\1" | grep "\(.\).\1" | wc -l
 | |
| pub fn process_part2(input: &str) -> i32 {
 | |
|     input
 | |
|         .lines()
 | |
|         .map(|line| line.as_bytes())
 | |
|         .map(|line| {
 | |
|             let mut pairs = HashMap::new();
 | |
|             let mut has_sandwich = false;
 | |
|             for window in line.windows(3) {
 | |
|                 if window[0] == window[2] {
 | |
|                     has_sandwich = true;
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|             if !has_sandwich {
 | |
|                 return 0;
 | |
|             }
 | |
|             let mut last_pair = "".to_string();
 | |
|             let mut is_valid = true;
 | |
|             for window in line.windows(2) {
 | |
|                 let pair = String::from_utf8(window.to_vec()).unwrap();
 | |
|                 if pair == last_pair && is_valid {
 | |
|                     is_valid = false;
 | |
|                     continue;
 | |
|                 }
 | |
|                 is_valid = true;
 | |
|                 pairs
 | |
|                     .entry(pair.clone())
 | |
|                     .and_modify(|counter| *counter += 1)
 | |
|                     .or_insert(1);
 | |
|                 last_pair = pair;
 | |
|             }
 | |
|             for (_, count) in pairs.into_iter() {
 | |
|                 if count >= 2 {
 | |
|                     return 1;
 | |
|                 }
 | |
|             }
 | |
|             0
 | |
|         })
 | |
|         .sum()
 | |
| }
 | |
| 
 | |
| #[cfg(test)]
 | |
| mod tests {
 | |
|     use super::*;
 | |
| 
 | |
|     const INPUT1: &str = "ugknbfddgicrmopn
 | |
| aaa
 | |
| jchzalrnumimnmhp
 | |
| haegwjzuvuyypxyu
 | |
| dvszwmarrgswjxmb";
 | |
| 
 | |
|     #[test]
 | |
|     fn part1() {
 | |
|         let result = process_part1(INPUT1);
 | |
|         assert_eq!(result, 2);
 | |
|     }
 | |
| 
 | |
|     const INPUT2: &str = "qjhvhtzxzqqjkmpb
 | |
| xxyxx
 | |
| uurcxstgmygtbstg
 | |
| ieodomkazucvgmuy";
 | |
| 
 | |
|     #[test]
 | |
|     fn part2() {
 | |
|         let result = process_part2(INPUT2);
 | |
|         assert_eq!(result, 2);
 | |
|     }
 | |
| }
 |