Steve Klabnik

Apparently, the great eater-of-iron himself has graced us with his presence. Welcome, ‘Steve’, and thanks for your submissions!

steveklabnik/steveklabnik-day01.rs
steveklabnik/steveklabnik-day01.rs
fn solve(input: &str) -> (u32, u32) {
      let mut input: Vec<u32> = input.lines().map(|s| s.parse().unwrap()).collect();
      input.sort\_unstable();
    
      let solve\_a = |target, i| {
          input
              .iter()
              .skip(i)
              .copied()
              .take\_while(|&a| a < target)
              .enumerate()
              .find(|&(j, a)| input[i + j + 1..].binary\_search(&(target - a)).is\_ok())
              .map(|(\_, a)| a \* (target - a))
      };
    
      (
          solve\_a(2020, 0).unwrap(),
          input
              .iter()
              .copied()
              .enumerate()
              .filter\_map(|(i, a)| solve\_a(2020 - a, i + 1).map(|b| a \* b))
              .next()
              .unwrap()
      )
    }
    
steveklabnik/steveklabnik-day02.rs
steveklabnik/steveklabnik-day02.rs
macro\_rules! parse {
      ($input:ident, [$($split:literal),+], $($name:ident$(: $ty:ty)?),+) => {
          let mut iter = $input
              .split(|c| matches!(c, $($split)|+))
              .filter(|s| !s.is\_empty());
    
          $( let $name = iter.next().unwrap()$(.parse::<$ty>().unwrap())?; )+
      };
    }
    
    fn solve(input: &str) -> (u32, u32) {
      input.lines().fold((0, 0), |(a, b), s| {
          parse!(s, [&\#39; &\#39;, &\#39;-&\#39;, &\#39;:&\#39;], min: usize, max: usize, c: char, pass);
          let c = c as u8;
    
          (
              a + u32::from((min..=max).contains(&pass.bytes().filter(|&b| b == c).count())),
              b + u32::from((pass.as\_bytes()[min - 1] == c) ^ (pass.as\_bytes()[max - 1] == c))
          )
      })
    }
    
steveklabnik/steveklabnik-day03.rs
steveklabnik/steveklabnik-day03.rs
use std::iter::successors;
    
    fn solve(input: &str) -> (u32, u64) {
      let width = input.find(&\#39;\n&\#39;).unwrap();
      let height = input.len() / (width + 1);
      debug\_assert!(input.len() % (width + 1) == 0);
    
      let count\_trees = |dx, dy| {
          (0..height)
              .step\_by(dy)
              .zip(successors(Some(0), |x| Some((x + dx) % width)))
              .map(|(y, x)| u32::from(input.as\_bytes()[y \* (width + 1) + x] == b&\#39;\#&\#39;))
              .sum()
      };
    
      let counts = [
          count\_trees(1, 1),
          count\_trees(3, 1),
          count\_trees(5, 1),
          count\_trees(7, 1),
          count\_trees(1, 2)
      ];
    
      (counts[1], counts.iter().copied().map(u64::from).product())
    }
    
steveklabnik/steveklabnik-day04.rs
steveklabnik/steveklabnik-day04.rs
use std::ops::RangeInclusive;
    
    fn solve(input: &str) -> (u32, u32) {
      input.split("\n\n").fold((0, 0), |(a, b), s| {
          let (keys, valid) = s
              .split\_whitespace()
              .map(|s| {
                  let (k, v) = s.split\_at(4);
    
                  match k {
                      "byr:" => (1 << 0, check\_number(v, 4, 1920..=2002)),
                      "iyr:" => (1 << 1, check\_number(v, 4, 2010..=2020)),
                      "eyr:" => (1 << 2, check\_number(v, 4, 2020..=2030)),
                      "hgt:" => {
                          (
                              1 << 3,
                              v.strip\_suffix("cm")
                                  .map(|v| check\_number(v, 3, 150..=193))
                                  .xor(v.strip\_suffix("in").map(|v| check\_number(v, 2, 59..=76)))
                                  .unwrap\_or(false)
                          )
                      }
                      "hcl:" => {
                          (
                              1 << 4,
                              v.strip\_prefix("\#").map\_or(false, |v| {
                                  v.len() == 6 && u32::from\_str\_radix(&v[1..], 16).is\_ok()
                              })
                          )
                      }
                      "ecl:" => {
                          (
                              1 << 5,
                              matches!(v, "amb" | "blu" | "brn" | "gry" | "grn" | "hzl" | "oth")
                          )
                      }
                      "pid:" => (1 << 6, v.len() == 9 && v.parse::<u32>().is\_ok()),
                      "cid:" => (0, true),
                      \_ => (0, false)
                  }
              })
              .fold((0, true), |(keys, valid), (k, v)| (keys | k, valid && v));
    
          let all\_fields = keys == 0b0111\_1111;
    
          (
              a + u32::from(all\_fields),
              b + u32::from(all\_fields && valid)
          )
      })
    }
    
    fn check\_number(s: &str, len: usize, range: RangeInclusive<u32>) -> bool {
      s.len() == len && s.parse().map\_or(false, |i| range.contains(&i))
    }
    
steveklabnik/steveklabnik-day05.rs
steveklabnik/steveklabnik-day05.rs
fn solve(input: &str) -> (u32, u32) {
      let (min, max, sum) = input
          .lines()
          .map(|s| {
              s.bytes()
                  .fold(0, |acc, b| (acc << 1) | u32::from(b == b&\#39;B&\#39; || b == b&\#39;R&\#39;))
          })
          .fold((!0, 0, 0), |(min, max, sum), id| {
              (min.min(id), max.max(id), sum ^ id)
          });
    
      (max, cum\_xor(max) ^ cum\_xor(min - 1) ^ sum)
    }
    
    fn cum\_xor(a: u32) -> u32 {
      [a, 1, a + 1, 0][a as usize % 4]
    }
    
steveklabnik/steveklabnik-day06.rs
steveklabnik/steveklabnik-day06.rs
fn solve(input: &str) -> (u32, u32) {
      input
          .split("\n\n")
          .map(|s| {
              s.lines()
                  .map(|s| s.bytes().fold(0\_u32, |acc, b| acc | (1 << (b - b&\#39;a&\#39;))))
                  .fold((0, !0), |(a, b), i| (a | i, b & i))
          })
          .fold((0, 0), |(aa, ab), (a, b)| {
              (aa + a.count\_ones(), ab + b.count\_ones())
          })
    }
    
steveklabnik/steveklabnik-day07.rs
steveklabnik/steveklabnik-day07.rs
use std::collections::{HashMap, HashSet};
    
    fn solve(input: &str) -> (u32, u32) {
      let mut graph: HashMap<\_, Vec<\_>> = Default::default();
      let mut graph2: HashMap<\_, Vec<\_>> = Default::default();
    
      for s in input.lines() {
          let (outer, s) = s.split\_at(s.find(" bags").unwrap());
          let s = &s[14..];
    
          if s != "no other bags." {
              for s in s.split(&\#39;,&\#39;).map(str::trim\_start) {
                  let (count, s) = s.split\_at(s.find(&\#39; &\#39;).unwrap());
                  let count = count.parse().unwrap();
                  let (inner, \_) = s.split\_at(s.rfind(&\#39; &\#39;).unwrap());
                  let inner = inner.trim();
    
                  graph.entry(outer).or\_default().push((inner, count));
                  graph2.entry(inner).or\_default().push((outer, 1));
              }
          }
      }
    
      (
          dfs(&graph2, &mut Some(HashSet::new()), "shiny gold"),
          dfs(&graph, &mut None, "shiny gold")
      )
    }
    
    fn dfs<&\#39;a>(
      graph: &HashMap<&str, Vec<(&&\#39;a str, u32)>>,
      visited: &mut Option<HashSet<&&\#39;a str>>,
      from: &str
    ) -> u32 {
      graph.get(&from).map\_or(0, |tos| {
          let mut count = 0;
    
          for &(to, c) in tos {
              if visited.as\_mut().map\_or(true, |v| v.insert(to)) {
                  count += c + c \* dfs(graph, visited, to);
              }
          }
    
          count
      })
    }
    
steveklabnik/steveklabnik-day08.rs
steveklabnik/steveklabnik-day08.rs
\#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    enum Op {
      Nop,
      Jmp,
      Acc
    }
    
    fn solve(input: &str) -> (i32, i32) {
      let ops: Vec<\_> = input
          .lines()
          .map(|s| {
              let arg = s[4..].parse().unwrap();
    
              match &s[..3] {
                  "nop" => (Op::Nop, arg),
                  "jmp" => (Op::Jmp, arg),
                  "acc" => (Op::Acc, arg),
                  \_ => unreachable!()
              }
          })
          .collect();
    
      let b = (0..ops.len())
          .filter(|&i| ops[i].0 != Op::Acc)
          .map(|i| {
              let mut ops = ops.clone();
              let op = &mut ops[i].0;
              \*op = if \*op == Op::Nop { Op::Jmp } else { Op::Nop };
              ops
          })
          .filter\_map(|ops| run(&ops).ok())
          .next()
          .unwrap();
    
      (run(&ops).unwrap\_err(), b)
    }
    
    fn run(ops: &[(Op, i32)]) -> Result<i32, i32> {
      let mut set = vec![false; ops.len()];
      let mut pc: u32 = 0;
      let mut acc = 0;
    
      while !std::mem::replace(&mut set[pc as usize], true) {
          match ops[pc as usize] {
              (Op::Nop, \_) => pc += 1,
              (Op::Jmp, arg) => pc = ((pc as i32) + arg) as u32,
              (Op::Acc, arg) => {
                  acc += arg;
                  pc += 1;
              }
          }
    
          if pc as usize == ops.len() {
              return Ok(acc);
          }
      }
    
      Err(acc)
    }
    
steveklabnik/steveklabnik-day09.rs
steveklabnik/steveklabnik-day09.rs
fn solve(input: &str) -> (u64, u64) {
      let numbers: Vec<\_> = input.lines().map(|s| s.parse().unwrap()).collect();
    
      let a = numbers
          .windows(26)
          .map(|w| (&w[..25], w[25]))
          .find(|&(preamble, target)| {
              let mut iter = preamble.iter().copied();
    
              while let Some(a) = iter.next() {
                  if iter.clone().any(|b| a + b == target) {
                      return false;
                  }
              }
    
              true
          })
          .map(|(\_, n)| n)
          .unwrap();
    
      let mut stack = VecDeque::new();
      let mut sum = 0;
    
      numbers
          .iter()
          .find(|&&n| {
              stack.push\_back(n);
              sum += n;
    
              while sum > a {
                  sum -= stack.pop\_front().unwrap();
              }
    
              sum == a
          })
          .unwrap();
    
      let b = stack
          .iter()
          .fold((!0, 0), |(a, b), &n| (a.min(n), b.max(n)));
    
      (a, b.0 + b.1)
    }
    
steveklabnik/steveklabnik-day10.rs
steveklabnik/steveklabnik-day10.rs
fn solve(input: &str) -> (u32, u64) {
      let mut adapters: Vec<usize> = input.lines().map(|s| s.parse().unwrap()).collect();
      adapters.sort\_unstable();
      let max = adapters.last().unwrap() + 3;
      adapters.push(max);
    
      let mut last = 0;
      let mut count = vec![0; max + 1];
      count[0] = 1;
    
      let a = adapters
          .iter()
          .inspect(|&&n| {
              count[n] = (1..=3)
                  .filter\_map(|d| n.checked\_sub(d).map(|n| count[n]))
                  .sum()
          })
          .map(|&n| n - std::mem::replace(&mut last, n))
          .fold((0, 0), |(a, b), d| {
              (a + u32::from(d == 1), b + u32::from(d == 3))
          });
    
      (a.0 \* a.1, count[max])
    }
    

Tags: