Skip to content

Instantly share code, notes, and snippets.

@dubzzz
dubzzz / pbt.ts
Created April 14, 2021 19:36
pbt.ts
import fc from 'fast-check';
// Characteristics independent of the inputs
test('for any floating point number d, Math.floor(d) is an integer', () => {
fc.assert(fc.property(fc.double(), (d) => Number.isInteger(Math.floor(d))));
});
test('for any floating point number d, Math.abs(d) ≥ 0', () => {
fc.assert(fc.property(fc.double(), (d) => Math.abs(d) >= 0));
@dubzzz
dubzzz / rpn.ts
Created November 29, 2020 15:42
RPN Eval with Types
// Create a tuple of size N
type Tuple<N extends number, Rest extends any[] = []> = Rest['length'] extends N ? Rest : Tuple<N, [any, ...Rest]>;
type TestTuple_0 = Tuple<0>;
type TestTuple_2 = Tuple<2>;
type TestTuple_5 = Tuple<5>;
// Add two positive numbers
type Add<A extends number, B extends number> = [...Tuple<A>, ...Tuple<B>]['length'] & number;
type TestAdd_1_2 = Add<1, 2>;
type TestAdd_10_4 = Add<10, 4>;
miniFc.property = (generator, predicate) => {
return {
generate(mrng) {
return generator.generate(mrng);
},
shrink(value) {
return generator.shrink(value);
},
run(valueUnderTest) {
return predicate(valueUnderTest);
miniFc.boolean = () => map(
miniFc.integer(0, 1),
Boolean,
b => b ? 1 : 0,
)
miniFc.character = () => map(
miniFc.integer(0, 25),
n => String.fromCharCode(97 + n),
c => c.codePointAt(0) - 97,
)
const map = (g, mapper, unmapper) => {
return {
generate(mrng) {
return mapper(g.generate(mrng));
},
*shrink(value) {
for (const shrunkValue of g.shrink(unmapper(value))) {
yield mapper(shrunkValue);
}
}
const shrinker = (character) => {
const derivedGenerator = miniFc.integer(0, 25);
const initialValue = character.codePointAt(0) - 97;
for (const shrunkValue of derivedGenerator.shrink(initialValue)) {
yield String.fromCharCode(97 + shrunkValue);
}
}
miniFc.character = () => map(
miniFc.integer(0, 25),
n => String.fromCharCode(97 + n)
)
miniFc.array = (itemGenerator) => {
return {
generate(mrng) {
const size = mrng.next(0, 10);
const content = [];
for (let index = 0 ; index !== size ; ++index) {
content.push(itemGenerator.generate(mrng));
}
return content;
},
miniFc.tuple = (...itemGenerators) => {
return {
generate(mrng) {
return itemGenerators.map(g => g.generate(mrng));
},
*shrink(value) {
for (let index = 0 ; index !== itemGenerators.length ; ++index) {
const currentGenerator = itemGenerators[index];
const currentValue = value[index];
for (const shrunkValue of currentGenerator.shrink(currentValue)) {
miniFc.integer = (min, max) => {
return {
generate(mrng) {
return mrng.next(min, max);
},
*shrink(value) {
while (value !== min) {
value = min + Math.floor((value - min) / 2);
yield value;
}