BEGIN
    # find the numbers the string 123456789 ( with "+/-" optionally inserted  #
    # before each digit ) can generate                                        #

    # experimentation shows that the largest hundred numbers that can be      #
    # generated are are greater than or equal to 56795                        #
    # as we can't declare an array with bounds -123456789 : 123456789 in      #
    # Algol 68G, we use -60000 : 60000 and keep counts for the top hundred    #

    INT max number = 60 000;
    [ - max number : max number ]STRING solutions;
    [ - max number : max number ]INT    count;
    FOR i FROM LWB solutions TO UPB solutions DO solutions[ i ] := ""; count[ i ] := 0 OD;

    # calculate the numbers ( up to max number ) we can generate and the strings leading to them  #
    # also determine the largest numbers we can generate #
    [ 100 ]INT largest;
    [ 100 ]INT largest count;
    INT impossible number = - 999 999 999;
    FOR i FROM LWB largest TO UPB largest DO
        largest      [ i ] := impossible number;
        largest count[ i ] := 0
    OD;
    [ 1 : 18 ]CHAR sum string := ".1.2.3.4.5.6.7.8.9";
    []CHAR sign char = []CHAR( "-", " ", "+" )[ AT -1 ];
    # we don't distinguish between strings starting "+1" and starting " 1" #
    FOR s1 FROM -1 TO 0 DO
        sum string[  1 ] := sign char[ s1 ];
        FOR s2 FROM -1 TO 1 DO
            sum string[  3 ] := sign char[ s2 ];
            FOR s3 FROM -1 TO 1 DO
                sum string[  5 ] := sign char[ s3 ];
                FOR s4 FROM -1 TO 1 DO
                    sum string[  7 ] := sign char[ s4 ];
                    FOR s5 FROM -1 TO 1 DO
                        sum string[  9 ] := sign char[ s5 ];
                        FOR s6 FROM -1 TO 1 DO
                            sum string[ 11 ] := sign char[ s6 ];
                            FOR s7 FROM -1 TO 1 DO
                                sum string[ 13 ] := sign char[ s7 ];
                                FOR s8 FROM -1 TO 1 DO
                                    sum string[ 15 ] := sign char[ s8 ];
                                    FOR s9 FROM -1 TO 1 DO
                                        sum string[ 17 ] := sign char[ s9 ];
                                        INT number := 0;
                                        INT part   := IF s1 < 0 THEN -1 ELSE 1 FI;
                                        IF s2 = 0 THEN part *:= 10 +:= 2 * SIGN part ELSE number +:= part; part := 2 * s2 FI;
                                        IF s3 = 0 THEN part *:= 10 +:= 3 * SIGN part ELSE number +:= part; part := 3 * s3 FI;
                                        IF s4 = 0 THEN part *:= 10 +:= 4 * SIGN part ELSE number +:= part; part := 4 * s4 FI;
                                        IF s5 = 0 THEN part *:= 10 +:= 5 * SIGN part ELSE number +:= part; part := 5 * s5 FI;
                                        IF s6 = 0 THEN part *:= 10 +:= 6 * SIGN part ELSE number +:= part; part := 6 * s6 FI;
                                        IF s7 = 0 THEN part *:= 10 +:= 7 * SIGN part ELSE number +:= part; part := 7 * s7 FI;
                                        IF s8 = 0 THEN part *:= 10 +:= 8 * SIGN part ELSE number +:= part; part := 8 * s8 FI;
                                        IF s9 = 0 THEN part *:= 10 +:= 9 * SIGN part ELSE number +:= part; part := 9 * s9 FI;
                                        number +:= part;
                                        IF  number >= LWB solutions
                                        AND number <= UPB solutions
                                        THEN
                                            solutions[ number ] +:= ";" + sum string;
                                            count    [ number ] +:= 1
                                        FI;
                                        BOOL inserted := FALSE;
                                        FOR l pos FROM LWB largest TO UPB largest WHILE NOT inserted DO
                                            IF number > largest[ l pos ] THEN
                                                # found a new larger number #
                                                FOR m pos FROM UPB largest BY -1 TO l pos + 1 DO
                                                    largest      [ m pos ] := largest      [ m pos - 1 ];
                                                    largest count[ m pos ] := largest count[ m pos - 1 ]
                                                OD;
                                                largest      [ l pos ] := number;
                                                largest count[ l pos ] := 1;
                                                inserted := TRUE
                                            ELIF number = largest[ l pos ] THEN
                                                # have another way of generating this number #
                                                largest count[ l pos ] +:= 1;
                                                inserted := TRUE
                                            FI
                                        OD
                                    OD
                                OD
                            OD
                        OD
                    OD
                OD
            OD
        OD
    OD;

    # show the solutions for 100 #
    print( ( "100 has ", whole( count[ 100 ], 0 ), " solutions:" ) );
    STRING s := solutions[ 100 ];
    FOR s pos FROM LWB s TO UPB s DO
        IF   s[ s pos ] = ";" THEN print( ( newline, "        " ) )
        ELIF s[ s pos ] /= " " THEN print( ( s[ s pos ] ) )
        FI
    OD;
    print( ( newline ) );
    # find the number with the most solutions #
    INT max solutions := 0;
    INT number with max := LWB count - 1;
    FOR n FROM 0 TO max number DO
        IF count[ n ] > max solutions THEN
            max solutions := count[ n ];
            number with max := n
        FI
    OD;
    FOR n FROM LWB largest count TO UPB largest count DO
        IF largest count[ n ] > max solutions THEN
            max solutions := largest count[ n ];
            number with max := largest[ n ]
        FI
    OD;
    print( ( whole( number with max, 0 ), " has the maximum number of solutions: ", whole( max solutions, 0 ), newline ) );
    # find the smallest positive number that has no solutions #
    BOOL have solutions := TRUE;
    FOR n FROM 0 TO max number
    WHILE IF NOT ( have solutions := count[ n ] > 0 )
          THEN print( ( whole( n, 0 ), " is the lowest positive number with no solutions", newline ) )
          FI;
          have solutions
    DO SKIP OD;
    IF have solutions
    THEN print( ( "All positive numbers up to ", whole( max number, 0 ), " have solutions", newline ) )
    FI;
    print( ( "The 10 largest numbers that can be generated are:", newline ) );
    FOR t pos FROM 1 TO 10 DO
        print( ( " ", whole( largest[ t pos ], 0 ) ) )
    OD;
    print( ( newline ) )

END


use framework "Foundation" -- for basic NSArray sort

property pSigns : {1, 0, -1} --> ( + | unsigned | - )
property plst100 : {"Sums to 100:", ""}
property plstSums : {}
property plstSumsSorted : missing value
property plstSumGroups : missing value

-- data Sign :: [ 1 | 0 | -1 ] = ( Plus | Unsigned | Minus )
-- asSum :: [Sign] -> Int
on asSum(xs)
    script
        on |λ|(a, sign, i)
            if sign ≠ 0 then
                {digits:{}, n:(n of a) + (sign * ((i & digits of a) as string as integer))}
            else
                {digits:{i} & (digits of a), n:n of a}
            end if
        end |λ|
    end script

    set rec to foldr(result, {digits:{}, n:0}, xs)
    set ds to digits of rec
    if length of ds > 0 then
        (n of rec) + (ds as string as integer)
    else
        n of rec
    end if
end asSum

-- data Sign :: [ 1 | 0 | -1 ] = ( Plus | Unisigned | Minus )
-- asString :: [Sign] -> String
on asString(xs)
    script
        on |λ|(a, sign, i)
            set d to i as string
            if sign ≠ 0 then
                if sign > 0 then
                    a & " +" & d
                else
                    a & " -" & d
                end if
            else
                a & d
            end if
        end |λ|
    end script

    foldl(result, "", xs)
end asString

-- sumsTo100 :: () -> String
on sumsTo100()
    -- From first permutation without leading '+' (3 ^ 8) to end of universe (3 ^ 9)
    repeat with i from 6561 to 19683
        set xs to nthPermutationWithRepn(pSigns, 9, i)
        if asSum(xs) = 100 then set end of plst100 to asString(xs)
    end repeat
    intercalate(linefeed, plst100)
end sumsTo100

-- mostCommonSum :: () -> String
on mostCommonSum()
    -- From first permutation without leading '+' (3 ^ 8) to end of universe (3 ^ 9)
    repeat with i from 6561 to 19683
        set intSum to asSum(nthPermutationWithRepn(pSigns, 9, i))
        if intSum ≥ 0 then set end of plstSums to intSum
    end repeat

    set plstSumsSorted to sort(plstSums)
    set plstSumGroups to group(plstSumsSorted)

    script groupLength
        on |λ|(a, b)
            set intA to length of a
            set intB to length of b
            if intA < intB then
                -1
            else if intA > intB then
                1
            else
                0
            end if
        end |λ|
    end script

    set lstMaxSum to maximumBy(groupLength, plstSumGroups)
    intercalate(linefeed, ¬
        {"Most common sum: " & item 1 of lstMaxSum, ¬
            "Number of instances: " & length of lstMaxSum})
end mostCommonSum

-- TEST ----------------------------------------------------------------------
on run
    return sumsTo100()

    -- Also returns a value, but slow:
    -- mostCommonSum()
end run

-- GENERIC FUNCTIONS ---------------------------------------------------------

-- nthPermutationWithRepn :: [a] -> Int -> Int -> [a]
on nthPermutationWithRepn(xs, groupSize, iIndex)
    set intBase to length of xs
    set intSetSize to intBase ^ groupSize

    if intBase < 1 or iIndex > intSetSize then
        {}
    else
        set baseElems to inBaseElements(xs, iIndex)
        set intZeros to groupSize - (length of baseElems)

        if intZeros > 0 then
            replicate(intZeros, item 1 of xs) & baseElems
        else
            baseElems
        end if
    end if
end nthPermutationWithRepn

-- inBaseElements :: [a] -> Int -> [String]
on inBaseElements(xs, n)
    set intBase to length of xs

    script nextDigit
        on |λ|(residue)
            set {divided, remainder} to quotRem(residue, intBase)

            {valid:divided > 0, value:(item (remainder + 1) of xs), new:divided}
        end |λ|
    end script

    reverse of unfoldr(nextDigit, n)
end inBaseElements

-- sort :: [a] -> [a]
on sort(lst)
    ((current application's NSArray's arrayWithArray:lst)'s ¬
        sortedArrayUsingSelector:"compare:") as list
end sort

-- maximumBy :: (a -> a -> Ordering) -> [a] -> a
on maximumBy(f, xs)
    set cmp to mReturn(f)
    script max
        on |λ|(a, b)
            if a is missing value or cmp's |λ|(a, b) < 0 then
                b
            else
                a
            end if
        end |λ|
    end script

    foldl(max, missing value, xs)
end maximumBy

-- group :: Eq a => [a] -> [[a]]
on group(xs)
    script eq
        on |λ|(a, b)
            a = b
        end |λ|
    end script

    groupBy(eq, xs)
end group

-- groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
on groupBy(f, xs)
    set mf to mReturn(f)

    script enGroup
        on |λ|(a, x)
            if length of (active of a) > 0 then
                set h to item 1 of active of a
            else
                set h to missing value
            end if

            if h is not missing value and mf's |λ|(h, x) then
                {active:(active of a) & x, sofar:sofar of a}
            else
                {active:{x}, sofar:(sofar of a) & {active of a}}
            end if
        end |λ|
    end script

    if length of xs > 0 then
        set dct to foldl(enGroup, {active:{item 1 of xs}, sofar:{}}, tail(xs))
        if length of (active of dct) > 0 then
            sofar of dct & {active of dct}
        else
            sofar of dct
        end if
    else
        {}
    end if
end groupBy

-- tail :: [a] -> [a]
on tail(xs)
    if length of xs > 1 then
        items 2 thru -1 of xs
    else
        {}
    end if
end tail

-- intercalate :: Text -> [Text] -> Text
on intercalate(strText, lstText)
    set {dlm, my text item delimiters} to {my text item delimiters, strText}
    set strJoined to lstText as text
    set my text item delimiters to dlm
    return strJoined
end intercalate

--  quotRem :: Integral a => a -> a -> (a, a)
on quotRem(m, n)
    {m div n, m mod n}
end quotRem

-- replicate :: Int -> a -> [a]
on replicate(n, a)
    set out to {}
    if n < 1 then return out
    set dbl to {a}

    repeat while (n > 1)
        if (n mod 2) > 0 then set out to out & dbl
        set n to (n div 2)
        set dbl to (dbl & dbl)
    end repeat
    return out & dbl
end replicate

-- foldr :: (a -> b -> a) -> a -> [b] -> a
on foldr(f, startValue, xs)
    tell mReturn(f)
        set v to startValue
        set lng to length of xs
        repeat with i from lng to 1 by -1
            set v to |λ|(v, item i of xs, i, xs)
        end repeat
        return v
    end tell
end foldr

-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
    tell mReturn(f)
        set v to startValue
        set lng to length of xs
        repeat with i from 1 to lng
            set v to |λ|(v, item i of xs, i, xs)
        end repeat
        return v
    end tell
end foldl

-- unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
on unfoldr(f, v)
    set mf to mReturn(f)
    set lst to {}
    set recM to mf's |λ|(v)
    repeat while (valid of recM) is true
        set end of lst to value of recM
        set recM to mf's |λ|(new of recM)
    end repeat
    lst & value of recM
end unfoldr

-- until :: (a -> Bool) -> (a -> a) -> a -> a
on |until|(p, f, x)
    set mp to mReturn(p)
    set v to x

    tell mReturn(f)
        repeat until mp's |λ|(v)
            set v to |λ|(v)
        end repeat
    end tell
    return v
end |until|

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn


output:=""
for k, v in (sum2num(100))
    output .= k "`n"
MsgBox, 262144, , % output

mx := []
loop 123456789{
    x := sum2num(A_Index)
    mx[x.Count()] := mx[x.Count()] ? mx[x.Count()] ", " A_Index : A_Index
}
MsgBox, 262144, , % mx[mx.MaxIndex()] " has " mx.MaxIndex() " solutions"

loop {
    if !sum2num(A_Index).Count(){
        MsgBox, 262144, , % "Lowest positive sum that can't be expressed is " A_Index
        break
    }
}
return

sum2num(num){
    output := []
    loop % 6561
    {
        oper := SubStr("00000000" ConvertBase(10, 3, A_Index-1), -7)
        oper := StrReplace(oper, 0, "+")
        oper := StrReplace(oper, 1, "-")
        oper := StrReplace(oper, 2, ".")
        str := ""
        loop 9
            str .= A_Index . SubStr(oper, A_Index, 1)
        str := StrReplace(str, ".")
        loop 2
        {
            val := 0
            for i, v in StrSplit(str, "+")
                for j, m in StrSplit(v, "-")
                    val += A_Index=1 ? m : 0-m
            if (val = num)
                output[str] := true
            str := "-" str
        }
    }
    Sort, output
    return output
}

; https://www.autohotkey.com/boards/viewtopic.php?p=21143&sid=02b9c92ea98737f1db6067b80a2a59cd#p21143
ConvertBase(InputBase, OutputBase, nptr){
    static u := A_IsUnicode ? "_wcstoui64" : "_strtoui64"
    static v := A_IsUnicode ? "_i64tow"    : "_i64toa"
    VarSetCapacity(s, 66, 0)
    value := DllCall("msvcrt.dll\" u, "Str", nptr, "UInt", 0, "UInt", InputBase, "CDECL Int64")
    DllCall("msvcrt.dll\" v, "Int64", value, "Str", s, "UInt", OutputBase, "CDECL")
    return s
}


#
# RossetaCode: Sum to 100, AWK.
#
# Find solutions to the "sum to one hundred" puzzle.

function evaluate(code)
{
    value  = 0
    number = 0
    power  = 1
    for ( k = 9; k >= 1; k-- )
    {
        number = power*k + number
        op = code % 3
        if ( op == 0 ) {
            value = value + number
            number = 0
            power = 1
        } else if (op == 1 ) {
            value = value - number
            number = 0
            power = 1
        } else if ( op == 2) {
            power = power * 10
        } else {
        }
        code = int(code / 3);
    }
    return value;
}

function show(code)
{
    s = ""
    a = 19683
    b = 6561

    for ( k = 1; k <= 9; k++ )
    {
        op = int( (code % a) / b )
        if ( op == 0 && k > 1 )
            s = s "+"
        else if ( op == 1 )
            s = s "-"
        else {
        }
        a = b
        b = int(b / 3)
        s = s  k
    }
    printf "%9d = %s\n", evaluate(code), s;
}

BEGIN {
    nexpr = 13122

    print
    print "Show all solutions that sum to 100"
    print
    for ( i = 0; i < nexpr; i++ ) if ( evaluate(i) == 100 ) show(i);

    print
    print "Show the sum that has the maximum number of solutions"
    print
    for ( i = 0; i < nexpr; i++ ) {
        sum = evaluate(i);
        if ( sum >= 0 )
            stat[sum]++;
    }
    best = (-1);
    for ( sum in stat )
        if ( best < stat[sum] ) {
            best = stat[sum]
            bestSum = sum
        }
    delete stat
    printf "%d has %d solutions\n", bestSum, best

    print
    print "Show the lowest positive number that can't be expressed"
    print
    for ( i = 0; i <= 123456789; i++ ){
        for ( j = 0; j < nexpr; j++ )
            if ( i == evaluate(j) )
                break;
        if ( i != evaluate(j) )
            break;
    }
    printf "%d\n",i

    print
    print "Show the ten highest numbers that can be expressed"
    print
    limit = 123456789 + 1;
    for ( i = 1; i <= 10; i++ )
    {
        best = 0;
        for ( j = 0; j < nexpr; j++ )
        {
            test = evaluate(j);
            if ( test < limit && test > best ) best = test;
        }
        for ( j = 0; j < nexpr; j++ ) if ( evaluate(j) == best ) show(j)
        limit = best
    }
}


/*
 * RossetaCode: Sum to 100, C99, an algorithm using ternary numbers.
 *
 * Find solutions to the "sum to one hundred" puzzle.
 */

#include <stdio.h>
#include <stdlib.h>

/*
 * There are only 13122 (i.e. 2*3**8) different possible expressions,
 * thus we can encode them as positive integer numbers from 0 to 13121.
 */
#define NUMBER_OF_EXPRESSIONS (2 * 3*3*3*3 * 3*3*3*3 )
enum OP { ADD, SUB, JOIN };
typedef int (*cmp)(const void*, const void*);

// Replacing struct Expression and struct CountSum by a tuple like
// struct Pair { int first; int last; } is possible but would make the source
// code less readable.

struct Expression{
    int sum;
    int code;
}expressions[NUMBER_OF_EXPRESSIONS];
int expressionsLength = 0;
int compareExpressionBySum(const struct Expression* a, const struct Expression* b){
    return a->sum - b->sum;
}

struct CountSum{
    int counts;
    int sum;
}countSums[NUMBER_OF_EXPRESSIONS];
int countSumsLength = 0;
int compareCountSumsByCount(const struct CountSum* a, const struct CountSum* b){
    return a->counts - b->counts;
}

int evaluate(int code){
    int value  = 0, number = 0, power  = 1;
    for ( int k = 9; k >= 1; k-- ){
        number = power*k + number;
        switch( code % 3 ){
            case ADD:  value = value + number; number = 0; power = 1; break;
            case SUB:  value = value - number; number = 0; power = 1; break;
            case JOIN: power = power * 10                ; break;
        }
        code /= 3;
    }
    return value;
}

void print(int code){
    static char s[19]; char* p = s;
    int a = 19683, b = 6561;
    for ( int k = 1; k <= 9; k++ ){
        switch((code % a) / b){
            case ADD: if ( k > 1 ) *p++ = '+'; break;
            case SUB:              *p++ = '-'; break;
        }
        a = b;
        b = b / 3;
        *p++ = '0' + k;
    }
    *p = 0;
    printf("%9d = %s\n", evaluate(code), s);
}

void comment(char* string){
    printf("\n\n%s\n\n", string);
}

void init(void){
    for ( int i = 0; i < NUMBER_OF_EXPRESSIONS; i++ ){
        expressions[i].sum = evaluate(i);
        expressions[i].code = i;
    }
    expressionsLength = NUMBER_OF_EXPRESSIONS;
    qsort(expressions,expressionsLength,sizeof(struct Expression),(cmp)compareExpressionBySum);

    int j = 0;
    countSums[0].counts = 1;
    countSums[0].sum = expressions[0].sum;
    for ( int i = 0; i < expressionsLength; i++ ){
        if ( countSums[j].sum != expressions[i].sum ){
            j++;
            countSums[j].counts = 1;
            countSums[j].sum = expressions[i].sum;
        }
        else
            countSums[j].counts++;
    }
    countSumsLength = j + 1;
    qsort(countSums,countSumsLength,sizeof(struct CountSum),(cmp)compareCountSumsByCount);
}

int main(void){

    init();

    comment("Show all solutions that sum to 100");
    const int givenSum = 100;
    struct Expression ex = { givenSum, 0 };
    struct Expression* found;
    if ( found = bsearch(&ex,expressions,expressionsLength,
        sizeof(struct Expression),(cmp)compareExpressionBySum) ){
        while ( found != expressions && (found-1)->sum == givenSum )
            found--;
        while ( found != &expressions[expressionsLength] && found->sum == givenSum )
            print(found++->code);
    }

    comment("Show the positve sum that has the maximum number of solutions");
    int maxSumIndex = countSumsLength - 1;
    while( countSums[maxSumIndex].sum < 0 )
        maxSumIndex--;
    printf("%d has %d solutions\n",
        countSums[maxSumIndex].sum, countSums[maxSumIndex].counts);

    comment("Show the lowest positive number that can't be expressed");
    for ( int value = 0; ; value++ ){
        struct Expression ex = { value, 0 };
        if (!bsearch(&ex,expressions,expressionsLength,
                sizeof(struct Expression),(cmp)compareExpressionBySum)){
            printf("%d\n", value);
            break;
        }
    }

    comment("Show the ten highest numbers that can be expressed");
    for ( int i = expressionsLength-1; i >= expressionsLength-10; i-- )
        print(expressions[i].code);

    return 0;
}


using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        // All unique expressions that have a plus sign in front of the 1; calculated in parallel
        var expressionsPlus = Enumerable.Range(0, (int)Math.Pow(3, 8)).AsParallel().Select(i => new Expression(i, 1));
        // All unique expressions that have a minus sign in front of the 1; calculated in parallel
        var expressionsMinus = Enumerable.Range(0, (int)Math.Pow(3, 8)).AsParallel().Select(i => new Expression(i, -1));
        var expressions = expressionsPlus.Concat(expressionsMinus);
        var results = new Dictionary<int, List<Expression>>();
        foreach (var e in expressions)
        {
            if (results.Keys.Contains(e.Value))
                results[e.Value].Add(e);
            else
                results[e.Value] = new List<Expression>() { e };
        }
        Console.WriteLine("Show all solutions that sum to 100");
        foreach (Expression e in results[100])
            Console.WriteLine("  " + e);
        Console.WriteLine("Show the sum that has the maximum number of solutions (from zero to infinity)");
        var summary = results.Keys.Select(k => new Tuple<int, int>(k, results[k].Count));
        var maxSols = summary.Aggregate((a, b) => a.Item2 > b.Item2 ? a : b);
        Console.WriteLine("  The sum " + maxSols.Item1 + " has " + maxSols.Item2 + " solutions.");
        Console.WriteLine("Show the lowest positive sum that can't be expressed (has no solutions), using the rules for this task");
        var lowestPositive = Enumerable.Range(1, int.MaxValue).First(x => !results.Keys.Contains(x));
        Console.WriteLine("  " + lowestPositive);
        Console.WriteLine("Show the ten highest numbers that can be expressed using the rules for this task (extra credit)");
        var highest = from k in results.Keys
                      orderby k descending
                      select k;
        foreach (var x in highest.Take(10))
            Console.WriteLine("  " + x);
    }
}
public enum Operations { Plus, Minus, Join };
public class Expression
{
    protected Operations[] Gaps;
    // 123456789 => there are 8 "gaps" between each number
    ///             with 3 possibilities for each gap: plus, minus, or join
    public int Value; // What this expression sums up to
    protected int _one;

    public Expression(int serial, int one)
    {
        _one = one;
        Gaps = new Operations[8];
        // This represents "serial" as a base 3 number, each Gap expression being a base-three digit
        int divisor = 2187; // == Math.Pow(3,7)
        int times;
        for (int i = 0; i < 8; i++)
        {
            times = Math.DivRem(serial, divisor, out serial);
            divisor /= 3;
            if (times == 0)
                Gaps[i] = Operations.Join;
            else if (times == 1)
                Gaps[i] = Operations.Minus;
            else
                Gaps[i] = Operations.Plus;
        }
        // go ahead and calculate the value of this expression
        // because this is going to be done in a parallel thread (save time)
        Value = Evaluate();
    }
    public override string ToString()
    {
        string ret = _one.ToString();
        for (int i = 0; i < 8; i++)
        {
            switch (Gaps[i])
            {
                case Operations.Plus:
                    ret += "+";
                    break;
                case Operations.Minus:
                    ret += "-";
                    break;
            }
            ret += (i + 2);
        }
        return ret;
    }
    private int Evaluate()
        /* Calculate what this expression equals */
    {
        var numbers = new int[9];
        int nc = 0;
        var operations = new List<Operations>();
        int a = 1;
        for (int i = 0; i < 8; i++)
        {
            if (Gaps[i] == Operations.Join)
                a = a * 10 + (i + 2);
            else
            {
                if (a > 0)
                {
                    if (nc == 0)
                        a *= _one;
                    numbers[nc++] = a;
                    a = i + 2;
                }
                operations.Add(Gaps[i]);
            }
        }
        if (nc == 0)
            a *= _one;
        numbers[nc++] = a;
        int ni = 0;
        int left = numbers[ni++];
        foreach (var operation in operations)
        {
            int right = numbers[ni++];
            if (operation == Operations.Plus)
                left = left + right;
            else
                left = left - right;
        }
        return left;
    }
}


PROC PrintMatrix(INT ARRAY m BYTE size)
  BYTE x,y
  INT v

  FOR y=0 TO size-1
  DO
    FOR x=0 TO size-1
    DO
      v=m(x+y*size)
      IF v<10 THEN Put(32) FI
      PrintB(v) Put(32)
    OD
    PutE()
  OD
RETURN

INT FUNC SumBelowDiagonal(INT ARRAY m BYTE size)
  BYTE x,y
  INT sum

  sum=0
  FOR y=1 TO size-1
  DO
    FOR x=0 TO y-1
    DO
      sum==+m(x+y*size)
    OD
  OD
RETURN (sum)

PROC Main()
  INT sum
  INT ARRAY m=[
     1  3  7  8 10
     2  4 16 14  4
     3  1  9 18 11
    12 14 17 18 20
     7  1  3  9  5]

  PrintE("Matrix")
  PrintMatrix(m,5)
  PutE()
  sum=SumBelowDiagonal(m,5)
  PrintF("Sum below diagonal is %I",sum)
RETURN


with Ada.Text_Io;
with Ada.Numerics.Generic_Real_Arrays;

procedure Sum_Below_Diagonals is

   type Real is new Float;

   package Real_Arrays
   is new Ada.Numerics.Generic_Real_Arrays (Real);

   function Sum_Below_Diagonal (M : Real_Arrays.Real_Matrix) return Real
   with Pre => M'Length (1) = M'Length (2)
   is
      Sum : Real := 0.0;
   begin
      for Row in 0 .. M'Length (1) - 1 loop
         for Col in 0 .. Row - 1 loop
            Sum := Sum + M (M'First (1) + Row,
                            M'First (2) + Col);
         end loop;
      end loop;
      return Sum;
   end Sum_Below_Diagonal;

   M : constant Real_Arrays.Real_Matrix :=
     (( 1.0,  3.0,  7.0,  8.0, 10.0),
      ( 2.0,  4.0, 16.0, 14.0,  4.0),
      ( 3.0,  1.0,  9.0, 18.0, 11.0),
      (12.0, 14.0, 17.0, 18.0, 20.0),
      ( 7.0,  1.0,  3.0,  9.0,  5.0));
   Sum : constant Real := Sum_Below_Diagonal (M);

   package Real_Io is new Ada.Text_Io.Float_Io (Real);
   use Ada.Text_Io, Real_Io;
begin
   Put ("Sum below diagonal: ");
   Put (Sum, Exp => 0, Aft => 1);
   New_Line;
end Sum_Below_Diagonals;


BEGIN # sum the elements below the main diagonal of a matrix  #
    # returns the sum of the elements below the main diagonal #
    # of m, m must be a square matrix                         #
    OP   LOWERSUM = ( [,]INT m )INT:
         IF 1 LWB m /= 2 LWB m OR 1 UPB m /= 2 UPB m THEN
            # the matrix isn't square                         #
            print( ( "Matrix must be suare for LOWERSUM", newline ) );
            stop
         ELSE
            # have a square matrix                            #
            INT sum := 0;
            FOR r FROM 1 LWB m + 1 TO 1 UPB m DO
                 FOR c FROM 1 LWB m TO r - 1 DO
                     sum +:= m[ r, c ]
                 OD
            OD;
            sum
         FI; # LOWERSUM #
    # task test case                                          #
    print( ( whole( LOWERSUM [,]INT( (  1,  3,  7,  8, 10 )
                                   , (  2,  4, 16, 14,  4 )
                                   , (  3,  1,  9, 18, 11 )
                                   , ( 12, 14, 17, 18, 20 )
                                   , (  7,  1,  3,  9,  5 )
                                   )
                  , 0
                  )
            , newline
            )
          )
END


/*
 * RossetaCode: Sum to 100, C++, STL, OOP.
 * Works with: MSC 16.0 (MSVS2010); GCC 5.1 (use -std=c++11 or -std=c++14 etc.).
 *
 * Find solutions to the "sum to one hundred" puzzle.
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <set>
#include <map>

using namespace std;

class Expression{
    private:
        enum { NUMBER_OF_DIGITS = 9 }; // hack for C++98, use const int in C++11
        enum Op { ADD, SUB, JOIN };
        int code[NUMBER_OF_DIGITS];
    public:
        static const int NUMBER_OF_EXPRESSIONS;
        Expression(){
            for ( int i = 0; i < NUMBER_OF_DIGITS; i++ )
                code[i] = ADD;
        }
        Expression& operator++(int){ // post incrementation
            for ( int i = 0; i < NUMBER_OF_DIGITS; i++ )
                if ( ++code[i] > JOIN ) code[i] = ADD;
                else break;
            return *this;
        }
        operator int() const{
            int value = 0, number = 0, sign = (+1);
            for ( int digit = 1; digit <= 9; digit++ )
                switch ( code[NUMBER_OF_DIGITS - digit] ){
                case ADD: value += sign*number; number = digit; sign = (+1); break;
                case SUB: value += sign*number; number = digit; sign = (-1); break;
                case JOIN:                      number = 10*number + digit;  break;
            }
            return value + sign*number;
        }
        operator string() const{
            string s;
            for ( int digit = 1; digit <= NUMBER_OF_DIGITS; digit++ ){
                switch( code[NUMBER_OF_DIGITS - digit] ){
                    case ADD: if ( digit > 1 ) s.push_back('+'); break;
                    case SUB:                  s.push_back('-'); break;
                }
                s.push_back('0' + digit);
            }
            return s;
        }
};
const int Expression::NUMBER_OF_EXPRESSIONS = 2 * 3*3*3*3 * 3*3*3*3;

ostream& operator<< (ostream& os, Expression& ex){
    ios::fmtflags oldFlags(os.flags());
    os << setw(9) << right << static_cast<int>(ex)    << " = "
       << setw(0) << left  << static_cast<string>(ex) << endl;
    os.flags(oldFlags);
    return os;
}

struct Stat{
    map<int,int> countSum;
    map<int, set<int> > sumCount;
    Stat(){
        Expression expression;
        for ( int i = 0; i < Expression::NUMBER_OF_EXPRESSIONS; i++, expression++ )
            countSum[expression]++;
        for ( auto it = countSum.begin(); it != countSum.end(); it++ )
            sumCount[it->second].insert(it->first);
    }
};

void print(int givenSum){
    Expression expression;
    for ( int i = 0; i < Expression::NUMBER_OF_EXPRESSIONS; i++, expression++ )
        if ( expression == givenSum )
            cout << expression;
}

void comment(string commentString){
    cout << endl << commentString << endl << endl;
}

int main(){
    Stat stat;

    comment( "Show all solutions that sum to 100" );
    const int givenSum = 100;
    print(givenSum);

    comment( "Show the sum that has the maximum number of solutions" );
    auto maxi = max_element(stat.sumCount.begin(),stat.sumCount.end());
    auto it = maxi->second.begin();
    while ( *it < 0 ) it++;
    cout << static_cast<int>(*it) << " has " << maxi->first << " solutions" << endl;

    comment( "Show the lowest positive number that can't be expressed" );
    int value = 0;
    while(stat.countSum.count(value) != 0) value++;
    cout << value << endl;

    comment( "Show the ten highest numbers that can be expressed" );
    auto rit = stat.countSum.rbegin();
    for ( int i = 0; i < 10; i++, rit++ ) print(rit->first);

    return 0;
}


begin % sum the elements below the main diagonal of a matrix  %
    % returns the sum of the elements below the main diagonal %
    % of m, m must have bounds lb :: ub, lb :: ub             %
    integer procedure lowerSum ( integer array m ( *, * )
                               ; integer value lb, ub
                               ) ;
    begin
        integer sum;
        sum := 0;
        for r := lb + 1 until ub do begin
             for c := lb until r - 1 do sum := sum + m( r, c )
        end for_r;
        sum
    end lowerSum ;
    begin % task test case                                    %
        integer array m ( 1 :: 5, 1 :: 5 );
        integer r, c;
        r := 1; c := 0; for v :=  1,  3,  7,  8, 10 do begin c := c + 1; m( r, c ) := v end;
        r := 2; c := 0; for v :=  2,  4, 16, 14,  4 do begin c := c + 1; m( r, c ) := v end;
        r := 3; c := 0; for v :=  3,  1,  9, 18, 11 do begin c := c + 1; m( r, c ) := v end;
        r := 4; c := 0; for v := 12, 14, 17, 18, 20 do begin c := c + 1; m( r, c ) := v end;
        r := 5; c := 0; for v :=  7,  1,  3,  9,  5 do begin c := c + 1; m( r, c ) := v end;
        write( i_w := 1, lowerSum( m, 1, 5 ) )
    end
end.


matrx :=[[1,3,7,8,10]
		,[2,4,16,14,4]
		,[3,1,9,18,11]
		,[12,14,17,18,20]
		,[7,1,3,9,5]]
sumA := sumB := sumD :=  sumAll := 0
for r, obj in matrx
	for c, val in obj
		sumAll += val
		,sumA += r<c ? val : 0
		,sumB += r>c ? val : 0
		,sumD += r=c ? val : 0

MsgBox % result := "sum above diagonal = " sumA
. "`nsum below diagonal = " sumB
. "`nsum on diagonal = " sumD
. "`nsum all = " sumAll


# syntax: GAWK -f SUM_OF_ELEMENTS_BELOW_MAIN_DIAGONAL_OF_MATRIX.AWK
BEGIN {
    arr1[++n] = "1,3,7,8,10"
    arr1[++n] = "2,4,16,14,4"
    arr1[++n] = "3,1,9,18,11"
    arr1[++n] = "12,14,17,18,20"
    arr1[++n] = "7,1,3,9,5"
    for (i=1; i<=n; i++) {
      x = split(arr1[i],arr2,",")
      if (x != n) {
        printf("error: row %d has %d elements; S/B %d\n",i,x,n)
        errors++
        continue
      }
      for (j=1; j<i; j++) { # below main diagonal
        sum_b += arr2[j]
        cnt_b++
      }
      for (j=i+1; j<=n; j++) { # above main diagonal
        sum_a += arr2[j]
        cnt_a++
      }
      for (j=1; j<=i; j++) { # on main diagonal
        if (j == i) {
          sum_o += arr2[j]
          cnt_o++
        }
      }
    }
    if (errors > 0) { exit(1) }
    printf("%5g Sum of the %d elements below main diagonal\n",sum_b,cnt_b)
    printf("%5g Sum of the %d elements above main diagonal\n",sum_a,cnt_a)
    printf("%5g Sum of the %d elements on main diagonal\n",sum_o,cnt_o)
    printf("%5g Sum of the %d elements in the matrix\n",sum_b+sum_a+sum_o,cnt_b+cnt_a+cnt_o)
    exit(0)
}


(defun f (lst &optional (sum 100) (so-far nil))
 "Takes a list of digits as argument"
  (if (null lst)
    (cond ((= sum 0) (format t "~d = ~{[email protected]~}~%" (apply #'+ so-far) (reverse so-far)) 1)
          (t 0) )
    (let ((total 0)
          (len (length lst)) )
      (dotimes (i len total)
        (let* ((str1 (butlast lst i))
               (num1 (or (numlist-to-string str1) 0))
               (rem (nthcdr (- len i) lst)) )
          (incf total
            (+ (f rem (- sum num1) (cons num1 so-far))
               (f rem (+ sum num1) (cons (- num1) so-far)) )))))))

(defun numlist-to-string (lst)
 "Convert a list of digits into an integer"
  (when lst
    (parse-integer (format nil "~{~d~}" lst)) ))


arraybase 1
dim diag = {{ 1, 3, 7, 8,10}, { 2, 4,16,14, 4}, { 3, 1, 9,18,11}, {12,14,17,18,20}, { 7, 1, 3, 9, 5}}
ind = diag[?,]
sumDiag = 0

for x = 1 to diag[?,]
	for y = 1 to diag[,?]-ind
		sumDiag += diag[x, y]
	next y
	ind -= 1
next x

print "Sum of elements below main diagonal of matrix is "; sumDiag
end


SumBelowDiagonal ← +´∘⥊⊢×(>⌜´)∘(↕¨≢)

matrix ← >⟨⟨ 1, 3, 7, 8,10⟩,
           ⟨ 2, 4,16,14, 4⟩,
           ⟨ 3, 1, 9,18,11⟩,
           ⟨12,14,17,18,20⟩,
           ⟨ 7, 1, 3, 9, 5⟩⟩

SumBelowDiagonal matrix


#include<stdlib.h>
#include<stdio.h>

typedef struct{
	int rows,cols;
	int** dataSet;
}matrix;

matrix readMatrix(char* dataFile){
	FILE* fp = fopen(dataFile,"r");
	matrix rosetta;
	int i,j;

	fscanf(fp,"%d%d",&rosetta.rows,&rosetta.cols);

	rosetta.dataSet = (int**)malloc(rosetta.rows*sizeof(int*));

	for(i=0;i<rosetta.rows;i++){
		rosetta.dataSet[i] = (int*)malloc(rosetta.cols*sizeof(int));
		for(j=0;j<rosetta.cols;j++)
			fscanf(fp,"%d",&rosetta.dataSet[i][j]);
	}

	fclose(fp);
	return rosetta;
}

void printMatrix(matrix rosetta){
	int i,j;

	for(i=0;i<rosetta.rows;i++){
		printf("\n");
		for(j=0;j<rosetta.cols;j++)
			printf("%3d",rosetta.dataSet[i][j]);
	}
}

int findSum(matrix rosetta){
	int i,j,sum = 0;

	for(i=1;i<rosetta.rows;i++){
		for(j=0;j<i;j++){
			sum += rosetta.dataSet[i][j];
		}
	}

	return sum;
}

int main(int argC,char* argV[])
{
	if(argC!=2)
		return printf("Usage : %s <filename>",argV[0]);

	matrix data = readMatrix(argV[1]);

	printf("\n\nMatrix is : \n\n");
	printMatrix(data);

	printf("\n\nSum below main diagonal : %d",findSum(data));

	return 0;
}


import std.stdio;

void main() {
    import std.algorithm : each, max, reduce, sort;
    import std.range : take;

    Stat stat = new Stat();

    comment("Show all solutions that sum to 100");
    immutable givenSum = 100;
    print(givenSum);

    comment("Show the sum that has the maximum number of solutions");
    const int maxCount = reduce!max(stat.sumCount.keys);
    int maxSum;
    foreach(key, entry; stat.sumCount[maxCount]) {
        if (key >= 0) {
            maxSum = key;
            break;
        }
    }
    writeln(maxSum, " has ", maxCount, " solutions");

    comment("Show the lowest positive number that can't be expressed");
    int value = 0;
    while (value in stat.countSum) {
        value++;
    }
    writeln(value);

    comment("Show the ten highest numbers that can be expressed");
    const int n = stat.countSum.keys.length;
    auto sums = stat.countSum.keys;
    sums.sort!"a>b"
        .take(10)
        .each!print;
}

void comment(string commentString) {
    writeln();
    writeln(commentString);
    writeln();
}

void print(int givenSum) {
    Expression expression = new Expression();
    for (int i=0; i<Expression.NUMBER_OF_EXPRESSIONS; i++, expression.next()) {
        if (expression.toInt() == givenSum) {
            expression.print();
        }
    }
}

class Expression {
    private enum NUMBER_OF_DIGITS = 9;
    private enum ADD = 0;
    private enum SUB = 1;
    private enum JOIN = 2;

    enum NUMBER_OF_EXPRESSIONS = 2 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3;
    byte[NUMBER_OF_DIGITS] code;

    Expression next() {
        for (int i=0; i<NUMBER_OF_DIGITS; i++) {
            if (++code[i] > JOIN) {
                code[i] = ADD;
            } else {
                break;
            }
        }
        return this;
    }

    int toInt() {
        int value = 0;
        int number = 0;
        int sign = (+1);
        for (int digit=1; digit<=9; digit++) {
            switch (code[NUMBER_OF_DIGITS - digit]) {
                case ADD:
                    value += sign * number;
                    number = digit;
                    sign = (+1);
                    break;
                case SUB:
                    value += sign * number;
                    number = digit;
                    sign = (-1);
                    break;
                case JOIN:
                    number = 10 * number + digit;
                    break;
                default:
                    assert(false);
            }
        }
        return value + sign * number;
    }

    void toString(scope void delegate(const(char)[]) sink) const {
        import std.conv : to;
        import std.format : FormatSpec, formatValue;
        import std.range : put;

        auto fmt = FormatSpec!char("s");
        for (int digit=1; digit<=NUMBER_OF_DIGITS; digit++) {
            switch (code[NUMBER_OF_DIGITS - digit]) {
                case ADD:
                    if (digit > 1) {
                        put(sink, '+');
                    }
                    break;
                case SUB:
                    put(sink, '-');
                    break;
                default:
                    break;
            }
            formatValue(sink, digit, fmt);
        }
    }

    void print() {
        print(stdout);
    }

    void print(File printStream) {
        printStream.writefln("%9d = %s", toInt(), this);
    }
}

class Stat {
    int[int] countSum;
    bool[int][int] sumCount;

    this() {
        Expression expression = new Expression();
        for (int i=0; i<Expression.NUMBER_OF_EXPRESSIONS; i++, expression.next()) {
            int sum = expression.toInt();
            countSum[sum]++;
        }
        foreach (key, entry; countSum) {
            bool[int] set;
            if (entry in sumCount) {
                set = sumCount[entry];
            } else {
                set.clear();
            }
            set[key] = true;
            sumCount[entry] = set;
        }
    }
}


#include <iostream>
#include <vector>

template<typename T>
T sum_below_diagonal(const std::vector<std::vector<T>>& matrix) {
    T sum = 0;
    for (std::size_t y = 0; y < matrix.size(); y++)
        for (std::size_t x = 0; x < matrix[y].size() && x < y; x++)
            sum += matrix[y][x];
    return sum;
}

int main() {
    std::vector<std::vector<int>> matrix = {
        {1,3,7,8,10},
        {2,4,16,14,4},
        {3,1,9,18,11},
        {12,14,17,18,20},
        {7,1,3,9,5}
    };

    std::cout << sum_below_diagonal(matrix) << std::endl;
    return 0;
}


=LAMBDA(isUpper,
    LAMBDA(matrix,
        LET(
            nCols, COLUMNS(matrix),
            nRows, ROWS(matrix),
            ixs, SEQUENCE(nRows, nCols, 0, 1),
            x, MOD(ixs, nCols),
            y, QUOTIENT(ixs, nRows),

            IF(nCols=nRows,
                LET(
                    p, LAMBDA(x, y,
                        IF(isUpper, x > y, x < y)
                    ),

                    IF(p(x, y),
                        INDEX(matrix, 1 + y, 1 + x),
                        0
                    )
                ),
                "Matrix not square"
            )
        )
    )
)


defmodule Sum do
  def to(val) do
    generate
    |> Enum.map(&{eval(&1), &1})
    |> Enum.filter(fn {v, _s} -> v==val end)
    |> Enum.each(&IO.inspect &1)
  end

  def max_solve do
    generate
    |> Enum.group_by(&eval &1)
    |> Enum.filter_map(fn {k,_} -> k>=0 end, fn {k,v} -> {length(v),k} end)
    |> Enum.max
    |> fn {len,sum} -> IO.puts "sum of #{sum} has the maximum number of solutions : #{len}" end.()
  end

  def min_solve do
    solve = generate |> Enum.group_by(&eval &1)
    Stream.iterate(1, &(&1+1))
    |> Enum.find(fn n -> solve[n]==nil end)
    |> fn sum -> IO.puts "lowest positive sum that can't be expressed : #{sum}" end.()
  end

  def  highest_sums(n\\10) do
    IO.puts "highest sums :"
    generate
    |> Enum.map(&eval &1)
    |> Enum.uniq
    |> Enum.sort_by(fn sum -> -sum end)
    |> Enum.take(n)
    |> IO.inspect
  end

  defp generate do
    x = ["+", "-", ""]
    for a <- ["-", ""], b <- x, c <- x, d <- x, e <- x, f <- x, g <- x, h <- x, i <- x,
        do: "#{a}1#{b}2#{c}3#{d}4#{e}5#{f}6#{g}7#{h}8#{i}9"
  end

  defp eval(str), do: Code.eval_string(str) |> elem(0)
end

Sum.to(100)
Sum.max_solve
Sum.min_solve
Sum.highest_sums


USING: kernel math math.matrices prettyprint sequences ;

: sum-below-diagonal ( matrix -- sum )
    dup square-matrix? [ "Matrix must be square." throw ] unless
    0 swap [ head sum + ] each-index ;

{
    { 1 3 7 8 10 }
    { 2 4 16 14 4 }
    { 3 1 9 18 11 }
    { 12 14 17 18 20 }
    { 7 1 3 9 5 }
} sum-below-diagonal .


package main

import (
    "fmt"
    "log"
)

func main() {
    m := [][]int{
        {1, 3, 7, 8, 10},
        {2, 4, 16, 14, 4},
        {3, 1, 9, 18, 11},
        {12, 14, 17, 18, 20},
        {7, 1, 3, 9, 5},
    }
    if len(m) != len(m[0]) {
        log.Fatal("Matrix must be square.")
    }
    sum := 0
    for i := 1; i < len(m); i++ {
        for j := 0; j < i; j++ {
            sum = sum + m[i][j]
        }
    }
    fmt.Println("Sum of elements below main diagonal is", sum)
}


(*
Generate the data set
Nigel Galloway February 22nd., 2017
*)
type N = {n:string; g:int}
let N = seq {
  let rec fn n i g e l = seq {
    match i with
    |9 -> yield {n=l + "-9"; g=g+e-9}
          yield {n=l + "+9"; g=g+e+9}
          yield {n=l +  "9"; g=g+e*10+9*n}
    |_ -> yield! fn -1 (i+1) (g+e) -i (l + string -i)
          yield! fn  1 (i+1) (g+e)  i (l + "+" + string i)
          yield! fn  n (i+1) g (e*10+i*n) (l + string i)
  }
  yield! fn  1 2 0  1  "1"
  yield! fn -1 2 0 -1 "-1"
}


----------------- UPPER OR LOWER TRIANGLE ----------------

matrixTriangle :: Bool -> [[a]] -> Either String [[a]]
matrixTriangle upper matrix
  | upper = go drop id
  | otherwise = go take pred
  where
    go f g
      | isSquare matrix =
        (Right . snd) $
          foldr
            (\xs (n, rows) -> (pred n, f n xs : rows))
            (g $ length matrix, [])
            matrix
      | otherwise = Left "Defined only for a square matrix."

isSquare :: [[a]] -> Bool
isSquare rows = all ((n ==) . length) rows
  where
    n = length rows

--------------------------- TEST -------------------------
main :: IO ()
main =
  mapM_ putStrLn $
    zipWith
      ( flip ((<>) . (<> " triangle:\n\t"))
          . either id (show . sum . concat)
      )
      ( [matrixTriangle] <*> [False, True]
          <*> [ [ [1, 3, 7, 8, 10],
                  [2, 4, 16, 14, 4],
                  [3, 1, 9, 18, 11],
                  [12, 14, 17, 18, 20],
                  [7, 1, 3, 9, 5]
                ]
              ]
      )
      ["Lower", "Upper"]


(() => {
    "use strict";

    // -------- LOWER TRIANGLE OF A SQUARE MATRIX --------

    // lowerTriangle :: [[a]] -> Either String [[a]]
    const lowerTriangle = matrix =>
        // Either a message, if the matrix is not square,
        // or the lower triangle of the matrix.
        isSquare(matrix) ? (
            Right(
                matrix.reduce(
                    ([n, rows], xs) => [
                        1 + n,
                        rows.concat([xs.slice(0, n)])
                    ],
                    [0, []]
                )[1]
            )
        ) : Left("Not a square matrix");

    // isSquare :: [[a]] -> Bool
    const isSquare = rows => {
        // True if the length of every row in the matrix
        // matches the number of rows in the matrix.
        const n = rows.length;

        return rows.every(x => n === x.length);
    };

    // ---------------------- TEST -----------------------
    const main = () =>
        either(
            msg => `Lower triangle undefined :: ${msg}`
        )(
            rows => sum([].concat(...rows))
        )(
            lowerTriangle([
                [1, 3, 7, 8, 10],
                [2, 4, 16, 14, 4],
                [3, 1, 9, 18, 11],
                [12, 14, 17, 18, 20],
                [7, 1, 3, 9, 5]
            ])
        );

    // --------------------- GENERIC ---------------------

    // Left :: a -> Either a b
    const Left = x => ({
        type: "Either",
        Left: x
    });

    // Right :: b -> Either a b
    const Right = x => ({
        type: "Either",
        Right: x
    });

    // either :: (a -> c) -> (b -> c) -> Either a b -> c
    const either = fl =>
        // Application of the function fl to the
        // contents of any Left value in e, or
        // the application of fr to its Right value.
        fr => e => e.Left ? (
            fl(e.Left)
        ) : fr(e.Right);

    // sum :: [Num] -> Num
    const sum = xs =>
        // The numeric sum of all values in xs.
        xs.reduce((a, x) => a + x, 0);

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


CREATE *OPS CHAR + C, CHAR - C, CHAR # C,
CREATE 0OPS CHAR - C, CHAR # C,
CREATE BUFF 43 C, 43 CHARS ALLOT
CREATE PTR CELL ALLOT
CREATE LIMITS 2 C, 3 C, 3 C, 3 C, 3 C, 3 C, 3 C, 3 C, 3 C,
CREATE INDX   0 C, 0 C, 0 C, 0 C, 0 C, 0 C, 0 C, 0 C, 0 C,
CREATE OPS 0OPS , *OPS , *OPS , *OPS , *OPS , *OPS , *OPS , *OPS , *OPS ,
: B0   BUFF 1+ dup  PTR !  43 blank ;
: B, ( c --)  PTR @ C!  1 PTR +! ;
CREATE STATS 123456790 ALLOT  STATS 123456790 ERASE

: inc ( c-addr c-lim u -- t|f)
   1- tuck + >r swap dup rot + ( addr a-addr) ( R: l-addr)
   BEGIN dup [email protected] 1+ dup [email protected] [email protected] =
     IF drop 2dup =
       IF 2drop FALSE rdrop EXIT   \ no inc, contents invalid
       ELSE 0 over C! 1-  r> 1- >r  \ reset and carry
       THEN
     ELSE swap C! drop TRUE rdrop EXIT
     THEN
   AGAIN ;
: INDX+   INDX LIMITS 9 inc 0= ;
: SYNTH   B0  [CHAR] 0 B,  9 0 DO
     INDX I + [email protected]  OPS I CELLS + @ + [email protected]
     dup  [CHAR] # <> IF BL B, B, BL B, ELSE drop THEN
     I [CHAR] 1 + B,
   LOOP  BUFF COUNT ;
: .MOST   cr ." Sum that has the maximum number of solutions" cr 4 spaces
   STATS 0  STATS 1+ 123456789 bounds DO
     dup I [email protected] <  IF drop drop I I [email protected] THEN
   LOOP  swap STATS - . ." has " . ." solutions" ;
: .CANT   cr ." Lowest positive sum that can't be expressed" cr 4 spaces
   STATS 1+ ( 0 not positive)  BEGIN dup [email protected] WHILE 1+ REPEAT  STATS - . ;
: .BEST   cr ." Ten highest numbers that can be expressed" cr 4 spaces
   0 >r  [ STATS 123456789 + ]L
   BEGIN  [email protected] 10 <  over STATS >= and
   WHILE  dup [email protected] IF dup STATS - .  r> 1+ >r THEN  1-
   REPEAT  r> drop ;
: .   0 <# #S #> TYPE ;
: .INFX   cr 4 spaces  9 0 DO
     INDX I + [email protected]  OPS I cells + @ + [email protected]
     dup  [char] # <> IF emit ELSE drop THEN  I 1+ .
   LOOP ;
: REPORT ( n)   dup 100 =  IF .INFX THEN
   dup 0> IF STATS + dup  [email protected] 1+  swap c! ELSE drop THEN ;
: >NUM   0. bl word count >number 2drop d>s ;
: #   10 * + ;   \ numeric concatenation
: +    >NUM + ;  \ infix +
: -    >NUM - ;  \ infix -
: .SOLUTIONS   cr ." Solutions that sum to 100:"
   BEGIN SYNTH EVALUATE REPORT INDX+ UNTIL ;
: SUM100   .SOLUTIONS .MOST .CANT .BEST cr ;


def add(s): reduce s as $x (null; . + $x);

# input: a square matrix
def sum_below_diagonal:
  add( range(0;length) as $i | .[$i][:$i][] ) ;


type SquareMatrix[T: SomeNumber; N: static Positive] = array[N, array[N, T]]

func sumBelowDiagonal[T, N](m: SquareMatrix[T, N]): T =
  for i in 1..<N:
    for j in 0..<i:
      result += m[i][j]

const M = [[ 1,  3,  7,  8, 10],
           [ 2,  4, 16, 14,  4],
           [ 3,  1,  9, 18, 11],
           [12, 14, 17, 18, 20],
           [ 7,  1,  3,  9,  5]]

echo sumBelowDiagonal(M)


C ROSSETACODE: SUM TO 100, FORTRAN IV
C FIND SOLUTIONS TO THE "SUM TO ONE HUNDRED" PUZZLE
C =================================================

      PROGRAM SUMTO100
      DATA NEXPRM1/13121/
      WRITE(6,110)
 110  FORMAT(1X/1X,34HSHOW ALL SOLUTIONS THAT SUM TO 100/)
      DO 10 I = 0,NEXPRM1
  10  IF ( IEVAL(I) .EQ. 100 ) CALL PREXPR(I)

      WRITE(6,120)
 120  FORMAT(1X/1X,
     153HSHOW THE SUM THAT HAS THE MAXIMUM NUMBER OF SOLUTIONS/)
      NBEST = -1
      DO 30 I = 0, NEXPRM1
      ITEST = IEVAL(I)
      IF ( ITEST .LT. 0 ) GOTO 30
      NTEST = 0
      DO 20 J = 0, NEXPRM1
  20  IF ( IEVAL(J) .EQ. ITEST ) NTEST = NTEST + 1
      IF ( NTEST .LE. NBEST ) GOTO 30
      IBEST = ITEST
      NBEST = NTEST
  30  CONTINUE
      WRITE(6,121) IBEST, NBEST
 121  FORMAT(1X,I8,5H HAS ,I8,10H SOLUTIONS/)

      WRITE(6,130)
 130  FORMAT(1X/1X,
     155HSHOW THE LOWEST POSITIVE NUMBER THAT CAN'T BE EXPRESSED/)
      DO 50 I = 0,123456789
      DO 40 J = 0,NEXPRM1
  40  IF ( I .EQ. IEVAL(J) ) GOTO 50
      GOTO 60
  50  CONTINUE
  60  WRITE(6,131) I
 131  FORMAT(1X,I8)

      WRITE(6,140)
 140  FORMAT(1X/1X,
     150HSHOW THE TEN HIGHEST NUMBERS THAT CAN BE EXPRESSED/)
      ILIMIT = 123456789
      DO 90 I = 1,10
      IBEST = 0
      DO 70 J = 0, NEXPRM1
      ITEST = IEVAL(J)
  70  IF( (ITEST .LE. ILIMIT) .AND. (ITEST .GT. IBEST)) IBEST = ITEST
      DO 80 J = 0, NEXPRM1
  80  IF ( IEVAL(J) .EQ. IBEST ) CALL PREXPR(J)
  90  ILIMIT = IBEST - 1
      END

C     EVALUATE THE VALUE OF THE GIVEN ENCODED EXPRESSION
C     --------------------------------------------------
      FUNCTION IEVAL(ICODE)
      IC = ICODE
      IEVAL = 0
      N = 0
      IP = 1
      DO 50 K = 9,1,-1
      N = IP*K + N
      GOTO (10,20,40,30) MOD(IC,3)+1
  10  IEVAL = IEVAL + N
      GOTO 30
  20  IEVAL = IEVAL - N
  30  N = 0
      IP = 1
      GOTO 50
  40  IP = IP * 10
  50  IC = IC / 3
      END

C     PRINT THE ENCODED EXPRESSION IN THE READABLE FORMAT
C     ---------------------------------------------------
      SUBROUTINE PREXPR(ICODE)
      DIMENSION IH(9),IHPMJ(4)
      DATA IHPMJ/1H+,1H-,1H ,1H?/
      IA = 19683
      IB =  6561
      DO 10 K = 1,9
      IH(K) = IHPMJ(MOD(ICODE,IA) / IB+1)
      IA = IB
  10  IB = IB / 3
      IVALUE = IEVAL(ICODE)
      WRITE(6,110) IVALUE, IH
 110  FORMAT(I9,3H = 1A1,1H1,1A1,1H2,1A1,1H3,1A1,1H4,1A1,1H5,1A1,1H6,1A1
     1,1H7,1A1,1H8,1A1,1H9)
      END


#define PERM 13122

'Between any two adjacent digits there can be nothing, a plus, or a minus.
'And the first term can only be + or -
'This is equivalent to an eight-digit base 3 number. We therefore only need
'to consider 2*3^8=13122 possibilities

function ndig(n as uinteger) as uinteger
    return 1+int(log(n+0.5)/log(10))
end function

function calculate( byval n as uinteger, outstr as string ) as integer
    'calculates the sum given by one of the 13122 possibilities, as well as
    'storing the equation itself as a string
    outstr = "9"
    dim as integer ret = 0, curr = 9
    dim as boolean firstplus = n>=PERM/2
    for i as integer = 8 to 1 step -1
        select case n mod 3
            case 0   'no symbol means we just prepend the next number
                curr += i*10^(ndig(curr))
            case 1   'addition: add the current term to the running sum, and clear the current term
                ret += curr
                curr = i
                outstr = " + " + outstr
            case 2   'subtraction: minus the current term from the running sum, and clear the current term
                ret -= curr
                curr = i
                outstr = " - " + outstr
        end select
        outstr = str(i) + outstr      'prepend the previous digit to the string
        n \= 3                        'get next symbol
    next i
    if firstplus = 0 then
        outstr = "-"+outstr
        ret -= curr
    else
        ret += curr
    end if
    outstr = outstr + " = " + str(ret)
    return ret
end function

'calculate and store all 13122 solutions
dim as string eqn
dim as integer n, sum(0 to PERM-1), curr
for n = 0 to PERM-1
    curr = calculate(n, eqn)
    sum(n) = curr
    if curr = 100 then print eqn
next n

'what is the sum that has the most solutions?
dim as integer champ = 0, cnum = 0, i, j, acc
for i = 0 to PERM-1
    acc = 0
    for j = i to PERM-1
        if sum(j) = sum(i) then acc+=1
    next j
    if acc>cnum then
        champ = sum(i)
        cnum=acc
    end if
next i
print "The sum with the most occurrences is ";champ;", which shows up ";cnum;" times."

'what is the first nonnegative number that has no solution
for i = 0 to 123456788
    for j = 0 to PERM-1
        if sum(j)=i then goto nexti
    next j
    print "The first number that has no solution is ";i
    exit for
    nexti:
next i

'What are the ten highest numbers?
'this partially destroys the information in the array, but who cares?
'We're almost done and these excessive questionnaires are the worst
'and most boring part of Rosetta Code tasks

print "The ten highest numbers attainable are:"
champ = 0
for i = 1 to 10
    for j = 0 to PERM-1
        if sum(j)>sum(champ) then champ = j
    next j
    calculate(champ, eqn)
    print eqn
    sum(champ) = -9999   'overwrite to stop this being found a second time
next i


constant M = {{ 1,  3,  7,  8, 10},
              { 2,  4, 16, 14,  4},
              { 3,  1,  9, 18, 11},
              {12, 14, 17, 18, 20},
              { 7,  1,  3,  9,  5}}
atom res = 0
integer height = length(M)
for row=1 to height do
    integer width = length(M[row])
    if width!=height then crash("not square") end if
    for col=1 to row-1 do
        res += M[row][col]
    end for
end for
?res


trap: procedure options (main);      /* 17 December 2021 */
   declare n fixed binary;
   get (n);
   put ('The order of the matrix is ' || trim(n));
   begin;
      declare A (n,n) fixed binary;
      declare sum fixed binary;
      declare (i, j) fixed binary;

      get (A);
      sum = 0;
      do i = 2 to n;
         do j = 1 to i-1;
            sum = sum + a(i,j);
         end;
      end;
      put edit (A) (skip, (n) f(4) );
      put skip data (sum);
   end;
end trap;


100H: /* SUM THE ELEMENTS BELOW THE MAIN DIAGONAL OF A MATRIX                */

   /* CP/M BDOS SYSTEM CALL, IGNORE THE RETURN VALUE                         */
   BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5;     END;
   PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S );      END;
   PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH  */
      DECLARE N ADDRESS;
      DECLARE V ADDRESS, N$STR ( 6 )BYTE, W BYTE;
      V = N;
      W = LAST( N$STR );
      N$STR( W ) = '$';
      N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      DO WHILE( ( V := V / 10 ) > 0 );
         N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      END;
      CALL PR$STRING( .N$STR( W ) );
   END PR$NUMBER;

   /* RETURNS THE SUM OF THE ELEMENTS BELOW THE MAIN DIAGONAL OF MX          */
   /* MX WOULD BE DECLARED AS ''( UB, UB )ADDRESS'' IF PL/M SUPPORTED        */
   /* 2-DIMENSIONAL ARRAYS, IT DOESN'T SO MX MUST ACTULLY BE DECLARED        */
   /* ''( UB * UB )ADDRESS'' - EXCEPT THE BOUND MUST BE A CONSTANT, NOT AN   */
   /* EXPRESSION                                                             */
   /* NOTE ''ADDRESS'' MEANS UNSIGNED 16-BIT QUANTITY, WHICH CAN BE USED FOR */
   /* OTHER PURPOSES THAN JUST POINTERS                                      */
   LOWER$SUM: PROCEDURE( MX, UB )ADDRESS;
      DECLARE ( MX, UB ) ADDRESS;
      DECLARE ( SUM, R, C, STRIDE, R$PTR ) ADDRESS;
      DECLARE M$PTR ADDRESS, M$VALUE BASED M$PTR ADDRESS;
      SUM    = 0;
      STRIDE = UB + UB;
      R$PTR  = MX + STRIDE;      /* ADDRESS OF ROW 1 ( THE FIRST ROW IS 0 )  */
      DO R = 1 TO UB - 1;
         M$PTR = R$PTR;
         DO C = 0 TO R - 1;
            SUM = SUM + M$VALUE;
            M$PTR = M$PTR + 2;
         END;
         R$PTR = R$PTR + STRIDE; /* ADDRESS OF THE NEXT ROW                  */
      END;
      RETURN SUM;
   END LOWER$SUM ;

   /* TASK TEST CASE                                                         */
   DECLARE T ( 25 )ADDRESS
                   INITIAL(  1,  3,  7,  8, 10
                          ,  2,  4, 16, 14,  4
                          ,  3,  1,  9, 18, 11
                          , 12, 14, 17, 18, 20
                          ,  7,  1,  3,  9,  5
                          );
   CALL PR$NUMBER( LOWER$SUM( .T, 5 ) );

EOF


digits = array[1 to 9]
opList = makeArray[[8], ["", " + ", " - "]]
opList.pushFirst[["", "-"]]
countDict = new dict

multifor ops = opList
{
   str = ""
   for d = rangeOf[digits]
      str = str + [email protected] + [email protected]
   e = eval[str]
   countDict.increment[e, 1]
   if e == 100
      println[str]
}
println[]

// Find the sum that has the maximum number of solutions
freq = toArray[countDict]
sort[freq, {|a,b| -([email protected] <=> [email protected])}]
max = [email protected]@1
print["Maximum count is $max at: "]
n = 0
while [email protected]@1 == max
{
   print[[email protected]@0 + " "]
   n = n + 1
}
println[]

// Find the smallest non-representable positive sum
sort[freq, {|a,b| [email protected] <=> [email protected]}]
last = 0
for [num, count] = freq
{
   if num > 0 and last+1 != num
   {
      println["Lowest non-representable positive sum is " + (last+1)]
      break
   }
   last = num
}

// Find highest 10 representable numbers
println["\nHighest representable numbers:"]
size = length[freq]
for i = size-10 to size-1
   println[[email protected]@0]


package main

import (
	"fmt"
	"sort"
)

const pow3_8 = 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 // 3^8
const pow3_9 = 3 * pow3_8                    // 3^9
const maxExprs = 2 * pow3_8                  // not 3^9 since first op can't be Join

type op uint8

const (
	Add  op = iota // insert a "+"
	Sub            //     or a "-"
	Join           //     or just join together
)

// code is an encoding of [9]op, the nine "operations"
// we do on each each digit. The op for 1 is in
// the highest bits, the op for 9 in the lowest.
type code uint16

// evaluate 123456789 with + - or "" prepended to each as indicated by `c`.
func (c code) evaluate() (sum int) {
	num, pow := 0, 1
	for k := 9; k >= 1; k-- {
		num += pow * k
		switch op(c % 3) {
		case Add:
			sum += num
			num, pow = 0, 1
		case Sub:
			sum -= num
			num, pow = 0, 1
		case Join:
			pow *= 10
		}
		c /= 3
	}
	return sum
}

func (c code) String() string {
	buf := make([]byte, 0, 18)
	a, b := code(pow3_9), code(pow3_8)
	for k := 1; k <= 9; k++ {
		switch op((c % a) / b) {
		case Add:
			if k > 1 {
				buf = append(buf, '+')
			}
		case Sub:
			buf = append(buf, '-')
		}
		buf = append(buf, '0'+byte(k))
		a, b = b, b/3
	}
	return string(buf)
}

type sumCode struct {
	sum  int
	code code
}
type sumCodes []sumCode

type sumCount struct {
	sum   int
	count int
}
type sumCounts []sumCount

// For sorting (could also use sort.Slice with just Less).
func (p sumCodes) Len() int            { return len(p) }
func (p sumCodes) Swap(i, j int)       { p[i], p[j] = p[j], p[i] }
func (p sumCodes) Less(i, j int) bool  { return p[i].sum < p[j].sum }
func (p sumCounts) Len() int           { return len(p) }
func (p sumCounts) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
func (p sumCounts) Less(i, j int) bool { return p[i].count > p[j].count }

// For printing.
func (sc sumCode) String() string {
	return fmt.Sprintf("% 10d = %v", sc.sum, sc.code)
}
func (sc sumCount) String() string {
	return fmt.Sprintf("% 10d has %d solutions", sc.sum, sc.count)
}

func main() {
	// Evaluate all expressions.
	expressions := make(sumCodes, 0, maxExprs/2)
	counts := make(sumCounts, 0, 1715)
	for c := code(0); c < maxExprs; c++ {
		// All negative sums are exactly like their positive
		// counterpart with all +/- switched, we don't need to
		// keep track of them.
		sum := c.evaluate()
		if sum >= 0 {
			expressions = append(expressions, sumCode{sum, c})
		}
	}
	sort.Sort(expressions)

	// Count all unique sums
	sc := sumCount{expressions[0].sum, 1}
	for _, e := range expressions[1:] {
		if e.sum == sc.sum {
			sc.count++
		} else {
			counts = append(counts, sc)
			sc = sumCount{e.sum, 1}
		}
	}
	counts = append(counts, sc)
	sort.Sort(counts)

	// Extract required results

	fmt.Println("All solutions that sum to 100:")
	i := sort.Search(len(expressions), func(i int) bool {
		return expressions[i].sum >= 100
	})
	for _, e := range expressions[i:] {
		if e.sum != 100 {
			break
		}
		fmt.Println(e)
	}

	fmt.Println("\nThe positive sum with maximum number of solutions:")
	fmt.Println(counts[0])

	fmt.Println("\nThe lowest positive number that can't be expressed:")
	s := 1
	for _, e := range expressions {
		if e.sum == s {
			s++
		} else if e.sum > s {
			fmt.Printf("% 10d\n", s)
			break
		}
	}

	fmt.Println("\nThe ten highest numbers that can be expressed:")
	for _, e := range expressions[len(expressions)-10:] {
		fmt.Println(e)
	}
}


import Control.Monad (replicateM)
import Data.Char (intToDigit)
import Data.List
  ( find,
    group,
    intercalate,
    nub,
    sort,
    sortBy,
  )
import Data.Monoid ((<>))
import Data.Ord (comparing)

data Sign
  = Unsigned
  | Plus
  | Minus
  deriving (Eq, Show)

------------------------ SUM TO 100 ----------------------

universe :: [[(Int, Sign)]]
universe =
  zip [1 .. 9]
    <$> filter
      ((/= Plus) . head)
      (replicateM 9 [Unsigned, Plus, Minus])

allNonNegativeSums :: [Int]
allNonNegativeSums =
  sort $
    filter
      (>= 0)
      (asSum <$> universe)

uniqueNonNegativeSums :: [Int]
uniqueNonNegativeSums = nub allNonNegativeSums

asSum :: [(Int, Sign)] -> Int
asSum xs =
  n
    + ( case s of
          [] -> 0
          _ -> read s :: Int
      )
  where
    (n, s) = foldr readSign (0, []) xs
    readSign ::
      (Int, Sign) ->
      (Int, String) ->
      (Int, String)
    readSign (i, x) (n, s)
      | x == Unsigned = (n, intToDigit i : s)
      | otherwise =
        ( ( case x of
              Plus -> (+)
              _ -> (-)
          )
            n
            (read (show i <> s) :: Int),
          []
        )

asString :: [(Int, Sign)] -> String
asString = foldr signedDigit []
  where
    signedDigit (i, x) s
      | x == Unsigned = intToDigit i : s
      | otherwise =
        ( case x of
            Plus -> " +"
            _ -> " -"
        )
          <> [intToDigit i]
          <> s

--------------------------- TEST -------------------------
main :: IO ()
main =
  putStrLn $
    unlines
      [ "Sums to 100:",
        unlines
          (asString <$> filter ((100 ==) . asSum) universe),
        "\n10 commonest sums (sum, number of routes to it):",
        show
          ( ((,) <$> head <*> length)
              <$> take
                10
                ( sortBy
                    (flip (comparing length))
                    (group allNonNegativeSums)
                )
          ),
        "\nFirst positive integer not expressible "
          <> "as a sum of this kind:",
        maybeReport
          ( find
              (uncurry (/=))
              (zip [0 ..] uniqueNonNegativeSums)
          ),
        "\n10 largest sums:",
        show
          ( take
              10
              ( sortBy
                  (flip compare)
                  uniqueNonNegativeSums
              )
          )
      ]
  where
    maybeReport ::
      Show a =>
      Maybe (a, b) ->
      String
    maybeReport (Just (x, _)) = show x
    maybeReport _ = "No gaps found"


/* REXX */
ml ='1 3 7 8 10 2 4 16 14 4 3 1 9 18 11 12 14 17 18 20 7 1 3 9 5'
Do i=1 To 5
  Do j=1 To 5
    Parse Var ml m.i.j ml
    End
  End

l=''
Do i=1 To 5
  Do j=1 To 5
    l=l right(m.i.j,2)
    End
  Say l
  l=''
  End

sum=0
Do i=2 To 5
  Do j=1 To i-1
    sum=sum+m.i.j
    End
  End
Say 'Sum below main diagonal:' sum


see "working..." + nl
see "Sum of elements below main diagonal of matrix:" + nl
diag = [[1,3,7,8,10],
        [2,4,16,14,4],
        [3,1,9,18,11],
        [12,14,17,18,20],
        [7,1,3,9,5]]

lenDiag = len(diag)
ind = lenDiag
sumDiag = 0

for n=1 to lenDiag
    for m=1 to lenDiag-ind
        sumDiag += diag[n][m]
    next
    ind--
next

see "" + sumDiag + nl
see "done..." + nl


$ include "seed7_05.s7i";

const proc: main is func
  local
    var integer: sum is 0;
    var integer: i is 0;
    var integer: j is 0;
    const array array integer: m is [] ([] ( 1,  3,  7,  8, 10),
                                        [] ( 2,  4, 16, 14,  4),
                                        [] ( 3,  1,  9, 18, 11),
                                        [] (12, 14, 17, 18, 20),
                                        [] ( 7,  1,  3,  9,  5));
  begin
    for i range 2 to length(m) do
      for j range 1 to i - 1 do
        sum +:= m[i][j];
      end for;
    end for;
    writeln(sum);
  end func;


var m = [
    [ 1,  3,  7,  8, 10],
    [ 2,  4, 16, 14,  4],
    [ 3,  1,  9, 18, 11],
    [12, 14, 17, 18, 20],
    [ 7,  1,  3,  9,  5]
]
if (m.count != m[0].count) Fiber.abort("Matrix must be square.")
var sum = 0
for (i in 1...m.count) {
   for (j in 0...i) {
       sum = sum + m[i][j]
  }
}
System.print("Sum of elements below main diagonal is %(sum).")


/*
 * RossetaCode: Sum to 100, Java 8.
 *
 * Find solutions to the "sum to one hundred" puzzle.
 */
package rosettacode;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class SumTo100 implements Runnable {

    public static void main(String[] args) {
        new SumTo100().run();
    }

    void print(int givenSum) {
        Expression expression = new Expression();
        for (int i = 0; i < Expression.NUMBER_OF_EXPRESSIONS; i++, expression.next()) {
            if (expression.toInt() == givenSum) {
                expression.print();
            }
        }
    }

    void comment(String commentString) {
        System.out.println();
        System.out.println(commentString);
        System.out.println();
    }

    @Override
    public void run() {
        final Stat stat = new Stat();

        comment("Show all solutions that sum to 100");
        final int givenSum = 100;
        print(givenSum);

        comment("Show the sum that has the maximum number of solutions");
        final int maxCount = Collections.max(stat.sumCount.keySet());
        int maxSum;
        Iterator<Integer> it = stat.sumCount.get(maxCount).iterator();
        do {
            maxSum = it.next();
        } while (maxSum < 0);
        System.out.println(maxSum + " has " + maxCount + " solutions");

        comment("Show the lowest positive number that can't be expressed");
        int value = 0;
        while (stat.countSum.containsKey(value)) {
            value++;
        }
        System.out.println(value);

        comment("Show the ten highest numbers that can be expressed");
        final int n = stat.countSum.keySet().size();
        final Integer[] sums = stat.countSum.keySet().toArray(new Integer[n]);
        Arrays.sort(sums);
        for (int i = n - 1; i >= n - 10; i--) {
            print(sums[i]);
        }
    }

    private static class Expression {

        private final static int NUMBER_OF_DIGITS = 9;
        private final static byte ADD = 0;
        private final static byte SUB = 1;
        private final static byte JOIN = 2;

        final byte[] code = new byte[NUMBER_OF_DIGITS];
        final static int NUMBER_OF_EXPRESSIONS = 2 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3;

        Expression next() {
            for (int i = 0; i < NUMBER_OF_DIGITS; i++) {
                if (++code[i] > JOIN) {
                    code[i] = ADD;
                } else {
                    break;
                }
            }
            return this;
        }

        int toInt() {
            int value = 0;
            int number = 0;
            int sign = (+1);
            for (int digit = 1; digit <= 9; digit++) {
                switch (code[NUMBER_OF_DIGITS - digit]) {
                    case ADD:
                        value += sign * number;
                        number = digit;
                        sign = (+1);
                        break;
                    case SUB:
                        value += sign * number;
                        number = digit;
                        sign = (-1);
                        break;
                    case JOIN:
                        number = 10 * number + digit;
                        break;
                }
            }
            return value + sign * number;
        }

        @Override
        public String toString() {
            StringBuilder s = new StringBuilder(2 * NUMBER_OF_DIGITS + 1);
            for (int digit = 1; digit <= NUMBER_OF_DIGITS; digit++) {
                switch (code[NUMBER_OF_DIGITS - digit]) {
                    case ADD:
                        if (digit > 1) {
                            s.append('+');
                        }
                        break;
                    case SUB:
                        s.append('-');
                        break;
                }
                s.append(digit);
            }
            return s.toString();
        }

        void print() {
            print(System.out);
        }

        void print(PrintStream printStream) {
            printStream.format("%9d", this.toInt());
            printStream.println(" = " + this);
        }
    }

    private static class Stat {

        final Map<Integer, Integer> countSum = new HashMap<>();
        final Map<Integer, Set<Integer>> sumCount = new HashMap<>();

        Stat() {
            Expression expression = new Expression();
            for (int i = 0; i < Expression.NUMBER_OF_EXPRESSIONS; i++, expression.next()) {
                int sum = expression.toInt();
                countSum.put(sum, countSum.getOrDefault(sum, 0) + 1);
            }
            for (Map.Entry<Integer, Integer> entry : countSum.entrySet()) {
                Set<Integer> set;
                if (sumCount.containsKey(entry.getValue())) {
                    set = sumCount.get(entry.getValue());
                } else {
                    set = new HashSet<>();
                }
                set.add(entry.getKey());
                sumCount.put(entry.getValue(), set);
            }
        }
    }
}


(function () {
    'use strict';

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

    // permutationsWithRepetition :: Int -> [a] -> [[a]]
    var permutationsWithRepetition = function (n, as) {
        return as.length > 0 ?
            foldl1(curry(cartesianProduct)(as), replicate(n, as)) : [];
    };

    // cartesianProduct :: [a] -> [b] -> [[a, b]]
    var cartesianProduct = function (xs, ys) {
        return [].concat.apply([], xs.map(function (x) {
            return [].concat.apply([], ys.map(function (y) {
                return [
                    [x].concat(y)
                ];
            }));
        }));
    };

    // curry :: ((a, b) -> c) -> a -> b -> c
    var curry = function (f) {
        return function (a) {
            return function (b) {
                return f(a, b);
            };
        };
    };

    // flip :: (a -> b -> c) -> b -> a -> c
    var flip = function (f) {
        return function (a, b) {
            return f.apply(null, [b, a]);
        };
    };

    // foldl1 :: (a -> a -> a) -> [a] -> a
    var foldl1 = function (f, xs) {
        return xs.length > 0 ? xs.slice(1)
            .reduce(f, xs[0]) : [];
    };

    // replicate :: Int -> a -> [a]
    var replicate = function (n, a) {
        var v = [a],
            o = [];
        if (n < 1) return o;
        while (n > 1) {
            if (n & 1) o = o.concat(v);
            n >>= 1;
            v = v.concat(v);
        }
        return o.concat(v);
    };

    // group :: Eq a => [a] -> [[a]]
    var group = function (xs) {
        return groupBy(function (a, b) {
            return a === b;
        }, xs);
    };

    // groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
    var groupBy = function (f, xs) {
        var dct = xs.slice(1)
            .reduce(function (a, x) {
                var h = a.active.length > 0 ? a.active[0] : undefined,
                    blnGroup = h !== undefined && f(h, x);

                return {
                    active: blnGroup ? a.active.concat(x) : [x],
                    sofar: blnGroup ? a.sofar : a.sofar.concat([a.active])
                };
            }, {
                active: xs.length > 0 ? [xs[0]] : [],
                sofar: []
            });
        return dct.sofar.concat(dct.active.length > 0 ? [dct.active] : []);
    };

    // compare :: a -> a -> Ordering
    var compare = function (a, b) {
        return a < b ? -1 : a > b ? 1 : 0;
    };

    // on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
    var on = function (f, g) {
        return function (a, b) {
            return f(g(a), g(b));
        };
    };

    // nub :: [a] -> [a]
    var nub = function (xs) {
        return nubBy(function (a, b) {
            return a === b;
        }, xs);
    };

    // nubBy :: (a -> a -> Bool) -> [a] -> [a]
    var nubBy = function (p, xs) {
        var x = xs.length ? xs[0] : undefined;

        return x !== undefined ? [x].concat(nubBy(p, xs.slice(1)
            .filter(function (y) {
                return !p(x, y);
            }))) : [];
    };

    // find :: (a -> Bool) -> [a] -> Maybe a
    var find = function (f, xs) {
        for (var i = 0, lng = xs.length; i < lng; i++) {
            if (f(xs[i], i)) return xs[i];
        }
        return undefined;
    };

    // Int -> [a] -> [a]
    var take = function (n, xs) {
        return xs.slice(0, n);
    };

    // unlines :: [String] -> String
    var unlines = function (xs) {
        return xs.join('\n');
    };

    // show :: a -> String
    var show = function (x) {
        return JSON.stringify(x);
    }; //, null, 2);

    // head :: [a] -> a
    var head = function (xs) {
        return xs.length ? xs[0] : undefined;
    };

    // tail :: [a] -> [a]
    var tail = function (xs) {
        return xs.length ? xs.slice(1) : undefined;
    };

    // length :: [a] -> Int
    var length = function (xs) {
        return xs.length;
    };

    // SIGNED DIGIT SEQUENCES  (mapped to sums and to strings)

    // data Sign :: [ 0 | 1 | -1 ] = ( Unsigned | Plus | Minus )
    // asSum :: [Sign] -> Int
    var asSum = function (xs) {
        var dct = xs.reduceRight(function (a, sign, i) {
            var d = i + 1; //  zero-based index to [1-9] positions
            if (sign !== 0) {
                // Sum increased, digits cleared
                return {
                    digits: [],
                    n: a.n + sign * parseInt([d].concat(a.digits)
                        .join(''), 10)
                };
            } else return { // Digits extended, sum unchanged
                digits: [d].concat(a.digits),
                n: a.n
            };
        }, {
            digits: [],
            n: 0
        });
        return dct.n + (
            dct.digits.length > 0 ? parseInt(dct.digits.join(''), 10) : 0
        );
    };

    // data Sign :: [ 0 | 1 | -1 ] = ( Unsigned | Plus | Minus )
    // asString :: [Sign] -> String
    var asString = function (xs) {
        var ns = xs.reduce(function (a, sign, i) {
            var d = (i + 1)
                .toString();
            return sign === 0 ? a + d : a + (sign > 0 ? ' +' : ' -') + d;
        }, '');

        return ns[0] === '+' ? tail(ns) : ns;
    };

    // SUM T0 100 ------------------------------------------------------------

    // universe :: [[Sign]]
    var universe = permutationsWithRepetition(9, [0, 1, -1])
        .filter(function (x) {
            return x[0] !== 1;
        });

    // allNonNegativeSums :: [Int]
    var allNonNegativeSums = universe.map(asSum)
        .filter(function (x) {
            return x >= 0;
        })
        .sort();

    // uniqueNonNegativeSums :: [Int]
    var uniqueNonNegativeSums = nub(allNonNegativeSums);

    return ["Sums to 100:\n", unlines(universe.filter(function (x) {
                return asSum(x) === 100;
            })
            .map(asString)),

        "\n\n10 commonest sums (sum, followed by number of routes to it):\n",
        show(take(10, group(allNonNegativeSums)
            .sort(on(flip(compare), length))
            .map(function (xs) {
                return [xs[0], xs.length];
            }))),

        "\n\nFirst positive integer not expressible as a sum of this kind:\n",
        show(find(function (x, i) {
            return x !== i;
        }, uniqueNonNegativeSums.sort(compare)) - 1), // zero-based index

        "\n10 largest sums:\n",
        show(take(10, uniqueNonNegativeSums.sort(flip(compare))))
    ].join('\n') + '\n';
})();


# Generate a "sum" in the form:  [I, 1, X, 2, X, 3, ..., X, n] where I is "-" or "", and X is "+", "-", or ""
def generate(n):
  def pm: ["+"], ["-"], [""];

  if n == 1 then (["-"], [""]) + [1]
  else generate(n-1) + pm +  [n]
  end;

# The numerical value of a "sum"
def addup:
  reduce .[] as $x ({sum:0, previous: "0"};
     if   $x == "+" then .sum += (.previous|tonumber) | .previous = ""
     elif $x == "-" then .sum += (.previous|tonumber) | .previous = "-"
     elif $x == "" then .
     else .previous += ($x|tostring)
     end)
     | .sum + (.previous | tonumber) ;

# Pretty-print a "sum", e.g. ["",1,"+", 2] => 1 + 2
def pp: map(if . == "+" or . == "-" then " " + . else tostring end) | join("");


using Printf, IterTools, DataStructures

expr(p::String...)::String = @sprintf("%s1%s2%s3%s4%s5%s6%s7%s8%s9", p...)
function genexpr()::Vector{String}
    op = ["+", "-", ""]
    return collect(expr(p...) for (p) in Iterators.product(op, op, op, op, op, op, op, op, op) if p[1] != "+")
end

using DataStructures

function allexpr()::Dict{Int,Int}
    rst = DefaultDict{Int,Int}(0)
    for e in genexpr()
        val = eval(Meta.parse(e))
        rst[val] += 1
    end
    return rst
end

sumto(val::Int)::Vector{String} = filter(e -> eval(Meta.parse(e)) == val, genexpr())
function maxsolve()::Dict{Int,Int}
    ae = allexpr()
    vmax = maximum(values(ae))
    smax = filter(ae) do (v, f)
        f == vmax
    end
    return smax
end
function minsolve()::Int
    ae = keys(allexpr())
    for i in 1:typemax(Int)
        if i ∉ ae
            return i
        end
    end
end
function highestsums(n::Int)::Vector{Int}
    sums = collect(keys(allexpr()))
    return sort!(sums; rev=true)[1:n]
end

const solutions = sumto(100)
const smax = maxsolve()
const smin   = minsolve()
const hsums = highestsums(10)

println("100 =")
foreach(println, solutions)

println("\nMax number of solutions:")
for (v, f) in smax
    @printf("%3i -> %2i\n", v, f)
end

println("\nMin number with no solutions: $smin")

println("\nHighest sums representable:")
foreach(println, hsums)


// version 1.1.51

class Expression {

    private enum class Op { ADD, SUB, JOIN }
    private val code = Array<Op>(NUMBER_OF_DIGITS) { Op.ADD }

    companion object {
        private const val NUMBER_OF_DIGITS = 9
        private const val THREE_POW_4 = 3 * 3 * 3 * 3
        private const val FMT = "%9d"
        const val NUMBER_OF_EXPRESSIONS = 2 * THREE_POW_4 * THREE_POW_4

        fun print(givenSum: Int) {
            var expression = Expression()
            repeat(Expression.NUMBER_OF_EXPRESSIONS) {
                if (expression.toInt() == givenSum) println("${FMT.format(givenSum)} = $expression")
                expression++
            }
        }
    }

    operator fun inc(): Expression {
        for (i in 0 until code.size) {
            code[i] = when (code[i]) {
                Op.ADD  -> Op.SUB
                Op.SUB  -> Op.JOIN
                Op.JOIN -> Op.ADD
            }
            if (code[i] != Op.ADD) break
        }
        return this
    }

    fun toInt(): Int {
        var value = 0
        var number = 0
        var sign = +1
        for (digit in 1..9) {
            when (code[NUMBER_OF_DIGITS - digit]) {
                Op.ADD  -> { value += sign * number; number = digit; sign = +1 }
                Op.SUB  -> { value += sign * number; number = digit; sign = -1 }
                Op.JOIN -> { number = 10 * number + digit }
            }
        }
        return value + sign * number
    }

    override fun toString(): String {
        val sb = StringBuilder()
        for (digit in 1..NUMBER_OF_DIGITS) {
            when (code[NUMBER_OF_DIGITS - digit]) {
                Op.ADD  -> if (digit > 1) sb.append(" + ")
                Op.SUB  -> sb.append(" - ")
                Op.JOIN -> {}
            }
            sb.append(digit)
        }
        return sb.toString().trimStart()
    }
}

class Stat {

    val countSum = mutableMapOf<Int, Int>()
    val sumCount = mutableMapOf<Int, MutableSet<Int>>()

    init {
        var expression = Expression()
        repeat (Expression.NUMBER_OF_EXPRESSIONS) {
            val sum = expression.toInt()
            countSum.put(sum, 1 + (countSum[sum] ?: 0))
            expression++
        }
        for ((k, v) in countSum) {
            val set = if (sumCount.containsKey(v))
                sumCount[v]!!
            else
                mutableSetOf<Int>()
            set.add(k)
            sumCount.put(v, set)
        }
    }
}

fun main(args: Array<String>) {
    println("100 has the following solutions:\n")
    Expression.print(100)

    val stat = Stat()
    val maxCount = stat.sumCount.keys.max()
    val maxSum = stat.sumCount[maxCount]!!.max()
    println("\n$maxSum has the maximum number of solutions, namely $maxCount")

    var value = 0
    while (stat.countSum.containsKey(value)) value++
    println("\n$value is the lowest positive number with no solutions")

    println("\nThe ten highest numbers that do have solutions are:\n")
    stat.countSum.keys.toIntArray().sorted().reversed().take(10).forEach { Expression.print(it) }
}


local expressionsLength = 0
function compareExpressionBySum(a, b)
    return a.sum - b.sum
end

local countSumsLength = 0
function compareCountSumsByCount(a, b)
    return a.counts - b.counts
end

function evaluate(code)
    local value = 0
    local number = 0
    local power = 1
    for k=9,1,-1 do
        number = power*k + number
        local mod = code % 3
        if mod == 0 then
            -- ADD
            value = value + number
            number = 0
            power = 1
        elseif mod == 1 then
            -- SUB
            value = value - number
            number = 0
            power = 1
        elseif mod == 2 then
            -- JOIN
            power = 10 * power
        else
            print("This should not happen.")
        end
        code = math.floor(code / 3)
    end
    return value
end

function printCode(code)
    local a = 19683
    local b = 6561
    local s = ""
    for k=1,9 do
        local temp = math.floor((code % a) / b)
        if temp == 0 then
            -- ADD
            if k>1 then
                s = s .. '+'
            end
        elseif temp == 1 then
            -- SUB
            s = s .. '-'
        end
        a = b
        b = math.floor(b/3)
        s = s .. tostring(k)
    end
    print("\t"..evaluate(code).." = "..s)
end

-- Main
local nexpr = 13122

print("Show all solutions that sum to 100")
for i=0,nexpr-1 do
    if evaluate(i) == 100 then
        printCode(i)
    end
end
print()

print("Show the sum that has the maximum number of solutions")
local nbest = -1
for i=0,nexpr-1 do
    local test = evaluate(i)
    if test>0 then
        local ntest = 0
        for j=0,nexpr-1 do
            if evaluate(j) == test then
                ntest = ntest + 1
            end
            if ntest > nbest then
                best = test
                nbest = ntest
            end
        end
    end
end
print(best.." has "..nbest.." solutions\n")

print("Show the lowest positive number that can't be expressed")
local code = -1
for i=0,123456789 do
    for j=0,nexpr-1 do
        if evaluate(j) == i then
            code = j
            break
        end
    end
    if evaluate(code) ~= i then
        code = i
        break
    end
end
print(code.."\n")

print("Show the ten highest numbers that can be expressed")
local limit = 123456789 + 1
for i=1,10 do
    local best=0
    for j=0,nexpr-1 do
        local test = evaluate(j)
        if (test<limit) and (test>best) then
            best = test
        end
    end
    for j=0,nexpr-1 do
        if evaluate(j) == best then
            printCode(j)
        end
    end
    limit = best
end


operations = DeleteCases[Tuples[{"+", "-", ""}, 9], {x_, y__} /; x == "+"];
sums = Map[StringJoin[Riffle[#, CharacterRange["1", "9"]]] &, operations];


MODULE SumTo100;
FROM FormatString IMPORT FormatString;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;

PROCEDURE Evaluate(code : INTEGER) : INTEGER;
VAR
    value,number,power,k : INTEGER;
BEGIN
    value := 0;
    number := 0;
    power := 1;

    FOR k:=9 TO 1 BY -1 DO
        number := power * k + number;
        IF code MOD 3 = 0 THEN
            (* ADD *)
            value := value + number;
            number := 0;
            power := 1
        ELSIF code MOD 3 = 1 THEN
            (* SUB *)
            value := value - number;
            number := 0;
            power := 1
        ELSE
            (* CAT *)
            power := power * 10
        END;
        code := code / 3
    END;

    RETURN value
END Evaluate;

PROCEDURE Print(code : INTEGER);
VAR
    expr,buf : ARRAY[0..63] OF CHAR;
    a,b,k,p : INTEGER;
BEGIN
    a := 19683;
    b := 6561;
    p := 0;

    FOR k:=1 TO 9 DO
        IF (code MOD a) / b = 0 THEN
            IF k > 1 THEN
                expr[p] := '+';
                INC(p)
            END
        ELSIF (code MOD a) / b = 1 THEN
            expr[p] := '-';
            INC(p)
        END;

        a := b;
        b := b / 3;
        expr[p] := CHR(k + 30H);
        INC(p)
    END;
    expr[p] := 0C;

    FormatString("%9i = %s\n", buf, Evaluate(code), expr);
    WriteString(buf)
END Print;

(* Main *)
CONST nexpr = 13122;
VAR
    i,j : INTEGER;
    best,nbest,test,ntest,limit : INTEGER;
    buf : ARRAY[0..63] OF CHAR;
BEGIN
    WriteString("Show all solution that sum to 100");
    WriteLn;
    FOR i:=0 TO nexpr-1 DO
        IF Evaluate(i) = 100 THEN
            Print(i)
        END
    END;
    WriteLn;

    WriteString("Show the sum that has the maximum number of solutions");
    WriteLn;
    nbest := -1;
    FOR i:=0 TO nexpr-1 DO
        test := Evaluate(i);
        IF test > 0 THEN
            ntest := 0;
            FOR j:=0 TO nexpr-1 DO
                IF Evaluate(j) = test THEN
                    INC(ntest)
                END;
                IF ntest > nbest THEN
                    best := test;
                    nbest := ntest
                END
            END
        END
    END;
    FormatString("%i has %i solutions\n\n", buf, best, nbest);
    WriteString(buf);

    WriteString("Show the lowest positive number that can't be expressed");
    WriteLn;
    FOR i:=0 TO 123456789 DO
        FOR j:=0 TO nexpr-1 DO
            IF i = Evaluate(j) THEN
                BREAK
            END
        END;
        IF i # Evaluate(j) THEN
            BREAK
        END
    END;
    FormatString("%i\n\n", buf, i);
    WriteString(buf);

    WriteString("Show the ten highest numbers that can be expressed");
    WriteLn;
    limit := 123456789 + 1;
    FOR i:=1 TO 10 DO
        best := 0;
        FOR j:=0 TO nexpr-1 DO
            test := Evaluate(j);
            IF (test < limit) AND (test > best) THEN
                best := test
            END
        END;
        FOR j:=0 TO nexpr-1 DO
            IF Evaluate(j) = best THEN
                Print(j)
            END
        END;
        limit := best
    END;

    ReadChar
END SumTo100.


import algorithm, parseutils, sequtils, strutils, tables

type Expression = string

proc buildExprs(start: Natural = 0): seq[Expression] =
  let item = if start == 0: "" else: $start
  if start == 9: return @[item]
  for expr in buildExprs(start + 1):
    result.add item & expr
    result.add item & '-' & expr
    if start != 0: result.add item & '+' & expr

proc evaluate(expr: Expression): int =
  var idx = 0
  var val: int
  while idx < expr.len:
    let n = expr.parseInt(val, idx)
    inc idx, n
    result += val

let exprs = buildExprs()
var counts: CountTable[int]

echo "The solutions for 100 are:"
for expr in exprs:
  let sum = evaluate(expr)
  if sum == 100: echo expr
  if sum > 0: counts.inc(sum)

let (n, count) = counts.largest()
echo "\nThe maximum count of positive solutions is $1 for number $2.".format(count, n)

var s = 1
while true:
  if s notin counts:
    echo "\nThe smallest number than cannot be expressed is: $1.".format(s)
    break
  inc s

echo "\nThe ten highest numbers than can be expressed are:"
let numbers = sorted(toSeq(counts.keys), Descending)
echo numbers[0..9].join(", ")


{ RossetaCode: Sum to 100, Pascal.

  Find solutions to the "sum to one hundred" puzzle.

  We don't use arrays, but recompute all values again and again.
  It is a little surprise that the time efficiency is quite acceptable. }

program sumto100;

const
  ADD = 0; SUB = 1; JOIN = 2; { opcodes inserted between digits }
  NEXPR = 13122;              { the total number of expressions }
var
  i, j: integer;
  loop: boolean;
  test, ntest, best, nbest, limit: integer;

  function evaluate(code: integer): integer;
  var
    k: integer;
    value, number, power: integer;
  begin
    value  := 0;
    number := 0;
    power  := 1;
    for  k := 9 downto 1 do
    begin
      number := power * k + number;
      case code mod 3 of
        ADD: begin value := value + number; number := 0; power := 1; end;
        SUB: begin value := value - number; number := 0; power := 1; end;
        JOIN:                                            power := power * 10
      end;
      code := code div 3
    end;
    evaluate := value
  end;

  procedure print(code: integer);
  var
    k: integer;
    a, b: integer;
  begin
    a := 19683;
    b := 6561;
    write( evaluate(code):9 );
    write(' = ');
    for  k := 1 to 9 do
    begin
      case ((code mod a) div b) of
        ADD: if k > 1 then write('+');
        SUB: { always }    write('-');
      end;
      a := b;
      b := b div 3;
      write( k:1 )
    end;
    writeln
  end;

begin
  writeln;
  writeln('Show all solutions that sum to 100');
  writeln;
  for i := 0 to NEXPR - 1 do
    if evaluate(i) = 100 then
      print(i);

  writeln;
  writeln('Show the sum that has the maximum number of solutions');
  writeln;
  nbest := (-1);
  for i := 0 to NEXPR - 1 do
  begin
    test := evaluate(i);
    if test > 0 then
    begin
      ntest := 0;
      for j := 0 to NEXPR - 1 do
        if evaluate(j) = test then
          ntest := ntest + 1;
      if ntest > nbest then
      begin
        best := test;
        nbest := ntest;
      end
    end
  end;
  writeln(best, ' has ', nbest, ' solutions');

  writeln;
  writeln('Show the lowest positive number that can''t be expressed');
  writeln;
  i := 0;
  loop := TRUE;
  while (i <= 123456789) and loop do
  begin
    j := 0;
    while (j < NEXPR - 1) and (i <> evaluate(j)) do
      j := j + 1;
    if i <> evaluate(j) then
      loop := FALSE
    else
      i := i + 1;
  end;
  writeln(i);

  writeln;
  writeln('Show the ten highest numbers that can be expressed');
  writeln;
  limit := 123456789 + 1;
  for i := 1 to 10 do
  begin
    best := 0;
    for j := 0 to NEXPR - 1 do
    begin
      test := evaluate(j);
      if (test < limit) and (test > best) then
        best := test;
    end;
    for j := 0 to NEXPR - 1 do
      if evaluate(j) = best then
        print(j);
    limit := best;
  end
end.


#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my $string = '123456789';
my $length = length $string;
my @possible_ops = ("" , '+', '-');

{
    my @ops;
    sub Next {
        return @ops = (0) x ($length) unless @ops;

        my $i = 0;
        while ($i < $length) {
            if ($ops[$i]++ > $#possible_ops - 1) {
                $ops[$i++] = 0;
                next
            }
            # + before the first number
            next if 0 == $i && '+' eq $possible_ops[ $ops[0] ];

            return @ops
        }
        return
    }
}

sub evaluate {
    my ($expression) = @_;
    my $sum;
    $sum += $_ for $expression =~ /([-+]?[0-9]+)/g;
    return $sum
}

my %count = ( my $max_count = 0 => 0 );

say 'Show all solutions that sum to 100';

while (my @ops = Next()) {
    my $expression = "";
    for my $i (0 .. $length - 1) {
        $expression .= $possible_ops[ $ops[$i] ];
        $expression .= substr $string, $i, 1;
    }
    my $sum = evaluate($expression);
    ++$count{$sum};
    $max_count = $sum if $count{$sum} > $count{$max_count};
    say $expression if 100 == $sum;
}

say 'Show the sum that has the maximum number of solutions';
say "sum: $max_count; solutions: $count{$max_count}";

my $n = 1;
++$n until ! exists $count{$n};
say "Show the lowest positive sum that can't be expressed";
say $n;

say 'Show the ten highest numbers that can be expressed';
say for (sort { $b <=> $a } keys %count)[0 .. 9];