Implement functional programming paradigms
Haskell, many previous byte counts 127 * 0.9 = 114.3 bytes
f#(a:b)=f a:f#b;f#x=x
(f&x)0=x;(f&x)i=f$f&x$i-1
i=id
r x=i%(1,x)
(g?x)(a:b)=g(g?x$b)a;(g?x)y=x
f%(a,b)|a>b=[]|1<2=f a:f%(a+1,b)
No loops, just recursion.
#
is map: (*2) # [1,2,3]
-> [2,4,6]
&
is nest: ((*2) & 3) 4
-> 48
i
is apply: i (*2) 7
-> 14
r
is range: r 4
-> [1,2,3,4]
?
is fold: ((+) ? 0) [1,2,3,4]
-> 10
%
is table: (*2) % (2,4)
-> [4,6,8]
As requested an ungolfed version with comments. Note, &
and ?
are ternary infix operators, which require additional parentheses when called or pattern matched.
f # (a:b) = f a : f#b -- map on a list (a->head, b->tail) is f a in front of mapping f to b
f # x = x -- map on the empty list is the empty list
-- (non empty lists are caught in the line before)
(f & x) 0 = x -- nesting zero times is x
(f & x) i = f $ f&x $ i-1 -- nesting i times is f (nesting one time less)
i=id -- apply in Haskell is just the identity function
r x = i % (1,x) -- defined via the "table" of the identity function from 1 to x
(g ? x) (a:b) = g (g?x$b) a -- folding g into a list (a->head, b->tail) is g applied to (folding g into b) and a
(g ? x) y = x -- folding the empty list is x
-- again, y must be the empty list, else it would have been handled by the previous line
f % (a,b)
|a>b = [] -- if iMin is greater than iMax, the table is empty
|otherwise = f a : f%(a+1,b) -- otherwise f a in front of the table with iMin increased by one
Thanks to @dfeuer and @Zgarb for some useful hints
Python 2, 305.1 bytes (-10% 376 369 366 349 339 bytes)
exec'e=eval;q=len;m=@,l:e("["+"f(l.pop()),"*q(l)+"][::-1]");n=@,x,l:e("f("*l+"*x"+")"*l);r=@:e("r(f-1)+"*(f>1)+"[f]");a=@,a:e("f(a["+`r(q(a))`[1:-1]$",","-1],a[")+"-1])");f=@,x,l:e("f("*q(l)+"x,["+`r(q(l))`[1:-1]$",","-1]),l[")+"-1])");t=@,n,x:e("[f("+`r(x)[n-1:]`$",","),f(")[1:-1]+")]")'.replace("@","lambda f").replace("$",".replace(")
When expanded, equivalent to:
e=eval;q=len
m=lambda f,l:e("["+"f(l.pop()),"*q(l)+"][::-1]")
n=lambda f,x,l:e("f("*l+"*x"+")"*l)
r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
a=lambda f,a:e("f(a["+`r(q(a))`[1:-1].replace(",","-1],a[")+"-1])")
f=lambda f,x,l:e("f("*q(l)+"x,["+`r(q(l))`[1:-1].replace(",","-1]),l[")+"-1])")
t=lambda f,n,x:e("[f("+`r(x)[n-1:]`.replace(",","),f(")[1:-1]+")]")
No loops!
Well, it does a lot of eval
ing and if your boss can't stand loops, then they'll HATE eval. But, they're going to have to put up with it
A way to do range
in a lambda is appreciated so I don't have to do any functions (Shudder.).
Explanations:
m=lambda f,l:eval("["+"f(l.pop()),"*len(l)+"][::-1]")
- Create a string that pops elements from the list, wrap it into a list, reverse it and finally eval it!
n=lambda f,x,l:eval("f("*l+"*x"+")"*l)
- Manually create the string with the nesting, and eval it!
r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
- Create a string that when
eval
ed, either returns[0]
or uses recursion to get the previous results and adds the current index to the list. Evals it.
- Create a string that when
a=lambda f,a:eval("f(a["+
r(len(a))[1:-1].replace(",","-1],a[")+"-1])")
- Uses the range function to get the indexes 1-len(list). Replaces the commas in the list stringified with a way to get the correct index of the list
a
. Evals it!
- Uses the range function to get the indexes 1-len(list). Replaces the commas in the list stringified with a way to get the correct index of the list
f=lambda f,x,l:eval("f("*len(l)+"x,["+
r(len(l))[1:-1].replace(",","-1]),l[")+"-1])")
- Same as apply except replaces the commas with closing brackets, commas and starting the list index.
t=lambda f,n,x:eval("[f("+
r(x)[n-1:].replace(",","),f(")[1:-1]+")]")
- Same as apply and fold except replaces with ending the function and calling the new one. Evals it!
Map, nest, range, apply, fold, table.
Thanks @Zgarb for a lambda for range!
Javascript ES6, 197 * 0.9 = 177.3 bytes
M=(f,l)=>F((a,b)=>[...a,f(b)],[],l)
N=(f,x,n)=>f(--n?N(f,x,n):x)
A=(f,l)=>f(...l)
R=n=>n--?[...R(n),n+1]:[]
F=(f,x,l,n=l.length)=>n--?f(F(f,x,l,n),l[n]):x
T=(f,i)=>([n,x]=i,M(q=>f(q+n-1),R(x-n+1)))
Map (M=(f,l)=>F((a,b)=>[...a,f(b)],[],l)
):
Uses Fold to concat the results of f
applied to every member of l
onto an empty list. Using built-in functions reduces the this to M=(f,l)=>l.map(f)
(didn't use it because it seems cheap...?).
Nest (N=(f,x,n)=>f(--n?N(f,x,n):x)
):
Apply f
recursively until n
is decremented to 0.
Apply (A=(f,l)=>f(...l)
):
Uses the spread (...
) operator to apply l
onto f
.
Range (R=n=>n--?[...R(n),n+1]:[]
):
Concat n
to recursive call of Range until n
is decremented to 0.
Fold (F=(f,x,l,n=l.length)=>n--?f(F(f,x,l,n),l[n]):x
):
Applies the recursive call of Fold and the n
'th element of l
to f
until n
is decremented to 0. Using built-in functions reduces this to F=(f,x,l)=>l.reduce(f,x)
(again, seemed cheap...).
Table (T=(f,i)=>([n,x]=i,M(q=>f(q+n-1),R(x-n+1)))
):
First initializes n
and x
to iMin and iMax using destructuring ([n,x]=i
), then uses Range to construct the table of values from iMin to iMax. f
is then applied over the table using Map and the result is returned.