Compare commits

...

3 Commits

Author SHA1 Message Date
25644f23c8 quest 01 complete 2025-11-06 21:12:41 +01:00
bab84f0fe3 rename coding project bc I did the wrong one 2025-11-06 20:03:33 +01:00
3d0725272f quest 1, init 2025-11-05 17:10:51 +01:00
20 changed files with 616 additions and 0 deletions

13
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/.idea.coding-challenges.iml
/projectSettingsUpdater.xml
/modules.xml
/contentModel.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -0,0 +1,4 @@
bin
obj
.idea
*.DotSettings*

View File

@@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/projectSettingsUpdater.xml
/.idea.EveryBodyCodes2025.iml
/modules.xml
/contentModel.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "EveryBodyCodes_WrongOne", "EveryBodyCodes_WrongOne\EveryBodyCodes_WrongOne.fsproj", "{18C7585C-4183-4966-8217-A97E0E6200A8}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "EveryBodyCodes2025", "EveryBodyCodes2025\EveryBodyCodes2025.fsproj", "{17C27272-7D29-47A0-A3E1-27054D52D77F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{18C7585C-4183-4966-8217-A97E0E6200A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18C7585C-4183-4966-8217-A97E0E6200A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18C7585C-4183-4966-8217-A97E0E6200A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18C7585C-4183-4966-8217-A97E0E6200A8}.Release|Any CPU.Build.0 = Release|Any CPU
{17C27272-7D29-47A0-A3E1-27054D52D77F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{17C27272-7D29-47A0-A3E1-27054D52D77F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{17C27272-7D29-47A0-A3E1-27054D52D77F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{17C27272-7D29-47A0-A3E1-27054D52D77F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Content Include="Inputs\Quest01\Q01_P01.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Inputs\Quest01\Q01_P02.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Inputs\Quest01\Q01_P03.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Compile Include="Helpers.fs" />
<Compile Include="Quest01.fs" />
<Compile Include="Program.fs"/>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,18 @@
module EveryBodyCodes2025.Helpers
let foldUntilNone folder (state: 's) (source: 'a seq) : 's option =
use e = source.GetEnumerator()
let rec loop acc =
if e.MoveNext() then
match folder acc e.Current with
| Some s -> loop s
| None -> Some acc // last good state
else Some acc // finished entire sequence
loop state
let arraySwap idx0 idx1 (array: 'a array) =
let a = array[idx0]
let b = array[idx1]
array[idx0] <- b
array[idx1] <- a
array

View File

@@ -0,0 +1,3 @@
Krynnfal,Felnnyn,Norakmarn,Glynngnaris,Zorasis,Ulmarsarix,Rynquin,Wyntor,Harnmarn,Selkvel
L6,R8,L7,R1,L2,R7,L1,R6,L5,R2,L7

View File

@@ -0,0 +1,3 @@
Ascalthar,Skarkael,Vyrbel,Havisis,Tarlzral,Paltheldrith,Hazthel,Hazwyris,Jarzyth,Mornxal,Vaelacris,Xardaros,Lirzyph,Sylacris,Nexor,Vorndra,Cyndhynd,Ralkyris,Cragkael,Galoryn
L7,R12,L8,R12,L9,R18,L16,R13,L9,R12,L5,R11,L5,R14,L5,R18,L5,R15,L5,R17,L5,R18,L16,R12,L14,R7,L11,R9,L12

View File

@@ -0,0 +1,3 @@
Xarsar,Elvareldrin,Zraalcyth,Vyrlfeth,Palthonar,Maralor,Qalirin,Dalnyn,Havryn,Maralxal,Ulthyn,Ascalxeth,Thymfyr,Varinralis,Rythangarath,Ulkkynar,Lazlon,Grimulrix,Draithvash,Voraxmir,Vyrlxal,Elvarmal,Maralsyx,Wyrvash,Vornketh,Torendris,Thalcoryx,Paldeth,Vyrlcion,Tazroth
L25,R49,L14,R13,L11,R12,L43,R45,L38,R34,L34,R44,L44,R35,L35,R30,L38,R37,L49,R48,L5,R39,L5,R27,L5,R14,L5,R32,L5,R46,L5,R9,L5,R24,L5,R43,L5,R21,L5,R22,L15,R49,L27,R41,L18,R31,L26,R16,L10,R40,L19,R6,L20,R24,L40,R44,L5,R47,L35

View File

@@ -0,0 +1,13 @@
// For more information see https://aka.ms/fsharp-console-apps
open EveryBodyCodes2025
[<EntryPoint>]
let main argv =
try
printfn $"{Quest01.part1()}"
printfn $"{Quest01.part2()}"
printfn $"{Quest01.part3()}"
with exn ->
printfn $"{exn}"
0

View File

@@ -0,0 +1,81 @@
module EveryBodyCodes2025.Quest01
open System
open System.IO
open EveryBodyCodes2025.Helpers
type Direction = Left | Right
type Instruction = { Direction: Direction; Distance: int }
let parseInstruction (segment:string) =
let direction = if segment[0] = 'L' then Left else Right
let distance = Int32.Parse(segment.AsSpan().Slice(1))
{ Direction = direction; Distance = distance }
let inline normalize (array: 'a array) idx =
if idx >= 0 then idx % array.Length else array.Length - (-idx % array.Length)
let inline nextIndex instruction idx =
match instruction.Direction with
| Left -> idx - instruction.Distance
| Right -> idx + instruction.Distance
let readFile file =
File.ReadAllLines(file)
|> fun lines ->
let names = lines.[0] |> _.Split(",", StringSplitOptions.RemoveEmptyEntries ||| StringSplitOptions.TrimEntries)
let instructions =
lines[2]
|> _.Split(",", StringSplitOptions.RemoveEmptyEntries ||| StringSplitOptions.TrimEntries)
|> Array.map parseInstruction
(names, instructions)
let part1File file : string =
readFile file
|> fun (names, instructions) ->
instructions
|> Seq.fold (fun (idx, _) instruction ->
let next = nextIndex instruction idx |> fun v -> Math.Clamp(v, 0, names.Length - 1)
match Array.tryItem next names with
| Some n -> next, n
| None -> failwith "off array"
) (0, "")
|> snd
let part1 () = part1File "Inputs/Quest01/Q01_P01.txt"
let part2File file =
readFile file
|> fun (names, instructions) ->
instructions
|> Seq.fold (fun (idx, _) instruction ->
let next = nextIndex instruction idx |> normalize names
match Array.tryItem next names with
| Some n -> next, n
| None -> failwith "off array"
) (0, "")
|> snd
let part2() = part2File "Inputs/Quest01/Q01_P02.txt"
let part3File file =
readFile file
|> fun (names, instructions) ->
// need to preserve a reference to an array that can be mutated
let mutable nameArray = names
instructions
|> Seq.fold (fun _ instruction ->
// for this challenge the index doesn't matter
let next = match instruction.Direction with
| Left -> names.Length - instruction.Distance
| Right -> instruction.Distance
|> normalize names
match Array.tryItem next nameArray with
| Some n ->
nameArray <- arraySwap 0 next names
0, n
| None -> failwith "off array"
) (0, "")
|> snd
let part3() = part3File "Inputs/Quest01/Q01_P03.txt"

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<RootNamespace>EveryBodyCodes2025</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Content Include="Inputs\Q01_P01.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Inputs\Q01_P02.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Inputs\Q01_P02a.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Compile Include="QuestOne.fs" />
<Compile Include="QuestOne_ai.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,10 @@
A=9 B=5 C=8 X=6 Y=6 Z=5 M=21
A=2 B=5 C=9 X=3 Y=7 Z=5 M=15
A=2 B=9 C=5 X=6 Y=5 Z=6 M=23
A=5 B=9 C=8 X=4 Y=3 Z=6 M=23
A=4 B=4 C=7 X=5 Y=4 Z=7 M=20
A=8 B=8 C=9 X=6 Y=8 Z=7 M=15
A=5 B=9 C=8 X=8 Y=7 Z=9 M=12
A=9 B=8 C=8 X=6 Y=6 Z=7 M=11
A=4 B=9 C=9 X=4 Y=3 Z=6 M=16
A=3 B=3 C=6 X=3 Y=3 Z=9 M=10

View File

@@ -0,0 +1,100 @@
A=3963 B=8842 C=8687 X=409495541 Y=7293148889 Z=69968178871 M=172
A=7942 B=7029 C=6244 X=839539903 Y=4169342114 Z=95037937077 M=160
A=7979 B=8971 C=6912 X=442664734 Y=6237597808 Z=86442494244 M=68
A=7688 B=9813 C=8682 X=332021203 Y=9856217610 Z=80328955369 M=62
A=5835 B=5848 C=9080 X=142585645 Y=1900208603 Z=95352568867 M=102
A=5334 B=9954 C=9648 X=905887097 Y=9241714569 Z=54782995871 M=64
A=7455 B=3708 C=8255 X=504254875 Y=4435182630 Z=47061156208 M=196
A=7792 B=9864 C=5393 X=480894345 Y=7574321009 Z=28916297468 M=162
A=8393 B=3232 C=8104 X=330175845 Y=5289733360 Z=31518107012 M=79
A=3882 B=3375 C=6068 X=518104895 Y=1025354059 Z=23851183794 M=109
A=7157 B=6688 C=8802 X=343914437 Y=8548573578 Z=39640082726 M=108
A=9267 B=9026 C=5652 X=552894284 Y=5449382534 Z=15095836120 M=131
A=7709 B=7053 C=6015 X=692558506 Y=3648795546 Z=80249693831 M=94
A=4090 B=7395 C=9247 X=462765550 Y=4135859740 Z=20266326837 M=98
A=5319 B=9603 C=8458 X=837675237 Y=7562163981 Z=81526783792 M=98
A=5056 B=3354 C=8506 X=215467750 Y=8934346014 Z=80156785083 M=64
A=8946 B=9714 C=8466 X=186796372 Y=6752172401 Z=97885508408 M=85
A=6634 B=3765 C=5216 X=684211300 Y=7194085573 Z=84235702575 M=93
A=7700 B=9075 C=8639 X=769343115 Y=4951946895 Z=12460628812 M=192
A=2270 B=6794 C=9887 X=753574022 Y=1010353710 Z=22079276874 M=199
A=4608 B=6704 C=6374 X=489461820 Y=2617126841 Z=99189476796 M=56
A=7991 B=6698 C=5009 X=865348038 Y=6628450920 Z=82542609090 M=138
A=9146 B=3602 C=5757 X=948362149 Y=6536500415 Z=42356087927 M=63
A=6135 B=6979 C=7331 X=296914642 Y=5562957551 Z=15296896818 M=154
A=6740 B=4037 C=9925 X=664678186 Y=2062390238 Z=26147984893 M=127
A=4286 B=3122 C=7026 X=326371845 Y=1116546423 Z=13319294289 M=72
A=2440 B=4715 C=8385 X=255209406 Y=9382774924 Z=54150329024 M=196
A=3576 B=9613 C=9732 X=944415768 Y=5592859961 Z=38006825858 M=75
A=3943 B=4271 C=8115 X=435401018 Y=3803008103 Z=87256283762 M=71
A=5046 B=5121 C=7477 X=882139913 Y=1929832251 Z=25182537189 M=51
A=3106 B=5337 C=7157 X=456093739 Y=5663851313 Z=64060187791 M=66
A=6809 B=5664 C=8361 X=881954026 Y=6714747784 Z=67415739912 M=193
A=2947 B=4118 C=7935 X=459311447 Y=1504393004 Z=93240766891 M=120
A=6368 B=5612 C=8266 X=231311396 Y=2500175052 Z=54868769612 M=155
A=7059 B=8353 C=9272 X=386198328 Y=6033513339 Z=34890243693 M=95
A=6639 B=7182 C=9599 X=203138028 Y=8848877703 Z=41738077352 M=50
A=4327 B=9940 C=7620 X=144124863 Y=2255030420 Z=72197832296 M=187
A=8129 B=3767 C=7930 X=874606203 Y=2598169766 Z=43845885455 M=76
A=7857 B=6832 C=6907 X=739251256 Y=6913635659 Z=68561001761 M=105
A=3786 B=5820 C=9138 X=497623985 Y=1048832748 Z=22080414607 M=58
A=2235 B=4081 C=7532 X=481034867 Y=6763036282 Z=90858998586 M=146
A=6570 B=4019 C=9385 X=687612339 Y=5923858682 Z=37417952027 M=173
A=8715 B=6433 C=6347 X=302773772 Y=5836323573 Z=85318938543 M=149
A=5272 B=5147 C=6267 X=952029958 Y=5064309718 Z=46637498104 M=158
A=8251 B=3017 C=9953 X=520837819 Y=4171582367 Z=32996622261 M=186
A=5058 B=5497 C=8865 X=209462541 Y=3152901709 Z=28469776806 M=127
A=7458 B=4164 C=5570 X=504629974 Y=2847240248 Z=58865406911 M=69
A=3860 B=3876 C=7655 X=406121777 Y=8124355470 Z=87786303696 M=63
A=3203 B=8316 C=6886 X=455814102 Y=4577442858 Z=78541358333 M=159
A=3125 B=6022 C=7456 X=381823686 Y=5752089240 Z=93786233800 M=65
A=3159 B=5387 C=8685 X=867405378 Y=4700629430 Z=13338543360 M=110
A=9443 B=8949 C=9618 X=708422252 Y=5713427199 Z=93352128799 M=138
A=8269 B=8771 C=9138 X=115479767 Y=6857455766 Z=88859949122 M=148
A=5030 B=7425 C=8196 X=382353180 Y=5987748430 Z=25607872228 M=57
A=3129 B=9466 C=6663 X=436840184 Y=4007277476 Z=67936955089 M=121
A=8863 B=4951 C=6103 X=474069087 Y=2653137145 Z=50414775315 M=142
A=7710 B=5762 C=7992 X=599214654 Y=7004049394 Z=34839364869 M=60
A=3632 B=7511 C=9400 X=363797903 Y=6114932282 Z=92960791069 M=102
A=5952 B=4083 C=5910 X=774389174 Y=5176494427 Z=12141381856 M=56
A=3348 B=7169 C=7752 X=235855845 Y=7501135473 Z=66780467588 M=53
A=5619 B=7340 C=9967 X=294184624 Y=2180513244 Z=79033007662 M=168
A=7091 B=6809 C=8576 X=451316478 Y=5083584456 Z=75461336471 M=132
A=6986 B=7754 C=7425 X=757283512 Y=6808223862 Z=34941686102 M=85
A=9456 B=7652 C=8565 X=979905517 Y=5198120313 Z=89655367929 M=145
A=6408 B=3375 C=9204 X=167783992 Y=7153984590 Z=92427049931 M=163
A=5763 B=6148 C=9274 X=279889725 Y=9964940531 Z=70350391483 M=107
A=8547 B=3879 C=6951 X=378902964 Y=2470752240 Z=41679149795 M=164
A=9030 B=7546 C=9608 X=362501898 Y=4119049939 Z=34688334048 M=63
A=6606 B=3185 C=7598 X=989305093 Y=8605576905 Z=51083739654 M=75
A=6638 B=6554 C=9533 X=454809416 Y=9071666311 Z=84656936473 M=153
A=5935 B=6809 C=7923 X=466741209 Y=3713819811 Z=67566769458 M=82
A=4142 B=3634 C=8916 X=533140627 Y=2195880417 Z=63200440973 M=155
A=6744 B=6198 C=6326 X=537074856 Y=6435636287 Z=37528504509 M=187
A=4239 B=4620 C=7151 X=462984355 Y=5222077949 Z=15395506154 M=128
A=6828 B=3182 C=6966 X=496586089 Y=7568408954 Z=19431263615 M=154
A=9989 B=3481 C=5907 X=513706785 Y=7730898126 Z=95604573977 M=187
A=3705 B=7381 C=9078 X=944788648 Y=3774196339 Z=94727056559 M=109
A=6519 B=8081 C=6652 X=515939261 Y=7364208903 Z=76245157293 M=119
A=6783 B=3628 C=6785 X=612616358 Y=2730449251 Z=43338128854 M=119
A=5754 B=4424 C=9976 X=455602255 Y=3399840701 Z=39884578932 M=58
A=7329 B=5584 C=9481 X=765182920 Y=1848910508 Z=45635859967 M=136
A=6519 B=3508 C=5784 X=715678818 Y=9372223394 Z=26437577265 M=148
A=4079 B=8159 C=7501 X=806798900 Y=3775959987 Z=13667259165 M=171
A=5610 B=8246 C=9431 X=876328126 Y=3062507221 Z=76968043190 M=192
A=8793 B=7191 C=8651 X=507531146 Y=1481324914 Z=10641325001 M=140
A=3474 B=4504 C=6865 X=153892044 Y=1499530230 Z=23327074226 M=148
A=2283 B=7236 C=6691 X=349591700 Y=5648605259 Z=52789615621 M=193
A=5353 B=7290 C=8351 X=904035360 Y=1079381894 Z=32939365470 M=151
A=3335 B=3714 C=9424 X=490506342 Y=3864608302 Z=22684283111 M=193
A=6639 B=4126 C=6774 X=303155063 Y=8058444773 Z=51242239037 M=140
A=5939 B=8415 C=7647 X=864474320 Y=7501144894 Z=16280658244 M=158
A=7462 B=5382 C=6626 X=507130448 Y=5725528199 Z=64532140016 M=189
A=7292 B=9734 C=9202 X=249977263 Y=9609502439 Z=18773414989 M=151
A=4252 B=6928 C=7069 X=520151955 Y=5022079447 Z=17156955195 M=168
A=6024 B=9247 C=8017 X=691392384 Y=2452486474 Z=98856856289 M=188
A=3965 B=6464 C=7846 X=890087137 Y=1960036667 Z=58084547133 M=117
A=3493 B=4567 C=5429 X=385555783 Y=9048831860 Z=95579371679 M=132
A=6806 B=3897 C=6437 X=760150394 Y=7972134501 Z=88248014690 M=178
A=5943 B=7880 C=9482 X=796170662 Y=8924797876 Z=68139919278 M=77
A=4792 B=6913 C=7409 X=184894441 Y=4869520047 Z=27653781346 M=166

View File

@@ -0,0 +1,2 @@
A=5 B=9 C=7 X=6 Y=16 Z=18 M=15
A=8 B=8 C=8 X=6 Y=19 Z=16 M=16

View File

@@ -0,0 +1,14 @@
// For more information see https://aka.ms/fsharp-console-apps
open System
open EveryBodyCodes2025.QuestOne
[<EntryPoint>]
let main argv =
//printfn $"{part1Answer}"
//printfn $"{test2}"
printfn $"part 2 answer {part2Answer}"
//let testAnswer = part2Answer' "Inputs/Q01_P02a.txt"
//printfn $"part 2 answer test 1 {testAnswer}"
//printfn $"part 2 answer test 1 11051340 expected"
0

View File

@@ -0,0 +1,143 @@
module EveryBodyCodes2025.QuestOne
open System
open System.Collections.Generic
open System.IO
open System.Linq
open System.Numerics
open System.Threading.Tasks
let eni (n:BigInteger) (exp:BigInteger) (m:BigInteger) =
let mutable remainders = []
let mutable score = BigInteger 1
for _ in (BigInteger 1)..exp do
score <- (score * n) % m
remainders <- score::remainders
List.rev remainders // Reverse to get correct order (oldest first)
// let test1 = eni 2 4 5 |> fun l -> String.Join("", l) |> int64
// let test2 = eni 3 5 16 |> fun l -> String.Join("", l) |> int64
let part1Lines (input:String array) =
input |> Array.map (fun line ->
line.Split(" ") |> Array.map(fun segment ->
let parts = segment.Split("=")
let alias = parts[0]
let num = parts[1] |> BigInteger.Parse
(alias, num)
)
|> dict
)
let toBigInt (list:'a list) = String.Join("", list) |> BigInteger.Parse
let part1 (input: IDictionary<string, BigInteger> array)=
input
|> Seq.map (fun line ->
let a = eni line["A"] line["X"] line["M"] |> toBigInt
let b = eni line["B"] line["Y"] line["M"] |> toBigInt
let c = eni line["C"] line["Z"] line["M"] |> toBigInt
a + b + c
) |> Seq.max
|> fun x ->
printfn $"{x}"
x
let part1Answer =
File.ReadAllLines "Inputs/Q01_P01.txt"
|> part1Lines
|> part1
/// Map from (prev, curr) pair to position
type PositionMap = Map<BigInteger * BigInteger, BigInteger * BigInteger>
let rec findCycle (pairToNextPair: PositionMap) startPair currentPair acc =
if currentPair = startPair && List.length acc > 0 then
Some (List.rev acc)
else
match Map.tryFind currentPair pairToNextPair with
| None -> None
| Some nextPair ->
findCycle pairToNextPair startPair nextPair (snd currentPair :: acc)
let rec eni2' score (n:BigInteger) (exp:BigInteger) (m:BigInteger) (pairMap: PositionMap) (scores:BigInteger list) iter =
if iter > exp then scores |> List.rev |> List.skip (max 0 (List.length scores - 5)) |> toBigInt
else
let newScore = (score * n) % m
let key = (score, newScore)
match Map.tryFind key pairMap with
| Some _ ->
match findCycle pairMap key key [] with
| Some cycle ->
let remaining = int64 (exp - iter)
let cycleValues = cycle
let cycleLength = List.length cycleValues |> int64
let scoresLength = List.length scores |> int64
let totalLength = scoresLength + 1L + remaining // scores + newScore + remaining
let needCount = min 5L totalLength
let startPos = max 0L (totalLength - needCount)
let scoresReversed = List.rev scores
let final5 =
[startPos..totalLength - 1L]
|> List.map (fun pos ->
if pos < scoresLength then
// Position is in scores (scores is reversed, so oldest is at end)
scoresReversed.[int pos]
elif pos = scoresLength then
// Position is newScore
newScore
else
let cycleOffset = pos - scoresLength
let cyclePos = cycleOffset % cycleLength
cycleValues.[int cyclePos]
)
// final 5 comes out in reverse order
final5 |> List.rev |> toBigInt
| None ->
eni2' newScore n exp m (Map.add key ((newScore, (newScore * n) % m)) pairMap) (newScore::scores) (iter + BigInteger 1)
| None ->
let nextPair = (newScore, (newScore * n) % m)
eni2' newScore n exp m (Map.add key nextPair pairMap) (newScore::scores) (iter + BigInteger 1)
let eni2 (n) (exp) (m) = eni2' (BigInteger 1) n exp m Map.empty [] (BigInteger 1)
let part2 (input: IDictionary<string, BigInteger> array)=
input
|> Array.mapi (fun i line ->
//printfn $"""running line {line.AsEnumerable() |> Seq.map(fun kv -> kv.Key + "=" + kv.Value.ToString()) |> fun x -> String.Join(", ", x)}"""
let a = eni2 line["A"] line["X"] line["M"]
let b = eni2 line["B"] line["Y"] line["M"]
let c = eni2 line["C"] line["Z"] line["M"]
let ret = a + b + c
//printfn $"found {ret}"
ret
) |> Seq.max
let test2 =
let a = eni2 5 6 15
let b = eni2 9 16 15
let c = eni2 7 18 15
let r = a + b + c
printfn $"{r}"
r
let part2Answer =
File.ReadAllLines "Inputs/Q01_P02.txt"
|> part1Lines
|> part2
|> fun x ->
printfn $"part2 {x}"
x
let part2Answer' file =
File.ReadAllLines file
|> part1Lines
|> part2
|> fun x ->
printfn $"part2 {x}"
x

View File

@@ -0,0 +1,123 @@
module EveryBodyCodes2025.QuestOne_ai
open System
open System.Collections.Generic
open System.IO
open System.Numerics
open System.Threading.Tasks
let eni (n:int64) (exp:int64) (m:int64) =
// Compute n^k mod m for k = 1..exp
// The sequence will cycle, so we detect the cycle and use it
// Track pairs of consecutive remainders to detect cycles
let mutable remainders = []
let mutable score : int64 = 1
let mutable seenPairs = Map.empty<int64 * int64, int> // Map from (prev, curr) pair to position
let mutable prevScore = 0L
let mutable cycleLength = -1
let mutable doneWithCycle = false
// Build sequence until we detect a cycle
let mutable k = 1
while k <= int exp && not doneWithCycle do
prevScore <- score
score <- (score * n) % m
remainders <- score::remainders
// Check if we've seen this (prev, curr) pair before
if k > 1 && seenPairs.ContainsKey (prevScore, score) && cycleLength = -1 then
let prevPos = seenPairs[(prevScore, score)]
let candidateLength = (remainders.Length - 1) - prevPos
// Verify it's a cycle by checking one more value
if candidateLength > 0 then
let nextScore = (score * n) % m
let nextPos = if prevPos + 1 < remainders.Length then
(remainders.Length - 1) - (prevPos + 1)
else -1
if nextPos >= 0 && nextPos < remainders.Length && remainders[nextPos] = nextScore then
// Found a cycle!
cycleLength <- candidateLength
// Use cycle to compute remaining values
let remaining = int exp - k
if remaining > 0 then
// Extract the cycle (in correct order)
let cycleList = remainders.[0..cycleLength - 1] |> List.rev
let fullCycles = remaining / cycleLength
let extra = remaining % cycleLength
for _ in 1..fullCycles do
remainders <- cycleList @ remainders
for i in 0..extra - 1 do
remainders <- cycleList.[i]::remainders
doneWithCycle <- true
else
if cycleLength = -1 && k > 1 then
seenPairs <- seenPairs.Add((prevScore, score), remainders.Length - 1)
k <- k + 1
List.rev remainders
// let test1 = eni 2 4 5 |> fun l -> String.Join("", l) |> int64
// let test2 = eni 3 5 16 |> fun l -> String.Join("", l) |> int64
let part1Lines (input:String array) =
input |> Array.map (fun line ->
line.Split(" ") |> Array.map(fun segment ->
let parts = segment.Split("=")
let alias = parts[0]
let num = parts[1] |> int64
(alias, num)
)
|> dict
)
let toBigInt (list:int64 list) = String.Join("", list) |> BigInteger.Parse
let part1 (input: IDictionary<string, int64> array)=
input
|> Seq.map (fun line ->
let a = eni line["A"] line["X"] line["M"] |> toBigInt
let b = eni line["B"] line["Y"] line["M"] |> toBigInt
let c = eni line["C"] line["Z"] line["M"] |> toBigInt
a + b + c
) |> Seq.max
let part1Answer =
File.ReadAllLines "Inputs/Q01_P01.txt"
|> part1Lines
|> part1
let eni2 (n:int64) (exp:int64) (m:int64) =
// For part 2, we only need the last 5 remainders
// Use the same cycle detection as eni, then take last 5
let allRemainders = eni n exp m
let len = List.length allRemainders
if len <= 5 then
allRemainders
else
allRemainders |> List.skip (len - 5)
let part2 (input: IDictionary<string, int64> array)=
input
|> Array.Parallel.map (fun line ->
let a = eni2 line["A"] line["X"] line["M"] |> toBigInt
let b = eni2 line["B"] line["Y"] line["M"] |> toBigInt
let c = eni2 line["C"] line["Z"] line["M"] |> toBigInt
a + b + c
) |> Seq.max
let test2 =
toBigInt(eni2 5 6 15) + toBigInt(eni2 9 16 15) + toBigInt(eni2 7 18 15)
let part2Answer =
File.ReadAllLines "Inputs/Q01_P02.txt"
|> part1Lines
|> part2