2020-12-20 17:09:40 +01:00
package main
import (
"AoC2020/helper"
"fmt"
"os"
"regexp"
"strconv"
"strings"
)
2020-12-20 20:19:05 +01:00
var lineBreak = "\r\n"
2020-12-20 17:09:40 +01:00
type tile struct {
neighbourID [ 4 ] int
edges [ 4 ] string
2020-12-20 20:19:05 +01:00
picture [ ] string
2020-12-20 17:09:40 +01:00
}
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 )
2020-12-20 20:19:05 +01:00
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
2020-12-20 17:09:40 +01:00
}
fmt . Println ( product )
2020-12-20 20:19:05 +01:00
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
2020-12-20 17:09:40 +01:00
}
2020-12-20 20:19:05 +01:00
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 )
2020-12-20 17:09:40 +01:00
for _ , val := range input {
2020-12-20 20:19:05 +01:00
id , tile := getTile ( val )
tiles [ id ] = tile
2020-12-20 17:09:40 +01:00
}
return tiles
}
2020-12-20 20:19:05 +01:00
func getTile ( input string ) ( int , tile ) {
2020-12-20 17:09:40 +01:00
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 ] ) )
2020-12-20 20:19:05 +01:00
return number , tile { [ 4 ] int { } , edges , tilesRow [ 1 : ] }
2020-12-20 17:09:40 +01:00
}
2020-12-20 20:19:05 +01:00
func getAllPossibleEdgesForTile ( tile tile , direction int ) [ ] string {
switch direction {
case - 1 :
var edges [ 4 ] string
for i , edge := range tile . edges {
edges [ i ] = edge
2020-12-20 17:09:40 +01:00
}
2020-12-20 20:19:05 +01:00
return edges [ : ]
case 0 :
return getAllPossibleEdgesForFlippedTile ( tile , 0 )
case 1 :
return getAllPossibleEdgesForFlippedTile ( tile , 1 )
2020-12-20 17:09:40 +01:00
}
2020-12-20 20:19:05 +01:00
return [ ] string { }
2020-12-20 17:09:40 +01:00
}
2020-12-20 20:19:05 +01:00
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 ] )
2020-12-20 17:09:40 +01:00
}
}
2020-12-20 20:19:05 +01:00
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
2020-12-20 17:09:40 +01:00
}
2020-12-20 20:19:05 +01:00
func getFittingTileForEdge ( choosenTile int , edge string , idToPossibleEdges map [ int ] [ ] string ) int {
for id , edges := range idToPossibleEdges {
if choosenTile != id && hasMatchingEdge ( edges , edge ) {
return id
2020-12-20 17:09:40 +01:00
}
}
2020-12-20 20:19:05 +01:00
return 0
2020-12-20 17:09:40 +01:00
}
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 )
}
2020-12-20 20:19:05 +01:00