Skip to content

Instantly share code, notes, and snippets.

@cohama
Created October 24, 2015 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cohama/ee7ad0a5a75f0bdc4e09 to your computer and use it in GitHub Desktop.
Save cohama/ee7ad0a5a75f0bdc4e09 to your computer and use it in GitHub Desktop.
"use strict"
const ZERO = f => x => x
const ONE = f => x => f(x)
const TWO = f => x => f(f(x))
const THREE = f => x => f(f(f(x)))
const FOUR = f => x => f(f(f(f(x))))
const FIVE = f => x => f(f(f(f(f(x)))))
const SUCC = n => f => x => n(f)(f(x))
const SLIDE = p => PAIR(SND(p))(SUCC(SND(p)))
const PRED = n => FST(n(SLIDE)(PAIR(ZERO)(ZERO)))
const ADD = n => m => m(SUCC)(n)
const SUBTRACT = n => m => m(PRED)(n)
const MULTIPLY = n => m => m(ADD(n))(ZERO)
const POWER = n => m => m(MULTIPLY(n))(ONE)
const TEN = MULTIPLY(TWO)(FIVE)
const FIFTEEN = MULTIPLY(THREE)(FIVE)
const HUNDRED = POWER(TEN)(TWO)
const MOD_BAD = n => m =>
IF(LTEQ(m)(n)) (
x => MOD(SUBTRACT(n)(m))(m)(x)
) (
n
)
const Z = f => (x => f(y => x(x)(y)))(x => f(y => x(x)(y)))
const FLIP = f => x => y => f(y)(x)
const MOD = Z(mod => n => m =>
IF(LTEQ(m)(n)) (
x => mod(SUBTRACT(n)(m))(m)(x)
) (
n
)
)
const DIV = n => m =>
Z(div => (
i => j =>
IF (GTEQ(i)(j)) (
x => SUCC(div(SUBTRACT(i)(j))(j))(x)
) (
ZERO
)
))(n)(m)
const TO_DIGIT = n => REVERSE(Z(toDigit =>
i =>
IF (GTEQ(i)(TEN)) (
x => CONS(MOD(i)(TEN))(toDigit(DIV(i)(TEN)))(x)
) (
y => CONS(i)(NIL)(y)
)
)(n))
const TRUE = o => x => o
const FALSE = o => x => x
const IF = b => b
const IS_ZERO = n => n(_ => FALSE)(TRUE)
const NOT = b => b(FALSE)(TRUE)
const LTEQ = n => m => IS_ZERO(SUBTRACT(n)(m))
const LT = n => m => LTEQ(SUCC(n))(m)
const GT = FLIP(LT)
const GTEQ = FLIP(LTEQ)
const PAIR = x => y => f => f(x)(y)
const FST = p => p(o => _ => o)
const SND = p => p(_ => o => o)
const NIL = PAIR(TRUE)(TRUE)
const CONS = x => xs => PAIR(FALSE)(PAIR(x)(xs))
const IS_EMPTY = FST
const HEAD = xs => FST(SND(xs))
const TAIL = xs => SND(SND(xs))
const RANGE = Z(range => n => m =>
IF(LTEQ(n)(m)) (
x => CONS(n)(range(SUCC(n))(m))(x)
) (
NIL
)
)
const FOLDL = Z(foldl => f => init => xs =>
IF (IS_EMPTY(xs)) (
init
) (
y => foldl(f)(f(init)(HEAD(xs)))(TAIL(xs))(y)
)
)
const FOLDR = Z(foldr => f => init => xs =>
IF (IS_EMPTY(xs)) (
init
) (
y => f(HEAD(xs))(foldr(f)(init)(TAIL(xs)))(y)
)
)
const REVERSE = FOLDL(FLIP(CONS))(NIL)
const MAP = f => FOLDR(h => CONS(f(h)))(NIL)
const CONCAT = FLIP(FOLDR(CONS))
const ChrF = MULTIPLY(TWO)(FIVE)
const Chri = SUCC(ChrF)
const Chrz = SUCC(Chri)
const ChrB = SUCC(Chrz)
const Chru = SUCC(ChrB)
const STR_FIZZ = CONS(ChrF)(CONS(Chri)(CONS(Chrz)(CONS(Chrz)(NIL))))
const STR_BUZZ = CONS(ChrB)(CONS(Chru)(CONS(Chrz)(CONS(Chrz)(NIL))))
const STR_FIZZBUZZ = CONCAT(STR_FIZZ)(STR_BUZZ)
const jsNumber = n => n(x => x + 1)(0)
const jsBool = b => b(true)(false)
const jsPair = p => p(a => b => [a, b])
const jsArray = xs => {
let a = []
while (jsBool(NOT(IS_EMPTY(xs)))) {
a.push(HEAD(xs))
xs = TAIL(xs)
}
return a
}
const jsNumArray = xs => jsArray(xs).map(jsNumber)
const jsString = s => {
const base = '0123456789FizBu'
return jsArray(s).reduce((a, x) => {
return a + base[jsNumber(x)]
}, "")
}
const FIZZBUZZ_SOLUTION =
MAP(i =>
IF (IS_ZERO(MOD(i)(FIFTEEN))) (
STR_FIZZBUZZ
) (IF (IS_ZERO(MOD(i)(FIVE))) (
STR_BUZZ
) (IF (IS_ZERO(MOD(i)(THREE))) (
STR_FIZZ
) (
TO_DIGIT(i)
)))
)(RANGE(ONE)(HUNDRED))
console.log(jsArray(FIZZBUZZ_SOLUTION).map(jsString));
/* eslint-env es6 */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment