11import Algorithms
22
3+ enum Border : Hashable {
4+ case north( y: Int )
5+ case east( x: Int )
6+ case south( y: Int )
7+ case west( x: Int )
8+
9+ static func create( direction: Int , coord: Coord ) -> ( Self , Int ) {
10+ switch direction {
11+ case 0 : ( north ( y: coord. y) , coord. x)
12+ case 1 : ( east ( x: coord. x) , coord. y)
13+ case 2 : ( south ( y: coord. y) , coord. x)
14+ case 3 : ( west ( x: coord. x) , coord. y)
15+ default : ( north ( y: - 1 ) , - 1 )
16+ }
17+ }
18+
19+ func toCardDirection( ) -> CardDirection {
20+ switch self {
21+ case . north: . north
22+ case . south: . south
23+ case . east: . east
24+ case . west: . west
25+ }
26+ }
27+
28+ }
29+
30+ enum CardDirection : Int , CustomStringConvertible {
31+ var description : String {
32+ switch self {
33+ case . north: " N "
34+ case . south: " S "
35+ case . east: " E "
36+ case . west: " W "
37+ }
38+ }
39+
40+ case north = 0
41+ case east
42+ case south
43+ case west
44+ }
45+
46+ struct Side : CustomStringConvertible {
47+ var description : String {
48+ " Side( \( direction) | \( border) \( values) ) "
49+ }
50+
51+ var direction : CardDirection
52+ var border : Border
53+ var values : [ Int ]
54+ }
55+
356struct Field {
457 var id : Character
5- var area : Int = 1
58+ var area : Int = 0
659 var perimeter : Int = 0
760 var coords : [ Coord ] = [ Coord] ( )
61+ var sides : [ Border : [ Int ] ] = [ Border: [ Int] ] ( )
62+ var sideCount : Int {
63+ let allSides = sides. values. map { side in
64+ let sortedSide = side. sorted ( )
65+ print ( " sorted " , sortedSide)
66+ return zip ( sortedSide, sortedSide. dropFirst ( ) ) . map { $1 - $0 } . filter { $0 > 1 } . count + 1
67+ }
68+ print ( " allsides " , allSides)
69+ return allSides. compactMap { $0 } . count
70+ }
871
9- func compute( ) -> Int {
72+ // mutating func extendSides(idx: Int, pos: Coord) {
73+ // let (border, otherAxis) = Border.create(direction: idx, coord: pos)
74+ // let sideIdx = sides.firstIndex { side in
75+ // if side.direction == border.toCardDirection() && side.border == border {
76+ // let max = side.values.max() ?? -1
77+ // let min = side.values.min() ?? -1
78+ // if max + 1 == otherAxis || min - 1 == otherAxis {
79+ // return true
80+ // }
81+ // }
82+ // return false
83+ // }
84+ // if let sideIdx {
85+ // sides[sideIdx].values.append(otherAxis)
86+ // } else {
87+ // sides.append(Side(direction: border.toCardDirection(), border: border, values: [otherAxis]))
88+ // }
89+ // }
90+
91+ mutating func addSide( idx: Int , pos: Coord ) {
92+ let ( border, otherAxis) = Border . create ( direction: idx, coord: pos)
93+ sides [ border, default: [ ] ] . append ( otherAxis)
94+ }
95+
96+ func compute1( ) -> Int {
1097 area * perimeter
1198 }
99+ func compute2( ) -> Int {
100+ sideCount * area
101+ }
12102
13103 mutating func visited( coord: Coord ) {
14104 coords. append ( coord)
@@ -17,7 +107,7 @@ struct Field {
17107extension Field {
18108 init ( id: Character ) {
19109 self . id = id
20- area = 1
110+ area = 0
21111 perimeter = 0
22112 }
23113}
@@ -34,58 +124,67 @@ struct Day12: AdventDay {
34124 field. visited ( coord: pos)
35125 field. area += 1
36126 // explore the grid
37- for neighbor in pos. crossNeighbors {
38- print ( " checking for " , neighbor)
127+ for (idx, neighbor) in pos. crossNeighbors. enumerated ( ) {
128+ if field. coords. contains ( neighbor) {
129+ continue
130+ }
39131 if let candidate = grid [ neighbor] {
40132 if candidate == id {
41- print ( " we are together " )
42133 // same value means we have a new area tile
43- return exploreField ( from: neighbor, id: id, field: field)
134+ field = exploreField ( from: neighbor, id: id, field: field)
44135 } else {
45- print ( " someone else " )
46136 // this is a frontier
47137 field. perimeter += 1
138+ field. addSide ( idx: idx, pos: neighbor)
139+ // print("border found at", pos)
140+ // print(field.sides)
48141 }
49142 } else {
50- print ( " grid boundary " )
51143 // this is the frontier of the grid
52144 field. perimeter += 1
145+ field. addSide ( idx: idx, pos: neighbor)
146+ // print(field.sideCount)
147+
53148 }
54149 }
55150 return field
56151 }
57152
58- func part1( ) -> Int {
59-
153+ func getFields( ) -> [ Field ] {
60154 var record = [ Coord: Bool] ( )
61155 var fields = [ Field] ( )
62156 for y in 0 ..< grid. height {
63157 for x in 0 ..< grid. width {
64158 let currentPos = Coord ( x: x, y: y)
65- print ( currentPos)
66159 // position has already been visited
67160 guard record [ currentPos] == nil else {
68- print ( " already visited " )
69161 continue
70162 }
71163
72164 if let gridValue = grid [ currentPos] {
73165 // start a new field
74- print ( " starting a new field " )
75166 let field = exploreField (
76167 from: currentPos, id: gridValue, field: Field ( id: gridValue) )
77168 fields. append ( field)
78169 field. coords. forEach { s in
79170 record [ s] = true
80171 }
81- print ( " ------- " , field)
172+ print ( " sides of " , gridValue , field. sideCount )
82173 }
83174 }
84175 }
85- return fields. map { $0. compute ( ) } . sum
176+ return fields
177+ }
178+
179+ func part1( ) -> Int {
180+
181+ return getFields ( ) . map { $0. compute1 ( ) } . sum
86182 }
87183
88184 func part2( ) -> Int {
89- 0
185+ // merge sides that are next to each other
186+
187+ return getFields ( ) . map { $0. compute2 ( ) } . sum
188+
90189 }
91190}
0 commit comments