this repo has no description
at main 161 lines 3.9 kB view raw
1import gleam/dict 2import gleam/function 3import gleam/io 4import gleam/list 5import gleam/result 6import gleam/set 7import gleam/string 8import simplifile 9import utils/utils 10 11type Type { 12 Tachion 13 Splitter 14} 15 16type Position { 17 Position(x: Int) 18} 19 20type Cell { 21 Cell(pos: Position, typ: Type) 22} 23 24pub fn start() -> Nil { 25 let assert Ok(content) = simplifile.read("inputs/day7.txt") 26 let data = parse(content) 27 28 let _ = io.debug(part1(data)) 29 let _ = io.debug(part2(data)) 30 31 Nil 32} 33 34fn parse(data: String) { 35 string.split(data, "\n") 36 |> list.index_map(fn(l, _) { 37 list.index_map(string.to_graphemes(l), fn(c, x) { 38 case c { 39 "S" -> Ok(Cell(Position(x), Tachion)) 40 "^" -> Ok(Cell(Position(x), Splitter)) 41 42 // Should never happen 43 _ -> Error(Nil) 44 } 45 }) 46 |> list.filter_map(function.identity) 47 }) 48 |> list.filter(fn(x) { !list.is_empty(x) }) 49} 50 51type Res { 52 Res(splits: Int, tachions: List(Cell)) 53} 54 55fn part1(data: List(List(Cell))) { 56 let res = 57 list.fold(data, Res(0, []), fn(acc, cells_on_line) { 58 let new_tachions = 59 list.map(cells_on_line, fn(c) { 60 case c.typ { 61 Tachion -> #([c], 0, []) 62 Splitter -> { 63 let Position(cx) = c.pos 64 case list.find(acc.tachions, fn(x) { x.pos.x == cx }) { 65 Ok(c) -> #( 66 [ 67 Cell(Position(cx - 1), Tachion), 68 Cell(Position(cx + 1), Tachion), 69 ], 70 1, 71 [c], 72 ) 73 Error(_) -> #([], 0, []) 74 } 75 } 76 } 77 }) 78 79 let used_tachions = 80 list.fold(new_tachions, [], fn(acc, x) { [x.2, ..acc] }) 81 |> list.flatten 82 |> list.fold(set.new(), set.insert) 83 |> set.to_list 84 85 let new_splits = 86 acc.splits + list.fold(new_tachions, 0, fn(acc, t) { acc + t.1 }) 87 88 let new_tachions = 89 list.map(new_tachions, fn(x) { x.0 }) 90 |> list.filter(fn(x) { !list.is_empty(x) }) 91 |> list.flatten 92 93 let tachions = 94 list.filter(acc.tachions, fn(x) { !list.contains(used_tachions, x) }) 95 |> list.append(new_tachions) 96 |> list.fold(set.new(), set.insert) 97 |> set.to_list 98 99 Res(new_splits, tachions) 100 }) 101 102 res.splits 103} 104 105type Cache = 106 dict.Dict(#(Int, Int), Int) 107 108fn rec( 109 line: Int, 110 next: List(List(Cell)), 111 depth: Int, 112 cache: Cache, 113) -> #(Int, Cache) { 114 let next_splitter = 115 utils.list_find_indexes(next, fn(x) { 116 result.is_ok(list.find(x, fn(y) { y.pos.x == line && y.typ == Splitter })) 117 }) 118 |> list.filter(fn(x) { x > depth }) 119 |> list.first() 120 121 case next_splitter { 122 Ok(lidx) -> { 123 let assert Ok(l) = list.drop(next, lidx) |> list.first 124 let assert Ok(splitter) = 125 list.find(l, fn(y) { y.pos.x == line && y.typ == Splitter }) 126 127 // Check left Side 128 let #(left, cache) = case 129 dict.has_key(cache, #(splitter.pos.x - 1, lidx)) 130 { 131 True -> { 132 let assert Ok(v) = dict.get(cache, #(splitter.pos.x - 1, lidx)) 133 #(v, cache) 134 } 135 False -> rec(splitter.pos.x - 1, next, lidx, cache) 136 } 137 let cache = dict.insert(cache, #(splitter.pos.x - 1, lidx), left) 138 139 // Check right Side 140 let #(right, cache) = case 141 dict.has_key(cache, #(splitter.pos.x + 1, lidx)) 142 { 143 True -> { 144 let assert Ok(v) = dict.get(cache, #(splitter.pos.x + 1, lidx)) 145 #(v, cache) 146 } 147 False -> rec(splitter.pos.x + 1, next, lidx, cache) 148 } 149 let cache = dict.insert(cache, #(splitter.pos.x + 1, lidx), right) 150 151 #(left + right, cache) 152 } 153 Error(_) -> #(1, cache) 154 } 155} 156 157fn part2(data: List(List(Cell))) { 158 let assert Ok(fl) = list.first(data) 159 let assert Ok(t) = list.first(fl) 160 rec(t.pos.x, data, 0, dict.new()).0 161}