package main import ( "bufio" "log" "math" "os" "strconv" "strings" ) type Point struct { X int Y int } func main() { file, err := os.Open("input.txt") if err != nil { log.Fatal(err) } defer file.Close() scanner := bufio.NewScanner(file) if !scanner.Scan() { log.Fatalln("Problem while read line.") return } route1 := scanner.Text() if !scanner.Scan() { log.Fatalln("Problem while read second line.") return } route2 := scanner.Text() distance := GetShortestDistance(route1, route2) routeDistance := GetShortestRoute(route1, route2) log.Println("Part1: Distance: " + strconv.Itoa(distance)) log.Println("Part2: Route: " + strconv.Itoa(routeDistance)) } func GetShortestDistance(route1 string, route2 string) int { points1 := GetAllPointsFromRoute(ParseRoute(route1)) points2 := GetAllPointsFromRoute(ParseRoute(route2)) crossed := FindAllCrossedPoints(points1, points2) distance := GetShortestDistanceFromPoints(crossed) return distance } func GetShortestRoute(route1 string, route2 string) int { points1 := GetAllPointsFromRoute(ParseRoute(route1)) points2 := GetAllPointsFromRoute(ParseRoute(route2)) crossed := FindAllCrossedPoints(points1, points2) shortestDis := math.MaxInt32 for _, point := range crossed { distance1 := GetRouteDistanceToPoint(points1, point) distance2 := GetRouteDistanceToPoint(points2, point) fullDistance := distance1 + distance2 if fullDistance < shortestDis { shortestDis = fullDistance } } return shortestDis } func ParseRoute(route string) []string { return strings.Split(route, ",") } func GetAllPointsFromRoute(cmds []string) []Point { var ( currentX int currentY int points []Point ) for _, cmd := range cmds { runes := []rune(cmd) direction := string(runes[0]) lengthStr := string(runes[1:len(runes)]) length, _ := strconv.Atoi(lengthStr) if direction == "R" { for i := 1; i <= length; i++ { currentX++ points = append(points, Point{X: currentX, Y: currentY}) } } else if direction == "L" { for i := 1; i <= length; i++ { currentX-- points = append(points, Point{X: currentX, Y: currentY}) } } else if direction == "U" { for i := 1; i <= length; i++ { currentY++ points = append(points, Point{X: currentX, Y: currentY}) } } else if direction == "D" { for i := 1; i <= length; i++ { currentY-- points = append(points, Point{X: currentX, Y: currentY}) } } else { log.Fatal("ERROR Cmd: " + direction) } } return points } func FindAllCrossedPoints(a []Point, b []Point) []Point { crossedPoints := make([]Point, 0) for _, pointA := range a { for _, pointB := range b { if pointA.X == pointB.X && pointA.Y == pointB.Y { crossedPoints = append(crossedPoints, pointA) } } } return crossedPoints } func GetShortestDistanceFromPoints(points []Point) int { shortestDis := math.MaxInt32 for _, point := range points { distance := GetDistanceFromPoint(point) if distance < shortestDis { shortestDis = distance } } return shortestDis } func GetRouteDistanceToPoint(route []Point, point Point) int { sum := 0 for _, routePoint := range route { sum++ if routePoint.X == point.X && routePoint.Y == point.Y { break } } return sum } func GetDistanceFromPoint(point Point) int { return GetPositiveNumber(point.X) + GetPositiveNumber(point.Y) } func GetPositiveNumber(num int) int { if num < 0 { return -1 * num } return num }