Fast Fourier transform

Calculate the   FFT   (Fast Fourier Transform)   of an input sequence.

The most general case allows for complex numbers at the input
and results in a sequence of equal length, again of complex numbers.
If you need to restrict yourself to real numbers, the output should
be the magnitude   (i.e.:   sqrt(re2 + im2))   of the complex result.

The classic version is the recursive Cooley-Tukey FFT. Wikipedia has pseudo-code for that.
Further optimizations are possible but not required.

Solution:
-- operations on complex number
complex = {__mt={} }

function complex.new (r, i)
  local new={r=r, i=i or 0}
  setmetatable(new,complex.__mt)
  return new
end

function complex.__mt.__add (c1, c2)
  return complex.new(c1.r + c2.r, c1.i + c2.i)
end

function complex.__mt.__sub (c1, c2)
  return complex.new(c1.r - c2.r, c1.i - c2.i)
end

function complex.__mt.__mul (c1, c2)
  return complex.new(c1.r*c2.r - c1.i*c2.i,
                      c1.r*c2.i + c1.i*c2.r)
end

function complex.expi (i)
  return complex.new(math.cos(i),math.sin(i))
end

function complex.__mt.__tostring(c)
  return "("..c.r..","..c.i..")"
end

-- Cooley–Tukey FFT (in-place, divide-and-conquer)
-- Higher memory requirements and redundancy although more intuitive
function fft(vect)
  local n=#vect
  if n<=1 then return vect end
-- divide
  local odd,even={},{}
  for i=1,n,2 do
    odd[#odd+1]=vect[i]
    even[#even+1]=vect[i+1]
  end
-- conquer
  fft(even);
  fft(odd);
-- combine
  for k=1,n/2 do
    local t=even[k] * complex.expi(-2*math.pi*(k-1)/n)
    vect[k] = odd[k] + t;
    vect[k+n/2] = odd[k] - t;
  end
  return vect
end

function toComplex(vectr)
  vect={}
  for i,r in ipairs(vectr) do
    vect[i]=complex.new(r)
  end
  return vect
end

-- test
data = toComplex{1, 1, 1, 1, 0, 0, 0, 0};

-- this works for old lua versions & luaJIT (depends on version!)
-- print("orig:", unpack(data))
-- print("fft:", unpack(fft(data)))

-- Beginning with Lua 5.2 you have to write
print("orig:", table.unpack(data))
print("fft:", table.unpack(fft(data)))


Feigenbaum constant calculation

Calculate the Feigenbaum constant.

;See:
:*   Details in the Wikipedia article:   Feigenbaum constant.

Solution:
function leftShift(n,p)
    local r = n
    while p>0 do
        r = r * 2
        p = p - 1
    end
    return r
end

-- main

local MAX_IT = 13
local MAX_IT_J = 10
local a1 = 1.0
local a2 = 0.0
local d1 = 3.2

print(" i       d")
for i=2,MAX_IT do
    local a = a1 + (a1 - a2) / d1
    for j=1,MAX_IT_J do
        local x = 0.0
        local y = 0.0
        for k=1,leftShift(1,i) do
            y = 1.0 - 2.0 * y * x
            x = a - x * x
        end
        a = a - x / y
    end
    d = (a1 - a2) / (a - a1)
    print(string.format("%2d    %.8f", i, d))
    d1 = d
    a2 = a1
    a1 = a
end


Fibonacci n-step number sequences

These number series are an expansion of the ordinary [[Fibonacci sequence]] where:
# For n = 2 we have the Fibonacci sequence; with initial values [1, 1] and F_k^2 = F_{k-1}^2 + F_{k-2}^2
# For n = 3 we have the tribonacci sequence; with initial values [1, 1, 2] and F_k^3 = F_{k-1}^3 + F_{k-2}^3 + F_{k-3}^3
# For n = 4 we have the tetranacci sequence; with initial values [1, 1, 2, 4] and F_k^4 = F_{k-1}^4 + F_{k-2}^4 + F_{k-3}^4 + F_{k-4}^4...
# For general n>2 we have the Fibonacci n-step sequence - F_k^n; with initial values of the first n values of the (n-1)'th Fibonacci n-step sequence F_k^{n-1}; and k'th value of this n'th sequence being F_k^n = \sum_{i=1}^{(n)} {F_{k-i}^{(n)}}

For small values of n, Greek numeric prefixes are sometimes used to individually name each series.

:::: {| style="text-align: left;" border="4" cellpadding="2" cellspacing="2"
|+ Fibonacci n-step sequences
|- style="background-color: rgb(255, 204, 255);"
! n !! Series name !! Values
|-
|  2 ||  fibonacci || 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 ...
|-
|  3 || tribonacci || 1 1 2 4 7 13 24 44 81 149 274 504 927 1705 3136 ...
|-
|  4 || tetranacci || 1 1 2 4 8 15 29 56 108 208 401 773 1490 2872 5536 ...
|-
|  5 || pentanacci || 1 1 2 4 8 16 31 61 120 236 464 912 1793 3525 6930 ...
|-
|  6 ||  hexanacci || 1 1 2 4 8 16 32 63 125 248 492 976 1936 3840 7617 ...
|-
|  7 || heptanacci || 1 1 2 4 8 16 32 64 127 253 504 1004 2000 3984 7936 ...
|-
|  8 ||  octonacci || 1 1 2 4 8 16 32 64 128 255 509 1016 2028 4048 8080 ...
|-
|  9 ||  nonanacci || 1 1 2 4 8 16 32 64 128 256 511 1021 2040 4076 8144 ...
|-
| 10 ||  decanacci || 1 1 2 4 8 16 32 64 128 256 512 1023 2045 4088 8172 ...
|}

Allied sequences can be generated where the initial values are changed:
: '''The Lucas series''' sums the two preceding values like the fibonacci series for n=2 but uses [2, 1] as its initial values.

;Task:
# Write a function to generate Fibonacci n-step number sequences given its initial values and assuming the number of initial values determines how many previous values are summed to make the next number of the series.
# Use this to print and show here at least the first ten members of the Fibo/tribo/tetra-nacci and Lucas sequences.

;Related tasks:
*   [[Fibonacci sequence]]
*   Wolfram Mathworld
*   [[Hofstadter Q sequence]]
*   [[Leonardo numbers]]

;Also see:
*   Lucas Numbers - Numberphile (Video)
*   Tribonacci Numbers (and the Rauzy Fractal) - Numberphile (Video)
*   Wikipedia, Lucas number
*   MathWorld, Fibonacci Number
*   Some identities for r-Fibonacci numbers
*   OEIS Fibonacci numbers
*   OEIS Lucas numbers

Solution:
function nStepFibs (seq, limit)
    local iMax, sum = #seq - 1
    while #seq < limit do
        sum = 0
        for i = 0, iMax do sum = sum + seq[#seq - i] end
        table.insert(seq, sum)
    end
    return seq
end

local fibSeqs = {
    {name = "Fibonacci",  values = {1, 1}      },
    {name = "Tribonacci", values = {1, 1, 2}   },
    {name = "Tetranacci", values = {1, 1, 2, 4}},
    {name = "Lucas",      values = {2, 1}      }
}
for _, sequence in pairs(fibSeqs) do
    io.write(sequence.name .. ": ")
    print(table.concat(nStepFibs(sequence.values, 10), " "))
end


Fibonacci word

The   Fibonacci Word   may be created in a manner analogous to the   Fibonacci Sequence    as described here:

     Define   F_Word1   as   '''1'''
     Define   F_Word2   as   '''0'''
     Form     F_Word3   as   F_Word2     concatenated with   F_Word1    i.e.:   '''01'''
     Form     F_Wordn   as   F_Wordn-1   concatenated with   F_wordn-2

;Task:
Perform the above steps for     n = 37.

You may display the first few but not the larger values of   n.
{Doing so will get the task's author into trouble with them what be (again!).}

Instead, create a table for   F_Words   '''1'''   to   '''37'''   which shows:
::*   The number of characters in the word
::*   The word's [[Entropy]]

;Related tasks:
*   Fibonacci word/fractal
*   [[Entropy]]
*   [[Entropy/Narcissist]]

Solution:
-- Return the base two logarithm of x
function log2 (x) return math.log(x) / math.log(2) end

-- Return the Shannon entropy of X
function entropy (X)
    local N, count, sum, i = X:len(), {}, 0
    for char = 1, N do
        i = X:sub(char, char)
        if count[i] then
            count[i] = count[i] + 1
        else
            count[i] = 1
        end
    end
    for n_i, count_i in pairs(count) do
        sum = sum + count_i / N * log2(count_i / N)
    end
    return -sum
end

-- Return a table of the first n Fibonacci words
function fibWords (n)
    local fw = {1, 0}
    while #fw < n do fw[#fw + 1] = fw[#fw] .. fw[#fw - 1] end
    return fw
end

-- Main procedure
print("n\tWord length\tEntropy")
for k, v in pairs(fibWords(37)) do
    v = tostring(v)
    io.write(k .. "\t" .. #v)
    if string.len(#v) < 8 then io.write("\t") end
    print("\t" .. entropy(v))
end


File extension is in extensions list

Checking if a file is in a certain category of file formats with known extensions (e.g. archive files, or image files) is a common problem in practice, and may be approached differently from extracting and outputting an arbitrary extension ''(see e.g. FileNameExtensionFilter in Java)''.

It also requires less assumptions about the format of an extension, because the calling code can decide what extensions are valid.

For these reasons, this task exists in addition to the [[Extract file extension]] task.

;Related tasks:
* [[Extract file extension]]
* [[String matching]]

Solution:
-- Data declarations
local extentions = {"zip", "rar", "7z", "gz", "archive", "A##", "tar.bz2"}
local testCases = {
  "MyData.a##",
  "MyData.tar.Gz",
  "MyData.gzip",
  "MyData.7z.backup",
  "MyData...",
  "MyData",
  "MyData_v1.0.tar.bz2",
  "MyData_v1.0.bz2"
}

-- Return boolean of whether example has a file extension found in extList
function extMatch (extList, example)
  for _, extension in pairs(extList) do
    if example:lower():match("%." .. extension:lower() .. "$") then
      return true
    end
  end
  return false
end

-- Main procedure
for _, case in pairs(testCases) do
  print(case .. ": " .. tostring(extMatch(extentions, case)))
end


Find if a point is within a triangle

Find if a point is within a triangle.

;Task:

::*   Assume points are on a plane defined by (x, y) real number coordinates.

::*   Given a point P(x, y) and a triangle formed by points A, B, and C, determine if P is within triangle ABC.

::*   You may use any algorithm.

::*   Bonus: explain why the algorithm you chose works.

;Related tasks:
*   [[Determine_if_two_triangles_overlap]]

;Also see:
:* Discussion of several methods. [[http://totologic.blogspot.com/2014/01/accurate-point-in-triangle-test.html]]
:* Determine if a point is in a polygon [[https://en.wikipedia.org/wiki/Point_in_polygon]]
:* Triangle based coordinate systems [[https://en.wikipedia.org/wiki/Barycentric_coordinate_system]]
:* Wolfram entry [[https://mathworld.wolfram.com/TriangleInterior.html]]

Solution:
EPS = 0.001
EPS_SQUARE = EPS * EPS

function side(x1, y1, x2, y2, x, y)
    return (y2 - y1) * (x - x1) + (-x2 + x1) * (y - y1)
end

function naivePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)
    local checkSide1 = side(x1, y1, x2, y2, x, y) >= 0
    local checkSide2 = side(x2, y2, x3, y3, x, y) >= 0
    local checkSide3 = side(x3, y3, x1, y1, x, y) >= 0
    return checkSide1 and checkSide2 and checkSide3
end

function pointInTriangleBoundingBox(x1, y1, x2, y2, x3, y3, x, y)
    local xMin = math.min(x1, x2, x3) - EPS
    local xMax = math.max(x1, x2, x3) + EPS
    local yMin = math.min(y1, y2, y3) - EPS
    local yMax = math.max(y1, y2, y3) + EPS
    return not (x < xMin or xMax < x or y < yMin or yMax < y)
end

function distanceSquarePointToSegment(x1, y1, x2, y2, x, y)
    local p1_p2_squareLength = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)
    local dotProduct = ((x - x1) * (x2 - x1) + (y - y1) * (y2 - y1)) / p1_p2_squareLength
    if dotProduct < 0 then
        return (x - x1) * (x - x1) + (y - y1) * (y - y1)
    end
    if dotProduct <= 1 then
        local p_p1_squareLength = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)
        return p_p1_squareLength - dotProduct * dotProduct * p1_p2_squareLength
    end
    return (x - x2) * (x - x2) + (y - y2) * (y - y2)
end

function accuratePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)
    if not pointInTriangleBoundingBox(x1, y1, x2, y2, x3, y3, x, y) then
        return false
    end
    if naivePointInTriangle(x1, y1, x2, y2, x3, y3, x, y) then
        return true
    end
    if distanceSquarePointToSegment(x1, y1, x2, y2, x, y) <= EPS_SQUARE then
        return true
    end
    if distanceSquarePointToSegment(x2, y2, x3, y3, x, y) <= EPS_SQUARE then
        return true
    end
    if distanceSquarePointToSegment(x3, y3, x1, y1, x, y) <= EPS_SQUARE then
        return true
    end
    return false
end

function printPoint(x, y)
    io.write('('..x..", "..y..')')
end

function printTriangle(x1, y1, x2, y2, x3, y3)
    io.write("Triangle is [")
    printPoint(x1, y1)
    io.write(", ")
    printPoint(x2, y2)
    io.write(", ")
    printPoint(x3, y3)
    print("]")
end

function test(x1, y1, x2, y2, x3, y3, x, y)
    printTriangle(x1, y1, x2, y2, x3, y3)
    io.write("Point ")
    printPoint(x, y)
    print(" is within triangle? " .. tostring(accuratePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)))
end

test(1.5, 2.4, 5.1, -3.1, -3.8, 1.2, 0, 0)
test(1.5, 2.4, 5.1, -3.1, -3.8, 1.2, 0, 1)
test(1.5, 2.4, 5.1, -3.1, -3.8, 1.2, 3, 1)
print()

test(0.1, 0.1111111111111111, 12.5, 33.333333333333336, 25, 11.11111111111111, 5.414285714285714, 14.349206349206348)
print()

test(0.1, 0.1111111111111111, 12.5, 33.333333333333336, -12.5, 16.666666666666668, 5.414285714285714, 14.349206349206348)
print()


Find limit of recursion

{{selection|Short Circuit|Console Program Basics}}

;Task:
Find the limit of recursion.

Solution:
local c = 0
function Tail(proper)
  c = c + 1
  if proper then
    if c < 9999999 then return Tail(proper) else return c end
  else
    return 1/c+Tail(proper) -- make the recursive call must keep previous stack
  end
end

local ok,check = pcall(Tail,true)
print(c, ok, check)
c=0
ok,check = pcall(Tail,false)
print(c, ok, check)


Find the intersection of a line with a plane

Finding the intersection of an infinite ray with a plane in 3D is an important topic in collision detection.

;Task:
Find the point of intersection for the infinite ray with direction   (0, -1, -1)   passing through position   (0, 0, 10)   with the infinite plane with a normal vector of   (0, 0, 1)   and which passes through [0, 0, 5].

Solution:
function make(xval, yval, zval)
    return {x=xval, y=yval, z=zval}
end

function plus(lhs, rhs)
    return make(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z)
end

function minus(lhs, rhs)
    return make(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z)
end

function times(lhs, scale)
    return make(scale * lhs.x, scale * lhs.y, scale * lhs.z)
end

function dot(lhs, rhs)
    return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z
end

function tostr(val)
    return "(" .. val.x .. ", " .. val.y .. ", " .. val.z .. ")"
end

function intersectPoint(rayVector, rayPoint, planeNormal, planePoint)
    diff = minus(rayPoint, planePoint)
    prod1 = dot(diff, planeNormal)
    prod2 = dot(rayVector, planeNormal)
    prod3 = prod1 / prod2
    return minus(rayPoint, times(rayVector, prod3))
end

rv = make(0.0, -1.0, -1.0)
rp = make(0.0, 0.0, 10.0)
pn = make(0.0, 0.0, 1.0)
pp = make(0.0, 0.0, 5.0)
ip = intersectPoint(rv, rp, pn, pp)
print("The ray intersects the plane at " .. tostr(ip))


Find the intersection of two lines

Finding the intersection of two lines that are in the same plane is an important topic in collision detection.[http://mathworld.wolfram.com/Line-LineIntersection.html]

;Task:
Find the point of intersection of two lines in 2D.

The 1st     line passes though    (4,0)    and    (6,10) .
The 2nd line passes though    (0,3)    and    (10,7) .

Solution:
function intersection (s1, e1, s2, e2)
  local d = (s1.x - e1.x) * (s2.y - e2.y) - (s1.y - e1.y) * (s2.x - e2.x)
  local a = s1.x * e1.y - s1.y * e1.x
  local b = s2.x * e2.y - s2.y * e2.x
  local x = (a * (s2.x - e2.x) - (s1.x - e1.x) * b) / d
  local y = (a * (s2.y - e2.y) - (s1.y - e1.y) * b) / d
  return x, y
end

local line1start, line1end = {x = 4, y = 0}, {x = 6, y = 10}
local line2start, line2end = {x = 0, y = 3}, {x = 10, y = 7}
print(intersection(line1start, line1end, line2start, line2end))


Find the last Sunday of each month

Write a program or a script that returns the last Sundays of each month of a given year. The year may be given through any simple input method in your language (command line, std in, etc).

Example of an expected output:

./last_sundays 2013
2013-01-27
2013-02-24
2013-03-31
2013-04-28
2013-05-26
2013-06-30
2013-07-28
2013-08-25
2013-09-29
2013-10-27
2013-11-24
2013-12-29

;Related tasks
* [[Day of the week]]
* [[Five weekends]]
* [[Last Friday of each month]]

Solution:
function isLeapYear (y)
    return (y % 4 == 0 and y % 100 ~=0) or y % 400 == 0
end

function dayOfWeek (y, m, d)
    local t = os.time({year = y, month = m, day = d})
    return os.date("%A", t)
end

function lastWeekdays (wday, year)
    local monthLength, day = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    if isLeapYear(year) then monthLength[2] = 29 end
    for month = 1, 12 do
        day = monthLength[month]
        while dayOfWeek(year, month, day) ~= wday do day = day - 1 end
        print(year .. "-" .. month .. "-" .. day)
    end
end

lastWeekdays("Sunday", tonumber(arg[1]))


Find the missing permutation

ABCD
                    CABD
                    ACDB
                    DACB
                    BCDA
                    ACBD
                    ADCB
                    CDAB
                    DABC
                    BCAD
                    CADB
                    CDBA
                    CBAD
                    ABDC
                    ADBC
                    BDCA
                    DCBA
                    BACD
                    BADC
                    BDAC
                    CBDA
                    DBCA
                    DCAB

Listed above are   all-but-one   of the permutations of the symbols   '''A''',   '''B''',   '''C''',   and   '''D''',   ''except''   for one permutation that's   ''not''   listed.

;Task:
Find that missing permutation.

;Methods:
* Obvious method:
         enumerate all permutations of   '''A''',  '''B''',  '''C''',  and  '''D''',
         and then look for the missing permutation.

* alternate method:
         Hint:  if all permutations were shown above,  how many
         times would  '''A'''  appear in each position?
         What is the  ''parity''  of this number?

* another alternate method:
         Hint:  if you add up the letter values of each column,
         does a missing letter   '''A''',  '''B''',  '''C''',  and  '''D'''   from each
         column cause the total value for each column to be unique?

;Related task:
*   [[Permutations]])

Solution:
local permute, tablex = require("pl.permute"), require("pl.tablex")
local permList, pStr = {
    "ABCD", "CABD", "ACDB", "DACB", "BCDA", "ACBD", "ADCB", "CDAB",
    "DABC", "BCAD", "CADB", "CDBA", "CBAD", "ABDC", "ADBC", "BDCA",
    "DCBA", "BACD", "BADC", "BDAC", "CBDA", "DBCA", "DCAB"
}
for perm in permute.iter({"A","B","C","D"}) do
    pStr = table.concat(perm)
    if not tablex.find(permList, pStr) then print(pStr) end
end


First-class functions/Use numbers analogously

In [[First-class functions]], a language is showing how its manipulation of functions is similar to its manipulation of other types.

This tasks aim is to compare and contrast a language's implementation of first class functions, with its normal handling of numbers.

Write a program to create an ordered collection of a mixture of literally typed and expressions producing a real number, together with another ordered collection of their multiplicative inverses. Try and use the following pseudo-code to generate the numbers for the ordered collections:
   x  = 2.0
   xi = 0.5
   y  = 4.0
   yi = 0.25
   z  = x + y
   zi = 1.0 / ( x + y )

Create a function ''multiplier'', that given two numbers as arguments returns a function that when called with one argument, returns the result of multiplying the two arguments to the call to multiplier that created it and the argument in the call:
  new_function = multiplier(n1,n2)
  # where new_function(m) returns the result of n1 * n2 * m

Applying the multiplier of a number and its inverse from the two ordered collections of numbers in pairs, show that the result in each case is one.
'''Compare and contrast the resultant program with the corresponding entry in [[First-class functions]].''' They should be close.

To paraphrase the task description: Do what was done before, but with numbers rather than functions

Solution:
-- This function returns another function that
-- keeps n1 and n2 in scope, ie. a closure.
function multiplier (n1, n2)
    return  function (m)
                return n1 * n2 * m
            end
end

-- Multiple assignment a-go-go
local x, xi, y, yi  = 2.0, 0.5, 4.0, 0.25
local z, zi = x + y, 1.0 / ( x + y )
local nums, invs = {x, y, z}, {xi, yi, zi}

-- 'new_function' stores the closure and then has the 0.5 applied to it
-- (this 0.5 isn't in the task description but everyone else used it)
for k, v in pairs(nums) do
    new_function = multiplier(v, invs[k])
    print(v .. " * " .. invs[k] .. " * 0.5 = " .. new_function(0.5))
end


Fivenum

Many big data or scientific programs use boxplots to show distributions of data.   In addition, sometimes saving large arrays for boxplots can be impractical and use extreme amounts of RAM.   It can be useful to save large arrays as arrays with five numbers to save memory.

For example, the   '''R'''   programming language implements Tukey's five-number summary as the '''fivenum''' function.

;Task:
Given an array of numbers, compute the five-number summary.

;Note:
While these five numbers can be used to draw a boxplot,   statistical packages will typically need extra data.

Moreover, while there is a consensus about the "box" of the boxplot,   there are variations among statistical packages for the whiskers.

Solution:
function slice(tbl, low, high)
    local copy = {}

    for i=low or 1, high or #tbl do
        copy[#copy+1] = tbl[i]
    end

    return copy
end

-- assumes that tbl is sorted
function median(tbl)
    m = math.floor(#tbl / 2) + 1
    if #tbl % 2 == 1 then
        return tbl[m]
    end
    return (tbl[m-1] + tbl[m]) / 2
end

function fivenum(tbl)
    table.sort(tbl)

    r0 = tbl[1]
    r2 = median(tbl)
    r4 = tbl[#tbl]

    m = math.floor(#tbl / 2)
    if #tbl % 2 == 1 then
        low = m
    else
        low = m - 1
    end
    r1 = median(slice(tbl, nil, low+1))
    r3 = median(slice(tbl, low+2, nil))

    return r0, r1, r2, r3, r4
end

x1 = {
    {15.0, 6.0, 42.0, 41.0, 7.0, 36.0, 49.0, 40.0, 39.0, 47.0, 43.0},
    {36.0, 40.0, 7.0, 39.0, 41.0, 15.0},
    {
        0.14082834,  0.09748790,  1.73131507,  0.87636009, -1.95059594,  0.73438555,
       -0.03035726,  1.46675970, -0.74621349, -0.72588772,  0.63905160,  0.61501527,
       -0.98983780, -1.00447874, -0.62759469,  0.66206163,  1.04312009, -0.10305385,
        0.75775634,  0.32566578
    }
}

for i,x in ipairs(x1) do
    print(fivenum(x))
end


Fixed length records

Fixed length read/write

Before terminals, computers commonly used punch card readers or paper tape input.

A common format before these devices were superseded by terminal technology was based on the Hollerith code, Hollerith code.

These input devices handled 80 columns per card and had a limited character set, encoded by punching holes in one or more rows of the card for each column.

These devices assumed/demanded a fixed line width of 80 characters, newlines were not required (and could not even be encoded in some systems).

;Task:
Write a program to read 80 column fixed length records (no newline terminators (but newline characters allowed in the data)) and then write out the reverse of each line as fixed length 80 column records.

Samples here use printable characters, but that is not a given with fixed length data.  Filenames used are sample.txt, infile.dat, outfile.dat.

'''Note:''' There are no newlines, inputs and outputs are fixed at 80 columns, no more, no less, space padded.  Fixed length data is 8 bit complete.  NUL bytes of zero are allowed.

These fixed length formats are still in wide use on mainframes, with JCL and with COBOL (which commonly use EBCDIC encoding and not ASCII).  Most of the large players in day to day financial transactions know all about fixed length records and the expression ''logical record length''.

;Sample data:
To create the sample input file, use an editor that supports fixed length records or use a conversion utility.  For instance, most GNU/Linux versions of '''dd''' support blocking and unblocking records with a conversion byte size.

Line 1...1.........2.........3.........4.........5.........6.........7.........8
Line 2
Line 3
Line 4

Line 6
Line 7
     Indented line 8............................................................
Line 9                                                                 RT MARGIN
prompt$ dd if=sample.txt of=infile.dat cbs=80 conv=block will create a fixed length record file of 80 bytes given newline delimited text input.

prompt$ dd if=infile.dat cbs=80 conv=unblock will display a file with 80 byte logical record lengths to standard out as standard text with newlines.

;Bonus round:
Forth systems often include BLOCK words.  A block is 1024 bytes.  Source code is stored as 16 lines of 64 characters each (again, no newline character or sequence to mark the end of a line).

Write a program to convert a block file to text (using newlines). Trailing spaces should be excluded from the output.

Also demonstrate how to convert from a normal text file to block form. All lines either truncated or padded to 64 characters with no newline terminators. The last block filled to be exactly 1024 characters by adding blanks if needed. Assume a full range of 8 bit byte values for each character.

The COBOL example uses forth.txt and forth.blk filenames.

Solution:
-- prep: convert given sample text to fixed length "infile.dat"
local sample = [[
Line 1...1.........2.........3.........4.........5.........6.........7.........8
Line 2
Line 3
Line 4

Line 6
Line 7
     Indented line 8............................................................
Line 9                                                                 RT MARGIN]]
local txtfile = io.open("sample.txt", "w")
txtfile:write(sample)
txtfile:close()
os.execute("dd if=sample.txt of=infile.dat cbs=80 conv=block > /dev/null 2>&1")

-- task: convert fixed length "infile.dat" to fixed length "outfile.dat" (reversed lines)
local infile = io.open("infile.dat", "rb")
local outfile = io.open("outfile.dat", "wb")
while true do
  local line = infile:read(80)
  if not line then break end
  outfile:write(string.reverse(line))
end
infile:close()
outfile:close()

-- output:
os.execute("dd if=outfile.dat cbs=80 conv=unblock")


Flatten a list

Write a function to flatten the nesting in an arbitrary list of values.

Your program should work on the equivalent of this list:
   [[1], 2, [[3, 4], 5], [[[]]], [[[6]]], 7, 8, []]
Where the correct result would be the list:
    [1, 2, 3, 4, 5, 6, 7, 8]

;Related task:
*   [[Tree traversal]]

Solution:
function flatten(list)
  if type(list) ~= "table" then return {list} end
  local flat_list = {}
  for _, elem in ipairs(list) do
    for _, val in ipairs(flatten(elem)) do
      flat_list[#flat_list + 1] = val
    end
  end
  return flat_list
end

test_list = {{1}, 2, {{3,4}, 5}, {{{}}}, {{{6}}}, 7, 8, {}}

print(table.concat(flatten(test_list), ","))


Flipping bits game

The game:
Given an   '''NxN'''   square array of zeroes or ones in an initial configuration,   and a target configuration of zeroes and ones.

The game is to transform one to the other in as few moves as possible by inverting whole numbered rows or whole lettered
columns at once   (as one move).

In an inversion.   any  '''1'''  becomes  '''0''',   and any  '''0'''  becomes  '''1'''  for that whole row or column.

;Task:
Create a program to score for the Flipping bits game.
# The game should create an original random target configuration and a starting configuration.
# Ensure that the starting position is ''never'' the target position.
# The target position must be guaranteed as reachable from the starting position.   (One possible way to do this is to generate the start position by legal flips from a random target position.   The flips will always be reversible back to the target from the given start position).
# The number of moves taken so far should be shown.

Show an example of a short game here, on this page, for a   '''3x3'''   array of bits.

Solution:
target, board, moves, W, H = {}, {}, 0, 3, 3

function getIndex( i, j ) return i + j * W - W end

function flip( d, r )
    function invert( a ) if a == 1 then return 0 end return 1 end
    local idx
    if d == 1 then
        for i = 1, W do
            idx = getIndex( i, r )
            board[idx] = invert( board[idx] )
        end
    else
        for i = 1, H do
            idx = getIndex( r, i )
            board[idx] = invert( board[idx] )
        end
    end
    moves = moves + 1
end
function createTarget()
    target, board = {}, {}
    local idx
    for j = 1, H do
        for i = 1, W do
            idx = getIndex( i, j )
            if math.random() < .5 then target[idx] = 0
            else target[idx] = 1
            end
            board[idx] = target[idx]
        end
    end
    for i = 1, 103 do
        if math.random() < .5 then flip( 1, math.random( H ) )
        else flip( 2, math.random( W ) )
        end
    end
    moves = 0
end
function getUserInput()
    io.write( "Input row and/or column: " ); local r = io.read()
    local a
    for i = 1, #r do
        a = string.byte( r:sub( i, i ):lower() )
        if a >= 48 and a <= 57 then flip( 2, a - 48 ) end
        if a >= 97 and a <= string.byte( 'z' ) then flip( 1, a - 96 ) end
    end
end
function solved()
    local idx
    for j = 1, H do
        for i = 1, W do
            idx = getIndex( i, j )
            if target[idx] ~= board[idx] then return false end
        end
    end
    return true
end
function display()
    local idx
    io.write( "\nTARGET\n   " )
    for i = 1, W do io.write( string.format( "%d  ", i ) ) end; print()
    for j = 1, H do
        io.write( string.format( "%s  ", string.char( 96 + j ) ) )
        for i = 1, W do
            idx = getIndex( i, j )
            io.write( string.format( "%d  ", target[idx] ) )
        end; io.write( "\n" )
    end
    io.write( "\nBOARD\n   " )
    for i = 1, W do io.write( string.format( "%d  ", i ) ) end; print()
    for j = 1, H do
        io.write( string.format( "%s  ", string.char( 96 + j ) ) )
        for i = 1, W do
            idx = getIndex( i, j )
            io.write( string.format( "%d  ", board[idx] ) )
        end; io.write( "\n" )
    end
    io.write( string.format( "Moves: %d\n", moves ) )
end
function play()
    while true do
        createTarget()
        repeat
            display()
            getUserInput()
        until solved()
        display()
        io.write( "Very well!\nPlay again(Y/N)? " );
        if io.read():lower() ~= "y" then return end
    end
end
--[[entry point]]--
math.randomseed( os.time() )
play()


Floyd's triangle

Floyd's triangle   lists the natural numbers in a right triangle aligned to the left where
* the first row is   '''1'''     (unity)
* successive rows start towards the left with the next number followed by successive naturals listing one more number than the line above.

The first few lines of a Floyd triangle looks like this:

 1
 2  3
 4  5  6
 7  8  9 10
11 12 13 14 15

;Task:
:# Write a program to generate and display here the first   n   lines of a Floyd triangle. (Use   n=5   and   n=14   rows).
:# Ensure that when displayed in a mono-space font, the numbers line up in vertical columns as shown and that only one space separates numbers of the last row.

Solution:
function print_floyd(rows)
	local c = 1
	local h = rows*(rows-1)/2
	for i=1,rows do
		local s = ""
		for j=1,i do
			for k=1, #tostring(h+j)-#tostring(c) do
				s = s .. " "
			end
			if j ~= 1 then s = s .. " " end
			s = s .. tostring(c)
			c = c + 1
		end
		print(s)
	end
end

print_floyd(5)
print_floyd(14)


Four bit adder

"''Simulate''" a four-bit adder.

This design can be realized using four 1-bit full adders.
Each of these 1-bit full adders can be built with two gate. ;

Finally a half adder can be made using an   ''xor''   gate and an   ''and''   gate.

The   ''xor''   gate can be made using two   ''not''s,   two   ''and''s   and one   ''or''.

'''Not''',   '''or'''   and   '''and''',   the only allowed "gates" for the task, can be "imitated" by using the bitwise operators of your language.

If there is not a ''bit type'' in your language, to be sure that the   ''not''   does not "invert" all the other bits of the basic type   (e.g. a byte)   we are not interested in,   you can use an extra   ''nand''   (''and''   then   ''not'')   with the constant   '''1'''   on one input.

Instead of optimizing and reducing the number of gates used for the final 4-bit adder,   build it in the most straightforward way,   ''connecting'' the other "constructive blocks",   in turn made of "simpler" and "smaller" ones.

{|
|+Schematics of the "constructive blocks"
!(Xor gate with ANDs, ORs and NOTs)
!   (A half adder)
!          (A full adder)
!                (A 4-bit adder)
|-
|Xor gate done with ands, ors and nots
|A half adder
|A full adder
|A 4-bit adder
|}

Solutions should try to be as descriptive as possible, making it as easy as possible to identify "connections" between higher-order "blocks".

It is not mandatory to replicate the syntax of higher-order blocks in the atomic "gate" blocks, i.e. basic "gate" operations can be performed as usual bitwise operations, or they can be "wrapped" in a ''block'' in order to expose the same syntax of higher-order blocks, at implementers' choice.

To test the implementation, show the sum of two four-bit numbers (in binary).

Solution:
-- Build XOR from AND, OR and NOT
function xor (a, b) return (a and not b) or (b and not a) end

-- Can make half adder now XOR exists
function halfAdder (a, b) return xor(a, b), a and b end

-- Full adder is two half adders with carry outputs OR'd
function fullAdder (a, b, cIn)
    local ha0s, ha0c = halfAdder(cIn, a)
    local ha1s, ha1c = halfAdder(ha0s, b)
    local cOut, s = ha0c or ha1c, ha1s
    return cOut, s
end

-- Carry bits 'ripple' through adders, first returned value is overflow
function fourBitAdder (a3, a2, a1, a0, b3, b2, b1, b0) -- LSB-first
    local fa0c, fa0s = fullAdder(a0, b0, false)
    local fa1c, fa1s = fullAdder(a1, b1, fa0c)
    local fa2c, fa2s = fullAdder(a2, b2, fa1c)
    local fa3c, fa3s = fullAdder(a3, b3, fa2c)
    return fa3c, fa3s, fa2s, fa1s, fa0s -- Return as MSB-first
end

-- Take string of noughts and ones, convert to native boolean type
function toBool (bitString)
    local boolList, bit = {}
    for digit = 1, 4 do
        bit = string.sub(string.format("%04d", bitString), digit, digit)
        if bit == "0" then table.insert(boolList, false) end
        if bit == "1" then table.insert(boolList, true) end
    end
    return boolList
end

-- Take list of booleans, convert to string of binary digits (variadic)
function toBits (...)
    local bStr = ""
    for i, bool in pairs{...} do
        if bool then bStr = bStr .. "1" else bStr = bStr .. "0" end
    end
    return bStr
end

-- Little driver function to neaten use of the adder
function add (n1, n2)
    local A, B = toBool(n1), toBool(n2)
    local v, s0, s1, s2, s3 = fourBitAdder( A[1], A[2], A[3], A[4],
                                            B[1], B[2], B[3], B[4] )
    return toBits(s0, s1, s2, s3), v
end

-- Main procedure (usage examples)
print("SUM", "OVERFLOW\n")
print(add(0001, 0001)) -- 1 + 1 = 2
print(add(0101, 1010)) -- 5 + 10 = 15
print(add(0000, 1111)) -- 0 + 15 = 15
print(add(0001, 1111)) -- 1 + 15 = 16 (causes overflow)


Four is magic

Write a subroutine, function, whatever it may be called in your language, that takes an integer number and returns an English text sequence starting with the English cardinal representation of that integer, the word 'is' and then the English cardinal representation of the count of characters that made up the first word, followed by a comma.

Continue the sequence by using the previous count word as the first word of the next phrase, append 'is' and the cardinal count of the letters in ''that'' word.

Continue until you reach four. Since four has four characters, finish by adding the words 'four is magic' and a period. All integers will eventually wind up at four.

For instance, suppose your are given the integer '''3'''. Convert '''3''' to '''Three''', add ''' is ''', then the cardinal character count of three, or '''five''', with a comma to separate if from the next phrase. Continue the sequence '''five is four,''' (five has four letters), and finally, '''four is magic.'''

      '''Three is five, five is four, four is magic.'''

For reference, here are outputs for 0 through 9.

      Zero is four, four is magic.
      One is three, three is five, five is four, four is magic.
      Two is three, three is five, five is four, four is magic.
      Three is five, five is four, four is magic.
      Four is magic.
      Five is four, four is magic.
      Six is three, three is five, five is four, four is magic.
      Seven is five, five is four, four is magic.
      Eight is five, five is four, four is magic.
      Nine is four, four is magic.

;Some task guidelines:
:* You may assume the input will only contain integer numbers.
:* Cardinal numbers between 20 and 100 may use either hyphens or spaces as word separators but they must use a word separator. ('''23''' is '''twenty three''' or '''twenty-three''' not '''twentythree'''.)
:* Cardinal number conversions should follow the  English short scale. (billion is 1e9, trillion is 1e12, etc.)
:* Cardinal numbers should not include commas. ('''20140''' is '''twenty thousand one hundred forty''' not '''twenty thousand, one hundred forty'''.)
:* When converted to a string, '''100''' should be '''one hundred''', not '''a hundred''' or '''hundred''', '''1000''' should be '''one thousand''', not '''a thousand''' or '''thousand'''.
:* When converted to a string, there should be no '''and''' in the cardinal string. '''130''' should be '''one hundred thirty''' not '''one hundred and thirty'''.
:* When counting characters, count ''all'' of the characters in the cardinal number including spaces and hyphens. '''One hundred fifty-one''' should be '''21''' not '''18'''.
:* The output should follow the format "N is K, K is M, M is ... four is magic." (unless the input is 4, in which case the output should simply be "four is magic.")
:* The output can either be the return value from the function, or be displayed from within the function.
:* You are encouraged, though not mandated to use proper sentence capitalization.
:* You may optionally support negative numbers. '''-7''' is '''negative seven'''.
:* Show the output here for a small representative sample of values, at least 5 but no more than 25. You are free to choose which which numbers to use for output demonstration.

You can choose to use a library, (module, external routine, whatever) to do the cardinal conversions as long as the code is easily and freely available to the public.

If you roll your own, make the routine accept at minimum any integer from 0 up to 999999. If you use a pre-made library, support at least up to unsigned 64 bit integers. (or the largest integer supported in your language if it is less.)

Four is magic is a popular code-golf task. '''This is not code golf.''' Write legible, idiomatic and well formatted code.

;Related tasks:
:*   [[Four is the number of_letters in the ...]]
:*   [[Look-and-say sequence]]
:*   [[Number names]]
:*   [[Self-describing numbers]]
:*   [[Summarize and say sequence]]
:*   [[Spelling of ordinal numbers]]
:*   [[De Bruijn sequences]]

Solution:
-- Four is magic, in Lua, 6/16/2020 db
local oneslist = { [0]="", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }
local teenlist = { [0]="ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }
local tenslist = { [0]="", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" }
local lionlist = { [0]="", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", "decillion" }
local abs, floor = math.abs, math.floor

local function numname(num)
  if (num == 0) then return "zero" end
  local absnum, lion, result = abs(num), 0, ""
  local function dashed(s) return s=="" and s or "-"..s end
  local function spaced(s) return s=="" and s or " "..s end
  while (absnum > 0) do
    local word, ones, tens, huns = "", absnum%10, floor(absnum/10)%10, floor(absnum/100)%10
    if (tens==0) then word = oneslist[ones]
    elseif (tens==1) then word = teenlist[ones]
    else word = tenslist[tens] .. dashed(oneslist[ones]) end
    if (huns > 0) then word = oneslist[huns] .. " hundred" .. spaced(word) end
    if (word ~= "") then result = word .. spaced(lionlist[lion]) .. spaced(result) end
    absnum = floor(absnum / 1000)
    lion = lion + 1
  end
  if (num < 0) then result = "negative " .. result end
  return result
end

local function fourismagic(num)
  local function fim(num)
    local name = numname(num)
    if (num == 4) then
      return name .. " is magic."
    else
      local what = numname(#name)
      return name .. " is " .. what .. ", " .. fim(#name)
    end
  end
  local result = fim(num):gsub("^%l", string.upper)
  return result
end

local numbers = { -21,-1, 0,1,2,3,4,5,6,7,8,9, 12,34,123,456,1024,1234,12345,123456,1010101 }
for _, num in ipairs(numbers) do
  print(num, fourismagic(num))
end


Function prototype

Some languages provide the facility to declare functions and subroutines through the use of function prototyping.

;Task:
Demonstrate the methods available for declaring prototypes within the language. The provided solutions should include:

* An explanation of any placement restrictions for prototype declarations
* A prototype declaration for a function that does not require arguments
* A prototype declaration for a function that requires two arguments
* A prototype declaration for a function that utilizes varargs
* A prototype declaration for a function that utilizes optional arguments
* A prototype declaration for a function that utilizes named parameters
* Example of prototype declarations for subroutines or procedures (if these differ from functions)
* An explanation and example of any special forms of prototyping not covered by the above

Languages that do not provide function prototyping facilities should be omitted from this task.

Solution:
function Func() -- Does not require arguments
	return 1
end

function Func(a,b) -- Requires arguments
	return a + b
end

function Func(a,b) -- Arguments are optional
	return a or 4 + b or 2
end

function Func(a,...) -- One argument followed by varargs
	return a,{...} -- Returns both arguments, varargs as table
end


Functional coverage tree

Functional coverage is a measure of how much a particular function of a system
has been verified as correct. It is used heavily in tracking the completeness
of the verification of complex System on Chip (SoC) integrated circuits, where
it can also be used to track how well the functional ''requirements'' of the
system have been verified.

This task uses a sub-set of the calculations sometimes used in tracking
functional coverage but uses a more familiar(?) scenario.

;Task Description:
The head of the clean-up crews for "The Men in a very dark shade of grey when
viewed at night" has been tasked with managing the cleansing of two properties
after an incident involving aliens.

She arranges the task hierarchically with a manager for the crews working on
each house who return with a breakdown of how they will report on progress in
each house.

The overall hierarchy of (sub)tasks is as follows,
cleaning
    house1
        bedrooms
        bathrooms
            bathroom1
            bathroom2
            outside lavatory
        attic
        kitchen
        living rooms
            lounge
            dining room
            conservatory
            playroom
        basement
        garage
        garden
    house2
        upstairs
            bedrooms
                suite 1
                suite 2
                bedroom 3
                bedroom 4
            bathroom
            toilet
            attics
        groundfloor
            kitchen
            living rooms
                lounge
                dining room
                conservatory
                playroom
            wet room & toilet
            garage
            garden
            hot tub suite
        basement
            cellars
            wine cellar
            cinema

The head of cleanup knows that her managers will report fractional completion of leaf tasks (tasks with no child tasks of their own), and she knows that she will want to modify the weight of values of completion as she sees fit.

Some time into the cleaning, and some coverage reports have come in and she thinks see needs to weight the big house2 60-40 with respect to coverage from house1 She prefers a tabular view of her data where missing weights are assumed to be 1.0 and missing coverage 0.0.
NAME_HIERARCHY                  |WEIGHT  |COVERAGE  |
cleaning                        |        |          |
    house1                      |40      |          |
        bedrooms                |        |0.25      |
        bathrooms               |        |          |
            bathroom1           |        |0.5       |
            bathroom2           |        |          |
            outside_lavatory    |        |1         |
        attic                   |        |0.75      |
        kitchen                 |        |0.1       |
        living_rooms            |        |          |
            lounge              |        |          |
            dining_room         |        |          |
            conservatory        |        |          |
            playroom            |        |1         |
        basement                |        |          |
        garage                  |        |          |
        garden                  |        |0.8       |
    house2                      |60      |          |
        upstairs                |        |          |
            bedrooms            |        |          |
                suite_1         |        |          |
                suite_2         |        |          |
                bedroom_3       |        |          |
                bedroom_4       |        |          |
            bathroom            |        |          |
            toilet              |        |          |
            attics              |        |0.6       |
        groundfloor             |        |          |
            kitchen             |        |          |
            living_rooms        |        |          |
                lounge          |        |          |
                dining_room     |        |          |
                conservatory    |        |          |
                playroom        |        |          |
            wet_room_&_toilet   |        |          |
            garage              |        |          |
            garden              |        |0.9       |
            hot_tub_suite       |        |1         |
        basement                |        |          |
            cellars             |        |1         |
            wine_cellar         |        |1         |
            cinema              |        |0.75      |

;Calculation:
The coverage of a node in the tree is calculated as the weighted average of the coverage of its children evaluated bottom-upwards in the tree.

'''The task is to''' calculate the overall coverage of the cleaning task and display the coverage at all levels of the hierarchy on this page, in a manner that visually shows the hierarchy, weights and coverage of all nodes.

;Extra Credit:
After calculating the coverage for all nodes, one can also calculate the additional/delta top level coverage that would occur if any (sub)task were to be fully covered from its current fractional coverage. This is done by multiplying the extra coverage that could be gained 1-coverage for any node, by the product of the `powers` of its parent nodes from the top down to the node.
The power of a direct child of any parent is given by the power of the parent multiplied by the weight of the child divided by the sum of the weights of all the direct children.

The pseudo code would be:

    method delta_calculation(this, power):
        sum_of_weights = sum(node.weight for node in children)
        this.delta  = (1 - this.coverage) * power
        for node in self.children:
            node.delta_calculation(power * node.weight / sum_of_weights)
        return this.delta

Followed by a call to:

    top.delta_calculation(power=1)

'''Note:''' to aid in getting the data into your program you might want to use an alternative, more functional description of the starting data given on the discussion page.

Solution:
-- DATA:
local function node(name, weight, coverage, children)
  return { name=name, weight=weight or 1.0, coverage=coverage or 0.0, sumofweights=0, delta=0, children=children }
end

local root =
node("cleaning", nil, nil, {
  node("house1", 40, nil, {
    node("bedrooms", nil, 0.25),
    node("bathrooms", nil, nil, {
      node("bathroom1", nil, 0.5),
      node("bathroom2"),
      node("outside_lavatory", nil, 1)
    }),
    node("attic", nil, 0.75),
    node("kitchen", nil, 0.1),
    node("living_rooms", nil, nil, {
      node("lounge"),
      node("dining_room"),
      node("conservatory"),
      node("playroom",nil,1)
    }),
    node("basement"),
    node("garage"),
    node("garden", nil, 0.8)
  }),
  node("house2", 60, nil, {
    node("upstairs", nil, nil, {
      node("bedrooms", nil, nil, {
        node("suite_1"),
        node("suite_2"),
        node("bedroom_3"),
        node("bedroom_4")
      }),
      node("bathroom"),
      node("toilet"),
      node("attics", nil, 0.6)
    }),
    node("groundfloor", nil, nil, {
      node("kitchen"),
      node("living_rooms", nil, nil, {
        node("lounge"),
        node("dining_room"),
        node("conservatory"),
        node("playroom")
      }),
      node("wet_room_&_toilet"),
      node("garage"),
      node("garden", nil, 0.9),
      node("hot_tub_suite", nil, 1)
    }),
    node("basement", nil, nil, {
      node("cellars", nil, 1),
      node("wine_cellar", nil, 1),
      node("cinema", nil, 0.75)
    })
  })
})

-- TASK:
local function calccover(node)
  if (node.children) then
    local cnt, sum = 0, 0
    for _,child in ipairs(node.children) do
      local ccnt, csum = calccover(child)
      cnt, sum = cnt+ccnt, sum+csum
    end
    node.coverage = sum/cnt
    node.sumofweights = cnt -- just as prep for extra credit
  end
  return node.weight, node.coverage * node.weight
end
calccover(root)

-- EXTRA CREDIT:
local function calcdelta(node, power)
  node.delta = (1.0 - node.coverage) * power
  if (node.children) then
    for _,child in ipairs(node.children) do
      calcdelta(child, power * child.weight / node.sumofweights)
    end
  end
end
calcdelta(root,1)

-- OUTPUT:
local function printnode(node, space)
  print(string.format("%-32s|  %3.f   | %8.6f | %8.6f |", string.rep(" ",space)..node.name, node.weight, node.coverage, node.delta))
  if node.children then
    for _,child in ipairs(node.children) do printnode(child,space+4) end
  end
end
print("NAME_HIERARCHY                  |WEIGHT  |COVERAGE  |DELTA     |")
printnode(root,0)


Fusc sequence

Definitions:
The   '''fusc'''   integer sequence is defined as:
::*   fusc(0) = 0
::*   fusc(1) = 1
::*   for '''n'''>1,   the   '''n'''th   term is defined as:
::::*   if   '''n'''   is       even;     fusc(n) = fusc(n/2)
::::*   if   '''n'''   is   odd;     fusc(n) = fusc((n-1)/2)   +   fusc((n+1)/2)

Note that MathWorld's definition starts with unity, not zero.   This task will be using the OEIS' version   (above).

;An observation:
:::::*   fusc(A) = fusc(B)

where   '''A'''   is some non-negative integer expressed in binary,   and
where   '''B'''   is the binary value of   '''A'''   reversed.

Fusc numbers are also known as:
::*   fusc function   (named by Dijkstra, 1982)
::*   Stern's Diatomic series   (although it starts with unity, not zero)
::*   Stern-Brocot sequence   (although it starts with unity, not zero)

;Task:
::*   show the first   '''61'''   fusc numbers (starting at zero) in a horizontal format.
::*   show the fusc number (and its index) whose length is greater than any previous fusc number length.
::::*   (the length is the number of decimal digits when the fusc number is expressed in base ten.)
::*   show all numbers with commas   (if appropriate).
::*   show all output here.

;Related task:
::*   RosettaCode Stern-Brocot sequence

;Also see:
::*   the MathWorld entry:   Stern's Diatomic Series.
::*   the OEIS      entry:   A2487.

Solution:
function fusc(n)
    n = math.floor(n)
    if n == 0 or n == 1 then
        return n
    elseif n % 2 == 0 then
        return fusc(n / 2)
    else
        return fusc((n - 1) / 2) + fusc((n + 1) / 2)
    end
end

function numLen(n)
    local sum = 1
    while n > 9 do
        n = math.floor(n / 10)
        sum = sum + 1
    end
    return sum
end

function printLargeFuscs(limit)
    print("Printing all largest Fusc numbers up to " .. limit)
    print("Index-------Value")
    local maxLen = 1
    for i=0,limit do
        local f = fusc(i)
        local le = numLen(f)
        if le > maxLen then
            maxLen = le
        print(string.format("%5d%12d", i, f))
        end
    end
end

function main()
    print("Index-------Value")
    for i=0,60 do
        print(string.format("%5d%12d", i, fusc(i)))
    end
    printLargeFuscs(math.pow(2, 31) - 1)
end

main()


Gapful numbers

Numbers   (positive integers expressed in base ten)   that are (evenly) divisible by the number formed by the
first and last digit are known as   '''gapful numbers'''.

''Evenly divisible''   means divisible with   no   remainder.

All   one-   and two-digit   numbers have this property and are trivially excluded.   Only
numbers    >=  '''100'''   will be considered for this Rosetta Code task.

;Example:
'''187'''   is a   '''gapful'''   number because it is evenly divisible by the
number   '''17'''   which is formed by the first and last decimal digits
of    '''187'''.

About   7.46%   of positive integers are   ''gapful''.

;Task:
:*   Generate and show all sets of numbers (below) on one line (horizontally) with a title,   here on this page
:*   Show the first   '''30'''   gapful numbers
:*   Show the first   '''15'''   gapful numbers    >=           '''1,000,000'''
:*   Show the first   '''10'''   gapful numbers    >=                               '''1,000,000,000'''

;Related tasks:
:*   Harshad or Niven series.
:*   palindromic gapful numbers.
:*   largest number divisible by its digits.

;Also see:
:*   The OEIS entry:   A108343 gapful numbers.
:*   numbersaplenty gapful numbers

Solution:
function generateGaps(start, count)
    local counter = 0
    local i = start

    print(string.format("First %d Gapful numbers >= %d :", count, start))

    while counter < count do
        local str = tostring(i)
        local denom = 10 * tonumber(str:sub(1, 1)) + (i % 10)
        if i % denom == 0 then
            print(string.format("%3d : %d", counter + 1, i))
            counter = counter + 1
        end
        i = i + 1
    end
end

generateGaps(100, 30)
print()

generateGaps(1000000, 15)
print()

generateGaps(1000000000, 15)
print()


Generate Chess960 starting position

Bobby Fischer.  Unlike other variants of the game, Chess960 does not require a different material, but instead relies on a random initial position, with a few constraints:

* as in the standard chess game, all eight white pawns must be placed on the second rank.
* White pieces must stand on the first rank as in the standard game, in random column order but with the two following constraints:
** the bishops must be placed on opposite color squares (i.e. they must be an odd number of spaces apart or there must be an even number of spaces between them)
** the King must be between two rooks (with any number of other pieces between them all)
* Black pawns and pieces must be placed respectively on the seventh and eighth ranks, mirroring the white pawns and pieces, just as in the standard game.  (That is, their positions are not independently randomized.)

With those constraints there are '''960''' possible starting positions, thus the name of the variant.

;Task:
The purpose of this task is to write a program that can randomly generate any one of the 960 Chess960 initial positions. You will show the result as the first rank displayed with Chess symbols in Unicode:  or with the letters '''K'''ing '''Q'''ueen '''R'''ook '''B'''ishop k'''N'''ight.

Solution:
-- Insert 'str' into 't' at a random position from 'left' to 'right'
function randomInsert (t, str, left, right)
    local pos
    repeat pos = math.random(left, right) until not t[pos]
    t[pos] = str
    return pos
end

-- Generate a random Chess960 start position for white major pieces
function chess960 ()
    local t, b1, b2 = {}
    local kingPos = randomInsert(t, "K", 2, 7)
    randomInsert(t, "R", 1, kingPos - 1)
    randomInsert(t, "R", kingPos + 1, 8)
    b1 = randomInsert(t, "B", 1, 8)
    b2 = randomInsert(t, "B", 1, 8)
    while (b2 - b1) % 2 == 0 do
        t[b2] = false
        b2 = randomInsert(t, "B", 1, 8)
    end
    randomInsert(t, "Q", 1, 8)
    randomInsert(t, "N", 1, 8)
    randomInsert(t, "N", 1, 8)
    return t
end

-- Main procedure
math.randomseed(os.time())
print(table.concat(chess960()))


Generator/Exponential

A generator is an executable entity (like a function or procedure) that contains code that yields a sequence of values, one at a time, so that each time you call the generator, the next value in the sequence is provided.

Generators are often built on top of coroutines or objects so that the internal state of the object is handled "naturally".

Generators are often used in situations where a sequence is potentially infinite, and where it is possible to construct the next value of the sequence with only minimal state.

;Task:
* Create a function that returns a generation of the m'th powers of the positive integers starting from zero, in order, and without obvious or simple upper limit. (Any upper limit to the generator should not be stated in the source but should be down to factors such as the languages natural integer size limit or computational time/size).
* Use it to create a generator of:
:::*   Squares.
:::*   Cubes.
* Create a new generator that filters all cubes from the generator of squares.
* Drop the first 20 values from this last generator of filtered results, and then show the next 10 values.

Note that this task ''requires'' the use of generators in the calculation of the result.

;Also see:
* Generator

Solution:
--could be done with a coroutine, but a simple closure works just as well.
local function powgen(m)
  local count = 0
  return function()
    count = count + 1
    return count^m
  end
end

local squares = powgen(2)
local cubes = powgen(3)

local cowrap,coyield = coroutine.wrap, coroutine.yield

local function filter(f,g)
  return cowrap(function()
    local ff,gg = f(), g()
    while true do
      if ff == gg then
        ff,gg = f(), g()
      elseif ff < gg then
        coyield(ff)
        ff = f()
      else
        gg = g()
      end
    end
  end)
end

filter = filter(squares,cubes)

for i = 1,30 do
  local result = filter()
  if i > 20 then
    print(result)
  end
end


Get system command output

Task
Execute a system command and get its output into the program. The output may be stored in any kind of collection (array, list, etc.).

;Related task
*  Execute a system command

Solution:
local output = io.popen("echo Hurrah!")
print(output:read("*all"))


Globally replace text in several files

Replace every occurring instance of a piece of text in a group of text files with another one.

For this task we want to replace the text   "'''Goodbye London!'''"   with   "'''Hello New York!'''"   for a list of files.

Solution:
filenames = { "f1.txt", "f2.txt" }

for _, fn in pairs( filenames ) do
    fp = io.open( fn, "r" )
    str = fp:read( "*all" )
    str = string.gsub( str, "Goodbye London!", "Hello New York!" )
    fp:close()

    fp = io.open( fn, "w+" )
    fp:write( str )
    fp:close()
end


Gray code

Karnaugh maps in order from left to right or top to bottom.
Create functions to encode a number to and decode a number from Gray code.

Display the normal binary representations, Gray code representations, and decoded Gray code values for all 5-bit binary numbers (0-31 inclusive, leading 0's not necessary).

There are many possible Gray codes. The following encodes what is called "binary reflected Gray code."

Encoding (MSB is bit 0, b is binary, g is Gray code):

if b[i-1] = 1
   g[i] = not b[i]
else
   g[i] = b[i]

Or:

g = b xor (b logically right shifted 1 time)

Decoding (MSB is bit 0, b is binary, g is Gray code):

b[0] = g[0]

for other bits:
b[i] = g[i] xor b[i-1]

;Reference
* Converting Between Gray and Binary Codes. It includes step-by-step animations.

Solution:
local bit = require 'bit'
local gray = require 'gray'

-- simple binary string formatter
local function to_bit_string(n, width)
  width = width or 1
  local output = ""
  while n > 0 do
    output = bit.band(n,1) .. output
    n = bit.rshift(n,1)
  end
  while #output < width do
    output = '0' .. output
  end
  return output
end

for i = 0,31 do
  g = gray.encode(i);
  gd = gray.decode(g);
  print(string.format("%2d : %s => %s => %s : %2d", i,
    to_bit_string(i,5), to_bit_string(g, 5),
    to_bit_string(gd,5), gd))
end


Greatest subsequential sum

Given a sequence of integers, find a continuous subsequence which maximizes the sum of its elements, that is, the elements of no other single subsequence add up to a value larger than this one.

An empty subsequence is considered to have the sum of   '''0''';   thus if all elements are negative, the result must be the empty sequence.

Solution:
function sumt(t, start, last) return start <= last and t[start] + sumt(t, start+1, last) or 0 end
function maxsub(ary, idx)
  local idx = idx or 1
  if not ary[idx] then return {} end
  local maxsum, last = 0, idx
  for i = idx, #ary do
    if sumt(ary, idx, i) > maxsum then maxsum, last = sumt(ary, idx, i), i end
  end
  local v = maxsub(ary, idx + 1)
  if maxsum < sumt(v, 1, #v) then return v end
  local ret = {}
  for i = idx, last do ret[#ret+1] = ary[i] end
  return ret
end


Hailstone sequence

The Hailstone sequence of numbers can be generated from a starting positive integer,   n   by:
*   If   n   is     '''1'''     then the sequence ends.
*   If   n   is   '''even''' then the next   n   of the sequence    = n/2
*   If   n   is   '''odd'''    then the next   n   of the sequence    = (3 * n) + 1

The (unproven) Collatz conjecture is that the hailstone sequence for any starting number always terminates.

This sequence was named by Lothar Collatz in 1937   (or possibly in 1939),   and is also known as (the):
:::*   hailstone sequence,   hailstone numbers
:::*   3x + 2 mapping,   3n + 1 problem
:::*   Collatz sequence
:::*   Hasse's algorithm
:::*   Kakutani's problem
:::*   Syracuse algorithm,   Syracuse problem
:::*   Thwaites conjecture
:::*   Ulam's problem

The hailstone sequence is also known as   ''hailstone numbers''   (because the values are usually subject to multiple descents and ascents like hailstones in a cloud).

;Task:
# Create a routine to generate the hailstone sequence for a number.
# Use the routine to show that the hailstone sequence for the number 27 has 112 elements starting with 27, 82, 41, 124 and ending with 8, 4, 2, 1
# Show the number less than 100,000 which has the longest hailstone sequence together with that sequence's length.    (But don't show the actual sequence!)

;See also:
*   xkcd (humourous).
*   The Notorious Collatz conjecture Terence Tao, UCLA (Presentation, pdf).
*   The Simplest Math Problem No One Can Solve Veritasium (video, sponsored).

Solution:
function hailstone( n, print_numbers )
    local n_iter = 1

    while n ~= 1 do
        if print_numbers then print( n ) end
        if n % 2 == 0 then
            n = n / 2
        else
            n = 3 * n + 1
        end

        n_iter = n_iter + 1
    end
    if print_numbers then print( n ) end

    return n_iter;
end

hailstone( 27, true )

max_i, max_iter = 0, 0
for i = 1, 100000 do
    num = hailstone( i, false )
    if num >= max_iter then
        max_i = i
        max_iter = num
    end
end

print( string.format( "Needed %d iterations for the number %d.\n", max_iter, max_i ) )


Harmonic series

{{Wikipedia|Harmonic number}}

In mathematics, the '''n-th''' harmonic number is the sum of the reciprocals of the first '''n''' natural numbers:

'''H''n'' = 1 + 1/2 + 1/3 + ... + 1/n'''

The series of harmonic numbers thus obtained is often loosely referred to as the harmonic series.

Harmonic numbers are closely related to the Euler-Mascheroni constant.

The harmonic series is divergent, albeit quite slowly, and grows toward infinity.

;Task
* Write a function (routine, procedure, whatever it may be called in your language) to generate harmonic numbers.
* Use that procedure to show the values of the first 20 harmonic numbers.
* Find and show the position in the series of the first value greater than the integers 1 through 5

;Stretch
* Find and show the position in the series of the first value greater than the integers 6 through 10

;Related
* [[Egyptian fractions]]

Solution:
-- Task 1
function harmonic (n)
    if n < 1 or n ~= math.floor(n) then
        error("Argument to harmonic function is not a natural number")
    end
    local Hn = 1
    for i = 2, n do
        Hn = Hn + (1/i)
    end
    return Hn
end

-- Task 2
for x = 1, 20 do
    print(x .. " :\t" .. harmonic(x))
end

-- Task 3
local x, lastInt, Hx = 0, 1
repeat
    x = x + 1
    Hx = harmonic(x)
    if Hx > lastInt then
        io.write("The first harmonic number above " .. lastInt)
        print(" is " .. Hx .. " at position " .. x)
        lastInt = lastInt + 1
    end
until lastInt > 10  -- Stretch goal just meant changing that value from 5 to 10
                    -- Execution still only takes about 120 ms under LuaJIT


Harshad or Niven series

The Harshad or Niven numbers are positive integers >= 1 that are divisible by the sum of their digits.

For example,   '''42'''   is a Harshad number as   '''42'''   is divisible by   ('''4''' + '''2''')   without remainder.

Assume that the series is defined as the numbers in increasing order.

;Task:
The task is to create a function/method/procedure to generate successive members of the Harshad sequence.

Use it to:
::*   list the first '''20''' members of the sequence,   and
::*   list the first Harshad number greater than '''1000'''.

Show your output here.

;Related task
:*   Increasing gaps between consecutive Niven numbers

;See also
*    OEIS: A005349

Solution:
function isHarshad(n)
    local s=0
    local n_str=tostring(n)
    for i=1,#n_str do
        s=s+tonumber(n_str:sub(i,i))
    end
    return n%s==0
end

local count=0
local harshads={}
local n=1

while count<20 do
    if isHarshad(n) then
        count=count+1
        table.insert(harshads, n)
    end
    n=n+1
end

print(table.concat(harshads, " "))

local h=1001
while not isHarshad(h) do
    h=h+1
end
print(h)


Hash join

{| class="wikitable"
|-
! Input
! Output
|-
|

{| style="border:none; border-collapse:collapse;"
|-
| style="border:none" | ''A'' =
| style="border:none" |

{| class="wikitable"
|-
! Age !! Name
|-
| 27 || Jonah
|-
| 18 || Alan
|-
| 28 || Glory
|-
| 18 || Popeye
|-
| 28 || Alan
|}

| style="border:none; padding-left:1.5em;" rowspan="2" |
| style="border:none" | ''B'' =
| style="border:none" |

{| class="wikitable"
|-
! Character !! Nemesis
|-
| Jonah || Whales
|-
| Jonah || Spiders
|-
| Alan || Ghosts
|-
| Alan || Zombies
|-
| Glory || Buffy
|}

|-
| style="border:none" | ''jA'' =
| style="border:none" | Name (i.e. column 1)

| style="border:none" | ''jB'' =
| style="border:none" | Character (i.e. column 0)
|}

|

{| class="wikitable" style="margin-left:1em"
|-
! A.Age !! A.Name !! B.Character !! B.Nemesis
|-
| 27 || Jonah || Jonah || Whales
|-
| 27 || Jonah || Jonah || Spiders
|-
| 18 || Alan || Alan || Ghosts
|-
| 18 || Alan || Alan || Zombies
|-
| 28 || Glory || Glory || Buffy
|-
| 28 || Alan || Alan || Ghosts
|-
| 28 || Alan || Alan || Zombies
|}

|}

The order of the rows in the output table is not significant.
If you're using numerically indexed arrays to represent table rows (rather than referring to columns by name), you could represent the output rows in the form [[27, "Jonah"], ["Jonah", "Whales"]].

Solution:
local function recA(age, name) return { Age=age, Name=name } end
local tabA = { recA(27,"Jonah"), recA(18,"Alan"), recA(28,"Glory"), recA(18,"Popeye"), recA(28,"Alan") }

local function recB(character, nemesis) return { Character=character, Nemesis=nemesis } end
local tabB = { recB("Jonah","Whales"), recB("Jonah","Spiders"), recB("Alan","Ghosts"), recB("Alan","Zombies"), recB("Glory","Buffy") }

local function hashjoin(taba, cola, tabb, colb)
  local hash, join = {}, {}
  for _,rowa in pairs(taba) do
    if (not hash[rowa[cola]]) then hash[rowa[cola]] = {} end
    table.insert(hash[rowa[cola]], rowa)
  end
  for _,rowb in pairs(tabb) do
    for _,rowa in pairs(hash[rowb[colb]]) do
      join[#join+1] = { A=rowa, B=rowb }
    end
  end
  return join
end

for _,row in pairs(hashjoin(tabA, "Name", tabB, "Character")) do
  print(row.A.Age, row.A.Name, row.B.Character, row.B.Nemesis)
end


Haversine formula

{{Wikipedia}}

The '''haversine formula''' is an equation important in navigation, giving great-circle distances between two points on a sphere from their longitudes and latitudes.

It is a special case of a more general formula  in spherical trigonometry, the '''law of haversines''', relating the sides and angles of spherical "triangles".

;Task:
Implement a great-circle distance function, or use a library function,
to show the great-circle distance between:
* Nashville International Airport (BNA)   in Nashville, TN, USA,   which is:
    '''N''' 36deg7.2',   '''W''' 86deg40.2'     (36.12,   -86.67)           -and-
* Los Angeles International Airport (LAX)  in Los Angeles, CA, USA,   which is:
    '''N''' 33deg56.4',  '''W''' 118deg24.0'    (33.94,  -118.40)

User Kaimbridge clarified on the Talk page:

 -- 6371.0 km is the authalic radius based on/extracted from surface area;
 -- 6372.8 km is an approximation of the radius of the average circumference
    (i.e., the average great-elliptic or great-circle radius), where the
     boundaries are the meridian (6367.45 km) and the equator (6378.14 km).

Using either of these values results, of course, in differing distances:

 6371.0 km -> 2886.44444283798329974715782394574671655 km;
 6372.8 km -> 2887.25995060711033944886005029688505340 km;
 (results extended for accuracy check:  Given that the radii are only
  approximations anyways, .01'  1.0621333 km and .001"  .00177 km,
  practical precision required is certainly no greater than about
  .0000001----i.e., .1 mm!)

As distances are segments of great circles/circumferences, it is
recommended that the latter value (r = 6372.8 km) be used (which
most of the given solutions have already adopted, anyways).

Most of the examples below adopted Kaimbridge's recommended value of
6372.8 km for the earth radius.  However, the derivation of this
ellipsoidal quadratic mean radius
is wrong (the averaging over azimuth is biased).  When applying these
examples in real applications, it is better to use the
mean earth radius,
6371 km.  This value is recommended by the International Union of
Geodesy and Geophysics and it minimizes the RMS relative error between the
great circle and geodesic distance.

Solution:
local function haversine(x1, y1, x2, y2)
r=0.017453292519943295769236907684886127;
x1= x1*r; x2= x2*r; y1= y1*r; y2= y2*r; dy = y2-y1; dx = x2-x1;
a = math.pow(math.sin(dx/2),2) + math.cos(x1) * math.cos(x2) * math.pow(math.sin(dy/2),2); c = 2 * math.asin(math.sqrt(a)); d = 6372.8 * c;
return d;
end


Here document

A   ''here document''    (or "heredoc")   is a way of specifying a text block, preserving the line breaks, indentation and other whitespace within the text.

Depending on the language being used, a   ''here document''   is constructed using a command followed by "<<" (or some other symbol) followed by a token string.

The text block will then start on the next line, and will be followed by the chosen token at the beginning of the following line, which is used to mark the end of the text block.

;Task:
Demonstrate the use of   ''here documents''   within the language.

;Related task:
*   [[Documentation]]

Solution:
print([[
This is a long paragraph of text
it is the simplest while using it
with lua, however it will have the
same line breaks and spacing as
     you set in this block.
]])

print([=[by using equals signs, ]] may be embedded.]=])

local msg = [[this is a message that spans
multiple lines and will have the next lines
preserved as they were entered, so be careful
when using this]]

print(msg)


Heronian triangles

Hero's formula for the area of a triangle given the length of its three sides    ''a'',   ''b'',   and   ''c''   is given by:

:::: A = \sqrt{s(s-a)(s-b)(s-c)},

where   ''s''   is half the perimeter of the triangle; that is,

:::: s=\frac{a+b+c}{2}.

'''Heronian triangles'''
are triangles whose sides ''and area'' are all integers.
: An example is the triangle with sides   '''3, 4, 5'''   whose area is   '''6'''   (and whose perimeter is   '''12''').

Note that any triangle whose sides are all an integer multiple of   '''3, 4, 5''';   such as   '''6, 8, 10,'''   will also be a Heronian triangle.

Define a '''Primitive Heronian triangle''' as a Heronian triangle where the greatest common divisor
of all three sides is   '''1'''   (unity).

This will exclude, for example, triangle   '''6, 8, 10.'''

;Task:
# Create a named function/method/procedure/... that implements Hero's formula.
# Use the function to generate all the ''primitive'' Heronian triangles with sides <= 200.
# Show the count of how many triangles are found.
# Order the triangles by first increasing area, then by increasing perimeter, then by increasing maximum side lengths
# Show the first ten ordered triangles in a table of sides, perimeter, and area.
# Show a similar ordered table for those triangles with area = 210

Show all output here.

'''Note''': when generating triangles it may help to restrict a <= b <= c

Solution:
-- Returns the details of the Heronian Triangle with sides a, b, c or nil if it isn't one
local function tryHt( a, b, c )
    local result
    local s = ( a + b + c ) / 2;
    local areaSquared = s * ( s - a ) * ( s - b ) * ( s - c );
    if areaSquared > 0 then
        -- a, b, c does form a triangle
        local area = math.sqrt( areaSquared );
        if math.floor( area ) == area then
            -- the area is integral so the triangle is Heronian
            result = { a = a, b = b, c = c, perimeter = a + b + c, area = area }
        end
    end
    return result
end

-- Returns the GCD of a and b
local function gcd( a, b ) return ( b == 0 and a ) or gcd( b, a % b ) end

-- Prints the details of the Heronian triangle t
local function htPrint( t ) print( string.format( "%4d %4d %4d %4d      %4d", t.a, t.b, t.c, t.area, t.perimeter ) ) end
-- Prints headings for the Heronian Triangle table
local function htTitle() print( "   a    b    c area perimeter" ); print( "---- ---- ---- ---- ---------" ) end

-- Construct ht as a table of the Heronian Triangles with sides up to 200
local ht = {};
for c = 1, 200 do
    for b = 1, c do
        for a = 1, b do
            local t = gcd( gcd( a, b ), c ) == 1 and tryHt( a, b, c );
            if t then
                ht[ #ht + 1 ] = t
            end
        end
    end
end

-- sort the table on ascending area, perimiter and max side length
-- note we constructed the triangles with c as the longest side
table.sort( ht, function( a, b )
                return a.area < b.area or (   a.area == b.area
                                          and (  a.perimeter <  b.perimeter
                                              or (   a.perimiter == b.perimiter
                                                 and a.c         <  b.c
                                                 )
                                              )
                                          )
                end
           );

-- Display the triangles
print( "There are " .. #ht .. " Heronian triangles with sides up to 200" );
htTitle();
for htPos = 1, 10 do htPrint( ht[ htPos ] ) end
print( " ..." );
print( "Heronian triangles with area 210:" );
htTitle();
for htPos = 1, #ht do
    local t = ht[ htPos ];
    if t.area == 210 then htPrint( t ) end
end


History variables

''Storing the history of objects in a program is a common task.
Maintaining the history of an object in a program has traditionally required programmers either to write specific code for handling the historical data, or to use a library which supports history logging.''

''History variables are variables in a programming language which store not only their current value, but also the values they have contained in the past. Some existing languages do provide support for history variables. However these languages typically have many limits and restrictions on use of history variables.
''

"History Variables:
The Semantics, Formal Correctness, and Implementation of History Variables
in an Imperative Programming Language" by Mallon and Takaoka

Concept also discussed on LtU and Patents.com.

;Task:
Demonstrate History variable support:
* enable history variable support (if needed)
* define a history variable
* assign three values
* non-destructively display the history
* recall the three values.

For extra points, if the language of choice does not support history variables,
demonstrate how this might be implemented.

Solution:
-- History variables in Lua 6/12/2020 db
local HistoryVariable = {
  new = function(self)
    return setmetatable({history={}},self)
  end,
  get = function(self)
    return self.history[#self.history]
  end,
  set = function(self, value)
    self.history[#self.history+1] = value
  end,
  undo = function(self)
    self.history[#self.history] = nil
  end,
}
HistoryVariable.__index = HistoryVariable

local hv = HistoryVariable:new()
print("defined:", hv)
print("value is:", hv:get())
--
hv:set(1); print("set() to:", hv:get())
hv:set(2); print("set() to:", hv:get())
hv:set(3); print("set() to:", hv:get())
--
print("history:", table.concat(hv.history,","))
--
hv:undo(); print("undo() to:", hv:get())
hv:undo(); print("undo() to:", hv:get())
hv:undo(); print("undo() to:", hv:get())


Hofstadter-Conway $10,000 sequence

The definition of the sequence is colloquially described as:
*   Starting with the list [1,1],
*   Take the last number in the list so far: 1, I'll call it x.
*   Count forward x places from the beginning of the list to find the first number to add (1)
*   Count backward x places from the end of the list to find the second number to add (1)
*   Add the two indexed numbers from the list and the result becomes the next number in the list (1+1)
*   This would then produce [1,1,2] where 2 is the third element of the sequence.

Note that indexing for the description above starts from alternately the left and right ends of the list and starts from an index of ''one''.

A less wordy description of the sequence is:
    a(1)=a(2)=1
    a(n)=a(a(n-1))+a(n-a(n-1))

The sequence begins:
    1, 1, 2, 2, 3, 4, 4, 4, 5, ...

Interesting features of the sequence are that:
*   a(n)/n   tends to   0.5   as   n   grows towards infinity.
*   a(n)/n   where   n   is a power of   2   is   0.5
*   For   n>4   the maximal value of   a(n)/n   between successive powers of 2 decreases.

a(n) / n   for   n   in   1..256

The sequence is so named because John Conway offered a prize of $10,000 to the first person who could
find the first position,   p   in the sequence where
    |a(n)/n| < 0.55  for all  n > p
It was later found that Hofstadter had also done prior work on the sequence.

The 'prize' was won quite quickly by Dr. Colin L. Mallows who proved the properties of the sequence and allowed him to find the value of   n   (which is much smaller than the 3,173,375,556 quoted in the NYT article).

;Task:
#   Create a routine to generate members of the Hofstadter-Conway $10,000 sequence.
#   Use it to show the maxima of   a(n)/n   between successive powers of two up to   2**20
#   As a stretch goal:   compute the value of   n   that would have won the prize and confirm it is true for   n   up to 2**20

;Also see:
*   Conways Challenge Sequence, Mallows' own account.
*   Mathworld Article.

Solution:
local fmt, write=string.format,io.write
local hof=coroutine.wrap(function()
	local yield=coroutine.yield
	local a={1,1}
	yield(a[1], 1)
	yield(a[2], 2)
	local n=a[#a]
	repeat
		n=a[n]+a[1+#a-n]
		a[#a+1]=n
		yield(n, #a)
	until false
end)

local mallows, mdiv=0,0
for p=1,20 do
	local max, div, num, last, fdiv=0,0,0,0,0
	for i=2^(p-1),2^p-1 do
		h,n=hof()
		div=h/n
		if div>max then
			max=div
			num=n
		end
		if div>0.55 then
			last=n
			fdiv=div
		end
	end
	write(fmt("From 2^%-2d to 2^%-2d the max is %.4f the %6dth Hofstadter number.\n",
		p-1, p, max, num))
	if max>.55 and p>4 then
		mallows, mdiv=last, fdiv
	end
end
write("So Mallows number is ", mallows, " with ", fmt("%.4f",mdiv), ", yay, just wire me my $10000 now!\n")


Horner's rule for polynomial evaluation

A fast scheme for evaluating a polynomial such as:
: -19+7x-4x^2+6x^3\,
when
: x=3\;.
is to arrange the computation as follows:
: ((((0) x + 6) x + (-4)) x + 7) x + (-19)\;
And compute the result from the innermost brackets outwards as in this pseudocode:
 coefficients ''':=''' [-19, 7, -4, 6] ''# list coefficients of all x^0..x^n in order''
 x ''':=''' 3
 accumulator ''':=''' 0
 '''for''' i '''in''' ''length''(coefficients) '''downto''' 1 '''do'''
     ''# Assumes 1-based indexing for arrays''
     accumulator ''':=''' ( accumulator * x ) + coefficients[i]
 '''done'''
 ''# accumulator now has the answer''

'''Task Description'''
:Create a routine that takes a list of coefficients of a polynomial in order of increasing powers of x; together with a value of x to compute its value at, and return the value of the polynomial at that value using Horner's rule.

Cf. [[Formal power series]]

Solution:
function horners_rule( coeff, x )
    local res = 0
    for i = #coeff, 1, -1 do
        res = res * x + coeff[i]
    end
    return res
end

x = 3
coefficients = { -19, 7, -4, 6 }
print( horners_rule( coefficients, x ) )


ISBN13 check digit

Validate the check digit of an ISBN-13 code:
::*   Multiply every other digit by  '''3'''.
::*   Add these numbers and the other digits.
::*   Take the remainder of this number after division by  '''10'''.
::*   If it is  '''0''',   the ISBN-13 check digit is correct.

You might use the following codes for testing:
::::*   978-0596528126              (good)
::::*   978-0596528120          (bad)
::::*   978-1788399081              (good)
::::*   978-1788399083          (bad)

Show output here, on this page

;See also:
:*   for details:   13-digit ISBN method of validation.       (installs cookies.)

Solution:
function checkIsbn13(isbn)
    local count = 0
    local sum = 0
    for c in isbn:gmatch"." do
        if c == ' ' or c == '-' then
            -- skip
        elseif c < '0' or '9' < c then
            return false
        else
            local digit = c - '0'
            if (count % 2) > 0 then
                sum = sum + 3 * digit
            else
                sum = sum + digit
            end
            count = count + 1
        end
    end

    if count ~= 13 then
        return false
    end
    return (sum % 10) == 0
end

function test(isbn)
    if checkIsbn13(isbn) then
        print(isbn .. ": good")
    else
        print(isbn .. ": bad")
    end
end

function main()
    test("978-1734314502")
    test("978-1734314509")
    test("978-1788399081")
    test("978-1788399083")
end

main()


I before E except after C

The phrase      "I before E, except after C"     is a
widely known mnemonic which is supposed to help when spelling English words.

;Task:
Using the word list from   http://wiki.puzzlers.org/pub/wordlists/unixdict.txt,
check if the two sub-clauses of the phrase are plausible individually:
:::#   ''"I before E when not preceded by C"''
:::#   ''"E before I when preceded by C"''

If both sub-phrases are plausible then the original phrase can be said to be plausible.

Something is plausible if the number of words having the feature is more than two times the number of words having the opposite feature (where feature is 'ie' or 'ei' preceded or not by 'c' as appropriate).

;Stretch goal:
As a stretch goal use the entries from the table of Word Frequencies in Written and Spoken English: based on the British National Corpus, (selecting those rows with three space or tab separated words only), to see if the phrase is plausible when word frequencies are taken into account.

''Show your output here as well as your program.''

;cf.:
* Schools to rethink 'i before e' - BBC news, 20 June 2009
* I Before E Except After C - QI Series 8 Ep 14, (humorous)
* Companion website for the book: "Word Frequencies in Written and Spoken English: based on the British National Corpus".

Solution:
-- Needed to get dictionary file from web server
local http = require("socket.http")

-- Return count of words that contain pattern
function count (pattern, wordList)
    local total = 0
    for word in wordList:gmatch("%S+") do
        if word:match(pattern) then total = total + 1 end
    end
    return total
end

-- Check plausibility of case given its opposite
function plaus (case, opposite, words)
    if count(case, words) > 2 * count(opposite, words) then
        print("PLAUSIBLE")
        return true
    else
        print("IMPLAUSIBLE")
        return false
    end
end

-- Main procedure
local page = http.request("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt")
io.write("I before E when not preceded by C: ")
local sub1 = plaus("[^c]ie", "cie", page)
io.write("E before I when preceded by C: ")
local sub2 = plaus("cei", "[^c]ei", page)
io.write("Overall the phrase is ")
if not (sub1 and sub2) then io.write("not ") end
print("plausible.")


Identity matrix

Build an   identity matrix   of a size known at run-time.

An ''identity matrix'' is a square matrix of size '''''n'' x ''n''''',
where the diagonal elements are all '''1'''s (ones),
and all the other elements are all '''0'''s (zeroes).

I_n = \begin{bmatrix}
  1      & 0      & 0      & \cdots & 0      \\
  0      & 1      & 0      & \cdots & 0      \\
  0      & 0      & 1      & \cdots & 0      \\
  \vdots & \vdots & \vdots & \ddots & \vdots \\
  0      & 0      & 0      & \cdots & 1      \\
\end{bmatrix}

;Related tasks:
*   [[Spiral matrix]]
*   [[Zig-zag matrix]]
*   [[Ulam_spiral_(for_primes)]]

Solution:
function identity_matrix (size)
        local m = {}
        for i = 1, size do
                m[i] = {}
                for j = 1, size do
                        m[i][j] = i == j and 1 or 0
                end
        end
        return m
end

function print_matrix (m)
        for i = 1, #m do
                print(table.concat(m[i], " "))
        end
end

print_matrix(identity_matrix(5))


Idiomatically determine all the characters that can be used for symbols

Idiomatically determine all the characters that can be used for ''symbols''.
The word ''symbols'' is meant things like names of variables, procedures (i.e., named fragments of programs, functions, subroutines, routines), statement labels, events or conditions, and in general, anything a computer programmer can choose to ''name'', but not being restricted to this list. ''Identifiers'' might be another name for ''symbols''.

The method should find the characters regardless of the hardware architecture that is being used  (ASCII, EBCDIC, or other).

;Task requirements

Display the set of all the characters that can be used for symbols which can be used (allowed) by the computer program.
You may want to mention what hardware architecture is being used, and if applicable, the operating system.

Note that most languages have additional restrictions on what characters can't be used for the first character of a variable or statement label, for instance.  These type of restrictions needn't be addressed here (but can be mentioned).

;See also
* Idiomatically determine all the lowercase and uppercase letters.

Solution:
function isValidIdentifier(id)
  local reserved = {
    ["and"]=true, ["break"]=true, ["do"]=true, ["end"]=true, ["else"]=true, ["elseif"]=true, ["end"]=true,
    ["false"]=true, ["for"]=true, ["function"]=true, ["goto"]=true, ["if"]=true, ["in"]=true,
    ["local"]=true, ["nil"]=true, ["not"]=true, ["or"]=true, ["repeat"]=true, ["return"]=true,
    ["then"]=true, ["true"]=true, ["until"]=true, ["while"]=true }
  return id:find("^[a-zA-Z_][a-zA-Z0-9_]*$") ~= nil and not reserved[id]
end
vfc, vsc = {}, {}
for i = 0, 255 do
  local c = string.char(i)
  if isValidIdentifier(c) then vfc[#vfc+1]=c end
  if isValidIdentifier("_"..c) then vsc[#vsc+1]=c end
end
print("Valid First Characters:  " .. table.concat(vfc))
print("Valid Subsequent Characters:  " .. table.concat(vsc))


Idiomatically determine all the lowercase and uppercase letters   (of the Latin [English] alphabet)   being used currently by a computer programming language.
The method should find the letters regardless of the hardware architecture that is being used (ASCII, EBCDIC, or other).

;Task requirements

Display the set of all:
::::::*   lowercase letters
::::::*   uppercase letters

that can be used (allowed) by the computer program,

where   ''letter''   is a member of the Latin (English) alphabet:     '''a''' --> '''z'''     and     '''A''' --> '''Z'''.

You may want to mention what hardware architecture is being used, and if applicable, the operating system.

;See also
* Idiomatically determine all the characters that can be used for symbols.

Solution:
function ASCIIstring (pattern)
    local matchString, ch = ""
    for charNum = 0, 255 do
        ch = string.char(charNum)
        if string.match(ch, pattern) then
            matchString = matchString .. ch
        end
    end
    return matchString
end

print(ASCIIstring("%l"))
print(ASCIIstring("%u"))


Integer overflow

Some languages support one or more integer types of the underlying processor.

This integer types have fixed size;   usually   '''8'''-bit,   '''16'''-bit,   '''32'''-bit,   or   '''64'''-bit.
The integers supported by such a type can be   ''signed''   or   ''unsigned''.

Arithmetic for machine level integers can often be done by single CPU instructions.
This allows high performance and is the main reason to support machine level integers.

;Definition:
An integer overflow happens when the result of a computation does not fit into the fixed size integer.
The result can be too small or too big to be representable in the fixed size integer.

;Task:
When a language has fixed size integer types, create a program that
does arithmetic computations for the fixed size integers of the language.

These computations must be done such that the result would overflow.

The program should demonstrate what the following expressions do.

For 32-bit signed integers:
::::: {|class="wikitable"
!Expression
!Result that does not fit into a 32-bit signed integer
|-
| -(-2147483647-1)
| 2147483648
|-
| 2000000000 + 2000000000
| 4000000000
|-
| -2147483647 - 2147483647
| -4294967294
|-
| 46341 * 46341
| 2147488281
|-
| (-2147483647-1) / -1
| 2147483648
|}

For 64-bit signed integers:
::: {|class="wikitable"
!Expression
!Result that does not fit into a 64-bit signed integer
|-
| -(-9223372036854775807-1)
| 9223372036854775808
|-
| 5000000000000000000+5000000000000000000
| 10000000000000000000
|-
| -9223372036854775807 - 9223372036854775807
| -18446744073709551614
|-
| 3037000500 * 3037000500
| 9223372037000250000
|-
| (-9223372036854775807-1) / -1
| 9223372036854775808
|}

For 32-bit unsigned integers:
::::: {|class="wikitable"
!Expression
!Result that does not fit into a 32-bit unsigned integer
|-
| -4294967295
| -4294967295
|-
| 3000000000 + 3000000000
| 6000000000
|-
| 2147483647 - 4294967295
| -2147483648
|-
| 65537 * 65537
| 4295098369
|}

For 64-bit unsigned integers:
::: {|class="wikitable"
!Expression
!Result that does not fit into a 64-bit unsigned integer
|-
| -18446744073709551615
| -18446744073709551615
|-
| 10000000000000000000 + 10000000000000000000
| 20000000000000000000
|-
| 9223372036854775807 - 18446744073709551615
| -9223372036854775808
|-
| 4294967296 * 4294967296
| 18446744073709551616
|}

;Notes:
:*   When the integer overflow does trigger an exception show how the exception is caught.
:*   When the integer overflow produces some value,   print it.
:*   It should be explicitly noted when an integer overflow is not recognized,   the program continues with wrong results.
:*   This should be done for signed and unsigned integers of various sizes supported by the computer programming language.
:*   When a language has no fixed size integer type,   or when no integer overflow can occur for other reasons,   this should be noted.
:*   It is okay to mention,   when a language supports unlimited precision integers,   but this task is NOT the place to demonstrate the   capabilities of unlimited precision integers.

Solution:
assert(math.type~=nil, "Lua 5.3+ required for this test.")
minint, maxint = math.mininteger, math.maxinteger
print("min, max int64  = " .. minint .. ", " .. maxint)
print("min-1 underflow =  " .. (minint-1) .. "  equals max? " .. tostring(minint-1==maxint))
print("max+1 overflow  = " .. (maxint+1) .. "  equals min? " .. tostring(maxint+1==minint))


Integer sequence

Create a program that, when run, would display all integers from   '''1'''   to    '''    '''    (or any relevant implementation limit),   in sequence   (i.e.   1, 2, 3, 4, etc)   if given enough time.

An example may not be able to reach arbitrarily-large numbers based on implementations limits.   For example, if integers are represented as a 32-bit unsigned value with 0 as the smallest representable value, the largest representable value would be 4,294,967,295.   Some languages support arbitrarily-large numbers as a built-in feature, while others make use of a module or library.

If appropriate, provide an example which reflect the language implementation's common built-in limits as well as an example which supports arbitrarily large numbers, and describe the nature of such limitations--or lack thereof.

Solution:
i = 1

-- in the event that the number inadvertently wraps around,
-- stop looping - this is unlikely with Lua's default underlying
-- number type (double), but on platform without double
-- the C type used for numbers can be changed
while i > 0 do
    print( i )
    i = i + 1
end


Inverted syntax

'''Inverted syntax with conditional expressions'''

In traditional syntax conditional expressions are usually shown before the action within a statement or code block:

 IF raining=true THEN needumbrella=true

In inverted syntax, the action is listed before the conditional expression in the statement or code block:

 needumbrella=true IF raining=true

'''Inverted syntax with assignment'''

In traditional syntax, assignments are usually expressed with the variable appearing before the expression:

 a = 6

In inverted syntax, the expression appears before the variable:
 6 = a

'''Task'''

The task is to demonstrate support for inverted syntax forms within the language by showing both the traditional and inverted forms.

Solution:
a = {1,3,5,4,2} -- a "plain" table
table.sort(a) -- library method passing a as param
print(table.concat(a)) -- and again --> "12345"

b = {1,3,5,4,2} -- a "plain" table, so far..
setmetatable(b, {__index=table}) -- ..but now "meta-decorated"
b:sort() -- syntax sugar passes b as "self"
print(b:concat()) -- and again --> "12345"