Skip to content

Commit

Permalink
tiles placed in correct locations
Browse files Browse the repository at this point in the history
  • Loading branch information
2bjake committed Dec 20, 2020
1 parent 2ce15d6 commit 0a68212
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 22 deletions.
6 changes: 6 additions & 0 deletions day20/Sources/day20/Tile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import Foundation

enum TileType { case edge, corner, regular }

struct Tile: Hashable {
let id: Int
let data: [[Character]]
Expand Down Expand Up @@ -41,3 +43,7 @@ extension Tile {

}
}

extension Tile: CustomStringConvertible {
var description: String { "\(id)" }
}
63 changes: 48 additions & 15 deletions day20/Sources/day20/TileSorter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,79 @@

import Foundation

enum TileType { case edge, corner, nonEdge }
typealias TilesByEdge = [Edge: Set<Tile>]

struct TileSorter {

//private var tilesByType: [TileType: Set<Tile>]
private func buildTilesByEdge(_ tiles: Set<Tile>) -> TilesByEdge {
let tilesByEdge: [Edge: Set<Tile>] = tiles.reduce(into: [:]) { result, value in
for edge in value.allEdges {
result[edge, default: []].insert(value)
}
}
return tilesByEdge
}

var cornerTiles: Set<Tile>
var edgeTiles: Set<Tile>
var nonEdgeTiles: Set<Tile>
struct TileSorter {
var cornerTiles: Set<Tile> {
Set(tilesByTypeByEdge[.corner]?.values.flatMap { $0 } ?? [])
}

var tilesByEdge: [Edge: [Tile]]
private var tilesByTypeByEdge: [TileType: TilesByEdge]

init(_ source: String) {
let allTiles = Set(source.components(separatedBy: "\n\n").map(Tile.init))

tilesByEdge = allTiles.reduce(into: [:]) { result, value in
let tilesByEdge: [Edge: [Tile]] = allTiles.reduce(into: [:]) { result, value in
for edge in value.allEdges {
result[edge, default: []].append(value)
}
}

edgeTiles = Set(tilesByEdge.values.filter { $0.count == 1 }.flatMap { $0 })
var edgeTiles = Set(tilesByEdge.values.filter { $0.count == 1 }.flatMap { $0 })

nonEdgeTiles = allTiles.subtracting(edgeTiles)
let nonEdgeTiles = allTiles.subtracting(edgeTiles)

let edgeToCount: [Edge: Int] = edgeTiles.reduce(into: [:]) { result, value in
for edge in value.allEdges {
result[edge, default: 0] += 1
}
}

cornerTiles = edgeTiles.filter { tile in
let cornerTiles = edgeTiles.filter { tile in
guard tile.horizontalEdges.compactMap({ edgeToCount[$0] }).reduce(0, +) == 3 else { return false }
guard tile.verticalEdges.compactMap({ edgeToCount[$0] }).reduce(0, +) == 3 else { return false }
return true
}
edgeTiles.subtract(cornerTiles)


tilesByTypeByEdge = [
.corner: buildTilesByEdge(cornerTiles),
.edge: buildTilesByEdge(edgeTiles),
.regular: buildTilesByEdge(nonEdgeTiles)
]
}

// mutating func removeTile(_ type: TileType, matching: Tile, edge: Edge.Side) -> Tile? {
//
// }
mutating func removeEdge(_ edge: Edge) {
tilesByTypeByEdge[.corner]?[edge] = nil
tilesByTypeByEdge[.edge]?[edge] = nil
tilesByTypeByEdge[.regular]?[edge] = nil
}

// returns the tile of the specified type which matches an edge of the specified tile.
// NOTE: if a match is found, the edge is removed from the sorter so it won't be found again
mutating func findMatch(_ type: TileType, matching: Tile) -> Tile? {
for edge in matching.allEdges {
if let tiles = tilesByTypeByEdge[type]?[edge], let tile = tiles.first(where: { $0 != matching }) {
removeEdge(edge)
return tile
}
}
return nil
}

mutating func removeCommonEdge(_ a: Tile, _ b: Tile) {
let commonEdges = Set(a.allEdges).intersection(b.allEdges)
guard let edge = commonEdges.first, commonEdges.count == 1 else { fatalError("didn't expect multiple common edges")}
removeEdge(edge)
}
}
60 changes: 53 additions & 7 deletions day20/Sources/day20/main.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,61 @@
import Foundation

let sorter = TileSorter(input)
var sorter = TileSorter(input)
let cornerTileProduct = sorter.cornerTiles.map(\.id).reduce(1, *)
print("answer to part one: \(cornerTileProduct)") // 4006801655873

var puzzle: [[Tile?]] = Array(repeating: Array(repeating: nil, count: 12), count: 12)

puzzle[0][0] = sorter.cornerTiles.randomElement()
puzzle[0][0] = sorter.cornerTiles.first

func printPuzzle() {
for row in puzzle {
let values: [String] = row.map {
if let id = $0?.id {
return "\(id)"
} else {
return "----"
}
}
print(values)
}
}

func fillTopEdge() {
let cornerIdx = puzzle.count - 1
for i in 1..<cornerIdx {
puzzle[0][i] = sorter.findMatch(.edge, matching: puzzle[0][i - 1]!)
}

if puzzle[0][cornerIdx] == nil {
puzzle[0][cornerIdx] = sorter.findMatch(.corner, matching: puzzle[0][cornerIdx - 1]!)
}
}

func fillRow(_ rowIdx: Int) {
for i in rowIdx..<(puzzle.count - 1 - rowIdx) {
guard let match = sorter.findMatch(.regular, matching: puzzle[rowIdx - 1][i]!) else { fatalError() }
sorter.removeCommonEdge(match, puzzle[rowIdx][i - 1]!)
puzzle[rowIdx][i] = match
}
}

for _ in 0..<4 {
fillTopEdge()
puzzle.rotateLeft()
}

for i in 1...5 {
for _ in 0..<4 {
fillRow(i)
puzzle.rotateLeft()
}
}
printPuzzle()

let ids = puzzle.flatMap { $0 }.map { $0!.id }
print(ids.count)
print(Set(ids).count)

// 2789

//func fillTopEdge() {
// for i in 1..<(puzzle.count - 1) {
//
// }
//}

0 comments on commit 0a68212

Please sign in to comment.