FSharp
(my first submission failed, so I may not be as detailed here)
I laugh at how long this took me. At first I got stuck due to checked arithmetic. In FSharp you open the Checked module and you get the overloaded operators for primitives, whereas CSharp is checked {a + b}. I also mistakenly used distinct on part 3 when I didn't need it.
I did appreciate the choose functions of functional programming, which returns all of the Some values of a sequence of options. The PSeq library let me use 70% of the cpu on the calculations :)
module EveryBodyCodes2025.Quest02
open System.IO
open System.Text.RegularExpressions
open FSharp.Collections.ParallelSeq
open Checked
[<Struct>]
type ComplexNumber =
{X: int64; Y: int64}
static member (+) (a: ComplexNumber, b: ComplexNumber) = {X = a.X + b.X; Y = a.Y + b.Y }
static member (*) (a: ComplexNumber, b: ComplexNumber) = { X = ( a.X * b.X ) - (a.Y * b.Y); Y = (a.X * b.Y) + (a.Y * b.X) }
static member (/) (a: ComplexNumber, b: ComplexNumber) = { X = a.X / b.X; Y = a.Y / b.Y }
override this.ToString() = $"[{this.X},{this.Y}]"
let parseInput file =
File.ReadAllLines file
|> fun lines ->
let reg = Regex(@"A=\[(-?\d+),(-?\d+)\]")
let res = reg.Match(lines[0])
match res.Success with
| true ->
let x = int64 res.Groups[1].Value
let y = int64 res.Groups[2].Value
{X = x; Y = y}
| false -> failwith "failed to parse"
let part1 () =
parseInput "Inputs/Quest02/Q02_P01.txt"
|> fun a ->
[1..3]
|> List.fold (fun acc _ -> (acc * acc) / { X = 10; Y = 10 } + a ) {X = 0; Y = 0}
let cycle p =
let rec iterate current iteration =
if iteration = 100 then Some current
else
let next = (current * current) / {X = 100_000; Y = 100_000 } + p
if abs(next.X) > 1_000_000 || abs(next.Y) > 1_000_000 then
None
else iterate next (iteration + 1)
iterate { X = 0; Y = 0 } 0
let part2 () =
parseInput "Inputs/Quest02/Q02_P02.txt"
|> fun a ->
seq {
for y in 0..100 do
for x in 0..100 do
yield {X = a.X + (int64 x * 10L); Y = a.Y + (int64 y * 10L)}
}
|> PSeq.choose cycle
|> PSeq.distinct
|> PSeq.length
let part3 () =
parseInput "Inputs/Quest02/Q02_P03.txt"
|> fun a ->
seq {
for y in 0..1000 do
for x in 0..1000 do
yield {X = a.X + (int64 x); Y = a.Y + (int64 y)}
}
|> PSeq.choose cycle
|> PSeq.length
That sounds amazingly infuriating! and hard to debug. I totally feel you there.