You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
7.1 KiB
296 lines
7.1 KiB
package main |
|
|
|
import ( |
|
"AoC2020/helper" |
|
"fmt" |
|
"math" |
|
"os" |
|
"regexp" |
|
"strconv" |
|
"strings" |
|
) |
|
|
|
var lineBreak = "\r\n" |
|
|
|
type tile struct { |
|
neighbourID [4]int |
|
edges [4]string |
|
picture []string |
|
} |
|
|
|
func main() { |
|
args := os.Args[1:] |
|
input, err := helper.GetFile(args[0]) |
|
if err != nil { |
|
fmt.Println(err) |
|
} |
|
tileInput := strings.Split(input, lineBreak+lineBreak) |
|
tiles := getTiles(tileInput) |
|
var tilesWithNeighbours = make(map[int]tile) |
|
for id,tile := range tiles { |
|
tilesWithNeighbours[id] = getNeighboursForTile(id,tile,tiles) |
|
} |
|
var corners = make(map[int]tile) |
|
for key, tile := range tilesWithNeighbours { |
|
pictureEdges := 0 |
|
for _, val := range tile.neighbourID{ |
|
if val == 0 { |
|
pictureEdges++ |
|
} |
|
} |
|
if pictureEdges == 2 { |
|
corners[key] = tile |
|
} |
|
} |
|
product := 1 |
|
for key,_ := range corners { |
|
product *= key |
|
} |
|
fmt.Println(product) |
|
fmt.Println(tilesWithNeighbours[1951]) |
|
var picture = make(map[[2]int]int) |
|
picture = getPictureStep(1951,tilesWithNeighbours,[]int{},picture) |
|
} |
|
|
|
func getPicture(corners map[int]tile, allTiles map[int]tile) map[[2]int]int { |
|
var picture = make(map[[2]int]int) |
|
//len := math.Sqrt(float64(len(allTiles))) |
|
currentTileId := 1951 |
|
currentTile := corners[currentTileId] |
|
picture[[2]int{0,0}] = currentTileId |
|
printPicture(currentTile.picture) |
|
return picture |
|
} |
|
|
|
func getPictureStep(currentTile int,allTiles map[int]tile,visitedTiles []int, picture map[[2]int]int) map[[2]int]int{ |
|
lenght := int(math.Sqrt(float64(len(allTiles)))) |
|
position := [2]int{0,lenght} |
|
for allTiles[currentTile].neighbourID[1] != 0 || allTiles[currentTile].neighbourID[2] != 0{ |
|
allTiles[currentTile] = rotate(allTiles[currentTile]) |
|
fmt.Println(allTiles[currentTile]) |
|
} |
|
fmt.Println(allTiles[currentTile]) |
|
for len(visitedTiles) < 2{ |
|
picture[position] = currentTile |
|
visitedTiles = append(visitedTiles,currentTile) |
|
nextPosition, _ := getNextPosition(position,lenght,picture) |
|
//nextTileId, _ := getNextTile(allTiles[currentTile].edges[edge],allTiles,currentTile) |
|
position = nextPosition |
|
} |
|
return picture |
|
} |
|
|
|
func getNextPosition(position [2]int, length int, picture map[[2]int]int) ([2]int, int) { |
|
if (position[1]+1) < length && picture[[2]int{position[0],position[1]+1}] == 0 { |
|
return [2]int{position[0],position[1]+1}, 0 |
|
} |
|
if (position[0]-1) > 0 && picture[[2]int{position[0]-1,position[1]}] == 0 { |
|
return [2]int{position[0]-1,position[1]}, 3 |
|
} |
|
if (position[1]-1) > 0 && picture[[2]int{position[0],position[1]-1}] == 0 { |
|
return [2]int{position[0],position[1]-1}, 2 |
|
} |
|
if (position[0]+1) < 0 && picture[[2]int{position[0]+1,position[1]}] == 0 { |
|
return [2]int{position[0]+1,position[1]}, 1 |
|
} |
|
return position, -1 |
|
} |
|
|
|
func getNextTile(edge string, allTiles map[int]tile, currentTile int) (int, tile){ |
|
var newTile tile |
|
for id, tile := range allTiles{ |
|
if id != currentTile { |
|
if stringContains(edge, tile.edges[:]) { |
|
return id, tile |
|
} |
|
newTile = flip(tile, 0) |
|
if stringContains(edge, newTile.edges[:]) { |
|
return id, tile |
|
} |
|
newTile = flip(tile, 1) |
|
if stringContains(edge, newTile.edges[:]) { |
|
return id, tile |
|
} |
|
} |
|
} |
|
return 0,tile{} |
|
} |
|
|
|
func contains(elem int, array []int) bool{ |
|
for _, val := range array{ |
|
if val == elem{ |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
func stringContains(elem string, array []string) bool{ |
|
for _, val := range array{ |
|
if val == elem{ |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
func getSomeTile(m map[int]tile) int { |
|
for k := range m { |
|
return k |
|
} |
|
return 0 |
|
} |
|
|
|
func printPicture(input[]string){ |
|
for _, row := range input { |
|
fmt.Println(row) |
|
} |
|
fmt.Println() |
|
} |
|
|
|
func rotate(tile tile) tile{ |
|
var newPicture [10][10]rune |
|
for i:= 0; i < len(tile.picture); i++ { |
|
for j:= 0; j < len(tile.picture); j++ { |
|
newPicture[i][j] = rune(tile.picture[len(tile.picture)-j-1][i]); |
|
} |
|
} |
|
var newNeighbourId [4]int |
|
newNeighbourId[0] = tile.neighbourID[3] |
|
for i,val := range tile.neighbourID[:2]{ |
|
newNeighbourId[i+1] = val |
|
} |
|
tile.neighbourID = newNeighbourId |
|
for i,row := range newPicture { |
|
tile.picture[i] = string(row[:]) |
|
} |
|
tile = setEdges(tile) |
|
return tile |
|
} |
|
|
|
//0 horizontal |
|
//1 vertical |
|
func flip(tile tile, direction int) tile{ |
|
var newPicture []string |
|
if direction == 0{ |
|
for i := len(tile.picture)-1; i >= 0; i--{ |
|
newPicture = append(newPicture,tile.picture[i]) |
|
} |
|
} |
|
if direction == 1{ |
|
for _,val := range tile.picture { |
|
newPicture = append(newPicture,reverse(val)) |
|
} |
|
} |
|
newEdges := getAllPossibleEdgesForFlippedTile(tile,direction) |
|
for i:= 0; i < len(tile.edges); i++{ |
|
tile.edges[i] = newEdges[i] |
|
} |
|
tile.picture = newPicture |
|
return tile |
|
} |
|
|
|
func getTiles(input []string) map[int]tile{ |
|
var tiles = make(map[int]tile) |
|
for _, val := range input { |
|
id, tile := getTile(val) |
|
tiles[id] = tile |
|
} |
|
return tiles |
|
} |
|
|
|
func getTile(input string) (int, tile) { |
|
tilesRow := strings.Split(input, lineBreak) |
|
var edges [4]string |
|
edges[0] = tilesRow[1] |
|
edges[2] = tilesRow[len(tilesRow)-1] |
|
for _, val := range tilesRow[1:] { |
|
edges[3] = edges[3]+val[0:1] |
|
edges[1] = edges[1]+val[len(val)-1:] |
|
} |
|
r, _ := regexp.Compile("[0-9]{4}") |
|
number, _ := strconv.Atoi(r.FindString(tilesRow[0])) |
|
tile := tile{[4]int{},edges, tilesRow[1:]} |
|
return number, setEdges(tile) |
|
} |
|
|
|
func setEdges(tile tile)tile{ |
|
var newEdges [4]string |
|
newEdges[0] = tile.picture[0] |
|
newEdges[2] = tile.picture[len(tile.picture)-1] |
|
for _, val := range tile.picture { |
|
newEdges[3] = newEdges[3]+val[0:1] |
|
newEdges[1] = newEdges[1]+val[len(val)-1:] |
|
} |
|
tile.edges = newEdges |
|
return tile |
|
} |
|
|
|
func getAllPossibleEdgesForTile(tile tile, direction int) []string{ |
|
switch direction { |
|
case -1: |
|
var edges [4]string |
|
for i, edge := range tile.edges { |
|
edges[i] = edge |
|
} |
|
return edges[:] |
|
case 0: |
|
return getAllPossibleEdgesForFlippedTile(tile,0) |
|
case 1: |
|
return getAllPossibleEdgesForFlippedTile(tile,1) |
|
} |
|
return []string{} |
|
} |
|
|
|
func getAllPossibleEdgesForFlippedTile(tile tile, direction int) []string{ |
|
var edges [4]string |
|
for i:= 0; i < len(tile.edges); i ++ { |
|
if i % 2 == direction { |
|
edges[i] = reverse(tile.edges[i]) |
|
}else{ |
|
edges[i] = reverse(tile.edges[i]) |
|
} |
|
} |
|
return edges[:] |
|
} |
|
|
|
func getNeighboursForTile(choosenTile int, tile tile, allTiles map[int]tile) tile{ |
|
var idToPossibleEdges = make(map[int][]string) |
|
for id,tile := range allTiles { |
|
idToPossibleEdges[id] = getAllPossibleEdgesForTile(tile,-1) |
|
idToPossibleEdges[id] = append(idToPossibleEdges[id],getAllPossibleEdgesForTile(tile,0)...) |
|
idToPossibleEdges[id] = append(idToPossibleEdges[id],getAllPossibleEdgesForTile(tile,1)...) |
|
} |
|
for i, edge := range tile.edges { |
|
tile.neighbourID[i] = getFittingTileForEdge(choosenTile,edge,idToPossibleEdges) |
|
} |
|
return tile |
|
} |
|
|
|
func getFittingTileForEdge(choosenTile int, edge string, idToPossibleEdges map[int][]string) int{ |
|
for id,edges := range idToPossibleEdges { |
|
if choosenTile != id && hasMatchingEdge(edges,edge){ |
|
return id |
|
} |
|
} |
|
return 0 |
|
} |
|
|
|
func hasMatchingEdge(edges []string, edge string) bool { |
|
for _, val := range edges { |
|
if val == edge{ |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
func reverse(s string) string { |
|
runes := []rune(s) |
|
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { |
|
runes[i], runes[j] = runes[j], runes[i] |
|
} |
|
return string(runes) |
|
} |
|
|
|
|
|
|