Advertisement
Guest User

Untitled

a guest
Dec 24th, 2020
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 4.47 KB | None | 0 0
  1. import Foundation
  2. import utils
  3.  
  4. enum Direction: CaseIterable {
  5.     case west
  6.     case northwest
  7.     case southwest
  8.     case east
  9.     case northeast
  10.     case southeast
  11. }
  12.  
  13. struct HexPoint: Hashable, Equatable {
  14.     let x: Int
  15.     let y: Int
  16.     let z: Int
  17.  
  18.     init() {
  19.         self.x = 0
  20.         self.y = 0
  21.         self.z = 0
  22.     }
  23.    
  24.     init(_ direction: Direction) {
  25.         switch direction {
  26.         case .west:
  27.             self.init(-1, 1, 0)
  28.         case .northwest:
  29.             self.init(0, 1, -1)
  30.         case .southwest:
  31.             self.init(-1, 0, 1)
  32.         case .east:
  33.             self.init(1, -1, 0)
  34.         case .northeast:
  35.             self.init(1, 0, -1)
  36.         case .southeast:
  37.             self.init(0, -1, 1)
  38.         }
  39.     }
  40.    
  41.     init(_ x: Int, _ y: Int, _ z: Int) {
  42.         self.x = x
  43.         self.y = y
  44.         self.z = z
  45.     }
  46.  
  47.     static func == (lhs: HexPoint, rhs: HexPoint) -> Bool {
  48.         return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z
  49.     }
  50.  
  51.     static func + (lhs: HexPoint, rhs: HexPoint) -> HexPoint {
  52.         return HexPoint(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z)
  53.     }
  54. }
  55.  
  56. func parseLine(_ line: String) -> [Direction] {
  57.    
  58.     var directions = [String]()
  59.  
  60.     let mapping: [String: Direction] = ["nw": .northwest,
  61.                                         "w": .west,
  62.                                         "sw": .southwest,
  63.                                         "ne": .northeast,
  64.                                         "e": .east,
  65.                                         "se": .southeast]
  66.  
  67.     let chars = Array(line)
  68.     var idx = 0
  69.     while idx < chars.count {
  70.         switch chars[idx] {
  71.         case "n", "s":
  72.             directions.append(String(chars[idx...(idx+1)]))
  73.             idx += 2
  74.         default:
  75.             directions.append(String(chars[idx]))
  76.             idx += 1
  77.         }
  78.     }
  79.     return directions.map({mapping[$0]!})
  80. }
  81.  
  82. func flipTile(_ line: String) -> HexPoint {
  83.         return parseLine(line).reduce(HexPoint(), {x, dir in x + HexPoint(dir)})
  84. }
  85.  
  86. func part1(_ lines: [String]) -> Int {
  87.  
  88.     var tiles = [HexPoint: Int]()
  89.  
  90.     for line in lines {
  91.         let tile = flipTile(line)
  92.         if tiles[tile] == nil {
  93.             tiles[tile] = 1
  94.         }
  95.         else {
  96.             tiles[tile]! += 1
  97.         }
  98.     }
  99.    
  100.     return tiles.values.reduce(0, {x, y in x + Int(y % 2 == 1)})
  101. }
  102.  
  103. func part2(_ lines: [String]) -> Int {
  104.  
  105.     enum Color {
  106.         case white
  107.         case black
  108.     }
  109.  
  110.     typealias Grid = [HexPoint: Color]
  111.    
  112.     func initGrid() -> Grid {
  113.         var grid = Grid()
  114.         for line in lines {
  115.             let tile = flipTile(line)
  116.             if let color = grid[tile] {
  117.                 grid[tile] = (color == .black) ? .white : .black
  118.             }
  119.             else {
  120.                 grid[tile] = .black
  121.             }
  122.         }
  123.         return grid
  124.     }
  125.    
  126.     func expandGrid(_ grid: inout Grid) {
  127.         for point in grid.filter({$0.value == .black}).keys {
  128.             for direction in Direction.allCases {
  129.                 let otherPoint = point + HexPoint(direction)
  130.                 if grid[otherPoint] == nil {
  131.                     grid[otherPoint] = .white
  132.                 }
  133.             }
  134.         }  
  135.     }
  136.  
  137.     func applyRules(_ grid: inout Grid) {
  138.         var changes = Grid()
  139.  
  140.         for (point, color) in grid {
  141.  
  142.             var nAdjacentBlacks = 0
  143.             for direction in Direction.allCases {
  144.                 let adjPoint = point + HexPoint(direction)
  145.                 if let c = grid[adjPoint] {
  146.                     nAdjacentBlacks += Int(c == .black)
  147.                 }
  148.             }
  149.                
  150.             switch color {
  151.             case .black:
  152.                 if nAdjacentBlacks == 0 || nAdjacentBlacks > 2 {
  153.                     changes[point] = .white
  154.                 }
  155.             case .white:
  156.                 if nAdjacentBlacks == 2 {
  157.                     changes[point] = .black
  158.                 }
  159.             }
  160.         }
  161.  
  162.         for (point, color) in changes {
  163.             grid[point] = color
  164.         }
  165.     }
  166.    
  167.     var grid = initGrid()
  168.     for _ in (0..<100) {
  169.         expandGrid(&grid)
  170.         applyRules(&grid)
  171.     }
  172.    
  173.     return grid.reduce(0, {x, y in x + Int(y.value == .black)})
  174. }
  175.  
  176. let filename = getFilename(day: 24)
  177. let lines = getLines(from: filename)
  178.  
  179.  
  180. print("Part 1")
  181. print("--", part1(lines))
  182. print("Part 2")
  183. print("--", part2(lines))
  184.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement