Im trying to code a lem-in project.
https://github.com/01-edu/public/tree/master/subjects/lem-in

Im coding in go lang. But its okay in another language tho. I can convert it to go. Me and my friends cant even solve the algorithm neither. ChatGPT is stuck and in the web i found a 800 rows of code. Its working but really hard to understand.

All the instructions/wanted thing in the link. And here is my code and output:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "math"
    "os"
    "strconv"
    "strings"
)

// Farm structure
type farm struct {
    antCount       int
    roomCoordinates [][]string // Two-column slice for room coordinates
    tunnels        []string
    startLine       int
    endLine         int
    startRoomNumber int
    endRoomNumber   int
}

type ant struct {
    roomNumber int
}

func parseInput(textfile string) (farm, error) {
    var farmInfo farm

    content, err := ioutil.ReadFile("examples/" + textfile)
    if err != nil {
        return farmInfo, err
    }

    lines := strings.Split(string(content), "\n")
    for i, line := range lines {
        if line == "##start" {
            farmInfo.startLine = i + 2
        } else if line == "##end" {
            farmInfo.endLine = i + 2
        } else if strings.Contains(line, "-") {
            farmInfo.tunnels = append(farmInfo.tunnels, line)
        } else if !strings.Contains(line, "#") && len(strings.Split(line, " ")) == 3 {
            // Create a two-column slice for room coordinates
            roomCoordinates := strings.Split(line, " ")
            farmInfo.roomCoordinates = append(farmInfo.roomCoordinates, roomCoordinates)
        } else if len(line) > 0 {
            farmInfo.antCount, err = strconv.Atoi(strings.Fields(line)[0])
            if err != nil {
                fmt.Println("Ant count not found")
            }
        } else if len(line) > 0 {
            farmInfo.startRoomNumber = i + 2
        }
    }

    if farmInfo.startLine == 0 || farmInfo.endLine == 0 {
        return farmInfo, fmt.Errorf("Start and/or end markers not found")
    }

    return farmInfo, nil
}

// Check if all ants have reached the destination
func allArrived(ants []ant, destinationRoom int) bool {
    for _, ant := range ants {
        if ant.roomNumber != destinationRoom {
            return false
        }
    }
    return true
}

// Make the ant follow the shortest path
func useShortestPath(ant *ant, tunnels []string, tunnelUsage map[string]bool) {
    // Get the current room number of the ant
    currentRoom := ant.roomNumber

    fmt.Printf("Ant's current position: %d\n", currentRoom)

    // Find accessible tunnels from the current room
    accessibleTunnels := make([]string, 0)
    for _, tunnel := range tunnels {
        rooms := strings.Split(tunnel, "-")
        startRoom, _ := strconv.Atoi(rooms[0])
        endRoom, _ := strconv.Atoi(rooms[1])
        if currentRoom == startRoom && !tunnelUsage[tunnel] {
            accessibleTunnels = append(accessibleTunnels, tunnel)
        } else if currentRoom == endRoom && !tunnelUsage[tunnel] {
            accessibleTunnels = append(accessibleTunnels, tunnel)
        }
    }

    fmt.Println("Accessible tunnels:", accessibleTunnels)

    // Find the shortest tunnel among the accessible ones
    shortestTunnel := ""
    shortestLength := math.MaxInt64
    for _, tunnel := range accessibleTunnels {
        rooms := strings.Split(tunnel, "-")
        startRoom, _ := strconv.Atoi(rooms[0])
        endRoom, _ := strconv.Atoi(rooms[1])
        length := abs(endRoom - startRoom)
        if length < shortestLength {
            shortestLength = length
            shortestTunnel = tunnel
        }
    }

    fmt.Println("Shortest tunnel:", shortestTunnel)

    // Use the shortest tunnel and update the ant's position
    if shortestTunnel != "" {
        rooms := strings.Split(shortestTunnel, "-")
        startRoom, _ := strconv.Atoi(rooms[0])
        endRoom, _ := strconv.Atoi(rooms[1])
        if currentRoom == startRoom {
            ant.roomNumber = endRoom
        } else if currentRoom == endRoom {
            ant.roomNumber = startRoom
        }
        tunnelUsage[shortestTunnel] = true

        fmt.Printf("Ant's new position: %d\n", ant.roomNumber)
    }
}

// Reverse the tunnel (end room -> start room)
func reverseTunnel(tunnel string) string {
    rooms := strings.Split(tunnel, "-")
    return rooms[1] + "-" + rooms[0]
}

// Get the absolute value
func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}

func main() {
    if len(os.Args) != 2 {
        fmt.Println("Usage: go run . <file_name>")
        os.Exit(1)
    }

    textfile := os.Args[1]

    farmInfo, err := parseInput(textfile)
    if err != nil {
        log.Fatal(err)
    }

    // Create ant structures
    ants := make([]ant, farmInfo.antCount)

    // Place the ants in the starting room
    for i := range ants {
        ants[i].roomNumber = farmInfo.startRoomNumber
    }

    // Create a map to track tunnel usage
    tunnelUsage := make(map[string]bool)
    for _, tunnel := range farmInfo.tunnels {
        tunnelUsage[tunnel] = false
    }

    // Move the ants until they reach the destination room
    destinationRoom := farmInfo.endRoomNumber
    for !allArrived(ants, destinationRoom) {
        // Move each ant
        for i := range ants {
            // Check if the ant has reached the destination
            if ants[i].roomNumber != destinationRoom {
                // If not, make the ant follow the shortest path
                useShortestPath(&ants[i], farmInfo.tunnels, tunnelUsage)
            }
        }
    }

    // Print the final positions of the ants
    for i, ant := range ants {
        fmt.Printf("Ant %d's position: %d\n", i+1, ant.roomNumber)
    }

    // You can use the data from parseInput function here
    fmt.Println("Ant Count:", farmInfo.antCount)
    fmt.Println("Start Line:", farmInfo.startLine)
    fmt.Println("End Line:", farmInfo.endLine)
    fmt.Println("Room Coordinates:")
    for _, room := range farmInfo.roomCoordinates {
        fmt.Println(room[1], room[2]) // Print the two-column room coordinates
    }
    fmt.Println("Tunnels:", farmInfo.tunnels)

    // Print the path the ants should take
    fmt.Println("Path the ants should take:")
    for i, ant := range ants {
        path := ""
        for j := 1; j <= i; j++ {
            path += fmt.Sprintf("L%d-%d ", j, ant.roomNumber)
        }
        fmt.Println(path)
    }
}

`Ant 1's position: 0
Ant 2's position: 0
Ant 3's position: 0
Ant 4's position: 0
Ant Count: 4
Start Line: 3
End Line: 7
Room Coordinates:
0 3
2 5
4 0
8 3
Tunnels: [0-2 2-3 3-1]
Path the ants should take:

L1-0
L1-0 L2-0
L1-0 L2-0 L3-0 `

Its for example00.txt and as you can see the ants are not moving + the displaying the pats is wrong.

This assignment would get a failing grade if you used GPT or found code. Toss all that out and write it yourself.

Sadly, like i said GPT is not working anymore. My team coded this one. And AI & Ready code is acceptable. But it has to simple because we must understand the code. I found the working code but its 800 rows. So no we cant use it either. Even if anybody can explain the algorithm, that would help a lot too. Its like onion, we are thinking we solved but than another layer comes up.

Then you have to design and create the algorithm before you write code. There's a lesson here about writing code before the design is done.

True. Wish we had able to. We cant manage it, thays why im seeking some help.

This is some academic assignment so the lesson isn't about fixing this found or GPT generated code, it's not even about coding.
It's about designing before code. Without a design, how would we code?

Or if we use AI to write code, it's a lesson about how we still have to understand the code that it generates.

Now for those that just want it fixed, you place the task on job sites like Upwork and pay for the work. But for assignments that's not applicable.

commented: Well said +16

Display everything to see where you go wrong. Also, simplify your testing, e.g., 1 ant 2 rooms, 2 paths. There are some algorithms to consider. The Breadth-First Search (BFS) and Dijkstra’s algorithms are ways to find the shortest path. Research those to understand your use case. A fix to your parse function and ant struct will help get you back started. This should help:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "strconv"
    "strings"
)

type farm struct {
    antCount       int
    roomCoordinates map[string][]int
    tunnels        map[string]map[string]bool
    startRoom      string
    endRoom        string
}

type ant struct {
    name string
    room string
}

func bfs(start string, end string, tunnels map[string]map[string]bool) []string {
    visited := make(map[string]bool)
    queue := []string{start}
    path := make(map[string]string)

    for len(queue) > 0 {
        room := queue[0]
        queue = queue[1:]

        if room == end {
            break
        }

        for adjRoom := range tunnels[room] {
            if !visited[adjRoom] {
                visited[adjRoom] = true
                queue = append(queue, adjRoom)
                path[adjRoom] = room
            }
        }
    }

    shortestPath := []string{}
    for room := end; room != ""; room = path[room] {
        shortestPath = append([]string{room}, shortestPath...)
    }

    return shortestPath
}

func parseInput(textfile string) (farm, error) {
    var farmInfo farm
    farmInfo.roomCoordinates = make(map[string][]int)
    farmInfo.tunnels = make(map[string]map[string]bool)

    content, err := ioutil.ReadFile("examples/" + textfile)
    if err != nil {
        return farmInfo, err
    }

    lines := strings.Split(string(content), "\n")
    for i, line := range lines {
        if strings.Contains(line, "##start") {
            roomDetails := strings.Fields(lines[i+1])
            farmInfo.startRoom = roomDetails[0]
        } else if strings.Contains(line, "##end") {
            roomDetails := strings.Fields(lines[i+1])
            farmInfo.endRoom = roomDetails[0]
        } else if strings.Contains(line, "-") {
            rooms := strings.Split(line, "-")
            if _, ok := farmInfo.tunnels[rooms[0]]; !ok {
                farmInfo.tunnels[rooms[0]] = make(map[string]bool)
            }
            farmInfo.tunnels[rooms[0]][rooms[1]] = true
        } else if !strings.Contains(line, "#") && len(strings.Fields(line)) == 3 {
            roomDetails := strings.Fields(line)
            x, _ := strconv.Atoi(roomDetails[1])
            y, _ := strconv.Atoi(roomDetails[2])
            farmInfo.roomCoordinates[roomDetails[0]] = []int{x, y}
        } else if len(line) > 0 && !strings.Contains(line, "-") && !strings.Contains(line, " ") && !strings.Contains(line, "#") {
            farmInfo.antCount, err = strconv.Atoi(strings.Fields(line)[0])
            if err != nil {
                fmt.Println("Ant count not found")
            }
        }
    }

    return farmInfo, nil
}

func main() {
    if len(os.Args) != 2 {
        fmt.Println("Usage: go run . <file_name>")
        os.Exit(1)
    }

    textfile := os.Args[1]

    farmInfo, err := parseInput(textfile)
    if err != nil {
        log.Fatal(err)
    }

    // Initialize the ants at the starting room
    ants := make([]ant, farmInfo.antCount)
    for i := range ants {
        ants[i] = ant{name: fmt.Sprintf("L%d", i+1), room: farmInfo.startRoom}
    }

    // Print the initial positions of the ants
    fmt.Println("Initial positions of the ants:")
    for _, ant := range ants {
        fmt.Printf("%s-%s ", ant.name, ant.room)
    }
    fmt.Println()

    // Find the shortest path
    shortestPath := bfs(farmInfo.startRoom, farmInfo.endRoom, farmInfo.tunnels)

    // Move the ants to the end room along the shortest path
    fmt.Println("Moving the ants to the end room...")
    for i := range ants {
        for _, room := range shortestPath {
            ants[i].room = room
        }
    }

    // Print the final positions of the ants
    fmt.Println("Final positions of the ants:")
    for _, ant := range ants {
        fmt.Printf("%s-%s ", ant.name, ant.room)
    }
    fmt.Println()

    // Print the ant count
    fmt.Println("Ant Count:", farmInfo.antCount)

    // Print the start and end rooms
    fmt.Println("Start Room:", farmInfo.startRoom)
    fmt.Println("End Room:", farmInfo.endRoom)

    // Print the room coordinates
    fmt.Println("Room Coordinates:")
    for room, coords := range farmInfo.roomCoordinates {
        fmt.Printf("Room %s: %d, %d\n", room, coords[0], coords[1])
    }

    // Print the tunnels
    fmt.Println("Tunnels:")
    for room, connectedRooms := range farmInfo.tunnels {
        for connectedRoom := range connectedRooms {
            fmt.Printf("%s-%s\n", room, connectedRoom)
        }
    }
}

Output:

Initial positions of the ants:
L1-0 L2-0 L3-0
Moving the ants to the end room...
Final positions of the ants:
L1-1 L2-1 L3-1
Ant Count: 3
Start Room: 0
End Room: 1
Room Coordinates:
Room 1: 9, 2
Room 3: 5, 4
Room 2: 5, 0
Room 0: 1, 2
Tunnels:
0-2
0-3
2-1
2-3
3-1
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.