From 802a8dde266c2253c7321b5dc40461bb285dfb93 Mon Sep 17 00:00:00 2001 From: "RingOfStorms (Joshua Bell)" Date: Wed, 10 Dec 2025 09:46:39 -0600 Subject: [PATCH] my splitStringByLen function was extremely slow, and lists/iterating lists is slow in general so cahnge to splitByLen make old version 60% faster, and a version without the intermediate loop it is 4s --- 2025/day_2.nix | 7 +++--- 2025/day_2_perf.nix | 60 +++++++++++++++++++++++++++++++++++++++++++++ 2025/utils.nix | 23 +++-------------- 3 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 2025/day_2_perf.nix diff --git a/2025/day_2.nix b/2025/day_2.nix index 112c263..e1a393c 100644 --- a/2025/day_2.nix +++ b/2025/day_2.nix @@ -30,11 +30,12 @@ let str: let strLen = stringLength str; - splits = reverseList (genList (i: i + 1) strLen); + maxSplit = strLen / 2; # Only check up to half length since it must repeat at least twice + splits = genList (i: i + 1) maxSplit; in any ( split: - if split < strLen && mod strLen split == 0 then + if mod strLen split == 0 then let parts = splitStringByLength str split; in @@ -51,7 +52,7 @@ let let invalidIds = flatten ( map ( - range: (reduce (invalidIds: id: invalidIds ++ (if badIdFunc id then [ id ] else [ ])) [ ] range) + range: (foldl' (invalidIds: id: invalidIds ++ (if badIdFunc id then [ id ] else [ ])) [ ] range) ) fullRanges ); invalidIdNums = map (v: toIntBase10 v) invalidIds; diff --git a/2025/day_2_perf.nix b/2025/day_2_perf.nix new file mode 100644 index 0000000..1e9ece2 --- /dev/null +++ b/2025/day_2_perf.nix @@ -0,0 +1,60 @@ +# nix eval -f ./day_2_perf.nix part2 +# nix eval -f ./day_2_perf.nix part2 --arg input 'builtins.readFile ./puzzle_cache/day_2_1' +{ + input ? (builtins.readFile ./puzzle_cache/day_2_0), +}: +with builtins; +with import ./utils.nix; +let + # part 2 any repeat num + isStrPatternRepeated = + str: + let + strLen = stringLength str; + maxSplit = strLen / 2; # Only check up to half length since it must repeat at least twice + splits = genList (i: i + 1) maxSplit; + + checkSplit = + split: + if mod strLen split == 0 then + let + count = strLen / split; + firstElem = substring 0 split str; + checkElem = + index: + if index >= count then + true + else if substring (index * split) split str == firstElem then + checkElem (index + 1) + else + false; + allPartsEqual = checkElem 1; + in + allPartsEqual + else + false; + in + any checkSplit splits; + + ranges = map (range: map (v: toIntBase10 v) (split "-" range)) (split "," input); + + sumBadIdsInRange = + range: + let + from = elemAt range 0; + to = elemAt range 1; + ids = genList (i: from + i) (to - from + 1); + processId = + acc: id: + let + strId = toString id; + in + if isStrPatternRepeated strId then acc + id else acc; + in + (foldl' processId 0 ids); + + sumAllBadIds = sum (map sumBadIdsInRange ranges); +in +{ + part2 = sumAllBadIds; +} diff --git a/2025/utils.nix b/2025/utils.nix index 0fe5ee3..a284648 100644 --- a/2025/utils.nix +++ b/2025/utils.nix @@ -5,7 +5,6 @@ rec { min = a: b: if a < b then a else b; max = a: b: if a > b then a else b; split = delim: input: filter (s: isString s && s != "") (builtins.split delim input); - reduce = foldl'; # foldl' (acc: elem: acc + elem) 0 [1 2 3] flatten = input: concatMap (x: if isList x then x else [ x ]) input; rangeInclusive = min: max: @@ -16,30 +15,14 @@ rec { len = max - min + 1; in genList (i: min + i) len; - sum = input: reduce (sum: v: sum + v) 0 input; + sum = input: foldl' (sum: v: sum + v) 0 input; reverseList = list: if builtins.length list == 0 then [ ] else # Recursively reverse the tail and append the head to the end - (reverseList(builtins.tail list)) ++ [ (builtins.head list) ]; + (reverseList (builtins.tail list)) ++ [ (builtins.head list) ]; splitStringByLength = - # @param s: The input string. - # @param len: The desired length of each part. - s: len: - let - # Recursive helper function - splitRec = - currentString: acc: - if stringLength currentString <= 0 then - reverseList acc - else - let - chunk = substring 0 len currentString; - remaining = substring len (stringLength currentString - len) currentString; - in - splitRec remaining ([ chunk ] ++ acc); - in - splitRec s [ ]; + str: len: map (i: substring (i * len) (len) str) (genList (i: i) (stringLength str / len)); }