aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2022/04/solver.lisp
blob: bcf37d7c90bca103522c2e095e21e89e556914ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(ql:quickload '(:fiveam :uiop))

(defun subinterval (a0 a1 b0 b1)
  "Test if [b0;b1] within [a0;a1]"
  (and (<= a0 b0 ) (>= a1 b1)))

(defun subcontained (a0 a1 b0 b1)
  (or (subinterval a0 a1 b0 b1)
      (subinterval b0 b1 a0 a1)))

(defun overlap (a0 a1 b0 b1)
  "Test if [b0;b1] overlaps [a0;a1]"
  (and (<= a0 b1) (<= b0 a1)))

(defun sections-fulfills (function line)
  (apply function (mapcar #'parse-integer
                          (uiop:split-string line :separator '(#\, #\-)))))

(defun count-according (function)
  (with-open-file (in "input")
    (loop for l = (read-line in nil nil)
          while l
          count (sections-fulfills function l))))

(fiveam:test results
  (fiveam:is (= 515 (count-according #'subcontained)))
  (fiveam:is (= 883 (count-according #'overlap))))

(fiveam:run-all-tests)
Paper => 2, Hand::Scissors => 3, } } enum Conclusion { Loose, Draw, Win, } fn strategy(play: &str) -> Conclusion { match play { "X" => Conclusion::Loose, "Y" => Conclusion::Draw, "Z" => Conclusion::Win, &_ => panic!("Invalid input"), } } fn wins(play: Hand) -> Hand { match play { Hand::Rock => Hand::Scissors, Hand::Scissors => Hand::Paper, Hand::Paper => Hand::Rock, } } fn looses(play: Hand) -> Hand { match play { Hand::Scissors => Hand::Rock, Hand::Paper => Hand::Scissors, Hand::Rock => Hand::Paper, } } fn pick_move(strategy: Conclusion, other: Hand) -> Hand { match strategy { Conclusion::Draw => other, Conclusion::Win => looses(other), Conclusion::Loose => wins(other), } } fn fight(my: Hand, other: Hand) -> u32 { match (my, other) { (a, b) if a == b => 3, (a, b) => { if wins(a) == b { 6 } else { 0 } } } } fn fixed_plays(my: &str, _oponent: Hand) -> Hand { translate(my) } fn reactive_plays(my: &str, oponent: Hand) -> Hand { pick_move(strategy(my), oponent) } fn solver(strategy: &dyn Fn(&str, Hand) -> Hand) -> u32 { let file = fs::File::open("input").unwrap(); let lines = io::BufReader::new(file).lines(); lines.fold(0, |acc, line| { if let [ot, my] = line.unwrap().split_whitespace().collect::<Vec<_>>()[..] { let opo = translate(ot); let my_hand = strategy(my, opo.clone()); acc + fight(my_hand.clone(), opo) + weight(my_hand) } else { panic!("Wrong line") } }) } // Super simple strategies fn fixed_plays2(line: &str) -> u32 { match line { "A X" => 3 + 1, // draw rock "A Y" => 6 + 2, // win paper "A Z" => 0 + 3, // loose scissors "B X" => 0 + 1, // loose rock "B Y" => 3 + 2, // draw paper "B Z" => 6 + 3, // win scissors "C X" => 6 + 1, // win rock "C Y" => 0 + 2, // loose paper "C Z" => 3 + 3, // draw scissors &_ => panic!("Invalid play"), } } fn reactive_plays2(line: &str) -> u32 { match line { "A X" => 0 + 3, // loose scissors "A Y" => 3 + 1, // draw paper "A Z" => 6 + 2, // win "B X" => 0 + 1, // loose "B Y" => 3 + 2, // draw "B Z" => 6 + 3, // win "C X" => 0 + 2, // loose "C Y" => 3 + 3, // draw "C Z" => 6 + 1, // win &_ => panic!("Invalid play"), } } fn solver2(strategy: &dyn Fn(&str) -> u32) -> u32 { let file = fs::File::open("input").unwrap(); io::BufReader::new(file) .lines() .map(|x| strategy(&x.unwrap())) .sum() } fn main() { assert_eq!(12535, solver(&fixed_plays)); assert_eq!(15457, solver(&reactive_plays)); assert_eq!(12535, solver2(&fixed_plays2)); assert_eq!(15457, solver2(&reactive_plays2)); println!("All test passed.") }