vilcans

joined 1 year ago
[–] vilcans 1 points 11 months ago

Thanks for the answer! What you're saying seems to be true, but it wasn't given in the instructions, so I guess you were supposed to figure out that this was the case. It seems this was true for everyone, so it wasn't just me that got lucky. I got confused by my assertion failing on the example, because the second path reaches the goal in three steps which is not a multiple of the instruction length (2). This never happens with the real data. The example wraps around neatly at 6 instead, so just removing the assertion makes my code work on the example too.

 

I had 6 parallel paths, and for all of them, the goal node was found at the point where the directions string repeated. So I actually only had to search each of the paths for the point where I was on the goal position and the first direction. This worked on the input data, but not the example. See the assert in the code, and note that the statement println!("Found non-repeat at {node} step {step} (num dirs {num_directions})"); is never executed.

At the end there's also the first attempt of brute-forcing the solution which seems like it would have taken nearly forever.

use std::collections::HashMap;

use regex::Regex;

use crate::input::Source;

pub fn execute(source: Source) -> impl std::fmt::Debug {
    let lines = source.lines();
    let ([directions], [empty, nodes @ ..]) = lines.split_at(1) else {
        panic!("Wrong format");
    };
    assert!(empty.is_empty());

    let node_re = Regex::new(r"(...) = \((...), (...)\)").unwrap();
    let nodes: HashMap = nodes
        .iter()
        .map(|line| {
            let caps = node_re.captures(line).unwrap();
            let name = caps[1].to_string();
            let left = caps[2].to_string();
            let right = caps[3].to_string();
            (name, (left, right))
        })
        .collect();

    let start_nodes: Vec = nodes.keys().filter(|n| n.ends_with('A')).cloned().collect();
    let repeat_lengths: Vec = start_nodes
        .iter()
        .map(|node| {
            let (repeat_length, goal_steps) = find_repeats(node, directions, &nodes);
            assert!(goal_steps.is_empty()); // not a given, but that's what the input looks like
            dbg!(node, repeat_length, goal_steps);
            repeat_length
        })
        .collect();

    repeat_lengths.iter().cloned().reduce(num::integer::lcm)
}

/// (repeat length, steps to goal node within repeat)
fn find_repeats(
    starting_node: &str,
    directions: &str,
    nodes: &HashMap,
) -> (usize, Vec) {
    let mut node = starting_node.to_string();
    let num_directions = directions.chars().count();
    let mut goals = Vec::new();
    for (step, dir) in directions.chars().cycle().enumerate() {
        if node.ends_with('Z') {
            if step % num_directions == 0 {
                println!("Found repeat at {node} step {step} (num dirs {num_directions})");
                return (step, goals);
            }
            println!("Found non-repeat at {node} step {step} (num dirs {num_directions})");
            goals.push(step);
        }
        let (left, right) = &nodes[&node];
        node = match dir {
            'L' => left.clone(),
            'R' => right.clone(),
            other => panic!("Unknown dir {other}"),
        }
    }
    unreachable!()
}

// too slow
#[allow(dead_code)]
fn find_parallel(
    start_nodes: &[String],
    directions: &str,
    nodes: &HashMap,
) -> usize {
    let mut current_nodes = start_nodes.to_vec();
    for (step, dir) in directions.chars().cycle().enumerate() {
        if current_nodes.iter().all(|n| n.ends_with('Z')) {
            return step;
        }
        for node in current_nodes.iter_mut() {
            let (left, right) = nodes[node].clone();
            *node = match dir {
                'L' => left,
                'R' => right,
                other => panic!("Unknown dir {other}"),
            }
        }
    }
    unreachable!()
}
[–] vilcans 11 points 1 year ago (1 children)

It sounds like you have the mindset that you have to learn programming before you start doing it. Which is especially hard today as there's so much information, so much to learn, so many tutorials to watch. There's always something to learn. Don't expect to reach a point when you "know" programming.

Instead try this: Stop practicing and start programming. Start with a project that you want to do, for whatever reason. Some small utility, a really tiny game, a joke program, whatever that gets you to focus on creating something rather than learning something. You will learn the things you have to learn in order to progress on the project. This is completely normal, and a good skill to have, even for professional programmers.

[–] vilcans 2 points 1 year ago

One way to implement Rust-based "plugins" is to turn the whole application/plugins relation on its head: Publish the main application as a crate, which lets the user build their own executable that uses the main application as a library. That way they can customize the app however they like, if the main app just has hooks for it.

[–] vilcans 5 points 1 year ago

I use it from time to time. Often I test manually instead of automatic, and it often works very well.

But if you want a story about an unconventional use of git bisect, I think there's one about the time I had a directory with lots of files, and one of those files was causing some problem, but I didn't know which one it was. Those files were not under version control, but I created a repo with them, where each file was added in a separate commit. Then I could use git bisect to find which file was causing the problems.

[–] vilcans 1 points 1 year ago

Update: 0.18.0 fixed it.

[–] vilcans 1 points 1 year ago

Thanks, I hope 0.18 fixes it then. I tried logging in using another browser, and noticed that trying to log in gives the same infinite spinner. So it seems I can only use my account on the browser I'm on right now.

3
submitted 1 year ago* (last edited 1 year ago) by vilcans to c/meta
 

I registered on the web site today and then tried to log in on Jerboa, but it gives the Incorrect Login message. I figured maybe my first (autogenerated) password was too long or had invalid characters in it. So I've tried several times to change it, but neither the Change Password box in Settings nor reset password works. Both of them just changes the button to a spinner whenever I click it. What's up?

EDIT: It seems the same problem affects trying to log in (I'm still logged in on this browser, but I can't log in on any other). But it doesn't even seem to be specific to my user. No matter what username and password I give it, the button just keeps on spinning. Both on Firefox on Linux and Chrome on Android. So it should affect everyone. Strange.

EDIT 2: Logging in doesn't work on other servers running 0.17.4 (tried https://discuss.tchncs.de/login and https://sh.itjust.works/login).