Skip to content

Commit

Permalink
issue-#43,#61 - Re-instated 'Slice' type some 'list' methods.
Browse files Browse the repository at this point in the history
- Cleaned tests for 'permutations' method.
  • Loading branch information
elycruz committed Aug 27, 2022
1 parent 61e810c commit a1e5894
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 58 deletions.
6 changes: 3 additions & 3 deletions packages/fjl/src/list/elemIndices.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {findIndices} from "./findIndices";
import {Unary} from "../types";
import {Slice, Unary} from "../types";
import {$equal} from "../boolean/equal";

/**
* Returns found "value" indices.
*/
export const elemIndices = <T>(value: T, xs: T[]): number[] => findIndices($equal(value) as Unary, xs),
export const elemIndices = <T>(value: T, xs: Slice<T>): number[] => findIndices($equal(value) as Unary, xs),

$elemIndices = <T>(value: T) =>
(xs: T[]): number[] => elemIndices(value, xs)
(xs: Slice<T>): number[] => elemIndices(value, xs)
;
8 changes: 4 additions & 4 deletions packages/fjl/src/list/isPrefixOf.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {indexOf,} from "../platform/slice";
import {findIndex} from "./findIndex";
import {$equal} from "../boolean";
import {Slice} from "../types";

export const

/**
* Checks if list `xs1` is a prefix of list `xs2`
*/
isPrefixOf = <T, TS extends T[]>(xs1: TS, xs2: TS): boolean => {
isPrefixOf = <T>(xs1: Slice<T>, xs2: Slice<T>): boolean => {
const limit1 = xs1.length,
limit2 = xs2.length;
if (limit2 < limit1 || !limit1 || !limit2 || findIndex($equal(xs1[0]), xs2) === -1) {
Expand All @@ -22,5 +22,5 @@ export const
return true;
},

$isPrefixOf = <T, TS extends T[]>(xs1: TS) =>
(xs2: TS): boolean => isPrefixOf(xs1, xs2);
$isPrefixOf = <T>(xs1: Slice<T>) =>
(xs2: Slice<T>): boolean => isPrefixOf(xs1, xs2);
10 changes: 5 additions & 5 deletions packages/fjl/src/list/permutations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {swap} from "./utils";
import {repeat} from "./repeat";

/**
* Returns a list of permutations for passed in list.
Expand All @@ -11,15 +10,16 @@ export const permutations = <T>(xs: T[]): T[][] => {

if (!limit || limit === 1) return [xs];

const c = repeat(limit, 0) as number[];
const c = [].fill(0, 0, limit);
let list: T[] = xs.slice(0),
i = 0;

const out = [list];
const out = [list] as T[][];

for (; i < limit; i++) {
if (c[i] < i) {
list = swap((i % 2 === 0 ? 0 : c[i]) as number, i, list) as T[];
// `(i & 0) === 1` checks if `i` is even or not
list = swap(((i & 0) === 1 ? 0 : c[i]), i, list);
out.push(list);
c[i] += 1;
i = 0;
Expand All @@ -28,5 +28,5 @@ export const permutations = <T>(xs: T[]): T[][] => {
c[i] = 0;
}

return out as T[][];
return out;
};
7 changes: 4 additions & 3 deletions packages/fjl/src/list/stripPrefix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import {isPrefixOf} from "./isPrefixOf";
import {splitAt} from "./splitAt";
import {length} from "./length";
import {sliceCopy} from "./utils/sliceCopy";
import {Slice} from "../types";

export const

/**
* Strips prefix list from given list
*/
stripPrefix = <T>(prefix: T[], list: T[]): T[] =>
stripPrefix = <T>(prefix: Slice<T>, list: Slice<T>): Slice<T> =>
isPrefixOf(prefix, list) ?
splitAt(length(prefix), list)[1] :
sliceCopy(list),

$stripPrefix = <T>(prefix: T[]) =>
(list: T[]): T[] =>
$stripPrefix = <T>(prefix: Slice<T>) =>
(list: Slice<T>): Slice<T> =>
stripPrefix(prefix, list)
91 changes: 48 additions & 43 deletions packages/fjl/tests/list/test-permutations.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,55 @@
import {expectLength, expectTrue} from "../helpers";
import {expectLength, expectTrue, vowelsArray} from "../helpers";
import {permutations} from "../../src/list/permutations";

describe('#permutations', () => {
const areAllPermutesUnique = permutes => {
const xs = permutes,
limit = xs.length;
for (let i = 0; i < limit; i += 1) {
let str = xs[i].join('');
for (let j = 0; j < limit; j += 1) {
if (j !== i && xs[j].join('') === str) {
return false;
}
}
}
return true;
},
const areAllPermutesUnique = permutes => {
const xs = permutes,
limit = xs.length;
for (let i = 0; i < limit; i += 1) {
const str = xs[i].join('');
for (let j = 0; j < limit; j += 1) {
if (j !== i && xs[j].join('') === str) {
return false;
}
}
}
return true;
},

howManyPermutes = n => {
if (n <= 0) {
return 0;
}
let lastPermutes = 1,
i = 1;
while (i <= n) {
lastPermutes = i * lastPermutes;
i += 1;
}
return lastPermutes;
};
howManyPermutes = n => {
if (n <= 0) {
return 0;
}
let lastPermutes = 1,
i = 1;
while (i <= n) {
lastPermutes = i * lastPermutes;
i += 1;
}
return lastPermutes;
};

it('Should return unique permutations for a given set of items', () => {
const lists: string[] =
'abcd'.split('').reduceRight((agg, item, ind, list) =>
agg.concat([list.slice(ind)]),
(<any[]>[])
); // I know laziness lol
expectLength(4, lists);
expectTrue(lists.every(
(xs, ind) => xs.length === ind + 1
));
expectTrue(
lists.every(xs => {
const result = permutations(xs);
return areAllPermutesUnique(result) &&
howManyPermutes(xs.length) === result.length;
})
);
it('Should return unique permutations for a given set of items', () => {
const lists =
vowelsArray.reduceRight((agg, _, ind, list) =>
agg.concat([list.slice(ind)]),
[]
);

// Test initial `lists`

expect(lists).toHaveLength(vowelsArray.length);

// Tests initial lists' length
lists.forEach(
(xs, ind) => expect(xs).toHaveLength(ind + 1)
);

// Test permutations uniqueness, and number
lists.forEach(xs => {
const result = permutations(xs);
expect(areAllPermutesUnique(result)).toEqual(true)
expect(howManyPermutes(xs.length)).toEqual(result.length);
});
});
});

0 comments on commit a1e5894

Please sign in to comment.