public class LongestCommonSubstring {

    public static void main(String[] args) {
        System.out.println(lcs("testing123testing", "thisisatest"));
        System.out.println(lcs("test", "thisisatest"));
        System.out.println(lcs("testing", "sting"));
        System.out.println(lcs("testing", "thisisasting"));
    }

    static String lcs(String a, String b) {
        if (a.length() > b.length())
            return lcs(b, a);

        String res = "";
        for (int ai = 0; ai < a.length(); ai++) {
            for (int len = a.length() - ai; len > 0; len--) {

                for (int bi = 0; bi <= b.length() - len; bi++) {

                    if (a.regionMatches(ai, b, bi, len) && len > res.length()) {
                        res = a.substring(ai, ai + len);
                    }
                }
            }
        }
        return res;
    }
}


module(lcs).
-compile(export_all).

lcs_length(S,T) ->
    {L,_C} = lcs_length(S,T,dict:new()),
    L.

lcs_length([]=S,T,Cache) ->
    {0,dict:store({S,T},0,Cache)};
lcs_length(S,[]=T,Cache) ->
    {0,dict:store({S,T},0,Cache)};
lcs_length([H|ST]=S,[H|TT]=T,Cache) ->
    {L,C} = lcs_length(ST,TT,Cache),
    {L+1,dict:store({S,T},L+1,C)};
lcs_length([_SH|ST]=S,[_TH|TT]=T,Cache) ->
    case dict:is_key({S,T},Cache) of
        true -> {dict:fetch({S,T},Cache),Cache};
        false ->
            {L1,C1} = lcs_length(S,TT,Cache),
            {L2,C2} = lcs_length(ST,T,C1),
            L = lists:max([L1,L2]),
            {L,dict:store({S,T},L,C2)}
    end.

lcs(S,T) ->
    {_,C} = lcs_length(S,T,dict:new()),
    lcs(S,T,C,[]).

lcs([],_,_,Acc) ->
    lists:reverse(Acc);
lcs(_,[],_,Acc) ->
    lists:reverse(Acc);
lcs([H|ST],[H|TT],Cache,Acc) ->
    lcs(ST,TT,Cache,[H|Acc]);
lcs([_SH|ST]=S,[_TH|TT]=T,Cache,Acc) ->
    case dict:fetch({S,TT},Cache) > dict:fetch({ST,T},Cache) of
        true ->
            lcs(S,TT,Cache, Acc);
        false ->
            lcs(ST,T,Cache,Acc)
    end.


ultimaRevision$ = "2021-11-12"
arraybase 1
dim elemento$ = {"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"}

print "Last updated       : "; ultimaRevision$
print "Number of elements : "; elemento$[?]
print "Last element       : "; elemento$[elemento$[?]]
end


require "time"

last_revision = Time.utc year: 2021, month: 2, day: 25

# the `%w()` literal creates an array from a whitespace-delimited string literal
# it's equivalent to %(string literal).split
# https://crystal-lang.org/reference/syntax_and_semantics/literals/string.html
element_list : Array(String) = %w(
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)

puts last_revision.to_s "last revised %B %e, %Y"
puts "number of elements: #{element_list.size}"
puts "highest element: #{element_list.last}"


program Long_literals_with_continuations;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.StrUtils;

// Copy and past of Free_Pascal version
const
  StdWordDelims: array[0..16] of char = (#0, ' ', ',', '.', ';', '/', '\', ':',
    '''', '"', '`', '(', ')', '[', ']', '{', '}');
  revisionNotice = 'Last update: %0:s';

  elementString = 'hydrogen helium lithium beryllium boron carbon nitrogen oxy'
    + 'gen fluorine neon sodium magnesium aluminum silicon phosphorous sulfur chl'
    + 'orine argon potassium calcium scandium titanium vanadium chromium manganes'
    + 'e iron cobalt nickel copper zinc gallium germanium arsenic selenium bromin'
    + 'e krypton rubidium strontium yttrium zirconium niobium molybdenum techneti'
    + 'um ruthenium rhodium palladium silver cadmium indium tin antimony telluriu'
    + 'm iodine xenon cesium barium lanthanum cerium praseodymium neodymium prome'
    + 'thium samarium europium gadolinium terbium dysprosium holmium erbium thuli'
    + 'um ytterbium lutetium hafnium tantalum tungsten rhenium osmium iridium pla'
    + 'tinum gold mercury thallium lead bismuth polonium astatine radon francium '
    + 'radium actinium thorium protactinium uranium neptunium plutonium americium'
    + ' curium berkelium californium einsteinium fermium mendelevium nobelium law'
    + 'rencium rutherfordium dubnium seaborgium bohrium hassium meitnerium darmst'
    + 'adtium roentgenium copernicium nihonium flerovium moscovium livermorium te'
    + 'nnessine oganesson';
  elementRevision = '2020-11-11';

begin
  var words := elementString.Split(StdWordDelims);

  writeLn(format(revisionNotice, [elementRevision]));
  writeln(length(words));
  writeln(words[high(words)]);
  readln;
end.


program longStringLiteralDemo(output);

{$mode objFPC}
{$longStrings on}

uses
	// for `format`
	sysUtils,
	// for `wordCount` and `extractWord`
	strUtils;

const
	elementString = 'hydrogen helium lithium beryllium boron carbon nitrogen oxy' +
		'gen fluorine neon sodium magnesium aluminum silicon phosphorous sulfur chl' +
		'orine argon potassium calcium scandium titanium vanadium chromium manganes' +
		'e iron cobalt nickel copper zinc gallium germanium arsenic selenium bromin' +
		'e krypton rubidium strontium yttrium zirconium niobium molybdenum techneti' +
		'um ruthenium rhodium palladium silver cadmium indium tin antimony telluriu' +
		'm iodine xenon cesium barium lanthanum cerium praseodymium neodymium prome' +
		'thium samarium europium gadolinium terbium dysprosium holmium erbium thuli' +
		'um ytterbium lutetium hafnium tantalum tungsten rhenium osmium iridium pla' +
		'tinum gold mercury thallium lead bismuth polonium astatine radon francium ' +
		'radium actinium thorium protactinium uranium neptunium plutonium americium' +
		' curium berkelium californium einsteinium fermium mendelevium nobelium law' +
		'rencium rutherfordium dubnium seaborgium bohrium hassium meitnerium darmst' +
		'adtium roentgenium copernicium nihonium flerovium moscovium livermorium te' +
		'nnessine oganesson';
	elementRevision = '2020‑11‑11';

resourcestring
	revisionNotice = 'Last update: %0:s';

begin
	writeLn(format(revisionNotice, [elementRevision]));
	writeLn(wordCount(elementString, stdWordDelims));
	writeLn(extractWord(wordCount(elementString, stdWordDelims),
		elementString, stdWordDelims));
end.


(() => {
    'use strict';

    // longestCommon :: String -> String -> String
    const longestCommon = (s1, s2) => maximumBy(
        comparing(length),
        intersect(...apList(
            [s => map(
                concat,
                concatMap(tails, compose(tail, inits)(s))
            )],
            [s1, s2]
        ))
    );

    // main :: IO ()
    const main = () =>
        console.log(
            longestCommon(
                "testing123testing",
                "thisisatest"
            )
        );

    // GENERIC FUNCTIONS ----------------------------

    // Each member of a list of functions applied to each
    // of a list of arguments, deriving a list of new values.

    // apList (<*>) :: [(a -> b)] -> [a] -> [b]
    const apList = (fs, xs) => //
        fs.reduce((a, f) => a.concat(
            xs.reduce((a, x) => a.concat([f(x)]), [])
        ), []);

    // comparing :: (a -> b) -> (a -> a -> Ordering)
    const comparing = f =>
        (x, y) => {
            const
                a = f(x),
                b = f(y);
            return a < b ? -1 : (a > b ? 1 : 0);
        };

    // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
    const compose = (f, g) => x => f(g(x));

    // concat :: [[a]] -> [a]
    // concat :: [String] -> String
    const concat = xs =>
        0 < xs.length ? (() => {
            const unit = 'string' !== typeof xs[0] ? (
                []
            ) : '';
            return unit.concat.apply(unit, xs);
        })() : [];

    // concatMap :: (a -> [b]) -> [a] -> [b]
    const concatMap = (f, xs) =>
        xs.reduce((a, x) => a.concat(f(x)), []);

    // inits([1, 2, 3]) -> [[], [1], [1, 2], [1, 2, 3]
    // inits('abc') -> ["", "a", "ab", "abc"]

    // inits :: [a] -> [[a]]
    // inits :: String -> [String]
    const inits = xs => [
            []
        ]
        .concat(('string' === typeof xs ? xs.split('') : xs)
            .map((_, i, lst) => lst.slice(0, i + 1)));

    // intersect :: (Eq a) => [a] -> [a] -> [a]
    const intersect = (xs, ys) =>
        xs.filter(x => -1 !== ys.indexOf(x));

    // Returns Infinity over objects without finite length.
    // This enables zip and zipWith to choose the shorter
    // argument when one is non-finite, like cycle, repeat etc

    // length :: [a] -> Int
    const length = xs =>
        (Array.isArray(xs) || 'string' === typeof xs) ? (
            xs.length
        ) : Infinity;

    // map :: (a -> b) -> [a] -> [b]
    const map = (f, xs) => xs.map(f);

    // maximumBy :: (a -> a -> Ordering) -> [a] -> a
    const maximumBy = (f, xs) =>
        0 < xs.length ? (
            xs.slice(1)
            .reduce((a, x) => 0 < f(x, a) ? x : a, xs[0])
        ) : undefined;

    // tail :: [a] -> [a]
    const tail = xs => 0 < xs.length ? xs.slice(1) : [];

    // tails :: [a] -> [[a]]
    const tails = xs => {
        const
            es = ('string' === typeof xs) ? (
                xs.split('')
            ) : xs;
        return es.map((_, i) => es.slice(i))
            .concat([
                []
            ]);
    };

    // MAIN ---
    return main();
})();


open System

let longest xs ys = if List.length xs > List.length ys then xs else ys

let rec lcs a b =
    match a, b with
    | [], _
    | _, []        -> []
    | x::xs, y::ys ->
        if x = y then
            x :: lcs xs ys
        else
            longest (lcs a ys) (lcs xs b)

[<EntryPoint>]
let main argv =
    let split (str:string) = List.init str.Length (fun i -> str.[i])
    printfn "%A" (String.Join("",
        (lcs (split "thisisatest") (split "testing123testing"))))
    0


USE: lcs
"thisisatest" "testing123testing" lcs print


Dim As String ultimaRevision = "2021-11-12"
Dim As String elemento(0 to ...) => { _
"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"}

Print "Last updated       : "; ultimaRevision
Print "Number of elements : "; Ubound(elemento) - Lbound(elemento) + 1
Print "Last element       : "; elemento(Ubound(elemento))
Sleep


package main

import (
    "fmt"
    "regexp"
    "strings"
)

// Uses a 'raw string literal' which is a character sequence enclosed in back quotes.
// Within the quotes any character (including new line) may appear except
// back quotes themselves.
var elements = `
    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
`

func main() {
    lastRevDate := "March 24th, 2020"
    re := regexp.MustCompile(`\s+`) // split on one or more whitespace characters
    els := re.Split(strings.TrimSpace(elements), -1)
    numEls := len(els)
    // Recombine as a single string with elements separated by a single space.
    elements2 := strings.Join(els, " ")
    // Required output.
    fmt.Println("Last revision Date: ", lastRevDate)
    fmt.Println("Number of elements: ", numEls)
    // The compiler complains that 'elements2' is unused if we don't use
    // something like this to get the last element rather than just els[numEls-1].
    lix := strings.LastIndex(elements2, " ") // get index of last space
    fmt.Println("Last element      : ", elements2[lix+1:])
}


elements = words "hydrogen \
\   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"


# Create an m x n matrix
def matrix(m; n; init):
  if m == 0 then []
  elif m == 1 then [range(0;n) | init]
  elif m > 0 then
    matrix(1;n;init) as $row
    | [range(0;m) | $row ]
  else error("matrix\(m);_;_) invalid")
  end;

def set(i;j; value):
  setpath([i,j]; value);


function lcs(s1::AbstractString, s2::AbstractString)
    l, r = 1, 0
    sub_len = 0
    for i in 1:length(s1)
        for j in i:length(s1)
            if !contains(s2, SubString(s1, i, j)) break
            elseif sub_len < j - i
                l, r = i, j
                sub_len = j - i
            end
        end
    end
    s1[l:r]
end

@show lcs("thisisatest", "testing123testing")


// version 1.1.2

fun lcs(a: String, b: String): String {
    if (a.length > b.length) return lcs(b, a)
    var res = ""
    for (ai in 0 until a.length) {
        for (len in a.length - ai downTo 1) {
            for (bi in 0 until b.length - len) {
                if (a.regionMatches(ai, b, bi,len) && len > res.length) {
                    res = a.substring(ai, ai + len)
                }
            }
        }
    }
    return res
}

fun main(args: Array<String>) = println(lcs("testing123testing", "thisisatest"))


program lcstest
  use iso_varying_string
  implicit none

  type(varying_string) :: s1, s2

  s1 = "thisisatest"
  s2 = "testing123testing"
  print *, char(lcs(s1, s2))

  s1 = "1234"
  s2 = "1224533324"
  print *, char(lcs(s1, s2))

contains

  recursive function lcs(a, b) result(l)
    type(varying_string) :: l
    type(varying_string), intent(in) :: a, b

    type(varying_string) :: x, y

    l = ""
    if ( (len(a) == 0) .or. (len(b) == 0) ) return
    if ( extract(a, len(a), len(a)) == extract(b, len(b), len(b)) ) then
       l = lcs(extract(a, 1, len(a)-1), extract(b, 1, len(b)-1)) // extract(a, len(a), len(a))
    else
       x = lcs(a, extract(b, 1, len(b)-1))
       y = lcs(extract(a, 1, len(a)-1), b)
       if ( len(x) > len(y) ) then
          l = x
       else
          l = y
       end if
    end if
  end function lcs

end program lcstest


Function LCS(a As String, b As String) As String
    Dim As String x, y
    If Len(a) = 0 Or Len(b) = 0 Then
        Return ""
    Elseif Right(a, 1) = Right(b, 1) Then
        LCS = LCS(Left(a, Len(a) - 1), Left(b, Len(b) - 1)) + Right(a, 1)
    Else
        x = LCS(a, Left(b, Len(b) - 1))
        y = LCS(Left(a, Len(a) - 1), b)
        If Len(x) > Len(y) Then Return x Else Return y
    End If
End Function

Print LCS("1234", "1224533324")
Print LCS("thisisatest", "testing123testing")
Sleep


   NB. create a multi-line literal
   elements =: CRLF -.~ noun define
       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
)

   NB. same under words
   space_separated_elements =: ]&.:;: elements

   tally=: # ;: elements

   last_element=: _1 {:: ;: elements

   revision=: '2020-03-23'

   'Last revision: ', revision
   'Number of elements: ' , ": tally
   'Last element: ', last_element
   'first and last 30 characters:'
   30 ;&({.&space_separated_elements) _30
Last revision: 2020-03-23
Number of elements: 118
Last element: oganesson
first and last 30 characters:
┌──────────────────────────────┬──────────────────────────────┐
│hydrogen helium lithium beryll│vermorium tennessine oganesson│
└──────────────────────────────┴──────────────────────────────┘


# FOR FUTURE EDITORS:
# To add chemical elements, modify the CHEMICAL_ELEMENTS function,
# ensuring that the date is updated properly and that there is at least one
# space between the element names after concatenation of the strings.
# Do not include any of the "unnamed" chemical element names such as ununennium.

def CHEMICAL_ELEMENTS:
  {date: "Wed Jun 23 00:00:00 EDT 2021",
   elements: (

  "hydrogen helium lithium beryllium boron carbon nitrogen oxygen fluorine neon "
  + "sodium magnesium aluminum silicon phosphorus 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"

  ) }
;

def chemical_elements_array:
  CHEMICAL_ELEMENTS.elements
  # remove leading and trailing whitespace
  | sub("^ *";"") | sub(" *$";"")
  # return a list after splitting using whitespace between words as a separator
  | [splits("[ \t]+")] ;

def report:
  chemical_elements_array as $a
  | "List last revised:      \(CHEMICAL_ELEMENTS.date)",
    "Length of element list: \($a|length)",
    "Last element in list:   \($a[-1])";

report


using Dates

# FOR FUTURE EDITORS:
#
# Add to this list by adding more lines of text to this listing, placing the
# new words of text before the last """ below, with all entries separated by
# spaces.
#
const CHEMICAL_ELEMENTS = """

hydrogen helium lithium beryllium boron carbon nitrogen oxygen fluorine neon
sodium magnesium aluminum silicon phosphorus 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

"""
#
# END OF ABOVE LISTING--DO NOT ADD ELEMENTS BELOW THIS LINE
#

const EXCLUDED = split(strip(
"ununennium unquadnilium triunhexium penthextrium penthexpentium " *
" septhexunium octenntrium ennennbium"), r"\s+")

function process_chemical_element_list(s = CHEMICAL_ELEMENTS)
    # remove leading and trailing whitespace
    s = strip(s)
    # return a list after splitting using whitespace between words as a separator
    return [element for element in split(s, r"\s+") if !(element in EXCLUDED)]
end

function report()
    filedate = Dates.unix2datetime(mtime(@__FILE__))
    element_list = process_chemical_element_list()
    element_count = length(element_list)
    last_element_in_list = element_list[end]

    println("File last revised (formatted as dateTtime): ", filedate, " GMT")
    println("Length of element list: ", element_count)
    println("last element in list: ", last_element_in_list)
end

report()


import java.time.Instant

const val elementsChunk = """
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
"""

const val unamedElementsChunk = """
ununennium unquadnilium triunhexium penthextrium
penthexpentium septhexunium octenntrium ennennbium
"""

fun main() {
    fun String.splitToList() = trim().split("\\s+".toRegex());
    val elementsList =
        elementsChunk.splitToList()
            .filterNot(unamedElementsChunk.splitToList().toSet()::contains)
    println("Last revision Date:  ${Instant.now()}")
    println("Number of elements:  ${elementsList.size}")
    println("Last element      :  ${elementsList.last()}")
    println("The elements are  :  ${elementsList.joinToString(" ", limit = 5)}")
}


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," ")


import strutils

const RevDate = "2021-02-05"

# We use the concatenation operator "&" to assemble the strings.
# This is done at compile time and so the result is a long literal.
const ElementString =
  "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"

when isMainModule:

  const ElementList = ElementString.split()

  echo "Last revision date:   ", RevDate
  echo "Number of elements:   ", ElementList.len
  echo "Last element in list: ", ElementList[^1]


#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Long_literals,_with_continuations
use warnings;

my $longliteral = join ' ', split ' ', <<END;
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
END

my $version = 'Tue Feb  2 22:30:48 UTC 2021';
my $count = my @elements = split ' ', $longliteral;
my $last = $elements[-1];

print <<END;
      version: $version
element count: $count
 last element: $last
END


import std
def lcs(a, b) -> string:
    var out = ""
    let lengths = map(a.length * b.length): 0
    var greatestLength = 0
    for(a) x, i:
        for(b) y, j:
            if x == y:
                if i == 0 or j == 0:
                    lengths[i * b.length + j] = 1
                else:
                    lengths[i * b.length + j] = lengths[(i-1) * b.length + j - 1] + 1
                if lengths[i * b.length + j] > greatestLength:
                    greatestLength = lengths[i * b.length + j]
                    out = a.substring(i - greatestLength + 1, greatestLength)
    return out


MODULE LCS;
FROM FormatString IMPORT FormatString;
FROM Terminal IMPORT WriteString,WriteLn,Write,ReadChar;

PROCEDURE WriteSubstring(s : ARRAY OF CHAR; b,e : CARDINAL);
VAR i : CARDINAL;
BEGIN
    IF b=e THEN RETURN END;
    IF e>HIGH(s) THEN e := HIGH(s) END;

    FOR i:=b TO e DO
        Write(s[i])
    END
END WriteSubstring;

TYPE
    Pair = RECORD
        a,b : CARDINAL;
    END;

PROCEDURE lcs(sa,sb : ARRAY OF CHAR) : Pair;
VAR
    output : Pair;
    a,b,len : CARDINAL;
BEGIN
    output := Pair{0,0};

    FOR a:=0 TO HIGH(sa) DO
        FOR b:=0 TO HIGH(sb) DO
            IF (sa[a]#0C) AND (sb[b]#0C) AND (sa[a]=sb[b]) THEN
                len := 1;
                WHILE (a+len<HIGH(sa)) AND (b+len<HIGH(sb)) DO
                    IF sa[a+len] = sb[b+len] THEN
                        INC(len)
                    ELSE
                        BREAK
                    END
                END;
                DEC(len);

                IF len>output.b-output.a THEN
                    output := Pair{a,a+len}
                END
            END
        END
    END;

    RETURN output
END lcs;

VAR res : Pair;
BEGIN
    res := lcs("testing123testing", "thisisatest");
    WriteSubstring("testing123testing", res.a, res.b);
    WriteLn;

    ReadChar
END LCS.


func lcs(a, b string) string {
    aLen := len(a)
    bLen := len(b)
    if aLen == 0 || bLen == 0 {
        return ""
    } else if a[aLen-1] == b[bLen-1] {
        return lcs(a[:aLen-1], b[:bLen-1]) + string(a[aLen-1])
    }
    x := lcs(a, b[:bLen-1])
    y := lcs(a[:aLen-1], b)
    if len(x) > len(y) {
        return x
    }
    return y
}


def lcs(xstr, ystr) {
    if (xstr == "" || ystr == "") {
        return "";
    }

    def x = xstr[0];
    def y = ystr[0];

    def xs = xstr.size() > 1 ? xstr[1..-1] : "";
    def ys = ystr.size() > 1 ? ystr[1..-1] : "";

    if (x == y) {
        return (x + lcs(xs, ys));
    }

    def lcs1 = lcs(xstr, ys);
    def lcs2 = lcs(xs, ystr);

    lcs1.size() > lcs2.size() ? lcs1 : lcs2;
}

println(lcs("1234", "1224533324"));
println(lcs("thisisatest", "testing123testing"));


constant last_updated = "March 24th, 2020",
elements_text = `
    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
`,
elements = split(substitute_all(elements_text,{'\n','\r','\t'},"   "),no_empty:=true),
fmt = """
Last revision: %s
Number of elements: %d
The last of which is: "%s"
"""
printf(1,fmt,{last_updated,length(elements),elements[$]})


elements$=    "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"
revision$=    "2020-11-11"
Dim result$(0)
If OpenConsole() And CreateRegularExpression(0,"[a-z]{1,18}")
  nbf=ExtractRegularExpression(0,elements$,result$())
  PrintN("Last revision: "+revision$+
         ~"\nNumber of elements: "+Str(nbf)+
         ~"\nLast element: "+result$(nbf-1))
  Input()
EndIf


"""Long string literal. Requires Python 3.6+ for f-strings."""

revision = "October 13th 2020"

# String literal continuation. Notice the trailing space at the end of each
# line but the last, and the lack of commas. There is exactly one "blank"
# between each item in the list.
elements = (
    "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"
)

def report():
    """Write a summary report to stdout."""
    items = elements.split()

    print(f"Last revision date: {revision}")
    print(f"Number of elements: {len(items)}")
    print(f"Last element      : {items[-1]}")

if __name__ == "__main__":
    report()


# Longest common substring.

import sequtils

func lcs(a, b: string): string =
  var lengths = newSeqWith(a.len, newSeq[int](b.len))
  var greatestLength = 0
  for i, x in a:
    for j, y in b:
      if x == y:
        lengths[i][j] = if i == 0 or j == 0: 1 else: lengths[i - 1][j - 1] + 1
        if lengths[i][j] > greatestLength:
          greatestLength = lengths[i][j]
          result = a[(i - greatestLength + 1)..i]

echo lcs("thisisatest", "testing123testing")


PROGRAM LongestCommonSubString.pas;

{$DEFINE DEBUGGING}
{$IFDEF FPC}
    {$mode objfpc}{$H+}{$J-}{R+}
{$ELSE}
    {$APPTYPE CONSOLE}
{$ENDIF}

(*)

        Free Pascal Compiler version 3.2.0 [2020/06/14] for x86_64
        The free and readable alternative at C/C++ speeds
        compiles natively to almost any platform, including raspberry PI *
        Can run independently from DELPHI / Lazarus

(*)

    FUNCTION lcss( S1, S2: string ) : string ;

    (*)

        LongestCommonSubString: plain version without extra libraries

        From https://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Longest_common_substring
        translated from java

    (*)

        VAR
            i:      integer = 0;
            j:      integer = 0;
            x:      integer = 0;
            LenS1:  integer = 0;
            LenS2:  integer = 0;
            Start:  integer = 0;
            Max:    integer = 0;

        BEGIN

            LenS1 := length ( S1 ) - 1 ;
            LenS2 := length ( S2 ) - 1 ;

            FOR i := 0 TO  LenS1 DO
                BEGIN

                    FOR j := 0 TO LenS2 DO
                        BEGIN

                            x := 0;

                            WHILE ( S1 [ i + x ] = S2 [ j + x ] ) DO

                                BEGIN
                                    Inc ( x ) ;
                                    IF ( ( ( i + x ) > LenS1 ) or ( ( j + x ) > LenS2 ) ) THEN BREAK ;
                                END ;

                            IF ( x > Max ) THEN

                                BEGIN
                                    Max   := x ;
                                    Start := i ;
                                END ;
                        END ;
                END ;

            lcss :=  copy ( S1, Start, ( Start + Max ) ) ;

        END ;

VAR
    S1: string ;
    S2: string ;

BEGIN

    S1 :=   'thisisatest'       ;
    S2 :=   'testing123testing' ;

    WriteLn( Lcss ( S1, S2 ) )  ;

END.


longest xs ys = if length xs > length ys then xs else ys

lcs [] _ = []
lcs _ [] = []
lcs (x:xs) (y:ys)
  | x == y    = x : lcs xs ys
  | otherwise = longest (lcs (x:xs) ys) (lcs xs (y:ys))


procedure main()
LCSTEST("thisisatest","testing123testing")
LCSTEST("","x")
LCSTEST("x","x")
LCSTEST("beginning-middle-ending","beginning-diddle-dum-ending")
end

link strings

procedure LCSTEST(a,b)    #: helper to show inputs and results
write("lcs( ",image(a),", ",image(b)," ) = ",image(res := lcs(a,b)))
return res
end

procedure lcs(a,b)     #: return longest common sub-sequence of characters (modified recursive method)
local i,x,y
local c,nc

   if *(a|b) = 0 then return ""                               # done if either string is empty
   if a == b then return a                                    # done if equal

   if *(a ++ b -- (c := a ** b)) > 0 then {                   # find all characters not in common
      a := deletec(a,nc := ~c)                                # .. remove
      b := deletec(b,nc)                                      # .. remove
      }                                                       # only unequal strings and shared characters beyond

   i := 0 ; while a[i+1] == b[i+1] do i +:=1                  # find common prefix ...
   if *(x := a[1+:i]) > 0  then                               # if any
      return x || lcs(a[i+1:0],b[i+1:0])                      # ... remove and process remainder

   i := 0 ; while a[-(i+1)] == b[-(i+1)] do i +:=1            # find common suffix ...
   if *(y := a[0-:i]) > 0 then                                # if any
      return lcs(a[1:-i],b[1:-i]) || y                        # ... remove and process remainder

   return if *(x := lcs(a,b[1:-1])) > *(y := lcs(a[1:-1],b)) then x else y  # divide, discard, and keep longest
end


  [ stack ]                      is last-revision  ( --> $ )
  $ "6 Jun 2021" last-revision put

  [ stack ]                      is elements       ( --> $ )

  $ " 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"

  nest$
  $ "" swap
  witheach [ join space join ]
  -1 split drop
  elements put

  [ last-revision share decho$ ]   is echorevision ( -->   )

  [ elements share nest$ size ]    is elementcount ( --> n )

  [ elements share
    reverse nextword
    nip reverse ]                  is finalelement ( --> $ )

  say "Last revision: "      echorevision cr
  say "Number of elements: " elementcount echo cr
  say "Last element: "       finalelement echo$ cr


my %periodic;
%periodic<revision-date> = Date.new(2020,3,23);
%periodic<table> = |<

         Hydrogen  1.0079     H             Helium  4.0026    He
          Lithium  6.941     Li          Beryllium  9.0122    Be
            Boron  10.811     B             Carbon  12.0107    C
         Nitrogen  14.0067    N             Oxygen  15.9994    O
         Fluorine  18.9984    F               Neon  20.1797   Ne
           Sodium  22.9897   Na          Magnesium  24.305    Mg
         Aluminum  26.9815   Al            Silicon  28.0855   Si
       Phosphorus  30.9738    P             Sulfur  32.065     S
         Chlorine  35.453    Cl          Potassium  39.0983    K
            Argon  39.948    Ar            Calcium  40.078    Ca
         Scandium  44.9559   Sc           Titanium  47.867    Ti
         Vanadium  50.9415    V           Chromium  51.9961   Cr
        Manganese  54.938    Mn               Iron  55.845    Fe
           Nickel  58.6934   Ni             Cobalt  58.9332   Co
           Copper  63.546    Cu               Zinc  65.39     Zn
          Gallium  69.723    Ga          Germanium  72.64     Ge
          Arsenic  74.9216   As           Selenium  78.96     Se
          Bromine  79.904    Br            Krypton  83.8      Kr
         Rubidium  85.4678   Rb          Strontium  87.62     Sr
          Yttrium  88.9059    Y          Zirconium  91.224    Zr
          Niobium  92.9064   Nb         Molybdenum  95.94     Mo
       Technetium  98        Tc          Ruthenium  101.07    Ru
          Rhodium  102.9055  Rh          Palladium  106.42    Pd
           Silver  107.8682  Ag            Cadmium  112.411   Cd
           Indium  114.818   In                Tin  118.71    Sn
         Antimony  121.76    Sb             Iodine  126.9045   I
        Tellurium  127.6     Te              Xenon  131.293   Xe
           Cesium  132.9055  Cs             Barium  137.327   Ba
        Lanthanum  138.9055  La             Cerium  140.116   Ce
     Praseodymium  140.9077  Pr          Neodymium  144.24    Nd
       Promethium  145       Pm           Samarium  150.36    Sm
         Europium  151.964   Eu         Gadolinium  157.25    Gd
          Terbium  158.9253  Tb         Dysprosium  162.5     Dy
          Holmium  164.9303  Ho             Erbium  167.259   Er
          Thulium  168.9342  Tm          Ytterbium  173.04    Yb
         Lutetium  174.967   Lu            Hafnium  178.49    Hf
         Tantalum  180.9479  Ta           Tungsten  183.84     W
          Rhenium  186.207   Re             Osmium  190.23    Os
          Iridium  192.217   Ir           Platinum  195.078   Pt
             Gold  196.9665  Au            Mercury  200.59    Hg
         Thallium  204.3833  Tl               Lead  207.2     Pb
          Bismuth  208.9804  Bi           Polonium  209       Po
         Astatine  210       At              Radon  222       Rn
         Francium  223       Fr             Radium  226       Ra
         Actinium  227       Ac       Protactinium  231.0359  Pa
          Thorium  232.0381  Th          Neptunium  237       Np
          Uranium  238.0289   U          Americium  243       Am
        Plutonium  244       Pu             Curium  247       Cm
        Berkelium  247       Bk        Californium  251       Cf
      Einsteinium  252       Es            Fermium  257       Fm
      Mendelevium  258       Md           Nobelium  259       No
    Rutherfordium  261       Rf         Lawrencium  262       Lr
          Dubnium  262       Db            Bohrium  264       Bh
       Seaborgium  266       Sg         Meitnerium  268       Mt
      Roentgenium  272       Rg            Hassium  277       Hs
     Darmstadtium  ???       Ds        Copernicium  ???       Cn
         Nihonium  ???       Nh          Flerovium  ???       Fl
        Moscovium  ???       Mc        Livermorium  ???       Lv
       Tennessine  ???       Ts          Oganesson  ???       Og

>.words.map: { (:name($^a), :weight($^b), :symbol($^c)).hash };

put 'Revision date: ',                                   %periodic<revision-date>;
put 'Last element by position (nominally by weight): ',  %periodic<table>.tail.<name>;
put 'Total number of elements: ',                        %periodic<table>.elems;
put 'Last element sorted by full name: ',                %periodic<table>.sort( *.<name> ).tail.<name>;
put 'Longest element name: ',                            %periodic<table>.sort( *.<name>.chars ).tail.<name>;
put 'Shortest element name: ',                           %periodic<table>.sort( -*.<name>.chars ).tail.<name>;
put 'Symbols for elements whose name starts with "P": ', %periodic<table>.grep( *.<name>.starts-with('P') )».<symbol>;
put "Elements with molecular weight between 20 & 40:\n ",%periodic<table>.grep( {+.<weight> ~~ Numeric and 20 < .<weight> < 40} )».<name>;
put "SCRN: ",                                            %periodic<table>[87,17,92]».<symbol>.join.tclc;


#!/usr/bin/perl
use strict ;
use warnings ;

sub longestCommonSubstr {
   my $first = shift ;
   my $second = shift ;
   my %firstsubs = findSubstrings ( $first );
   my %secondsubs = findSubstrings ( $second ) ;
   my @commonsubs ;
   foreach my $subst ( keys %firstsubs ) {
      if ( exists $secondsubs{ $subst } ) {
	 push ( @commonsubs , $subst ) ;
      }
   }
   my @sorted = sort { length $b <=> length $a } @commonsubs ;
   return $sorted[0] ;
}

sub findSubstrings {
   my $string = shift ;
   my %substrings ;
   my $l = length $string ;
   for ( my $start = 0 ; $start < $l ; $start++ ) {
      for ( my $howmany = 1 ; $howmany < $l - $start + 1 ; $howmany++) {
	 $substrings{substr( $string , $start , $howmany) } = 1 ;
      }
   }
   return %substrings ;
}

my $longest = longestCommonSubstr( "thisisatest" ,"testing123testing" ) ;
print "The longest common substring of <thisisatest> and <testing123testing> is $longest !\n" ;


function lcs(string a, b)
integer longest = 0
string best = ""
    for i=1 to length(a) do
        integer ch = a[i]
        for j=1 to length(b) do
            if ch=b[j] then
                integer n=1
                while i+n<=length(a)
                  and j+n<=length(b)
                  and a[i+n]=b[j+n] do
                    n += 1
                end while
                if n>longest then
                    longest = n
                    best = a[i..i+n-1]
                end if
            end if
        end for
    end for
    return best
end function
?lcs("thisisatest", "testing123testing")
?lcs("testing123testing","thisisatest")


public static String lcs(String a, String b){
    int aLen = a.length();
    int bLen = b.length();
    if(aLen == 0 || bLen == 0){
        return "";
    }else if(a.charAt(aLen-1) == b.charAt(bLen-1)){
        return lcs(a.substring(0,aLen-1),b.substring(0,bLen-1))
            + a.charAt(aLen-1);
    }else{
        String x = lcs(a, b.substring(0,bLen-1));
        String y = lcs(a.substring(0,aLen-1), b);
        return (x.length() > y.length()) ? x : y;
    }
}


/*REXX pgm illustrates how to code a list of words  (named chemical elements  */
/*──────────────────────── ordered by their atomic number)  in a list format. */

$= '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'

                            /* [↑]  element list using continuation  (commas).*/

updated= 'February 29th, 2020'            /*date of the last revision of list.*/
say 'revision date of the list: ' updated /*show the date of the last update. */
elements= space($)                        /*elide excess  blanks   in the list*/
#= words(elements)                        /*the  number of elements "  "   "  */
say 'number of elements in the list: ' #  /*show   "     "    "     "  "   "  */
say 'the last element is: '    word($, #) /*stick a fork in it, we're all done*/


elements = %w(
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)

puts "Last mutation #{ File.mtime(__FILE__) }
number of elements: #{elements.size}
last element: #{elements.last}"


(* space in \ .. \ is ignored *)

val elements = "\
  \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"

fun report lst = print ("\
    \revision date:\t2021-02-25\n\
    \element count:\t" ^ Int.toString (length lst) ^ "\n\
    \last element:\t" ^ List.last lst ^ "\n")

val () = report (String.fields (fn c => c = #" ") elements)


set mtime "2021-05-10 16:11:50"
set elements {
    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
}
set elements [list {*}$elements]; # Normalize string representation

puts "Last modification time: $mtime"
puts "Number of elements:     [llength $elements]"
puts "Last element:           [lindex $elements end]"


  main() {
   elements=(
      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)

    updated=2021-08-30

    printf 'Last update: %s\n' "$updated"
    printf 'Element count: %d\n' ${#elements[@]}
    printf 'Latest element: %s\n' "${elements[-1]}"
  }
  main "[email protected]"


import "/pattern" for Pattern

var elementStr =
    "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"

var p = Pattern.new("+1/s")           // matches 1 or more whitespace characters
var elements = p.splitAll(elementStr) // get a list of elements
elementStr = elements.join(" ")       // recombine using a single space as separator
var lastUpdate = "2020-08-03"
System.print("Last updated       : %(lastUpdate)")
System.print("Number of elements : %(elements.count)")
System.print("Last element       : %(elements[-1])")


(de longestCommonSubstring (Str1 Str2)
   (setq Str1 (chop Str1)  Str2 (chop Str2))
   (let Res NIL
      (map
         '((Lst1)
            (map
               '((Lst2)
                  (let Len 0
                     (find
                        '((A B) (nand (= A B) (inc 'Len)))
                        Lst1
                        Lst2 )
                     (when (> Len (length Res))
                        (setq Res (head Len Lst1)) ) ) )
               Str2 ) )
         Str1 )
      (pack Res) ) )


function lcs([String]$a, [String]$b)
{
    if ([String]::IsNullOrEmpty($a) -or [String]::IsNullOrEmpty($b))
    {
        return ""
    }
    $startIndex, $size = -1, -1
    for ($k = 0; $k -lt $a.Length; ++$k)
    {
        for ($i, $j, $d = $k, 0, 0; ($i -lt $a.Length) -and ($j -lt $b.Length); ++$i, ++$j)
        {
            if ($a.Chars($i) -eq $b.Chars($j))
            {
                $d += 1
                if ($size -lt $d)
                {
                    $startIndex = $i - $d + 1
                    $size = $d
                }
            }
            else
            {
                $d = 0
            }
        }
    }
    for ($k = 1; $k -lt $b.Length; ++$k)
    {
        for ($i, $j, $d = 0, $k, 0; ($i -lt $a.Length) -and ($j -lt $b.Length); ++$i, ++$j)
        {
            if ($a.Chars($i) -eq $b.Chars($j))
            {
                $d += 1
                if ($size -lt $d)
                {
                    $startIndex = $i - $d + 1
                    $size = $d
                }
            }
            else
            {
                $d = 0
            }
        }
    }
    if ($size -lt 0)
    {
        return ""
    }
    return $a.Substring($startIndex, $size)
}

function Print-Lcs([String]$a, [String]$b)
{
    return "lcs $a $b = $(lcs $a $b)"
}
Print-Lcs 'thisisatest' 'testing123testing'
Print-Lcs 'testing' 'sting'
Print-Lcs 'thisisatest_stinger' 'testing123testingthing'
Print-Lcs 'thisisatest_stinger' 'thisis'
Print-Lcs 'testing123testingthing' 'thisis'
Print-Lcs 'thisisatest' 'thisisatest'


function lcs(a, b) {
  var aSub = a.substr(0, a.length - 1);
  var bSub = b.substr(0, b.length - 1);

  if (a.length === 0 || b.length === 0) {
    return '';
  } else if (a.charAt(a.length - 1) === b.charAt(b.length - 1)) {
    return lcs(aSub, bSub) + a.charAt(a.length - 1);
  } else {
    var x = lcs(a, bSub);
    var y = lcs(aSub, b);
    return (x.length > y.length) ? x : y;
  }
}


def lcs(xstr; ystr):
  if (xstr == "" or ystr == "") then ""
  else
    xstr[0:1] as $x
    |  xstr[1:] as $xs
    |  ystr[1:] as $ys
    | if ($x == ystr[0:1]) then ($x + lcs($xs; $ys))
      else
        lcs(xstr; $ys) as $one
	| lcs($xs; ystr) as $two
	| if ($one|length) > ($two|length) then $one else $two end
      end
  end;


revisionDate:="2020-03-23";
elements:=
#<<<"
   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"
   .split();
#<<<
println("Revision date: ",revisionDate);
println(elements.len()," elements, the last being \"",elements[-1],"\"");


common_sublist(A, B, M) :-
	append(_, Ma, A),
	append(M, _, Ma),
	append(_, Mb, B),
	append(M, _, Mb).

longest_list([], L, _, L).
longest_list([L|Ls], LongestList, LongestLength, Result) :-
	length(L, Len),
	Len >= LongestLength -> longest_list(Ls, L, Len, Result)
	; longest_list(Ls, LongestList, LongestLength, Result).

longest_substring(A, B, Result) :-
	string_chars(A, AChars),
	string_chars(B, BChars),
	findall(SubString, (
		dif(SubString, []), common_sublist(AChars, BChars, SubString)
	), AllSubstrings),
	longest_list(AllSubstrings, [], 0, LongestSubString),
	string_chars(Result, LongestSubString).


Procedure.s lcs(a$,b$)
  If Len(a$)>Len(b$) : Swap a$,b$ : EndIf
  l=Len(a$)
  For c=1 To l
    For i=1 To 1+l-c
      If FindString(b$,Mid(a$,i,c))
        res$=Mid(a$,i,c)
      EndIf
    Next
  Next
  ProcedureReturn res$
EndProcedure

t1$="testing123testing"
t2$="thisisatest"
Debug lcs(t1$,t2$)


longest(a::String, b::String) = length(a) ≥ length(b) ? a : b

"""
julia> lcsrecursive("thisisatest", "testing123testing")
"tsitest"
"""
# Recursive
function lcsrecursive(xstr::String, ystr::String)
    if length(xstr) == 0 || length(ystr) == 0
        return ""
    end

    x, xs, y, ys = xstr[1], xstr[2:end], ystr[1], ystr[2:end]
    if x == y
        return string(x, lcsrecursive(xs, ys))
    else
        return longest(lcsrecursive(xstr, ys), lcsrecursive(xs, ystr))
    end
end

# Dynamic
function lcsdynamic(a::String, b::String)
    lengths = zeros(Int, length(a) + 1, length(b) + 1)

    # row 0 and column 0 are initialized to 0 already
    for (i, x) in enumerate(a), (j, y) in enumerate(b)
        if x == y
            lengths[i+1, j+1] = lengths[i, j] + 1
        else
            lengths[i+1, j+1] = max(lengths[i+1, j], lengths[i, j+1])
        end
    end

    # read the substring out from the matrix
    result = ""
    x, y = length(a) + 1, length(b) + 1
    while x > 1 && y > 1
        if lengths[x, y] == lengths[x-1, y]
            x -= 1
        elseif lengths[x, y] == lengths[x, y-1]
            y -= 1
        else
            @assert a[x-1] == b[y-1]
            result = string(a[x-1], result)
            x -= 1
            y -= 1
        end
    end

    return result
end

@show lcsrecursive("thisisatest", "testing123testing")
@time lcsrecursive("thisisatest", "testing123testing")
@show lcsdynamic("thisisatest", "testing123testing")
@time lcsdynamic("thisisatest", "testing123testing")


// version 1.1.2

fun lcs(x: String, y: String): String {
    if (x.length == 0 || y.length == 0) return ""
    val x1 = x.dropLast(1)
    val y1 = y.dropLast(1)
    if (x.last() == y.last()) return lcs(x1, y1) + x.last()
    val x2 = lcs(x, y1)
    val y2 = lcs(x1, y)
    return if (x2.length > y2.length) x2 else y2
}

fun main(args: Array<String>) {
    val x = "thisisatest"
    val y = "testing123testing"
    println(lcs(x, y))
}


s1 = "thisisatest"
s2 = "testing123testing"
len1, len2 = len(s1), len(s2)
ir, jr = 0, -1
for i1 in range(len1):
    i2 = s2.find(s1[i1])
    while i2 >= 0:
        j1, j2 = i1, i2
        while j1 < len1 and j2 < len2 and s2[j2] == s1[j1]:
            if j1-i1 >= jr-ir:
                ir, jr = i1, j1
            j1 += 1; j2 += 1
        i2 = s2.find(s1[i1], i2+1)
print (s1[ir:jr+1])


#lang typed/racket
(: lcs (String String -> String))
(define (lcs a b)
  (: all-substrings# (String -> (HashTable String Boolean)))
  (define (all-substrings# str)
    (define l (string-length str))
    (for*/hash : (HashTable String Boolean)
      ((s (in-range 0 l)) (e (in-range (add1 s) (add1 l))))
      (values (substring str s e) #t)))

  (define a# (all-substrings# a))

  (define b# (all-substrings# b))

  (define-values (s l)
    (for/fold : (Values String Nonnegative-Integer)
    ((s "") (l : Nonnegative-Integer 0))
    ((a_ (in-hash-keys a#))
     #:when (and (> (string-length a_) l) (hash-ref b# a_ #f)))
    (values a_ (string-length a_))))

  s)

(module+ test
  ("thisisatest" . lcs . "testing123testing"))


'variation of BASIC example
w$="aebdef"
z$="cacbc"
print lcs$(w$,z$)

'output:
'ab

wait

FUNCTION lcs$(a$, b$)
    IF LEN(a$) = 0 OR LEN(b$) = 0 THEN
        lcs$ = ""
        exit function
    end if

    IF RIGHT$(a$, 1) = RIGHT$(b$, 1) THEN
        lcs$ = lcs$(LEFT$(a$, LEN(a$) - 1), LEFT$(b$, LEN(b$) - 1)) + RIGHT$(a$, 1)
        exit function
    ELSE
        x$ = lcs$(a$, LEFT$(b$, LEN(b$) - 1))
        y$ = lcs$(LEFT$(a$, LEN(a$) - 1), b$)
        IF LEN(x$) > LEN(y$) THEN
            lcs$ = x$
            exit function
        ELSE
            lcs$ = y$
            exit function
        END IF
    END IF
END FUNCTION


to longest :s :t
  output ifelse greater? count :s count :t [:s] [:t]
end
to lcs :s :t
  if empty? :s [output :s]
  if empty? :t [output :t]
  if equal? first :s first :t [output combine  first :s  lcs bf :s bf :t]
  output longest lcs :s bf :t  lcs bf :s :t
end


sub createSubstrings( Str $word --> Array ) {
   my $length = $word.chars ;
   my @substrings ;
   for (0..$length - 1) -> $start {
      for (1..$length - $start) -> $howmany {
	 @substrings.push( $word.substr( $start , $howmany ) ) ;
      }
   }
   return @substrings ;
}

sub findLongestCommon( Str $first , Str $second --> Str ) {
   my @substringsFirst  = createSubstrings( $first ) ;
   my @substringsSecond = createSubstrings( $second ) ;
   my $firstset  = set( @substringsFirst ) ;
   my $secondset = set( @substringsSecond ) ;
   my $common = $firstset (&) $secondset ;
   return $common.keys.sort({$^b.chars <=> $^a.chars})[0] ; # or: sort(-*.chars)[0]
}

sub MAIN( Str $first , Str $second ) {
   say "The longest common substring of $first and $second is " ~
   "{findLongestCommon( $first , $second ) } !" ;
}


/*REXX program determines the   LCSUBSTR   (Longest Common Substring)  via a function.  */
parse arg a b .                                  /*obtain optional arguments from the CL*/
if a==''  then a= "thisisatest"                  /*Not specified?  Then use the default.*/
if b==''  then b= "testing123testing"            /* "      "         "   "     "    "   */
say '   string A ='            a                 /*echo string A to the terminal screen.*/
say '   string B ='               b              /*  "     "   B  "  "      "       "   */
say '   LCsubstr ='   LCsubstr(a, b)             /*display the Longest Common Substring.*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
LCsubstr: procedure;  parse arg x,y,,$;     #= 0 /*LCsubstr:  Longest Common Substring. */
          L= length(x);     w= length(y)         /*placeholders for string length of X,Y*/
          if w<L  then do;  parse arg y,x;  L= w /*switch X & Y   if Y is shorter than X*/
                       end
             do j=1  for L  while j<=L-#         /*step through start points in string X*/
                do k=L-j+1   to #   by -1        /*step through string lengths.         */
                _= substr(x, j, k)               /*extract a possible common substring. */
                if pos(_, y)\==0  then  if k>#  then do;     $= _;     #= k;      end
                end   /*k*/                      /* [↑]  determine if string _ is longer*/
             end      /*j*/                      /*#:  the current length of  $  string.*/
          return $                               /*$:  (null if there isn't common str.)*/


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" ) )


> StringTools:-LongestCommonSubSequence( "thisisatest", "testing123testing" );
                               "tsitest"


# Project : Longest Common Substring

str1 = "testing123testing"
str2 = "tsitest"
see longest(str1, str2)

func  longest(str1, str2)
subarr = []
for n=1 to len(str1)
    for m=1 to len(str1)
        sub = substr(str1, n, m)
        if substr(str2, sub) > 0
           add(subarr, sub)
        ok
    next
next

temp = 0
for n=1 to len(subarr)
    if len(subarr[n]) > temp
       temp = len(subarr[n])
       subend = subarr[n]
    ok
next
see subend + nl


def longest_common_substring(a,b)
  lengths = Array.new(a.length){Array.new(b.length, 0)}
  greatestLength = 0
  output = ""
  a.each_char.with_index do |x,i|
    b.each_char.with_index do |y,j|
      next if x != y
      lengths[i][j] = (i.zero? || j.zero?) ? 1 : lengths[i-1][j-1] + 1
      if lengths[i][j] > greatestLength
        greatestLength = lengths[i][j]
        output = a[i - greatestLength + 1, greatestLength]
      end
    end
  end
  output
end

p longest_common_substring("thisisatest", "testing123testing")


fn longest_common_substring(s1: &str, s2: &str) -> String {
    let s1_chars: Vec<char> = s1.chars().collect();
    let s2_chars: Vec<char> = s2.chars().collect();
    let mut lcs = "".to_string();

    for i in 0..s1_chars.len() {
        for j in 0..s2_chars.len() {
            if s1_chars[i] == s2_chars[j] {
                let mut tmp_lcs = s2_chars[j].to_string();
                let mut tmp_i = i + 1;
                let mut tmp_j = j + 1;

                while tmp_i < s1_chars.len() && tmp_j < s2_chars.len() && s1_chars[tmp_i] == s2_chars[tmp_j] {
                    tmp_lcs = format!("{}{}", tmp_lcs, s1_chars[tmp_i]);
                    tmp_i += 1;
                    tmp_j += 1;
                }

                if tmp_lcs.len() > lcs.len() {
                    lcs = tmp_lcs;
                }
            }
        }
    }

    lcs
}

fn main() {
    let s1 = "thisisatest";
    let s2 = "testing123testing";
    let lcs = longest_common_substring(s1, s2);
    println!("{}", lcs);
}


def longestCommonSubstringsOptimizedPureFP(left: String, right: String): Option[Set[String]] =
  if (left.nonEmpty && right.nonEmpty) {
    val (shorter, longer) =
      if (left.length < right.length) (left, right)
      else (right, left)

    @scala.annotation.tailrec
    def recursive(
      indexLonger: Int = 0,
      indexShorter: Int = 0,
      currentLongestLength: Int = 0,
      lengthsPrior: List[Int] = List.fill(shorter.length)(0),
      lengths: List[Int] = Nil,
      accumulator: List[Int] = Nil
    ): (Int, List[Int]) =
      if (indexLonger < longer.length) {
        val length =
          if (longer(indexLonger) != shorter(indexShorter)) 0
          else lengthsPrior.head + 1
        val newCurrentLongestLength =
          if (length > currentLongestLength) length
          else currentLongestLength
        val newAccumulator =
          if ((length < currentLongestLength) || (length == 0)) accumulator
          else {
            val entry = indexShorter - length + 1
            if (length > currentLongestLength) List(entry)
            else entry :: accumulator
          }
        if (indexShorter < shorter.length - 1)
          recursive(
            indexLonger,
            indexShorter + 1,
            newCurrentLongestLength,
            lengthsPrior.tail,
            length :: lengths,
            newAccumulator
          )
        else
          recursive(
            indexLonger + 1,
            0,
            newCurrentLongestLength,
            0 :: lengths.reverse,
            Nil,
            newAccumulator
          )
      }
      else (currentLongestLength, accumulator)

    val (length, indexShorters) = recursive()
    if (indexShorters.nonEmpty)
      Some(
        indexShorters
          .map {
            indexShorter =>
              shorter.substring(indexShorter, indexShorter + length)
          }
          .toSet
      )
    else None
  }
  else None

println(longestCommonSubstringsOptimizedPureFP("thisisatest", "testing123testing"))


a = "thisisatest";
b = "testing123testing";
LongestCommonSequence[a, b]


proc lcs(x, y: string): string =
  if x == "" or y == "":
    return ""

  if x[0] == y[0]:
    return x[0] & lcs(x[1..x.high], y[1..y.high])

  let a = lcs(x, y[1..y.high])
  let b = lcs(x[1..x.high], y)
  result = if a.len > b.len: a else: b

echo lcs("1234", "1224533324")
echo lcs("thisisatest", "testing123testing")


let longest xs ys = if List.length xs > List.length ys then xs else ys

let rec lcs a b = match a, b with
   [], _
 | _, []        -> []
 | x::xs, y::ys ->
    if x = y then
      x :: lcs xs ys
    else
      longest (lcs a ys) (lcs xs b)


declare
  fun {LCS Xs Ys}
     case [Xs Ys]
     of [nil _]                   then nil
     [] [_ nil]                   then nil
     [] [X|Xr  Y|Yr] andthen X==Y then X|{LCS Xr Yr}
     [] [_|Xr  _|Yr]              then {Longest {LCS Xs Yr} {LCS Xr Ys}}
     end
  end

  fun {Longest Xs Ys}
     if {Length Xs} > {Length Ys} then Xs else Ys end
  end
in
  {System.showInfo {LCS "thisisatest" "testing123testing"}}


func createSubstrings(String word) -> Array {
  gather {
    combinations(word.len+1, 2, {|i,j|
        take(word.substr(i, j-i))
    })
  }
}

func findLongestCommon(String first, String second) -> String {
    createSubstrings(first) & createSubstrings(second) -> max_by { .len }
}

say findLongestCommon("thisisatest", "testing123testing")


func lComSubStr<
  S0: Sliceable, S1: Sliceable, T: Equatable where
  S0.Generator.Element == T, S1.Generator.Element == T,
  S0.Index.Distance == Int, S1.Index.Distance == Int
  >(w1: S0, _ w2: S1) -> S0.SubSlice {

    var (len, end) = (0, 0)

    let empty = Array(Repeat(count: w2.count + 1, repeatedValue: 0))
    var mat: [[Int]] = Array(Repeat(count: w1.count + 1, repeatedValue: empty))

    for (i, sLett) in w1.enumerate() {
      for (j, tLett) in w2.enumerate() where tLett == sLett {
        let curLen = mat[i][j] + 1
        mat[i + 1][j + 1] = curLen
        if curLen > len {
          len = curLen
          end = i
        }
      }
    }
    return w1[advance(w1.startIndex, (end + 1) - len)...advance(w1.startIndex, end)]
}

func lComSubStr(w1: String, _ w2: String) -> String {
  return String(lComSubStr(w1.characters, w2.characters))
}


Function Longest_common_substring(string1 As String, string2 As String) As String
Dim i As Integer, j As Integer, temp As String, result As String
    For i = 1 To Len(string1)
        For j = 1 To Len(string1)
            temp = Mid(string1, i, j)
            If InStr(string2, temp) Then
                If Len(temp) > Len(result) Then result = temp
            End If
        Next
    Next
    Longest_common_substring = result
End Function

Sub MainLCS()
    Debug.Print Longest_common_substring("thisisatest", "testing123testing")
End Sub


Function lcs(string1,string2)
	For i = 1 To Len(string1)
		tlcs = tlcs & Mid(string1,i,1)
		If InStr(string2,tlcs) Then
			If Len(tlcs) > Len(lcs) Then
				lcs = tlcs
			End If
		Else
			tlcs = ""
		End If
	Next
End Function

WScript.Echo lcs(WScript.Arguments(0),WScript.Arguments(1))


Program LongestCommonSubsequence(output);

function lcs(a, b: string): string;
  var
    x, y: string;
    lenga, lengb: integer;
  begin
    lenga := length(a);
    lengb := length(b);
    lcs := '';
    if (lenga >  0) and (lengb >  0) then
      if a[lenga] =  b[lengb] then
        lcs := lcs(copy(a, 1, lenga-1), copy(b, 1, lengb-1)) + a[lenga]
      else
      begin
        x := lcs(a, copy(b, 1, lengb-1));
        y := lcs(copy(a, 1, lenga-1), b);
        if length(x) > length(y) then
          lcs := x
        else
          lcs := y;
      end;
  end;

var
  s1, s2: string;
begin
  s1 := 'thisisatest';
  s2 := 'testing123testing';
  writeln (lcs(s1, s2));
  s1 := '1234';
  s2 := '1224533324';
  writeln (lcs(s1, s2));
end.


sub lcs {
    my ($a, $b) = @_;
    if (!length($a) || !length($b)) {
        return "";
    }
    if (substr($a, 0, 1) eq substr($b, 0, 1)) {
        return substr($a, 0, 1) . lcs(substr($a, 1), substr($b, 1));
    }
    my $c = lcs(substr($a, 1), $b) || "";
    my $d = lcs($a, substr($b, 1)) || "";
    return length($c) > length($d) ? $c : $d;
}

print lcs("thisisatest", "testing123testing") . "\n";


var lcs = Fn.new { |a, b|
    var la = a.count
    var lb = b.count
    var lengths = List.filled(la * lb, 0)
    var greatestLength = 0
    var output = ""
    var i = 0
    for (x in a) {
        var j = 0
        for (y in b) {
            if (x == y) {
                lengths[i*lb + j] = (i == 0 || j == 0) ? 1 : lengths[(i-1)*lb+j-1] + 1
            }
            if (lengths[i*lb+j] > greatestLength) {
                greatestLength = lengths[i*lb+j]
                output = a[i-greatestLength+1..i]
            }
            j = j + 1
        }
        i = i + 1
    }
    return output
}

System.print(lcs.call("thisisatest", "testing123testing"))


sub LCS$(a$, b$)
    if len(a$) = 0 or len(b$) = 0 then return "" : endif
	while len(b$)
		for j = len(b$) to 1 step -1
			if instr(a$, left$(b$, j)) then return left$(b$, j) : endif
		next j
		b$ = mid$(b$, 2)
	wend
end sub

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


fcn lcd(a,b){
   if(b.len()<a.len()){ t:=a; a=b; b=t; }
   foreach n,m in ([a.len()..1,-1],a.len()-n+1){
      s:=a[m,n];
      if(b.holds(s)) return(s);
   }
   ""
}


with javascript_semantics
function lcs(sequence a, b)
    sequence res = ""
    if length(a) and length(b) then
        if a[$]=b[$] then
            res = lcs(a[1..-2],b[1..-2])&a[$]
        else
            sequence l = lcs(a,b[1..-2]),
                     r = lcs(a[1..-2],b)
            res = iff(length(l)>length(r)?l:r)
        end if
    end if
    return res
end function

constant tests = {{"1234","1224533324"},
                  {"thisisatest","testing123testing"}}
for i=1 to length(tests) do
    string {a,b} = tests[i]
    ?lcs(a,b)
end for


lcs_wiki(X,Y) = V =>
  [C, _Len] = lcs_length(X,Y),
  V = backTrace(C,X,Y,X.length+1,Y.length+1).

lcs_length(X, Y) = V=>
  M = X.length,
  N = Y.length,
  C = [[0 : J in 1..N+1]  : I in 1..N+1],
  foreach(I in 2..M+1,J in 2..N+1)
     if X[I-1] == Y[J-1] then
        C[I,J] := C[I-1,J-1] + 1
     else
        C[I,J] := max([C[I,J-1], C[I-1,J]])
     end
  end,
  V = [C, C[M+1,N+1]].

backTrace(C, X, Y, I, J) = V =>
  if I == 1; J == 1 then
    V = ""
  elseif X[I-1] == Y[J-1] then
    V = backTrace(C, X, Y, I-1, J-1) ++ [X[I-1]]
  else
    if C[I,J-1] > C[I-1,J] then
      V = backTrace(C, X, Y, I, J-1)
    else
      V = backTrace(C, X, Y, I-1, J)
    end
  end.


(de commonSequences (A B)
   (when A
      (conc
         (when (member (car A) B)
            (mapcar '((L) (cons (car A) L))
               (cons NIL (commonSequences (cdr A) (cdr @))) ) )
         (commonSequences (cdr A) B) ) ) )

(maxi length
   (commonSequences
      (chop "thisisatest")
      (chop "testing123testing") ) )


function Get-Lcs ($ReferenceObject, $DifferenceObject)
{
    $longestCommonSubsequence = @()
    $x = $ReferenceObject.Length
    $y = $DifferenceObject.Length

    $lengths = New-Object -TypeName 'System.Object[,]' -ArgumentList ($x + 1), ($y + 1)

    for($i = 0; $i -lt $x; $i++)
    {
        for ($j = 0; $j -lt $y; $j++)
        {
            if ($ReferenceObject[$i] -ceq $DifferenceObject[$j])
            {
                $lengths[($i+1),($j+1)] = $lengths[$i,$j] + 1
            }
            else
            {
                $lengths[($i+1),($j+1)] = [Math]::Max(($lengths[($i+1),$j]),($lengths[$i,($j+1)]))
            }
        }
    }

    while (($x -ne 0) -and ($y -ne 0))
    {
        if ( $lengths[$x,$y] -eq $lengths[($x-1),$y])
        {
            --$x
        }
        elseif ($lengths[$x,$y] -eq $lengths[$x,($y-1)])
        {
            --$y
        }
        else
        {
            if ($ReferenceObject[($x-1)] -ceq $DifferenceObject[($y-1)])
            {
                $longestCommonSubsequence = ,($ReferenceObject[($x-1)]) + $longestCommonSubsequence
            }

            --$x
            --$y
        }
    }

    $longestCommonSubsequence
}


test :-
    time(lcs("thisisatest", "testing123testing", Lcs)),
    writef('%s',[Lcs]).

lcs([ H|L1],[ H|L2],[H|Lcs]) :- !,
    lcs(L1,L2,Lcs).

lcs([H1|L1],[H2|L2],Lcs):-
    lcs(    L1 ,[H2|L2],Lcs1),
    lcs([H1|L1],    L2 ,Lcs2),
    longest(Lcs1,Lcs2,Lcs),!.

lcs(_,_,[]).

longest(L1,L2,Longest) :-
    length(L1,Length1),
    length(L2,Length2),
    ((Length1 > Length2) -> Longest = L1; Longest = L2).


Procedure.s lcs(a$, b$)
  Protected x$ , lcs$
  If Len(a$) = 0 Or Len(b$) = 0
    lcs$ = ""
  ElseIf Right(a$, 1) = Right(b$, 1)
    lcs$ = lcs(Left(a$, Len(a$) - 1), Left(b$, Len(b$) - 1)) + Right(a$, 1)
  Else
    x$ = lcs(a$, Left(b$, Len(b$) - 1))
    y$ = lcs(Left(a$, Len(a$) - 1), b$)
    If Len(x$) > Len(y$)
      lcs$ = x$
    Else
      lcs$ = y$
    EndIf
  EndIf
  ProcedureReturn lcs$
EndProcedure
OpenConsole()
PrintN( lcs("thisisatest", "testing123testing"))
PrintN("Press any key to exit"): Repeat: Until Inkey() <> ""


def lcs(xstr, ystr):
    """
    >>> lcs('thisisatest', 'testing123testing')
    'tsitest'
    """
    if not xstr or not ystr:
        return ""
    x, xs, y, ys = xstr[0], xstr[1:], ystr[0], ystr[1:]
    if x == y:
        return str(lcs(xs, ys)) + x
    else:
        return max(lcs(xstr, ys), lcs(xs, ystr), key=len)


#lang racket
(define (longest xs ys)
  (if (> (length xs) (length ys))
      xs ys))

(define memo (make-hash))
(define (lookup xs ys)
  (hash-ref memo (cons xs ys) #f))
(define (store xs ys r)
  (hash-set! memo (cons xs ys) r)
  r)

(define (lcs/list sx sy)
  (or (lookup sx sy)
      (store sx sy
             (match* (sx sy)
               [((cons x xs) (cons y ys))
                (if (equal? x y)
                    (cons x (lcs/list xs ys))
                    (longest (lcs/list sx ys) (lcs/list xs sy)))]
               [(_ _) '()]))))

(define (lcs sx sy)
  (list->string (lcs/list (string->list sx) (string->list sy))))

(lcs "thisisatest" "testing123testing")


say lcs("thisisatest", "testing123testing");sub lcs(Str $xstr, Str $ystr) {
    return "" unless $xstr && $ystr;

    my ($x, $xs, $y, $ys) = $xstr.substr(0, 1), $xstr.substr(1), $ystr.substr(0, 1), $ystr.substr(1);
    return $x eq $y
        ?? $x ~ lcs($xs, $ys)
        !! max(:by{ $^a.chars }, lcs($xstr, $ys), lcs($xs, $ystr) );
}

say lcs("thisisatest", "testing123testing");


let longest = (xs, ys) =>
  if (List.length(xs) > List.length(ys)) {
    xs;
  } else {
    ys;
  };

let rec lcs = (a, b) =>
  switch (a, b) {
  | ([], _)
  | (_, []) => []
  | ([x, ...xs], [y, ...ys]) =>
    if (x == y) {
      [x, ...lcs(xs, ys)];
    } else {
      longest(lcs(a, ys), lcs(xs, b));
    }
  };


/*REXX program tests the  LCS  (Longest Common Subsequence)  subroutine.                */
parse arg aaa bbb .                              /*obtain optional arguments from the CL*/
say 'string A ='     aaa                         /*echo the string   A   to the screen. */
say 'string B ='     bbb                         /*  "   "     "     B    "  "     "    */
say '     LCS ='     LCS(aaa, bbb)               /*tell the  Longest Common Sequence.   */
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
LCS: procedure; parse arg a,b,z                  /*Longest Common Subsequence.          */
                                                 /*reduce recursions, removes the       */
                                                 /*chars in  A ¬ in B,   and vice─versa.*/
     if z==''  then return LCS( LCS(a,b,0), LCS(b,a,0), 9)   /*Is Z null?   Do recurse. */
     j= length(a)
     if z==0 then do                             /*a special invocation:  shrink  Z.    */
                                      do j=1  for j;                 _= substr(a, j, 1)
                                      if pos(_, b)\==0  then z= z || _
                                      end   /*j*/
                  return substr(z, 2)
                  end
     k= length(b)
     if j==0 | k==0  then return ''              /*Is either string null?    Bupkis.    */
        _= substr(a, j, 1)
     if _==substr(b, k, 1)  then return LCS( substr(a, 1, j - 1), substr(b, 1, k - 1), 9)_
     x= LCS(a, substr(b, 1, k - 1), 9)
     y= LCS(   substr(a, 1, j - 1), b, 9)
     if length(x)>length(y)  then return x
                                  return y


see longest("1267834", "1224533324") + nl

func longest a, b
     if a = "" or b = "" return "" ok
     if right(a, 1) = right(b, 1)
        lcs = longest(left(a, len(a) - 1), left(b, len(b) - 1)) + right(a, 1)
        return lcs
     else
        x1 = longest(a, left(b, len(b) - 1))
        x2 = longest(left(a, len(a) - 1), b)
        if len(x1) > len(x2)
           lcs = x1
           return lcs
        else
           lcs = x2
           return lcs ok ok


=begin
irb(main):001:0> lcs('thisisatest', 'testing123testing')
=> "tsitest"
=end
def lcs(xstr, ystr)
  return "" if xstr.empty? || ystr.empty?

  x, xs, y, ys = xstr[0..0], xstr[1..-1], ystr[0..0], ystr[1..-1]
  if x == y
    x + lcs(xs, ys)
  else
    [lcs(xstr, ys), lcs(xs, ystr)].max_by {|x| x.size}
  end
end


a$	= "aebdaef"
b$	= "cacbac"
print lcs$(a$,b$)
end

FUNCTION lcs$(a$, b$)
IF a$ = "" OR b$ = "" THEN
  lcs$ = ""
  goto [ext]
end if

IF RIGHT$(a$, 1) = RIGHT$(b$, 1) THEN
  lcs$ = lcs$(LEFT$(a$, LEN(a$) - 1), LEFT$(b$, LEN(b$) - 1)) + RIGHT$(a$, 1)
  goto [ext]
 ELSE
  x1$ = lcs$(a$, LEFT$(b$, LEN(b$) - 1))
  x2$ = lcs$(LEFT$(a$, LEN(a$) - 1), b$)
  IF LEN(x1$) > LEN(x2$) THEN
    lcs$ = x1$
    goto [ext]
   ELSE
    lcs$ = x2$
    goto [ext]
  END IF
END IF
[ext]
END FUNCTION