Skip to content

Instantly share code, notes, and snippets.

@randrews
Created September 11, 2010 21:33
Show Gist options
  • Save randrews/575569 to your computer and use it in GitHub Desktop.
Save randrews/575569 to your computer and use it in GitHub Desktop.
-- 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