Quest 5: Fishbone Order

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

Link to participate: https://everybody.codes/

you are viewing a single comment's thread
view the rest of the comments
[โ€“] [S] 3 points 1 year 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()
}
  • source