Skip to content

Commit

Permalink
Day10 and Day11
Browse files Browse the repository at this point in the history
  • Loading branch information
JimWallace committed Dec 11, 2023
1 parent 32f81e5 commit 84d1ed2
Show file tree
Hide file tree
Showing 8 changed files with 861 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Sources/AdventOfCode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import ArgumentParser

// Add each new day implementation to this array:
let allChallenges: [any AdventDay] = [
Day00(), Day01(), Day02(), Day03(), Day04(), Day05(), Day06(), Day07(), Day08(), Day09()
Day00(), Day01(), Day02(), Day03(), Day04(), Day05(), Day06(), Day07(), Day08(), Day09(), Day10(), Day11()
]

@main
Expand Down
140 changes: 140 additions & 0 deletions Sources/Data/Day10.txt

Large diffs are not rendered by default.

140 changes: 140 additions & 0 deletions Sources/Data/Day11.txt

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Sources/Day09.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct Day09: AdventDay {

func extrapolateFirst(_ samples: [Int]) -> Int {

print("> \(samples)")
//print("> \(samples)")
if samples.allSatisfy({ $0 == 0 }) {
return 0
}
Expand All @@ -52,10 +52,10 @@ struct Day09: AdventDay {
func part2() -> Any {
var nextSample: [Int] = [Int]()
for sample in samples {
print(sample)
//print(sample)
nextSample.append( extrapolateFirst(sample) )
}
print(nextSample)
//print(nextSample)
return nextSample.reduce(0, +)
}
}
281 changes: 281 additions & 0 deletions Sources/Day10.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
import Algorithms
import Foundation

struct Day10: AdventDay {

// Save your data in a corresponding text file in the `Data` directory.
let data: String
let lines: [String]

var startX: Int = -1
var startY: Int = -1

//var searchNext: [(Int,Int)]
//var steps: Int = 0

init(data: String) {
self.data = data
self.lines = data.components(separatedBy: CharacterSet.newlines).filter { !$0.isEmpty }

//self.searchNext = [(Int, Int)]()

// Add the S point
for (y, _ ) in lines.enumerated() {
for (x, _ ) in lines[y].enumerated() {
if charAt(x, y).rawValue == "S" {
startX = x
startY = y
//searchNext.append( (x,y) )
}
}
}
}

func printGrid() {
for y in lines {
print(y)
}
}

func getGrid() -> [[PipeTile]] {
var result = [[PipeTile]]()
for (y, _ ) in lines.enumerated() {
var currentRow: [PipeTile] = [PipeTile]()
for (x, _ ) in lines[y].enumerated() {
currentRow.append( charAt(x,y) )
}
result.append(currentRow)
}
return result
}

func printGrid(_ grid: [[PipeTile]]) {
for y in 0 ..< grid.count {
var row: String = ""
for x in 0 ..< grid[y].count {
row += grid[y][x].rawValue
}
print(row)
}
}


// @inlinable
// func charAt(_ x: Int, _ y: Int) -> Character {
// if x < 0 || y < 0 || y >= lines.count || x >= lines[y].count {
// return "."
// }
// let row = lines[y]
// return row[ row.index( row.startIndex, offsetBy: x)]
// }

@inlinable
func charAt(_ x: Int, _ y: Int) -> PipeTile {
if x < 0 || y < 0 || y >= lines.count || x >= lines[y].count {
return .ground
}
let row = lines[y]
return PipeTile(rawValue: String(row[ row.index( row.startIndex, offsetBy: x)])) ?? .ground
}

@inlinable
func isConnected( _ x1: Int, _ y1: Int, _ x2: Int, _ y2: Int) -> Bool {

let start: PipeTile = charAt(x1,y1)
let end: PipeTile = charAt(x2,y2)

// <----
if x1 > x2 {
if start == .start || start == .horizontal || start == .NWbend || start == .SWbend {
return end == .horizontal || end == .NEbend || end == .SEbend
}
}

// ---->
if x1 < x2 {
if start == .start || start == .horizontal || start == .NEbend || start == .SEbend {
return end == .horizontal || end == .NWbend || end == .SWbend
}
}

// ^^^^^
if y1 > y2 {
if start == .start || start == .vertical || start == .NEbend || start == .NWbend {
return end == .vertical || end == .SEbend || end == .SWbend
}
}

// VVVVVVV
if y1 < y2 {
if start == .start || start == .vertical || start == .SEbend || start == .SWbend {
return end == .vertical || end == .NEbend || end == .NWbend
}
}

// Ground, error, etc.
return false
}

func bfs(_ x: Int, _ y: Int, _ map: inout [[PipeTile]]) -> [(Int, Int)] {
var result: [(Int, Int)] = [(Int,Int)]()

// North
if isConnected(x, y, x, y - 1) && map[y - 1][x] != .explored {
result.append((x,y-1))
map[y-1][x] = .explored
}

// East
if isConnected(x, y, x + 1, y) && map[y][x + 1] != .explored {
result.append((x + 1,y))
map[y][x + 1] = .explored
}

// South
if isConnected(x, y, x, y + 1) && map[y + 1][x] != .explored {
result.append((x,y + 1))
map[y + 1][x] = .explored
}

// West
if isConnected(x, y, x - 1, y) && map[y][x - 1] != .explored {
result.append((x - 1,y))
map[y][x - 1] = .explored
}

return result
}


func fill(_ x: Int, _ y: Int, _ map: inout [[PipeTile]], _ value: PipeTile) {
var searchNext: [(Int, Int)] = [(Int,Int)]()
searchNext.append( (x, y) )

// Find the loop
while !searchNext.isEmpty {
let next = searchNext.removeFirst()
map[next.1][next.0] = value
let bfs = fillBFS(next.0, next.1, &map)
//print(bfs)
searchNext.append(contentsOf: bfs)
}
}

func fillBFS(_ x: Int, _ y: Int, _ map: inout [[PipeTile]]) -> [(Int, Int)] {

var result: [(Int, Int)] = [(Int,Int)]()

if !inRange(x,y,map) { return result }

// North
if inRange(x,y - 1,map) && map[y - 1][x] == .ground {
result.append((x,y-1))
}

// East
if inRange(x + 1,y,map) && map[y][x + 1] == .ground {
result.append((x + 1,y))
}

// South
if inRange(x,y + 1,map) && map[y + 1][x] == .ground {
result.append((x,y + 1))
}

// West
if inRange(x - 1,y,map) && map[y][x - 1] == .ground {
result.append((x - 1,y))
}

return result
}

func inRange(_ x: Int, _ y: Int, _ map: [[PipeTile]]) -> Bool {
if x < 0 || y < 0 || y >= map.count || x >= map[y].count {
return false
}
return true
}

// Replace this with your solution for the first part of the day's challenge.
func part1() -> Any {

var searchNext: [(Int, Int)] = [(Int,Int)]()
searchNext.append( (startX, startY) )
var steps: Int = 0

var myMap: [[PipeTile]] = getGrid()

// Find the loop
while !searchNext.isEmpty {
let next = searchNext.removeFirst()
let bfs = bfs(next.0, next.1, &myMap)
searchNext.append(contentsOf: bfs)
steps += 1
}

// return
return Int(ceil(Double(steps)/2.0))
}

// Replace this with your solution for the second part of the day's challenge.
func part2() -> Any {

var searchNext: [(Int, Int)] = [(Int,Int)]()
searchNext.append( (startX, startY) )
var steps: Int = 0

var myMap: [[PipeTile]] = getGrid()

// Find the loop
while !searchNext.isEmpty {
let next = searchNext.removeFirst()
let bfs = bfs(next.0, next.1, &myMap)
searchNext.append(contentsOf: bfs)
steps += 1
}
myMap[startY][startX] = .explored
printGrid(myMap)
print("---")

var inside: Bool = false
for y in 0 ..< myMap.count {
inside = false
for x in 0 ..< myMap[y].count {
let tile = charAt(x,y)
//let marked = myMap[y][x] == .outside
if myMap[y][x] == .explored && tile != .horizontal && tile != .ground && tile != .SEbend && tile != .SWbend && tile != .start {
inside = !inside
}
// If we found some ground fill it in!
if myMap[y][x] != .explored && myMap[y][x] != .outside && !inside {
fill(x,y, &myMap, inside ? .inside : .outside )
//printGrid(myMap)
//print("---")
}

}
}
printGrid(myMap)

return myMap.flatMap{ $0 }.filter({$0 != PipeTile.explored && $0 != PipeTile.outside }).count
}
}


enum PipeTile: String, CustomStringConvertible {

case vertical = "|"
case horizontal = "-"
case NEbend = "L"
case NWbend = "J"
case SWbend = "7"
case SEbend = "F"
case ground = "."
case start = "S"
case explored = "X"
case inside = "I"
case outside = "O"

var description: String { rawValue }
}
Loading

0 comments on commit 84d1ed2

Please sign in to comment.