view 12/12.jl @ 18:6ad216d8abee

Day 12 part 1
author Lewin Bormann <lbo@spheniscida.de>
date Wed, 14 Dec 2022 21:12:55 +0100
parents
children 9b6e6ace0e72
line wrap: on
line source


import DataStructures: PriorityQueue, enqueue!, dequeue!;

const test_input = "12/test_input.txt";
const input = "12/input.txt";

const START = -1;
const END = -2;

const MAX_DIFF = 1;

function read_map(fh::IOStream)::Matrix{Int}
    lines = readlines(fh);
    m = zeros(Int, length(lines), length(lines[1]));
    for (i, line) in enumerate(lines)
        for (j, char) in enumerate(line)
            m[i,j] = char - 'a';
            if char == 'E'
                m[i,j] = END;
            elseif char == 'S'
                m[i,j] = START;
            end
        end
    end
    m
end

function find_start_end(m::Matrix{Int})::Tuple{CartesianIndex, CartesianIndex}
    findnext((==)(START), m, CartesianIndex((1,1))), findnext((==)(END), m, CartesianIndex((1,1)))
end

function reconstruct_path(parents::Matrix{CartesianIndex{2}}, start::CartesianIndex, endd::CartesianIndex)::Vector{CartesianIndex}
    v = Vector{CartesianIndex}();
    current = endd;
    while current != start 
        push!(v, current);
        current = parents[(current)];
    end
    reverse!(v);
    v
end

function find_path(m::Matrix{Int})
    s, e = find_start_end(m);
    current_best = zeros(Int, size(m)) .+ 10000;
    parents = [CartesianIndex((-1,-1)) for i = 1:size(m, 1), j = 1:size(m, 2)];
    top = PriorityQueue{Tuple{CartesianIndex,Int}, Int}();
    enqueue!(top, (s, 0), 0);

    valid(x) = x[1] > 0 && x[1] <= size(m, 1) && x[2] > 0 && x[2] <= size(m, 2);

    while length(top) > 0
        (cb, dist) = dequeue!(top);
        for mov in [(0,1),(0,-1),(1,0),(-1,0)]
            nb = cb + CartesianIndex(mov);
            if !valid(nb)
                continue
            end
            if m[nb] == END && m[cb] >= 24
                parents[nb] = cb;
                return reconstruct_path(parents, s, nb)
            elseif m[nb] == END || (m[nb]-m[cb]) > 1
                continue;
            end
            if current_best[nb] > dist + 1
                current_best[nb] = dist + 1;
                parents[nb] = cb;
                enqueue!(top, (nb, dist + 1), dist + 1);
            end
        end
    end
    error("no path found!");
end

open(input; read=true) do fh
    m = read_map(fh);
    for c in eachrow(m)
        println(c);
    end
    @time p = find_path(m);
    println("PART 1: Path $p with length $(length(p))");
end