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) }