Advent of Code 2025 solutions
1export type MultiArray<T, N extends number> = N extends N
2 ? number extends N
3 ? T[]
4 : _BuildTuple<T, N, []>
5 : never;
6
7type _BuildTuple<
8 T,
9 N extends number,
10 R extends readonly unknown[],
11> = R["length"] extends N ? R : _BuildTuple<T, N, readonly [T, ...R]>;
12
13export function combinations<T, N extends number>(
14 arr: T[],
15 n: N,
16): Array<MultiArray<T, N>> {
17 let res: Array<MultiArray<T, N>> = [];
18 arr.forEach((item, i) => {
19 if (n === 1) return res.push([item] as any);
20 const c = combinations(arr.slice(i + 1), n - 1);
21 c.forEach((a) => res.push([item, ...a] as any));
22 });
23 return res;
24}
25
26export function multicombinations<T, N extends number>(
27 arr: T[],
28 n: N,
29): Array<MultiArray<T, N>> {
30 let res: Array<MultiArray<T, N>> = [];
31 arr.forEach((item, i) => {
32 if (n === 1) return res.push([item] as any);
33 const c = multicombinations(arr.slice(i), n - 1);
34 c.forEach((a) => res.push([item, ...a] as any));
35 });
36 return res;
37}
38
39export function unique<T>(arr: T[]): T[] {
40 return Array.from(new Set(arr));
41}
42
43export function first<T>(arr: T[]) {
44 return arr[0];
45}
46
47export function last<T>(arr: T[]) {
48 return arr[arr.length - 1];
49}
50
51export function middle<T>(arr: T[]) {
52 return arr[Math.floor(arr.length / 2)];
53}
54
55export function swap<T>(a: number, b: number, arr: T[]): T[] {
56 const newArr = [...arr];
57 const temp = newArr[a];
58 newArr[a] = newArr[b]!;
59 newArr[b] = temp!;
60 return newArr;
61}
62
63export function remove<T>(arr: T[], idx: number): T[] {
64 return arr.filter((_, i) => i !== idx);
65}
66
67export function sum(arr: number[]): number {
68 return arr.reduce((acc, curr) => acc + curr, 0);
69}
70
71export function getIdxAt(idx: number, length: number) {
72 if (idx >= 0) return idx % length;
73 return length + (idx % length);
74}
75
76export function compareArr(arr1: unknown[], arr2: unknown[]): boolean {
77 return arr1.every((item, i) => item === arr2[i]);
78}
79