100 doors

There are 100 doors in a row that are all initially closed.

You make 100 passes by the doors.

The first time through, visit every door and  ''toggle''  the door  (if the door is closed,  open it;   if it is open,  close it).

The second time, only visit every 2nd door   (door #2, #4, #6, ...),   and toggle it.

The third time, visit every 3rd door   (door #3, #6, #9, ...), etc,   until you only visit the 100th door.

;Task:
Answer the question:   what state are the doors in after the last pass?   Which are open, which are closed?

'''Alternate:'''
As noted in this page's   discussion page,   the only doors that remain open are those whose numbers are perfect squares.

Opening only those doors is an   optimization   that may also be expressed;
however, as should be obvious, this defeats the intent of comparing implementations across programming languages.

Solution:
local is_open = {}

for pass = 1,100 do
    for door = pass,100,pass do
        is_open[door] = not is_open[door]
    end
end

for i,v in next,is_open do
    print ('Door '..i..':',v and 'open' or 'close')
end


100 prisoners

The Problem:
* 100 prisoners are individually numbered 1 to 100
* A room having a cupboard of 100 opaque drawers numbered 1 to 100, that cannot be seen from outside.
* Cards numbered 1 to 100 are placed randomly, one to a drawer, and the drawers all closed; at the start.
* Prisoners start outside the room
:* They can decide some strategy before any enter the room.
:* Prisoners enter the room one by one, can open a drawer, inspect the card number in the drawer, then close the drawer.
:* A prisoner can open no more than 50 drawers.
:* A prisoner tries to find his own number.
:* A prisoner finding his own number is then held apart from the others.
* If '''all''' 100 prisoners find their own numbers then they will all be pardoned. If ''any'' don't then ''all'' sentences stand.

;The task:
# Simulate several thousand instances of the game where the prisoners randomly open drawers
# Simulate several thousand instances of the game where the prisoners use the optimal strategy mentioned in the Wikipedia article, of:
:* First opening the drawer whose outside number is his prisoner number.
:* If the card within has his number then he succeeds otherwise he opens the drawer with the same number as that of the revealed card. (until he opens his maximum).

Show and compare the computed probabilities of success for the two strategies, here, on this page.

;References:
# The unbelievable solution to the 100 prisoner puzzle standupmaths (Video).
# [[wp:100 prisoners problem]]
# 100 Prisoners Escape Puzzle DataGenetics.
# Random permutation statistics#One hundred prisoners on Wikipedia.

Solution:
function shuffle(tbl)
  for i = #tbl, 2, -1 do
    local j = math.random(i)
    tbl[i], tbl[j] = tbl[j], tbl[i]
  end
  return tbl
end

function playOptimal()
    local secrets = {}
    for i=1,100 do
        secrets[i] = i
    end
    shuffle(secrets)

    for p=1,100 do
        local success = false

        local choice = p
        for i=1,50 do
            if secrets[choice] == p then
                success = true
                break
            end
            choice = secrets[choice]
        end

        if not success then
            return false
        end
    end

    return true
end

function playRandom()
    local secrets = {}
    for i=1,100 do
        secrets[i] = i
    end
    shuffle(secrets)

    for p=1,100 do
        local choices = {}
        for i=1,100 do
            choices[i] = i
        end
        shuffle(choices)

        local success = false
        for i=1,50 do
            if choices[i] == p then
                success = true
                break
            end
        end

        if not success then
            return false
        end
    end

    return true
end

function exec(n,play)
    local success = 0
    for i=1,n do
        if play() then
            success = success + 1
        end
    end
    return 100.0 * success / n
end

function main()
    local N = 1000000
    print("# of executions: "..N)
    print(string.format("Optimal play success rate: %f", exec(N, playOptimal)))
    print(string.format("Random play success rate: %f", exec(N, playRandom)))
end

main()


15 puzzle game

Implement the Fifteen Puzzle Game.

The   '''15-puzzle'''   is also known as:
:::*   '''Fifteen Puzzle'''
:::*   '''Gem Puzzle'''
:::*   '''Boss Puzzle'''
:::*   '''Game of Fifteen'''
:::*   '''Mystic Square'''
:::*   '''14-15 Puzzle'''
:::*   and some others.

;Related Tasks:
:*   15 Puzzle Solver
:*   [[16 Puzzle Game]]

Solution:
math.randomseed( os.time() )
local puz = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 }
local dir = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }
local sx, sy = 4, 4

function isValid( tx, ty )
    return tx > 0 and tx < 5 and ty > 0 and ty < 5
end
function display()
    io.write( "\n\n" )
    for j = 1, 4 do
        io.write( "+----+----+----+----+\n" )
        for i = 1, 4 do
            local d = puz[i + j * 4 - 4]
            io.write( ": " )
            if d < 10 then io.write( " " ) end
            if d < 1  then
                io.write( "  " )
            else
                io.write( string.format( "%d ", d ) )
            end
        end
        io.write( ":\n" )
    end
    io.write( "+----+----+----+----+\n\n" )
end
function getUserNove()
    local moves, r, tx, ty = {}
    for d = 1, 4 do
        tx = sx; ty = sy
        tx = tx + dir[d][1]; ty = ty + dir[d][2]

        if isValid( tx, ty ) then
            table.insert( moves, puz[tx + ty * 4 - 4] )
        end
    end

    io.write( "Your possible moves are: " )
    for i = 1, #moves do
        io.write( string.format( "%d ", moves[i] ) )
    end

    io.write ( "\nYour move: " ); r = tonumber( io.read() )
    if r ~= nil then
        for i = 1, #moves do
            if moves[i] == r then return r end
        end
    end
    print( "Invalid move!" )
    return -1
end
function checked( r )
    for i = 1, #puz do
        if puz[i] == r then
            puz[i] = 0
            sx = 1 + ( i - 1 ) % 4; sy = math.floor( ( i + 3 ) / 4 )
        elseif puz[i] == 0 then
            puz[i] = r
        end
    end
    for i = 2, #puz - 1 do
        if puz[i - 1] + 1 ~= puz[i] then return false end
    end
    return true
end
function beginGame()
    local r, d, tx, ty
    while( true ) do
        for i = 1, 100 do
            while( true ) do
                tx = sx; ty = sy; d = math.random( 4 )
                tx = tx + dir[d][1]; ty = ty + dir[d][2]
                if isValid( tx, ty ) then break end
            end
            puz[sx + sy * 4 - 4] = puz[tx + ty * 4 - 4]
            puz[tx + ty * 4 - 4] = 0; sx = tx; sy = ty
        end
        while( true ) do
            display(); r = getUserNove()
            if r > 0 then
                if checked( r ) then
                    display()
                    io.write( "\nDone!\n\nPlay again (Y/N)?" )
                    r = io.read()
                    if r ~= "Y" and r ~= "y" then
                        return
                    else
                        break
                    end
                end
            end
        end
    end
end
-- [ entry point ] --
beginGame()


21 game

'''21''' is a two player game, the game is played by choosing
a number ('''1''', '''2''', or '''3''')  to be added to the ''running total''.

The game is won by the player whose chosen number causes the ''running total''
to reach ''exactly'' '''21'''.

The ''running total'' starts at zero.
One player will be the computer.

Players alternate supplying a number to be added to the ''running total''.

;Task:
Write a computer program that will:
::* do the prompting (or provide a button menu),
::* check for errors and display appropriate error messages,
::* do the additions (add a chosen number to the ''running total''),
::* display the ''running total'',
::* provide a mechanism for the player to quit/exit/halt/stop/close the program,
::* issue a notification when there is a winner, and
::* determine who goes first (maybe a random or user choice, or can be specified when the game begins).

Solution:
gamewon = false
running_total = 0
player = 1
opponent = 2

while not gamewon do
  num = 0

  if player == 1 then
    opponent = 2
    repeat
      print("Enter a number between 1 and 3 (0 to quit):")
      num = io.read("*n")
      if num == 0 then
          os.exit()
      end
    until (num > 0) and (num <=3)
  end

  if player == 2 and not (gamewon) then
      opponent = 1
      if (21 - running_total <= 3) then
        num = 21 - running_total
      else
        num = math.random(1,3)
      end
      print("Player 2 picks number "..num)
  end

  running_total = running_total + num
  print("Total: "..running_total)

  if running_total == 21 then
    print("Player "..player.." wins!")
    gamewon = true
  end

  if running_total > 21 then
    print("Player "..player.." lost...")
    print("Player "..opponent.." wins!")
    gamewon = true
  end

  if player == 1 then
    player = 2
  else player = 1
  end

end


24 game

The 24 Game tests one's mental arithmetic.

;Task
Write a program that displays four digits, each from 1 --> 9 (inclusive) with repetitions allowed.

The program should prompt for the player to enter an arithmetic expression using ''just'' those, and ''all'' of those four digits, used exactly ''once'' each. The program should ''check'' then evaluate the expression.

The goal is for the player to enter an expression that (numerically) evaluates to '''24'''.
*  Only the following operators/functions are allowed: multiplication, division, addition, subtraction
*  Division should use floating point or rational arithmetic, etc, to preserve remainders.
*  Brackets are allowed, if using an infix expression evaluator.
*  Forming multiple digit numbers from the supplied digits is ''disallowed''. (So an answer of 12+12 when given 1, 2, 2, and 1 is wrong).
*  The order of the digits when given does not have to be preserved.

;Notes
* The type of expression evaluator used is not mandated. An RPN evaluator is equally acceptable for example.
* The task is not for the program to generate the expression, or test whether an expression is even possible.

;Related tasks
* [[24 game/Solve]]

;Reference
* The 24 Game on h2g2.

Solution:
local function help()
	print [[
 The 24 Game

 Given any four digits in the range 1 to 9, which may have repetitions,
 Using just the +, -, *, and / operators; and the possible use of
 brackets, (), show how to make an answer of 24.

 An answer of "q" will quit the game.
 An answer of "!" will generate a new set of four digits.

 Note: you cannot form multiple digit numbers from the supplied digits,
 so an answer of 12+12 when given 1, 2, 2, and 1 would not be allowed.

 ]]
end

local function generate(n)
	result = {}
	for i=1,n do
		result[i] = math.random(1,9)
	end
	return result
end

local function check(answer, digits)
	local adig = {}
	local ddig = {}
	local index
	local lastWasDigit = false
	for i=1,9 do adig[i] = 0 ddig[i] = 0 end
	allowed = {['(']=true,[')']=true,[' ']=true,['+']=true,['-']=true,['*']=true,['/']=true,['\t']=true,['1']=true,['2']=true,['3']=true,['4']=true,['5']=true,['6']=true,['7']=true,['8']=true,['9']=true}
	for i=1,string.len(answer) do
		if not allowed[string.sub(answer,i,i)] then
			return false
		end
		index = string.byte(answer,i)-48
		if index > 0 and index < 10 then
			if lastWasDigit then
				return false
			end
			lastWasDigit = true
			adig[index] = adig[index] + 1
		else
			lastWasDigit = false
		end
	end
	for i,digit in next,digits do
		ddig[digit] = ddig[digit]+1
	end
	for i=1,9 do
		if adig[i] ~= ddig[i] then
			return false
		end
	end
	return loadstring('return '..answer)()
end

local function game24()
	help()
	math.randomseed(os.time())
	math.random()
	local digits = generate(4)
	local trial = 0
	local answer = 0
	local ans = false
	io.write 'Your four digits:'
	for i,digit in next,digits do
		io.write (' ' .. digit)
	end
	print()
	while ans ~= 24 do
		trial = trial + 1
		io.write("Expression "..trial..": ")
		answer = io.read()
		if string.lower(answer) == 'q' then
			break
		end
		if answer == '!' then
			digits = generate(4)
			io.write ("New digits:")
			for i,digit in next,digits do
				io.write (' ' .. digit)
			end
			print()
		else
			ans = check(answer,digits)
			if ans == false then
				print ('The input '.. answer ..' was wonky!')
			else
				print (' = '.. ans)
				if ans == 24 then
					print ("Thats right!")
				end
			end
		end
	end
end
game24()


24 game/Solve

Write a program that takes four digits, either from user input or by random generation, and computes arithmetic expressions following the rules of the [[24 game]].

Show examples of solutions generated by the program.

;Related task:
*   [[Arithmetic Evaluator]]

Solution:
local SIZE = #arg[1]
local GOAL = tonumber(arg[2]) or 24

local input = {}
for v in arg[1]:gmatch("%d") do
	table.insert(input, v)
end
assert(#input == SIZE, 'Invalid input')

local operations = {'+', '-', '*', '/'}

local function BinaryTrees(vert)
	if vert == 0 then
		return {false}
	else
		local buf = {}
		for leften = 0, vert - 1 do
			local righten = vert - leften - 1
			for _, left in pairs(BinaryTrees(leften)) do
				for _, right in pairs(BinaryTrees(righten)) do
					table.insert(buf, {left, right})
				end
			end
		end
		return buf
	end
end
local trees = BinaryTrees(SIZE-1)
local c, opc, oper, str
local max = math.pow(#operations, SIZE-1)
local function op(a,b)
	opc = opc + 1
	local i = math.floor(oper/math.pow(#operations, opc-1))%#operations+1
	return '('.. a .. operations[i] .. b ..')'
end

local function EvalTree(tree)
	if tree == false then
		c = c + 1
		return input[c-1]
	else
		return op(EvalTree(tree[1]), EvalTree(tree[2]))
	end
end

local function printResult()
	for _, v in ipairs(trees) do
		for i = 0, max do
			c, opc, oper = 1, 0, i
			str = EvalTree(v)
			loadstring('res='..str)()
			if(res == GOAL) then print(str, '=', res) end
		end
	end
end

local uniq = {}
local function permgen (a, n)
	if n == 0 then
		local str = table.concat(a)
		if not uniq[str] then
			printResult()
			uniq[str] = true
		end
	else
		for i = 1, n do
			a[n], a[i] = a[i], a[n]
			permgen(a, n - 1)
			a[n], a[i] = a[i], a[n]
		end
	end
end

permgen(input, SIZE)


4-rings or 4-squares puzzle

Replace       '''a, b, c, d, e, f,'''   and
  '''g '''       with the decimal
digits   LOW   --->   HIGH
such that the sum of the letters inside of each of the four large squares add up to
the same sum.

            +--------------+      +--------------+
            |              |      |              |
            |      a       |      |      e       |
            |              |      |              |
            |          +---+------+---+      +---+---------+
            |          |   |      |   |      |   |         |
            |          | b |      | d |      | f |         |
            |          |   |      |   |      |   |         |
            |          |   |      |   |      |   |         |
            +----------+---+      +---+------+---+         |
                       |       c      |      |      g      |
                       |              |      |             |
                       |              |      |             |
                       +--------------+      +-------------+

Show all output here.

:*   Show all solutions for each letter being unique with
         LOW=1     HIGH=7
:*   Show all solutions for each letter being unique with
         LOW=3     HIGH=9
:*   Show only the   ''number''   of solutions when each letter can be non-unique
         LOW=0     HIGH=9

;Related task:
* [[Solve the no connection puzzle]]

Solution:
function valid(unique,needle,haystack)
    if unique then
        for _,value in pairs(haystack) do
            if needle == value then
                return false
            end
        end
    end
    return true
end

function fourSquare(low,high,unique,prnt)
    count = 0
    if prnt then
        print("a", "b", "c", "d", "e", "f", "g")
    end
    for a=low,high do
        for b=low,high do
            if valid(unique, a, {b}) then
                fp = a + b
                for c=low,high do
                    if valid(unique, c, {a, b}) then
                        for d=low,high do
                            if valid(unique, d, {a, b, c}) and fp == b + c + d then
                                for e=low,high do
                                    if valid(unique, e, {a, b, c, d}) then
                                        for f=low,high do
                                            if valid(unique, f, {a, b, c, d, e}) and fp == d + e + f then
                                                for g=low,high do
                                                    if valid(unique, g, {a, b, c, d, e, f}) and fp == f + g then
                                                        count = count + 1
                                                        if prnt then
                                                            print(a, b, c, d, e, f, g)
                                                        end
                                                    end
                                                end
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end
    if unique then
        print(string.format("There are %d unique solutions in [%d, %d]", count, low, high))
    else
        print(string.format("There are %d non-unique solutions in [%d, %d]", count, low, high))
    end
end

fourSquare(1,7,true,true)
fourSquare(3,9,true,true)
fourSquare(0,9,false,false)


99 bottles of beer

Display the complete lyrics for the song:     '''99 Bottles of Beer on the Wall'''.

;The beer song:
The lyrics follow this form:

:::              99 bottles of beer on the wall
:::              99 bottles of beer
:::              Take one down, pass it around
:::              98 bottles of beer on the wall

:::              98 bottles of beer on the wall
:::              98 bottles of beer
:::              Take one down, pass it around
:::              97 bottles of beer on the wall

... and so on, until reaching   '''0'''     (zero).

Grammatical support for   ''1 bottle of beer''   is optional.

As with any puzzle, try to do it in as creative/concise/comical a way
as possible (simple, obvious solutions allowed, too).

;See also:
*   http://99-bottles-of-beer.net/
*   [[:Category:99_Bottles_of_Beer]]
*   [[:Category:Programming language families]]
*   Wikipedia 99 bottles of beer

Solution:
local bottles = 99

local function plural (bottles) if bottles == 1 then return '' end return 's' end
while bottles > 0 do
    print (bottles..' bottle'..plural(bottles)..' of beer on the wall')
    print (bottles..' bottle'..plural(bottles)..' of beer')
    print ('Take one down, pass it around')
    bottles = bottles - 1
    print (bottles..' bottle'..plural(bottles)..' of beer on the wall')
    print ()
end


9 billion names of God the integer

This task is a variation of the short story by Arthur C. Clarke.

(Solvers should be aware of the consequences of completing this task.)

In detail, to specify what is meant by a   "name":
:The integer 1 has 1 name       "1".
:The integer 2 has 2 names   "1+1",   and   "2".
:The integer 3 has 3 names   "1+1+1",   "2+1",   and   "3".
:The integer 4 has 5 names   "1+1+1+1",   "2+1+1",   "2+2",   "3+1",   "4".
:The integer 5 has 7 names   "1+1+1+1+1",   "2+1+1+1",   "2+2+1",   "3+1+1",   "3+2",   "4+1",   "5".

;Task
Display the first 25 rows of a number triangle which begins:

                                      1
                                    1   1
                                  1   1   1
                                1   2   1   1
                              1   2   2   1   1
                            1   3   3   2   1   1

Where row   n   corresponds to integer   n,   and each column   C   in row   m   from left to right corresponds to the number of names beginning with   C.

A function   G(n)   should return the sum of the   n-th   row.

Demonstrate this function by displaying:   G(23),   G(123),   G(1234),   and   G(12345).

Optionally note that the sum of the   n-th   row   P(n)   is the      integer partition function.

Demonstrate this is equivalent to   G(n)   by displaying:   P(23),   P(123),   P(1234),   and   P(12345).

;Extra credit

If your environment is able, plot   P(n)   against   n   for   n=1\ldots 999.

;Related tasks
* [[Partition function P]]

Solution:
function nog(n)
  local tri = {{1}}
  for r = 2, n do
    tri[r] = {}
    for c = 1, r do
      tri[r][c] = (tri[r-1][c-1] or 0) + (tri[r-c] and tri[r-c][c] or 0)
    end
  end
  return tri
end

function G(n)
  local tri, sum = nog(n), 0
  for _, v in ipairs(tri[n]) do sum = sum + v end
  return sum
end

tri = nog(25)
for i, row in ipairs(tri) do
  print(i .. ":  " .. table.concat(row, " "))
end
print("G(23) = " .. G(23))
print("G(123) = " .. G(123))


ABC problem

You are given a collection of ABC blocks   (maybe like the ones you had when you were a kid).

There are twenty blocks with two letters on each block.

A complete alphabet is guaranteed amongst all sides of the blocks.

The sample collection of blocks:
  (B O)
  (X K)
  (D Q)
  (C P)
  (N A)
  (G T)
  (R E)
  (T G)
  (Q D)
  (F S)
  (J W)
  (H U)
  (V I)
  (A N)
  (O B)
  (E R)
  (F S)
  (L Y)
  (P C)
  (Z M)

;Task:
Write a function that takes a string (word) and determines whether the word can be spelled with the given collection of blocks.

The rules are simple:
::#   Once a letter on a block is used that block cannot be used again
::#   The function should be case-insensitive
::#   Show the output on this page for the following 7 words in the following example

;Example:
    >>> can_make_word("A")
    True
    >>> can_make_word("BARK")
    True
    >>> can_make_word("BOOK")
    False
    >>> can_make_word("TREAT")
    True
    >>> can_make_word("COMMON")
    False
    >>> can_make_word("SQUAD")
    True
    >>> can_make_word("CONFUSE")
    True

Solution:
blocks = {
	{"B","O"};	{"X","K"};	{"D","Q"};	{"C","P"};
	{"N","A"};	{"G","T"};	{"R","E"};	{"T","G"};
	{"Q","D"};	{"F","S"};	{"J","W"};	{"H","U"};
	{"V","I"};	{"A","N"};	{"O","B"};	{"E","R"};
	{"F","S"};	{"L","Y"};	{"P","C"};	{"Z","M"};
	};

function canUse(table, letter)
	for i,v in pairs(blocks) do
		if (v[1] == letter:upper() or v[2] == letter:upper())  and table[i] then
			table[i] = false;
			return true;
		end
	end
	return false;
end

function canMake(Word)
	local Taken = {};
	for i,v in pairs(blocks) do
		table.insert(Taken,true);
	end
	local found = true;
	for i = 1,#Word do
		if not canUse(Taken,Word:sub(i,i)) then
			found = false;
		end
	end
	print(found)
end


ASCII art diagram converter

Given the RFC 1035 message diagram from Section 4.1.1 (Header section format) as a string:
http://www.ietf.org/rfc/rfc1035.txt

 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                      ID                       |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                    QDCOUNT                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                    ANCOUNT                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                    NSCOUNT                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                    ARCOUNT                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Where (every column of the table is 1 bit):

 ID is 16 bits
 QR = Query (0) or Response (1)
 Opcode = Four bits defining kind of query:
   0:    a standard query (QUERY)
   1:    an inverse query (IQUERY)
   2:    a server status request (STATUS)
   3-15: reserved for future use
 AA = Authoritative Answer bit
 TC = Truncation bit
 RD = Recursion Desired bit
 RA = Recursion Available bit
 Z = Reserved
 RCODE = Response code
 QC = Question Count
 ANC = Answer Count
 AUC = Authority Count
 ADC = Additional Count

Write a function, member function, class or template that accepts a similar multi-line string as input to define a data structure or something else able to decode or store a header with that specified bit structure.

If your language has macros, introspection, code generation, or powerful enough templates, then accept such string at compile-time to define the header data structure statically.

Such "Header" function or template should accept a table with 8, 16, 32 or 64 columns, and any number of rows. For simplicity the only allowed symbols to define the table are + - | (plus, minus, pipe), and whitespace. Lines of the input string composed just of whitespace should be ignored. Leading and trailing whitespace in the input string should be ignored, as well as  before and after each table row. The box for each bit of the diagram takes four chars "+--+". The code should perform a little of validation of the input string, but for brevity a full validation is not required.

Bonus: perform a thoroughly validation of the input string.

Solution:
local function validate(diagram)
  local lines = {}
  for s in diagram:gmatch("[^\r\n]+") do
    s = s:match("^%s*(.-)%s*$")
    if s~="" then lines[#lines+1]=s end
  end
  -- "a little of validation".."for brevity"
  assert(#lines>0, "FAIL:  no non-empty lines")
  assert(#lines%2==1, "FAIL:  even number of lines")
  return lines
end

local function parse(lines)
  local schema, offset = {}, 0
  for i = 2,#lines,2 do
    for part in lines[i]:gmatch("\|([^\|]+)") do
      schema[#schema+1] = { name=part:match("^%s*(.-)%s*$"), numbits=(#part+1)/3, offset=offset }
      offset = offset + (#part+1)/3
    end
  end
  return schema
end

local diagram = [[

  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      ID                       |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    QDCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                    ANCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    NSCOUNT                    |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ARCOUNT                    |
  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

]] -- extra whitespace added for testing

local schema = parse(validate(diagram))
print("NAME       NUMBITS    OFFSET")
print("--------  --------  --------")
for i = 1,#schema do
  local item = schema[i]
  print(string.format("%-8s  %8d  %8d", item.name, item.numbits, item.offset))
end


AVL tree

{{wikipedia|AVL tree}}

In computer science, an '''AVL tree''' is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; at no time do they differ by more than one because rebalancing is done ensure this is the case. Lookup, insertion, and deletion all take O(log ''n'') time in both the average and worst cases, where n is the number of nodes in the tree prior to the operation. Insertions and deletions may require the tree to be rebalanced by one or more tree rotations. Note the tree of nodes comprise a set, so duplicate node keys are not allowed.

AVL trees are often compared with red-black trees because they support the same set of operations and because red-black trees also take O(log ''n'') time for the basic operations.  Because AVL trees are more rigidly balanced, they are faster than red-black trees for lookup-intensive applications. Similar to red-black trees, AVL trees are height-balanced, but in general not weight-balanced nor m-balanced; that is, sibling nodes can have hugely differing numbers of descendants.

;Task:
Implement an AVL tree in the language of choice, and provide at least basic operations.

;Related task
[[Red_black_tree_sort]]

Solution:
AVL={balance=0}
AVL.__mt={__index = AVL}

function AVL:new(list)
  local o={}
  setmetatable(o, AVL.__mt)
  for _,v in ipairs(list or {}) do
    o=o:insert(v)
  end
  return o
end

function AVL:rebalance()
  local rotated=false
  if self.balance>1 then
    if self.right.balance<0 then
      self.right, self.right.left.right, self.right.left = self.right.left, self.right, self.right.left.right
      self.right.right.balance=self.right.balance>-1 and 0 or 1
      self.right.balance=self.right.balance>0 and 2 or 1
    end
    self, self.right.left, self.right = self.right, self, self.right.left
    self.left.balance=1-self.balance
    self.balance=self.balance==0 and -1 or 0
    rotated=true
  elseif self.balance<-1 then
    if self.left.balance>0 then
      self.left, self.left.right.left, self.left.right = self.left.right, self.left, self.left.right.left
      self.left.left.balance=self.left.balance<1 and 0 or -1
      self.left.balance=self.left.balance<0 and -2 or -1
    end
    self, self.left.right, self.left = self.left, self, self.left.right
    self.right.balance=-1-self.balance
    self.balance=self.balance==0 and 1 or 0
    rotated=true
  end
  return self,rotated
end

function AVL:insert(v)
  if not self.value then
    self.value=v
    self.balance=0
    return self,1
  end
  local grow
  if v==self.value then
    return self,0
  elseif v<self.value then
    if not self.left then self.left=self:new() end
    self.left,grow=self.left:insert(v)
    self.balance=self.balance-grow
  else
    if not self.right then self.right=self:new() end
    self.right,grow=self.right:insert(v)
    self.balance=self.balance+grow
  end
  self,rotated=self:rebalance()
  return self, (rotated or self.balance==0) and 0 or grow
end

function AVL:delete_move(dir,other,mul)
  if self[dir] then
    local sb2,v
    self[dir], sb2, v=self[dir]:delete_move(dir,other,mul)
    self.balance=self.balance+sb2*mul
    self,sb2=self:rebalance()
    return self,(sb2 or self.balance==0) and -1 or 0,v
  else
    return self[other],-1,self.value
  end
end

function AVL:delete(v,isSubtree)
  local grow=0
  if v==self.value then
    local v
    if self.balance>0 then
      self.right,grow,v=self.right:delete_move("left","right",-1)
    elseif self.left then
      self.left,grow,v=self.left:delete_move("right","left",1)
      grow=-grow
    else
      return not isSubtree and AVL:new(),-1
    end
    self.value=v
    self.balance=self.balance+grow
  elseif v<self.value and self.left then
    self.left,grow=self.left:delete(v,true)
    self.balance=self.balance-grow
  elseif v>self.value and self.right then
    self.right,grow=self.right:delete(v,true)
    self.balance=self.balance+grow
  else
    return self,0
  end
  self,rotated=self:rebalance()
  return self, grow~=0 and (rotated or self.balance==0) and -1 or 0
end

-- output functions

function AVL:toList(list)
  if not self.value then return {} end
  list=list or {}
  if self.left then self.left:toList(list) end
  list[#list+1]=self.value
  if self.right then self.right:toList(list) end
  return list
end

function AVL:dump(depth)
  if not self.value then return end
  depth=depth or 0
  if self.right then self.right:dump(depth+1) end
  print(string.rep("    ",depth)..self.value.." ("..self.balance..")")
  if self.left then self.left:dump(depth+1) end
end

-- test

local test=AVL:new{1,10,5,15,20,3,5,14,7,13,2,8,3,4,5,10,9,8,7}

test:dump()
print("\ninsert 17:")
test=test:insert(17)
test:dump()
print("\ndelete 10:")
test=test:delete(10)
test:dump()
print("\nlist:")
print(unpack(test:toList()))


Abbreviations, automatic

The use of   abbreviations    (also sometimes called synonyms, nicknames, AKAs, or aliases)    can be an
easy way to add flexibility when specifying or using commands, sub-commands, options, etc.

It would make a list of words easier to maintain   (as words are added, changed, and/or deleted)   if
the minimum abbreviation length of that list could be automatically (programmatically) determined.

For this task, use the list (below) of the days-of-the-week names that are expressed in about a hundred languages   (note that there is a blank line in the list).

Sunday Monday Tuesday Wednesday Thursday Friday Saturday
Sondag Maandag Dinsdag Woensdag Donderdag Vrydag Saterdag
E_djele E_hene E_marte E_merkure E_enjte E_premte E_shtune
Ehud Segno Maksegno Erob Hamus Arbe Kedame
Al_Ahad Al_Ithinin Al_Tholatha'a Al_Arbia'a Al_Kamis Al_Gomia'a Al_Sabit
Guiragui Yergou_shapti Yerek_shapti Tchorek_shapti Hink_shapti Ourpat Shapat
domingu llunes martes miercoles xueves vienres sabadu
Bazar_gUnU Birinci_gUn Ckinci_gUn UcUncU_gUn DOrdUncU_gUn Bes,inci_gUn Altonco_gUn
Igande Astelehen Astearte Asteazken Ostegun Ostiral Larunbat
Robi_bar Shom_bar Mongal_bar Budhh_bar BRihashpati_bar Shukro_bar Shoni_bar
Nedjelja Ponedeljak Utorak Srijeda Cxetvrtak Petak Subota
Disul Dilun Dimeurzh Dimerc'her Diriaou Digwener Disadorn
nedelia ponedelnik vtornik sriada chetvartak petak sabota
sing_kei_yaht sing_kei_yat sing_kei_yee sing_kei_saam sing_kei_sie sing_kei_ng sing_kei_luk
Diumenge Dilluns Dimarts Dimecres Dijous Divendres Dissabte
Dzeenkk-eh Dzeehn_kk-ehreh Dzeehn_kk-ehreh_nah_kay_dzeeneh Tah_neesee_dzeehn_neh Deehn_ghee_dzee-neh Tl-oowey_tts-el_dehlee Dzeentt-ahzee
dy_Sul dy_Lun dy_Meurth dy_Mergher dy_You dy_Gwener dy_Sadorn
Dimanch Lendi Madi Mekredi Jedi Vandredi Samdi
nedjelja ponedjeljak utorak srijeda cxetvrtak petak subota
nede^le ponde^li utery str^eda c^tvrtek patek sobota
Sondee Mondee Tiisiday Walansedee TOOsedee Feraadee Satadee
s0ndag mandag tirsdag onsdag torsdag fredag l0rdag
zondag maandag dinsdag woensdag donderdag vrijdag zaterdag
Diman^co Lundo Mardo Merkredo ^Jaudo Vendredo Sabato
pUhapaev esmaspaev teisipaev kolmapaev neljapaev reede laupaev

Diu_prima Diu_sequima Diu_tritima Diu_quartima Diu_quintima Diu_sextima Diu_sabbata
sunnudagur manadagur tysdaguy mikudagur hosdagur friggjadagur leygardagur
Yek_Sham'beh Do_Sham'beh Seh_Sham'beh Cha'har_Sham'beh Panj_Sham'beh Jom'eh Sham'beh
sunnuntai maanantai tiistai keskiviiko torsktai perjantai lauantai
dimanche lundi mardi mercredi jeudi vendredi samedi
Snein Moandei Tiisdei Woansdei Tonersdei Freed Sneon
Domingo Segunda_feira Martes Mercores Joves Venres Sabado
k'vira orshabati samshabati otkhshabati khutshabati p'arask'evi shabati
Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag
Kiriaki' Defte'ra Tri'ti Teta'rti Pe'mpti Paraskebi' Sa'bato
ravivaar somvaar mangalvaar budhvaar guruvaar shukravaar shanivaar
popule po`akahi po`alua po`akolu po`aha po`alima po`aono
Yom_rishon Yom_sheni Yom_shlishi Yom_revi'i Yom_chamishi Yom_shishi Shabat
ravivara somavar mangalavar budhavara brahaspativar shukravara shanivar
vasarnap hetfo kedd szerda csutortok pentek szombat
Sunnudagur Manudagur +ridjudagur Midvikudagar Fimmtudagur FOstudagur Laugardagur
sundio lundio mardio merkurdio jovdio venerdio saturdio
Minggu Senin Selasa Rabu Kamis Jumat Sabtu
Dominica Lunedi Martedi Mercuridi Jovedi Venerdi Sabbato
De_Domhnaigh De_Luain De_Mairt De_Ceadaoin De_ardaoin De_hAoine De_Sathairn
domenica lunedi martedi mercoledi giovedi venerdi sabato
Nichiyou_bi Getzuyou_bi Kayou_bi Suiyou_bi Mokuyou_bi Kin'you_bi Doyou_bi
Il-yo-il Wol-yo-il Hwa-yo-il Su-yo-il Mok-yo-il Kum-yo-il To-yo-il
Dies_Dominica Dies_Lunae Dies_Martis Dies_Mercurii Dies_Iovis Dies_Veneris Dies_Saturni
sve-tdien pirmdien otrdien tresvdien ceturtdien piektdien sestdien
Sekmadienis Pirmadienis Antradienis Trec^iadienis Ketvirtadienis Penktadienis S^es^tadienis
Wangu Kazooba Walumbe Mukasa Kiwanuka Nnagawonye Wamunyi
xing-_qi-_ri xing-_qi-_yi-. xing-_qi-_er xing-_qi-_san-. xing-_qi-_si xing-_qi-_wuv. xing-_qi-_liu
Jedoonee Jelune Jemayrt Jecrean Jardaim Jeheiney Jesam
Jabot Manre Juje Wonje Taije Balaire Jarere
geminrongo minomishi martes mierkoles misheushi bernashi mishabaro
Ahad Isnin Selasa Rabu Khamis Jumaat Sabtu
sphndag mandag tirsdag onsdag torsdag fredag lphrdag
lo_dimenge lo_diluns lo_dimarc lo_dimercres lo_dijous lo_divendres lo_dissabte
djadomingo djaluna djamars djarason djaweps djabierna djasabra
Niedziela Poniedzial/ek Wtorek S,roda Czwartek Pia,tek Sobota
Domingo segunda-feire terca-feire quarta-feire quinta-feire sexta-feira sabado
Domingo Lunes martes Miercoles Jueves Viernes Sabado
Duminica Luni Mart'i Miercuri Joi Vineri Sambata
voskresenie ponedelnik vtornik sreda chetverg pyatnitsa subbota
Sunday Di-luain Di-mairt Di-ciadain Di-ardaoin Di-haoine Di-sathurne
nedjelja ponedjeljak utorak sreda cxetvrtak petak subota
Sontaha Mmantaha Labobedi Laboraro Labone Labohlano Moqebelo
Iridha- Sandhudha- Anga.haruwa-dha- Badha-dha- Brahaspa.thindha- Sikura-dha- Sena.sura-dha-
nedel^a pondelok utorok streda s^tvrtok piatok sobota
Nedelja Ponedeljek Torek Sreda Cxetrtek Petek Sobota
domingo lunes martes miercoles jueves viernes sabado
sonde mundey tude-wroko dride-wroko fode-wroko freyda Saturday
Jumapili Jumatatu Jumanne Jumatano Alhamisi Ijumaa Jumamosi
sondag mandag tisdag onsdag torsdag fredag lordag
Linggo Lunes Martes Miyerkoles Huwebes Biyernes Sabado
Le-pai-jit Pai-it Pai-ji Pai-san Pai-si Pai-gO. Pai-lak
wan-ar-tit wan-tjan wan-ang-kaan wan-phoet wan-pha-ru-hat-sa-boh-die wan-sook wan-sao
Tshipi Mosupologo Labobedi Laboraro Labone Labotlhano Matlhatso
Pazar Pazartesi Sali Car,samba Per,sembe Cuma Cumartesi
nedilya ponedilok vivtorok sereda chetver pyatnytsya subota
Chu?_Nha.t Thu*_Hai Thu*_Ba Thu*_Tu* Thu*_Na'm Thu*_Sau Thu*_Ba?y
dydd_Sul dyds_Llun dydd_Mawrth dyds_Mercher dydd_Iau dydd_Gwener dyds_Sadwrn
Dibeer Altine Talaata Allarba Al_xebes Aljuma Gaaw
iCawa uMvulo uLwesibini uLwesithathu uLuwesine uLwesihlanu uMgqibelo
zuntik montik dinstik mitvokh donershtik fraytik shabes
iSonto uMsombuluko uLwesibili uLwesithathu uLwesine uLwesihlanu uMgqibelo
Dies_Dominica Dies_Lunae Dies_Martis Dies_Mercurii Dies_Iovis Dies_Veneris Dies_Saturni
Bazar_gUnU Bazar_aertaesi Caers,aenbae_axs,amo Caers,aenbae_gUnU CUmae_axs,amo CUmae_gUnU CUmae_Senbae
Sun Moon Mars Mercury Jove Venus Saturn
zondag maandag dinsdag woensdag donderdag vrijdag zaterdag
KoseEraa GyoOraa BenEraa Kuoraa YOwaaraa FeEraa Memenaa
Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Sonnabend
Domingo Luns Terza_feira Corta_feira Xoves Venres Sabado
Dies_Solis Dies_Lunae Dies_Martis Dies_Mercurii Dies_Iovis Dies_Veneris Dies_Sabbatum
xing-_qi-_tian xing-_qi-_yi-. xing-_qi-_er xing-_qi-_san-. xing-_qi-_si xing-_qi-_wuv. xing-_qi-_liu
djadomingu djaluna djamars djarason djaweps djabierne djasabra
Killachau Atichau Quoyllurchau Illapachau Chaskachau Kuychichau Intichau

''Caveat:   The list (above) most surely contains errors (or, at the least, differences) of what the actual (or true) names for the days-of-the-week.''

To make this Rosetta Code task page as small as possible, if processing the complete list, read the days-of-the-week from a file (that is created from the above list).

Notes concerning the above list of words
::*   each line has a list of days-of-the-week for a language, separated by at least one blank
::*   the words on each line happen to be in order, from Sunday --> Saturday
::*   most lines have words in mixed case and some have all manner of accented words and other characters
::*   some words were translated to the nearest character that was available to ''code page''   '''437'''
::*   the characters in the words are not restricted except that they may not have imbedded blanks
::*   for this example, the use of an underscore ('''_''') was used to indicate a blank in a word

;Task:
::*   The list of words   (days of the week)   needn't be verified/validated.
::*   Write a function to find the (numeric) minimum length abbreviation for each line that would make abbreviations unique.
::*   A blank line   (or a null line)   should return a null string.
::*   Process and show the output for at least the first '''five''' lines of the file.
::*   Show all output here.

Solution:
function split(line)
    local wa = {}
    for i in string.gmatch(line, "%S+") do
        table.insert(wa, i)
    end
    return wa
end

-- main
local file = assert(io.open("days_of_week.txt", "r"))
io.input(file)

local line_num = 0
while true do
    local line = io.read()
    if line == nil then break end
    line_num = line_num + 1

    if string.len(line) > 0 then
        local days = split(line)
        if #days ~= 7 then
            error("There aren't 7 days in line "..line_num)
        end

        local temp = {}
        for i,day in pairs(days) do
            if temp[day] ~= nil then
                io.stderr:write(" ∞  "..line.."\n")
            else
                temp[day] = true
            end
        end

        local length = 1
        while length < 50 do
            temp = {}
            local count = 0
            for i,day in pairs(days) do
                local key = string.sub(day, 0, length)
                if temp[key] ~= nil then break end
                temp[key] = true
                count = count + 1
            end
            if count == 7 then
                print(string.format("%2d  %s", length, line))
                break
            end
            length = length + 1
        end
    end
end


Abbreviations, easy

This task is an easier (to code) variant of the Rosetta Code task:    [[Abbreviations, simple]].

For this task, the following   ''command table''   will be used:
    Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy
    COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find
    NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput
    Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO
    MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT
    READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT
    RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up

Notes concerning the above   ''command table'':
::*   it can be thought of as one long literal string   (with blanks at end-of-lines)
::*   it may have superfluous blanks
::*   it may be in any case (lower/upper/mixed)
::*   the order of the words in the   ''command table''   must be preserved as shown
::*   the user input(s) may be in any case (upper/lower/mixed)
::*   commands will be restricted to the Latin alphabet   (A --> Z,   a --> z)
::*   A valid abbreviation is a word that has:
:::*   at least the minimum length of the number of capital letters of the word in the ''command table''
:::*   compares equal (regardless of case) to the leading characters of the word in the ''command table''
:::*   a length not longer than the word in the ''command table''
::::*   '''ALT''',   '''aLt''',   '''ALTE''',   and   '''ALTER'''   are all abbreviations of   '''ALTer'''
::::*   '''AL''',   '''ALF''',   '''ALTERS''',   '''TER''',   and   '''A'''    aren't valid abbreviations of   '''ALTer'''
::::*   The number of capital letters in   '''ALTer'''   indicates that any abbreviation for   '''ALTer'''   must be at least three letters
::::*   Any word longer than five characters can't be an abbreviation for   '''ALTer'''
::::*   '''o''',    '''ov''',    '''oVe''',    '''over''',    '''overL''',    '''overla'''   are all acceptable abbreviations for   '''Overlay'''
::*   if there isn't any lowercase letters in the word in the ''command table'',   then there isn't an abbreviation permitted

;Task:
::*   The command table needn't be verified/validated.
::*   Write a function to validate if the user "words"   (given as input)   are valid   (in the ''command table'').
::*   If the word   is   valid,   then return the full uppercase version of that "word".
::*   If the word        isn't     valid,   then return the lowercase string:    '''*error*'''        (7 characters).
::*   A blank input   (or a null input)   should return a null string.
::*   Show all output here.

;An example test case to be used for this task:
For a user string of:
  riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
the computer program should return the string:
  RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Solution:
#!/usr/bin/lua

local list1 = [[
   Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst
 COMPress COpy COUnt COVerlay CURsor DELete CDelete Down DUPlicate
 Xedit EXPand EXTract Find NFind NFINDUp NFUp CFind FINdup FUp
 FOrward GET Help HEXType Input POWerinput Join SPlit SPLTJOIN
 LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO MErge
 MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query
  QUIT READ  RECover REFRESH RENum REPeat  Replace CReplace
  RESet  RESTore  RGTLEFT RIght LEft  SAVE  SET SHift SI  SORT
  SOS  STAck STATus  TOP TRAnsfer Type Up ]]

local indata1 = [[riG  rePEAT copies  put mo   rest    types
   fup.    6       poweRin]]

local indata2 = [[ALT  aLt  ALTE  ALTER  AL  ALF ALTERS TER A]]
local indata3 = [[o  ov  oVe  over  overL  overla]]

local function split(text)
   local result = {}
   for w in string.gmatch(text, "%g+") do
      result[#result+1]=w
      -- print(#result,w,#w)
   end
   return result
end

local function print_line( t )
   for i = 1,#t do
      io.write( string.format("%s ", t[i] ) )
   end
   print()
end

local function is_valid(cmd,abbrev)
   --print(abbrev,cmd,"##")

   local sm = string.match( cmd:lower(), abbrev:lower() )
   if sm == nil then return -1 end

   -- test if any lowercase in "cmd"
   if false then do -- NOTE!: requirement spec error .. put not equal PUT
	 local lowcase = string.match(cmd,"%l+")
	 if lowcase == nil then return -2 end
	 if #lowcase < 1 then return -3 end
		 end
   end

   -- test if abbrev is too long
   if #abbrev > #cmd then return -4 end

   --- num caps in "cmd" is minimum length of abbrev
   local caps = string.match(cmd,"%u+")
   if #abbrev < #caps then return -5 end

   local s1 = abbrev:sub(1,#caps)
   local s2 = cmd:sub(1,#caps)
   if s1:lower() ~= s2:lower() then return -6 end

   return 1
end

local function start()
   local t1 = {}
   local t2 = {}
   local result = {}
   t1 = split(list1)
   t2 = split(indata1)
   print_line(t2);

   for i = 1,#t2 do
      good = 0
      for j = 1,#t1 do
	 local abbrev = t2[i]
	 local cmd = t1[j]
	 good = is_valid(cmd,abbrev)
	 if good==1 then do
	       result[#result+1] = t1[j]:upper()
	       break end
	 end  --if
      end --for j
      if good < 1 then result[#result+1] = "*error*" end
   end --for i
   print_line(result)
end

start() -- run the program


Abbreviations, simple

The use of   abbreviations    (also sometimes called synonyms, nicknames, AKAs, or aliases)    can be an
easy way to add flexibility when specifying or using commands, sub-commands, options, etc.

For this task, the following   ''command table''   will be used:
    add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
    compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
    3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
    forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
    locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
    msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
    refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
    2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1

Notes concerning the above   ''command table'':
::*   it can be thought of as one long literal string   (with blanks at end-of-lines)
::*   it may have superfluous blanks
::*   it may be in any case (lower/upper/mixed)
::*   the order of the words in the   ''command table''   must be preserved as shown
::*   the user input(s) may be in any case (upper/lower/mixed)
::*   commands will be restricted to the Latin alphabet   (A --> Z,   a --> z)
::*   a command is followed by an optional number, which indicates the minimum abbreviation
::*   A valid abbreviation is a word that has:
:::*   at least the minimum length of the word's minimum number in the ''command table''
:::*   compares equal (regardless of case) to the leading characters of the word in the ''command table''
:::*   a length not longer than the word in the ''command table''
::::*   '''ALT''',   '''aLt''',   '''ALTE''',   and   '''ALTER'''   are all abbreviations of   '''ALTER 3'''
::::*   '''AL''',   '''ALF''',   '''ALTERS''',   '''TER''',   and   '''A'''    aren't valid abbreviations of   '''ALTER 3'''
::::*   The   '''3'''   indicates that any abbreviation for   '''ALTER'''   must be at least three characters
::::*   Any word longer than five characters can't be an abbreviation for   '''ALTER'''
::::*   '''o''',    '''ov''',    '''oVe''',    '''over''',    '''overL''',    '''overla'''   are all acceptable abbreviations for   '''overlay 1'''
::*   if there isn't a number after the command,   then there isn't an abbreviation permitted

;Task:
::*   The command table needn't be verified/validated.
::*   Write a function to validate if the user "words"   (given as input)   are valid   (in the ''command table'').
::*   If the word   is   valid,   then return the full uppercase version of that "word".
::*   If the word        isn't     valid,   then return the lowercase string:    '''*error*'''        (7 characters).
::*   A blank input   (or a null input)   should return a null string.
::*   Show all output here.

;An example test case to be used for this task:
For a user string of:
  riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
the computer program should return the string:
  RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Solution:
abbr = {
  define = function(self, cmdstr)
    local cmd
    self.hash = {}
    for word in cmdstr:upper():gmatch("%S+") do
      if cmd then
        local n = tonumber(word)
        for len = n or #cmd, #cmd do
          self.hash[cmd:sub(1,len)] = cmd
        end
        cmd = n==nil and word or nil
      else
        cmd = word
      end
    end
  end,
  expand = function(self, input)
    local output = {}
    for word in input:upper():gmatch("%S+") do
      table.insert(output, self.hash[word] or "*error*")
    end
    return table.concat(output, " ")
  end
}
abbr:define[[
  add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
  compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
  3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
  forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
  locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
  msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
  refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
  2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1
]]
local input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
print("Input:", input)
print("Output:", abbr:expand(input))


Abelian sandpile model

{{wikipedia|Abelian sandpile model}}
Implement the '''Abelian sandpile model''' also known as '''Bak-Tang-Wiesenfeld model'''. Its history, mathematical definition and properties can be found under its wikipedia article.

The task requires the creation of a 2D grid of arbitrary size on which "piles of sand" can be placed. Any "pile" that has 4 or more sand particles on it ''collapses'', resulting in '''four particles being subtracted from the pile''' and '''distributed among its neighbors.'''

It is recommended to display the output in some kind of image format, as terminal emulators are usually too small to display images larger than a few dozen characters tall. As an example of how to accomplish this, see the Bitmap/Write a PPM file task.
Examples up to 2^30, wow!
javascript running on web
'''Examples:'''

0 0 0 0 0    0 0 0 0 0
0 0 0 0 0    0 0 1 0 0
0 0 4 0 0 -> 0 1 0 1 0
0 0 0 0 0    0 0 1 0 0
0 0 0 0 0    0 0 0 0 0

0 0 0 0 0    0 0 0 0 0
0 0 0 0 0    0 0 1 0 0
0 0 6 0 0 -> 0 1 2 1 0
0 0 0 0 0    0 0 1 0 0
0 0 0 0 0    0 0 0 0 0

0  0 0  0  0    0 0 1 0 0
0  0 0  0  0    0 2 1 2 0
0  0 16 0  0 -> 1 1 0 1 1
0  0 0  0  0    0 2 1 2 0
0  0 0  0  0    0 0 1 0 0

Solution:
local sandpile = {
  init = function(self, dim, val)
    self.cell, self.dim = {}, dim
    for r = 1, dim do
      self.cell[r] = {}
      for c = 1, dim do
        self.cell[r][c] = 0
      end
    end
    self.cell[math.floor(dim/2)+1][math.floor(dim/2)+1] = val
  end,
  iter = function(self)
    local dim, cel, more = self.dim, self.cell
    repeat
      more = false
      for r = 1, dim do
        for c = 1, dim do
          if cel[r][c] >= 4 then
            cel[r][c] = cel[r][c] - 4
            if c > 1 then cel[r][c-1], more = cel[r][c-1]+1, more or cel[r][c-1]>=3 end
            if c < dim then cel[r][c+1], more = cel[r][c+1]+1, more or cel[r][c+1]>=3 end
            if r > 1 then cel[r-1][c], more = cel[r-1][c]+1, more or cel[r-1][c]>=3 end
            if r < dim then cel[r+1][c], more = cel[r+1][c]+1, more or cel[r+1][c]>=3 end
          end
          more = more or cel[r][c] >= 4
        end
      end
    until not more
  end,
  draw = function(self)
    for r = 1, self.dim do
      print(table.concat(self.cell[r]," "))
    end
  end,
}
sandpile:init(15, 256)
sandpile:iter()
sandpile:draw()


Abelian sandpile model/Identity

Our sandpiles are based on a 3 by 3 rectangular grid giving nine areas that
contain a number from 0 to 3 inclusive. (The numbers are said to represent
grains of sand in each area of the sandpile).

E.g. s1 =

    1 2 0
    2 1 1
    0 1 3

and s2 =

    2 1 3
    1 0 1
    0 1 0

Addition on sandpiles is done by adding numbers in corresponding grid areas,
so for the above:

              1 2 0     2 1 3     3 3 3
    s1 + s2 = 2 1 1  +  1 0 1  =  3 1 2
              0 1 3     0 1 0     0 2 3

If the addition would result in more than 3 "grains of sand" in any area then
those areas cause the whole sandpile to become "unstable" and the sandpile
areas are "toppled" in an "avalanche" until the "stable" result is obtained.

Any unstable area (with a number >= 4), is "toppled" by loosing one grain of
sand to each of its four horizontal or vertical neighbours. Grains are lost
at the edge of the grid, but otherwise increase the number in neighbouring
cells by one, whilst decreasing the count in the toppled cell by four in each
toppling.

A toppling may give an adjacent area more than four grains of sand leading to
a chain of topplings called an "avalanche".
E.g.

    4 3 3     0 4 3     1 0 4     1 1 0     2 1 0
    3 1 2 ==> 4 1 2 ==> 4 2 2 ==> 4 2 3 ==> 0 3 3
    0 2 3     0 2 3     0 2 3     0 2 3     1 2 3

The final result is the stable sandpile on the right.

'''Note:''' The order in which cells are toppled does not affect the final result.

;Task:
* Create a class or datastructure and functions to represent and operate on sandpiles.
* Confirm the result of the avalanche of topplings shown above
* Confirm that s1 + s2 == s2 + s1  # Show the stable results
* If s3 is the sandpile with number 3 in every grid area, and s3_id is the following sandpile:

    2 1 2
    1 0 1
    2 1 2

* Show that s3 + s3_id == s3
* Show that s3_id + s3_id == s3_id

Show confirming output here, with your examples.

;References:
*    https://www.youtube.com/watch?v=1MtEUErz7Gg
*    https://en.wikipedia.org/wiki/Abelian_sandpile_model

Solution:
sandpile.__index = sandpile
sandpile.new = function(self, vals)
  local inst = setmetatable({},sandpile)
  inst.cell, inst.dim = {}, #vals
  for r = 1, inst.dim do
    inst.cell[r] = {}
    for c = 1, inst.dim do
      inst.cell[r][c] = vals[r][c]
    end
  end
  return inst
end
sandpile.add = function(self, other)
  local vals = {}
  for r = 1, self.dim do
    vals[r] = {}
    for c = 1, self.dim do
      vals[r][c] = self.cell[r][c] + other.cell[r][c]
    end
  end
  local inst = sandpile:new(vals)
  inst:iter()
  return inst
end

local s1 = sandpile:new{{1,2,0},{2,1,1},{0,1,3}}
local s2 = sandpile:new{{2,1,3},{1,0,1},{0,1,0}}
print("s1 =")  s1:draw()
print("\ns2 =")  s2:draw()
local s1ps2 = s1:add(s2)
print("\ns1 + s2 =")  s1ps2:draw()
local s2ps1 = s2:add(s1)
print("\ns2 + s1 =")  s2ps1:draw()
local topple = sandpile:new{{4,3,3},{3,1,2},{0,2,3}}
print("\ntopple, before =")  topple:draw()
topple:iter()
print("\ntopple, after =")  topple:draw()
local s3 = sandpile:new{{3,3,3},{3,3,3},{3,3,3}}
print("\ns3 =")  s3:draw()
local s3_id = sandpile:new{{2,1,2},{1,0,1},{2,1,2}}
print("\ns3_id =") s3_id:draw()
local s3ps3_id = s3:add(s3_id)
print("\ns3 + s3_id =")  s3ps3_id:draw()
local s3_idps3_id = s3_id:add(s3_id)
print("\ns3_id + s3_id =")  s3_idps3_id:draw()


Abundant odd numbers

An Abundant number is a number '''n''' for which the   ''sum of divisors''   '''s(n) > 2n''',
or,   equivalently,   the   ''sum of proper divisors''   (or aliquot sum)       '''s(n) > n'''.

;E.G.:
'''12'''   is abundant, it has the proper divisors     '''1,2,3,4 & 6'''     which sum to   '''16'''   ( > '''12''' or '''n''');
       or alternately,   has the sigma sum of   '''1,2,3,4,6 & 12'''   which sum to   '''28'''   ( > '''24''' or '''2n''').

Abundant numbers are common, though '''even''' abundant numbers seem to be much more common than '''odd''' abundant numbers.

To make things more interesting, this task is specifically about finding   ''odd abundant numbers''.

;Task
*Find and display here: at least the first 25 abundant odd numbers and either their proper divisor sum or sigma sum.
*Find and display here: the one thousandth abundant odd number and either its proper divisor sum or sigma sum.
*Find and display here: the first abundant odd number greater than one billion (109) and either its proper divisor sum or sigma sum.

;References:
:*   OEIS:A005231: Odd abundant numbers (odd numbers n whose sum of divisors exceeds 2n)
:*   American Journal of Mathematics, Vol. 35, No. 4 (Oct., 1913), pp. 413-422 - Finiteness of the Odd Perfect and Primitive Abundant Numbers with n Distinct Prime Factors (LE Dickson)

Solution:
-- Return the sum of the proper divisors of x
function sumDivs (x)
  local sum, sqr = 1, math.sqrt(x)
  for d = 2, sqr do
    if x % d == 0 then
      sum = sum + d
      if d ~= sqr then sum = sum + (x/d) end
    end
  end
  return sum
end

-- Return a table of odd abundant numbers
function oddAbundants (mode, limit)
  local n, count, divlist, divsum = 1, 0, {}
  repeat
    n = n + 2
    divsum = sumDivs(n)
    if divsum > n then
      table.insert(divlist, {n, divsum})
      count = count + 1
      if mode == "Above" and n > limit then return divlist[#divlist] end
    end
  until count == limit
  if mode == "First" then return divlist end
  if mode == "Nth" then return divlist[#divlist] end
end

-- Write a result to stdout
function showResult (msg, t)
  print(msg .. ": the proper divisors of " .. t[1] .. " sum to " .. t[2])
end

-- Main procedure
for k, v in pairs(oddAbundants("First", 25)) do  showResult(k, v) end
showResult("1000", oddAbundants("Nth", 1000))
showResult("Above 1e6", oddAbundants("Above", 1e6))


Accumulator factory

{{requires|Mutable State}}

A problem posed by Paul Graham is that of creating a function that takes a single (numeric) argument and which returns another function that is an accumulator. The returned accumulator function in turn also takes a single numeric argument, and returns the sum of all the numeric values passed in so far to that accumulator (including the initial value passed when the accumulator was created).

;Rules:
The detailed rules are at http://paulgraham.com/accgensub.html and are reproduced here for simplicity (with additions in ''small italic text'').
:Before you submit an example, make sure the function

:# Takes a number n and returns a function (lets call it g), that takes a number i, and returns n incremented by the accumulation of i from every call of function g(i).Although these exact function and parameter names need not be used
:# Works for any numeric type-- i.e. can take both ints and floats and returns functions that can take both ints and floats. (It is not enough simply to convert all input to floats. An accumulator that has only seen integers must return integers.) ''(i.e., if the language doesn't allow for numeric polymorphism, you have to use overloading or something like that)''
:# Generates functions that return the sum of every number ever passed to them, not just the most recent. ''(This requires a piece of state to hold the accumulated value, which in turn means that pure functional languages can't be used for this task.)''
:# Returns a real function, meaning something that you can use wherever you could use a function you had defined in the ordinary way in the text of your program. ''(Follow your language's conventions here.)''
:# Doesn't store the accumulated value or the returned functions in a way that could cause them to be inadvertently modified by other code. ''(No global variables or other such things.)''
: E.g. if after the example, you added the following code (in a made-up language) ''where the factory function is called foo'':
:: x = foo(1);
x(5);
foo(3);
print x(2.3);
: It should print 8.3. ''(There is no need to print the form of the accumulator function returned by foo(3); it's not part of the task at all.)''

;Task:
Create a function that implements the described rules.

It need not handle any special error cases not described above. The simplest way to implement the task as described is typically to use a closure, providing the language supports them.

Where it is not possible to hold exactly to the constraints above, describe the deviations.

Solution:
function acc(init)
  init = init or 0
  return function(delta)
    init = init + (delta or 0)
    return init
  end
end


Accumulator factory

Solution:
do
    local accSum = 0;               -- accumulator factory 'upvalue'
    function acc(v)                 -- the accumulator factory
        accSum = accSum + (v or 0)  -- increment factory sum

        local closuredSum = accSum;               -- new 'upvalue' at each factory call
        return function (w)                       -- the produced accumulator function
            closuredSum = closuredSum + (w or 0)  -- increment product 'upvalue'
            return closuredSum                    -- return 'upvalue'
        end, accSum                               -- end of product closure

    end--acc
end--end of factory closure


Amb

Define and give an example of the Amb operator.

The Amb operator (short for "ambiguous") expresses nondeterminism. This doesn't refer to randomness (as in "nondeterministic universe") but is closely related to the term as it is used in automata theory ("non-deterministic finite automaton").

The Amb operator takes a variable number of expressions (or values if that's simpler in the language) and yields a correct one which will satisfy a constraint in some future computation, thereby avoiding failure.

Problems whose solution the Amb operator naturally expresses can be approached with other tools, such as explicit nested iterations over data sets, or with pattern matching. By contrast, the Amb operator appears integrated into the language. Invocations of Amb are not wrapped in any visible loops or other search patterns; they appear to be independent.

Essentially Amb(x, y, z) splits the computation into three possible futures: a future in which the value x is yielded, a future in which the value y is yielded and a future in which the value z is yielded. The future which leads to a successful subsequent computation is chosen. The other "parallel universes" somehow go away.   Amb called with no arguments fails.

For simplicity, one of the domain values usable with Amb may denote failure, if that is convenient. For instance, it is convenient if a Boolean false denotes failure, so that Amb(false) fails, and thus constraints can be expressed using Boolean expressions like Amb(x * y == 8) which unless x and y add to four.

A pseudo-code program which satisfies this constraint might look like:

let x = Amb(1, 2, 3)
let y = Amb(7, 6, 4, 5)
Amb(x * y = 8)
print x, y

The output is 2 4 because Amb(1, 2, 3) correctly chooses the future in which x has value 2, Amb(7, 6, 4, 5) chooses 4 and consequently Amb(x * y = 8) produces a success.

Alternatively, failure could be represented using strictly Amb():

unless x * y = 8 do Amb()

Or else Amb could take the form of two operators or functions: one for producing values and one for enforcing constraints:

let x = Ambsel(1, 2, 3)
let y = Ambsel(4, 5, 6)
Ambassert(x * y = 8)
print x, y

where Ambassert behaves like Amb() if the Boolean expression is false, otherwise it allows the future computation to take place, without yielding any value.

The task is to somehow implement Amb, and demonstrate it with a program which chooses one word from each of the following four sets of character strings to generate a four-word sentence:

#"the" "that" "a"
#"frog" "elephant" "thing"
#"walked" "treaded" "grows"
#"slowly" "quickly"

The constraint to be satisfied is that the last character of each word (other than the last) is the same as the first character of its successor.

The only successful sentence is "that thing grows slowly"; other combinations do not satisfy the constraint and thus fail.

The goal of this task isn't to simply process the four lists of words with explicit, deterministic program flow such as nested iteration, to trivially demonstrate the correct output. The goal is to implement the Amb operator, or a facsimile thereof that is possible within the language limitations.

Solution:
print("Per task requirements:")
w1 = Amb('the','that','a')
w2 = Amb('frog','elephant','thing')
w3 = Amb('walked','treaded','grows')
w4 = Amb('slowly','quickly')
function rule(t) local a,b,c,d = unpack(t) return a:byte(#a)==b:byte(1) and b:byte(#b)==c:byte(1) and c:byte(#c)==d:byte(1) end
answers = Amb(rule, w1, w2, w3, w4)
answers:map(function(t) return t:concat(" ") end):each(print)

print()

print("Modified task, seek equal length of words:")
w1 = Amb('the','that','a','which')
w2 = Amb('red','green','blue','yellow')
w3 = Amb('frog','elephant','cow','thing')
w4 = Amb('walked','treaded','grew','shrunk')
w5 = Amb('slow','quick','moderately')
function rule(t) local a,b,c,d,e = unpack(t) return #a==#b and #b==#c and #c==#d and #d==#e end
answers = Amb(rule, w1, w2, w3, w4, w5)
answers:map(function(t) return t:concat(" ") end):each(print)

print()

print("Modified example, seek product of 12:")
x = Amb(1,2,3)
y = Amb(4,5,6)
function rule(t) local x,y = unpack(t) return x*y==12 end
answers = Amb(rule, x, y)
answers:map(function(t) return t:concat(" ") end):each(print)

print()

print("Pythagorean triples:")
x = Amb(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
y = Amb(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
z = Amb(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
function rule(t) local x,y,z = unpack(t) return x^2 + y^2 == z^2 end
answers = Amb(rule, x, y, z)
answers:map(function(t) return t:concat(" ") end):each(print)

print()

print("When there is no solution:")
x = Amb(1,2,3)
y = Amb(4,5,6)
function rule(t) local x,y = unpack(t) return x*y==7 end
answers = Amb(rule, x, y, z)
print("#answers = " .. #answers)

print()

print("send + more = money:")
-- intuitive simplification applied:  m must be 1 ==> others may not be 1 (reduces complexity from 10^8 to 9^7)
-- ("m is allowed to be leading zero" solutions exist, e.g. 2 8 1 7 0 3 6 5, and this could find them, but why?)
s = Amb(0,2,3,4,5,6,7,8,9)
e = Amb(0,2,3,4,5,6,7,8,9)
n = Amb(0,2,3,4,5,6,7,8,9)
d = Amb(0,2,3,4,5,6,7,8,9)
m = Amb(1)
o = Amb(0,2,3,4,5,6,7,8,9)
r = Amb(0,2,3,4,5,6,7,8,9)
y = Amb(0,2,3,4,5,6,7,8,9)
function rule(t)
  for i=1,#t do for j=i+1,#t do if t[i]==t[j] then return false end end end
  local s,e,n,d,m,o,r,y = unpack(t)
  return s*1000 + e*100 + 10*n + d + m*1000 + o*100 + r*10 + e == m*10000 + o*1000 + n*100 + e*10 + y
end
answers = Amb(rule, s, e, n, d, m, o, r, y)
answers:map(function(t) return t:concat(" ") end):each(print)


Anagrams/Deranged anagrams

Two or more words are said to be anagrams if they have the same characters, but in a different order.

By analogy with derangements we define a  ''deranged anagram'' as two words with the same characters, but in which the same character does ''not'' appear in the same position in both words.

;Task

Use the word list at unixdict to find and display the longest deranged anagram.

;Related
* [[Permutations/Derangements]]
* Best shuffle

{{Related tasks/Word plays}}

Solution:
string.tacnoc = function(str) -- 'inverse' of table.concat
  local arr={}
  for ch in str:gmatch(".") do arr[#arr+1]=ch end
  return arr
end

local function deranged(s1, s2)
  if s1==s2 then return false end
  local t1, t2 = s1:tacnoc(), s2:tacnoc()
  for i,v in ipairs(t1) do if t2[i]==v then return false end end
  return true
end

local dict = {}
local f = io.open("unixdict.txt", "r")
for word in f:lines() do
  local ltrs = word:tacnoc()
  table.sort(ltrs)
  local hash = table.concat(ltrs)
  dict[hash] = dict[hash] or {}
  table.insert(dict[hash], word)
end

local answer = { word="", anag="", len=0 }
for _,list in pairs(dict) do
  if #list>1 and #list[1]>answer.len then
    for _,word in ipairs(list) do
      for _,anag in ipairs(list) do
        if deranged(word, anag) then
          answer.word, answer.anag, answer.len = word, anag, #word
        end
      end
    end
  end
end
print(answer.word, answer.anag, answer.len)


Angle difference between two bearings

Finding the angle between two bearings is often confusing.[https://stackoverflow.com/questions/16180595/find-the-angle-between-two-bearings]

;Task:
Find the angle which is the result of the subtraction '''b2 - b1''', where '''b1''' and '''b2''' are the bearings.

Input bearings are expressed in the range   '''-180'''   to   '''+180'''   degrees.
The  result  is also expressed in the range   '''-180'''   to   '''+180'''   degrees.

Compute the angle for the following pairs:
*  20 degrees ('''b1''') and 45 degrees ('''b2''')
* -45 and  45
* -85 and  90
* -95 and  90
* -45 and 125
* -45 and 145
*  29.4803 and  -88.6381
* -78.3251 and -159.036

;Optional extra:
Allow the input bearings to be any (finite) value.

;Test cases:
*  -70099.74233810938   and   29840.67437876723
* -165313.6666297357    and   33693.9894517456
*    1174.8380510598456 and -154146.66490124757
*   60175.77306795546   and   42213.07192354373

Solution:
bearing = {degrees = 0} -- prototype object

function bearing:assign(angle)
	angle = tonumber(angle) or 0
	while angle > 180 do
		angle = angle - 360
	end
	while angle < -180 do
		angle = angle + 360
	end
	self.degrees = angle
end

function bearing:new(size)
	local child_object = {}
	setmetatable(child_object, {__index = self})
	child_object:assign(size)
	return child_object
end

function bearing:subtract(other)
	local difference = self.degrees - other.degrees
	return self:new(difference)
end

function bearing:list(sizes)
	local bearings = {}
	for index, size in ipairs(sizes) do
		table.insert(bearings, self:new(size))
	end
	return bearings
end

function bearing:text()
	return string.format("%.4f deg", self.degrees)
end

function main()
	local subtrahends = bearing:list{
		20, -45, -85, -95, -45, -45, 29.4803, -78.3251,
		-70099.74233810938, -165313.6666297357,
		1174.8380510598456, 60175.77306795546
	}
	local minuends = bearing:list{
		45, 45, 90, 90, 125, 145, -88.6381, -159.036,
		29840.67437876723, 33693.9894517456,
		-154146.66490124757, 42213.07192354373
	}
	for index = 1, #minuends do
		local b2, b1 = minuends[index], subtrahends[index]
		local b3 = b2:subtract(b1)
		local statement = string.format(
			"%s - %s = %s\n",
			b2:text(), b1:text(), b3:text()
		)
		io.write(statement)
	end
end

main()


Anti-primes

The anti-primes
(or highly composite numbers, sequence A002182 in the OEIS)
are the natural numbers with more factors than any smaller than itself.

;Task:
Generate and show here, the first twenty anti-primes.

;Related tasks:
:*   [[Factors of an integer]]
:*   [[Sieve of Eratosthenes]]

Solution:
-- First 20 antiprimes.

function count_factors(number)
	local count = 0
	for attempt = 1, number do
		local remainder = number % attempt
		if remainder == 0 then
			count = count + 1
		end
	end
	return count
end

function antiprimes(goal)
	local list, number, mostFactors = {}, 1, 0
	while #list < goal do
		local factors = count_factors(number)
		if factors > mostFactors then
			table.insert(list, number)
			mostFactors = factors
		end
		number = number + 1
	end
	return list
end

function recite(list)
	for index, item in ipairs(list) do
		print(item)
	end
end

print("The first 20 antiprimes:")
recite(antiprimes(20))
print("Done.")


Apply a digital filter (direct form II transposed)

Digital filters are used to apply a mathematical operation to a sampled signal. One of the common formulations is the "direct form II transposed" which can represent both infinite impulse response (IIR) and finite impulse response (FIR) filters, as well as being more numerically stable than other forms. [https://ccrma.stanford.edu/~jos/fp/Transposed_Direct_Forms.html]

;Task:

Filter a signal using an order 3 low-pass Butterworth filter. The coefficients for the filter are a=[1.00000000, -2.77555756e-16, 3.33333333e-01, -1.85037171e-17] and b = [0.16666667, 0.5, 0.5, 0.16666667]

The signal that needs filtering is the following vector: [-0.917843918645, 0.141984778794, 1.20536903482, 0.190286794412, -0.662370894973, -1.00700480494, -0.404707073677 ,0.800482325044, 0.743500089861, 1.01090520172, 0.741527555207, 0.277841675195, 0.400833448236, -0.2085993586, -0.172842103641, -0.134316096293, 0.0259303398477, 0.490105989562, 0.549391221511, 0.9047198589]

;See also:
[Wikipedia on Butterworth filters]

Solution:
function filter(b,a,input)
    local out = {}
    for i=1,table.getn(input) do
        local tmp = 0
        local j = 0
        out[i] = 0

        for j=1,table.getn(b) do
            if i - j < 0 then
                --continue
            else
                tmp = tmp + b[j] * input[i - j + 1]
            end
        end

        for j=2,table.getn(a) do
            if i - j < 0 then
                --continue
            else
                tmp = tmp - a[j] * out[i - j + 1]
            end
        end

        tmp = tmp / a[1]
        out[i] = tmp
    end
    return out
end

function main()
    local sig = {
        -0.917843918645, 0.141984778794, 1.20536903482,  0.190286794412,-0.662370894973,
        -1.00700480494, -0.404707073677, 0.800482325044, 0.743500089861, 1.01090520172,
         0.741527555207, 0.277841675195, 0.400833448236,-0.2085993586,  -0.172842103641,
        -0.134316096293, 0.0259303398477,0.490105989562, 0.549391221511, 0.9047198589
    }

    --Constants for a Butterworth filter (order 3, low pass)
    local a = {1.00000000, -2.77555756e-16, 3.33333333e-01, -1.85037171e-17}
    local b = {0.16666667, 0.5, 0.5, 0.16666667}

    local result = filter(b,a,sig)
    for i=1,table.getn(result) do
        io.write(result[i] .. ", ")
    end
    print()

    return nil
end

main()


Approximate equality

Sometimes, when testing whether the solution to a task (for example, here on Rosetta Code) is correct, the
difference in floating point calculations between different language implementations becomes significant.

For example, a difference between '''32''' bit and '''64''' bit floating point calculations may appear by
about the 8th significant digit in base 10 arithmetic.

;Task:
Create a function which returns true if two floating point numbers are approximately equal.

The function should allow for differences in the magnitude of numbers, so that, for example,
'''100000000000000.01'''   may be approximately equal to   '''100000000000000.011''',
even though   '''100.01'''   is not approximately equal to   '''100.011'''.

If the language has such a feature in its standard library, this may be used instead of a custom function.

Show the function results with comparisons on the following pairs of values:
:#     100000000000000.01,                        100000000000000.011       (note: should return ''true'')
:#     100.01,                                    100.011                                                     (note: should return ''false'')
:#     10000000000000.001 / 10000.0,   1000000000.0000001000
:#     0.001,                                     0.0010000001
:#     0.000000000000000000000101,                0.0
:#      sqrt(2) * sqrt(2),                    2.0
:#     -sqrt(2) * sqrt(2),                        -2.0
:#     3.14159265358979323846,                    3.14159265358979324

Answers should be true for the first example and false in the second, so that just rounding the numbers to a fixed number of decimals should not be enough. Otherwise answers may vary and still be correct. See the Python code for one type of solution.

__TOC__

Solution:
function approxEquals(value, other, epsilon)
    return math.abs(value - other) < epsilon
end

function test(a, b)
    local epsilon = 1e-18
    print(string.format("%f, %f => %s", a, b, tostring(approxEquals(a, b, epsilon))))
end

function main()
    test(100000000000000.01, 100000000000000.011);
    test(100.01, 100.011)
    test(10000000000000.001 / 10000.0, 1000000000.0000001000)
    test(0.001, 0.0010000001)
    test(0.000000000000000000000101, 0.0)
    test(math.sqrt(2.0) * math.sqrt(2.0), 2.0)
    test(-math.sqrt(2.0) * math.sqrt(2.0), -2.0)
    test(3.14159265358979323846, 3.14159265358979324)
end

main()


Arena storage pool

Dynamically allocated objects take their memory from a [[heap]].

The memory for an object is provided by an '''allocator''' which maintains the storage pool used for the [[heap]].

Often a call to allocator is denoted as
P := new T
where   '''T'''   is the type of an allocated object,   and   '''P'''   is a [[reference]] to the object.

The storage pool chosen by the allocator can be determined by either:
* the object type   '''T'''
* the type of pointer   '''P'''

In the former case objects can be allocated only in one storage pool.

In the latter case objects of the type can be allocated in any storage pool or on the [[stack]].

;Task:
The task is to show how allocators and user-defined storage pools are supported by the language.

In particular:
# define an arena storage pool.   An arena is a pool in which objects are allocated individually, but freed by groups.
# allocate some objects (e.g., integers) in the pool.

Explain what controls the storage pool choice in the language.

Solution:
pool = {} -- create an "arena" for the variables a,b,c,d
pool.a = 1 -- individually allocated..
pool.b = "hello"
pool.c = true
pool.d = { 1,2,3 }
pool = nil -- release reference allowing garbage collection of entire structure


Arithmetic-geometric mean

{{wikipedia|Arithmetic-geometric mean}}

;Task:
Write a function to compute the arithmetic-geometric mean of two numbers.

The arithmetic-geometric mean of two numbers can be (usefully) denoted as \mathrm{agm}(a,g), and is equal to the limit of the sequence:
: a_0 = a; \qquad g_0 = g
: a_{n+1} = \tfrac{1}{2}(a_n + g_n); \quad g_{n+1} = \sqrt{a_n g_n}.
Since the limit of a_n-g_n tends (rapidly) to zero with iterations, this is an efficient method.

Demonstrate the function by calculating:
:\mathrm{agm}(1,1/\sqrt{2})

;Also see:
*   mathworld.wolfram.com/Arithmetic-Geometric Mean

Solution:
function agm(a, b, tolerance)
    if not tolerance or tolerance < 1e-15 then
        tolerance = 1e-15
    end
    repeat
        a, b = (a + b) / 2, math.sqrt(a * b)
    until math.abs(a-b) < tolerance
    return a
end

print(string.format("%.15f", agm(1, 1 / math.sqrt(2))))


Arithmetic evaluation

Create a program which parses and evaluates arithmetic expressions.
;Requirements:
* An abstract-syntax tree (AST) for the expression must be created from parsing the input.
* The AST must be used in evaluation, also, so the input may not be directly evaluated (e.g. by calling eval or a similar language feature.)
* The expression will be a string or list of symbols like "(1+3)*7".
* The four symbols + - * / must be supported as binary operators with conventional precedence rules.
* Precedence-control parentheses must also be supported.

;Note:
For those who don't remember, mathematical precedence is as follows:
* Parentheses
* Multiplication/Division (left to right)
* Addition/Subtraction (left to right)

;C.f:
* [[24 game Player]].
* [[Parsing/RPN calculator algorithm]].
* [[Parsing/RPN to infix conversion]].

Solution:
require"lpeg"

P, R, C, S, V = lpeg.P, lpeg.R, lpeg.C, lpeg.S, lpeg.V

--matches arithmetic expressions and returns a syntax tree
expression = P{"expr";
ws = P" "^0,
number = C(R"09"^1) * V"ws",
lp = "(" * V"ws",
rp = ")" * V"ws",
sym = C(S"+-*/") * V"ws",
more = (V"sym" * V"expr")^0,
expr = V"number" * V"more" + V"lp" * lpeg.Ct(V"expr" * V"more") * V"rp" * V"more"}

--evaluates a tree
function eval(expr)
  --empty
  if type(expr) == "string" or type(expr) == "number" then return expr + 0 end

  --arithmetic functions
  tb = {["+"] = function(a,b) return eval(a) + eval(b) end,
		["-"] = function(a,b) return eval(a) - eval(b) end,
		["*"] = function(a,b) return eval(a) * eval(b) end,
		["/"] = function(a,b) return eval(a) / eval(b) end}

  --you could add ^ or other operators to this pretty easily
  for i, v in ipairs{"*/", "+-"} do
    for s, u in ipairs(expr) do
	  local k = type(u) == "string" and C(S(v)):match(u)
	  if k then
	    expr[s-1] = tb[k](expr[s-1],expr[s+1])
	    table.remove(expr, s)
	    table.remove(expr, s)
	  end
	end
  end
  return expr[1]
end

print(eval{expression:match(io.read())})


Arithmetic numbers

Definition
A positive integer '''n''' is an arithmetic number if the average of its positive divisors is also an integer.

Clearly all odd primes '''p''' must be arithmetic numbers because their only divisors are '''1''' and '''p''' whose sum is even and hence their average must be an integer. However, the prime number '''2''' is not an arithmetic number because the average of its divisors is 1.5.

;Example
30 is an arithmetic number because its 7 divisors are: [1, 2, 3, 5, 6, 10, 15, 30], their sum is 72 and average 9 which is an integer.

;Task
Calculate and show here:

1. The first 100 arithmetic numbers.

2. The '''x'''th arithmetic number where '''x''' = 1,000 and '''x''' = 10,000.

3. How many of the first '''x''' arithmetic numbers are composite.

Note that, technically, the arithmetic number '''1''' is neither prime nor composite.

;Stretch
Carry out the same exercise in 2. and 3. above for '''x''' = 100,000 and '''x''' = 1,000,000.

;References

* Wikipedia: Arithmetic number
* OEIS:A003601 - Numbers n such that the average of the divisors of n is an integer

Solution:
local function factors (n)
	local f, i = {1, n}, 2
	while true do
		local j = n//i -- floor division by Lua 5.3
		if j < i then
			break
		elseif j == i and i * j == n then
			table.insert (f, i)
			break
		elseif i * j == n then
			table.insert (f, i)
			table.insert (f, j)
		end
		i = i + 1
	end
	return f
end

local function sum (f)
	local s = 0
	for i, value in ipairs (f) do
		s = s + value
	end
	return s
end

local arithmetic_count = 1
local composite_count = 0
local hundr = {1}

for n = 2, 1228663 do
	local f = factors (n)
	local s = sum (f)
	local l = #f
	if (s/l)%1 == 0 then
		arithmetic_count = arithmetic_count + 1
		if l > 2 then
			composite_count = composite_count + 1
		end
		if arithmetic_count <= 100 then
			table.insert (hundr, n)
		end
		if arithmetic_count == 100 then
			for i = 0, 9 do
				print (table.concat(hundr, ',	', 10*i+1, 10*i+10))
			end
		elseif arithmetic_count == 1000
			or arithmetic_count == 10000
			or arithmetic_count == 100000 then
			print (arithmetic_count..'th arithmetic number is '..(n))
			print ('Number of composite arithmetic numbers <= '..(n)..': '..composite_count)
		elseif arithmetic_count == 1000000 then
			print (arithmetic_count..'th arithmetic number is '..(n))
			print ('Number of composite arithmetic numbers <= '..(n)..': '..composite_count)
			return
		end
	end
end


Array length

Determine the amount of elements in an array.

As an example use an array holding the strings 'apple' and 'orange'.

Solution:
-- For tables as simple arrays, use the # operator:
fruits = {"apple", "orange"}
print(#fruits)

-- Note the # symbol does not work for non-integer-indexed tables:
fruits = {fruit1 = "apple", fruit2 = "orange"}
print(#fruits)

-- For this you can use this short function:
function size (tab)
  local count = 0
  for k, v in pairs(tab) do
    count = count + 1
  end
  return count
end

print(size(fruits))


Ascending primes

Generate and show all primes with strictly ascending decimal digits.

Aside: Try solving without peeking at existing solutions. I had a weird idea for generating
a prime sieve faster, which needless to say didn't pan out. The solution may be p(r)etty trivial
but generating them quickly is at least mildly interesting.
Tip: filtering all 7,027,260 primes below 123,456,789 probably won't kill you, but there is
at least one significantly better and much faster way, needing a mere 511 odd/prime tests.

;See also
;* OEIS:A052015 - Primes with distinct digits in ascending order

;Related:
*[[Primes with digits in nondecreasing order]] (infinite series allowing duplicate digits, whereas this isn't and doesn't)
*[[Pandigital prime]] (whereas this is the smallest, with gaps in the used digits being permitted)

Solution:
local function is_prime(n)
  if n < 2 then return false end
  if n % 2 == 0 then return n==2 end
  if n % 3 == 0 then return n==3 end
  for f = 5, n^0.5, 6 do
    if n%f==0 or n%(f+2)==0 then return false end
  end
  return true
end

local function ascending_primes()
  local digits, candidates, primes = {1,2,3,4,5,6,7,8,9}, {0}, {}
  for i = 1, #digits do
    for j = 1, #candidates do
      local value = candidates[j] * 10 + digits[i]
      if is_prime(value) then primes[#primes+1] = value end
      candidates[#candidates+1] = value
    end
  end
  table.sort(primes)
  return primes
end

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


Associative array/Merging

Define two associative arrays, where one represents the following "base" data:

::::: {| class="wikitable"
|+
| '''Key''' || '''Value'''
|-
| "name" || "Rocket Skates"
|-
| "price" || 12.75
|-
| "color" || "yellow"
|}

And the other represents "update" data:

::::: {| class="wikitable"
|+
| '''Key''' || '''Value'''
|-
| "price" || 15.25
|-
| "color" || "red"
|-
| "year" || 1974
|}

Merge these into a new associative array that contains every key found in either of the source ones.  Each key should map to the value in the second (update) table if that exists, or else to the value in the first (base) table.  If possible, do this in a way that does not mutate the original two associative arrays.  Obviously this should be done in a way that would work for any data, not just the specific data given here, but in this example the result should be:

::::: {| class="wikitable"
|+
| '''Key''' || '''Value'''
|-
| "name" || "Rocket Skates"
|-
| "price" || 15.25
|-
| "color" || "red"
|-
| "year" || 1974
|}

Solution:
base = {name="Rocket Skates", price=12.75, color="yellow"}
update = {price=15.25, color="red", year=1974}

--[[ clone the base data ]]--
result = {}
for key,val in pairs(base) do
    result[key] = val
end

--[[ copy in the update data ]]--
for key,val in pairs(update) do
    result[key] = val
end

--[[ print the result ]]--
for key,val in pairs(result) do
    print(string.format("%s: %s", key, val))
end


Attractive numbers

A number is an   ''attractive number''   if the number of its prime factors (whether distinct or not) is also prime.

;Example:
The number   '''20''',   whose prime decomposition is   '''2 x 2 x 5''',   is an   ''attractive number''   because the number of its prime factors   ('''3''')   is also prime.

;Task:
Show sequence items up to   '''120'''.

;Reference:
:*   The OEIS entry:   A063989: Numbers with a prime number of prime divisors.

Solution:
-- Returns true if x is prime, and false otherwise
function isPrime (x)
  if x < 2 then return false end
  if x < 4 then return true end
  if x % 2 == 0 then return false end
  for d = 3, math.sqrt(x), 2 do
    if x % d == 0 then return false end
  end
  return true
end

-- Compute the prime factors of n
function factors (n)
  local facList, divisor, count = {}, 1
  if n < 2 then return facList end
  while not isPrime(n) do
    while not isPrime(divisor) do divisor = divisor + 1 end
    count = 0
    while n % divisor == 0 do
      n = n / divisor
      table.insert(facList, divisor)
    end
    divisor = divisor + 1
    if n == 1 then return facList end
  end
  table.insert(facList, n)
  return facList
end

-- Main procedure
for i = 1, 120 do
  if isPrime(#factors(i)) then io.write(i .. "\t") end
end


Average loop length

Let f be a uniformly-randomly chosen mapping from the numbers 1..N to the numbers 1..N (note: not necessarily a permutation of 1..N; the mapping could produce a number in more than one way or not at all). At some point, the sequence 1, f(1), f(f(1))... will contain a repetition, a number that occurring for the second time in the sequence.

;Task:
Write a program or a script that estimates, for each N, the average length until the first such repetition.

Also calculate this expected length using an analytical formula, and optionally compare the simulated result with the theoretical one.

This problem comes from the end of Donald Knuth's Christmas tree lecture 2011.

Example of expected output:

 N    average    analytical    (error)
===  =========  ============  =========
  1     1.0000        1.0000  (  0.00%)
  2     1.4992        1.5000  (  0.05%)
  3     1.8784        1.8889  (  0.56%)
  4     2.2316        2.2188  (  0.58%)
  5     2.4982        2.5104  (  0.49%)
  6     2.7897        2.7747  (  0.54%)
  7     3.0153        3.0181  (  0.09%)
  8     3.2429        3.2450  (  0.07%)
  9     3.4536        3.4583  (  0.14%)
 10     3.6649        3.6602  (  0.13%)
 11     3.8091        3.8524  (  1.12%)
 12     3.9986        4.0361  (  0.93%)
 13     4.2074        4.2123  (  0.12%)
 14     4.3711        4.3820  (  0.25%)
 15     4.5275        4.5458  (  0.40%)
 16     4.6755        4.7043  (  0.61%)
 17     4.8877        4.8579  (  0.61%)
 18     4.9951        5.0071  (  0.24%)
 19     5.1312        5.1522  (  0.41%)
 20     5.2699        5.2936  (  0.45%)

Solution:
function average(n, reps)
  local count = 0
  for r = 1, reps do
    local f = {}
    for i = 1, n do f[i] = math.random(n) end
    local seen, x = {}, 1
    while not seen[x] do
      seen[x], x, count = true, f[x], count+1
    end
  end
  return count / reps
end

function analytical(n)
  local s, t = 1, 1
  for i = n-1, 1, -1 do t=t*i/n s=s+t end
  return s
end

print(" N    average    analytical    (error)")
print("===  =========  ============  =========")
for n = 1, 20 do
  local avg, ana = average(n, 1e6), analytical(n)
  local err = (avg-ana) / ana * 100
  print(string.format("%3d  %9.4f  %12.4f  (%6.3f%%)", n, avg, ana, err))
end


Averages/Mean angle

Solution:
function meanAngle (angleList)
  local sumSin, sumCos = 0, 0
  for i, angle in pairs(angleList) do
    sumSin = sumSin + math.sin(math.rad(angle))
    sumCos = sumCos + math.cos(math.rad(angle))
  end
  local result = math.deg(math.atan2(sumSin, sumCos))
  return string.format("%.2f", result)
end

print(meanAngle({350, 10}))
print(meanAngle({90, 180, 270, 360}))
print(meanAngle({10, 20, 30}))


Averages/Pythagorean means

Solution:
function fsum(f, a, ...) return a and f(a) + fsum(f, ...) or 0 end
function pymean(t, f, finv) return finv(fsum(f, unpack(t)) / #t) end
nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

--arithmetic
a = pymean(nums, function(n) return n end, function(n) return n end)
--geometric
g = pymean(nums, math.log, math.exp)
--harmonic
h = pymean(nums, function(n) return 1/n end, function(n) return 1/n end)
print(a, g, h)
assert(a >= g and g >= h)


Averages/Root mean square

Task

Compute the   Root mean square   of the numbers 1..10.

The   ''root mean square''   is also known by its initials RMS (or rms), and as the '''quadratic mean'''.

The RMS is calculated as the mean of the squares of the numbers, square-rooted:

::: x_{\mathrm{rms}} = \sqrt {{{x_1}^2 + {x_2}^2 + \cdots + {x_n}^2} \over n}.

;See also

{{Related tasks/Statistical measures}}

Solution:
function sumsq(a, ...) return a and a^2 + sumsq(...) or 0 end
function rms(t) return (sumsq(unpack(t)) / #t)^.5 end

print(rms{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})


Babbage problem

Charles Babbage
Charles Babbage's analytical engine.

Charles Babbage, looking ahead to the sorts of problems his Analytical Engine would be able to solve, gave this example:
{{quote
 | What is the smallest positive integer whose square ends in the digits 269,696?
 | Babbage, letter to Lord Bowden, 1837; see Hollingdale and Tootill, Electronic Computers, second edition, 1970, p. 125.
}}
He thought the answer might be 99,736, whose square is 9,947,269,696; but he couldn't be certain.

;Task

The task is to find out if Babbage had the right answer -- and to do so, as far as your language allows it, in code that Babbage himself would have been able to read and understand.
As Babbage evidently solved the task with pencil and paper, a similar efficient solution is preferred.

For these purposes, Charles Babbage may be taken to be an intelligent person, familiar with mathematics and with the idea of a computer; he has written the first drafts of simple computer programmes in tabular form. [Babbage Archive Series L].

;Motivation

The aim of the task is to write a program that is sufficiently clear and well-documented for such a person to be able to read it and be confident that it does indeed solve the specified problem.

Solution:
-- get smallest number <= sqrt(269696)
k = math.floor(math.sqrt(269696))

-- if root is odd -> make it even
if k % 2 == 1 then
    k = k - 1
end

-- cycle through numbers
while not ((k * k) % 1000000 == 269696) do
    k = k + 2
end

io.write(string.format("%d * %d = %d\n", k, k, k * k))


Balanced brackets

'''Task''':
* Generate a string with   '''N'''   opening brackets   '''['''   and with   '''N'''   closing brackets   ''']''',   in some arbitrary order.
* Determine whether the generated string is ''balanced''; that is, whether it consists entirely of pairs of opening/closing brackets (in that order), none of which mis-nest.

;Examples:
    (empty)      OK
    []           OK
    [][]         OK
    [[][]]       OK
    ][         NOT OK
    ][][       NOT OK
    []][[]     NOT OK

Solution:
function isBalanced(s)
  --Lua pattern matching has a 'balanced' pattern that matches sets of balanced characters.
  --Any two characters can be used.
  return s:gsub('%b[]','')=='' and true or false
end

function randomString()
  math.randomseed(os.time())
  math.random()math.random()math.random()math.random()
  local tokens={'[',']'}
  local result={}
  for i=1,8 do
    table.insert(result,tokens[math.random(1,2)])
  end
  return table.concat(result)
end

local RS=randomString()
print(RS)
print(isBalanced(RS))