Move general functions into AoCLib
This commit is contained in:
parent
3234596629
commit
a41e1ce80e
|
@ -10,11 +10,13 @@ let
|
||||||
];
|
];
|
||||||
|
|
||||||
inherentValue = x: { A = 1; B = 2; C = 3; }.${x};
|
inherentValue = x: { A = 1; B = 2; C = 3; }.${x};
|
||||||
|
|
||||||
comparativeValue = { they, you }: if they == you then 3 else
|
comparativeValue = { they, you }: if they == you then 3 else
|
||||||
if (they == "A" && you == "B")
|
if (they == "A" && you == "B")
|
||||||
|| (they == "B" && you == "C")
|
|| (they == "B" && you == "C")
|
||||||
|| (they == "C" && you == "A") then 6 else
|
|| (they == "C" && you == "A") then 6 else
|
||||||
0;
|
0;
|
||||||
|
|
||||||
score = match: comparativeValue match + inherentValue match.you;
|
score = match: comparativeValue match + inherentValue match.you;
|
||||||
|
|
||||||
equalizeValueType = x: { X = "A"; Y = "B"; Z = "C"; }.${x};
|
equalizeValueType = x: { X = "A"; Y = "B"; Z = "C"; }.${x};
|
||||||
|
@ -31,7 +33,9 @@ let
|
||||||
Y = { A = 1; B = 2; C = 3; };
|
Y = { A = 1; B = 2; C = 3; };
|
||||||
Z = { A = 2; B = 3; C = 1; };
|
Z = { A = 2; B = 3; C = 1; };
|
||||||
}.${you}.${they};
|
}.${you}.${they};
|
||||||
|
|
||||||
comparativeValue2 = x: { X = 0; Y = 3; Z = 6; }.${x};
|
comparativeValue2 = x: { X = 0; Y = 3; Z = 6; }.${x};
|
||||||
|
|
||||||
score2 = match: comparativeValue2 match.you + inherentValue2 match;
|
score2 = match: comparativeValue2 match.you + inherentValue2 match;
|
||||||
|
|
||||||
answer2 = pipe guide [
|
answer2 = pipe guide [
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib, AoCLib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
inherit (AoCLib) transformRange chunksOf;
|
||||||
|
|
||||||
compartments = pipe (fileContents ./input.txt) [
|
compartments = pipe (fileContents ./input.txt) [
|
||||||
(splitString "\n")
|
(splitString "\n")
|
||||||
];
|
];
|
||||||
|
@ -11,15 +13,15 @@ let
|
||||||
c1 = substring 0 ((stringLength s) / 2) s;
|
c1 = substring 0 ((stringLength s) / 2) s;
|
||||||
c2 = substring ((stringLength s) / 2) (stringLength s) s;
|
c2 = substring ((stringLength s) / 2) (stringLength s) s;
|
||||||
};
|
};
|
||||||
|
|
||||||
charsToSet = s: foldl (set: c: set // { ${c} = true; }) { } (stringToCharacters s);
|
charsToSet = s: foldl (set: c: set // { ${c} = true; }) { } (stringToCharacters s);
|
||||||
|
|
||||||
getCommonChar = { c1, c2 }:
|
getCommonChar = { c1, c2 }:
|
||||||
findSingle
|
findSingle
|
||||||
(c: c2.${c} or false)
|
(c: c2.${c} or false)
|
||||||
"Error: no common chars"
|
"Error: no common chars"
|
||||||
"Error: multiple chars"
|
"Error: multiple chars"
|
||||||
(attrNames c1);
|
(attrNames c1);
|
||||||
mapRange = min: max: f: i: if min <= i && i < max then f i else i;
|
|
||||||
transformRange = min: max: offset: i: mapRange min max (x: x + offset) i;
|
|
||||||
|
|
||||||
charValue = c: pipe c [
|
charValue = c: pipe c [
|
||||||
lib.strings.charToInt
|
lib.strings.charToInt
|
||||||
|
@ -36,14 +38,12 @@ let
|
||||||
toString
|
toString
|
||||||
];
|
];
|
||||||
|
|
||||||
chunksOf = n: l: if length l <= n
|
|
||||||
then [l]
|
|
||||||
else [(take n l)] ++ (chunksOf n (drop n l));
|
|
||||||
toA123 = l: {
|
toA123 = l: {
|
||||||
a1 = elemAt l 0;
|
a1 = elemAt l 0;
|
||||||
a2 = elemAt l 1;
|
a2 = elemAt l 1;
|
||||||
a3 = elemAt l 2;
|
a3 = elemAt l 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
getCommonChar2 = { a1, a2, a3 }:
|
getCommonChar2 = { a1, a2, a3 }:
|
||||||
findSingle
|
findSingle
|
||||||
(c: a2.${c} or false && a3.${c} or false)
|
(c: a2.${c} or false && a3.${c} or false)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib, AoCLib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
inherit (AoCLib) allUnique;
|
||||||
|
|
||||||
countWithNUntil = n: pred: list: let
|
countWithNUntil = n: pred: list: let
|
||||||
inner = list': count:
|
inner = list': count:
|
||||||
if pred (take n list')
|
if pred (take n list')
|
||||||
|
@ -10,13 +12,10 @@ let
|
||||||
else inner (tail list') (count + 1);
|
else inner (tail list') (count + 1);
|
||||||
in inner list 0;
|
in inner list 0;
|
||||||
|
|
||||||
allItemsAreUnique = l: l == []
|
|
||||||
|| !(elem (head l) (tail l)) && allItemsAreUnique (tail l);
|
|
||||||
|
|
||||||
answerN = n: pipe ./input.txt [
|
answerN = n: pipe ./input.txt [
|
||||||
fileContents
|
fileContents
|
||||||
stringToCharacters
|
stringToCharacters
|
||||||
(countWithNUntil n allItemsAreUnique)
|
(countWithNUntil n allUnique)
|
||||||
(add n)
|
(add n)
|
||||||
toString
|
toString
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib, AoCLib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
inherit (AoCLib) transpose countWhile multiply;
|
||||||
|
|
||||||
calculateTreeVisibilityForLine = line: let
|
calculateTreeVisibilityForLine = line: let
|
||||||
updateState = { currentMax ? (-1), trees ? [] }: tree:
|
updateState = { currentMax ? (-1), trees ? [] }: tree:
|
||||||
if tree > currentMax then { currentMax = tree; trees = trees ++ [true]; }
|
if tree > currentMax then { currentMax = tree; trees = trees ++ [true]; }
|
||||||
|
@ -11,9 +13,6 @@ let
|
||||||
backwards = reverseList (foldr (flip updateState) { } line).trees;
|
backwards = reverseList (foldr (flip updateState) { } line).trees;
|
||||||
in zipListsWith or forwards backwards;
|
in zipListsWith or forwards backwards;
|
||||||
|
|
||||||
transpose = grid:
|
|
||||||
genList (n: map ((flip elemAt) n) grid) (length grid);
|
|
||||||
|
|
||||||
combineGridsWith = f: grid1: grid2: let
|
combineGridsWith = f: grid1: grid2: let
|
||||||
height = length grid1;
|
height = length grid1;
|
||||||
width = length (elemAt grid1 0);
|
width = length (elemAt grid1 0);
|
||||||
|
@ -88,13 +87,13 @@ let
|
||||||
visibleDistanceBackwards
|
visibleDistanceBackwards
|
||||||
reverseList
|
reverseList
|
||||||
];
|
];
|
||||||
in zipListsWith (x: y: x * y) forwards backwards;
|
in zipListsWith multiply forwards backwards;
|
||||||
|
|
||||||
answer2 = pipe trees [
|
answer2 = pipe trees [
|
||||||
(lines: { horizontal = lines; vertical = transpose lines; })
|
(lines: { horizontal = lines; vertical = transpose lines; })
|
||||||
(mapAttrs (_: map visibleDistanceHorizontal))
|
(mapAttrs (_: map visibleDistanceHorizontal))
|
||||||
({horizontal, vertical}: { inherit horizontal; vertical = transpose vertical; })
|
({horizontal, vertical}: { inherit horizontal; vertical = transpose vertical; })
|
||||||
({horizontal, vertical}: combineGridsWith (x: y: x * y) horizontal vertical)
|
({horizontal, vertical}: combineGridsWith multiply horizontal vertical)
|
||||||
(map (foldr max 0))
|
(map (foldr max 0))
|
||||||
(foldr max 0)
|
(foldr max 0)
|
||||||
toString
|
toString
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib, AoCLib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
inherit (AoCLib) scanl abs repeat cmp;
|
||||||
|
|
||||||
mapDirectionStepsToHorizontalVertical = { direction, steps }: {
|
mapDirectionStepsToHorizontalVertical = { direction, steps }: {
|
||||||
horizontal = if direction == "L" then steps else
|
horizontal = if direction == "L" then steps else
|
||||||
if direction == "R" then -steps else 0;
|
if direction == "R" then -steps else 0;
|
||||||
|
@ -10,11 +12,6 @@ let
|
||||||
if direction == "U" then -steps else 0;
|
if direction == "U" then -steps else 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
scanl = f: x1: list: let
|
|
||||||
x2 = head list;
|
|
||||||
x1' = f x1 x2;
|
|
||||||
in if list == [] then [] else [x1'] ++ (scanl f x1' (tail list));
|
|
||||||
|
|
||||||
foldHeadPosition =
|
foldHeadPosition =
|
||||||
{ x ? 0, y ? 0 }:
|
{ x ? 0, y ? 0 }:
|
||||||
{ horizontal, vertical }: {
|
{ horizontal, vertical }: {
|
||||||
|
@ -31,20 +28,14 @@ let
|
||||||
(scanl foldHeadPosition {})
|
(scanl foldHeadPosition {})
|
||||||
];
|
];
|
||||||
|
|
||||||
abs = x: if x < 0 then -x else x;
|
|
||||||
|
|
||||||
ropePieceLength = headPiece: tailPiece: let
|
ropePieceLength = headPiece: tailPiece: let
|
||||||
deltaX = abs (headPiece.x - tailPiece.x);
|
deltaX = abs (headPiece.x - tailPiece.x);
|
||||||
deltaY = abs (headPiece.y - tailPiece.y);
|
deltaY = abs (headPiece.y - tailPiece.y);
|
||||||
in max deltaX deltaY;
|
in max deltaX deltaY;
|
||||||
|
|
||||||
moveRopePiece = headPiece: tailPiece: {
|
moveRopePiece = headPiece: tailPiece: {
|
||||||
x = if headPiece.x > tailPiece.x then tailPiece.x + 1 else
|
x = tailPiece.x + (cmp headPiece.x tailPiece.x);
|
||||||
if headPiece.x < tailPiece.x then tailPiece.x - 1 else
|
y = tailPiece.y + (cmp headPiece.y tailPiece.y);
|
||||||
tailPiece.x;
|
|
||||||
y = if headPiece.y > tailPiece.y then tailPiece.y + 1 else
|
|
||||||
if headPiece.y < tailPiece.y then tailPiece.y - 1 else
|
|
||||||
tailPiece.y;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
moveRope = headToOverlap: rope: let
|
moveRope = headToOverlap: rope: let
|
||||||
|
@ -69,8 +60,6 @@ let
|
||||||
tailPositions = [(last newRope)] ++ nextIteration.tailPositions;
|
tailPositions = [(last newRope)] ++ nextIteration.tailPositions;
|
||||||
};
|
};
|
||||||
|
|
||||||
repeat = item: times: map (const item) (range 1 times);
|
|
||||||
|
|
||||||
f = n: { rope ? (repeat { x = 0; y = 0; } n), tailPositions ? [{ x = 0; y = 0; }] }: newHeadPosition: let
|
f = n: { rope ? (repeat { x = 0; y = 0; } n), tailPositions ? [{ x = 0; y = 0; }] }: newHeadPosition: let
|
||||||
newRope = moveRopeUntilHeadOverlapsAndReportLastPositions newHeadPosition rope;
|
newRope = moveRopeUntilHeadOverlapsAndReportLastPositions newHeadPosition rope;
|
||||||
in {
|
in {
|
||||||
|
|
|
@ -1,39 +1,9 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib, AoCLib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
# See https://github.com/NixOS/nixpkgs/pull/205457
|
inherit (AoCLib) toInt repeat takeWithStride chunksOf;
|
||||||
toInt = str:
|
|
||||||
let
|
|
||||||
inherit (builtins) match fromJSON;
|
|
||||||
# RegEx: Match any leading whitespace, possibly a '-', one or more digits,
|
|
||||||
# and finally match any trailing whitespace.
|
|
||||||
strippedInput = match "[[:space:]]*(-?[[:digit:]]+)[[:space:]]*" str;
|
|
||||||
|
|
||||||
# RegEx: Match a leading '0' then one or more digits.
|
|
||||||
isLeadingZero = match "0[[:digit:]]+" (head strippedInput) == [];
|
|
||||||
|
|
||||||
# Attempt to parse input
|
|
||||||
parsedInput = fromJSON (head strippedInput);
|
|
||||||
|
|
||||||
generalError = "toInt: Could not convert ${escapeNixString str} to int.";
|
|
||||||
|
|
||||||
octalAmbigError = "toInt: Ambiguity in interpretation of ${escapeNixString str}"
|
|
||||||
+ " between octal and zero padded integer.";
|
|
||||||
|
|
||||||
in
|
|
||||||
# Error on presence of non digit characters.
|
|
||||||
if strippedInput == null
|
|
||||||
then throw generalError
|
|
||||||
# Error on presence of leading zero/octal ambiguity.
|
|
||||||
else if isLeadingZero
|
|
||||||
then throw octalAmbigError
|
|
||||||
# Error if parse function fails.
|
|
||||||
else if !isInt parsedInput
|
|
||||||
then throw generalError
|
|
||||||
# Return result.
|
|
||||||
else parsedInput;
|
|
||||||
|
|
||||||
lineToInstruction = line:
|
lineToInstruction = line:
|
||||||
if line == "noop"
|
if line == "noop"
|
||||||
|
@ -48,17 +18,12 @@ let
|
||||||
else { cycles = 2; X = nextX; nextX = nextX + instr.val; };
|
else { cycles = 2; X = nextX; nextX = nextX + instr.val; };
|
||||||
in if instructions == [] then [] else [nextSignalState] ++ (foldToSignalState nextSignalState (tail instructions));
|
in if instructions == [] then [] else [nextSignalState] ++ (foldToSignalState nextSignalState (tail instructions));
|
||||||
|
|
||||||
repeat = item: times: map (const item) (range 1 times);
|
|
||||||
|
|
||||||
expandSignalStates = signalStates: let
|
expandSignalStates = signalStates: let
|
||||||
s = head signalStates;
|
s = head signalStates;
|
||||||
in if signalStates == []
|
in if signalStates == []
|
||||||
then []
|
then []
|
||||||
else (repeat s.X s.cycles) ++ (expandSignalStates (tail signalStates));
|
else (repeat s.X s.cycles) ++ (expandSignalStates (tail signalStates));
|
||||||
|
|
||||||
takeWithStride = n: l:
|
|
||||||
if l == [] then [] else [(head l)] ++ takeWithStride n (drop n l);
|
|
||||||
|
|
||||||
signalStates = pipe ./input.txt [
|
signalStates = pipe ./input.txt [
|
||||||
fileContents
|
fileContents
|
||||||
(splitString "\n")
|
(splitString "\n")
|
||||||
|
@ -75,14 +40,10 @@ let
|
||||||
toString
|
toString
|
||||||
];
|
];
|
||||||
|
|
||||||
splitAtInterval = n: list:
|
|
||||||
if list == [] then []
|
|
||||||
else [(take n list)] ++ (splitAtInterval n (drop n list));
|
|
||||||
|
|
||||||
f = i: v: if v <= i && i <= v + 2 then "#" else ".";
|
f = i: v: if v <= i && i <= v + 2 then "#" else ".";
|
||||||
|
|
||||||
answer2 = pipe signalStates [
|
answer2 = pipe signalStates [
|
||||||
(splitAtInterval 40)
|
(chunksOf 40)
|
||||||
(map (imap1 f))
|
(map (imap1 f))
|
||||||
(map (concatStringsSep ""))
|
(map (concatStringsSep ""))
|
||||||
(concatStringsSep "\n")
|
(concatStringsSep "\n")
|
||||||
|
|
21
flake.nix
21
flake.nix
|
@ -5,17 +5,18 @@
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
in {
|
in {
|
||||||
|
AoCLib = pkgs.callPackage ./lib.nix { };
|
||||||
packages.${system} = {
|
packages.${system} = {
|
||||||
day01 = pkgs.callPackage ./day01 { };
|
day01 = pkgs.callPackage ./day01 { inherit (self) AoCLib; };
|
||||||
day02 = pkgs.callPackage ./day02 { };
|
day02 = pkgs.callPackage ./day02 { inherit (self) AoCLib; };
|
||||||
day03 = pkgs.callPackage ./day03 { };
|
day03 = pkgs.callPackage ./day03 { inherit (self) AoCLib; };
|
||||||
day04 = pkgs.callPackage ./day04 { };
|
day04 = pkgs.callPackage ./day04 { inherit (self) AoCLib; };
|
||||||
day05 = pkgs.callPackage ./day05 { };
|
day05 = pkgs.callPackage ./day05 { inherit (self) AoCLib; };
|
||||||
day06 = pkgs.callPackage ./day06 { };
|
day06 = pkgs.callPackage ./day06 { inherit (self) AoCLib; };
|
||||||
day07 = pkgs.callPackage ./day07 { };
|
day07 = pkgs.callPackage ./day07 { inherit (self) AoCLib; };
|
||||||
day08 = pkgs.callPackage ./day08 { };
|
day08 = pkgs.callPackage ./day08 { inherit (self) AoCLib; };
|
||||||
day09 = pkgs.callPackage ./day09 { };
|
day09 = pkgs.callPackage ./day09 { inherit (self) AoCLib; };
|
||||||
day10 = pkgs.callPackage ./day10 { };
|
day10 = pkgs.callPackage ./day10 { inherit (self) AoCLib; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
{ pkgs, lib }: with lib; rec {
|
||||||
|
# Transpose a square grid
|
||||||
|
#
|
||||||
|
# [[a]] -> [[a]]
|
||||||
|
transpose = grid:
|
||||||
|
genList (n: map ((flip elemAt) n) grid) (length grid);
|
||||||
|
|
||||||
|
# Checks if there are any duplicate items in the list,
|
||||||
|
# in which case it returns false.
|
||||||
|
#
|
||||||
|
# [a] -> Bool
|
||||||
|
allUnique = list: list == []
|
||||||
|
|| !(elem (head list) (tail list)) && allUnique (tail list);
|
||||||
|
|
||||||
|
# Takes items until either a predicate fails, or the list is empty.
|
||||||
|
#
|
||||||
|
# (a -> Bool) -> [a] -> Int
|
||||||
|
takeWhile = pred: xs:
|
||||||
|
if xs == [] || !(stopPred (head xs))
|
||||||
|
then []
|
||||||
|
else [(head xs)] + (takeWhile pred (tail xs));
|
||||||
|
|
||||||
|
# Counts items until either a predicate fails, or the list is empty
|
||||||
|
#
|
||||||
|
# (a -> Bool) -> [a] -> Int
|
||||||
|
countWhile = pred: xs: length (takeWhile head xs);
|
||||||
|
|
||||||
|
# Like foldl, but keeps all intermediate values
|
||||||
|
#
|
||||||
|
# (b -> a -> b) -> b -> [a] -> [b]
|
||||||
|
scanl = f: x1: list: let
|
||||||
|
x2 = head list;
|
||||||
|
x1' = f x1 x2;
|
||||||
|
in if list == [] then [] else [x1'] ++ (scanl f x1' (tail list));
|
||||||
|
|
||||||
|
# Like scanl, but uses the first element as its start element.
|
||||||
|
#
|
||||||
|
# (a -> a -> a) -> [a] -> [a]
|
||||||
|
scanl1 = f: list:
|
||||||
|
if list == [] then [] else scanl f (head list) (tail list);
|
||||||
|
|
||||||
|
# See https://github.com/NixOS/nixpkgs/pull/205457
|
||||||
|
toInt = str:
|
||||||
|
let
|
||||||
|
inherit (builtins) match fromJSON;
|
||||||
|
# RegEx: Match any leading whitespace, possibly a '-', one or more digits,
|
||||||
|
# and finally match any trailing whitespace.
|
||||||
|
strippedInput = match "[[:space:]]*(-?[[:digit:]]+)[[:space:]]*" str;
|
||||||
|
|
||||||
|
# RegEx: Match a leading '0' then one or more digits.
|
||||||
|
isLeadingZero = match "0[[:digit:]]+" (head strippedInput) == [];
|
||||||
|
|
||||||
|
# Attempt to parse input
|
||||||
|
parsedInput = fromJSON (head strippedInput);
|
||||||
|
|
||||||
|
generalError = "toInt: Could not convert ${escapeNixString str} to int.";
|
||||||
|
|
||||||
|
octalAmbigError = "toInt: Ambiguity in interpretation of ${escapeNixString str}"
|
||||||
|
+ " between octal and zero padded integer.";
|
||||||
|
|
||||||
|
in
|
||||||
|
# Error on presence of non digit characters.
|
||||||
|
if strippedInput == null
|
||||||
|
then throw generalError
|
||||||
|
# Error on presence of leading zero/octal ambiguity.
|
||||||
|
else if isLeadingZero
|
||||||
|
then throw octalAmbigError
|
||||||
|
# Error if parse function fails.
|
||||||
|
else if !isInt parsedInput
|
||||||
|
then throw generalError
|
||||||
|
# Return result.
|
||||||
|
else parsedInput;
|
||||||
|
|
||||||
|
# Trivial function to wrap around the multiplication operation.
|
||||||
|
#
|
||||||
|
# Number -> Number -> Number
|
||||||
|
multiply = x: y: x * y;
|
||||||
|
|
||||||
|
# Trivial function to take the absolute value of a number
|
||||||
|
#
|
||||||
|
# Number -> Number
|
||||||
|
abs = x: if x < 0 then -x else x;
|
||||||
|
|
||||||
|
# Generate a list by repeating an element n times.
|
||||||
|
#
|
||||||
|
# a -> Int -> [a]
|
||||||
|
repeat = item: times: map (const item) (range 1 times);
|
||||||
|
|
||||||
|
# Compare two items, return either 1, 0, or -1 depending on whether
|
||||||
|
# one is bigger than the other.
|
||||||
|
#
|
||||||
|
# Ord a => a -> a -> Int
|
||||||
|
cmp = x: y: if x > y then 1 else if x < y then -1 else 0;
|
||||||
|
|
||||||
|
# Take 1 item, and skip the n-1 next items continuosly until the list is empty.
|
||||||
|
#
|
||||||
|
# Int -> [a] -> [a]
|
||||||
|
takeWithStride = n: l:
|
||||||
|
if l == [] then [] else [(head l)] ++ takeWithStride n (drop n l);
|
||||||
|
|
||||||
|
# Split a list at every n items.
|
||||||
|
#
|
||||||
|
# Int -> [a] -> [[a]]
|
||||||
|
chunksOf = n: list: if list == []
|
||||||
|
then []
|
||||||
|
else [(take n list)] ++ (chunksOf n (drop n list));
|
||||||
|
|
||||||
|
# Map something orderable through a function f if it is between min and max.
|
||||||
|
#
|
||||||
|
# Ord a => a -> a -> (a -> b) -> a -> Either a b
|
||||||
|
mapRange = min: max: f: o: if min <= o && o < max then f o else o;
|
||||||
|
|
||||||
|
# Shift a number n by an offset if it is between min and max.
|
||||||
|
#
|
||||||
|
# Number -> Number -> Number -> Number -> Number
|
||||||
|
transformRange = min: max: offset: n: mapRange min max (x: x + offset) n;
|
||||||
|
}
|
Loading…
Reference in New Issue