240 lines
5.5 KiB
Go
240 lines
5.5 KiB
Go
package main
|
|
|
|
import (
|
|
"AoC2020/helper"
|
|
"fmt"
|
|
"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)
|
|
var picture = make(map[[2]int]int)
|
|
picture = getPictureStep(1951,tilesWithNeighbours,[]int{},picture,[2]int{0,0})
|
|
fmt.Println(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)))
|
|
fmt.Printf("HI %v \n", getSomeTile(corners))
|
|
currentTileId := 1951
|
|
currentTile := corners[currentTileId]
|
|
picture[[2]int{0,0}] = currentTileId
|
|
fmt.Println(currentTile.neighbourID)
|
|
fmt.Println(currentTile.edges)
|
|
printPicture(currentTile.picture)
|
|
return picture
|
|
}
|
|
|
|
func getPictureStep(currentTile int,allTiles map[int]tile,visitedTiles []int, picture map[[2]int]int,position [2]int) map[[2]int]int{
|
|
for len(visitedTiles) < len(allTiles){
|
|
picture[position] = currentTile
|
|
visitedTiles = append(visitedTiles,currentTile)
|
|
nextTile := 0
|
|
for i, val := range allTiles[currentTile].neighbourID {
|
|
if val != 0 && !contains(val,visitedTiles){
|
|
nextTile = val
|
|
switch i {
|
|
case 0: position = [2]int{position[0],position[1]+1}
|
|
case 1: position = [2]int{position[0]+1,position[1]}
|
|
case 2: position = [2]int{position[0],position[1]-1}
|
|
case 3: position = [2]int{position[0]-1,position[1]}
|
|
}
|
|
}
|
|
}
|
|
currentTile = nextTile
|
|
}
|
|
return picture
|
|
}
|
|
|
|
func contains(elem int, array []int) 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[:])
|
|
}
|
|
return tile
|
|
}
|
|
|
|
//0 horizontal
|
|
//1 vertical
|
|
func flip(tile tile, direction int) tile{
|
|
var newPicture []string
|
|
if direction == 0{
|
|
for i := len(tile.picture); i >= 0; i--{
|
|
newPicture = append(newPicture,tile.picture[i])
|
|
}
|
|
}
|
|
if direction == 1{
|
|
for _,val := range tile.picture {
|
|
newPicture = append(newPicture,reverse(val))
|
|
}
|
|
}
|
|
printPicture(newPicture)
|
|
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]))
|
|
return number, tile{[4]int{},edges, tilesRow[1:]}
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
|