@@ -23,89 +23,63 @@ object Day12 {
2323 }
2424
2525 object NaiveSolution extends Solution {
26- /* def fits(shapes: Seq[Shape])(region: Region): Boolean = {
27-
28- def helper(grid: Grid[Boolean], shapeCounts: Seq[Int]): Boolean = {
29- val shapeI = shapeCounts.indexWhere(_ > 0)
30- if (shapeI < 0)
31- true // nothing more to fit
32- else {
33- val newShapeCounts = shapeCounts.updated(shapeI, shapeCounts(shapeI) - 1)
34- val shape = shapes(shapeI)
35- (for {
36- shapeOrientation <- shape.orientations.iterator
37- shapeOrientationSize = Pos(shapeOrientation(0).size, shapeOrientation.size)
38- shapeOrientationBox = Box(Pos.zero, region.size - shapeOrientationSize)
39- shapeOrientationBox2 = Box(Pos.zero, shapeOrientationSize - Pos(1, 1))
40- pos <- shapeOrientationBox.iterator
41- if shapeOrientationBox2.iterator.forall(p => !(shapeOrientation(p) && grid(pos + p)))
42- newGrid = shapeOrientationBox2.iterator.foldLeft(grid)((newGrid, p) => newGrid.updatedGrid(pos + p, true))
43- } yield helper(newGrid, newShapeCounts)).exists(identity)
44- }
45- }
46-
47- val initialGrid = Vector.fill(region.size.y, region.size.x)(false)
48- helper(initialGrid, region.shapeCounts)
49- }*/
50-
51- // probably broken: skips over poss when finding place for a shape
5226 override def fits (shapes : Seq [Shape ])(region : Region ): Boolean = {
5327 val shapeOrientationBox = Box (Pos .zero, region.size - Pos (3 , 3 )) // assuming all shappes of same size
5428
55- def helper (grid : Grid [Boolean ], shapeCounts : Seq [Int ], poss : List [Pos ]): Boolean = {
29+ val shapeOrientations = shapes.map(_.orientations.toSet)
30+
31+ def helper (grid : Grid [Boolean ], shapeCounts : Seq [Int ], poss : List [Pos ], depth : Int ): Boolean = {
32+ val indent = " " * depth
33+ // println(s"$indent: $shapeCounts")
34+ // for (row <- grid) {
35+ // print(indent)
36+ // for (cell <- row)
37+ // print(if (cell) '#' else '.')
38+ // println()
39+ // }
5640 val shapeI = shapeCounts.indexWhere(_ > 0 )
5741 if (shapeI < 0 )
5842 true // nothing more to fit
5943 else {
60- val newShapeCounts = shapeCounts.updated(shapeI, shapeCounts(shapeI) - 1 )
61- val shape = shapes(shapeI)
62- (for {
63- shapeOrientation <- shape.orientations.iterator
64- shapeOrientationSize = Pos (shapeOrientation(0 ).size, shapeOrientation.size)
65- shapeOrientationBox2 = Box (Pos .zero, shapeOrientationSize - Pos (1 , 1 ))
66- case pos :: newPoss <- poss.tails
67- if shapeOrientationBox2.iterator.forall(p => ! (shapeOrientation(p) && grid(pos + p)))
68- newGrid = shapeOrientationBox2.iterator.foldLeft(grid)((newGrid, p) => newGrid.updatedGrid(pos + p, shapeOrientation(p)))
69- } yield helper(newGrid, newShapeCounts, newPoss)).exists(identity)
44+ // val newShapeCounts = shapeCounts.updated(shapeI, shapeCounts(shapeI) - 1)
45+ // val shape = shapes(shapeI)
46+ if (poss.isEmpty)
47+ false
48+ else {
49+ val pos = poss.head
50+ // print(s"$indent $pos")
51+ val todo = region.size.x * region.size.y - pos.x * region.size.y - pos.y
52+ val areaLowerBound = // only counting the #-s in shapes
53+ shapes
54+ .map(_.countGrid(identity))
55+ .lazyZip(shapeCounts)
56+ .map(_ * _)
57+ .sum
58+ if (areaLowerBound > todo) {
59+ // println("bounded")
60+ false
61+ } else {
62+ // println()
63+ val newPoss = poss.tail
64+ (for {
65+ ((shapeO, count), shapeI) <- shapeOrientations.lazyZip(shapeCounts).zipWithIndex
66+ if count > 0
67+ newShapeCounts = shapeCounts.updated(shapeI, count - 1 )
68+ shapeOrientation <- shapeO.iterator
69+ shapeOrientationSize = Pos (shapeOrientation(0 ).size, shapeOrientation.size)
70+ shapeOrientationBox2 = Box (Pos .zero, shapeOrientationSize - Pos (1 , 1 ))
71+ if shapeOrientationBox2.iterator.forall(p => ! (shapeOrientation(p) && grid(pos + p)))
72+ newGrid = shapeOrientationBox2.iterator.foldLeft(grid)((newGrid, p) => newGrid.updatedGrid(pos + p, newGrid(pos + p) || shapeOrientation(p)))
73+ } yield helper(newGrid, newShapeCounts, newPoss, depth + 1 )).exists(identity) ||
74+ ! Box (Pos .zero, Pos (2 , 2 )).iterator.forall(p => ! grid(pos + p)) && helper(grid, shapeCounts, newPoss, depth + 1 ) // or don't place anything here
75+ }
76+ }
7077 }
7178 }
7279
7380 val initialGrid = Vector .fill(region.size.y, region.size.x)(false )
74- helper(initialGrid, region.shapeCounts, shapeOrientationBox.iterator.toList)
75- }
76-
77- /* def fits(shapes: Seq[Shape])(region: Region): Boolean = {
78- val shapeOrientationBox = Box(Pos.zero, region.size - Pos(3, 3)) // assuming all shappes of same size
79-
80- def helper(grid: Grid[Boolean], shapeCounts: Seq[Int], poss: List[Pos]): Boolean = {
81- val shapeI = shapeCounts.indexWhere(_ > 0)
82- if (shapeI < 0)
83- true // nothing more to fit
84- else {
85- //val newShapeCounts = shapeCounts.updated(shapeI, shapeCounts(shapeI) - 1)
86- //val shape = shapes(shapeI)
87- if (poss.isEmpty)
88- false
89- else {
90- val pos = poss.head
91- val newPoss = poss.tail
92- (for {
93- ((shape, count), shapeI) <- shapes.lazyZip(shapeCounts).zipWithIndex
94- if count > 0
95- newShapeCounts = shapeCounts.updated(shapeI, count - 1)
96- shapeOrientation <- shape.orientations.iterator
97- shapeOrientationSize = Pos(shapeOrientation(0).size, shapeOrientation.size)
98- shapeOrientationBox2 = Box(Pos.zero, shapeOrientationSize - Pos(1, 1))
99- if shapeOrientationBox2.iterator.forall(p => !(shapeOrientation(p) && grid(pos + p)))
100- newGrid = shapeOrientationBox2.iterator.foldLeft(grid)((newGrid, p) => newGrid.updatedGrid(pos + p, shapeOrientation(p)))
101- } yield helper(newGrid, newShapeCounts, newPoss)).exists(identity) || helper(grid, shapeCounts, newPoss) // or don't place anything here
102- }
103- }
81+ helper(initialGrid, region.shapeCounts, shapeOrientationBox.iterator.toList, 0 )
10482 }
105-
106- val initialGrid = Vector.fill(region.size.y, region.size.x)(false)
107- helper(initialGrid, region.shapeCounts, shapeOrientationBox.iterator.toList)
108- }*/
10983 }
11084
11185 object SanitySolution extends Solution {
0 commit comments