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