157 lines
3.4 KiB
Go
157 lines
3.4 KiB
Go
|
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
|
||
|
}
|