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

This commit is contained in:
RingOfStorms (Joshua Bell) 2025-12-10 09:46:39 -06:00
parent e9f2b69924
commit 802a8dde26
3 changed files with 67 additions and 23 deletions

View file

@ -30,11 +30,12 @@ let
str: str:
let let
strLen = stringLength str; 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 in
any ( any (
split: split:
if split < strLen && mod strLen split == 0 then if mod strLen split == 0 then
let let
parts = splitStringByLength str split; parts = splitStringByLength str split;
in in
@ -51,7 +52,7 @@ let
let let
invalidIds = flatten ( invalidIds = flatten (
map ( 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 ) fullRanges
); );
invalidIdNums = map (v: toIntBase10 v) invalidIds; invalidIdNums = map (v: toIntBase10 v) invalidIds;

60
2025/day_2_perf.nix Normal file
View file

@ -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;
}

View file

@ -5,7 +5,6 @@ rec {
min = a: b: if a < b then a else b; min = a: b: if a < b then a else b;
max = 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); 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; flatten = input: concatMap (x: if isList x then x else [ x ]) input;
rangeInclusive = rangeInclusive =
min: max: min: max:
@ -16,7 +15,7 @@ rec {
len = max - min + 1; len = max - min + 1;
in in
genList (i: min + i) len; genList (i: min + i) len;
sum = input: reduce (sum: v: sum + v) 0 input; sum = input: foldl' (sum: v: sum + v) 0 input;
reverseList = reverseList =
list: list:
if builtins.length list == 0 then if builtins.length list == 0 then
@ -25,21 +24,5 @@ rec {
# Recursively reverse the tail and append the head to the end # 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 = splitStringByLength =
# @param s: The input string. str: len: map (i: substring (i * len) (len) str) (genList (i: i) (stringLength str / len));
# @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 [ ];
} }