hades

joined 1 year ago
MODERATOR OF
[–] hades@programming.dev 1 points 9 months ago

I don't think there's such a thing as a "spirit of the question", but you're free to set your own challenges of course :)

[–] hades@programming.dev 2 points 9 months ago (1 children)

ah, uiua, the only thing that makes me wish Unicode hadn't been invented :)

[–] hades@programming.dev 2 points 9 months ago

Rust

pub fn solve_part_1(input: &str) -> String {
    let numbers: Vec<i32> = input.split(",").map(|x| x.parse().unwrap()).collect();
    let mut count = 0;
    for i in 1..numbers.len() {
        if numbers[i].abs_diff(numbers[i - 1]) == 16 {
            count += 1;
        }
    }
    count.to_string()
}

pub fn solve_part_2(input: &str) -> String {
    let numbers: Vec<i32> = input.split(",").map(|x| x.parse().unwrap()).collect();
    let mut lines: Vec<(i32, i32)> = vec![];
    for i in 1..numbers.len() {
        let (a, b) = (numbers[i - 1], numbers[i]);
        if a > b {
            lines.push((b, a));
        } else {
            lines.push((a, b));
        }
    }
    let mut knots = 0;
    for i in 0..lines.len() {
        for j in 0..i {
            let (a, b) = lines[i];
            let (c, d) = lines[j];
            if a == c || a == d || b == c || b == d {
                continue;
            }
            let c_inside = c > a && c < b;
            let d_inside = d > a && d < b;
            if c_inside != d_inside {
                knots += 1;
            }
        }
    }
    knots.to_string()
}

pub fn solve_part_3(input: &str) -> String {
    let numbers: Vec<i32> = input.split(",").map(|x| x.parse().unwrap()).collect();
    let mut lines: Vec<(i32, i32)> = vec![];
    for i in 1..numbers.len() {
        let (a, b) = (numbers[i - 1], numbers[i]);
        if a > b {
            lines.push((b, a));
        } else {
            lines.push((a, b));
        }
    }
    let mut best_cut_threads = i64::MIN;
    for d in 1..=256 {
        for c in 1..d {
            let mut cut_threads = 0;
            for (a, b) in lines.iter().copied() {
                if a == c || a == d || b == c || b == d {
                    if a == c && b == d {
                        cut_threads += 1;
                    }
                    continue;
                }
                let c_inside = c > a && c < b;
                let d_inside = d > a && d < b;
                if c_inside != d_inside {
                    cut_threads += 1;
                }
            }
            if cut_threads > best_cut_threads {
                best_cut_threads = cut_threads;
            }
        }
    }
    best_cut_threads.to_string()
}
[–] hades@programming.dev 2 points 9 months ago

Rust

Technically you don't need to store the names in part 3, but I was too lazy.

use std::collections::{HashMap, HashSet};

pub fn solve_part_1(input: &str) -> String {
    let (names, rules) = input.split_once("\n\n").unwrap();
    let names: Vec<&str> = names.split(",").collect();
    let rules: HashMap<char, HashSet<char>> = rules
        .lines()
        .map(|line| {
            let (from, to) = line.split_once(" > ").unwrap();
            let to = to.split(",");
            (
                from.chars().next().unwrap(),
                to.map(|s| s.chars().next().unwrap()).collect(),
            )
        })
        .collect();
    for name in names {
        let mut allowed_chars = rules.get(&name.chars().next().unwrap());
        let mut acceptable = true;
        for ch in name.chars().skip(1) {
            match allowed_chars {
                Some(allowed) => {
                    if !allowed.contains(&ch) {
                        acceptable = false;
                        break;
                    }
                    allowed_chars = rules.get(&ch);
                }
                None => {
                    panic!("no rules for letter {ch} in name {name}");
                }
            }
        }
        if acceptable {
            return name.to_string();
        }
    }
    panic!("all names bad");
}

pub fn solve_part_2(input: &str) -> String {
    let (names, rules) = input.split_once("\n\n").unwrap();
    let names: Vec<&str> = names.split(",").collect();
    let rules: HashMap<char, HashSet<char>> = rules
        .lines()
        .map(|line| {
            let (from, to) = line.split_once(" > ").unwrap();
            let to = to.split(",");
            (
                from.chars().next().unwrap(),
                to.map(|s| s.chars().next().unwrap()).collect(),
            )
        })
        .collect();
    let mut sum_of_indices = 0;
    for (i, name) in names.into_iter().enumerate() {
        let mut allowed_chars = rules.get(&name.chars().next().unwrap());
        let mut acceptable = true;
        for ch in name.chars().skip(1) {
            match allowed_chars {
                Some(allowed) => {
                    if !allowed.contains(&ch) {
                        acceptable = false;
                        break;
                    }
                    allowed_chars = rules.get(&ch);
                }
                None => {
                    panic!("no rules for letter {ch} in name {name}");
                }
            }
        }
        if acceptable {
            sum_of_indices += 1 + i;
        }
    }
    sum_of_indices.to_string()
}

fn gen_names_with_prefix(
    prefix: &str,
    rules: &HashMap<char, HashSet<char>>,
    result: &mut HashSet<String>,
) {
    if prefix.len() >= 7 {
        result.insert(prefix.to_string());
    }
    if prefix.len() == 11 {
        return;
    }
    let last_char = prefix.chars().last().unwrap();
    if let Some(next_chars) = rules.get(&last_char) {
        for next_char in next_chars {
            let new_prefix = format!("{prefix}{next_char}");
            gen_names_with_prefix(new_prefix.as_str(), rules, result);
        }
    }
}

pub fn solve_part_3(input: &str) -> String {
    let (prefix, rules) = input.split_once("\n\n").unwrap();
    let prefixes: Vec<_> = prefix.split(",").collect();
    let rules: HashMap<char, HashSet<char>> = rules
        .lines()
        .map(|line| {
            let (from, to) = line.split_once(" > ").unwrap();
            let to = to.split(",");
            (
                from.chars().next().unwrap(),
                to.map(|s| s.chars().next().unwrap()).collect(),
            )
        })
        .collect();
    let mut results: HashSet<String> = HashSet::new();
    prefixes
        .into_iter()
        .filter(|&name| {
            let mut allowed_chars = rules.get(&name.chars().next().unwrap());
            let mut acceptable = true;
            for ch in name.chars().skip(1) {
                match allowed_chars {
                    Some(allowed) => {
                        if !allowed.contains(&ch) {
                            acceptable = false;
                            break;
                        }
                        allowed_chars = rules.get(&ch);
                    }
                    None => {
                        panic!("no rules for letter {ch} in name {name}");
                    }
                }
            }
            acceptable
        })
        .for_each(|prefix| gen_names_with_prefix(prefix, &rules, &mut results));
    results.len().to_string()
}
[–] hades@programming.dev 3 points 9 months ago

Rust

use std::collections::HashMap;
use itertools::Itertools;

pub fn solve_part_1(input: &str) -> String {
    let mut mentors = 0;
    let mut pairs = 0;
    for ch in input.chars() {
        match ch {
            'A' => mentors += 1,
            'a' => pairs += mentors,
            _ => {}
        }
    }
    pairs.to_string()
}

pub fn solve_part_2(input: &str) -> String {
    let mut mentors: HashMap<char, i64> = HashMap::new();
    let mut pairs = 0;
    for ch in input.chars() {
        match ch {
            'A'..='Z' => *mentors.entry(ch).or_default() += 1,
            'a'..='z' => pairs += *mentors.entry(ch.to_ascii_uppercase()).or_default(),
            _ => panic!("unexpected character {ch}"),
        }
    }
    pairs.to_string()
}

pub fn solve_part_3(input: &str) -> String {
    let data: Vec<_> = input.chars().collect();
    let len = data.len();
    let mentors: HashMap<char, Vec<usize>> = data
        .iter()
        .enumerate()
        .map(|(i, ch)| (*ch, i))
        .into_group_map();
    let mut pairs: i64 = 0;
    for (squire_position, ch) in data.into_iter().enumerate() {
        if ch.is_ascii_lowercase() {
            for mentor_position in mentors.get(&ch.to_ascii_uppercase()).unwrap() {
                if squire_position.abs_diff(*mentor_position) <= 1000 {
                    pairs += 1000;
                } else if (squire_position as isize)
                    .wrapping_sub_unsigned(len)
                    .abs_diff(*mentor_position as isize)
                    <= 1000
                    || (*mentor_position as isize)
                        .wrapping_sub_unsigned(len)
                        .abs_diff(squire_position as isize)
                        <= 1000
                {
                    pairs += 999;
                }
            }
        }
    }
    pairs.to_string()
}
[–] hades@programming.dev 3 points 9 months ago

Rust

use itertools::Itertools;

type Fishbone = Vec<(i64, Option<i64>, Option<i64>)>;

fn parse_fishbone(quality_str: &str) -> Fishbone {
    let mut fishbone: Fishbone = vec![];
    'outer: for num in quality_str.split(",").map(|x| x.parse().unwrap()) {
        for e in fishbone.iter_mut() {
            if num < e.0 && e.1.is_none() {
                e.1 = Some(num);
                continue 'outer;
            }
            if num > e.0 && e.2.is_none() {
                e.2 = Some(num);
                continue 'outer;
            }
        }
        fishbone.push((num, None, None));
    }
    fishbone
}

fn compute_quality(fishbone: &Fishbone) -> i64 {
    fishbone
        .iter()
        .map(|(c, _, _)| c.to_string())
        .join("")
        .parse()
        .unwrap()
}

pub fn solve_part_1(input: &str) -> String {
    let (_, data) = input.split_once(":").unwrap();
    compute_quality(&parse_fishbone(data)).to_string()
}

pub fn solve_part_2(input: &str) -> String {
    let mut worst_quality = i64::MAX;
    let mut best_quality = i64::MIN;
    for sword in input.lines() {
        let (_, data) = sword.split_once(":").unwrap();
        let quality = compute_quality(&parse_fishbone(data));
        worst_quality = worst_quality.min(quality);
        best_quality = best_quality.max(quality);
    }
    (best_quality - worst_quality).to_string()
}

pub fn solve_part_3(input: &str) -> String {
    let mut swords: Vec<_> = input
        .lines()
        .map(|def| {
            let (id, data) = def.split_once(":").unwrap();
            let fishbone = parse_fishbone(data);
            (id.parse::<i64>().unwrap(), fishbone)
        })
        .collect();
    swords.sort_by(|a, b| {
        let cmp = compute_quality(&a.1).cmp(&compute_quality(&b.1));
        if !matches!(cmp, std::cmp::Ordering::Equal) {
            return cmp;
        }
        for (a_seg, b_seg) in a.1.iter().zip(b.1.iter()) {
            let a_val = match a_seg {
                (a, Some(b), Some(c)) => format!("{b}{a}{c}"),
                (a, Some(b), None) => format!("{b}{a}"),
                (a, None, Some(c)) => format!("{a}{c}"),
                (a, None, None) => format!("{a}"),
            };
            let b_val = match b_seg {
                (a, Some(b), Some(c)) => format!("{b}{a}{c}"),
                (a, Some(b), None) => format!("{b}{a}"),
                (a, None, Some(c)) => format!("{a}{c}"),
                (a, None, None) => format!("{a}"),
            };
            let cmp = a_val.parse::<i64>().unwrap().cmp(&b_val.parse().unwrap());
            if !matches!(cmp, std::cmp::Ordering::Equal) {
                return cmp;
            }
        }
        a.0.cmp(&b.0)
    });
    swords.reverse();
    swords
        .into_iter()
        .enumerate()
        .map(|(pos, (id, _))| id * (pos as i64 + 1))
        .sum::<i64>()
        .to_string()
}
[–] hades@programming.dev 2 points 9 months ago

Rust

use num::{BigInt, Integer};

pub fn solve_part_1(input: &str) -> String {
    let gears: Vec<i64> = input.trim().lines().map(|g| g.parse().unwrap()).collect();
    (2025 * gears[0] / gears.last().unwrap()).to_string()
}

pub fn solve_part_2(input: &str) -> String {
    let gears: Vec<i64> = input.trim().lines().map(|g| g.parse().unwrap()).collect();
    let res = (BigInt::parse_bytes(b"10000000000000", 10).unwrap() * gears.last().unwrap())
        .div_ceil(&(BigInt::ZERO + gears[0]));
    res.to_string()
}

pub fn solve_part_3(input: &str) -> String {
    let mut lines = input.trim().lines();
    let first_gear = BigInt::parse_bytes(lines.next().unwrap().as_bytes(), 10).unwrap();
    let mut nominator: BigInt = first_gear * 100;
    let mut denominator: BigInt = BigInt::ZERO + 1;
    for line in lines {
        let mut split = line.split("|");
        denominator *= BigInt::parse_bytes(split.next().unwrap().as_bytes(), 10).unwrap();
        match split.next() {
            Some(size) => {
                nominator *= BigInt::parse_bytes(size.as_bytes(), 10).unwrap();
            }
            None => {
                break;
            }
        }
    }
    (nominator / denominator).to_string()
}
[–] hades@programming.dev 2 points 9 months ago

Rust

pub fn solve_part_1(input: &str) -> String {
    let mut crates: Vec<i64> = input.split(",").map(|s| s.parse().unwrap()).collect();
    crates.sort();
    let mut monotonic_subsequence = vec![crates[0]];
    for size in crates.into_iter().skip(1) {
        if size == *monotonic_subsequence.last().unwrap() {
            continue;
        }
        monotonic_subsequence.push(size);
    }
    monotonic_subsequence.iter().sum::<i64>().to_string()
}

pub fn solve_part_2(input: &str) -> String {
    let mut crates: Vec<i64> = input.split(",").map(|s| s.parse().unwrap()).collect();
    crates.sort();
    let mut monotonic_subsequence = vec![crates[0]];
    for size in crates.into_iter().skip(1) {
        if size == *monotonic_subsequence.last().unwrap() {
            continue;
        }
        monotonic_subsequence.push(size);
        if monotonic_subsequence.len() >= 20 {
            break;
        }
    }
    monotonic_subsequence.iter().sum::<i64>().to_string()
}

pub fn solve_part_3(input: &str) -> String {
    let mut crates: Vec<i64> = input.split(",").map(|s| s.parse().unwrap()).collect();
    crates.sort();
    let mut monotonic_subsequences = vec![vec![crates[0]]];
    for size in crates.into_iter().skip(1) {
        let updateable_sequence = monotonic_subsequences
            .iter_mut()
            .find(|v| *v.last().unwrap() < size);
        match updateable_sequence {
            Some(v) => {
                v.push(size);
            }
            None => {
                monotonic_subsequences.push(vec![size]);
            }
        }
    }
    monotonic_subsequences.len().to_string()
}
[–] hades@programming.dev 3 points 9 months ago

Rust

use log::debug;
use std::collections::HashSet;

use regex::Regex;

#[derive(PartialEq, Eq, Hash, Clone)]
struct Number(isize, isize);

impl Number {

  fn add(self: &Number, b: &Number) -> Number {
    Number(self.0 + b.0, self.1 + b.1)
  }

  fn mul(self: &Number, b: &Number) -> Number {
    Number(self.0 * b.0 - self.1 * b.1, self.0 * b.1 + self.1 * b.0)
  }

  fn div(self: &Number, b: &Number) -> Number {
    Number(self.0 / b.0, self.1 / b.1)
  }
}

pub fn solve_part_1(input: &str) -> String {
  let re = Regex::new(r"A=\[(\d+),(\d+)\]").unwrap();
  let (_, [x, y]) = re.captures(input).unwrap().extract();
  let a = Number(x.parse().unwrap(), y.parse().unwrap());
  let mut res = Number(0, 0);
  for _ in 0..3 {
    res = res.mul(&res);
    res = res.div(&Number(10, 10));
    res = res.add(&a);
  }
  format!("[{},{}]", res.0, res.1)
}

pub fn solve_part_2(input: &str) -> String {
  let re = Regex::new(r"A=\[([-0-9]+),([-0-9]+)\]").unwrap();
  let (_, [x, y]) = re.captures(input).unwrap().extract();
  let a = Number(x.parse().unwrap(), y.parse().unwrap());
  let mut engraved_points = 0;
  let mut pts: HashSet<_> = HashSet::new();
  for i in 0..=100 {
    for j in 0..=100 {
      let pt = Number(a.0 + 10 * i, a.1 + 10 * j);
      let mut res = Number(0, 0);
      engraved_points += 1;
      pts.insert(pt.clone());
      for _ in 0..100 {
        res = res.mul(&res);
        res = res.div(&Number(100_000, 100_000));
        res = res.add(&pt);
        if res.0.abs() > 1_000_000 || res.1.abs() > 1_000_000 {
          engraved_points -= 1;
          pts.remove(&pt);
          break;
        }
      }
    }
  }
  for i in 0..=100 {
    debug!("{}", (0..=100).map(|j| if pts.contains(&Number(a.0 + 10*i, a.1 + 10*j)) { 'X' } else {'.'}).collect::<String>());
  }
  engraved_points.to_string()
}

pub fn solve_part_3(input: &str) -> String {
  let re = Regex::new(r"A=\[([-0-9]+),([-0-9]+)\]").unwrap();
  let (_, [x, y]) = re.captures(input).unwrap().extract();
  let a = Number(x.parse().unwrap(), y.parse().unwrap());
  let mut engraved_points = 0;
  for i in 0..=1000 {
    for j in 0..=1000 {
      let pt = Number(a.0 + i, a.1 + j);
      let mut res = Number(0, 0);
      engraved_points += 1;
      for _ in 0..100 {
        res = res.mul(&res);
        res = res.div(&Number(100_000, 100_000));
        res = res.add(&pt);
        if res.0.abs() > 1_000_000 || res.1.abs() > 1_000_000 {
          engraved_points -= 1;
          break;
        }
      }
    }
  }
  engraved_points.to_string()
}
[–] hades@programming.dev 15 points 9 months ago

Just an ad article. "Did you also encounter skill issues while building web applications? Try my platform."

[–] hades@programming.dev 11 points 10 months ago

but how many COMEFROMs are there

[–] hades@programming.dev 2 points 1 year ago

imagine the diffs

view more: β€Ή prev next β€Ί