Browse Source

Needs work

Piotr Czajkowski 1 year ago
parent
commit
30eacff169
1 changed files with 166 additions and 1 deletions
  1. 166 1
      17/code.go

+ 166 - 1
17/code.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"log"
 	"os"
+	"sort"
 )
 
 const Diff = 48
@@ -30,6 +31,170 @@ func readInput(file *os.File) [][]int {
 	return board
 }
 
+const (
+	North = iota
+	East
+	South
+	West
+)
+
+type Point struct {
+	y, x int
+}
+
+type Destination struct {
+	pos       Point
+	cost      int
+	moves     int
+	direction int
+}
+
+func getNorth(board [][]int, height int, width int, lava Destination) []Destination {
+	var destinations []Destination
+	moves := 3
+	if lava.direction == North {
+		moves = lava.moves
+	}
+
+	end := lava.pos.y - moves
+	if end < 0 {
+		end = 0
+	}
+
+	cost := lava.cost
+	for y := lava.pos.y - 1; y >= end; y-- {
+		cost += board[y][lava.pos.x]
+		moves--
+		destinations = append(destinations, Destination{pos: Point{y: y, x: lava.pos.x}, moves: moves, cost: cost, direction: North})
+	}
+
+	return destinations
+}
+
+func getEast(board [][]int, height int, width int, lava Destination) []Destination {
+	var destinations []Destination
+	moves := 3
+	if lava.direction == East {
+		moves = lava.moves
+	}
+
+	end := lava.pos.x + moves
+	if end >= width {
+		end = width - 1
+	}
+
+	cost := lava.cost
+	for x := lava.pos.x + 1; x <= end; x++ {
+		cost += board[lava.pos.y][x]
+		moves--
+		destinations = append(destinations, Destination{pos: Point{y: lava.pos.y, x: x}, moves: moves, cost: cost, direction: East})
+	}
+
+	return destinations
+}
+
+func getSouth(board [][]int, height int, width int, lava Destination) []Destination {
+	var destinations []Destination
+	moves := 3
+	if lava.direction == South {
+		moves = lava.moves
+	}
+
+	end := lava.pos.y + moves
+	if end >= height {
+		end = height - 1
+	}
+
+	cost := lava.cost
+	for y := lava.pos.y + 1; y <= end; y++ {
+		cost += board[y][lava.pos.x]
+		moves--
+		destinations = append(destinations, Destination{pos: Point{y: y, x: lava.pos.x}, moves: moves, cost: cost, direction: South})
+	}
+
+	return destinations
+}
+
+func getWest(board [][]int, height int, width int, lava Destination) []Destination {
+	var destinations []Destination
+	moves := 3
+	if lava.direction == West {
+		moves = lava.moves
+	}
+
+	end := lava.pos.x - moves
+	if end < 0 {
+		end = 0
+	}
+
+	cost := lava.cost
+	for x := lava.pos.x - 1; x >= end; x-- {
+		cost += board[lava.pos.y][x]
+		moves--
+		destinations = append(destinations, Destination{pos: Point{y: lava.pos.y, x: x}, moves: moves, cost: cost, direction: West})
+	}
+
+	return destinations
+}
+
+func getDestinations(board [][]int, height int, width int, lava Destination) []Destination {
+	var destinations []Destination
+	for i := lava.direction - 1; i <= lava.direction+1; i++ {
+		switch i {
+		case North:
+			destinations = append(destinations, getNorth(board, height, width, lava)...)
+		case East:
+			destinations = append(destinations, getEast(board, height, width, lava)...)
+		case South:
+			destinations = append(destinations, getSouth(board, height, width, lava)...)
+		case West:
+			destinations = append(destinations, getWest(board, height, width, lava)...)
+		}
+	}
+
+	return destinations
+}
+
+func part1(board [][]int) int {
+	min := 1000000
+	height := len(board)
+	width := len(board[0])
+	goal := Point{y: height - 1, x: width - 1}
+	explored := make(map[Point]int)
+	lava := Destination{pos: Point{x: 0, y: 0}, moves: 3, direction: East}
+	frontier := getDestinations(board, height, width, lava)
+
+	for {
+		if len(frontier) == 0 {
+			break
+		}
+
+		sort.Slice(frontier, func(i, j int) bool {
+			return frontier[i].cost < frontier[j].cost
+		})
+
+		current := frontier[0]
+		frontier = frontier[1:]
+
+		if current.pos == goal {
+			if min > current.cost {
+				min = current.cost
+			}
+		}
+
+		successors := getDestinations(board, height, width, current)
+		for i := range successors {
+			value, ok := explored[successors[i].pos]
+			if !ok || value > successors[i].cost {
+				explored[successors[i].pos] = successors[i].cost
+				frontier = append(frontier, successors[i])
+			}
+		}
+	}
+
+	return min
+}
+
 func main() {
 	if len(os.Args) < 2 {
 		log.Fatal("You need to specify a file!")
@@ -43,5 +208,5 @@ func main() {
 	}
 
 	board := readInput(file)
-	fmt.Println(board)
+	fmt.Println("Part1:", part1(board))
 }