adventofcode

git clone https://git.ce9e.org/adventofcode.git

commit
bd4fddf63a014f5046cba68ea17435ed392657c4
parent
c72b57251130d870803925ca2c5271f84d84e342
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2021-12-25 00:24
simplify

Diffstat

M 2021/24/part1.rs 270 ++++++++++++++++++++++++++++++++-----------------------------

1 files changed, 141 insertions, 129 deletions


diff --git a/2021/24/part1.rs b/2021/24/part1.rs

@@ -3,11 +3,6 @@ use std::fs::File;
    3     3 use std::io::BufRead;
    4     4 use std::io::BufReader;
    5     5 
    6    -1 fn s2c(s: &str) -> char {
    7    -1     assert_eq!(s.len(), 1);
    8    -1     return s.chars().next().unwrap();
    9    -1 }
   10    -1 
   11     6 #[derive(PartialEq, Debug, Copy, Clone)]
   12     7 enum Token {
   13     8     Add,
@@ -15,8 +10,8 @@ enum Token {
   15    10     Div,
   16    11     Mod,
   17    12     Eql,
   18    -1     Int(i16),
   19    -1     Var(char),
   -1    13     Int(i64),
   -1    14     Var(usize),
   20    15     Input(u8),
   21    16 }
   22    17 
@@ -60,9 +55,6 @@ fn print_formular(formular: &mut std::slice::Iter<'_, Token>) {
   60    55         Some(Token::Int(i)) => {
   61    56             print!("{}", i);
   62    57         },
   63    -1         Some(Token::Var(c)) => {
   64    -1             print!("{}", c);
   65    -1         },
   66    58         Some(Token::Input(i)) => {
   67    59             print!("in{}", i);
   68    60         },
@@ -70,143 +62,163 @@ fn print_formular(formular: &mut std::slice::Iter<'_, Token>) {
   70    62     }
   71    63 }
   72    64 
   73    -1 fn optimize(input: Vec<Token>) -> Vec<Token> {
   74    -1     let mut stack = input;
   75    -1     let mut dirty = true;
   76    -1     while dirty {
   77    -1         let mut new = vec![];
   78    -1         dirty = false;
   79    -1         let mut i = 0;
   80    -1         while i < stack.len() - 2 {
   81    -1             match stack[i..i+3] {
   82    -1                 [Token::Mul, Token::Var(_), Token::Int(0)] => {
   83    -1                     new.push(Token::Int(0));
   84    -1                     i += 2;
   85    -1                     dirty = true;
   86    -1                 },
   87    -1                 [Token::Mul, Token::Int(0), Token::Var(_)] => {
   88    -1                     new.push(Token::Int(0));
   89    -1                     i += 2;
   90    -1                     dirty = true;
   91    -1                 },
   92    -1                 [Token::Mul, Token::Int(1), Token::Var(b)] => {
   93    -1                     new.push(Token::Var(b));
   94    -1                     i += 2;
   95    -1                     dirty = true;
   96    -1                 },
   97    -1                 [Token::Mul, Token::Var(a), Token::Int(1)] => {
   98    -1                     new.push(Token::Var(a));
   99    -1                     i += 2;
  100    -1                     dirty = true;
  101    -1                 },
  102    -1                 [Token::Add, Token::Int(0), Token::Var(b)] => {
  103    -1                     new.push(Token::Var(b));
  104    -1                     i += 2;
  105    -1                     dirty = true;
  106    -1                 },
  107    -1                 [Token::Add, Token::Var(a), Token::Int(0)] => {
  108    -1                     new.push(Token::Var(a));
  109    -1                     i += 2;
  110    -1                     dirty = true;
  111    -1                 },
  112    -1                 [Token::Div, Token::Var(a), Token::Int(1)] => {
  113    -1                     new.push(Token::Var(a));
  114    -1                     i += 2;
  115    -1                     dirty = true;
  116    -1                 },
  117    -1                 [Token::Add, Token::Int(a), Token::Int(b)] => {
  118    -1                     new.push(Token::Int(a + b));
  119    -1                     i += 2;
  120    -1                     dirty = true;
  121    -1                 },
  122    -1                 [Token::Mul, Token::Int(a), Token::Int(b)] => {
  123    -1                     new.push(Token::Int(a * b));
  124    -1                     i += 2;
  125    -1                     dirty = true;
  126    -1                 },
  127    -1                 [Token::Div, Token::Int(a), Token::Int(b)] => {
  128    -1                     new.push(Token::Int(a / b));
  129    -1                     i += 2;
  130    -1                     dirty = true;
  131    -1                 },
  132    -1                 [Token::Mod, Token::Int(a), Token::Int(b)] => {
  133    -1                     new.push(Token::Int(a % b));
  134    -1                     i += 2;
  135    -1                     dirty = true;
  136    -1                 },
  137    -1                 [Token::Eql, Token::Int(a), Token::Int(b)] => {
  138    -1                     new.push(Token::Int(if a == b {1} else {0}));
  139    -1                     i += 2;
  140    -1                     dirty = true;
  141    -1                 },
  142    -1                 _ => new.push(stack[i]),
  143    -1             }
  144    -1             i += 1;
  145    -1         }
  146    -1         while i < stack.len() {
  147    -1             new.push(stack[i]);
  148    -1             i += 1;
  149    -1         }
  150    -1         stack = new;
  151    -1     }
  152    -1     return stack;
  153    -1 }
  154    -1 
  155    -1 fn main() {
   -1    65 fn get_data() -> Vec<(Token, Token, Token)> {
  156    66     let path = args().nth(1).unwrap();
  157    67     let file = File::open(path).unwrap();
  158    68 
   -1    69     let mut lines = vec![];
  159    70     let mut input = 0;
  160    -1     let mut stack = vec![Token::Var('z')];
  161    71 
  162    -1     // FIXME: reverse
  163    -1     for (i, line) in BufReader::new(file).lines().enumerate() {
   -1    72     for line in BufReader::new(file).lines() {
  164    73         let l = line.unwrap();
  165    74 
  166    75         match l.split(" ").collect::<Vec<&str>>()[..] {
  167    76             ["inp", a] => {
  168    -1                 let mut new = vec![];
  169    -1                 for token in stack {
  170    -1                     if token == Token::Var(s2c(a)) {
  171    -1                         new.push(Token::Input(input));
  172    -1                     } else {
  173    -1                         new.push(token);
  174    -1                     }
  175    -1                 }
  176    -1                 stack = new;
   -1    77                 lines.push((
   -1    78                     Token::Input(input),
   -1    79                     Token::Var(match a {
   -1    80                         "z" => 0,
   -1    81                         "y" => 1,
   -1    82                         "x" => 2,
   -1    83                         "w" => 3,
   -1    84                         _ => unreachable!(),
   -1    85                     }),
   -1    86                     Token::Int(0),
   -1    87                 ));
  177    88                 input += 1;
  178    89             },
  179    90             [op, a, b] => {
  180    -1                 let mut new = vec![];
  181    -1                 for token in stack {
  182    -1                     if token == Token::Var(s2c(a)) {
  183    -1                         new.push(match op {
  184    -1                             "add" => Token::Add,
  185    -1                             "mul" => Token::Mul,
  186    -1                             "div" => Token::Div,
  187    -1                             "mod" => Token::Mod,
  188    -1                             "eql" => Token::Eql,
   -1    91                 lines.push((
   -1    92                     match op {
   -1    93                         "add" => Token::Add,
   -1    94                         "mul" => Token::Mul,
   -1    95                         "div" => Token::Div,
   -1    96                         "mod" => Token::Mod,
   -1    97                         "eql" => Token::Eql,
   -1    98                         _ => unreachable!(),
   -1    99                     },
   -1   100                     Token::Var(match a {
   -1   101                         "z" => 0,
   -1   102                         "y" => 1,
   -1   103                         "x" => 2,
   -1   104                         "w" => 3,
   -1   105                         _ => unreachable!(),
   -1   106                     }),
   -1   107                     match b.parse::<i64>() {
   -1   108                         Ok(bi) => Token::Int(bi),
   -1   109                         Err(_) => Token::Var(match b {
   -1   110                             "z" => 0,
   -1   111                             "y" => 1,
   -1   112                             "x" => 2,
   -1   113                             "w" => 3,
  189   114                             _ => unreachable!(),
  190    -1                         });
  191    -1                         new.push(Token::Var(s2c(a)));
  192    -1                         new.push(match b.parse::<i16>() {
  193    -1                             Ok(bi) => Token::Int(bi),
  194    -1                             Err(_) => Token::Var(s2c(b)),
  195    -1                         });
  196    -1                     } else {
  197    -1                         new.push(token);
  198    -1                     }
   -1   115                         }),
   -1   116                     },
   -1   117                 ));
   -1   118             },
   -1   119             _ => unreachable!(),
   -1   120         }
   -1   121     }
   -1   122 
   -1   123     return lines;
   -1   124 }
   -1   125 
   -1   126 fn foo(inputs: &[Option<i64>; 14], lines: &Vec<(Token, Token, Token)>) -> bool {
   -1   127     let mut mins = [0; 4];
   -1   128     let mut maxs = [0; 4];
   -1   129 
   -1   130     for line in lines.iter() {
   -1   131         match line {
   -1   132             (Token::Input(input), Token::Var(c), _) => {
   -1   133                 match inputs[*input as usize] {
   -1   134                     Some(value) => {
   -1   135                         mins[*c] = value;
   -1   136                         maxs[*c] = value;
   -1   137                     },
   -1   138                     None => {
   -1   139                         mins[*c] = 1;
   -1   140                         maxs[*c] = 9;
   -1   141                     },
   -1   142                 }
   -1   143             },
   -1   144             (op, Token::Var(c), b) => {
   -1   145                 let left_min = mins[*c];
   -1   146                 let left_max = maxs[*c];
   -1   147 
   -1   148                 let (right_min, right_max): (i64, i64) = match b {
   -1   149                     Token::Int(bi) => (*bi, *bi),
   -1   150                     Token::Var(bc) => (mins[*bc], maxs[*bc]),
   -1   151                     _ => unreachable!(),
   -1   152                 };
   -1   153 
   -1   154                 match op {
   -1   155                     Token::Add => {
   -1   156                         mins[*c] = left_min + right_min;
   -1   157                         maxs[*c] = left_max + right_max;
   -1   158                     },
   -1   159                     Token::Mul => {
   -1   160                         mins[*c] = *vec![left_min * right_min, left_max * right_min, left_min * right_max, left_min * right_min].iter().min().unwrap();
   -1   161                         maxs[*c] = *vec![left_min * right_min, left_max * right_min, left_min * right_max, left_min * right_min].iter().max().unwrap();
   -1   162                     },
   -1   163                     Token::Div => {
   -1   164                         mins[*c] = *vec![left_min / right_min, left_max / right_min, left_min / right_max, left_min / right_min].iter().min().unwrap();
   -1   165                         maxs[*c] = *vec![left_min / right_min, left_max / right_min, left_min / right_max, left_min / right_min].iter().max().unwrap();
   -1   166                     },
   -1   167                     Token::Mod => {
   -1   168                         if left_min == left_max && right_min == right_max {
   -1   169                             let v = left_min % right_min;
   -1   170                             mins[*c] = v;
   -1   171                             maxs[*c] = v;
   -1   172                         } else {
   -1   173                             mins[*c] = 0;
   -1   174                             maxs[*c] = right_max - 1;
   -1   175                         }
   -1   176                     },
   -1   177                     Token::Eql => {
   -1   178                         if left_min == left_max && right_min == right_max {
   -1   179                             let v = if left_min == right_min {1} else {0};
   -1   180                             mins[*c] = v;
   -1   181                             maxs[*c] = v;
   -1   182                         } else {
   -1   183                             mins[*c] = 0;
   -1   184                             maxs[*c] = 1;
   -1   185                         }
   -1   186                     },
   -1   187                     _ => unreachable!(),
  199   188                 }
  200    -1                 stack = new;
  201   189             },
  202   190             _ => unreachable!(),
  203   191         }
   -1   192     }
   -1   193 
   -1   194     return mins[0] <= 0 && maxs[0] >= 0;
   -1   195 }
  204   196 
  205    -1         stack = optimize(stack);
   -1   197 fn bar(i: usize, mut solution: &mut [Option<i64>; 14], lines: &Vec<(Token, Token, Token)>) -> bool {
   -1   198     if i == 5 {
   -1   199         println!("{:?}", solution);
   -1   200     }
   -1   201     for value in (1..=9).rev() {
   -1   202         solution[i] = Some(value);
   -1   203         if foo(solution, lines) {
   -1   204             if i == 13 {
   -1   205                 return true;
   -1   206             }
   -1   207             if bar(i + 1, solution, lines) {
   -1   208                 return true;
   -1   209             }
   -1   210         }
   -1   211     }
   -1   212     solution[i] = None;
   -1   213     return false;
   -1   214 }
  206   215 
  207    -1         // println!("{} {:?}", i, stack);
  208    -1         println!("{}", i);
  209    -1         // print_formular(&mut stack.iter());
  210    -1         // println!("");
   -1   216 fn main() {
   -1   217     let lines = get_data();
   -1   218     let mut solution = [None; 14];
   -1   219     bar(0, &mut solution, &lines);
   -1   220     for i in solution.iter() {
   -1   221         print!("{}", i.unwrap());
  211   222     }
   -1   223     println!("");
  212   224 }