open System.IO let readLines (filePath: string) = seq { use sr = new StreamReader (filePath) while not sr.EndOfStream do yield sr.ReadLine() } type Pos = { x: int; y: int } type Slope = { x: int; y: int } type Tile = | Open | Tree type Map = { tiles: Tile list list } let createMap (lines: string seq): Map = { Map.tiles = [ for line in lines do [ for char in line do if char = '#' then Tile.Tree else Tile.Open ] ] } let getMaxPos (map: Map): Pos = { Pos.x = map.tiles.[0].Length - 1; y = map.tiles.Length - 1 } let advancePos (pos: Pos) (slope: Slope) (maxPos: Pos): (bool * Pos) = if (pos.y + slope.y > maxPos.y) then (true, pos) else if pos.x + slope.x > maxPos.x then (false, { Pos.x = ((pos.x + slope.x) % maxPos.x) - 1; y = pos.y + slope.y }) else (false, { Pos.x = pos.x + slope.x; y = pos.y + slope.y }) let rec checkSlope (map: Map) (pos: Pos) (slope: Slope) (maxPos: Pos) (count: int64): int64 = match advancePos pos slope maxPos with | (true, { Pos.x = x; Pos.y = y }) -> count | (false, { Pos.x = x; Pos.y = y }) -> if map.tiles.[y].[x] = Tile.Tree then checkSlope map { Pos.x = x; Pos.y = y } slope maxPos (count + 1L) else checkSlope map { Pos.x = x; Pos.y = y } slope maxPos (count) [<EntryPoint>] let main argv = let lines = readLines "input.txt" let map = createMap lines let maxPos = getMaxPos map let count1 = checkSlope map { Pos.x = 0; y = 0 } { Slope.x = 1; y = 1 } maxPos 0L let count2 = checkSlope map { Pos.x = 0; y = 0 } { Slope.x = 3; y = 1 } maxPos 0L let count3 = checkSlope map { Pos.x = 0; y = 0 } { Slope.x = 5; y = 1 } maxPos 0L let count4 = checkSlope map { Pos.x = 0; y = 0 } { Slope.x = 7; y = 1 } maxPos 0L let count5 = checkSlope map { Pos.x = 0; y = 0 } { Slope.x = 1; y = 2 } maxPos 0L let part1 = count2 let part2 = count1 * count2 * count3 * count4 * count5 printf "%d, %d\n" part1 part2 0