Skip to content

Instantly share code, notes, and snippets.

@kersny
Created December 14, 2011 03:26
Show Gist options
  • Save kersny/1475141 to your computer and use it in GitHub Desktop.
Save kersny/1475141 to your computer and use it in GitHub Desktop.
http://experthuman.com/programming-with-nothing in CoffeeScript (my first CS code)
INCREMENT = (n) -> (p) -> (x) -> p(n(p)(x))
DECREMENT = (n) -> (f) -> (x) -> n((g) -> (h) -> h(g(f)))((y) -> x)((y) -> y)
ADD = (m) -> (n) -> n(INCREMENT)(m)
SUBTRACT = (m) -> (n) -> n(DECREMENT)(m)
MULTIPLY = (m) -> (n) -> n(ADD(m))(ZERO)
POW = (m) -> (n) -> n(MULTIPLY(m))(ONE)
ZERO = (f) -> (x) -> x
ONE = (f) -> (x) -> f(x)
TWO = (f) -> (x) -> f(f(x))
THREE = (f) -> (x) -> f(f(f(x)))
FOUR = (f) -> (x) -> f(f(f(f(x))))
FIVE = (f) -> (x) -> f(f(f(f(f(x)))))
SIX = MULTIPLY(THREE)(TWO)
TEN = MULTIPLY(FIVE)(TWO)
FIFTEEN = MULTIPLY(FIVE)(THREE)
ONEHUNDRED = MULTIPLY(FIVE)(MULTIPLY(FOUR)(FIVE))
TRUE = (x) -> (y) -> x
FALSE = (x) -> (y) -> y
B = TEN
F = INCREMENT(B)
I = INCREMENT(F)
U = INCREMENT(I)
Z = INCREMENT(U)
IF = (b) -> b
IS_ZERO = (n) -> n((x) -> FALSE)(TRUE)
IS_LESS_OR_EQUAL = (m) -> (n) -> IS_ZERO(SUBTRACT(m)(n))
ZC = (f) -> ((x) -> f((y) -> x(x)(y)))((x) -> f((y) -> x(x)(y)))
MOD = ZC((f) -> (m) -> (n) -> IF(IS_LESS_OR_EQUAL(n)(m))((x) -> f(SUBTRACT(m)(n))(n)(x))(m))
PAIR = (x) -> (y) -> (f) -> f(x)(y)
LEFT = (p) -> p((x) -> (y) -> x)
RIGHT = (p) -> p((x) -> (y) -> y)
EMPTY = PAIR(TRUE)(TRUE)
UNSHIFT = (l) -> (x) -> PAIR(FALSE)(PAIR(x)(l))
IS_EMPTY = LEFT
FIRST = (l) -> LEFT RIGHT l
REST = (l) -> RIGHT RIGHT l
RANGE = ZC((f) => (m) -> (n) -> IF(IS_LESS_OR_EQUAL(m)(n))((x) -> UNSHIFT(f(INCREMENT(m))(n))(m)(x))(EMPTY))
FOLD = ZC((f) -> (l) -> (x) -> (g) -> IF(IS_EMPTY(l))(x)((y) -> g(f(REST(l))(x)(g))(FIRST(l))(y)))
MAP = (k) -> (f) -> FOLD(k)(EMPTY)((l) -> (x) -> UNSHIFT(l)(f(x)))
FIZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(Z))(Z))(I))(F)
BUZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(Z))(Z))(U))(B)
FIZZBUZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(BUZZ)(Z))(Z))(I))(F)
DIV = ZC((f) -> (m) -> (n) -> IF(IS_LESS_OR_EQUAL(n)(m))((x) -> INCREMENT(f(SUBTRACT(m)(n))(n))(x))(ZERO))
PUSH = (l) -> (x) -> FOLD(l)(UNSHIFT(EMPTY)(x))(UNSHIFT)
TO_DIGITS = ZC((f) -> (n) -> PUSH(IF(IS_LESS_OR_EQUAL(n)(DECREMENT(TEN)))(EMPTY)((x) -> f(DIV(n)(TEN))(x)))(MOD(n)(TEN)))
to_int = (num) -> num((x) -> x + 1)(0)
to_bool = (b) -> b(true)(false)
to_array = (p) ->
ret = []
until to_bool IS_EMPTY p
ret.push FIRST p
p = REST p
ret
to_char = (c) -> '0123456789BFiuz'[to_int c]
to_string = (s) -> to_array(s).map((c) -> to_char(c)).join('')
fizzbuzz = MAP(RANGE(ONE)(ONEHUNDRED))((n) -> IF(IS_ZERO(MOD(n)(FIFTEEN)))(FIZZBUZZ)(IF(IS_ZERO(MOD(n)(THREE)))(FIZZ)(IF(IS_ZERO(MOD(n)(FIVE)))(BUZZ)(TO_DIGITS(n)))))
console.dir to_array(fizzbuzz).map((x) -> to_string x)
@tomstuart
Copy link

Bravo!

It's amazing how fast this runs; on my machine it takes about two seconds in Chrome. The Ruby version takes about two minutes.

(Erratum: to_string(BUZZ) is 'Bizz'.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment