Search code examples
javascriptstackiterationdepth-first-searchmaze

Iterative depth-first search to find longest path in JavaScript?


I'm a fairly beginner/novice JavaScript coder, without much CS/math experience, trying to program part of a web-based game to check for the "longest road" across all possible paths, e.g. the longest road score in Catan.

I've tried to do this using a probably-wrong implementation of an iterative depth-first search using a stack. It's supposed to walk each possible path, then when it hits a dead end, check whether the current path is longer than the previous longest path, and overwrite if so.

My code doesn't quite work, though; it doesn't seem to actually walk/check all possible paths when hitting intersections or other variations.

I have done all kinds of research into DFS and these kinds of algorithms and have had an extremely rough time trying to get my head around it; this is the closest I've come to something that works. I'm sure the code could be made more elegant via recursion or somesuch, but at this point I just want to understand why what I've written here isn't functional.

Relevant code below. I'm sure it's a mess in many different ways, but hopefully at least the function names and such are clear enough that this is enough context to figure out what's ultimately going wrong:

function walkAllPaths(node, network, t) {
    var stack = [ node ];
    var path = new Array();
    var visited = new Array();

    while (stack.length) {
        var curr = stack.pop();
        visited.push(curr);

        var moveNorth = myNeighbor(curr, "north");
        var moveSouth = myNeighbor(curr, "south");
        var moveWest = myNeighbor(curr, "west");
        var moveEast = myNeighbor(curr, "east");

        if (isValidMove(network, visited, t, moveNorth)) { stack.push(moveNorth); }
        else if (isValidMove(network, visited, t, moveWest)) { stack.push(moveWest); }
        else if (isValidMove(network, visited, t, moveSouth)) { stack.push(moveSouth); }
        else if (isValidMove(network, visited, t, moveEast)) { stack.push(moveEast); }

        else {
            if (visited.length > path.length) {
                path.length = 0;
                for (var i = 0; i < visited.length; i++) {
                    path.push(visited[i]);
                }
            }
            visited.pop();
        }
        console.log(visited);
    }

    return path;
}

Solution

  • I actually managed to figure out what was going on! I am still fairly positive that this is not at all an optimal solution, but it now does exactly what it's supposed to -- walk all valid paths and then return an array containing the longest path it walked. Here's the final code:

    function walkAllPaths(node, network, t) {
        var stack = [ node ];
        var path = [];
        var visited = [];
        var longPath = [];
    
        while (stack.length) {
            var curr = stack.pop();
    
            visited.push(curr);
            if (curr !== path[path.length - 1]) { path.push(curr); }
    
            var moveNorth = myNeighbor(curr, "north");
            var moveSouth = myNeighbor(curr, "south");
            var moveWest = myNeighbor(curr, "west");
            var moveEast = myNeighbor(curr, "east");
    
            if (isValidMove(network, visited, t, moveNorth)) { stack.push(moveNorth); }
            else if (isValidMove(network, visited, t, moveWest)) { stack.push(moveWest); }
            else if (isValidMove(network, visited, t, moveSouth)) { stack.push(moveSouth); }
            else if (isValidMove(network, visited, t, moveEast)) { stack.push(moveEast); }
            else {
                if (path.length > longPath.length) {
                    longPath.length = 0;
                    for (var i = 0; i < path.length; i++) {
                        longPath.push(path[i]);
                    }
                }
                path.pop();
                if (path.length) { stack.push(path[path.length - 1]); }
            }
        }
    
        return longPath;
    }
    

    Thanks to those who offered thoughts/suggestions!