this post was submitted on 05 Dec 2024
26 points (100.0% liked)

Advent Of Code

1012 readers
1 users here now

An unofficial home for the advent of code community on programming.dev!

Advent of Code is an annual Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

AoC 2024

Solution Threads

M T W T F S S
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

Rules/Guidelines

Relevant Communities

Relevant Links

Credits

Icon base by Lorc under CC BY 3.0 with modifications to add a gradient

console.log('Hello World')

founded 2 years ago
MODERATORS
 

Day 5: Print Queue

Megathread guidelines

  • 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

FAQ

(page 2) 7 comments
sorted by: hot top controversial new old
[โ€“] madmo@programming.dev 1 points 2 months ago

Rust

Used a sorted/unsorted comparison to solve the first part, the second part was just filling out the else branch.

use std::{
    cmp::Ordering,
    collections::HashMap,
    io::{BufRead, BufReader},
};

fn main() {
    let mut lines = BufReader::new(std::fs::File::open("input.txt").unwrap()).lines();

    let mut rules: HashMap<u64, Vec<u64>> = HashMap::default();

    for line in lines.by_ref() {
        let line = line.unwrap();

        if line.is_empty() {
            break;
        }

        let lr = line
            .split('|')
            .map(|el| el.parse::<u64>())
            .collect::<Result<Vec<u64>, _>>()
            .unwrap();

        let left = lr[0];
        let right = lr[1];

        if let Some(values) = rules.get_mut(&left) {
            values.push(right);
            values.sort();
        } else {
            rules.insert(left, vec![right]);
        }
    }

    let mut updates: Vec<Vec<u64>> = Vec::default();

    for line in lines {
        let line = line.unwrap();

        let update = line
            .split(',')
            .map(|el| el.parse::<u64>())
            .collect::<Result<Vec<u64>, _>>()
            .unwrap();

        updates.push(update);
    }

    let mut middle_sum = 0;
    let mut fixed_middle_sum = 0;

    for update in updates {
        let mut update_sorted = update.clone();
        update_sorted.sort_by(|a, b| {
            if let Some(rules) = rules.get(a) {
                if rules.contains(b) {
                    Ordering::Less
                } else {
                    Ordering::Equal
                }
            } else {
                Ordering::Equal
            }
        });

        if update.eq(&update_sorted) {
            let middle = update[(update.len() - 1) / 2];
            middle_sum += middle;
        } else {
            let middle = update_sorted[(update_sorted.len() - 1) / 2];
            fixed_middle_sum += middle;
        }
    }

    println!("part1: {} part2: {}", middle_sum, fixed_middle_sum);
}
[โ€“] JRaccoon@discuss.tchncs.de 1 points 2 months ago (2 children)

Java

Part 2 was an interesting one and my solution kinda feels like cheating. What I did I only changed the validation method from part 1 to return the indexes of incorrectly placed pages and then randomly swapped those around in a loop until the validation passed. I was expecting this to not work at all or take forever to run but surprisingly it only takes three to five seconds to complete.

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

public class Day05 {
    private static final Random random = new Random();

    public static void main(final String[] args) throws IOException {
        final String input = Files.readString(Path.of("2024\\05\\input.txt"), StandardCharsets.UTF_8);
        final String[] inputSplit = input.split("[\r\n]{4,}");

        final List<PageOrderingRule> rules = Arrays.stream(inputSplit[0].split("[\r\n]+"))
            .map(row -> row.split("\\|"))
            .map(row -> new PageOrderingRule(Integer.parseInt(row[0]), Integer.parseInt(row[1])))
            .toList();

        final List<ArrayList<Integer>> updates = Arrays.stream(inputSplit[1].split("[\r\n]+"))
            .map(row -> row.split(","))
            .map(row -> Arrays.stream(row).map(Integer::parseInt).collect(Collectors.toCollection(ArrayList::new)))
            .toList();

        System.out.println("Part 1: " + updates.stream()
            .filter(update -> validate(update, rules).isEmpty())
            .mapToInt(update -> update.get(update.size() / 2))
            .sum()
        );

        System.out.println("Part 2: " + updates.stream()
            .filter(update -> !validate(update, rules).isEmpty())
            .map(update -> fixOrder(update, rules))
            .mapToInt(update -> update.get(update.size() / 2))
            .sum()
        );
    }

    private static Set<Integer> validate(final List<Integer> update, final List<PageOrderingRule> rules) {
        final Set<Integer> invalidIndexes = new HashSet<>();

        for (int i = 0; i < update.size(); i++) {
            final Integer integer = update.get(i);
            for (final PageOrderingRule rule : rules) {
                if (rule.x == integer && update.contains(rule.y) && i > update.indexOf(rule.y)) {
                    invalidIndexes.add(i);
                }
                else if (rule.y == integer && update.contains(rule.x) && i < update.indexOf(rule.x)) {
                    invalidIndexes.add(i);
                }
            }
        }

        return invalidIndexes;
    }

    private static List<Integer> fixOrder(final List<Integer> update, final List<PageOrderingRule> rules) {
        List<Integer> invalidIndexesList = new ArrayList<>(validate(update, rules));

        // Swap randomly until the validation passes
        while (!invalidIndexesList.isEmpty()) {
            Collections.swap(update, random.nextInt(invalidIndexesList.size()), random.nextInt(invalidIndexesList.size()));
            invalidIndexesList = new ArrayList<>(validate(update, rules));
        }

        return update;
    }

    private static record PageOrderingRule(int x, int y) {}
}
load more comments (2 replies)
[โ€“] Hammerheart@programming.dev 1 points 2 months ago* (last edited 2 months ago)

Python

(Part 1) omg I can't believe this actually worked first try!

with open('input') as data:
    parts = data.read().rstrip().split("\n\n")
    ordering_rules = parts[0].split("\n")
    updates = parts[1].split("\n")

correct_updates = []
middle_updates = []

def find_relevant_rules(pg_num: str, rules: list[str]) -> list[str] | None:
    for rule in rules:
        return list(filter(lambda x: x.split("|")[0] == pg_num, rules))

def interpret_rule(rule: str) -> list[str]:
    return rule.split("|")

def interpret_update(update: str) -> list[str]:
    return update.split(",")

def find_middle_update_index(update: list[str]) -> int:
    num_of_elements = len(update)
    return num_of_elements // 2

for update in updates:
    is_correct = True
    for i, page in enumerate(interpret_update(update)):
       rules_to_check = find_relevant_rules(page, ordering_rules) 
       for rule in rules_to_check:
           if rule.split("|")[1] in interpret_update(update)[:i]:
               is_correct = False
    if is_correct:
        correct_updates.append(update)

for update in correct_updates:
    split_update = update.split(",")
    middle_updates.append(int(split_update[find_middle_update_index(split_update)]))
print(sum(middle_updates))
[โ€“] Leavingoldhabits@lemmy.world 1 points 2 months ago

Still in rust, and still inexperienced.

Forgot to make a separate solve for part two, for part one, imagine this without the make_valid function and some slightly different structure changes around the accumulator in babbage().

Used a hash map to track what should be in order, and a few indexed loops to keep track of where Iโ€™m at and where to look forward.

Day 5

[โ€“] sleeplessone@lemmy.ml 0 points 2 months ago

Rust

Kinda sorta got day 5 done on time.

use std::cmp::Ordering;

use crate::utils::{bytes_to_num, read_lines};

pub fn solution1() {
    let mut lines = read_input();
    let rules = parse_rules(&mut lines);

    let middle_rules_sum = lines
        .filter_map(|line| {
            let line_nums = rule_line_to_list(&line);
            line_nums
                .is_sorted_by(|&a, &b| is_sorted(&rules, (a, b)))
                .then_some(line_nums[line_nums.len() / 2])
        })
        .sum::<usize>();

    println!("Sum of in-order middle rules = {middle_rules_sum}");
}

pub fn solution2() {
    let mut lines = read_input();
    let rules = parse_rules(&mut lines);

    let middle_rules_sum = lines
        .filter_map(|line| {
            let mut line_nums = rule_line_to_list(&line);

            (!line_nums.is_sorted_by(|&a, &b| is_sorted(&rules, (a, b)))).then(|| {
                line_nums.sort_by(|&a, &b| {
                    is_sorted(&rules, (a, b))
                        .then_some(Ordering::Less)
                        .unwrap_or(Ordering::Greater)
                });

                line_nums[line_nums.len() / 2]
            })
        })
        .sum::<usize>();

    println!("Sum of middle rules = {middle_rules_sum}");
}

fn read_input() -> impl Iterator<Item = String> {
    read_lines("src/day5/input.txt")
}

fn parse_rules(lines: &mut impl Iterator<Item = String>) -> Vec<(usize, usize)> {
    lines
        .take_while(|line| !line.is_empty())
        .fold(Vec::new(), |mut rules, line| {
            let (a, b) = line.as_bytes().split_at(2);
            let a = bytes_to_num(a);
            let b = bytes_to_num(&b[1..]);

            rules.push((a, b));

            rules
        })
}

fn rule_line_to_list(line: &str) -> Vec<usize> {
    line.split(',')
        .map(|s| bytes_to_num(s.as_bytes()))
        .collect::<Vec<_>>()
}

fn is_sorted(rules: &[(usize, usize)], tuple: (usize, usize)) -> bool {
    rules.iter().any(|&r| r == tuple)
}

Reusing my bytes_to_num function from day 3 feels nice. Pretty fun challenge.

load more comments
view more: โ€น prev next โ€บ