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.