|  | @@ -8,7 +8,10 @@ import (
 | 
	
		
			
				|  |  |  	"sort"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const Diff = 48
 | 
	
		
			
				|  |  | +const (
 | 
	
		
			
				|  |  | +	Diff     = 48
 | 
	
		
			
				|  |  | +	MaxMoves = 3
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func readInput(file *os.File) [][]int {
 | 
	
		
			
				|  |  |  	scanner := bufio.NewScanner(file)
 | 
	
	
		
			
				|  | @@ -51,12 +54,16 @@ type Destination struct {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func getNorth(board [][]int, height int, width int, lava Destination) []Destination {
 | 
	
		
			
				|  |  |  	var destinations []Destination
 | 
	
		
			
				|  |  | -	moves := 3
 | 
	
		
			
				|  |  | +	moves := 0
 | 
	
		
			
				|  |  |  	if lava.direction == North {
 | 
	
		
			
				|  |  |  		moves = lava.moves
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	end := lava.pos.y - moves
 | 
	
		
			
				|  |  | +	if moves > MaxMoves {
 | 
	
		
			
				|  |  | +		return destinations
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	end := lava.pos.y - MaxMoves
 | 
	
		
			
				|  |  |  	if end < 0 {
 | 
	
		
			
				|  |  |  		end = 0
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -64,7 +71,11 @@ func getNorth(board [][]int, height int, width int, lava Destination) []Destinat
 | 
	
		
			
				|  |  |  	cost := lava.cost
 | 
	
		
			
				|  |  |  	for y := lava.pos.y - 1; y >= end; y-- {
 | 
	
		
			
				|  |  |  		cost += board[y][lava.pos.x]
 | 
	
		
			
				|  |  | -		moves--
 | 
	
		
			
				|  |  | +		moves++
 | 
	
		
			
				|  |  | +		if moves > MaxMoves {
 | 
	
		
			
				|  |  | +			break
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		destinations = append(destinations, Destination{pos: Point{y: y, x: lava.pos.x}, moves: moves, cost: cost, direction: North})
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -73,12 +84,16 @@ func getNorth(board [][]int, height int, width int, lava Destination) []Destinat
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func getEast(board [][]int, height int, width int, lava Destination) []Destination {
 | 
	
		
			
				|  |  |  	var destinations []Destination
 | 
	
		
			
				|  |  | -	moves := 3
 | 
	
		
			
				|  |  | +	moves := 0
 | 
	
		
			
				|  |  |  	if lava.direction == East {
 | 
	
		
			
				|  |  |  		moves = lava.moves
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	end := lava.pos.x + moves
 | 
	
		
			
				|  |  | +	if moves > MaxMoves {
 | 
	
		
			
				|  |  | +		return destinations
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	end := lava.pos.x + MaxMoves
 | 
	
		
			
				|  |  |  	if end >= width {
 | 
	
		
			
				|  |  |  		end = width - 1
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -86,8 +101,15 @@ func getEast(board [][]int, height int, width int, lava Destination) []Destinati
 | 
	
		
			
				|  |  |  	cost := lava.cost
 | 
	
		
			
				|  |  |  	for x := lava.pos.x + 1; x <= end; x++ {
 | 
	
		
			
				|  |  |  		cost += board[lava.pos.y][x]
 | 
	
		
			
				|  |  | -		moves--
 | 
	
		
			
				|  |  | +		moves++
 | 
	
		
			
				|  |  | +		if moves > MaxMoves {
 | 
	
		
			
				|  |  | +			break
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		destinations = append(destinations, Destination{pos: Point{y: lava.pos.y, x: x}, moves: moves, cost: cost, direction: East})
 | 
	
		
			
				|  |  | +		if moves > MaxMoves {
 | 
	
		
			
				|  |  | +			break
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return destinations
 | 
	
	
		
			
				|  | @@ -95,12 +117,16 @@ func getEast(board [][]int, height int, width int, lava Destination) []Destinati
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func getSouth(board [][]int, height int, width int, lava Destination) []Destination {
 | 
	
		
			
				|  |  |  	var destinations []Destination
 | 
	
		
			
				|  |  | -	moves := 3
 | 
	
		
			
				|  |  | +	moves := 0
 | 
	
		
			
				|  |  |  	if lava.direction == South {
 | 
	
		
			
				|  |  |  		moves = lava.moves
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	end := lava.pos.y + moves
 | 
	
		
			
				|  |  | +	if moves > MaxMoves {
 | 
	
		
			
				|  |  | +		return destinations
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	end := lava.pos.y + MaxMoves
 | 
	
		
			
				|  |  |  	if end >= height {
 | 
	
		
			
				|  |  |  		end = height - 1
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -108,7 +134,11 @@ func getSouth(board [][]int, height int, width int, lava Destination) []Destinat
 | 
	
		
			
				|  |  |  	cost := lava.cost
 | 
	
		
			
				|  |  |  	for y := lava.pos.y + 1; y <= end; y++ {
 | 
	
		
			
				|  |  |  		cost += board[y][lava.pos.x]
 | 
	
		
			
				|  |  | -		moves--
 | 
	
		
			
				|  |  | +		moves++
 | 
	
		
			
				|  |  | +		if moves > MaxMoves {
 | 
	
		
			
				|  |  | +			break
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		destinations = append(destinations, Destination{pos: Point{y: y, x: lava.pos.x}, moves: moves, cost: cost, direction: South})
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -117,12 +147,16 @@ func getSouth(board [][]int, height int, width int, lava Destination) []Destinat
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func getWest(board [][]int, height int, width int, lava Destination) []Destination {
 | 
	
		
			
				|  |  |  	var destinations []Destination
 | 
	
		
			
				|  |  | -	moves := 3
 | 
	
		
			
				|  |  | +	moves := 0
 | 
	
		
			
				|  |  |  	if lava.direction == West {
 | 
	
		
			
				|  |  |  		moves = lava.moves
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	end := lava.pos.x - moves
 | 
	
		
			
				|  |  | +	if moves > MaxMoves {
 | 
	
		
			
				|  |  | +		return destinations
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	end := lava.pos.x - MaxMoves
 | 
	
		
			
				|  |  |  	if end < 0 {
 | 
	
		
			
				|  |  |  		end = 0
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -130,16 +164,36 @@ func getWest(board [][]int, height int, width int, lava Destination) []Destinati
 | 
	
		
			
				|  |  |  	cost := lava.cost
 | 
	
		
			
				|  |  |  	for x := lava.pos.x - 1; x >= end; x-- {
 | 
	
		
			
				|  |  |  		cost += board[lava.pos.y][x]
 | 
	
		
			
				|  |  | -		moves--
 | 
	
		
			
				|  |  | +		moves++
 | 
	
		
			
				|  |  | +		if moves > MaxMoves {
 | 
	
		
			
				|  |  | +			break
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		destinations = append(destinations, Destination{pos: Point{y: lava.pos.y, x: x}, moves: moves, cost: cost, direction: West})
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return destinations
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +func getDirections(direction int) []int {
 | 
	
		
			
				|  |  | +	switch direction {
 | 
	
		
			
				|  |  | +	case North:
 | 
	
		
			
				|  |  | +		return []int{West, North, East}
 | 
	
		
			
				|  |  | +	case East:
 | 
	
		
			
				|  |  | +		return []int{North, East, South}
 | 
	
		
			
				|  |  | +	case South:
 | 
	
		
			
				|  |  | +		return []int{West, South, East}
 | 
	
		
			
				|  |  | +	case West:
 | 
	
		
			
				|  |  | +		return []int{South, West, North}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return []int{}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  func getDestinations(board [][]int, height int, width int, lava Destination) []Destination {
 | 
	
		
			
				|  |  |  	var destinations []Destination
 | 
	
		
			
				|  |  | -	for i := lava.direction - 1; i <= lava.direction+1; i++ {
 | 
	
		
			
				|  |  | +	directions := getDirections(lava.direction)
 | 
	
		
			
				|  |  | +	for i := range directions {
 | 
	
		
			
				|  |  |  		switch i {
 | 
	
		
			
				|  |  |  		case North:
 | 
	
		
			
				|  |  |  			destinations = append(destinations, getNorth(board, height, width, lava)...)
 | 
	
	
		
			
				|  | @@ -161,21 +215,23 @@ func part1(board [][]int) int {
 | 
	
		
			
				|  |  |  	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)
 | 
	
		
			
				|  |  | +	lava := Destination{pos: Point{x: 0, y: 0}, moves: 0, direction: East}
 | 
	
		
			
				|  |  | +	prev := lava
 | 
	
		
			
				|  |  | +	frontier := []Destination{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.direction == prev.direction && current.moves+prev.moves > MaxMoves {
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		prev = current
 | 
	
		
			
				|  |  |  		if current.pos == goal {
 | 
	
		
			
				|  |  |  			if min > current.cost {
 | 
	
		
			
				|  |  |  				min = current.cost
 | 
	
	
		
			
				|  | @@ -183,13 +239,20 @@ func part1(board [][]int) int {
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		successors := getDestinations(board, height, width, current)
 | 
	
		
			
				|  |  | +		fmt.Println(current, successors)
 | 
	
		
			
				|  |  |  		for i := range successors {
 | 
	
		
			
				|  |  | +			newCost := successors[i].cost + successors[i].moves
 | 
	
		
			
				|  |  |  			value, ok := explored[successors[i].pos]
 | 
	
		
			
				|  |  | -			if !ok || value > successors[i].cost {
 | 
	
		
			
				|  |  | -				explored[successors[i].pos] = successors[i].cost
 | 
	
		
			
				|  |  | +			if !ok || value > newCost {
 | 
	
		
			
				|  |  | +				explored[successors[i].pos] = newCost
 | 
	
		
			
				|  |  |  				frontier = append(frontier, successors[i])
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		sort.Slice(frontier, func(i, j int) bool {
 | 
	
		
			
				|  |  | +			return frontier[i].cost < frontier[j].cost
 | 
	
		
			
				|  |  | +		})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return min
 |