Created
September 11, 2010 21:33
-
-
Save randrews/575569 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Summing the sequence 1..n in as many ways as I can think of! | |
-- With the closed form | |
function sum(n) | |
return ((n+1) * n) / 2 | |
end | |
print(sum(6)) -- Had better be 21 | |
-- With tail recursion | |
function sum2(n) | |
local sum_help -- Must declare this first so it's in the function's scope | |
sum_help = function(k, total) | |
if k == 0 then | |
return total | |
else | |
return sum_help(k-1, total+k) | |
end | |
end | |
return sum_help(n, 0) | |
end | |
print(sum2(6)) -- had better be 21 | |
-- By making an array (method 1) | |
function sum3(n) | |
local a = {} | |
local k = 1 | |
while k <= n do | |
a[k] = k | |
k = k + 1 | |
end | |
local sum = 0 | |
k = 1 | |
while k <= #a do | |
sum = sum + a[k] | |
k = k + 1 | |
end | |
return sum | |
end | |
print(sum3(6)) -- had better be 21 | |
-- By making an array (method 2) | |
function sum4(n) | |
local a = {} | |
for k=1,n do | |
a[k] = k | |
end | |
local sum = 0 | |
for k,v in pairs(a) do | |
sum = sum + v | |
end | |
return sum | |
end | |
print(sum4(6)) -- had better be 21 | |
-- With a numeric for loop | |
function sum5(n) | |
local total = 0 | |
for k=1,n do | |
total = total + k | |
end | |
return total | |
end | |
print(sum5(6)) -- had better be 21 | |
-- Another tail recursion, no helper | |
function sum6(n,total) | |
total = total or 0 -- Standard idiom for a default argument | |
if n == 0 then | |
return total | |
else | |
return sum6(n-1, total+n) | |
end | |
end | |
print(sum6(6)) -- had better be 21 | |
-- Defining an iterator | |
function sum7(n) | |
local function upto(max) | |
local current = 0 | |
return function() | |
current = current + 1 | |
if current > max then | |
return nil | |
else | |
return current | |
end | |
end | |
end | |
total = 0 | |
for k in upto(n) do | |
total = total + k | |
end | |
return total | |
end | |
print(sum7(6)) -- had better be 21 | |
-- Iterator with a state | |
function sum8(n) | |
local function range_iterator(state) | |
state.current = state.current + 1 | |
if state.current <= state.max then | |
return state.current | |
else | |
return nil | |
end | |
end | |
local function range(max) | |
return range_iterator, {max=max, current=0} | |
end | |
total = 0 | |
for k in range(n) do | |
total = total + k | |
end | |
return total | |
end | |
print(sum8(6)) -- had better be 21 | |
-- Another iterator, just using the current value | |
function sum9(n) | |
local function range_iterator(state, current) | |
if current > 0 then | |
return current-1 | |
else | |
return nil | |
end | |
end | |
local function range(max) | |
return range_iterator, nil, max+1 | |
end | |
total = 0 | |
for k in range(n) do | |
total = total + k | |
end | |
return total | |
end | |
print(sum9(6)) -- had better be 21 | |
-- Using a coroutine | |
function sum10(n) | |
local co = coroutine.create(function() | |
for k = 1,n do coroutine.yield(k) end | |
end) | |
local total = 0 | |
local current | |
-- Resume returns whether the coroutine is still running, and *then* the yield. | |
-- So, we use select to pull just the second value. | |
local function it() | |
return select(2, coroutine.resume(co)) | |
end | |
for current in it do | |
total = total + current | |
end | |
return total | |
end | |
print(sum10(6)) -- had better be 21 | |
-- Using metatables | |
function sum11(n) | |
local mt = { __index = function(t,n) | |
if n == 1 then return 1 | |
else return n + t[n-1] end | |
end } | |
local t = {} | |
setmetatable(t,mt) | |
return t[n] | |
end | |
print(sum11(6)) -- had better be 21 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment