Isqrt (integer square root) of X

Sometimes a function is needed to find the integer square root of   '''X''',   where   '''X'''   can be a
real non-negative number.

Often   '''X'''   is actually a non-negative integer.

For the purposes of this task,   '''X'''   can be an integer or a real number,   but if it
simplifies things in your computer programming language,   assume it's an integer.

One of the most common uses of   '''Isqrt'''   is in the division of an integer by all factors   (or
primes)   up to the
 X     of that
integer,   either to find the factors of that integer,   or to determine primality.

An alternative method for finding the   '''Isqrt'''   of a number is to
calculate:        floor( sqrt(X) )
::*   where    '''sqrt'''    is the   square root   function for non-negative real numbers,   and
::*   where   '''floor'''         is the   floor         function for real numbers.

If the hardware supports the computation of (real) square roots,   the above method might be a faster method for
small numbers that don't have very many significant (decimal) digits.

However, floating point arithmetic is limited in the number of   (binary or decimal)   digits that it can support.

;Pseudo-code using quadratic residue:
For this task, the integer square root of a non-negative number will be computed using a version
of   ''quadratic residue'',   which has the advantage that no   ''floating point''   calculations are
used,   only integer arithmetic.

Furthermore, the two divisions can be performed by bit shifting,   and the one multiplication can also be be performed by bit shifting or additions.

The disadvantage is the limitation of the size of the largest integer that a particular computer programming language can support.

Pseudo-code of a procedure for finding the integer square root of   '''X'''       (all variables are integers):
          q <-- 1                                /*initialize  Q  to unity.  */
                                   /*find a power of 4 that's greater than X.*/
                   perform  while q <= x         /*perform while  Q <= X.    */
                   q <-- q * 4                   /*multiply  Q  by  four.    */
                   end  /*perform*/
                                                 /*Q  is now greater than  X.*/
          z <-- x                                /*set  Z  to the value of X.*/
          r <-- 0                                /*initialize  R  to zero.   */
                   perform  while q > 1          /*perform while  Q > unity. */
                   q <-- q / 4                   /*integer divide by  four.  */
                   t <-- z - r - q               /*compute value of  T.      */
                   r <-- r / 2                   /*integer divide by  two.   */
                   if t >= 0  then do
                                   z <-- t       /*set  Z  to value of  T.   */
                                   r <-- r + q   /*compute new value of  R.  */
                                   end
                   end  /*perform*/
                                                 /*R  is now the  Isqrt(X).  */

          /* Sidenote: Also, Z is now the remainder after square root (i.e.  */
          /*           R^2 + Z = X, so if Z = 0 then X is a perfect square). */

Another version for the (above)   1st   '''perform'''   is:
                   perform  until q > X          /*perform until  Q > X.     */
                   q <-- q * 4                   /*multiply  Q  by  four.    */
                   end  /*perform*/

Integer square roots of some values:
 Isqrt( 0)  is   0               Isqrt(60)  is  7                Isqrt( 99)  is   9
 Isqrt( 1)  is   1               Isqrt(61)  is  7                Isqrt(100)  is  10
 Isqrt( 2)  is   1               Isqrt(62)  is  7                Isqrt(102)  is  10
 Isqrt( 3)  is   1               Isqrt(63)  is  7
 Isqrt( 4)  is   2               Isqrt(64)  is  8                Isqet(120)  is  10
 Isqrt( 5)  is   2               Isqrt(65)  is  8                Isqrt(121)  is  11
 Isqrt( 6)  is   2               Isqrt(66)  is  8                Isqrt(122)  is  11
 Isqrt( 7)  is   2               Isqrt(67)  is  8
 Isqrt( 8)  is   2               Isqrt(68)  is  8                Isqrt(143)  is  11
 Isqrt( 9)  is   3               Isqrt(69)  is  8                Isqrt(144)  is  12
 Isqrt(10)  is   3               Isqrt(70)  is  8                Isqrt(145)  is  12

;Task:
Compute and show all output here   (on this page)   for:
::*   the Isqrt of the     integers     from     '''0''' ---> '''65'''                (inclusive), shown in a       horizontal       format.
::*   the Isqrt of the   odd powers               from          '''71''' ---> '''773'''   (inclusive), shown in a   vertical   format.
::*   use commas in the displaying of larger numbers.

You can show more numbers for the 2nd requirement if the displays fits on one screen on Rosetta Code.
If your computer programming language only supports smaller integers,   show what you can.

;Related tasks:
:*   sequence of non-squares
:*   integer roots
:*   square root by hand

Solution:
function isqrt(x)
    local q = 1
    local r = 0
    while q <= x do
        q = q << 2
    end
    while q > 1 do
        q = q >> 2
        local t = x - r - q
        r = r >> 1
        if t >= 0 then
            x = t
            r = r + q
        end
    end
    return r
end

print("Integer square root for numbers 0 to 65:")
for n=0,65 do
    io.write(isqrt(n) .. ' ')
end
print()
print()

print("Integer square roots of oddd powers of 7 from 1 to 21:")
print(" n |              7 ^ n | isqrt(7 ^ n)")
local p = 7
local n = 1
while n <= 21 do
    print(string.format("%2d | %18d | %12d", n, p, isqrt(p)))
    ----------------------
    n = n + 2
    p = p * 49
end


Iterated digits squaring

If you add the square of the digits of a Natural number (an integer bigger than zero), you always end with either 1 or 89:
15 -> 26 -> 40 -> 16 -> 37 -> 58 -> 89
7 -> 49 -> 97 -> 130 -> 10 -> 1

An example in Python:

>>> step = lambda x: sum(int(d) ** 2 for d in str(x))
>>> iterate = lambda x: x if x in [1, 89] else iterate(step(x))
>>> [iterate(x) for x in xrange(1, 20)]
[1, 89, 89, 89, 89, 89, 1, 89, 89, 1, 89, 89, 1, 89, 89, 89, 89, 89, 1]

;Task:
: Count how many number chains for integers 1 <= n < 100_000_000 end with a value 89.
Or, for much less credit - (showing that your algorithm and/or language is slow):
: Count how many number chains for integers 1 <= n < 1_000_000 end with a value 89.

This problem derives from the Project Euler problem 92.

For a quick algorithm for this task see the talk page

;Related tasks:
* [[Combinations with repetitions]]
* [[Digital root]]
* [[Digital root/Multiplicative digital root]]

Solution:
squares = {}

for i = 0, 9 do
    for j = 0, 9 do
        squares[i * 10 + j] = i * i + j * j
    end
end

for i = 1, 99 do
    for j = 0, 99 do
        squares[i * 100 + j] = squares[i] + squares[j]
    end
end

function sum_squares(n)
    if n < 9999.5 then
        return squares[n]
    else
        local m = math.floor(n / 10000)
        return squares[n - 10000 * m] + sum_squares(m)
    end
end

memory = {}

function calc_1_or_89(n)
    local m = {}
    n = memory[n] or n
    while n ~= 1 and n ~= 89 do
        n = memory[n] or sum_squares(n)
        table.insert(m, n)
    end
    for _, i in pairs(m) do
        memory[i] = n
    end
    return n
end

counter = 0

for i = 1, 100000000 do
    if calc_1_or_89(i) == 89 then
        counter = counter + 1
    end
end

print(counter)


JSON

Load a JSON string into a data structure.
Also, create a new data structure and serialize it into JSON.

Use objects and arrays (as appropriate for your language)
and make sure your JSON is valid (https://jsonformatter.org).

Solution:
local json = require("json")

local json_data = [=[[
    42,
    3.14159,
    [ 2, 4, 8, 16, 32, 64, "apples", "bananas", "cherries" ],
    { "H": 1, "He": 2, "X": null, "Li": 3 },
    null,
    true,
    false
]]=]

print("Original JSON: " .. json_data)
local data = json.decode(json_data)
json.util.printValue(data, 'Lua')
print("JSON re-encoded: " .. json.encode(data))

local data = {
    42,
    3.14159,
    {
        2, 4, 8, 16, 32, 64,
        "apples",
        "bananas",
        "cherries"
    },
    {
        H = 1,
        He = 2,
        X = json.util.null(),
        Li = 3
    },
    json.util.null(),
    true,
    false
}

print("JSON from new Lua data: " .. json.encode(data))


Jewels and stones

Create a function which takes two string parameters: 'stones' and 'jewels' and returns an integer.

Both strings can contain any number of upper or lower case letters. However, in the case of 'jewels', all letters must be distinct.

The function should count (and return) how many 'stones' are 'jewels' or, in other words, how many letters in 'stones' are also letters in 'jewels'.

Note that:
:# Only letters in the ISO basic Latin alphabet i.e. 'A to Z' or 'a to z' need be considered.
:# A lower case letter is considered to be different from its upper case equivalent for this purpose, i.e., 'a' != 'A'.
:# The parameters do not need to have exactly the same names.
:# Validating the arguments is unnecessary.

So, for example, if passed "aAAbbbb" for 'stones' and "aA" for 'jewels', the function should return 3.

This task was inspired by this problem.

Solution:
function count_jewels(s, j)
    local count = 0
    for i=1,#s do
        local c = s:sub(i,i)
        if string.match(j, c) then
            count = count + 1
        end
    end
    return count
end

print(count_jewels("aAAbbbb", "aA"))
print(count_jewels("ZZ", "z"))


Julia set

Task
Generate and draw a Julia set.

;Related tasks
*   Mandelbrot Set

Solution:
local cmap = { [0]=" ", ".", ":", "-", "=", "+", "*", "#", "%", "$", "@" }
for y = -1.0, 1.0, 0.05 do
  for x = -1.5, 1.5, 0.025 do
    local zr, zi, i = x, y, 0
    while i < 100 do
      zr, zi = zr*zr - zi*zi - 0.79, zr * zi * 2 + 0.15
      if (zr*zr + zi*zi > 4) then break else i = i + 1 end
    end
    io.write(cmap[math.floor(i/10)])
  end
  print()
end


Jump anywhere

Imperative programs like to jump around, but some languages restrict these jumps. Many structured languages restrict their [[conditional structures]] and [[loops]] to ''local jumps'' within a function. Some assembly languages limit certain jumps or branches to a small range.

This task is to demonstrate a local jump and a global jump and the various other types of jumps that the language supports.
For the purpose of this task, the jumps need not be used for a single purpose and you have the freedom to use these jumps for different purposes.
You may also defer to more specific tasks, like [[Exceptions]] or [[Generator]].
This task provides a "grab bag" for several types of jumps. There are ''non-local jumps'' across function calls, or ''long jumps'' to anywhere within a program. Anywhere means not only to the tops of functions!

* Some languages can ''go to'' any global label in a program.
* Some languages can break multiple function calls, also known as ''unwinding the call stack''.
* Some languages can save a ''continuation''. The program can later continue from the same place. So you can jump anywhere, but only if you have a previous visit there (to save the continuation).

These jumps are not all alike.
A simple ''goto'' never touches the call stack.
A continuation saves the call stack, so you can continue a function call after it ends.

;Task:
Use your language to demonstrate the various types of jumps that it supports.

Because the possibilities vary by language, this task is not specific.
You have the freedom to use these jumps for different purposes.
You may also defer to more specific tasks, like [[Exceptions]] or [[Generator]].

Solution:
-- Forward jump
goto skip_print
print "won't print"
::skip_print::

-- Backward jump
::loop::
print "infinite loop"
goto loop

-- Labels follow the same scoping rules as local variables, but with no equivalent of upvalues
goto next
do
    ::next:: -- not visible to above goto
    print "won't print"
end
::next:: -- goto actually jumps here

-- goto cannot jump into or out of a function
::outside::
function nope () goto outside end -- error: no visible label 'outside' for <goto> at line 2

goto inside
function nope () ::inside:: end -- error: no visible label 'inside' for <goto> at line 1

-- Convenient for breaking out of nested loops
for i = 1, 10 do
    for j = 1, 10 do
        for k = 1, 10 do
            if i^2 + j^2 == k^2 then
                print(("found: i=%d j=%d k=%d"):format(i, j, k))
                goto exit
            end
        end
    end
end
print "not found"
::exit::


Kaprekar numbers

A positive integer is a Kaprekar number if:
* It is   '''1'''     (unity)
* The decimal representation of its square may be split once into two parts consisting of positive integers which sum to the original number.
Note that a split resulting in a part consisting purely of 0s is not valid,
as 0 is not considered positive.

;Example Kaprekar numbers:
* 2223 is a Kaprekar number, as 2223 * 2223 = 4941729, 4941729 may be split to 494 and 1729, and 494 + 1729 = 2223.
* The series of Kaprekar numbers is known as A006886, and begins as 1, 9, 45, 55, ....

;Example process:
10000 (1002) splitting from left to right:
* The first split is [1, 0000], and is invalid; the 0000 element consists entirely of 0s, and 0 is not considered positive.
* Slight optimization opportunity: When splitting from left to right, once the right part consists entirely of 0s, no further testing is needed; all further splits would also be invalid.

;Task:
Generate and show all Kaprekar numbers less than 10,000.

;Extra credit:
Optionally, count (and report the count of) how many Kaprekar numbers are less than 1,000,000.

;Extra extra credit:
The concept of Kaprekar numbers is not limited to base 10 (i.e. decimal numbers);
if you can, show that Kaprekar numbers exist in other bases too.

For this purpose, do the following:
* Find all Kaprekar numbers for base 17 between 1 and 1,000,000 (one million);
* Display each of them in base 10 representation;
* Optionally, using base 17 representation (use letters 'a' to 'g' for digits 10(10) to 16(10)), display each of the numbers, its square, and where to split the square.

For example, 225(10) is "d4" in base 17, its square "a52g", and a5(17) + 2g(17) = d4(17), so the display would be something like:225   d4  a52g  a5 + 2g

;Reference:
* The Kaprekar Numbers by Douglas E. Iannucci (2000). PDF version

;Related task:
*   [[Casting out nines]]

Solution:
-- Return length of an integer without string conversion
function numLength (n)
    local length = 0
    repeat
        n = math.floor(n / 10)
        length = length + 1
    until n == 0
    return length
end

-- Return a boolean indicating whether n is a Kaprekar number
function isKaprekar (n)
    if n == 1 then return true end
    local nSquared, a, b = n * n
    for splitPoint = 1, numLength(nSquared) - 1 do
        a = math.floor(nSquared / 10^splitPoint)
        b = nSquared % 10^splitPoint
        if a > 0 and b > 0 and a + b == n then return true end
    end
    return false
end

-- Main task
for n = 1, 10^4 do
    if isKaprekar(n) then io.write(n .. " ") end
end

-- Extra credit
local count = 0
for n = 1, 10^6 do
    if isKaprekar(n) then count = count + 1 end
end
print("\nThere are " .. count .. " Kaprekar numbers under one million.")


Kernighans large earthquake problem

Brian Kernighan, in a lecture at the University of Nottingham, described a problem on which this task is based.

;Problem:
You are given a a data file of thousands of lines; each of three `whitespace` separated fields: a date, a one word name and the magnitude of the event.

Example lines from the file would be lines like:
8/27/1883    Krakatoa            8.8
5/18/1980    MountStHelens       7.6
3/13/2009    CostaRica           5.1

;Task:
* Create a program or script invocation to find all the events with magnitude greater than 6
* Assuming an appropriate name e.g. "data.txt" for the file:
:# Either: Show how your program is invoked to process a data file of that name.
:# Or: Incorporate the file name into the program, (as it is assumed that the program is single use).

Solution:
-- arg[1] is the first argument provided at the command line
for line in io.lines(arg[1] or "data.txt") do  -- use data.txt if arg[1] is nil
  magnitude = line:match("%S+$")
  if tonumber(magnitude) > 6 then print(line) end
end


Knight's tour

Task
Problem: you have a standard 8x8 chessboard, empty but for a single knight on some square.   Your task is to emit a series of legal knight moves that result in the knight visiting every square on the chessboard exactly once. Note that it is ''not'' a requirement that the tour be "closed"; that is, the knight need not end within a single move of its start position.

Input and output may be textual or graphical, according to the conventions of the programming environment.  If textual, squares should be indicated in algebraic notation.  The output should indicate the order in which the knight visits the squares, starting with the initial position.  The form of the output may be a diagram of the board with the squares numbered according to visitation sequence, or a textual list of algebraic coordinates in order, or even an actual animation of the knight moving around the chessboard.

Input: starting square

Output: move sequence

;Related tasks
* [[A* search algorithm]]
* [[N-queens problem]]
* [[Solve a Hidato puzzle]]
* [[Solve a Holy Knight's tour]]
* [[Solve a Hopido puzzle]]
* [[Solve a Numbrix puzzle]]
* [[Solve the no connection puzzle]]

Solution:
N = 8

moves = { {1,-2},{2,-1},{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2} }

function Move_Allowed( board, x, y )
    if board[x][y] >= 8 then return false end

    local new_x, new_y = x + moves[board[x][y]+1][1], y + moves[board[x][y]+1][2]
    if new_x >= 1 and new_x <= N and new_y >= 1 and new_y <= N and board[new_x][new_y] == 0 then return true end

    return false
end

board = {}
for i = 1, N do
    board[i] = {}
    for j = 1, N do
        board[i][j] = 0
    end
end

x, y = 1, 1

lst = {}
lst[1] = { x, y }

repeat
    if Move_Allowed( board, x, y ) then
        board[x][y] = board[x][y] + 1
        x, y = x+moves[board[x][y]][1], y+moves[board[x][y]][2]
        lst[#lst+1] = { x, y }
    else
        if board[x][y] >= 8 then
            board[x][y] = 0
            lst[#lst] = nil
            if #lst == 0 then
                print "No solution found."
                os.exit(1)
            end
            x, y = lst[#lst][1], lst[#lst][2]
        end
        board[x][y] = board[x][y] + 1
    end
until #lst == N^2

last = lst[1]
for i = 2, #lst do
    print( string.format( "%s%d - %s%d", string.sub("ABCDEFGH",last[1],last[1]), last[2], string.sub("ABCDEFGH",lst[i][1],lst[i][1]), lst[i][2] ) )
    last = lst[i]
end


Koch curve

Draw a Koch curve. See details: Koch curve

Solution:
local cos, sin, floor, pi = math.cos, math.sin, math.floor, math.pi

function Bitmap:render()
  for y = 1, self.height do
    print(table.concat(self.pixels[y]))
  end
end

function Bitmap:drawKochPath(path, x, y, angle, speed, color)
  local rules = {
    ["+"] = function() angle = angle + pi/3 end,
    ["-"] = function() angle = angle - pi/3 end,
    ["F"] = function()
      local nx, ny = x+speed*cos(angle), y+speed*sin(angle)
      self:line(floor(x*2+0.5), floor(y+0.5), floor(nx*2+0.5), floor(ny+0.5), color)
      x, y = nx, ny
    end
  }
  path:gsub("(.)", function(c) rules[c]() end)
end

function LSystem(axiom, rules, reps)
  for i = 1, reps do
    axiom = axiom:gsub("(.)", function(c) return rules[c] or c end)
  end
  return axiom
end
function KochPath(reps) return LSystem("F--F--F--", { F = "F+F--F+F" }, reps) end

demos = {
  { n=0, w= 11, h= 6, x=1, y= 4 },
  { n=1, w= 22, h=14, x=1, y= 9 },
  { n=2, w= 60, h=34, x=1, y=24 },
  { n=3, w=168, h=96, x=1, y=71 }
}
for _,d in ipairs(demos) do
  bitmap = Bitmap(d.w, d.h)
  bitmap:clear(".")
  bitmap:drawKochPath(KochPath(d.n), d.x, d.y, 0, 3, "@")
  bitmap:render()
  print()
end


Kolakoski sequence

The natural numbers, (excluding zero); with the property that:
: ''if you form a new sequence from the counts of runs of the same number in the first sequence, this new sequence is the same as the first sequence''.

;Example:
This is ''not'' a Kolakoski sequence:
1,1,2,2,2,1,2,2,1,2,...
Its sequence of run counts, (sometimes called a run length encoding, (RLE); but a true RLE also gives the character that each run encodes), is calculated like this:

: Starting from the leftmost number of the sequence we have 2 ones, followed by 3 twos, then 1 ones, 2 twos, 1 one, ...

The above gives the RLE of:
2, 3, 1, 2, 1, ...

The original sequence is different from its RLE in this case. '''It would be the same for a true Kolakoski sequence'''.

;Creating a Kolakoski sequence:

Lets start with the two numbers (1, 2) that we will cycle through; i.e. they will be used in this order: 1,2,1,2,1,2,....

# We start the sequence s with the first item from the cycle c: 1
# An index, k, into the, (expanding), sequence will step, or index through each item of the sequence s from the first, at its own rate.
We will arrange that the k'th item of s states how many ''times'' the ''last'' item of sshould appear at the end of s.

We started s with 1 and therefore s[k] states that it should appear only the 1 time.

Increment k
Get the next item from c and append it to the end of sequence s. s will then become: 1, 2
k was moved to the second item in the list and s[k] states that it should appear two times, so append another of the last item to the sequence s: 1, 2,2
Increment k
Append the next item from the cycle to the list: 1, 2,2, 1
k is now at the third item in the list that states that the last item should appear twice so add another copy of the last item to the sequence s: 1, 2,2, 1,1
increment k

...

'''Note''' that the RLE of 1, 2, 2, 1, 1, ... begins 1, 2, 2 which is the beginning of the original sequence. The generation algorithm ensures that this will always be the case.

;Task:
# Create a routine/proceedure/function/... that given an initial ordered list/array/tuple etc of the natural numbers (1, 2), returns the next number from the list when accessed in a cycle.
# Create another routine that when given the initial ordered list (1, 2) and the minimum length of the sequence  to generate; uses the first routine and the algorithm above, to generate at least the requested first members of the kolakoski sequence.
# Create a routine that when given a sequence, creates the run length encoding of that sequence (as defined above) and returns the result of checking if sequence starts with the exact members of its RLE. (But ''note'', due to sampling, do not compare the last member of the RLE).
# Show, on this page, (compactly), the first 20 members of the sequence generated from (1, 2)
# Check the sequence againt its RLE.
# Show, on this page, the first 20 members of the sequence generated from (2, 1)
# Check the sequence againt its RLE.
# Show, on this page, the first 30 members of the Kolakoski sequence generated from (1, 3, 1, 2)
# Check the sequence againt its RLE.
# Show, on this page, the first 30 members of the Kolakoski sequence generated from (1, 3, 2, 1)
# Check the sequence againt its RLE.
(There are rules on generating Kolakoski sequences from this method that are broken by the last example)

Solution:
function next_in_cycle(c,length,index)
    local pos = index % length
    return c[pos]
end

function kolakoski(c,s,clen,slen)
    local i = 0
    local k = 0

    while true do
        s[i] = next_in_cycle(c,clen,k)
        if s[k] > 1 then
            for j=1,s[k]-1 do
                i = i + 1
                if i == slen then
                    return nil
                end
                s[i] = s[i - 1]
            end
        end
        i = i + 1
        if i == slen then
            return nil
        end
        k = k + 1
    end
    return nil
end

function possible_kolakoski(s,length)
    local j = 0
    local prev = s[0]
    local count = 1
    local rle = {}
    local result = "True"

    for i=0,length do
        rle[i] = 0
    end

    for i=1,length-1 do
        if s[i] == prev then
            count = count + 1
        else
            rle[j] = count
            j = j + 1
            count = 1
            prev = s[i]
        end
    end

    -- no point adding the final 'count' to rle as we're not going to compare it anyway
    for i=0,j-1 do
        if rle[i] ~= s[i] then
            result = "False"
            break
        end
    end

    return result
end

function print_array(a)
    io.write("[")
    for i=0,#a do
        if i>0 then
            io.write(", ")
        end
        io.write(a[i])
    end
    io.write("]")
end

-- main
local c0 =    {[0]=1,  [1]=2}
local c1 =    {[0]=2,  [1]=1}
local c2 =    {[0]=1,  [1]=3,  [2]=1,  [3]=2}
local c3 =    {[0]=1,  [1]=3,  [2]=2,  [3]=1}

local cs =    {[0]=c0, [1]=c1, [2]=c2, [3]=c3}
local clens = {[0]=2,  [1]=2,  [2]=4,  [3]=4}
local slens = {[0]=20, [1]=20, [2]=30, [3]=30}

for i=0,3 do
    local clen = clens[i]
    local slen = slens[i]
    local s = {}

    for j=0,slen-1 do
        s[j] = 0
    end

    kolakoski(cs[i],s,clen,slen)
    io.write(string.format("First %d members of the sequence generated by ", slen))
    print_array(cs[i])
    print(":")
    print_array(s)
    print()

    local p = possible_kolakoski(s,slen)
    print(string.format("Possible Kolakoski sequence? %s", p))

    print()
end


Kosaraju

{{wikipedia|Graph}}

Kosaraju's algorithm (also known as the Kosaraju-Sharir algorithm) is a linear time algorithm to find the strongly connected components of a directed graph. Aho, Hopcroft and Ullman credit it to an unpublished paper from 1978 by S. Rao Kosaraju. The same algorithm was independently discovered by Micha Sharir and published by him in 1981. It makes use of the fact that the transpose graph (the same graph with the direction of every edge reversed) has exactly the same strongly connected components as the original graph.

For this task consider the directed graph with these connections:
  0 -> 1
  1 -> 2
  2 -> 0
  3 -> 1,  3 -> 2,  3 -> 4
  4 -> 3,  4 -> 5
  5 -> 2,  5 -> 6
  6 -> 5
  7 -> 4, 7  -> 6, 7 -> 7

And report the kosaraju strongly connected component for each node.

;References:
* The article on Wikipedia.

Solution:
function write_array(a)
    io.write("[")
    for i=0,#a do
        if i>0 then
            io.write(", ")
        end
        io.write(tostring(a[i]))
    end
    io.write("]")
end

function kosaraju(g)
    -- 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
    local size = #g

    local vis = {}
    for i=0,size do
        -- all false by default
        vis[i] = false
    end

    local l = {}
    for i=0,size do
        -- all zero by default
        l[i] = 0
    end

    local x = size+1  -- index for filling l in reverse order

    local t = {}    -- transpose graph

    -- Recursive subroutine 'visit'
    function visit(u)
        if not vis[u] then
            vis[u] = true
            for i=0,#g[u] do
                local v = g[u][i]
                visit(v)
                if t[v] then
                    local a = t[v]
                    a[#a+1] = u
                else
                    t[v] = {[0]=u}
                end
            end
            x = x - 1
            l[x] = u
        end
    end

    -- 2. For each vertex u of the graph do visit(u)
    for i=0,#g do
        visit(i)
    end
    local c = {}
    for i=0,size do
        -- used for component assignment
        c[i] = 0
    end

    -- Recursive subroutine 'assign'
    function assign(u, root)
        if vis[u] then  -- repurpose vis to mean 'unassigned'
            vis[u] = false
            c[u] = root
            for i=0,#t[u] do
                local v = t[u][i]
                assign(v, root)
            end
        end
    end

    -- 3: For each element u of l in order, do assign(u, u)
    for i=0,#l do
        local u = l[i]
        assign(u, u)
    end

    return c
end

-- main
local g = {
    [0]={[0]=1},
    [1]={[0]=2},
    [2]={[0]=0},
    [3]={[0]=1, [1]=2, [2]=4},
    [4]={[0]=3, [1]=5},
    [5]={[0]=2, [1]=6},
    [6]={[0]=5},
    [7]={[0]=4, [1]=6, [2]=7},
}

write_array(kosaraju(g))
print()


Largest int from concatenated ints

Given a set of positive integers, write a function to order the integers in such a way that the concatenation of the numbers forms the largest possible integer and return this integer.

Use the following two sets of integers as tests   and   show your program output here.

:::::*   {1, 34, 3, 98, 9, 76, 45, 4}
:::::*   {54, 546, 548, 60}

;Possible algorithms:
# A solution could be found by trying all combinations and return the best.
# Another way to solve this is to note that in the best arrangement, for any two adjacent original integers '''X''' and '''Y''', the concatenation '''X''' followed by '''Y''' will be numerically greater than or equal to the concatenation '''Y''' followed by '''X.
# Yet another way to solve this is to pad the integers to the same size by repeating the digits then sort using these repeated integers as a sort key.

;See also:
*   Algorithms: What is the most efficient way to arrange the given numbers to form the biggest number?
*   Constructing the largest number possible by rearranging a list

Solution:
function icsort(numbers)
	table.sort(numbers,function(x,y) return (x..y) > (y..x) end)
	return numbers
end

for _,numbers in pairs({{1, 34, 3, 98, 9, 76, 45, 4}, {54, 546, 548, 60}}) do
	print(('Numbers: {%s}\n  Largest integer: %s'):format(
		table.concat(numbers,","),table.concat(icsort(numbers))
	))
end


Largest number divisible by its digits

Find the largest base 10 integer whose digits are all different,   and   is evenly divisible by each of its individual digits.

These numbers are also known as   '''Lynch-Bell numbers''',   numbers   '''n'''   such that the
(base ten) digits are all different (and do not include zero)   and   '''n'''   is divisible by each of its individual digits.

;Example:
'''135'''   is evenly divisible by   '''1''',   '''3''',   and   '''5'''.

Note that the digit zero (0) can not be in the number as integer division by zero is undefined.

The digits must all be unique so a base ten number will have at most '''9''' digits.

Feel free to use analytics and clever algorithms to reduce the search space your example needs to visit, but it must do an actual search. (Don't just feed it the answer and verify it is correct.)

;Stretch goal:
Do the same thing for hexadecimal.

;Related tasks:
:*   gapful numbers.
:*   palindromic gapful numbers.

;Also see:
:*   The OEIS sequence:   A115569: Lynch-Bell numbers.

Solution:
function isDivisible(n)
    local t = n
    local a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    while t ~= 0 do
        local r = t % 10
        if r == 0 then
            return false
        end
        if n % r ~= 0 then
            return false
        end
        if a[r + 1] > 0 then
            return false
        end
        a[r + 1] = 1
        t = math.floor(t / 10)
    end

    return true
end

for i=9999999999,0,-1 do
    if isDivisible(i) then
        print(i)
        break
    end
end


Last Friday of each month

Write a program or a script that returns the date of the last Fridays of each month of a given year.

The year may be given through any simple input method in your language (command line, std in, etc).

Example of an expected output:
./last_fridays 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

;Related tasks
* [[Five weekends]]
* [[Day of the week]]
* [[Find the last Sunday of each month]]

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

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

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

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


Last letter-first letter

A certain children's game involves starting with a word in a particular category.   Each participant in turn says a word, but that word must begin with the final letter of the previous word.   Once a word has been given, it cannot be repeated.   If an opponent cannot give a word in the category, they fall out of the game.

For example, with   "animals"   as the category,

Child 1: dog
Child 2: goldfish
Child 1: hippopotamus
Child 2: snake
...

;Task:
Take the following selection of 70 English Pokemon names   (extracted from   Wikipedia's list of Pokemon)   and generate the/a sequence with the highest possible number of Pokemon names where the subsequent name starts with the final letter of the preceding name.

No Pokemon name is to be repeated.

audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask

Extra brownie points for dealing with the full list of   646   names.

Solution:
-- BUILDING:
pokemon = [[
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask]]
words, inits, succs = {}, {}, {}
for word in pokemon:gmatch("%S+") do
  table.insert(words, word)
  local ch = word:sub(1,1)
  inits[ch] = inits[ch] or {}
  table.insert(inits[ch], word)
end
for _,word in pairs(words) do
  succs[word] = {}
  local ch = word:sub(-1,-1)
  if inits[ch] then
    for _,succ in pairs(inits[ch]) do
      if succ~=word then
        table.insert(succs[word],succ)
      end
    end
  end
end

-- SEARCHING:
function expand(list, used, answer)
  local word = list[#list]
  for _,succ in ipairs(succs[word]) do
    if not used[succ] then
      used[succ] = true
      list[#list+1] = succ
      if #list == answer.len then
        local perm = table.concat(list," ")
        answer.perms[perm] = perm
        answer.num = answer.num + 1
      elseif #list > answer.len then
        answer.len = #list
        local perm = table.concat(list," ")
        answer.perms = {[perm] = perm}
        answer.num = 1
      end
      expand(list, used, answer)
      list[#list] = nil
      used[succ] = nil
    end
  end
end
answers = {}
for _,word in ipairs(words) do
  local answer = { word=word, len=0, num=0, perms={} }
  answers[#answers+1] = answer
  expand({word}, {[word]=true}, answer)
end

-- REPORTING:
table.sort(answers, function(a,b) return a.len<b.len or (a.len==b.len and a.word<b.word) end)
print("first word   length   count   example")
print("----------   ------   -----   -------...")
for _,answer in pairs(answers) do
  local perm = next(answer.perms) or ""
  print(string.format("%10s   %6d   %5d   %s", answer.word, answer.len, answer.num, perm))
end


Law of cosines - triples

The Law of cosines states that for an angle g, (gamma) of any triangle, if the sides adjacent to the angle are A and B and the side opposite is C; then the lengths of the sides are related by this formula:
           A2 + B2 - 2ABcos(g) = C2

;Specific angles:
For an angle of of   '''90o'''   this becomes the more familiar "Pythagoras equation":
           A2 + B2  =  C2

For an angle of   '''60o'''   this becomes the less familiar  equation:
           A2 + B2 - AB  =  C2

And finally for an angle of   '''120o'''   this becomes the equation:
           A2 + B2 + AB  =  C2

;Task:
*   Find all integer solutions (in order) to the three specific cases, distinguishing between each angle being considered.
*   Restrain all sides to the integers   '''1..13'''   inclusive.
*   Show how many results there are for each of the three angles mentioned above.
*   Display results on this page.

Note: Triangles with the same length sides but different order are to be treated as the same.

;Optional Extra credit:
* How many 60deg integer triples are there for sides in the range 1..10_000 ''where the sides are not all of the same length''.

;Related Task
* [[Pythagorean triples]]

;See also:
* Visualising Pythagoras: ultimate proofs and crazy contortions Mathlogger Video

Solution:
function solve(angle, maxlen, filter)
  local squares, roots, solutions = {}, {}, {}
  local cos2 = ({[60]=-1,[90]=0,[120]=1})[angle]
  for i = 1, maxlen do squares[i], roots[i^2] = i^2, i end
  for a = 1, maxlen do
    for b = a, maxlen do
      local lhs = squares[a] + squares[b] + cos2*a*b
      local c = roots[lhs]
      if c and (not filter or filter(a,b,c)) then
        solutions[#solutions+1] = {a=a,b=b,c=c}
      end
    end
  end
  print(angle.."° on 1.."..maxlen.." has "..#solutions.." solutions")
  if not filter then
    for i,v in ipairs(solutions) do print("",v.a,v.b,v.c) end
  end
end
solve(90, 13)
solve(60, 13)
solve(120, 13)
function fexcr(a,b,c) return a~=b or b~=c end
solve(60, 10000, fexcr)  -- extra credit
solve(90, 10000, fexcr)  -- more extra credit
solve(120, 10000, fexcr) -- even more extra credit


Least common multiple

Compute the   least common multiple   (LCM)   of two integers.

Given   ''m''   and   ''n'',   the least common multiple is the smallest positive integer that has both   ''m''   and   ''n''   as factors.

;Example:
The least common multiple of   '''12'''   and   '''18'''   is   '''36''',       because:
:*   '''12'''   is a factor     ('''12''' x '''3''' = '''36'''),     and
:*   '''18'''   is a factor     ('''18''' x '''2''' = '''36'''),     and
:*   there is no positive integer less than   '''36'''   that has both factors.

As a special case,   if either   ''m''   or   ''n''   is zero,   then the least common multiple is zero.

One way to calculate the least common multiple is to iterate all the multiples of   ''m'',   until you find one that is also a multiple of   ''n''.

If you already have   ''gcd''   for [[greatest common divisor]],   then this formula calculates   ''lcm''.

:::: \operatorname{lcm}(m, n) = \frac{|m \times n|}{\operatorname{gcd}(m, n)}

One can also find   ''lcm''   by merging the [[prime decomposition]]s of both   ''m''   and   ''n''.

;Related task
:*   greatest common divisor.

;See also:
*   MathWorld entry:   Least Common Multiple.
*   Wikipedia entry:   Least common multiple.

Solution:
function gcd( m, n )
    while n ~= 0 do
        local q = m
        m = n
        n = q % n
    end
    return m
end

function lcm( m, n )
    return ( m ~= 0 and n ~= 0 ) and m * n / gcd( m, n ) or 0
end

print( lcm(12,18) )


Left factorials

'''Left factorials''',   !n,   may refer to either   ''subfactorials''   or to   ''factorial sums'';
the same notation can be confusingly seen being used for the two different definitions.

Sometimes,   ''subfactorials''   (also known as ''derangements'')   may use any of the notations:
:::::::*     !''n''`
:::::::*     !''n''
:::::::*     ''n''!

(It may not be visually obvious, but the last example uses an upside-down exclamation mark.)

This Rosetta Code task will be using this formula   (''factorial sums'')   for   '''left factorial''':

:::::    !n = \sum_{k=0}^{n-1} k!

:::: where

:::::   !0 = 0

;Task
Display the left factorials for:
*   zero      through        ten     (inclusive)
*   20   through   110          (inclusive)   by tens

Display the length (in decimal digits) of the left factorials for:
*   1,000   through   10,000   (inclusive), by thousands.

;Also see:
*   The OEIS entry: A003422 left factorials
*   The MathWorld entry: left factorial
*   The MathWorld entry: factorial sums
*   The MathWorld entry: subfactorial

;Related task:
*   permutations/derangements (subfactorials)

Solution:
-- Lua bindings for GNU bc
require("bc")

-- Return table of factorials from 0 to n
function facsUpTo (n)
    local f, fList = bc.number(1), {}
    fList[0] = 1
    for i = 1, n do
        f = bc.mul(f, i)
        fList[i] = f
    end
    return fList
end

-- Return left factorial of n
function leftFac (n)
    local sum = bc.number(0)
    for k = 0, n - 1 do sum = bc.add(sum, facList[k]) end
    return bc.tostring(sum)
end

-- Main procedure
facList = facsUpTo(10000)
for i = 0, 10 do print("!" .. i .. " = " .. leftFac(i)) end
for i = 20, 110, 10 do print("!" .. i .. " = " .. leftFac(i)) end
for i = 1000, 10000, 1000 do
    print("!" .. i .. " contains " .. #leftFac(i) .. " digits")
end


Levenshtein distance

{{Wikipedia}}

In information theory and computer science, the '''Levenshtein distance''' is a edit distance). The Levenshtein distance between two strings is defined as the minimum number of edits needed to transform one string into the other, with the allowable edit operations being insertion, deletion, or substitution of a single character.

;Example:
The Levenshtein distance between "'''kitten'''" and "'''sitting'''" is 3, since the following three edits change one into the other, and there isn't a way to do it with fewer than three edits:
::#   '''k'''itten    '''s'''itten       (substitution of 'k' with 's')
::#   sitt'''e'''n    sitt'''i'''n       (substitution of 'e' with 'i')
::#   sittin          sittin'''g'''      (insert 'g' at the end).

''The Levenshtein distance between   "'''rosettacode'''",   "'''raisethysword'''"   is   '''8'''.

''The distance between two strings is same as that when both strings are reversed.''

;Task:
Implements a Levenshtein distance function, or uses a library function, to show the Levenshtein distance between   "kitten"   and   "sitting".

;Related task:
*   [[Longest common subsequence]]

Solution:
function leven(s,t)
    if s == '' then return t:len() end
    if t == '' then return s:len() end

    local s1 = s:sub(2, -1)
    local t1 = t:sub(2, -1)

    if s:sub(0, 1) == t:sub(0, 1) then
        return leven(s1, t1)
    end

    return 1 + math.min(
        leven(s1, t1),
        leven(s,  t1),
        leven(s1, t )
      )
end

print(leven("kitten", "sitting"))
print(leven("rosettacode", "raisethysword"))


List rooted trees

You came back from grocery shopping.    After putting away all the goods, you are left with a pile of plastic bags, which you want to save for later use, so you take one bag and stuff all the others into it, and throw it under the sink.   In doing so, you realize that there are various ways of nesting the bags, with all bags viewed as identical.

If we use a matching pair of parentheses to represent a bag, the ways are:

For 1 bag, there's one way:
  ()	<- a bag

for 2 bags, there's one way:
  (())	<- one bag in another

for 3 bags, there are two:
  ((())) <- 3 bags nested Russian doll style
  (()()) <- 2 bags side by side, inside the third

for 4 bags, four:
  (()()())
  ((())())
  ((()()))
  (((())))

Note that because all bags are identical, the two 4-bag strings ((())()) and (()(())) represent the same configuration.

It's easy to see that each configuration for ''n'' bags represents a ''n''-node rooted tree, where a bag is a tree node, and a bag with its content forms a subtree.  The outermost bag is the tree root.  Number of configurations for given ''n'' is given by OEIS A81.

;Task:
Write a program that, when given ''n'', enumerates all ways of nesting ''n'' bags.   You can use the parentheses notation above, or any tree representation that's unambiguous and preferably intuitive.

This task asks for enumeration of trees only; for counting solutions without enumeration, that OEIS page lists various formulas, but that's not encouraged by this task, especially if implementing it would significantly increase code size.

As an example output, run 5 bags.   There should be 9 ways.

Solution:
tree_list = {}
offset = {}

function init()
    for i=1,32 do
        if i == 2 then
            table.insert(offset, 1)
        else
            table.insert(offset, 0)
        end
    end
end

function append(t)
    local v = 1 | (t << 1)
    table.insert(tree_list, v)
end

function show(t, l)
    while l > 0 do
        l = l - 1
        if (t % 2) == 1 then
            io.write('(')
        else
            io.write(')')
        end
        t = t >> 1
    end
end

function listTrees(n)
    local i = offset[n]
    while i < offset[n + 1] do
        show(tree_list[i + 1], n * 2)
        print()
        i = i + 1
    end
end

function assemble(m, t, sl, pos, rem)
    if rem == 0 then
        append(t)
        return
    end

    local pp = pos
    local ss = sl

    if sl > rem then
        ss = rem
        pp = offset[ss]
    elseif pp >= offset[ss + 1] then
        ss = ss - 1
        if ss == 0 then
            return
        end
        pp = offset[ss]
    end

    assemble(n, t << (2 * ss) | tree_list[pp + 1], ss, pp, rem - ss)
    assemble(n, t, ss, pp + 1, rem)
end

function makeTrees(n)
    if offset[n + 1] ~= 0 then
        return
    end
    if n > 0 then
        makeTrees(n - 1)
    end
    assemble(n, 0, n - 1, offset[n - 1], n - 1)
    offset[n + 1] = #tree_list
end

function test(n)
    append(0)

    makeTrees(n)
    print(string.format("Number of %d-trees: %d", n, offset[n+1] - offset[n]))
    listTrees(n)
end

init()
test(5)


Long literals, with continuations

This task is about writing a computer program that has long literals   (character
literals that may require specifying the words/tokens on more than one (source)
line,   either with continuations or some other method, such as abutments or
concatenations   (or some other mechanisms).

The literal is to be in the form of a "list",    a literal that contains many
words (tokens) separated by a blank (space),   in this case   (so as to have a
common list),   the (English) names of the chemical elements of the periodic table.

The list is to be in (ascending) order of the (chemical) element's atomic number:

 ''hydrogen helium lithium beryllium boron carbon nitrogen oxygen fluorine neon sodium aluminum silicon ...''

... up to the last known (named) chemical element   (at this time).

Do not include any of the   "unnamed"   chemical element names such as:

 ''ununennium unquadnilium triunhexium penthextrium penthexpentium septhexunium octenntrium ennennbium''

To make computer programming languages comparable,   the statement widths should be
restricted to less than   '''81'''   bytes (characters),   or less
if a computer programming language has more restrictive limitations or standards.

Also mention what column the programming statements can start in if   ''not''
in column one.

The list   ''may''   have leading/embedded/trailing blanks during the
declaration   (the actual program statements),   this is allow the list to be
more readable.   The "final" list shouldn't have any leading/trailing or superfluous
blanks   (when stored in the program's "memory").

This list should be written with the idea in mind that the
program   ''will''   be updated,   most likely someone other than the
original author,   as there will be newer (discovered) elements of the periodic
table being added   (possibly in the near future).   These future updates
should be one of the primary concerns in writing these programs and it should be "easy"
for someone else to add chemical elements to the list   (within the computer
program).

Attention should be paid so as to not exceed the   ''clause length''   of
continued or specified statements,   if there is such a restriction.   If the
limit is greater than (say) 4,000 bytes or so,   it needn't be mentioned here.

;Task:
:*   Write a computer program (by whatever name) to contain a list of the known elements.
:*   The program should eventually contain a long literal of words   (the elements).
:*   The literal should show how one could create a long list of blank-delineated words.
:*   The "final" (stored) list should only have a single blank between elements.
:*   Try to use the most idiomatic approach(es) in creating the final list.
:*   Use continuation if possible, and/or show alternatives   (possibly using concatenation).
:*   Use a program comment to explain what the continuation character is if it isn't obvious.
:*   The program should contain a variable that has the date of the last update/revision.
:*   The program, when run, should display with verbiage:
:::*   The last update/revision date   (and should be unambiguous).
:::*   The number of chemical elements in the list.
:::*   The name of the highest (last) element name.

Show all output here, on this page.

Solution:
revised = "February 2, 2021"
-- the long literal string is delimited by double square brackets: [[...]]
-- each word must be separated by at least one whitespace character
-- additional whitespace may optionally be used to improve readability
-- (starting column does not matter, clause length is more than adequate)
longliteral = [[
    hydrogen     helium        lithium      beryllium
    boron        carbon        nitrogen     oxygen
    fluorine     neon          sodium       magnesium
    aluminum     silicon       phosphorous  sulfur
    chlorine     argon         potassium    calcium
    scandium     titanium      vanadium     chromium
    manganese    iron          cobalt       nickel
    copper       zinc          gallium      germanium
    arsenic      selenium      bromine      krypton
    rubidium     strontium     yttrium      zirconium
    niobium      molybdenum    technetium   ruthenium
    rhodium      palladium     silver       cadmium
    indium       tin           antimony     tellurium
    iodine       xenon         cesium       barium
    lanthanum    cerium        praseodymium neodymium
    promethium   samarium      europium     gadolinium
    terbium      dysprosium    holmium      erbium
    thulium      ytterbium     lutetium     hafnium
    tantalum     tungsten      rhenium      osmium
    iridium      platinum      gold         mercury
    thallium     lead          bismuth      polonium
    astatine     radon         francium     radium
    actinium     thorium       protactinium uranium
    neptunium    plutonium     americium    curium
    berkelium    californium   einsteinium  fermium
    mendelevium  nobelium      lawrencium   rutherfordium
    dubnium      seaborgium    bohrium      hassium
    meitnerium   darmstadtium  roentgenium  copernicium
    nihonium     flerovium     moscovium    livermorium
    tennessine   oganesson
]]
-- the task requires the "final list" as single-space-between string version
-- (a more idiomatic overall approach would be to directly split into a table)
finallist = longliteral:gsub("%s+"," ")

elements = {}
-- longliteral could be used here DIRECTLY instead of using finallist:
for name in finallist:gmatch("%w+") do elements[#elements+1]=name end
print("revised date:  " .. revised)
print("# elements  :  " .. #elements)
print("last element:  " .. elements[#elements])

-- then, if still required, produce a single-space-between string version:
--finallist = table.concat(elements," ")


Longest common subsequence

'''Introduction'''

Define a ''subsequence'' to be any output string obtained by deleting zero or more symbols from an input string.

The '''Longest Common Subsequence''' ('''LCS''') is a subsequence of maximum length common to two or more strings.

Let ''A''  ''A''[0]... ''A''[m - 1] and ''B''  ''B''[0]... ''B''[n - 1], m < n be strings drawn from an alphabet S of size s, containing every distinct symbol in A + B.

An ordered pair (i, j) will be referred to as a match if ''A''[i] = ''B''[j], where 0 <= i < m and 0 <= j < n.

The set of matches '''M''' defines a relation over matches: '''M'''[i, j] = (i, j)  '''M'''.

Define a ''non-strict'' product-order (<=) over ordered pairs, such that (i1, j1) <= (i2, j2) = i1 <= i2 and j1 <= j2.  We define (>=) similarly.

We say ordered pairs p1 and p2 are ''comparable'' if either p1 <= p2 or p1 >= p2 holds.  If i1 < i2 and j2 < j1 (or i2 < i1 and j1 < j2) then neither p1 <= p2 nor p1 >= p2 are possible, and we say p1 and p2 are ''incomparable''.

Define the ''strict'' product-order (<) over ordered pairs, such that (i1, j1) < (i2, j2) = i1 < i2 and j1 < j2.  We define (>) similarly.

A chain '''C''' is a subset of '''M''' consisting of at least one element m; and where either m1 < m2 or m1 > m2 for every pair of distinct elements m1 and m2.  An antichain '''D''' is any subset of '''M''' in which every pair of distinct elements m1 and m2 are incomparable.

A chain can be visualized as a strictly increasing curve that passes through matches (i, j) in the m*n coordinate space of '''M'''[i, j].

Every Common Sequence of length ''q'' corresponds to a chain of cardinality ''q'', over the set of matches '''M'''.  Thus, finding an LCS can be restated as the problem of finding a chain of maximum cardinality ''p''.

According to [Dilworth 1950], this cardinality ''p'' equals the minimum number of disjoint antichains into which '''M''' can be decomposed.  Note that such a decomposition into the minimal number p of disjoint antichains may not be unique.

'''Background'''

Where the number of symbols appearing in matches is small relative to the length of the input strings, reuse of the symbols increases; and the number of matches will tend towards O(''m*n'') quadratic growth.  This occurs, for example, in the Bioinformatics application of nucleotide and protein sequencing.

The divide-and-conquer approach of [Hirschberg 1975] limits the space required to O(''n'').  However, this approach requires O(''m*n'') time even in the best case.

This quadratic time dependency may become prohibitive, given very long input strings.  Thus, heuristics are often favored over optimal Dynamic Programming solutions.

In the application of comparing file revisions, records from the input files form a large symbol space; and the number of symbols approaches the length of the LCS.  In this case the number of matches reduces to linear, O(''n'') growth.

A binary search optimization due to [Hunt and Szymanski 1977] can be applied to the basic Dynamic Programming approach, resulting in an expected performance of O(''n log m'').  Performance can degrade to O(''m*n log m'') time in the worst case, as the number of matches grows to O(''m*n'').

'''Note'''

[Rick 2000] describes a linear-space algorithm with a time bound of O(''n*s + p*min(m, n - p)'').

'''Legend'''

 A, B are input strings of lengths m, n respectively
 p is the length of the LCS
 M is the set of matches (i, j) such that A[i] = B[j]
 r is the magnitude of M
 s is the magnitude of the alphabet S of distinct symbols in A + B

'''References'''

[Dilworth 1950] "A decomposition theorem for partially ordered sets"
by Robert P. Dilworth, published January 1950,
Annals of Mathematics [Volume 51, Number 1, ''pp.'' 161-166]

[Goeman and Clausen 2002] "A New Practical Linear Space Algorithm for the Longest Common
Subsequence Problem" by Heiko Goeman and Michael Clausen,
published 2002, Kybernetika [Volume 38, Issue 1, ''pp.'' 45-66]

[Hirschberg 1975] "A linear space algorithm for computing maximal common subsequences"
by Daniel S. Hirschberg, published June 1975
Communications of the ACM [Volume 18, Number 6, ''pp.'' 341-343]

[Hunt and McIlroy 1976] "An Algorithm for Differential File Comparison"
by James W. Hunt and M. Douglas McIlroy, June 1976
Computing Science Technical Report, Bell Laboratories 41

[Hunt and Szymanski 1977] "A Fast Algorithm for Computing Longest Common Subsequences"
by James W. Hunt and Thomas G. Szymanski, published May 1977
Communications of the ACM [Volume 20, Number 5, ''pp.'' 350-353]

[Rick 2000] "Simple and fast linear space computation of longest common subsequences"
by Claus Rick, received 17 March 2000, Information Processing Letters,
Elsevier Science [Volume 75, ''pp.'' 275-281]

'''Examples'''

The sequences "1234" and "1224533324" have an LCS of "1234":
 '''1234'''
 '''12'''245'''3'''332'''4'''

For a string example, consider the sequences "thisisatest" and "testing123testing". An LCS would be "tsitest":
 '''t'''hi'''si'''sa'''test'''
 '''t'''e'''s'''t'''i'''ng123'''test'''ing

In this puzzle, your code only needs to deal with strings. Write a function which returns an LCS of two strings (case-sensitive). You don't need to show multiple LCS's.

For more information on this problem please see Wikipedia.

Solution:
function LCS( a, b )
    if #a == 0 or #b == 0 then
        return ""
    elseif string.sub( a, -1, -1 ) == string.sub( b, -1, -1 ) then
        return LCS( string.sub( a, 1, -2 ), string.sub( b, 1, -2 ) ) .. string.sub( a, -1, -1 )
    else
        local a_sub = LCS( a, string.sub( b, 1, -2 ) )
        local b_sub = LCS( string.sub( a, 1, -2 ), b )

        if #a_sub > #b_sub then
            return a_sub
        else
            return b_sub
        end
    end
end

print( LCS( "thisisatest", "testing123testing" ) )


Longest increasing subsequence

Calculate and show here a longest increasing subsequence of the list:
:\{3, 2, 6, 4, 5, 1\}
And of the list:
:\{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15\}

Note that a list may have more than one subsequence that is of the maximum length.

;Ref:
# Dynamic Programming #1: Longest Increasing Subsequence on YouTube
# An efficient solution can be based on Patience sorting.

Solution:
function buildLIS(seq)
    local piles = { { {table.remove(seq, 1), nil} } }
    while #seq>0 do
        local x=table.remove(seq, 1)
        for j=1,#piles do
            if piles[j][#piles[j]][1]>x then
                table.insert(piles[j], {x, (piles[j-1] and #piles[j-1])})
                break
            elseif j==#piles then
                table.insert(piles, {{x, #piles[j]}})
            end
        end
    end
    local t={}
    table.insert(t, piles[#piles][1][1])
    local p=piles[#piles][1][2]
    for i=#piles-1,1,-1 do
        table.insert(t, piles[i][p][1])
        p=piles[i][p][2]
    end
    table.sort(t)
    print(unpack(t))
end

buildLIS({3,2,6,4,5,1})
buildLIS({0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15})


MAC vendor lookup

Every connected device around the world comes with a unique Media Access Control address, or a   MAC address.

A common task a network administrator may come across is being able to identify a network device's manufacturer when given only a MAC address.

;Task:
Interface with one (or numerous) APIs that exist on the internet and retrieve the device manufacturer based on a supplied MAC address.

A MAC address that does not return a valid result should return the String "N/A".   An error related to the network connectivity or the API should return a null result.

Many implementations on this page use http://api.macvendors.com/ which, as of 19th September 2021, is throttling requests. After only 2 calls, the following response is returned for all subsequent requests. If you are planning to use the same provider or going to run the examples on this page, consider building in a delay between two calls.

'''{"errors":{"detail":"Too Many Requests","message":"Please slow down your requests or upgrade your plan at https://macvendors.com"}}'''

Solution:
-- Requires LuaSocket extension by Lua
-- Created by James A. Donnell Jr.
-- www.JamesDonnell.com

local baseURL = "http://api.macvendors.com/"

local function lookup(macAddress)
	http = require "socket.http"
	result, statuscode, content = http.request(baseURL .. macAddress)
	return result
end

local macAddress = "FC-A1-3E-2A-1C-33"
print(lookup(macAddress))


Mad Libs

{{wikipedia}}

Mad Libs is a phrasal template word game where one player prompts another for a list of words to substitute for blanks in a story, usually with funny results.

;Task;
Write a program to create a Mad Libs like story.

The program should read an arbitrary multiline story from input.

The story will be terminated with a blank line.

Then, find each replacement to be made within the story, ask the user for a word to replace it with, and make all the replacements.

Stop when there are none left and print the final story.

The input should be an arbitrary story in the form:

 went for a walk in the park.
found a .  decided to take it home.

Given this example, it should then ask for a name, a he or she and a noun ( gets replaced both times with the same value).

Solution:
print("Enter a multi-line story (finish with blank line):")
dict, story, line = {}, "", io.read()
while #line>0 do story=story..line.."\n" line=io.read() end
story = story:gsub("(%<.-%>)", function(what)
  if dict[what] then return dict[what] end
  io.write("Please enter a " .. what .. ":  ")
  dict[what] = io.read()
  return dict[what]
  end)
print("\n"..story)


Magic 8-ball

Create Magic 8-Ball.

See details at:   Magic 8-Ball.

Solution:
math.randomseed(os.time())
answers = {
  "It is certain.", "It is decidedly so.", "Without a doubt.", "Yes, definitely.", "You may rely on it.",
  "As I see it, yes.", "Most likely.", "Outlook good.", "Signs point to yes.", "Yes.",
  "Reply hazy, try again.", "Ask again later.", "Better not tell you now.", "Cannot predict now.", "Concentrate and ask again.",
  "Don't bet on it.", "My reply is no.", "My sources say no.", "Outlook not so good.", "Very doubtful."
}
while true do
  io.write("Q:  ")
  question = io.read()
  print("A:  "..answers[math.random(#answers)])
end


Magic squares of doubly even order

Solution:
For all three kinds of Magic Squares(Odd, singly and doubly even)<br />
See [[Magic_squares/Lua]].


Magic squares of odd order

A magic square is an   '''NxN'''   square matrix whose numbers (usually integers) consist of consecutive numbers arranged so that the sum of each row and column,   ''and''   both long (main) diagonals are equal to the same sum (which is called the   ''magic number''   or   ''magic constant'').

The numbers are usually (but not always) the first   '''N'''2   positive integers.

A magic square whose rows and columns add up to a magic number but whose main diagonals do not, is known as a ''semimagic square''.

{| class="wikitable" style="float:right;border: 4px solid blue; background:lightgreen; color:black; margin-left:auto;margin-right:auto;text-align:center;width:15em;height:15em;table-layout:fixed;font-size:150%"
|-
| '''8''' || '''1''' || '''6'''
|-
| '''3''' || '''5''' || '''7'''
|-
| '''4''' || '''9''' || '''2'''
|}

;Task
For any odd   '''N''',   generate a magic square with the integers   ''' 1''' --> '''N''',   and show the results here.

Optionally, show the ''magic number''.

You should demonstrate the generator by showing at least a magic square for   '''N''' = '''5'''.

; Related tasks
* [[Magic squares of singly even order]]
* [[Magic squares of doubly even order]]

; See also:
* MathWorld(tm) entry: Magic_square
* Odd Magic Squares (1728.org)


Magic squares of singly even order

A magic square is an '''NxN''' square matrix whose numbers consist of consecutive numbers arranged so that the sum of each row and column, ''and'' both diagonals are equal to the same sum (which is called the ''magic number'' or ''magic constant'').

A  magic square of singly even order has a size that is a multiple of 4, plus 2 (e.g. 6, 10, 14). This means that the subsquares have an odd size, which plays a role in the construction.

;Task
Create a magic square of 6 x 6.

; Related tasks
* [[Magic squares of odd order]]
* [[Magic squares of doubly even order]]

; See also
* Singly Even Magic Squares (1728.org)


Map range

Given two ranges:
:::*   [a_1,a_2]   and
:::*   [b_1,b_2];
:::*   then a value   s   in range   [a_1,a_2]
:::*   is linearly mapped to a value   t   in range   [b_1,b_2]
   where:

:::*   t = b_1 + {(s - a_1)(b_2 - b_1) \over (a_2 - a_1)}

;Task:
Write a function/subroutine/... that takes two ranges and a real number, and returns the mapping of the real number from the first to the second range.

Use this function to map values from the range    [0, 10]    to the range    [-1, 0].

;Extra credit:
Show additional idiomatic ways of performing the mapping, using tools available to the language.

Solution:
function map_range( a1, a2, b1, b2, s )
    return b1 + (s-a1)*(b2-b1)/(a2-a1)
end

for i = 0, 10 do
    print( string.format( "f(%d) = %f", i, map_range( 0, 10, -1, 0, i ) ) )
end


Maximum triangle path sum

Starting from the top of a pyramid of numbers like this, you can walk down going one step on the right or on the left, until you reach the bottom row:

                          55
                        94 48
                       95 30 96
                     77 71 26 67

One of such walks is 55 - 94 - 30 - 26.
You can compute the total of the numbers you have seen in such walk,
in this case it's 205.

Your problem is to find the maximum total among all possible paths from the top to the bottom row of the triangle. In the little example above it's 321.

;Task:
Find the maximum total in the triangle below:

                          55
                        94 48
                       95 30 96
                     77 71 26 67
                    97 13 76 38 45
                  07 36 79 16 37 68
                 48 07 09 18 70 26 06
               18 72 79 46 59 79 29 90
              20 76 87 11 32 07 07 49 18
            27 83 58 35 71 11 25 57 29 85
           14 64 36 96 27 11 58 56 92 18 55
         02 90 03 60 48 49 41 46 33 36 47 23
        92 50 48 02 36 59 42 79 72 20 82 77 42
      56 78 38 80 39 75 02 71 66 66 01 03 55 72
     44 25 67 84 71 67 11 61 40 57 58 89 40 56 36
   85 32 25 85 57 48 84 35 47 62 17 01 01 99 89 52
  06 71 28 75 94 48 37 10 23 51 06 48 53 18 74 98 15
27 02 92 23 08 71 76 84 15 52 92 63 81 10 44 10 69 93

Such numbers can be included in the solution code, or read from a "triangle.txt" file.

This task is derived from the Euler Problem #18.

Solution:
local triangleSmall = {
    { 55 },
    { 94, 48 },
    { 95, 30, 96 },
    { 77, 71, 26, 67 },
}

local triangleLarge = {
    { 55 },
    { 94, 48 },
    { 95, 30, 96 },
    { 77, 71, 26, 67 },
    { 97, 13, 76, 38, 45 },
    {  7, 36, 79, 16, 37, 68 },
    { 48,  7,  9, 18, 70, 26,  6 },
    { 18, 72, 79, 46, 59, 79, 29, 90 },
    { 20, 76, 87, 11, 32,  7,  7, 49, 18 },
    { 27, 83, 58, 35, 71, 11, 25, 57, 29, 85 },
    { 14, 64, 36, 96, 27, 11, 58, 56, 92, 18, 55 },
    {  2, 90,  3, 60, 48, 49, 41, 46, 33, 36, 47, 23 },
    { 92, 50, 48,  2, 36, 59, 42, 79, 72, 20, 82, 77, 42 },
    { 56, 78, 38, 80, 39, 75,  2, 71, 66, 66,  1,  3, 55, 72 },
    { 44, 25, 67, 84, 71, 67, 11, 61, 40, 57, 58, 89, 40, 56, 36 },
    { 85, 32, 25, 85, 57, 48, 84, 35, 47, 62, 17,  1,  1, 99, 89, 52 },
    {  6, 71, 28, 75, 94, 48, 37, 10, 23, 51,  6, 48, 53, 18, 74, 98, 15 },
    { 27,  2, 92, 23,  8, 71, 76, 84, 15, 52, 92, 63, 81, 10, 44, 10, 69, 93 },
};

function solve(triangle)

    -- Get total number of rows in triangle.
    local nRows = table.getn(triangle)

    -- Start at 2nd-to-last row and work up to the top.
    for row = nRows-1, 1, -1 do

        -- For each value in row, add the max of the 2 children beneath it.
        for i = 1, row do
            local child1 = triangle[row+1][i]
            local child2 = triangle[row+1][i+1]
            triangle[row][i] = triangle[row][i] + math.max(child1, child2)
        end

    end

    -- The top of the triangle now holds the answer.
    return triangle[1][1];

end

print(solve(triangleSmall))
print(solve(triangleLarge))


McNuggets problem

From Wikipedia:
 The McNuggets version of the coin problem was introduced by Henri Picciotto,
 who included it in his algebra textbook co-authored with Anita Wah. Picciotto
 thought of the application in the 1980s while dining with his son at
 McDonald's, working the problem out on a napkin. A McNugget number is
 the total number of McDonald's Chicken McNuggets in any number of boxes.
 In the United Kingdom, the original boxes (prior to the introduction of
 the Happy Meal-sized nugget boxes) were of 6, 9, and 20 nuggets.

;Task:
Calculate (from 0 up to a limit of 100) the largest non-McNuggets
number (a number ''n'' which cannot be expressed with ''6x + 9y + 20z = n''
where ''x'', ''y'' and ''z'' are natural numbers).

Solution:
function range(A,B)
    return function()
        return coroutine.wrap(function()
            for i = A, B do coroutine.yield(i) end
        end)
    end
end

function filter(stream, f)
    return function()
        return coroutine.wrap(function()
            for i in stream() do
                if f(i) then coroutine.yield(i) end
            end
        end)
    end
end

function triple(s1, s2, s3)
    return function()
        return coroutine.wrap(function()
            for x in s1() do
                for y in s2() do
                    for z in s3() do
                        coroutine.yield{x,y,z}
                    end
                end
            end
        end)
    end
end

function apply(f, stream)
    return function()
        return coroutine.wrap(function()
            for T in stream() do
                coroutine.yield(f(table.unpack(T)))
            end
        end)
    end
end

function exclude(s1, s2)
    local exlusions = {} for x in s1() do exlusions[x] = true end
    return function()
        return coroutine.wrap(function()
            for x in s2() do
                if not exlusions[x] then
                    coroutine.yield(x)
                end
            end
        end)
    end
end

function maximum(stream)
    local M = math.mininteger
    for x in stream() do
        M = math.max(M, x)
    end
    return M
end

local N = 100
local A, B, C = 6, 9, 20

local Xs = filter(range(0, N), function(x) return x  % A == 0 end)
local Ys = filter(range(0, N), function(x) return x  % B == 0 end)
local Zs = filter(range(0, N), function(x) return x  % C == 0 end)
local sum = filter(apply(function(x, y, z) return x + y + z end, triple(Xs, Ys, Zs)), function(x) return x <= N end)

print(maximum(exclude(sum, range(1, N))))


Middle three digits

Write a function/procedure/subroutine that is called with an integer value and returns the middle three digits of the integer if possible or a clear indication of an error if this is not possible.

Note: The order of the middle digits should be preserved.

Your function should be tested with the following values; the first line should return valid answers, those of the second line should return clear indications of an error:

123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345
1, 2, -1, -10, 2002, -2002, 0

Show your output on this page.

Solution:
function middle_three(n)
	if n < 0 then
		n = -n
	end

	n = tostring(n)
	if #n % 2 == 0 then
		return "Error: the number of digits is even."
	elseif #n < 3 then
		return "Error: the number has less than 3 digits."
	end

	local l = math.floor(#n/2)
	return n:sub(l, l+2)
end

-- test
do
	local t = {123, 12345, 1234567, 987654321,
	10001, -10001, -123, -100, 100, -12345, 1,
	2, -1, -10, 2002, -2002, 0}

	for _,n in pairs(t) do
		print(n, middle_three(n))
	end
end


Mind boggling card trick

Matt Parker of the "Stand Up Maths channel" has a   YouTube video   of a card trick that creates a semblance of order from chaos.

The task is to simulate the trick in a way that mimics the steps shown in the video.

; 1. Cards.
# Create a common deck of cards of 52 cards    (which are half red, half black).
# Give the pack a good shuffle.
; 2. Deal from the shuffled deck, you'll be creating three piles.
#   Assemble the cards face down.
##   Turn up the   ''top card''   and hold it in your hand.
###    if the card is         black,        then add the   ''next''   card (unseen) to the       "black"      pile.
###    If the card is     red,    then add the   ''next''   card (unseen) to the   "red"  pile.
##   Add the   ''top card''   that you're holding to the '''discard''' pile.   (You might optionally show these discarded cards to get an idea of the randomness).
# Repeat the above for the rest of the shuffled deck.
; 3. Choose a random number   (call it '''X''')   that will be used to swap cards from the "red" and "black" piles.
# Randomly choose   '''X'''   cards from the   "red"  pile (unseen), let's call this the   "red"  bunch.
# Randomly choose   '''X'''   cards from the       "black"      pile (unseen), let's call this the      "black"       bunch.
# Put the     "red"    bunch into the         "black"      pile.
# Put the        "black"        bunch into the      "red"  pile.
# (The above two steps complete the swap of   '''X'''   cards of the "red" and "black" piles.  (Without knowing what those cards are --- they could be red or black, nobody knows).
; 4. Order from randomness?
# Verify (or not) the mathematician's assertion that:
      '''The number of black cards in the "black" pile equals the number of red cards in the "red" pile.'''

(Optionally, run this simulation a number of times, gathering more evidence of the truthfulness of the assertion.)

Show output on this page.

Solution:
-- support:
function T(t) return setmetatable(t, {__index=table}) end
table.range = function(t,n) local s=T{} for i=1,n do s[i]=i end return s end
table.map = function(t,f) local s=T{} for i=1,#t do s[i]=f(t[i]) end return s end
table.filter = function(t,f) local s=T{} for i=1,#t do if f(t[i]) then s[#s+1]=t[i] end end return s end
table.clone = function(t) local s=T{} for k,v in ipairs(t) do s[k]=v end return s end
table.head = function(t,n) local s=T{} n=n>#t and #t or n for i = 1,n do s[i]=t[i] end return s end
table.tail = function(t,n) local s=T{} n=n>#t and #t or n for i = 1,n do s[i]=t[#t-n+i] end return s end
table.append = function(t,v) local s=t:clone() for i=1,#v do s[#s+1]=v[i] end return s end
table.shuffle = function(t) for i=#t,2,-1 do local j=math.random(i) t[i],t[j]=t[j],t[i] end return t end -- inplace!

-- task:
function cardtrick()
  -- 1.
  local deck = T{}:range(52):map(function(v) return v%2==0 and "B" or "R" end):shuffle()
  print("1. DECK      : " .. deck:concat())
  -- 2. (which guarantees the outcome)
  local bpile, rpile, discs = T{}, T{}, T{}
  local xpile = {B=bpile, R=rpile}
  while #deck>0 do
    local card, next = deck:remove(), deck:remove()
    xpile[card]:insert(next)
    discs:insert(card)
  end
  print("2. BLACK PILE: " .. bpile:concat())
  print("2. RED PILE  : " .. rpile:concat())
  print("2. DISCARDS  : " .. discs:concat())
  -- 3. (which cannot change the outcome)
  local x = math.random(0, math.min(#bpile, #rpile))
  local btake, rtake = T{}, T{}
  for i = 1, x do
    btake:insert((bpile:remove(math.random(#bpile))))
    rtake:insert((rpile:remove(math.random(#rpile))))
  end
  print("3. SWAPPING X: " .. x)
  print("3. BLACK SWAP: keep:" .. bpile:concat() .. "  take:" .. btake:concat())
  print("3. RED SWAP  : keep:" .. rpile:concat() .. "  take:" .. rtake:concat())
  bpile, rpile = bpile:append(rtake), rpile:append(btake)
  print("3. BLACK PILE: " .. bpile:concat())
  print("3. RED PILE  : " .. rpile:concat())
  -- 4. ("proving" that which was guaranteed earlier)
  local binb, rinr = bpile:filter(function(v) return v=="B" end), rpile:filter(function(v) return v=="R" end)
  print("4. BLACK PILE: contains " .. #binb .. " B's")
  print("4. RED PILE  : contains " .. #rinr .. " R's")
  print(#binb==#rinr and "VERIFIED" or "NOT VERIFIED")
  print()
end

-- demo:
math.randomseed(os.time())
for i = 1,3 do cardtrick() end


Minimum positive multiple in base 10 using only 0 and 1

Every positive integer has infinitely many base-10 multiples that only use the digits '''0''' and '''1'''. The goal of this task is to find and display the '''minimum''' multiple that has this property.

This is simple to do, but can be challenging to do efficiently.

To avoid repeating long, unwieldy phrases, the operation "minimum positive multiple of a positive integer n in base 10 that only uses the digits 0 and 1" will hereafter be referred to as "'''B10'''".

;Task:

Write a routine to find the B10 of a given integer.

E.G.

       '''n'''                  '''B10'''      '''n'''  x '''multiplier'''
       1                    1    ( 1  x 1         )
       2                   10    ( 2  x 5         )
       7                 1001    ( 7  x 143       )
       9            111111111    ( 9  x 12345679  )
      10                   10    ( 10 x 1         )

and so on.

Use the routine to find and display here, on this page, the '''B10''' value for:

    1 through 10, 95 through 105, 297, 576, 594, 891, 909, 999

Optionally find '''B10''' for:

    1998, 2079, 2251, 2277

Stretch goal; find '''B10''' for:

    2439, 2997, 4878

There are many opportunities for optimizations, but avoid using magic numbers as much as possible. If you ''do'' use magic numbers, explain briefly why and what they do for your implementation.

;See also:

:* OEIS:A004290 Least positive multiple of n that when written in base 10 uses only 0's and 1's.
:* How to find Minimum Positive Multiple in base 10 using only 0 and 1

Solution: Without a bignum library, some values do not display or calculate properly


Solution:
function array1D(n, v)
    local tbl = {}
    for i=1,n do
        table.insert(tbl, v)
    end
    return tbl
end

function array2D(h, w, v)
    local tbl = {}
    for i=1,h do
        table.insert(tbl, array1D(w, v))
    end
    return tbl
end

function mod(m, n)
    m = math.floor(m)
    local result = m % n
    if result < 0 then
        result = result + n
    end
    return result
end

function getA004290(n)
    if n == 1 then
        return 1
    end
    local arr = array2D(n, n, 0)
    arr[1][1] = 1
    arr[1][2] = 1
    local m = 0
    while true do
        m = m + 1
        if arr[m][mod(-10 ^ m, n) + 1] == 1 then
            break
        end
        arr[m + 1][1] = 1
        for k = 1, n - 1 do
            arr[m + 1][k + 1] = math.max(arr[m][k + 1], arr[m][mod(k - 10 ^ m, n) + 1])
        end
    end
    local r = 10 ^ m
    local k = mod(-r, n)
    for j = m - 1, 1, -1 do
        if arr[j][k + 1] == 0 then
            r = r + 10 ^ j
            k = mod(k - 10 ^ j, n)
        end
    end
    if k == 1 then
        r = r + 1
    end
    return r
end

function test(cases)
    for _,n in ipairs(cases) do
        local result = getA004290(n)
        print(string.format("A004290(%d) = %s = %d * %d", n, math.floor(result), n, math.floor(result / n)))
    end
end

test({1, 2, 3, 4, 5, 6, 7, 8, 9})
test({95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105})
test({297, 576, 594, 891, 909, 999})
--test({1998, 2079, 2251, 2277})
--test({2439, 2997, 4878})


Modular arithmetic

equivalence relation called ''congruence''.

For any positive integer p called the ''congruence modulus'',
two numbers a and b are said to be ''congruent modulo p'' whenever there exists an integer k such that:
:a = b + k\,p

The corresponding set of multiplicative inverse for this task.

Addition and multiplication on this ring have the same algebraic structure as in usual arithmetic, so that a function such as a polynomial expression could receive a ring element as argument and give a consistent result.

The purpose of this task is to show, if your programming language allows it,
how to redefine operators so that they can be used transparently on modular integers.
You can do it either by using a dedicated library, or by implementing your own class.

You will use the following function for demonstration:
:f(x) = x^{100} + x + 1
You will use 13 as the congruence modulus and you will compute f(10).

It is important that the function f is agnostic about whether or not its argument is modular; it should behave the same way with normal and modular integers.
In other words, the function is an algebraic expression that could be used with any ring, not just integers.

Solution:
function make(value, modulo)
    local v = value % modulo
    local tbl = {value=v, modulo=modulo}

    local mt = {
        __add = function(lhs, rhs)
            if type(lhs) == "table" then
                if type(rhs) == "table" then
                    if lhs.modulo ~= rhs.modulo then
                        error("Cannot add rings with different modulus")
                    end
                    return make(lhs.value + rhs.value, lhs.modulo)
                else
                    return make(lhs.value + rhs, lhs.modulo)
                end
            else
                error("lhs is not a table in +")
            end
        end,
        __mul = function(lhs, rhs)
            if lhs.modulo ~= rhs.modulo then
                error("Cannot multiply rings with different modulus")
            end
            return make(lhs.value * rhs.value, lhs.modulo)
        end,
        __pow = function(b,p)
            if p<0 then
                error("p must be zero or greater")
            end

            local pp = p
            local pwr = make(1, b.modulo)
            while pp > 0 do
                pp = pp - 1
                pwr = pwr * b
            end
            return pwr
        end,
        __concat = function(lhs, rhs)
            if type(lhs) == "table" and type(rhs) == "string" then
                return "ModInt("..lhs.value..", "..lhs.modulo..")"..rhs
            elseif type(lhs) == "string" and type(rhs) == "table" then
                return lhs.."ModInt("..rhs.value..", "..rhs.modulo..")"
            else
                return "todo"
            end
        end
    }

    setmetatable(tbl, mt)
    return tbl
end

function func(x)
    return x ^ 100 + x + 1
end

-- main
local x = make(10, 13)
local y = func(x)
print("x ^ 100 + x + 1 for "..x.." is "..y)


Monads/Maybe monad

Demonstrate in your programming language the following:

#Construct a Maybe Monad by writing the 'bind' function and the 'unit' (sometimes known as 'return') function for that Monad (or just use what the language already has implemented)
#Make two functions, each which take a number and return a monadic number, e.g. Int -> Maybe Int and Int -> Maybe String
#Compose the two functions with bind

A Monad is a single type which encapsulates several other types, eliminating boilerplate code. In practice it acts like a dynamically typed computational sequence, though in many cases the type issues can be resolved at compile time.

A Maybe Monad is a monad which specifically encapsulates the type of an undefined value.

Solution:
-- None is represented by an empty table.  Some is represented by any
-- array with one element.  You SHOULD NOT compare maybe values with the
-- Lua operator == because it will give incorrect results.  Use the
-- functions isMaybe(), isNone(), and isSome().

-- define once for efficiency, to avoid many different empty tables
local NONE = {}

local function unit(x) return { x } end
local Some = unit
local function isNone(mb) return #mb == 0 end
local function isSome(mb) return #mb == 1 end
local function isMaybe(mb) return isNone(mb) or isSome(mb) end

-- inverse of Some(), extract the value from the maybe; get(Some(x)) === x
local function get(mb) return mb[1] end

function maybeToStr(mb)
	return isNone(mb) and "None" or ("Some " .. tostring(get(mb)))
end

local function bind(mb, ...)  -- monadic bind for multiple functions
	local acc = mb
	for _, fun in ipairs({...}) do  -- fun should be a monadic function
		assert(type(fun) == "function")
		if isNone(acc) then return NONE
		else acc = fun(get(acc)) end
	end
	return acc
end

local function fmap(mb, ...)  -- monadic fmap for multiple functions
	local acc = mb
	for _, fun in ipairs({...}) do  -- fun should be a regular function
		assert(type(fun) == "function")
		if isNone(acc) then return NONE
		else acc = Some(fun(get(acc))) end
	end
	return acc
end
-- ^^^ End of generic maybe monad functionality ^^^

--- vvv Start of example code vvv

local function time2(x) return x * 2 end
local function plus1(x) return x + 1 end

local answer
answer = fmap(Some(3), time2, plus1, time2)
assert(get(answer)==14)

answer = fmap(NONE, time2, plus1, time2)
assert(isNone(answer))

local function safeReciprocal(x)
	if x ~= 0 then return Some(1/x) else return NONE end
end
local function safeRoot(x)
	if x >= 0 then return Some(math.sqrt(x)) else return NONE end
end
local function safeLog(x)
	if x > 0 then return Some(math.log(x)) else return NONE end
end
local function safeComputation(x)
	return bind(safeReciprocal(x), safeRoot, safeLog)
end

local function map(func, table)
	local result = {}
	for key, val in pairs(table) do
		result[key] = func(val)
	end
	return result
end

local inList = {-2, -1, -0.5, 0, math.exp (-1), 1, 2, math.exp (1), 3, 4, 5}
print("input:", table.concat(map(tostring, inList), ",  "), "\n")

local outList = map(safeComputation, inList)
print("output:", table.concat(map(maybeToStr, outList), ",  "), "\n")


Move-to-front algorithm

Given a symbol table of a ''zero-indexed'' array of all possible input symbols
this algorithm reversibly transforms a sequence
of input symbols into an array of output numbers (indices).

The transform in many cases acts to give frequently repeated input symbols
lower indices which is  useful in some compression algorithms.

;Encoding algorithm:

    for each symbol of the input sequence:
        output the index of the symbol in the symbol table
        move that symbol to the front of the symbol table

;Decoding algorithm:

    # Using the same starting symbol table
    for each index of the input sequence:
        output the symbol at that index of the symbol table
        move that symbol to the front of the symbol table

;Example:
Encoding the string of character symbols 'broood' using a symbol table of the lowercase characters   '''a'''-to-'''z'''

:::::{| class="wikitable" border="1"
|-
! Input
! Output
! SymbolTable
|-
| '''b'''roood
| 1
| 'abcdefghijklmnopqrstuvwxyz'
|-
| b'''r'''oood
| 1 17
| 'bacdefghijklmnopqrstuvwxyz'
|-
| br'''o'''ood
| 1 17 15
| 'rbacdefghijklmnopqstuvwxyz'
|-
| bro'''o'''od
| 1 17 15 0
| 'orbacdefghijklmnpqstuvwxyz'
|-
| broo'''o'''d
| 1 17 15 0 0
| 'orbacdefghijklmnpqstuvwxyz'
|-
| brooo'''d'''
| 1 17 15 0 0 5
| 'orbacdefghijklmnpqstuvwxyz'
|}

Decoding the indices back to the original symbol order:
:::::{| class="wikitable" border="1"
|-
! Input
! Output
! SymbolTable
|-
|  '''1''' 17 15 0 0 5
| b
| 'abcdefghijklmnopqrstuvwxyz'
|-
| 1 '''17''' 15 0 0 5
| br
| 'bacdefghijklmnopqrstuvwxyz'
|-
| 1 17 '''15''' 0 0 5
| bro
| 'rbacdefghijklmnopqstuvwxyz'
|-
| 1 17 15 '''0''' 0 5
| broo
| 'orbacdefghijklmnpqstuvwxyz'
|-
| 1 17 15 0 '''0''' 5
| brooo
| 'orbacdefghijklmnpqstuvwxyz'
|-
| 1 17 15 0 0 '''5'''
| broood
| 'orbacdefghijklmnpqstuvwxyz'
|}

;Task:
:*   Encode and decode the following three strings of characters using the symbol table of the lowercase characters   '''a'''-to-'''z'''   as above.
:*   Show the strings and their encoding here.
:*   Add a check to ensure that the decoded string is the same as the original.

The strings are:

    broood
 bananaaa
 hiphophiphop
(Note the misspellings in the above strings.)

Solution:
-- Return table of the alphabet in lower case
function getAlphabet ()
    local letters = {}
    for ascii = 97, 122 do table.insert(letters, string.char(ascii)) end
    return letters
end

-- Move the table value at ind to the front of tab
function moveToFront (tab, ind)
    local toMove = tab[ind]
    for i = ind - 1, 1, -1 do tab[i + 1] = tab[i] end
    tab[1] = toMove
end

-- Perform move-to-front encoding on input
function encode (input)
    local symbolTable, output, index = getAlphabet(), {}
    for pos = 1, #input do
        for k, v in pairs(symbolTable) do
            if v == input:sub(pos, pos) then index = k end
        end
        moveToFront(symbolTable, index)
        table.insert(output, index - 1)
    end
    return table.concat(output, " ")
end

-- Perform move-to-front decoding on input
function decode (input)
    local symbolTable, output = getAlphabet(), ""
    for num in input:gmatch("%d+") do
        output = output .. symbolTable[num + 1]
        moveToFront(symbolTable, num + 1)
    end
    return output
end

-- Main procedure
local testCases, output = {"broood", "bananaaa", "hiphophiphop"}
for _, case in pairs(testCases) do
    output = encode(case)
    print("Original string: " .. case)
    print("Encoded: " .. output)
    print("Decoded: " .. decode(output))
    print()
end


Multi-dimensional array

For the purposes of this task, the actual memory layout or access method of this data structure is not mandated.

It is enough to:
# State the number and extent of each index to the array.
# Provide specific, ordered, integer indices for all dimensions of the array together with a new value to update the indexed value.
# Provide specific, ordered, numeric indices for all dimensions of the array to obtain the arrays value at that indexed position.

;Task:
* State if the language supports multi-dimensional arrays in its syntax and usual implementation.
* State whether the language uses row-major or column major order for multi-dimensional array storage, or any other relevant kind of storage.
* Show how to create a four dimensional array in your language and set, access, set to another value; and access the new value of an integer-indexed item of the array. The idiomatic method for the language is preferred.
:* The array should allow a range of five, four, three and two (or two three four five if convenient), in each of the indices, in order. (For example, ''if'' indexing starts at zero for the first index then a range of 0..4 inclusive would suffice).
* State if memory allocation is optimised for the array - especially if contiguous memory is likely to be allocated.
* If the language has exceptional native multi-dimensional array support such as optional bounds checking, reshaping, or being able to state both the lower and upper bounds of index ranges, then this is the task to mention them.

Show all output here, (but you may judiciously use ellipses to shorten repetitive output text).

Solution:
-- Variadic, first argument is the value with which to populate the array.
function multiArray (initVal, ...)
    local function copy (t)
        local new = {}
        for k, v in pairs(t) do
            if type(v) == "table" then
                new[k] = copy(v)
            else
                new[k] = v
            end
        end
        return new
    end
    local dimensions, arr, newArr = {...}, {}
    for i = 1, dimensions[#dimensions] do table.insert(arr, initVal) end
    for d = #dimensions - 1, 1, -1 do
        newArr = {}
        for i = 1, dimensions[d] do table.insert(newArr, copy(arr)) end
        arr = copy(newArr)
    end
    return arr
end

-- Function to print out the specific example created here
function show4dArray (a)
    print("\nPrinting 4D array in 2D...")
    for k, v in ipairs(a) do
        print(k)
        for l, w in ipairs(v) do
            print("\t" .. l)
                for m, x in ipairs(w) do
                    print("\t", m, unpack(x))
                end
        end
    end
end

-- Main procedure
local t = multiArray("a", 2, 3, 4, 5)
show4dArray(t)
t[1][1][1][1] = true
show4dArray(t)


Multifactorial

The factorial of a number, written as n!, is defined as n! = n(n-1)(n-2)...(2)(1).

Multifactorials generalize factorials as follows:
: n! = n(n-1)(n-2)...(2)(1)
: n!! = n(n-2)(n-4)...
: n!! ! = n(n-3)(n-6)...
: n!! !! = n(n-4)(n-8)...
: n!! !! ! = n(n-5)(n-10)...

In all cases, the terms in the products are positive integers.

If we define the degree of the multifactorial as the difference in successive terms that are multiplied together for a multifactorial (the number of exclamation marks), then the task is twofold:
# Write a function that given n and the degree, calculates the multifactorial.
# Use the function to generate and display here a table of the first ten members (1 to 10) of the first five degrees of multifactorial.

'''Note:''' The wikipedia entry on multifactorials gives a different formula. This task uses the Wolfram mathworld definition.

Solution:
function multiFact (n, degree)
    local fact = 1
    for i = n, 2, -degree do
        fact = fact * i
    end
    return fact
end

print("Degree\t|\tMultifactorials 1 to 10")
print(string.rep("-", 52))
for d = 1, 5 do
    io.write(" " .. d, "\t| ")
    for n = 1, 10 do
        io.write(multiFact(n, d) .. " ")
    end
    print()
end


Multiple distinct objects

Create a [[sequence]] (array, list, whatever) consisting of n distinct, initialized items of the same type. n should be determined at runtime.

By ''distinct'' we mean that if they are mutable, changes to one do not affect all others; if there is an appropriate equality operator they are considered unequal; etc. The code need not specify a particular kind of distinction, but do not use e.g. a numeric-range generator which does not generalize.

By ''initialized'' we mean that each item must be in a well-defined state appropriate for its type, rather than e.g. arbitrary previous memory contents in an array allocation. Do not show only an initialization technique which initializes only to "zero" values (e.g. calloc() or int a[n] = {}; in C), unless user-defined types can provide definitions of "zero" for that type.

This task was inspired by the common error of intending to do this, but instead creating a sequence of n references to the ''same'' mutable object; it might be informative to show the way to do that as well, both as a negative example and as how to do it when that's all that's actually necessary.

This task is most relevant to languages operating in the pass-references-by-value style (most object-oriented, garbage-collected, and/or 'dynamic' languages).

See also: [[Closures/Value capture]]

Solution:
-- This concept is relevant to tables in Lua
local table1 = {1,2,3}

-- The following will create a table of references to table1
local refTab = {}
for i = 1, 10 do refTab[i] = table1 end

-- Instead, tables should be copied using a function like this
function copy (t)
    local new = {}
    for k, v in pairs(t) do new[k] = v end
    return new
end

-- Now we can create a table of independent copies of table1
local copyTab = {}
for i = 1, 10 do copyTab[i] = copy(table1) end


Multisplit

It is often necessary to split a string into pieces
based on several different (potentially multi-character) separator strings,
while still retaining the information about which separators were present in the input.

This is particularly useful when doing small parsing tasks.
The task is to write code to demonstrate this.

The function (or procedure or method, as appropriate) should
take an input string and an ordered collection of separators.

The order of the separators is significant:
The delimiter order represents priority in matching, with the first defined delimiter having the highest priority.
In cases where there would be an ambiguity as to
which separator to use at a particular point
(e.g., because one separator is a prefix of another)
the separator with the highest priority should be used.
Delimiters can be reused and the output from the function should be an ordered sequence of substrings.

Test your code using the input string "a!===b=!=c" and the separators "==", "!=" and "=".

For these inputs the string should be parsed as "a" (!=) "" (==) "b" (=) "" (!=) "c", where matched delimiters are shown in parentheses, and separated strings are quoted, so our resulting output is "a", empty string, "b", empty string, "c".
Note that the quotation marks are shown for clarity and do not form part of the output.

'''Extra Credit:''' provide information that indicates which separator was matched at each separation point and where in the input string that separator was matched.

Solution:
--[[
Returns a table of substrings by splitting the given string on
occurrences of the given character delimiters, which may be specified
as a single- or multi-character string or a table of such strings.
If chars is omitted, it defaults to the set of all space characters,
and keep is taken to be false. The limit and keep arguments are
optional: they are a maximum size for the result and a flag
determining whether empty fields should be kept in the result.
]]
function split (str, chars, limit, keep)
    local limit, splitTable, entry, pos, match = limit or 0, {}, "", 1
    if keep == nil then keep = true end
    if not chars then
        for e in string.gmatch(str, "%S+") do
                table.insert(splitTable, e)
        end
        return splitTable
    end
    while pos <= str:len() do
        match = nil
        if type(chars) == "table" then
            for _, delim in pairs(chars) do
                if str:sub(pos, pos + delim:len() - 1) == delim then
                    match = string.len(delim) - 1
                    break
                end
            end
        elseif str:sub(pos, pos + chars:len() - 1) == chars then
            match = string.len(chars) - 1
        end
        if match then
            if not (keep == false and entry == "") then
                table.insert(splitTable, entry)
                if #splitTable == limit then return splitTable end
                entry = ""
            end
        else
            entry = entry .. str:sub(pos, pos)
        end
        pos = pos + 1 + (match or 0)
    end
    if entry ~= "" then table.insert(splitTable, entry) end
    return splitTable
end

local multisplit = split("a!===b=!=c", {"==", "!=", "="})

-- Returned result is a table (key/value pairs) - display all entries
print("Key\tValue")
print("---\t-----")
for k, v in pairs(multisplit) do
    print(k, v)
end


Munchausen numbers

A Munchausen number is a natural number ''n'' the sum of whose digits (in base 10), each raised to the power of itself, equals ''n''.

('''Munchausen''' is also spelled: '''Munchhausen'''.)

For instance:    3435 = 33 + 44 + 33 + 55

;Task
Find all Munchausen numbers between   '''1'''   and   '''5000'''.

;Also see:
:* The OEIS entry:  A046253
:* The Wikipedia entry:  Perfect digit-to-digit invariant, redirected from ''Munchausen Number''

Solution:
function isMunchausen (n)
    local sum, nStr, digit = 0, tostring(n)
    for pos = 1, #nStr do
        digit = tonumber(nStr:sub(pos, pos))
        sum = sum + digit ^ digit
    end
    return sum == n
end

-- alternative, faster version based on the C version,
-- avoiding string manipulation, for Lua 5.3 or higher
local function isMunchausen (n)
    local sum, digit, acc = 0, 0, n
    while acc > 0 do
        digit = acc % 10.0
        sum = sum + digit ^ digit
        acc = acc // 10 -- integer div
    end
    return sum == n
end

for i = 1, 5000 do
    if isMunchausen(i) then print(i) end
end