master
E. Almqvist 4 years ago
parent 4ec83cc456
commit 1495a8a8b1
  1. 355
      2020/20.py

@ -4,6 +4,10 @@ from collections import defaultdict as dd
from aoc import get_input # AoC from aoc import get_input # AoC
import re # regex import re # regex
import numpy as np import numpy as np
from copy import deepcopy as copy
from sys import setrecursionlimit
setrecursionlimit(20000)
data = get_input(20).strip() data = get_input(20).strip()
@ -30,14 +34,8 @@ for genpic in data.split("\n\n"):
for pid, pic in pics.items(): for pid, pic in pics.items():
pics[pid] = np.asarray(pic) pics[pid] = np.asarray(pic)
print(pics["3079"])
fits = dict()
# fits struc mapWidth = len(pics) ** (1/2)
#
# fits[id] = { "L": (otherid, rotation) }
# where key = "L", "R", "U", "D", "UL", "UR", "DL", "DR"
def compileBorder(row): def compileBorder(row):
out = "" out = ""
@ -61,10 +59,10 @@ def genBorders(picid):
## compile its borders ## compile its borders
borders = dict() borders = dict()
borders[0] = compileBorder(pic[0]) borders["U"] = compileBorder(pic[0])
borders[1] = compileSideBorder(pic, -1) borders["R"] = compileSideBorder(pic, -1)
borders[2] = compileBorder(pic[-1]) # up: 0, right: 1, down: 2, left: 3 borders["D"] = compileBorder(pic[-1]) # up: 0, right: 1, down: 2, left: 3
borders[3] = compileSideBorder(pic, 0) borders["L"] = compileSideBorder(pic, 0)
return borders return borders
@ -74,14 +72,14 @@ for pid, pic in pics.items():
# picmap = dict() # map of the arranged pics # picmap = dict() # map of the arranged pics
def rotateTile(otherside): def flip(otherside):
# 0 up, 1 right, 2 down, 3 left # 0 up, 1 right, 2 down, 3 left
sidething = { # used to rotate as the rotation is allways the opposite relative to the whole system sidething = { # used to rotate as the rotation is allways the opposite relative to the whole system
0: 2, "U": "D",
1: 3, "R": "L",
2: 0, "D": "U",
3: 1 "L": "R"
} }
newotherside = sidething[otherside] newotherside = sidething[otherside]
@ -98,301 +96,84 @@ def borderCheck(border, other):
else: else:
return False, other return False, other
def getFits(picid, ignoreid): fitsDict = dd(dict)
borders = picBorders[picid]
seenborders = [] # fits struc
attachedTiles = []
# if some border match, i.e. this[2] match other[1] then rotate and/or flip other?
# dont actually have to arrange the map, just get stuff that fits together and their IDs
# #
# probably gonna be in part 2 idk # fits[id] = { "L": (otherid, rotation) }
# where key = "L", "R", "U", "D", "UL", "UR", "DL", "DR"
match = False # otherid is the one that fits
matchID = None # rotation is the other that fits rotation to be able to fit
selfSide = None
matchSide = None
matchFlipped = False
prevTile = None
for side, border in borders.items(): # TODO: make recursive instead and flip (np.fliplr) (and for up-down)
# check other borders
selfSide = side
for pid, bor in picBorders.items():
if(pid == picid or pid == ignoreid):
continue
# print("Checking", pid, f"{attachedTiles=}") def getFits(borders, fits=fitsDict, ignore=[]):
#print(fits)
#print("\n#", borders, "\n")
ignoreLen = len(ignore)
borLen = len(borders)
print(ignoreLen, borLen)
for pos, line in bor.items(): # top and bottom matching if(ignoreLen >= borLen):
if(not pos in [0, len(bor)-1]): print("goodbye")
continue return fits # if there is nothing to do then return the result
if(line in seenborders): newborders = copy(borders)
for pid, border in borders.items(): # borders[pid]
#print(f"\nChecking {pid=}")
if( pid in ignore ):
continue continue
check, newborder = borderCheck(border, line) for pos, bor in border.items(): # check each border : borders[pid][pos]
print("TB Checking border", pos, ":", line, f"{newborder=} {line=} : {border=}")
if( check ):
matchID = pid
matchSide = pos
matchFlipped = line == newborder # flipped from matchSide axis
if( newborder != line ): print(f"##Border {pid=} {pos=} {bor=}")
picBorders[pid][pos] = newborder # flip that border if flipped
otherside = rotateTile(pos)
picBorders[pid][otherside] = picBorders[pid][otherside][::-1] # flip the other side too
match = True
attachedTiles.append(matchID)
seenborders.append(line)
prevTile = matchID
print("MATCH")
break
if(not match):
border_left, border_right = "", ""
for y, line in bor.items():
border_left += line[0]
border_right += line[-1]
print(f"LR Checking border : {border_left=} {border_right=}")
check_left, newborder_left = borderCheck(border_left, line)
check_right, newborder_right = borderCheck(border_right, line)
if(check_left):
pos = 3
matchID = pid
matchSide = pos
matchFlipped = border_left == newborder_left # flipped from matchSide axis
if( newborder_left != line ):
picBorders[pid][pos] = newborder_left # flip that border if flipped
otherside = rotateTile(pos)
picBorders[pid][otherside] = picBorders[pid][otherside][::-1] # flip the other side too
match = True
attachedTiles.append(matchID)
seenborders.append(line)
prevTile = matchID
print("MATCH")
break
elif(check_right):
pos = 1
matchID = pid
matchSide = pos
matchFlipped = border_right == newborder_right # flipped from matchSide axis
if( newborder_right != line ):
picBorders[pid][pos] = newborder_right # flip that border if flipped
otherside = rotateTile(pos)
picBorders[pid][otherside] = picBorders[pid][otherside][::-1] # flip the other side too
match = True
attachedTiles.append(matchID)
seenborders.append(line)
prevTile = matchID
print("MATCH")
break
else:
break
if(match):
return [selfSide, matchID, matchSide, matchFlipped]
for pid2, border2 in borders.items(): # check for others borders ; borders[pid2]
if(pid2 == pid or pid2 in ignore):
continue
mapWidth = int(len(pics) ** (1/2)) for pos2, bor2 in border2.items(): # check for other matching border ; borders[pid2][pos2]
tilemap = np.empty([mapWidth, mapWidth], dtype=str) check, newBor2 = borderCheck(bor, bor2)
print("") print(f"####Border2 {pid2=} {pos2=} {bor2=} {newBor2=} {check=}")
print(tilemap)
aligns = dict() if(check): # if the two borders match:
fits[pid] = dict()
fits[pid][pos] = (pid2, pos2)
#for pid, pic in pics.items(): ignore.append(pid)
nextTile = None
prevTile = None
for key in pics.keys(): fits[pid] = fits[pid] or {"E": None} # It has to end somewhere
nextTile = key
prevTile = key
break
return getFits(newborders, fits, ignore) # do the other borders
seenTiles = [] print(picBorders)
loop = False
while(not loop):
fits = getFits(nextTile, prevTile)
aligns[nextTile] = fits
fits = getFits(picBorders, fitsDict)
print("------------")
print(fits) print(fits)
# prevTile = nextTile picmap = dd(dict) # inp: coord [][] -> pid
# nextTile = fits[1] coords = dict() # inp: pid -> out: coord (tuple)
# if(nextTile in seenTiles):
# loop = True
# break
# seenTiles.append(prevTile)
# print(prevTile, nextTile, seenTiles)
print(aligns)
def copyList(ls):
return [elem for elem in ls]
# ################
# exit()
# ################
def rotateNumTo(numrot, tonum):
tonum = rotateTile(tonum)
# numrot -> tonum
# get num of rotations clockwise
rots = numrot - tonum
newrot = numrot + rots
while(newrot < 0):
newrot += 4
newrot = newrot % 4 pidList = fits.keys()
firstID = None
return newrot for pid in pidList:
firstID = pid
break
# ----------------------------------------------
# | 0 1 2 3 |
# |[selfSide, matchID, matchSide, matchFlipped]|
# ----------------------------------------------
# for pid, fit in aligns.items():
# fitid = fit[1]
# conRot = fit[0]
# myRot = fit[2]
# newrot = rotateNumTo(myRot, conRot)
# #print(f"{pid=} {fitid=} : {conRot=} {myRot=} : {newrot=}")
# aligns[fitid][0] = newrot # make others relative
print("\n\n----")
rotmap = dd(dict) # inp: coords
rotcoords = dd(tuple) # inp: pid
seenpid = []
i = 0 # y x
for pid, align in aligns.items(): picmap[0][0] = firstID
print(pid, align) print(firstID)
if( i == 0 ): for pid, fit in fits.items():
coords = (0, 0) if(pid == firstID):
rotmap[coords[1]][coords[0]] = pid
rotcoords[pid] = coords
seenpid.append(pid)
continue continue
for pos, fitin in fit.items():
if(pos != "E"):
fitID, fitDIR = fitin[0], fitin[1]
print(f"{pid=} {pos=} : {fitID=} {fitDIR=}")
selfside = align[0] else:
matchside = align[2] continue
matchid = align[1]
# while(len(rots) < len(pics)):
# for pid, fit in aligns.items():
# if(len(seenpid) >= len(aligns)):
# break
# if(pid in seenpid):
# continue
# seenpid.append(pid)
# if(len(rotmap) <= 0):
# rotmap[0][0] = pid
# rots[pid] = (0, 0)
# fitid = fit[1]
# conRot = fit[0]
# myRot = fit[2]
# coords = rots[pid]
# print(f"{pid} : {coords} : {fitid} |", end=" ")
# if(len(coords) < 2):
# print("no coords")
# continue
# x, y = coords[0], coords[1]
# if(conRot == 0):
# # put the connected one above it
# # x y is reversed because lists index and stuff
# rots[fitid] = (x, y-1)
# print(f"new coord: {rots[fitid]}")
# elif(conRot == 1):
# # right of
# rots[fitid] = (x+1, y)
# print(f"new coord: {rots[fitid]}")
# elif(conRot == 2):
# # down of
# rots[fitid] = (x, y+1)
# print(f"new coord: {rots[fitid]}")
# elif(conRot == 3):
# # left of
# rots[fitid] = (x-1, y)
# print(f"{fitid} new coord: {rots[fitid]}")
# print(rots)
# def rotateClock( rots, picRot, face ):
# clock = copyList(picRot)
# clocklen = len(clock)
# facei = face
# facei += rots
# while(facei < 0):
# facei += clocklen
# facei = facei % clocklen
# face = clock[facei]
# return face
# fitmap = dict()
# for pid, fits in aligns.items():
# side, fitid, fitside, flipside = fits
# newside = rotateTile(side, fitside)

Loading…
Cancel
Save