Skip to content

Instantly share code, notes, and snippets.

@hugoferreira
Last active April 30, 2018 01:41
Show Gist options
  • Save hugoferreira/21f1f0ec23186adb5e6832e6aee618d6 to your computer and use it in GitHub Desktop.
Save hugoferreira/21f1f0ec23186adb5e6832e6aee618d6 to your computer and use it in GitHub Desktop.
Origami Programming Exercises
/*
* 'Origami Programming' by Hugo Sereno Ferreira
*
* IEEE Talk @ FEUP (2018)
*
* Exercise sheet (http://goo.gl/Dd4p7b)
*
* Note: Make sure you have node.js, and then install the dependencies using:
*
* npm install -g lodash
*
* For a Live Programming experience, use the Quokka plugin (https://quokkajs.com) with VSCode (https://code.visualstudio.com)
*/
// region Preamble
const eq = require('lodash').isEqual
// endregion
// region Basic example
const a = [1, 2, 3, 4, 5]
let s = 0
for (let i = 0; i < a.length; i++)
s += a[i]
s
// endregion
// region Basic example with strings
const sin = ['To', ' be', ' or', ' not', ' to', ' be!']
let sout = ''
for (let i = 0; i < a.length; i++) // a bug lies here!
sout += sin[i]
sout
// endregion
// region Filtering even array elements
const b = [1, 2, 3, 4, 5, 6]
let filtered = Array()
for (let i = 0; i < b.length; i++)
if (a[i] % 2 == 0) filtered.push(a[i])
filtered
// endregion
// region Base definition of fold
const fold = (as, base) => (f) => {
let result = base
for (let i = 0; i < as.length; i++)
result = f(result, as[i])
return result
}
// endregion
// region sum = [as] => Integer
const sum = (as) => null
sum([1, 2, 3]) === 6 //?
sum([]) === 0 //?
// endregion
// region foreach = [a] => (a => void) => void
const foreach = (as) => (f) => null
const farr = new Array()
foreach([1, 2, 3])(e => farr.push(e))
eq(farr, [1, 2, 3]) //?
// endregion
// region map = [a] => (a => b) => [b]
const map = (as) => (f) => null
eq(map([1, 2, 3])(e => e + 1), [2, 3, 4]) //?
eq(map([])(x => x + 5), []) //?
// endregion
// region filter = [a] => (a => bool) => [a]
const filter = (as) => (f) => null
eq(filter([1, 2, 3, 4, 5, 6])(e => e % 2), [1, 3, 5]) //?
eq(filter([1, 2, 3, 4, 5, 6])(e => e % 2 == 0), [2, 4, 6]) //?
// endregion
// region filterNot = [a] => (a => bool) => [a]
const filterNot = (as) => (f) => null
eq(filterNot([1, 2, 3, 4, 5, 6])(e => e % 2), [2, 4, 6]) //?
eq(filterNot([1, 2, 3, 4, 5, 6])(e => e % 2 == 0), [1, 3, 5]) //?
// endregion
// region exists = [a] => (a => bool) => bool
const exists = (as) => (f) => null
exists([1, 2, 3])(e => e == 3) === true //?
exists([1, 2, 3])(e => e > 2) === true//?
exists([1, 2, 3])(e => e == 5) === false //?
// endregion
// region forall = [a] => (a => bool) => bool
const forall = (as) => (f) => null
forall([1, 2, 3])(e => e < 4) === true //?
forall([1, 2, 3])(e => e > 4) === false //?
forall([])(e => e > 5) === true //?
// endregion
// region length = [a] => Integer
const length = (as) => null
length([1, 2, 3]) == 3 //?
length([]) == 0 //?
// endregion
// region isEmpty = [a] => bool
const isEmpty = (as) => null
// const isEmpty = (as) => length(as) == 0
isEmpty([]) === true //?
isEmpty([1, 2, 3]) === false //?
// endregion
// region notEmpty = [a] => bool
const notEmpty = (as) => null
// const isEmpty = (as) => length(as) != 0
notEmpty([]) === false //?
notEmpty([1, 2, 3]) === true //?
// endregion
// region reverse = [a] => [a]
const reverse = (as) => null
eq(reverse([1, 2, 3]), [3, 2, 1]) //?
eq(reverse([]), []) //?
// endregion
// region first = [a] => a ?
const first = (as) => null
first([1, 2, 3]) === 1 //?
first([]) === null //?
// endregion
// region last = [a] => a ?
const last = (as) => null
last([1, 2, 3]) === 3 //?
last([]) === null //?
// endregion
// region tail = [a] => [a]
const tail = (as) => null
eq(tail([1, 2, 3]), [2, 3]) //?
eq(tail([2, 3]), [3]) //?
eq(tail([3]), []) //?
eq(tail([]), []) //?
// endregion
// region second = [a] => a ?
const second = (as) => null
second([1, 2, 3]) === 2 //?
second([1]) === null //?
second([]) === null //?
// endregion
// region max = [a] => a
const max = (as) => null
max([1, 2, 3]) === 3//?
max([1]) === 1//?
max([]) === null //?
// endregion
// region maxBy = [a] => (a => b) => a
const maxBy = (as) => (f) => null
eq(maxBy([{a: 1}, {a: 2}, {a: 3}])(e => e.a), {a: 3}) //?
// endregion
// region min = [a] => a
const min = (as) => null
min([1, 2, 3]) === 1//?
min([1]) === 1//?
min([]) === null //?
// endregion
// region minBy = [a] => (a => b) => a
const minBy = (as) => (f) => null
eq(minBy([{ a: 1 }, { a: 2 }, { a: 3 }])(e => e.a), { a: 1 }) //?
// endregion
// region find = [a] => (a => bool) => a?
const find = (as) => (f) => null
eq(find([{ name: 'quim', age: 2 }, { name: 'tostas', age: 3 }], e => e.age == 3), { name: 'tostas', age: 3 }) //?
find([{ name: 'quim', age: 2 }], e => e.age == 52) === null //?
// endregion
// region takeWhile = [a] => (a => bool) => [a]
const takeWhile = (as) => (f) => null
eq(takeWhile([1, 2, 3, 4, 5], e => e <= 2), [1, 2]) //?
// endregion
// region dropWhile = [a] => (a => bool) => [a]
const dropWhile = (as) => (f) => null
eq(dropWhile([1, 2, 3, 4, 5], e => e <= 2), [3, 4, 5]) //?
// endregion
// region partition = [a] => (a => bool) => ([a], [a])
const partition = (as) => (f) => null
eq(partition([1, 2, 3, 4], e => e % 2), [[1, 3], [2, 4]]) //?
// endregion
// region splitAt = [a] => Integer => ([a], [a])
const splitAt = (as) => (i) => null
eq(splitAt([1, 2, 3], 2), [[1, 2], [3]]) //?
// endregion
// region zip = [a] => [b] => [(a, b)]
const zip = (as) => (bs) => null
eq(zip([1, 2, 3], ['a', 'b', 'c']), [[1, 'a'], [2, 'b'], [3, 'c']]) //?
// endregion
// region zipWithIndex = [a] => [(Integer, b)]
const zipWithIndex = (as) => null
eq(zipWithIndex(['a', 'b', 'c']), [['a', 0], ['b', 1], ['c', 2]]) //?
// endregion
// region index = [a] => Integer => a?
const index = (as) => (i) => null
index(['a', 'b', 'c'], 0) === 'a' //?
index([1, 2, 3], 1) === 2 //?
// endregion
// region indexWhere = [a] => (a => bool) => Integer?
const indexWhere = (as) => (f) => null
indexWhere(['a', 'b', 'c'], e => e == 'b') === 1 //?
indexWhere(['a', 'b', 'c'], e => e == 'd') === null //?
// endregion
// region take = [a] => Integer => [a]
const take = (as) => (i) => null
eq(take(['a', 'b', 'c'], 2), ['a', 'b']) // ?
eq(take(['a', 'b', 'c'], 5), ['a', 'b', 'c']) // ?
eq(take(['a', 'b', 'c'], 0), []) // ?
// endregion
// region drop = [a] => Integer => [a]
const drop = (as) => (i) => null
eq(drop(['a', 'b', 'c'], 2), ['c']) // ?
eq(drop(['a', 'b', 'c'], 5), []) // ?
eq(drop(['a', 'b', 'c'], 0), ['a', 'b', 'c']) // ?
// endregion
/*
* 'Origami Programming' by Hugo Sereno Ferreira
*
* IEEE Talk @ FEUP (2018)
*
* Exercise sheet (http://goo.gl/Dd4p7b) - TypeScript version
*
* Note: Make sure you have node.js, and then install the dependencies using:
*
* npm install -g lodash
* npm install -g typescript
*/
// region Preamble
import { isEqual as eq } from 'lodash'
// endregion
const fold = <A, B>(as: Iterable<A>, base: B) => (f: (acc: B, e: A) => B): B => {
let result = base
for (const e of as) { result = f(result, e) }
return result
}
// region foreach
const foreach = <A>(as: A[]) => (f: (e: A) => void): void => undefined
const farr = new Array()
foreach([1, 2, 3])(e => farr.push(e))
eq(farr, [1, 2, 3]) //?
// endregion
// region map
const map = <A, B>(as: A[]) => (f: (e: A) => B): B[] => undefined
map([1, 2, 3])(e => e + 1) //?
eq(map([1, 2, 3])(e => e + 1), [2, 3, 4]) //?
eq(map([])(x => x + 5), []) //?
// endregion
// region filter
const filter = <A>(as: A[]) => (f: (e: A) => boolean): A[] => undefined
eq(filter([1, 2, 3, 4, 5, 6])(e => e % 2 === 1), [1, 3, 5]) //?
eq(filter([1, 2, 3, 4, 5, 6])(e => e % 2 === 0), [2, 4, 6]) //?
// endregion
// region filterNot
const filterNot = <A>(as: A[]) => (f: (e: A) => boolean): A[] => undefined
eq(filterNot([1, 2, 3, 4, 5, 6])(e => e % 2 === 1), [2, 4, 6]) //?
eq(filterNot([1, 2, 3, 4, 5, 6])(e => e % 2 === 0), [1, 3, 5]) //?
// endregion
// region exists
const exists = <A>(as: A[]) => (f: (e: A) => boolean): boolean => undefined
exists([1, 2, 3])(e => e === 3) === true //?
exists([1, 2, 3])(e => e > 2) === true//?
exists([1, 2, 3])(e => e === 5) === false //?
// endregion
// region forall
const forall = <A>(as: A[]) => (f: (e: A) => boolean): boolean => undefined
forall([1, 2, 3])(e => e < 4) === true //?
forall([1, 2, 3])(e => e > 4) === false //?
forall([])(e => e > 5) === true //?
// endregion
// region length
const length = <A>(as: A[]): number => undefined
length([1, 2, 3]) === 3 //?
length([]) === 0 //?
// endregion
// region isEmpty
const isEmpty = <A>(as: A[]): boolean => undefined
isEmpty([]) === true //?
isEmpty([1, 2, 3]) === false //?
// endregion
// region notEmpty
const notEmpty = <A>(as: A[]): boolean => undefined
notEmpty([]) === false //?
notEmpty([1, 2, 3]) === true //?
// endregion
// region reverse
const reverse = <A>(as: A[]): A[] => undefined
eq(reverse([1, 2, 3]), [3, 2, 1]) //?
eq(reverse([]), []) //?
// endregion
// region first
const first = <A>(as: A[]): A | undefined => undefined
first([1, 2, 3]) === 1 //?
first([]) === undefined //?
// endregion
// region last
const last = <A>(as: A[]): A | undefined => undefined
last([1, 2, 3]) === 3 //?
last([]) === undefined //?
// endregion
// region tail
const tail = <A>(as: A[]): A[] => undefined
eq(tail([1, 2, 3]), [2, 3]) //?
eq(tail([2, 3]), [3]) //?
eq(tail([3]), []) //?
eq(tail([]), []) //?
// endregion
// region second
const second = <A>(as: A[]): A | undefined => undefined
second([1, 2, 3]) === 2 //?
second([1]) === null //?
second([]) === null //?
// endregion
// region max
const max = <A>(as: A[]): A | undefined => undefined
max([1, 2, 3]) === 3//?
max([1]) === 1//?
max([]) === undefined //?
// endregion
// region maxBy
const maxBy = <A, B>(as: A[]) => (f: (e: A) => B): A | undefined => undefined
eq(maxBy([{ a: 1 }, { a: 2 }, { a: 3 }])(e => e.a), { a: 3 }) //?
// endregion
// region min
const min = <A>(as: A[]): A | undefined => undefined
min([1, 2, 3]) === 1//?
min([1]) === 1//?
min([]) === undefined //?
// endregion
// region minBy
const minBy = <A, B>(as: A[]) => (f: (e: A) => B): A | undefined => undefined
eq(minBy([{ a: 1 }, { a: 2 }, { a: 3 }])(e => e.a), { a: 1 }) //?
// endregion
// region index
const index = <A>(as: A[]) => (i: number): A | undefined => undefined
index(['a', 'b', 'c'])(0) === 'a' //?
index([1, 2, 3])(1) === 2 //?
// endregion
// region indexWhere
const indexWhere = <A>(as: A[]) => (f: (e: A) => boolean): number | undefined => undefined
indexWhere(['a', 'b', 'c'])(e => e === 'b') === 1 //?
indexWhere(['a', 'b', 'c'])(e => e === 'd') === null //?
// endregion
// region find
const find = <A>(as: A[]) => (f: (e: A) => boolean): A | undefined => undefined
eq(find([{ name: 'quim', age: 2 }, { name: 'tostas', age: 3 }])(e => e.age === 3), { name: 'tostas', age: 3 }) //?
find([{ name: 'quim', age: 2 }])(e => e.age === 52) === null //?
// endregion
// region take
const take = <A>(as: A[]) => (i: number): A[] => undefined
eq(take(['a', 'b', 'c'])(2), ['a', 'b']) // ?
eq(take(['a', 'b', 'c'])(5), ['a', 'b', 'c']) // ?
eq(take(['a', 'b', 'c'])(0), []) // ?
// endregion
// region drop
const drop = <A>(as: A[]) => (i: number): A[] => undefined
eq(drop(['a', 'b', 'c'])(2), ['c']) // ?
eq(drop(['a', 'b', 'c'])(5), []) // ?
eq(drop(['a', 'b', 'c'])(0), ['a', 'b', 'c']) // ?
// endregion
// region takeWhile
const takeWhile = <A>(as: A[]) => (f: (e: A) => boolean): A[] => undefined
eq(takeWhile([1, 2, 3, 4, 5])(e => e <= 2), [1, 2]) //?
// endregion
// region dropWhile
const dropWhile = <A>(as: A[]) => (f: (e: A) => boolean): A[] => undefined
eq(dropWhile([1, 2, 3, 4, 5])(e => e <= 2), [3, 4, 5]) //?
// endregion
// region partition = [a] => (a => bool) => ([a], [a])
const partition = <A>(as: A[]) => (f: (e: A) => boolean): [A, A] => undefined
eq(partition([1, 2, 3, 4])(e => e % 2 === 1), [[1, 3], [2, 4]]) //?
// endregion
// region splitAt = [a] => Integer => ([a], [a])
const splitAt = <A>(as: A[]) => (i: number): [A, A] => undefined
eq(splitAt([1, 2, 3])(2), [[1, 2], [3]]) //?
// endregion
// region zip = [a] => [b] => [(a, b)]
const zip = <A, B>(as: A[]) => (bs: B[]): [A, B][] => undefined
eq(zip([1, 2, 3])(['a', 'b', 'c']), [[1, 'a'], [2, 'b'], [3, 'c']]) //?
// endregion
// region zipWithIndex = [a] => [(Integer, b)]
const zipWithIndex = <A>(as: A[]): [A, number][] => undefined
zipWithIndex(['a', 'b', 'c']) //?
eq(zipWithIndex(['a', 'b', 'c']), [['a', 0], ['b', 1], ['c', 2]]) //?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment