Skip to content

Instantly share code, notes, and snippets.

@reissbaker
Last active April 12, 2017 04:50
Show Gist options
  • Save reissbaker/f786f83b19960f7f388658794f6bd02a to your computer and use it in GitHub Desktop.
Save reissbaker/f786f83b19960f7f388658794f6bd02a to your computer and use it in GitHub Desktop.
typescript port of aphyr's "reversing the technical interview." compiled with --noImplicitAny and --strictNullChecks, obv.
type empty = undefined | null;
type Maybe<T> = T | empty;
type TrueCell<T> = (b: true) => T;
type FalseCell<T> = (b: false) => Maybe<TrueCell<T> | FalseCell<T>>;
type Cell<T> = TrueCell<T> | FalseCell<T>;
type Next<T> = Maybe<Cell<T>>;
type Iteration<T> = T | Next<T>;
/*
* Get the value of a Cell
*/
function value<T>(cell: Cell<T>): T {
const realized: TrueCell<T> = cell as TrueCell<T>;
return realized(true);
}
/*
* Get the next list item from a Cell
*/
function next<T>(cell: Cell<T>): Next<T> {
const iterator: FalseCell<T> = cell as FalseCell<T>;
return iterator(false);
}
/*
* Given a value and an optional list, return a new list with the value prepended to the old list.
*/
function cons<T>(x: T, next?: Next<T>): Cell<T> {
// A cell function is an overloaded function that does different things depending on whether it
// takes true or false. Define the overload here, and return it.
function cell(b: true): T;
function cell(b: false): Next<T>;
function cell(b: boolean): Iteration<T> {
return b ? x : next;
}
return cell;
}
/*
* Given a set of values, return a list of those values
*/
function list<T>(...args: T[]): Next<T> {
if(args.length === 0) return null;
return cons<T>(args[0], list.apply(this, args.slice(1, args.length)));
}
/*
* Given a list and a number n, return the nth value from the list
*/
function nth<T>(cell: Next<T>, n: number): Maybe<T> {
if(cell == null) {
if(n === 0) return null;
throw 'Out of bounds';
}
if(n === 0) return value(cell);
return nth(next(cell), n - 1);
}
/*
* Reverses a list
*/
function reverse<T>(cell: Next<T>): Next<T> {
let curr = cell;
let reversed: Next<T> = null;
while(curr) {
reversed = cons<T>(value(curr), reversed);
curr = next<T>(curr);
}
return reversed;
}
/*
* Let's try it out:
*/
const l = list(1, 2, 3)
console.log(nth(l, 0));
console.log(nth(l, 1));
console.log(nth(l, 2));
const r = reverse(l);
console.log(nth(r, 0));
console.log(nth(r, 1));
console.log(nth(r, 2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment