sub rref {
  our @m; local *m = shift;
  @m or return;
  my ($lead, $rows, $cols) = (0, scalar(@m), scalar(@{$m[0]}));

  foreach my $r (0 .. $rows - 1) {
     $lead < $cols or return;
      my $i = $r;

      until ($m[$i][$lead])
         {++$i == $rows or next;
          $i = $r;
          ++$lead == $cols and return;}

      @m[$i, $r] = @m[$r, $i];
      my $lv = $m[$r][$lead];
      $_ /= $lv foreach @{ $m[$r] };

      my @mr = @{ $m[$r] };
      foreach my $i (0 .. $rows - 1)
         {$i == $r and next;
          ($lv, my $n) = ($m[$i][$lead], -1);
          $_ -= $lv * $mr[++$n] foreach @{ $m[$i] };}

      ++$lead;}
}

sub display { join("\n" => map join(" " => map(sprintf("%6.2f", $_), @$_)), @{+shift})."\n" }

sub gauss_jordan_invert {
    my(@m) = @_;
    my $rows = @m;
    my @i = identity(scalar @m);
    push @{$m[$_]}, @{$i[$_]} for 0..$rows-1;
    rref(\@m);
    map { splice @$_, 0, $rows } @m;
    @m;
}

sub identity {
    my($n) = @_;
    map { [ (0) x $_, 1, (0) x ($n-1 - $_) ] } 0..$n-1
}

my @tests = (
    [
      [ 2, -1,  0 ],
      [-1,  2, -1 ],
      [ 0, -1,  2 ]
    ],
    [
      [ -1, -2, 3, 2 ],
      [ -4, -1, 6, 2 ],
      [  7, -8, 9, 1 ],
      [  1, -2, 1, 3 ]
    ],
);

for my $matrix (@tests) {
    print "Original Matrix:\n" . display(\@$matrix) . "\n";
    my @gj = gauss_jordan_invert( @$matrix );
    print "Gauss-Jordan Inverted Matrix:\n" . display(\@gj) . "\n";
    my @rt = gauss_jordan_invert( @gj );
    print "After round-trip:\n" . display(\@rt) . "\n";} . "\n"
}


using Lazy, Formatting

firstlast(a) = 10 * a[end] + a[1]
isgapful(n) = (d = digits(n); length(d) < 3 || (m = firstlast(d)) != 0 && mod(n, m) == 0)
gapfuls(start) = filter(isgapful, Lazy.range(start))

for (x, n) in [(100, 30), (1_000_000, 15), (1_000_000_000, 10)]
    println("First $n gapful numbers starting at ", format(x, commas=true), ":\n",
        take(n, gapfuls(x)))
end


private fun commatize(n: Long): String {
    val sb = StringBuilder(n.toString())
    val le = sb.length
    var i = le - 3
    while (i >= 1) {
        sb.insert(i, ',')
        i -= 3
    }
    return sb.toString()
}

fun main() {
    val starts = listOf(1e2.toLong(), 1e6.toLong(), 1e7.toLong(), 1e9.toLong(), 7123.toLong())
    val counts = listOf(30, 15, 15, 10, 25)
    for (i in starts.indices) {
        var count = 0
        var j = starts[i]
        var pow: Long = 100
        while (j >= pow * 10) {
            pow *= 10
        }
        System.out.printf(
            "First %d gapful numbers starting at %s:\n",
            counts[i],
            commatize(starts[i])
        )
        while (count < counts[i]) {
            val fl = j / pow * 10 + j % 10
            if (j % fl == 0L) {
                System.out.printf("%d ", j)
                count++
            }
            j++
            if (j >= 10 * pow) {
                pow *= 10
            }
        }
        println('\n')
    }
}


with javascript_semantics
function ToReducedRowEchelonForm(sequence M)
integer lead = 1,
        rowCount = length(M),
        columnCount = length(M[1]),
        i
    for r=1 to rowCount do
        if lead>=columnCount then exit end if
        i = r
        while M[i][lead]=0 do
            i += 1
            if i=rowCount then
                i = r
                lead += 1
                if lead=columnCount then exit end if
            end if
        end while
        object mr = sq_div(M[i],M[i][lead])
        M[i] = M[r]
        M[r] = mr
        for j=1 to rowCount do
            if j!=r then
                M[j] = sq_sub(M[j],sq_mul(M[j][lead],M[r]))
            end if
        end for
        lead += 1
    end for
    return M
end function
--</end of copy>

function inverse(sequence mat)
    integer len = length(mat)
    sequence aug = repeat(repeat(0,2*len),len)
    for i=1 to len do
        if length(mat[i])!=len then ?9/0 end if -- "Not a square matrix"
        for j=1 to len do
            aug[i][j] = mat[i][j]
        end for
        -- augment by identity matrix to right
        aug[i][i + len] = 1
    end for
    aug = ToReducedRowEchelonForm(aug)
    sequence inv = repeat(repeat(0,len),len)
    -- remove identity matrix to left
    for i=1 to len do
        for j=len+1 to 2*len do
            inv[i][j-len] = aug[i][j]
        end for
    end for
    return inv
end function

constant test = {{ 2, -1,  0},
                 {-1,  2, -1},
                 { 0, -1,  2}}
pp(inverse(test),{pp_Nest,1})


to bookend_number :n
  output sum product 10 first :n last :n
end

to gapful? :n
  output and greaterequal? :n 100 equal? 0 modulo :n bookend_number :n
end

to gapfuls_in_range :start :size
  localmake "gapfuls []
  do.while [
    if (gapful? :start) [
      make "gapfuls (lput :start gapfuls)
    ]
    make "start sum :start 1
  ] [less? (count :gapfuls) :size]
  output :gapfuls
end

to report_range :start :size
  print (word "|The first | :size "| gapful numbers >= | :start "|:|)
  print gapfuls_in_range :start :size
  (print)
end

foreach [ [1 30] [1000000 15] [1000000000 10] ] [
  apply "report_range ?
]


HAI 1.2

HOW IZ I FurstDigit YR Numbr
  I HAS A Digit
  IM IN YR LOOP NERFIN YR Dummy WILE DIFFRINT Numbr AN 0
    Digit R MOD OF Numbr AN 10
    Numbr R QUOSHUNT OF Numbr AN 10
  IM OUTTA YR LOOP
  FOUND YR Digit
IF U SAY SO

HOW IZ I LastDigit YR Numbr
  FOUND YR MOD OF Numbr AN 10
IF U SAY SO

HOW IZ I Bookend YR Numbr
  FOUND YR SUM OF PRODUKT OF I IZ FurstDigit YR Numbr MKAY AN 10 AN I IZ LastDigit YR Numbr MKAY
IF U SAY SO

HOW IZ I CheckGapful YR Numbr
  I HAS A Bookend ITZ I IZ Bookend YR Numbr MKAY
  I HAS A BigEnuff ITZ BOTH SAEM Numbr AN BIGGR OF Numbr AN 100
  FOUND YR BOTH OF BigEnuff AN BOTH SAEM 0 AN MOD OF Numbr AN Bookend
IF U SAY SO

HOW IZ I FindGapfuls YR Start AN YR HowMany
  I HAS A Numbr ITZ Start
  I HAS A Anser ITZ A BUKKIT
  I HAS A Found ITZ 0
  IM IN YR LOOP UPPIN YR Dummy WILE DIFFRINT Found AN HowMany
    I IZ CheckGapful YR Numbr MKAY
    O RLY?
      YA RLY
        Anser HAS A SRS Found ITZ Numbr
        Found R SUM OF Found AN 1
    OIC
    Numbr R SUM OF Numbr AN 1
  IM OUTTA YR LOOP
  FOUND YR Anser
IF U SAY SO

HOW IZ I Report YR Start AN YR HowMany
  VISIBLE "The furst " !
  VISIBLE HowMany !
  VISIBLE " Gapful numbrs starting with " !
  VISIBLE Start !
  VISIBLE ":"
  I HAS A Anser ITZ I IZ FindGapfuls YR Start AN YR HowMany MKAY
  IM IN YR Loop UPPIN YR Index TIL BOTH SAEM Index AN HowMany
    DIFFRINT Index AN 0
    O RLY?
      YA RLY
        VISIBLE ", " !
    OIC
    VISIBLE Anser'Z SRS Index !
  IM OUTTA YR Loop
  VISIBLE ""
  VISIBLE ""
IF U SAY SO

I IZ Report YR 1 AN YR 30 MKAY
I IZ Report YR 1000000 AN YR 15 MKAY
I IZ Report YR 1000000000 AN YR 10 MKAY
KTHXBYE


/* Gauss-Jordan matrix inversion */

G_J: procedure options (main);       /* 4 November 2020 */

   declare t float;
   declare (i, j, k, n) fixed binary;

   open file (sysin) title ('/GAUSSJOR.DAT');

   get (n);                     /* Read in the order of the matrix. */
   put skip data (n);
   begin;
      declare a(n,n)float, aux(n,n) float;

      aux = 0;
      do i = 1 to n; aux(i,i) = 1; end;
      get (a);                  /* Read in the matrix. */
      put skip list ('The matrix to be inverted is:');
      put edit (a) ( skip, (n) F(10,4)); /* Print  the matrix. */

      do k = 1 to n;
         /* Divide row k by a(k,k) */
         t = a(k,k); a(k,*) = a(k,*) / t; aux(k,*) = aux(k,*) / t;

         do i = 1 to k-1, k+1 to n; /* Work down the rows. */
            t = a(i,k);
            a(i,*) = a(i,*) - t*a(k,*); aux(i,*) = aux(i,*)  - t*aux(k,*);
         end;
      end;
      put skip (2) list ('The inverse is:');
      put edit (aux) ( skip, (n) F(10,4));
   end; /* of BEGIN block */
end G_J;


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

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

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

generateGaps(100, 30)
print()

generateGaps(1000000, 15)
print()

generateGaps(1000000000, 15)
print()


ClearAll[GapFulQ]
GapFulQ[n_Integer] := Divisible[n, FromDigits[IntegerDigits[n][[{1, -1}]]]]
i = 100;
res = {};
While[Length[res] < 30,
 If[GapFulQ[i], AppendTo[res, i]];
 i++
 ]
res
i = 10^6;
res = {};
While[Length[res] < 15,
 If[GapFulQ[i], AppendTo[res, i]];
 i++
 ]
res
i = 10^9;
res = {};
While[Length[res] < 10,
 If[GapFulQ[i], AppendTo[res, i]];
 i++
 ]
res


(() 0 shorten) :new
(((10 mod) (10 div)) cleave) :moddiv
((dup 0 ==) (pop new) 'moddiv 'cons linrec) :digits
(digits ((last 10 *) (first +)) cleave) :flnum
(mod 0 ==) :divisor?
(dup flnum divisor?) :gapful?

(
  :target :n 0 :count
  "$1 gapful numbers starting at $2:" (target n) => % puts!
  (count target <) (
    (n gapful?) (
      count succ @count
      n print! " " print!
    ) when
    n succ @n
  ) while
  newline
) :show-gapfuls

100 30 show-gapfuls newline
1000000 15 show-gapfuls newline
1000000000 10 show-gapfuls


; Part 1: Useful functions

;; Create an integer out of the first and last digits of a given integer
(define (first-and-last-digits number)
 (local (digits first-digit last-digit)
  (set 'digits (format "%d" number))
  (set 'first-digit (first digits))
  (set 'last-digit (last digits))
  (int (append first-digit last-digit))))

;; Divisbility test
(define (divisible-by? num1 num2)
 (zero? (% num1 num2)))

;; Gapfulness test
(define (gapful? number)
 (divisible-by? number (first-and-last-digits number)))

;; Increment until a gapful number is found
(define (next-gapful-after number)
 (do-until (gapful? number)
  (++ number)))

;; Return a list of gapful numbers beyond some (excluded) lower limit.
(define (gapful-numbers quantity lower-limit)
 (let ((gapfuls '()) (number lower-limit))
  (dotimes (counter quantity)
   (set 'number (next-gapful-after number))
   (push number gapfuls))
  (reverse gapfuls)))

;; Format a list of numbers together into decimal notation.
(define (format-many numbers)
 (map (curry format "%d") numbers))

;; Format a list of integers on one line with commas
(define (format-one-line numbers)
 (join (format-many numbers) ", "))

;; Display a quantity of gapful numbers beyond some (excluded) lower limit.
(define (show-gapfuls quantity lower-limit)
 (println "The first " quantity " gapful numbers beyond " lower-limit " are:")
 (println (format-one-line (gapful-numbers quantity lower-limit))))

; Part 2: Complete the task
(show-gapfuls 30 99)
(show-gapfuls 15 999999)
(show-gapfuls 10 999999999)
(exit)


import numpy as np
from numpy.linalg import inv
a = np.array([[1., 2., 3.], [4., 1., 6.],[ 7., 8., 9.]])
ainv = inv(a)

print(a)
print(ainv)


#lang racket

(require math/matrix
         math/array)

(define (inverse M)
  (define dim (square-matrix-size M))
  (define MI (matrix-augment (list M (identity-matrix dim))))
  (submatrix (matrix-row-echelon MI #t #t) (::) (:: dim  #f)))

(define A (matrix [[1 2 3] [4 1 6] [7 8 9]]))

(inverse A)
(matrix-inverse A)


sub gauss-jordan-invert (@m where &is-square) {
    ^@m .map: { @m[$_].append: identity(+@m)[$_] };
    @m.&rref[*]»[+@m .. *];
}

sub is-square (@m) { so @m == all @m[*] }

sub identity ($n) { [ 1, |(0 xx $n-1) ], *.rotate(-1).Array ... *.tail }

# reduced row echelon form (from 'Gauss-Jordan elimination' task)
sub rref (@m) {
    my ($lead, $rows, $cols) = 0, @m, @m[0];

    for ^$rows -> $r {
        $lead < $cols or return @m;
        my $i = $r;
        until @m[$i;$lead] {
            ++$i == $rows or next;
            $i = $r;
            ++$lead == $cols and return @m;
        }
        @m[$i, $r] = @m[$r, $i] if $r != $i;
        @m[$r] »/=» $ = @m[$r;$lead];
        for ^$rows -> $n {
            next if $n == $r;
            @m[$n] »-=» @m[$r] »×» (@m[$n;$lead] // 0);
        }
        ++$lead;
    }
    @m
}
sub rat-or-int ($num) {
    return $num unless $num ~~ Rat|FatRat;
    return $num.narrow if $num.narrow ~~ Int;
    $num.nude.join: '/';
}

sub say_it ($message, @array) {
    my $max;
    @array.map: {$max max= max $_».&rat-or-int.comb(/\S+/)».chars};
    say "\n$message";
    $_».&rat-or-int.fmt(" %{$max}s").put for @array;
}

multi to-matrix ($str) { [$str.split(';').map(*.words.Array)] }
multi to-matrix (@array) { @array }

sub hilbert-matrix ($h) {
    [ (1..$h).map( -> $n { [ ($n ..^ $n + $h).map: { (1/$_).FatRat } ] } ) ]
}

my @tests =
    '1 2 3; 4 1 6; 7 8 9',
    '2 -1 0; -1 2 -1; 0 -1 2',
    '-1 -2 3 2; -4 -1 6 2; 7 -8 9 1; 1 -2 1 3',
    '1 2 3 4; 5 6 7 8; 9 33 11 12; 13 14 15 17',
    '3 1 8 9 6; 6 2 8 10 1; 5 7 2 10 3; 3 2 7 7 9; 3 5 6 1 1',

    # Test with a Hilbert matrix
    hilbert-matrix 10;

@tests.map: {
    my @matrix = .&to-matrix;
    say_it( " {'=' x 20} Original Matrix: {'=' x 20}", @matrix );
    say_it( ' Gauss-Jordan Inverted:', my @invert = gauss-jordan-invert @matrix );
    say_it( ' Re-inverted:', gauss-jordan-invert @invert».Array );
}


import strutils

func gapfulDivisor(n: Positive): Positive =
  ## Return the gapful divisor of "n".

  let last = n mod 10
  var first = n div 10
  while first > 9:
    first = first div 10
  result = 10 * first + last

iterator gapful(start: Positive): Positive =
  ## Yield the gapful numbers starting from "start".

  var n = start
  while true:
    let d = n.gapfulDivisor()
    if n mod d == 0: yield n
    inc n

proc displayGapfulNumbers(start, num: Positive) =
  ## Display the first "num" gapful numbers greater or equal to "start".

  echo "\nFirst $1 gapful numbers ⩾ $2:".format(num, start)
  var count = 0
  var line: string
  for n in gapful(start):
    line.addSep(" ")
    line.add($n)
    inc count
    if count == num: break
  echo line

when isMainModule:
  displayGapfulNumbers(100, 30)
  displayGapfulNumbers(1_000_000, 15)
  displayGapfulNumbers(1_000_000_000, 10)


program gapful;

{$IFDEF FPC}
   {$MODE DELPHI}{$OPTIMIZATION ON,ALL}
{$ELSE}
  {$APPTYPE CONSOLE}
{$ENDIF}

uses
  sysutils // IntToStr
{$IFDEF FPC}
  ,strUtils // Numb2USA aka commatize
{$ENDIF};

const
  cIdx = 5;
  starts: array[0..cIdx - 1] of Uint64 = (100, 1000 * 1000, 10 * 1000 * 1000,
    1000 * 1000 * 1000, 7123);
  counts: array[0..cIdx - 1] of Uint64 = (30, 15, 15, 10, 25);
  //100|  74623687  =>    1000*1000*1000
  //100| 746236131  => 10*1000*1000*1000
  //100|7462360431  =>100*1000*1000*1000
  Base = 10;

var
  ModsHL: array[0..99] of NativeUint;
  Pow10: Uint64;    //global, seldom used
  countLmt: NativeUint; //Uint64; only for extreme counting

{$IFNDEF FPC}

function Numb2USA(const S: string): string;
var
  i, NA: Integer;
begin
  i := Length(S);
  Result := S;
  NA := 0;
  while (i > 0) do
  begin
    if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
    begin
      insert(',', Result, i);
      inc(NA);
    end;
    Dec(i);
  end;
end;
{$ENDIF}

procedure OutHeader(i: NativeInt);
begin
  writeln('First ', counts[i], ', gapful numbers starting at ', Numb2USA(IntToStr
    (starts[i])));
end;

procedure OutNum(n: Uint64);
begin
  write(' ', n);
end;

procedure InitMods(n: Uint64; H_dgt: NativeUint);
//calculate first mod of n, when it reaches n
var
  i, j: NativeInt;
begin
  j := H_dgt; //= H_dgt+i
  for i := 0 to Base - 1 do
  begin
    ModsHL[j] := n mod j;
    inc(n);
    inc(j);
  end;
end;

procedure InitMods2(n: Uint64; H_dgt, L_Dgt: NativeUint);
//calculate first mod of n, when it reaches n
//beware, that the lower n are reached in the next base round
var
  i, j: NativeInt;
begin
  j := H_dgt;
  n := n - L_Dgt;
  for i := 0 to L_Dgt - 1 do
  begin
    ModsHL[j] := (n + base) mod j;
    inc(n);
    inc(j);
  end;
  for i := L_Dgt to Base - 1 do
  begin
    ModsHL[j] := n mod j;
    inc(n);
    inc(j);
  end;
end;

procedure Main(TestNum: Uint64; Cnt: NativeUint);
var
  LmtNextNewHiDgt: Uint64;
  tmp, LowDgt, GapNum: NativeUint;
begin
  countLmt := Cnt;
  Pow10 := Base * Base;
  LmtNextNewHiDgt := Base * Pow10;
  while LmtNextNewHiDgt <= TestNum do
  begin
    Pow10 := LmtNextNewHiDgt;
    LmtNextNewHiDgt := LmtNextNewHiDgt * Base;
  end;
  LowDgt := TestNum mod Base;
  GapNum := TestNum div Pow10;
  LmtNextNewHiDgt := (GapNum + 1) * Pow10;
  GapNum := Base * GapNum;
  if LowDgt <> 0 then
    InitMods2(TestNum, GapNum, LowDgt)
  else
    InitMODS(TestNum, GapNum);

  GapNum := GapNum + LowDgt;
  repeat
//     if TestNum MOD (GapNum) = 0 then
    if ModsHL[GapNum] = 0 then
    begin
      tmp := countLmt - 1;
      if tmp < 32 then
        OutNum(TestNum);
      countLmt := tmp;
      // Test and BREAK only if something has changed
      if tmp = 0 then
        BREAK;
    end;
    tmp := Base + ModsHL[GapNum];
    //translate into "if-less" version 3.35s -> 1.85s
    //bad branch prediction :-(
    //if tmp >= GapNum then tmp -= GapNum;
    tmp := tmp - (-ORD(tmp >= GapNum) and GapNum);
    ModsHL[GapNum] := tmp;

    TestNum := TestNum + 1;
    tmp := LowDgt + 1;

    inc(GapNum);
    if tmp >= Base then
    begin
      tmp := 0;
      GapNum := GapNum - Base;
    end;
    LowDgt := tmp;
    //next Hi Digit
    if TestNum >= LmtNextNewHiDgt then
    begin
      LowDgt := 0;
      GapNum := GapNum + Base;
      LmtNextNewHiDgt := LmtNextNewHiDgt + Pow10;
      //next power of 10
      if GapNum >= Base * Base then
      begin
        Pow10 := Pow10 * Base;
        LmtNextNewHiDgt := 2 * Pow10;
        GapNum := Base;
      end;
      initMods(TestNum, GapNum);
    end;
  until false;
end;

var
  i: integer;

begin
  for i := 0 to High(starts) do
  begin
    OutHeader(i);
    Main(starts[i], counts[i]);
    writeln(#13#10);
  end;
  {$IFNDEF LINUX}  readln; {$ENDIF}
end.


/* REXX */
Parse Arg seed nn
If seed='' Then
  seed=23345
If nn='' Then nn=5
If seed='?' Then Do
  Say 'rexx gjmi seed n computes a random matrix with n rows and columns'
  Say 'Default is 23345 5'
  Exit
  End
Numeric Digits 50
Call random 1,2,seed
a=''
Do i=1 To nn**2
  a=a random(9)+1
  End
n2=words(a)
Do n=2 To n2/2
  If n**2=n2 Then
    Leave
  End
If n>n2/2 Then
  Call exit 'Not a square matrix:' a '('n2 'elements).'
det=determinante(a,n)
If det=0 Then
  Call exit 'Determinant is 0'
Do j=1 To n
  Do i=1 To n
    Parse Var A a.i.j a
    aa.i.j=a.i.j
    End
  Do ii=1 To n
    z=(ii=j)
    iii=ii+n
    a.iii.j=z
    End
  End
Call show 1,'The given matrix'
Do m=1 To n-1
  If a.m.m=0 Then Do
    Do j=m+1 To n
      If a.m.j<>0 Then Leave
      End
    If j>n Then Do
      Say 'No pivot>0 found in column' m
      Exit
      End
    Do i=1 To n*2
      temp=a.i.m
      a.i.m=a.i.j
      a.i.j=temp
      End
    End
  Do j=m+1 To n
    If a.m.j<>0 Then Do
      jj=m
      fact=divide(a.m.m,a.m.j)
      Do i=1 To n*2
        a.i.j=subtract(multiply(a.i.j,fact),a.i.jj)
        End
      End
    End
  Call show 2 m
  End
Say 'Lower part has all zeros'
Say ''

Do j=1 To n
  If denom(a.j.j)<0 Then Do
    Do i=1 To 2*n
      a.i.j=subtract(0,a.i.j)
      End
    End
  End
Call show 3

Do m=n To 2 By -1
  Do j=1 To m-1
    jj=m
    fact=divide(a.m.j,a.m.jj)
    Do i=1 To n*2
      a.i.j=subtract(a.i.j,multiply(a.i.jj,fact))
      End
    End
  Call show 4 m
  End
Say 'Upper half has all zeros'
Say ''
Do j=1 To n
  If decimal(a.j.j)<>1 Then Do
    z=a.j.j
    Do i=1 To 2*n
      a.i.j=divide(a.i.j,z)
      End
    End
  End
Call show 5
Say 'Main diagonal has all ones'
Say ''

Do j=1 To n
  Do i=1 To n
    z=i+n
    a.i.j=a.z.j
    End
  End
Call show 6,'The inverse matrix'

do i = 1 to n
  do j = 1 to n
    sum=0
    Do k=1 To n
      sum=add(sum,multiply(aa.i.k,a.k.j))
      End
    c.i.j = sum
    end
  End
Call showc 7,'The product of input and inverse matrix'
Exit

show:
  Parse Arg num,text
  Say 'show' arg(1) text
  If arg(1)<>6 Then rows=n*2
               Else rows=n
  len=0
  Do j=1 To n
    Do i=1 To rows
      len=max(len,length(a.i.j))
      End
    End
  Do j=1 To n
    ol=''
    Do i=1 To rows
      ol=ol||right(a.i.j,len+1)
      End
    Say ol
    End
  Say ''
  Return

showc:
  Parse Arg num,text
  Say text
  clen=0
  Do j=1 To n
    Do i=1 To n
      clen=max(clen,length(c.i.j))
      End
    End
  Do j=1 To n
    ol=''
    Do i=1 To n
      ol=ol||right(c.i.j,clen+1)
      End
    Say ol
    End
  Say ''
  Return

denom: Procedure
  /* Return the denominator */
  Parse Arg d '/' n
  Return d

decimal: Procedure
  /* compute the fraction's value */
  Parse Arg a
  If pos('/',a)=0 Then a=a'/1'; Parse Var a ad '/' an
  Return ad/an

gcd: procedure
/**********************************************************************
* Greatest commn divisor
**********************************************************************/
  Parse Arg a,b
  If b = 0 Then Return abs(a)
  Return gcd(b,a//b)

add: Procedure
  Parse Arg a,b
  If pos('/',a)=0 Then a=a'/1'; Parse Var a ad '/' an
  If pos('/',b)=0 Then b=b'/1'; Parse Var b bd '/' bn
  sum=divide(ad*bn+bd*an,an*bn)
  Return sum

multiply: Procedure
  Parse Arg a,b
  If pos('/',a)=0 Then a=a'/1'; Parse Var a ad '/' an
  If pos('/',b)=0 Then b=b'/1'; Parse Var b bd '/' bn
  prd=divide(ad*bd,an*bn)
  Return prd

subtract: Procedure
  Parse Arg a,b
  If pos('/',a)=0 Then a=a'/1'; Parse Var a ad '/' an
  If pos('/',b)=0 Then b=b'/1'; Parse Var b bd '/' bn
  div=divide(ad*bn-bd*an,an*bn)
  Return div

divide: Procedure
  Parse Arg a,b
  If pos('/',a)=0 Then a=a'/1'; Parse Var a ad '/' an
  If pos('/',b)=0 Then b=b'/1'; Parse Var b bd '/' bn
  sd=ad*bn
  sn=an*bd
  g=gcd(sd,sn)
  Select
    When sd=0 Then res='0'
    When abs(sn/g)=1 Then res=(sd/g)*sign(sn/g)
    Otherwise Do
      den=sd/g
      nom=sn/g
      If nom<0 Then Do
        If den<0 Then den=abs(den)
        Else den=-den
        nom=abs(nom)
        End
      res=den'/'nom
      End
    End
  Return res

determinante: Procedure
/* REXX ***************************************************************
* determinant.rex
* compute the determinant of the given square matrix
* Input: as: the representation of the matrix as vector (n**2 elements)
* 21.05.2013 Walter Pachl
**********************************************************************/
  Parse Arg as,n
  Do i=1 To n
    Do j=1 To n
      Parse Var as a.i.j as
      End
    End
  Select
    When n=2 Then det=subtract(multiply(a.1.1,a.2.2),multiply(a.1.2,a.2.1))
    When n=3 Then Do
      det=multiply(multiply(a.1.1,a.2.2),a.3.3)
      det=add(det,multiply(multiply(a.1.2,a.2.3),a.3.1))
      det=add(det,multiply(multiply(a.1.3,a.2.1),a.3.2))
      det=subtract(det,multiply(multiply(a.1.3,a.2.2),a.3.1))
      det=subtract(det,multiply(multiply(a.1.2,a.2.1),a.3.3))
      det=subtract(det,multiply(multiply(a.1.1,a.2.3),a.3.2))
      End
    Otherwise Do
      det=0
      Do k=1 To n
        sign=((-1)**(k+1))
        If sign=1 Then
          det=add(det,multiply(a.1.k,determinante(subm(k),n-1)))
        Else
          det=subtract(det,multiply(a.1.k,determinante(subm(k),n-1)))
        End
      End
    End
  Return det

subm: Procedure Expose a. n
/**********************************************************************
* compute the submatrix resulting when row 1 and column k are removed
* Input: a.*.*, k
* Output: bs the representation of the submatrix as vector
**********************************************************************/
  Parse Arg k
  bs=''
  do i=2 To n
    Do j=1 To n
      If j=k Then Iterate
      bs=bs a.i.j
      End
    End
  Return bs

Exit: Say arg(1)


use strict;
use warnings;
use feature 'say';

sub comma { reverse ((reverse shift) =~ s/(.{3})/$1,/gr) =~ s/^,//r }

sub is_gapful { my $n = shift; 0 == $n % join('', (split //, $n)[0,-1]) }

use constant Inf => 1e10;
for ([1e2, 30], [1e6, 15], [1e9, 10], [7123, 25]) {
    my($start, $count) = @$_;
    printf "\nFirst $count gapful numbers starting at %s:\n", comma $start;
    my $n = 0; my $g = '';
    $g .= do { $n < $count ? (is_gapful($_) and ++$n and "$_ ") : last } for $start .. Inf;
    say $g;
}


constant starts = {1e2, 1e6, 1e7, 1e9, 7123},
         counts = {30,  15,  15,  10,  25}
for i=1 to length(starts) do
    integer count = counts[i],
            j = starts[i],
            pow = 100
    while j>=pow*10 do pow *= 10 end while
    printf(1,"First %d gapful numbers starting at %,d: ", {count, j})
    while count do
        integer fl = floor(j/pow)*10 + remainder(j,10)
        if remainder(j,fl)==0 then
            printf(1,"%d ", j)
            count -= 1
        end if
        j += 1
        if j>=10*pow then
            pow *= 10
        end if
    end while
    printf(1,"\n")
end for


fn main() {
    let mut a: Vec<Vec<f64>> = vec![vec![1.0, 2.0, 3.0],
                                vec![4.0, 1.0, 6.0],
                                vec![7.0, 8.0, 9.0]
                                ];
    let mut b: Vec<Vec<f64>> = vec![vec![2.0, -1.0, 0.0],
                                vec![-1.0, 2.0, -1.0],
                                vec![0.0, -1.0, 2.0]
                                ];

    let mut ref_a = &mut a;
    let rref_a = &mut ref_a;
    let mut ref_b = &mut b;
    let rref_b = &mut ref_b;

    println!("Matrix A:\n");
    print_matrix(rref_a);
    println!("\nInverse of Matrix A:\n");
    print_matrix(&mut matrix_inverse(rref_a));
    println!("\n\nMatrix B:\n");
    print_matrix(rref_b);
    println!("\nInverse of Matrix B:\n");
    print_matrix(&mut matrix_inverse(rref_b));
}

//Begin Matrix Inversion
fn matrix_inverse(matrix: &mut Vec<Vec<f64>>) -> Vec<Vec<f64>>{
    let len = matrix.len();
    let mut aug = zero_matrix(len, len * 2);
    for i in 0..len {
        for j in 0.. len {
            aug[i][j] = matrix[i][j];
        }
        aug[i][i + len] = 1.0;
    }

    gauss_jordan_general(&mut aug);

    let mut unaug = zero_matrix(len, len);
    for i in 0..len {
        for j in 0..len {
            unaug[i][j] = aug[i][j+len];
        }
    }
    unaug
}
//End Matrix Inversion

//Begin Generalised Reduced Row Echelon Form
fn gauss_jordan_general(matrix: &mut Vec<Vec<f64>>) {
    let mut lead = 0;
    let row_count = matrix.len();
    let col_count = matrix[0].len();

    for r in 0..row_count {
        if col_count <= lead {
            break;
        }
        let mut i = r;
        while matrix[i][lead] == 0.0 {
            i = i + 1;
            if row_count == i {
                i = r;
                lead = lead + 1;
                if col_count == lead {
                    break;
                }
            }
        }

        let temp = matrix[i].to_owned();
        matrix[i] = matrix[r].to_owned();
        matrix[r] = temp.to_owned();

        if matrix[r][lead] != 0.0 {
            let div = matrix[r][lead];
            for j in 0..col_count {
                matrix[r][j] = matrix[r][j] / div;
            }
        }

        for k in 0..row_count {
            if k != r {
                let mult = matrix[k][lead];
                for j in 0..col_count {
                    matrix[k][j] = matrix[k][j] - matrix[r][j] * mult;
                }
            }
        }
        lead = lead + 1;

    }
    //matrix.to_owned()
}

fn zero_matrix(rows: usize, cols: usize) -> Vec<Vec<f64>> {
    let mut matrix = Vec::with_capacity(cols);
    for _ in 0..rows {
        let mut col: Vec<f64> = Vec::with_capacity(rows);
        for _ in 0..cols {
            col.push(0.0);
        }
        matrix.push(col);
    }
    matrix
}

fn print_matrix(mat: &mut Vec<Vec<f64>>) {
    for row in 0..mat.len(){
        println!("{:?}", mat[row]);
    }
}


func gauss_jordan_invert (M) {

    var I = M.len.of {|i|
        M.len.of {|j|
            i == j ? 1 : 0
        }
    }

    var A = gather {
        ^M -> each {|i| take(M[i] + I[i]) }
    }

    rref(A).map { .last(M.len) }
}

var A = [
    [-1, -2, 3, 2],
    [-4, -1, 6, 2],
    [ 7, -8, 9, 1],
    [ 1, -2, 1, 3],
]

say gauss_jordan_invert(A).map {
    .map { "%6s" % .as_rat }.join("  ")
}.join("\n")


Private Function inverse(mat As Variant) As Variant
    Dim len_ As Integer: len_ = UBound(mat)
    Dim tmp() As Variant
    ReDim tmp(2 * len_ + 1)
    Dim aug As Variant
    ReDim aug(len_)
    For i = 0 To len_
        If UBound(mat(i)) <> len_ Then Debug.Print 9 / 0 '-- "Not a square matrix"
        aug(i) = tmp
        For j = 0 To len_
            aug(i)(j) = mat(i)(j)
        Next j
        '-- augment by identity matrix to right
        aug(i)(i + len_ + 1) = 1
    Next i
    aug = ToReducedRowEchelonForm(aug)
    Dim inv As Variant
    inv = mat
    '-- remove identity matrix to left
    For i = 0 To len_
        For j = len_ + 1 To 2 * len_ + 1
            inv(i)(j - len_ - 1) = aug(i)(j)
        Next j
    Next i
    inverse = inv
End Function

Public Sub main()
    Dim test As Variant
    test = inverse(Array( _
        Array(2, -1, 0), _
        Array(-1, 2, -1), _
        Array(0, -1, 2)))
    For i = LBound(test) To UBound(test)
        For j = LBound(test(0)) To UBound(test(0))
            Debug.Print test(i)(j),
        Next j
    Debug.Print
    Next i
End Sub


To run:
Start up.
Show the gapful numbers at various spots.
Wait for the escape key.
Shut down.

A digit is a number.

To get a digit of a number (last):
Privatize the number.
Divide the number by 10 giving a quotient and a remainder.
Put the remainder into the digit.

To get a digit of a number (first):
Privatize the number.
Loop.
Divide the number by 10 giving a quotient and a remainder.
Put the quotient into the number.
If the number is 0, put the remainder into the digit; exit.
Repeat.

To make a number from the first and last digits of another number:
Get a digit of the other number (first).
Get another digit of the other number (last).
Put the digit times 10 plus the other digit into the number.

To decide if a number is gapful:
Make another number from the first and last digits of the number.
If the number is evenly divisible by the other number, say yes.
Say no.

To show a number of the gapful numbers starting from another number:
Privatize the other number.
Put 0 into a gapful counter.
Loop.
If the other number is gapful, write "" then the other number then " " on the console without advancing; bump the gapful counter.
If the gapful counter is the number, break.
Bump the other number.
Repeat.
Write "" then the return byte on the console.

To show the gapful numbers at various spots:
Write "30 gapful numbers starting at 100:" on the console.
Show 30 of the gapful numbers starting from 100.
Write "15 gapful numbers starting at 1000000:" on the console.
Show 15 of the gapful numbers starting from 1000000.
Write "10 gapful numbers starting at 1000000000:" on the console.
Show 10 of the gapful numbers starting from 1000000000.


100H: /* FIND SOME GAPFUL NUMBERS: NUMBERS DIVISIBLE BY 10F + L WHERE F IS */
      /*                           THE FIRST DIGIT AND L IS THE LAST DIGIT */
   BDOS: PROCEDURE( FN, ARG ); /* CP/M BDOS SYSTEM CALL */
      DECLARE FN BYTE, ARG ADDRESS;
      GOTO 5;
   END BDOS;
   PR$CHAR:   PROCEDURE( C ); DECLARE C BYTE;    CALL BDOS( 2, C ); END;
   PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
   PR$NL:     PROCEDURE; CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH );  END;
   PR$NUMBER: PROCEDURE( N );
      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 TRUE IF N IS GAPFUL, FALSE OTHERWISE                         */
   IS$GAPFUL: PROCEDURE( N )BYTE;
      DECLARE N ADDRESS;
      DECLARE F ADDRESS;
      F = N / 10;
      DO WHILE ( F > 9 );
         F = F / 10;
      END;
      RETURN N MOD ( ( F * 10 ) + ( N MOD 10 ) ) = 0;
   END IS$GAPFUL;
   /* FIND THE FIRST 30 GAPFUL NUMBERS >= 100                              */
   CALL PR$STRING( .'FIRST 30 GAPFUL NUMBERS STARTING FROM 100:$' );
   CALL PR$NL;
   DECLARE N ADDRESS, G$COUNT BYTE;
   G$COUNT = 0;
   N = 100;
   DO WHILE ( G$COUNT < 30 );
      IF IS$GAPFUL( N ) THEN DO;
         /* HAVE A GAPFUL NUMBER                                           */
         G$COUNT = G$COUNT + 1;
         CALL PR$CHAR( ' ' );
         CALL PR$NUMBER( N );
      END;
      N = N + 1;
   END;
   CALL PR$NL;

EOF


' Gauss-Jordan matrix inversion - VBScript - 22/01/2021
Option Explicit

Function rref(m)
    Dim r, c, i, n, div, wrk
    n=UBound(m)
    For r = 1 To n  'row
        div = m(r,r)
        If div <> 0 Then
            For c = 1 To n*2  'col
                m(r,c) = m(r,c) / div
            Next 'c
        Else
            WScript.Echo "inversion impossible!"
            WScript.Quit
        End If
        For i = 1 To n  'row
            If i <> r Then
                wrk = m(i,r)
                For c = 1 To n*2
                    m(i,c) = m(i,c) - wrk * m(r,c)
                Next' c
            End If
        Next 'i
    Next 'r
    rref = m
End Function 'rref

Function inverse(mat)
    Dim i, j, aug, inv, n
    n = UBound(mat)
    ReDim inv(n,n), aug(n,2*n)
    For i = 1 To n
        For j = 1 To n
            aug(i,j) = mat(i,j)
        Next 'j
        aug(i,i+n) = 1
    Next 'i
    aug = rref(aug)
    For i = 1 To n
        For j = n+1 To 2*n
            inv(i,j-n) = aug(i,j)
        Next 'j
    Next 'i
    inverse = inv
End Function 'inverse

Sub wload(m)
    Dim i, j, k
    k = -1
    For i = 1 To n
        For j = 1 To n
            k = k + 1
            m(i,j) = w(k)
        Next 'j
    Next 'i
End Sub 'wload

Sub show(c, m, t)
    Dim i, j, buf
    buf = "Matrix " & c &"=" & vbCrlf & vbCrlf
    For i = 1 To n
        For j = 1 To n
            If t="fixed" Then
                buf = buf & FormatNumber(m(i,j),6,,,0) & "  "
            Else
                buf = buf & m(i,j) & "  "
            End If
        Next 'j
        buf=buf & vbCrlf
    Next 'i
    WScript.Echo buf
End Sub 'show

Dim n, a, b, c, w
w = Array( _
	2,  1,  1,  4, _
	0, -1,  0, -1, _
	1,  0, -2,  4, _
	4,  1,  2,  2)
n=Sqr(UBound(w)+1)
ReDim a(n,n), b(n,n), c(n,n)
wload a
show "a", a, "simple"
b = inverse(a)
show "b", b, "fixed"
c = inverse(b)
show "c", c, "fixed"


import "/matrix" for Matrix
import "/fmt" for Fmt

var arrays = [
    [ [ 1,  2,  3],
      [ 4,  1,  6],
      [ 7,  8,  9] ],

    [ [ 2, -1,  0 ],
      [-1,  2, -1 ],
      [ 0, -1,  2 ] ],

    [ [ -1, -2, 3, 2 ],
      [ -4, -1, 6, 2 ],
      [  7, -8, 9, 1 ],
      [  1, -2, 1, 3 ] ]
]

for (array in arrays) {
    System.print("Original:\n")
    var m = Matrix.new(array)
    Fmt.mprint(m, 2, 0)
    System.print("\nInverse:\n")
    Fmt.mprint(m.inverse, 9, 6)
    System.print()
}


function Get-FirstDigit {
  param ( [int] $Number )
  [int]$Number.ToString().Substring(0,1)
}

function Get-LastDigit {
  param ( [int] $Number )
  $Number % 10
}

function Get-BookendNumber {
  param ( [Int] $Number )
  10 * (Get-FirstDigit $Number) + (Get-LastDigit $Number)
}

function Test-Gapful {
  param ( [Int] $Number )
  100 -lt $Number -and 0 -eq $Number % (Get-BookendNumber $Number)
}

function Find-Gapfuls {
  param ( [Int] $Start, [Int] $Count )
  $result = @()

  While ($result.Count -lt $Count)  {
    If (Test-Gapful $Start) {
      $result += @($Start)
    }
    $Start += 1
  }
  return $result
}

function Search-Range {
  param ( [Int] $Start, [Int] $Count )
  Write-Output "The first $Count gapful numbers >= $($Start):"
  Write-Output( (Find-Gapfuls $Start $Count) -join ",")
  Write-Output ""
}

Search-Range 1 30
Search-Range 1000000 15
Search-Range 1000000000 10


Procedure.b isGapNum(n.i)
  n1.i=n%10
  n2.i=Val(Left(Str(n),1))
  If n%(n2*10+n1)=0
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure PutGapNum(start.i,rep.i,lfi.i=10)
  n.i=start
  While rep
    If isGapNum(n)
      Print(Str(n)+" ")
      rep-1
      If rep%lfi=0 : PrintN("") : EndIf
    EndIf
    n+1
  Wend
EndProcedure

OpenConsole()
PrintN("First 30 gapful numbers ≥ 100:")
PutGapNum(100,30)
PrintN(~"\nFirst 15 gapful numbers ≥ 1,000,000:")
PutGapNum(1000000,15,5)
PrintN(~"\nFirst 10 gapful numbers ≥ 1,000,000,000:")
PutGapNum(1000000000,10,5)
Input()


var [const] GSL=Import.lib("zklGSL");    // libGSL (GNU Scientific Library)
m:=GSL.Matrix(3,3).set(1,2,3, 4,1,6, 7,8,9);
i:=m.invert();
i.format(10,4).println("\n");
(m*i).format(10,4).println();


from itertools import islice, count
for start, n in [(100, 30), (1_000_000, 15), (1_000_000_000, 10)]:
    print(f"\nFirst {n} gapful numbers from {start:_}")
    print(list(islice(( x for x in count(start)
                        if (x % (int(str(x)[0]) * 10 + (x % 10)) == 0) )
                      , n)))


use Lingua::EN::Numbers;

for (1e2, 30, 1e6, 15, 1e9, 10, 7123, 25)».Int -> $start, $count {
    put "\nFirst $count gapful numbers starting at {comma $start}:\n" ~
    <Sir Lord Duke King>.pick ~ ": ", ~
    ($start..*).grep( { $_ %% .comb[0, *-1].join } )[^$count];
}


/*REXX program computes and displays a series of gapful numbers starting at some number.*/
numeric digits 20                                /*ensure enough decimal digits gapfuls.*/
parse arg gapfuls                                /*obtain optional arguments from the CL*/
if gapfuls=''  then gapfuls= 30 25@7123 15@1000000 10@1000000000      /*assume defaults.*/

        do until gapfuls='';      parse var gapfuls stuff gapfuls;       call gapful stuff
        end   /*until*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
gapful: procedure; parse arg n "@" sp;  if sp==''  then sp= 100 /*get args; use default.*/
        say center(' 'n      " gapful numbers starting at: "     sp' ', 125, "═")
        $=;                   #= 0                              /*initialize the $ list.*/
               do j=sp  until #==n                              /*SP:  starting point.  */
               parse var   j   a  2  ''  -1  b                  /*get 1st and last digit*/
               if j // (a||b) \== 0  then iterate               /*perform  ÷  into  J.  */
               #= # + 1;             $= $ j                     /*bump #;  append ──► $ */
               end   /*j*/
        say strip($);     say;     return


nr = 0
gapful1 = 99
gapful2 = 999999
gapful3 = 999999999
limit1 = 30
limit2 = 15
limit3 = 10

see "First 30 gapful numbers >= 100:" + nl
while nr < limit1
      gapful1 = gapful1 + 1
      gap1 = left((string(gapful1)),1)
      gap2 = right((string(gapful1)),1)
      gap = number(gap1 +gap2)
      if gapful1 % gap = 0
         nr = nr + 1
         see "" + nr + ". " + gapful1 + nl
      ok
end
see nl

see "First 15 gapful numbers >= 1000000:" + nl
nr = 0
while nr < limit2
      gapful2 = gapful2 + 1
      gap1 = left((string(gapful2)),1)
      gap2 = right((string(gapful2)),1)
      gap = number(gap1 +gap2)
      if (nr < limit2) and gapful2 % gap = 0
         nr = nr + 1
         see "" + nr + ". " + gapful2 + nl
      ok
end
see nl

see "First 10 gapful numbers >= 1000000000:" + nl
nr = 0
while nr < limit3
      gapful3 = gapful3 + 1
      gap1 = left((string(gapful3)),1)
      gap2 = right((string(gapful3)),1)
      gap = number(gap1 +gap2)
      if (nr < limit2) and gapful3 % gap = 0
         nr = nr + 1
         see "" + nr + ". " + gapful3 + nl
      ok
end


class Integer
  def gapful?
    a = digits
    self % (a.last*10 + a.first) == 0
  end
end

specs = {100 => 30, 1_000_000 => 15, 1_000_000_000 => 10, 7123 => 25}

specs.each do |start, num|
  puts "first #{num} gapful numbers >= #{start}:"
  p (start..).lazy.select(&:gapful?).take(num).to_a
end


(define (first-digit n) (string->number (string (string-ref (number->string n) 0))))
(define (last-digit n) (modulo n 10))
(define (bookend-number n) (+ (* 10 (first-digit n)) (last-digit n)))
(define (gapful? n) (and (>= n 100) (zero? (modulo n (bookend-number n)))))

(define (gapfuls-in-range start size)
  (let ((found 0) (result '()))
    (do ((n start (+ n 1))) ((>= found size) (reverse result))
      (if (gapful? n)
        (begin (set! result (cons n result)) (set! found (+ found 1)))))))

(define (report-range range)
  (apply (lambda (start size)
    (newline)
    (display "The first ")(display size)(display " gapful numbers >= ")
    (display start)(display ":")(newline)
    (display (gapfuls-in-range start size))(newline)) range))

(map report-range '((100 30) (1000000 15) (1000000000 10)))


func is_gapful(n, base=10) {
    n.is_div(base*floor(n / base**n.ilog(base)) + n%base)
}

var task = [
    "(Required) The first %s gapful numbers (>= %s)", 30, 1e2, 10,
    "(Required) The first %s gapful numbers (>= %s)", 15, 1e6, 10,
    "(Required) The first %s gapful numbers (>= %s)", 10, 1e9, 10,
    "(Extra) The first %s gapful numbers (>= %s)", 10, 987654321, 10,
    "(Extra) The first %s gapful numbers (>= %s)", 10, 987654321, 12,
]

task.each_slice(4, {|title, n, from, b|
    say sprintf("\n#{title} for base #{b}:", n, from.commify)
    say (from..Inf -> lazy.grep{ is_gapful(_,b) }.first(n).join(' '))
})


/*
This code is an implementation of gapful numbers in SQL ORACLE 19c
p_start -- start point
p_count -- total number to be found
*/
WITH
  FUNCTION gapful_numbers(p_start IN INTEGER, p_count IN INTEGER) RETURN varchar2 IS
    v_start   INTEGER := p_start;
    v_count   INTEGER := 0;
    v_res     varchar2(32767);
  BEGIN
    v_res := 'First '||p_count||' gapful numbers starting from '||p_start||': ';
    -- main cycle
    while TRUE loop
      IF MOD(v_start,to_number(substr(v_start,1,1)||substr(v_start,-1))) = 0 THEN
         v_res := v_res || v_start;
         v_count := v_count + 1;
         exit WHEN v_count = p_count;
         v_res := v_res || ', ';
      END IF;
      v_start := v_start + 1;
    END loop;
    --
    RETURN v_res;
    --
  END;

--Test
SELECT gapful_numbers(100,30) AS res FROM dual
UNION ALL
SELECT gapful_numbers(1000000,15) AS res FROM dual
UNION ALL
SELECT gapful_numbers(1000000000,10) AS res FROM dual;
/


func isGapful(n: Int) -> Bool {
  guard n > 100 else {
    return true
  }

  let asString = String(n)
  let div = Int("\(asString.first!)\(asString.last!)")!

  return n % div == 0
}

let first30 = (100...).lazy.filter(isGapful).prefix(30)
let mil = (1_000_000...).lazy.filter(isGapful).prefix(15)
let bil = (1_000_000_000...).lazy.filter(isGapful).prefix(15)

print("First 30 gapful numbers: \(Array(first30))")
print("First 15 >= 1,000,000: \(Array(mil))")
print("First 15 >= 1,000,000,000: \(Array(bil))")


proc ungap n {
    if {[string length $n] < 3} {
        return $n
    }
    return [string index $n 0][string index $n end]
}

proc gapful n {
    return [expr {0 == ($n % [ungap $n])}]
}

##      --> list of gapful numbers >= n
proc GFlist {count n} {
    set r {}
    while {[llength $r] < $count} {
        if {[gapful $n]} {
            lappend r $n
        }
        incr n
    }
    return $r
}

proc show {count n} {
    puts "The first $count gapful >= $n: [GFlist $count $n]"
}

show 30 100
show 15 1000000
show 10 1000000000


first-digit() {
  printf '%s\n' "${1:0:1}"
}

last-digit() {
  printf '%s\n' $(( $1 % 10 ))
}

bookend-number() {
  printf '%s%s\n' "$(first-digit "[email protected]")" "$(last-digit "[email protected]")"
}

is-gapful() {
  (( $1 >= 100 && $1 % $(bookend-number "$1") == 0 ))
}

gapfuls-in-range() {
  local gapfuls=()
  local -i i found
  for (( i=$1, found=0; found < $2; ++i )); do
    if is-gapful "$i"; then
      if (( found )); then
        printf ' ';
      fi
      printf '%s' "$i"
      (( found++ ))
    fi
  done
  printf '\n'
}

report-ranges() {
  local range
  local -i start size
  for range; do
    IFS=, read start size <<<"$range"
    printf 'The first %d gapful numbers >= %d:\n' "$size" "$start"
    gapfuls-in-range "$start" "$size"
    printf '\n'
  done
}

report-ranges 1,30 1000000,15 1000000000,10


Module Module1

    Function FirstNum(n As Integer) As Integer
        REM Divide by ten until the leading digit remains.
        While n >= 10
            n /= 10
        End While
        Return n
    End Function

    Function LastNum(n As Integer) As Integer
        REM Modulo gives you the last digit.
        Return n Mod 10
    End Function

    Sub FindGap(n As Integer, gaps As Integer)
        Dim count = 0
        While count < gaps
            Dim i = FirstNum(n) * 10 + LastNum(n)

            REM Modulo with our new integer and output the result.
            If n Mod i = 0 Then
                Console.Write("{0} ", n)
                count += 1
            End If

            n += 1
        End While
        Console.WriteLine()
        Console.WriteLine()
    End Sub

    Sub Main()
        Console.WriteLine("The first 30 gapful numbers are: ")
        FindGap(100, 30)

        Console.WriteLine("The first 15 gapful numbers > 1,000,000 are: ")
        FindGap(1000000, 15)

        Console.WriteLine("The first 10 gapful numbers > 1,000,000,000 are: ")
        FindGap(1000000000, 10)
    End Sub

End Module


fn commatize(n u64) string {
    mut s := n.str()
    le := s.len
    for i := le - 3; i >= 1; i -= 3 {
        s = '${s[0..i]},$s[i..]'
    }
    return s
}

fn main() {
    starts := [u64(1e2), u64(1e6), u64(1e7), u64(1e9), u64(7123)]
    counts := [30, 15, 15, 10, 25]
    for i in 0..starts.len {
        mut count := 0
        mut j := starts[i]
        mut pow := u64(100)
        for {
            if j < pow*10 {
                break
            }
            pow *= 10
        }
        println("First ${counts[i]} gapful numbers starting at ${commatize(starts[i])}:")
        for count < counts[i] {
            fl := (j/pow)*10 + (j % 10)
            if j%fl == 0 {
                print("$j ")
                count++
            }
            j++
            if j >= 10*pow {
                pow *= 10
            }
        }
        println("\n")
    }
}


import "/fmt" for Fmt

var starts = [1e2, 1e6, 1e7, 1e9, 7123]
var counts = [30, 15, 15, 10, 25]
for (i in 0...starts.count) {
    var count = 0
    var j = starts[i]
    var pow = 100
    while (true) {
        if (j < pow * 10) break
        pow = pow * 10
    }
    System.print("First %(counts[i]) gapful numbers starting at %(Fmt.dc(0, starts[i]))")
    while (count < counts[i]) {
        var fl = (j/pow).floor*10 + (j % 10)
        if (j%fl == 0) {
            System.write("%(j) ")
            count = count + 1
        }
        j = j + 1
        if (j >= 10*pow) pow = pow * 10
    }
    System.print("\n")
}


func isgapful(n:number):boolean{
	set s:string = tostring(n);
	set d = toint(`{s::at(0)}{s::at(?s-1)}`);
	send (n%d)==0
}

func findGapfulNumbers(start,amount){
	set gapful=[];
	set ind = start;
	while(true){
		if(isgapful(ind)){
			gapful::insert(ind);
		}
		ind++;
		if((?gapful)>=amount){
			stop;
		}
	}
	log(`First {amount} gapful ints at {start}: {gapful::join(", ")}`);
}

findGapfulNumbers(100,30);
findGapfulNumbers(1000000,15);
findGapfulNumbers(1000000000,15);


func Gapful(N0);        \Return 'true' if gapful number
int  N0, N, First, Last;
[N:= N0;
N:= N/10;
Last:= rem(0);
repeat  N:= N/10;
        First:= rem(0);
until   N = 0;
N:= First*10 + Last;
return rem(N0/N) = 0;
];

proc ShowGap(Start, Limit); \Display gapful numbers
int  Start, Limit, Count, N;
[Text(0, "First "); IntOut(0, Limit); Text(0, " gapful numbers starting from ");
IntOut(0, Start);  Text(0, ":^m^j");
Count:= 0;  N:= Start;
loop    [if Gapful(N) then
            [IntOut(0, N);  ChOut(0, ^ );
            Count:= Count+1;
            if Count >= Limit then quit;
            ];
        N:= N+1;
        ];
CrLf(0);
];

[ShowGap(100, 30);
ShowGap(1_000_000, 15);
ShowGap(1_000_000_000, 10);
]


sub is_gapful(n)
    m = n
	l = mod(n, 10)
    while (m >= 10)
        m = int(m / 10)
    wend
    return (m * 10) + l
end sub

sub muestra_gapful(n, gaps)
    inc = 0
    print "Primeros ", gaps, " numeros gapful >= ", n
    while inc < gaps
        if mod(n, is_gapful(n)) = 0 then
            print " " , n ,
            inc = inc + 1
        end if
        n = n + 1
    wend
    print chr$(10)
end sub

muestra_gapful(100, 30)
muestra_gapful(1000000, 15)
muestra_gapful(1000000000, 10)
muestra_gapful(7123,25)
end


fcn gapfulW(start){	//--> iterator
   [start..].tweak(
      fcn(n){ if(n % (10*n.toString()[0] + n%10)) Void.Skip else n })
}


function noargs return Integer;
function twoargs (a, b : Integer) return Integer;
--  varargs do not exist
function optionalargs (a, b : Integer := 0) return Integer;
--  all parameters are always named, only calling by name differs
procedure dostuff (a : Integer);


integer f0(void);               # No arguments
void f1(integer, real);         # Two arguments
real f2(...);                   # Varargs
void f3(integer, ...);          # Varargs

void f4(integer &, text &);     # Two arguments (integer and string), pass by reference
integer f5(integer, integer (*)(integer));
                                # Two arguments: integer and function returning integer and taking one integer argument
integer f6(integer a, real b);  # Parameters names are allowed
record f7(void);                # Function returning an associative array


#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #

# An explanation of any placement restrictions for prototype declarations #
PROC VOID no args; # Declare a function with no argument that returns an INTeger #
PROC (INT #a#,INT #b#)VOID two args; # Declare a function with two arguments that returns an INTeger #
MODE VARARGS = UNION(INT,REAL,COMPL);
PROC ([]VARARGS)VOID var args; # An empty parameter list can be used to declare a function that accepts varargs #
PROC (INT, []VARARGS)VOID at least one args; # One mandatory INTeger argument followed by varargs #

MODE OPTINT = UNION(VOID,INT), OPTSTRING=UNION(VOID,STRING); # a function that utilizes optional arguments #
PROC (OPTINT, OPTSTRING)VOID optional arguments;

# A prototype declaration for a function that utilizes named parameters #
MODE KWNAME = STRUCT(STRING name),
     KWSPECIES = STRUCT(STRING species),
     KWBREED = STRUCT(STRING breed),
     OWNER=STRUCT(STRING first name, middle name, last name);

# due to the "Yoneda ambiguity" simple arguments must have an unique operator defined #
OP NAME = (STRING name)KWNAME: (KWNAME opt; name OF opt := name; opt),
   SPECIES = (STRING species)KWSPECIES: (KWSPECIES opt; species OF opt := species; opt),
   BREED = (STRING breed)KWBREED: (KWBREED opt; breed OF opt := breed; opt);

PROC ([]UNION(KWNAME,KWSPECIES,KWBREED,OWNER) #options#)VOID print pet;

# subroutines, and fuctions are procedures, so have the same prototype declarations #

# An explanation and example of any special forms of prototyping not covered by the above:  #
COMMENT
  If a function has no arguments, eg f,
  then it is not requied to pass it a "vacuum()" to call it, eg "f()" not correct!
  Rather is can be called without the () vacuum. eg "f"
  A GOTO "label" is equivalent to "PROC VOID label".
END COMMENT

SKIP


#!/usr/bin/hopper

// Archivo Hopper
#include <hopper.h>

#context-free noargs         /* Declare a pseudo-function with no argument */
#synon noargs             no arguments
#context multiargs           /* Declare a pseudo-function with multi arguments */
#proto twoargs(_X_,_Y_)      /* Declare a pseudo-function with two arguments. #PROTO need arguments */

main:
   no arguments
   _two args(2,2)   // pseudo-function #proto need "_" sufix
   println
   {1,2,3,"hola mundo!","\n"}, multiargs
exit(0)

.locals

multiargs:
   _PARAMS_={},pushall(_PARAMS_)
   [1:3]get(_PARAMS_),stats(SUMMATORY),println
   {"Mensaje: "}[4:5]get(_PARAMS_),println
   clear(_PARAMS_)
back

twoargs(a,b)
   {a}mulby(b)
back

// This function is as useful a   s an ashtray on a motorcycle:
no args:
   {0}minus(0),kill
back

{0}return


int noargs(void); /* Declare a function with no argument that returns an integer */
int twoargs(int a,int b); /* Declare a function with two arguments that returns an integer */
int twoargs(int ,int); /* Parameter names are optional in a prototype definition */
int anyargs(); /* An empty parameter list can be used to declare a function that accepts varargs */
int atleastoneargs(int, ...); /* One mandatory integer argument followed by varargs */


using System;
abstract class Printer
{
    public abstract void Print();
}

class PrinterImpl : Printer
{
    public override void Print() {
        Console.WriteLine("Hello world!");
    }
}


int noargs(); // Declare a function with no arguments that returns an integer
int twoargs(int a,int b); // Declare a function with two arguments that returns an integer
int twoargs(int ,int); // Parameter names are optional in a prototype definition
int anyargs(...); // An ellipsis is used to declare a function that accepts varargs
int atleastoneargs(int, ...); // One mandatory integer argument followed by varargs
template<typename T> T declval(T); //A function template
template<typename ...T> tuple<T...> make_tuple(T...); //Function template using parameter pack (since c++11)


       *> A subprogram taking no arguments and returning nothing.
       PROGRAM-ID. no-args PROTOTYPE.
       END PROGRAM no-args.

       *> A subprogram taking two 8-digit numbers as arguments, and returning
       *> an 8-digit number.
       PROGRAM-ID. two-args PROTOTYPE.
       DATA DIVISION.
       LINKAGE SECTION.
       01  arg-1 PIC 9(8).
       01  arg-2 PIC 9(8).
       01  ret   PIC 9(8).
       PROCEDURE DIVISION USING arg-1, arg-2 RETURNING ret.
       END PROGRAM two-args.

       *> A subprogram taking two optional arguments which are 8-digit
       *> numbers (passed by reference (the default and compulsory for
       *> optional arguments)).
       PROGRAM-ID. optional-args PROTOTYPE.
       DATA DIVISION.
       LINKAGE SECTION.
       01  arg-1 PIC 9(8).
       01  arg-2 PIC 9(8).
       PROCEDURE DIVISION USING OPTIONAL arg-1, OPTIONAL arg-2.
       END PROGRAM optional-args.

       *> Standard COBOL does not support varargs or named parameters.

       *> A function from another language, taking a 32-bit integer by
       *> value and returning a 32-bit integer (in Visual COBOL).
       PROGRAM-ID. foreign-func PROTOTYPE.
       OPTIONS.
           ENTRY-CONVENTION some-langauge.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  arg PIC S9(9) USAGE COMP-5.
       01  ret PIC S9(9) USAGE COMP-5.
       PROCEDURE DIVISION USING arg RETURNING ret.
       END PROGRAM foreign-func.


(declaim (inline no-args))
(declaim (inline one-arg))
(declaim (inline two-args))
(declaim (inline optional-args))

(defun no-args ()
  (format nil "no arguments!"))

(defun one-arg (x)
  ; inserts the value of x into a string
  (format nil "~a" x))

(defun two-args (x y)
  ; same as function `one-arg', but with two arguments
  (format nil "~a ~a" x y))

(defun optional-args (x &optional y) ; optional args are denoted with &optional beforehand
  ; same as function `two-args', but if y is not given it just prints NIL
  (format nil "~a ~a~%" x y))

(no-args) ;=> "no arguments!"

(one-arg 1) ;=> "1"

(two-args 1 "example") ;=> "1 example"

(optional-args 1.0) ;=> "1.0 NIL"

(optional-args 1.0 "example") ;=> "1.0 example"


/// Declare a function with no arguments that returns an integer.
int noArgs();

/// Declare a function with no arguments that returns an integer.
int twoArgs(int a, int b);

/// Parameter names are optional in a prototype definition.
int twoArgs2(int, int);

/// An ellipsis can be used to declare a function that accepts
/// C-style varargs.
int anyArgs(...);

/// One mandatory integer argument followed by C-style varargs.
int atLeastOneArg(int, ...);

/// Declare a function that accepts any number of integers.
void anyInts(int[] a...);

/// Declare a function that accepts D-style varargs.
void anyArgs2(TArgs...)(TArgs args);

/// Declare a function that accepts two or more D-style varargs.
void anyArgs3(TArgs...)(TArgs args) if (TArgs.length > 2);

/// Currently D doesn't support named arguments.

/// One implementation.
int twoArgs(int a, int b) {
    return a + b;
}

interface SomeInterface {
    void foo();
    void foo(int, int);

    // Varargs
    void foo(...); // C-style.
    void foo(int[] a...);
    void bar(T...)(T args); // D-style.

    // Optional arguments are only supported if a default is provided,
    // the default arg(s) has/have to be at the end of the args list.
    void foo(int a, int b = 10);
}

void main() {}


program Function_prototype;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  TIntArray = TArray<Integer>;

  TIntArrayHelper = record helper for TIntArray
    const
      DEFAULT_VALUE = -1;
    // A prototype declaration for a function that does not require arguments
    function ToString(): string;

    // A prototype declaration for a function that requires two arguments
    procedure Insert(Index: Integer; value: Integer);

    // A prototype declaration for a function that utilizes varargs
    // varargs is not available, but a equivalent is array of const
    procedure From(Args: array of const);

    //A prototype declaration for a function that utilizes optional arguments
    procedure Delete(Index: Integer; Count: Integer = 1);

    //A prototype declaration for a function that utilizes named parameters
    // Named parameters is not supported in Delphi

    //Example of prototype declarations for subroutines or procedures
    //(if these differ from functions)
    procedure Sqr;    //Procedure return nothing
    function Averange: double; //Function return a value
  end;

{ TIntHelper }

function TIntArrayHelper.Averange: double;
begin
  Result := 0;
  for var e in self do
    Result := Result + e;
  Result := Result / Length(self);
end;

procedure TIntArrayHelper.Delete(Index, Count: Integer);
begin
  System.Delete(self, Index, Count);
end;

procedure TIntArrayHelper.From(Args: array of const);
var
  I, Count: Integer;
begin
  Count := Length(Args);
  SetLength(self, Count);

  if Count = 0 then
    exit;
  for I := 0 to High(Args) do
    with Args[I] do
      case VType of
        vtInteger:
          self[I] := VInteger;
        vtBoolean:
          self[I] := ord(VBoolean);
        vtChar, vtWideChar:
          self[I] := StrToIntDef(string(VChar), DEFAULT_VALUE);
        vtExtended:
          self[I] := Round(VExtended^);
        vtString:
          self[I] := StrToIntDef(VString^, DEFAULT_VALUE);
        vtPChar:
          self[I] := StrToIntDef(VPChar, DEFAULT_VALUE);
        vtObject:
          self[I] := cardinal(VObject);
        vtClass:
          self[I] := cardinal(VClass);
        vtAnsiString:
          self[I] := StrToIntDef(string(VAnsiString), DEFAULT_VALUE);
        vtCurrency:
          self[I] := Round(VCurrency^);
        vtVariant:
          self[I] := Integer(VVariant^);
        vtInt64:
          self[I] := Integer(VInt64^);
        vtUnicodeString:
          self[I] := StrToIntDef(string(VUnicodeString), DEFAULT_VALUE);
      end;
end;

procedure TIntArrayHelper.Insert(Index, value: Integer);
begin
  system.Insert([value], self, Index);
end;

procedure TIntArrayHelper.Sqr;
begin
  for var I := 0 to High(self) do
    Self[I] := Self[I] * Self[I];
end;

function TIntArrayHelper.ToString: string;
begin
  Result := '[';
  for var e in self do
    Result := Result + e.ToString + ', ';
  Result := Result + ']';
end;

begin
  var val: TArray<Integer>;
  val.From([1, '2', PI]);
  val.Insert(0, -1); // insert -1 at position 0
  writeln('  Array:    ', val.ToString, ' ');
  writeln('  Averange: ', val.Averange: 3: 2);
  val.Sqr;
  writeln('  Sqr:      ', val.ToString);
  Readln;

end.


// A prototype declaration for a function that does not require arguments

begin_funct(foo);                           // function as a 'method' with no arguments, no return type
end_funct(foo);

// or

with_funct(foo);                            // function as a 'method' with no arguments, no return type

// A prototype declaration for a function that requires two arguments

begin_funct(goo)_arg({string}, str1, str2); // two arguments, no return type
end_funct[];                                // derived name of function using [], like 'this'

with_funct(goo)_arg({str}, str1, str2);     // two arguments, no return type
with_funct(hoo)_param({integer}, i, j);     // 'param' posit can be used instead of 'arg'

// A prototype declaration for a function that utilizes varargs

begin_funct(voo)_arg({int}, [vararg], v);   // variable number of arguments, no return type, 'int' can be used instead of 'integer'
end_funct[];

begin_funct({int}, voo)_arg({int}, ..., v);   // variable number of arguments, with return type
    add_var({int}, sum)_v(0);
    forall_var(v)_calc([sum]+=[v]);
    [voo]_ret([sum]);
end_funct[];

// A prototype declaration for a function that utilizes optional arguments

begin_funct({int}, ooo)_arg(o)_value(1);   // optional argument with default value and return type integer
    with_funct(ooo)_return([o]);           // Can be shortened to [ooo]_ret([0]);
end_funct[];

begin_funct({int}, oxo)_arg(o,u,v)_opt(u)_value(1); // optional argument of second argument with default value and return type integer
    [ooo]_ret(1);                               // the execution has to name arguments or missing in comma-separated list of arguments
end_funct[];

// A prototype declaration for a function that utilizes named parameters

begin_funct({int}, poo)_param({int}, a, b, c); // to enforce named parameters '_param' posit can be used.
    [poo]_ret([a]+[b]+[c]);
end_funct[];

exec_funct(poo)_param(a)_value(1)_param(b, c)_value(2, 3) ? me_msg()_funct(poo); ;

begin_funct({int}, poo)_arg({int}, a, b, c); // named parameters can still be used with '_arg' posit.
    [poo]_ret([a]+[b]+[c]);
end_funct[];

me_msg()_funct(poo)_arg(a)_value(1)_value(2, 3); // Callee has to figure out unnamed arguments by extraction
                                                 // 'exec_' verb is implied before '_funct' action

// Example of prototype declarations for subroutines or procedures (if these differ from functions)

begin_instruct(foo);                        // instructions are 'methods', no arguments, no return type
end_instruct[foo];                          // explicit end of itself

// or

with_instruct(foo);                         // instructions are 'methods', no arguments, no return type

begin_funct(yoo)_arg(robotMoniker)_param(b);        // A '_funct' can be used as a subroutine when missing the '{}' return datatype
                                                    // a mix of '_arg' and '_param' posits can be used
    with_robot[robotMoniker]_var(sq)_calc([b]^2);   // create a variable called 'sq' on robot 'robotMoniker'
end_funct(yoo);

begin_instruct(woo)_arg(robotType)_param(b);           // An '_instuct' is only used for subroutines and return datatypes are not accepted
    with_robot()_type[robotType]_var(sq)_calc([b]^2);  // create a variable called 'sq' on all robots of type 'robotType'
end_funct(woo);

// An explanation and example of any special forms of prototyping not covered by the above

begin_funct({double}, voo)_arg({int}, [numArgs], v);   // variable-defined number of arguments, with return type
    add_var({int}, sum)_v(0);
    add_var({double}, average)_v(0);
    for_var(v)_until[numArgs]_calc([sum]+=[v]);        // the number of arguments [numArgs] does not have to be number of arguments of v
    [voo]_ret([sum]/[numArgs]);
end_funct[];

begin_funct({int}, [numArgsOut], voo)_arg({int}, [numArgsIn], v);   // variable-defined number of arguments, with variable-defined number of return types
    add_var({int}, sum)_v(0);
    add_var({double}, average)_v(0);
    for_var(v)_until[numArgsOut]_calc([sum]+=[v]);
    [voo]_ret([sum]/[numArgsOut]);
end_funct[];


// A function taking and returning nothing (unit).
val noArgs : unit -> unit
// A function taking two integers, and returning an integer.
val twoArgs : int -> int -> int
// A function taking a ParamPack array of ints, and returning an int. The ParamPack
// attribute is not included in the signature.
val varArgs : int [] -> int
// A function taking an int and a ParamPack array of ints, and returning an
// object of the same type.
val atLeastOnArg : int -> int [] -> int
// A function taking an int Option, and returning an int.
val optionalArg : Option<int> -> int

// Named arguments and the other form of optional arguments are only available on
// methods.
type methodClass =
  class
    // A method taking an int named x, and returning an int.
    member NamedArg : x:int -> int
    // A method taking two optional ints in a tuple, and returning an int. The
    //optional arguments must be tupled.
    member OptionalArgs : ?x:int * ?y:int -> int
  end


' FB 1.05.0 Win64

' The position regarding prototypes is broadly similar to that of the C language in that functions,
' sub-routines or operators (unless they have already been fully defined) must be declared before they can be used.
' This is usually done near the top of a file or in a separate header file which is then 'included'.

' Parameter names are optional in declarations. When calling functions, using parameter names
' (as opposed to identifying arguments by position) is not supported.

Type MyType ' needed for operator declaration
  i As Integer
End Type

Declare Function noArgs() As Integer  ' function with no argument that returns an integer
Declare Function twoArgs(As Integer, As Integer) As Integer ' function with two arguments that returns an integer
Declare Function atLeastOneArg CDecl(As Integer, ...) As Integer ' one mandatory integer argument followed by varargs
Declare Function optionalArg(As Integer = 0) As Integer ' function with a (single) optional argument with default value
Declare Sub noArgs2() ' sub-routine with no argument
Declare Operator + (As MyType, As MyType) As MyType ' operator declaration (no hidden 'This' parameter for MyType)

' FreeBASIC also supports object-oriented programming and here all constructors, destructors,
' methods (function or sub), properties and operators (having a hidden 'This' parameter) must be
' declared within a user defined type and then defined afterwards.

Type MyType2
  Public:
    Declare Constructor(As Integer)
    Declare Destructor()
    Declare Sub MySub()
    Declare Function MyFunction(As Integer) As Integer
    Declare Property MyProperty As Integer
    Declare Operator Cast() As String
  Private:
    i As Integer
End Type


func a()          // function with no arguments
func b(x, y int)  // function with two arguments
func c(...int)    // varargs are called "variadic parameters" in Go.


   NB. j assumes an unknown name f is a verb of infinite rank
   NB. f has infinite ranks
   f b. 0
_ _ _

   NB. The verb g makes a table.
   g=: f/~

   NB. * has rank 0
   f=: *

   NB. indeed, make a multiplication table
   f/~ i.5
0 0 0  0  0
0 1 2  3  4
0 2 4  6  8
0 3 6  9 12
0 4 8 12 16

   NB. g was defined as if f had infinite rank.
   g i.5
0 1 4 9 16

   NB. f is known to have rank 0.
   g=: f/~

   NB. Now we reproduce the table
   g i.5
0 0 0  0  0
0 1 2  3  4
0 2 4  6  8
0 3 6  9 12
0 4 8 12 16

   NB. change f to another rank 0 verb
   f=: +

   NB. and construct an addition table
   g i.5
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8

   NB. f is multiplication at infinite rank
   f=: *"_

   NB. g, however, has rank 0
   g i.5
0 0 0  0  0
0 1 2  3  4
0 2 4  6  8
0 3 6  9 12
0 4 8 12 16


// A prototype declaration for a function that does not require arguments
function List() {}

List.prototype.push = function() {
  return [].push.apply(this, arguments);
};

List.prototype.pop = function() {
  return [].pop.call(this);
};

var l = new List();
l.push(5);
l.length; // 1
l[0]; 5
l.pop(); // 5
l.length; // 0

// A prototype declaration for a function that utilizes varargs
function List() {
  this.push.apply(this, arguments);
}

List.prototype.push = function() {
  return [].push.apply(this, arguments);
};

List.prototype.pop = function() {
  return [].pop.call(this);
};

var l = new List(5, 10, 15);
l.length; // 3
l[0]; 5
l.pop(); // 15
l.length; // 2


julia > function mycompare(a, b)::Cint
      (a < b) ? -1 : ((a > b) ? +1 : 0)
  end
mycompare (generic function with 1 method)


// version 1.0.6

interface MyInterface {
    fun foo()                     // no arguments, no return type
    fun goo(i: Int, j: Int)       // two arguments, no return type
    fun voo(vararg v: Int)        // variable number of arguments, no return type
    fun ooo(o: Int = 1): Int      // optional argument with default value and return type Int
    fun roo(): Int                // no arguments with return type Int
    val poo: Int                // read only property of type Int
}

abstract class MyAbstractClass {
    abstract fun afoo()           // abstract member function, no arguments or return type
    abstract var apoo: Int        // abstract read/write member property of type Int
}

class Derived : MyAbstractClass(), MyInterface {
    override fun afoo() {}
    override var apoo: Int = 0

    override fun foo() {}
    override fun goo(i: Int, j: Int) {}
    override fun voo(vararg v: Int) {}
    override fun ooo(o: Int): Int = o  // can't specify default argument again here but same as in interface
    override fun roo(): Int = 2
    override val poo: Int = 3
}

fun main(args: Array<String>) {
    val d = Derived()
    println(d.apoo)
    println(d.ooo())  // default argument of 1 inferred
    println(d.roo())
    println(d.poo)
}


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

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

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

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


function noargs(): int = ? ;;
function twoargs(x:int, y:int): int = ? ;;

/* underscore means ignore and is not bound to lexical scope */
function twoargs(_:bool, _:bool): int = ? ;;

function anyargs(xs: ...): int = ? ;;
function plusargs(x:int, xs: ...): int = ? ;;


Module Check {
      Module MyBeta (a) {
            Print "MyBeta", a/2
      }
      Module TestMe {
            Module Beta (x) {
                  Print "TestMeBeta", x
            }
            Beta 100
      }
      TestMe ; Beta as MyBeta
}
Check


# Procedure declarations. All are named
proc noargs(): int
proc twoargs(a, b: int): int
proc anyargs(x: varargs[int]): int
proc optargs(a, b: int = 10): int

# Usage
discard noargs()
discard twoargs(1,2)
discard anyargs(1,2,3,4,5,6,7,8)
discard optargs(5)

# Procedure definitions
proc noargs(): int = echo "noargs"
proc twoargs(a, b: int): int = echo "twoargs"
proc anyargs(x: varargs[int]): int = echo "anyargs"
proc optargs(a: int, b = 10): int = echo "optargs"


(* Usually prototype declarations are put in an interface file,
   a file with .mli filename extension *)

(* A prototype declaration for a function that does not require arguments *)
val no_arg : unit -> unit

(* A prototype declaration for a function that requires two arguments *)
val two_args : int -> int -> unit

(* A prototype declaration for a function that utilizes optional arguments *)
val opt_arg : ?param:int -> unit -> unit
(* in this case we add a unit parameter in order to omit the argument,
   because ocaml supports partial application *)

(* A prototype declaration for a function that utilizes named parameters *)
val named_arg : param1:int -> param2:int -> unit

(* An explanation and example of any special forms of prototyping not covered by the above *)

(* A prototype declaration for a function that requires a function argument *)
val fun_arg : (int -> int) -> unit

(* A prototype declaration for a function with polymorphic argument *)
val poly_arg : 'a -> unit


'DECLARE FUNCTION' ABBREVIATED TO '!'

!  f()                     ' a procedure with no params
!  f(int a)                ' with 1 int param
!  f(int *a)               ' with 1 int pointer param
!  f(int a, int b, inc c)  ' with 3 int params
!  f(int a,b,c)            ' compaction with 3 int params
!  f(string s, int a,b)    ' with 1 string and 2 int params
!  f() as string           ' function returning a string
!  f(string s) as string   ' with 1 string param
! *f(string s) as string   ' as a function pointer: @f=address
!  f(string s, optional i) ' with opptional param
!  f(string s = "Hello")   ' optional param with default value
!  f(int n, ...)           ' 1 specific param and varargs
!  f(...)                  ' any params or none

'TRADITIONAL BASIC DECLARATIONS
declare sub f( s as string, i as long, j as long)  ' byref by default
declare function f( byref s as string, byval i as long, byval j as long) as string

'C-STYLE DECLARATIONS
void f(string *s, long i, long j)
string f(string *s, long i, long j)

'BLOCK DIRECTIVES FOR FUNCTION PROTOTYPES:

extern                      ' shareable stdcall functions

extern  lib "xyz.dll"       ' for accessing functions in xyz Dynamic Link Library

extern export               ' functions to be exported if this is a DLL

extern virtual              ' for accssing interfaces and other virtual classes

end extern                  ' revert to internal function mode


sub noargs(); # Declare a function with no arguments
sub twoargs($$); # Declare a function with two scalar arguments. The two sigils act as argument type placeholders
sub noargs :prototype(); # Using the :attribute syntax instead
sub twoargs :prototype($$);


forward function noargs() -- Declare a function with no arguments
forward procedure twoargs(integer a, integer b) -- Declare a procedure with two arguments
forward procedure twoargs(integer, integer /*b*/) -- Parameter names are optional in forward (and actual) definitions
forward function anyargs(sequence s) -- varargs are [best/often] handled as a (single) sequence in Phix
forward function atleastonearg(integer a, integer b=1, ...); -- Default makes args optional (== actual defn)


declare s1 entry;
declare s2 entry (fixed);
declare s3 entry (fixed, float);

declare f1 entry returns (fixed);
declare f2 entry (float) returns (float);
declare f3 entry (character(*), character(*)) returns (character (20));


;Forward procedure declare defined with no arguments and that returns a string
Declare.s booTwo()
;Forward procedure declare defined with two arguments and that returns a float
Declare.f moo(x.f, y.f)
;Forward procedure declare with two arguments and an optional argument and that returns a float
Declare.f cmoo(x.f, y.f, m.f = 0)

;*** The following three procedures are defined before their first use.
;Procedure defined with no arguments and that returns a string
Procedure.s boo(): ProcedureReturn "boo": EndProcedure
;Procedure defined with two arguments and that returns an float
Procedure.f aoo(x.f, y.f): ProcedureReturn x + y: EndProcedure
;Procedure defined with two arguments and an optional argument and that returns a float
Procedure.f caoo(x.f, y.f, m.f = 1): ProcedureReturn (x + y) * m: EndProcedure

;ProtoType defined for any function with no arguments and that returns a string
Prototype.s showString()
;Prototype defined for any function with two float arguments and that returns a float
Prototype.f doMath(x.f, y.f)
;ProtoType defined for any function with two float arguments and an optional float argument and that returns a float
Prototype.f doMathWithOpt(x.f, y.f, m.f = 0)

Define a.f = 12, b.f = 5, c.f = 9
Define proc_1.showString, proc_2.doMath, proc_3.doMathWithOpt ;using defined ProtoTypes
If OpenConsole("ProtoTypes and Forward Declarations")

  PrintN("Forward Declared procedures:")
  PrintN(boo())
  PrintN(StrF(a, 2) + " * " + StrF(b, 2) + " = " + StrF(moo(a, b), 2))
  PrintN(StrF(a, 2) + " * " + StrF(b, 2) + " + " + StrF(c, 2) + " = " + StrF(cmoo(a, b, c), 2))
  PrintN(StrF(a, 2) + " * " + StrF(b, 2) + " = " + StrF(cmoo(a, b), 2))

  ;set pointers to second set of functions
  proc_1 = @boo()
  proc_2 = @aoo()
  proc_3 = @caoo()

  PrintN("ProtoTyped procedures (set 1):")
  PrintN(proc_1())
  PrintN(StrF(a, 2) + " ? " + StrF(b, 2) + " = " + StrF(proc_2(a, b), 2))
  PrintN(StrF(a, 2) + " ? " + StrF(b, 2) + " ? " + StrF(c, 2) + " = " + StrF(proc_3(a, b, c), 2))
  PrintN(StrF(a, 2) + " ? " + StrF(b, 2) + " = " + StrF(proc_3(a, b), 2))

  ;set pointers to second set of functions
  proc_1 = @booTwo()
  proc_2 = @moo()
  proc_3 = @cmoo()

  PrintN("ProtoTyped procedures (set 2):")
  PrintN(proc_1())
  PrintN(StrF(a, 2) + " ? " + StrF(b, 2) + " = " + StrF(proc_2(a, b), 2))
  PrintN(StrF(a, 2) + " ? " + StrF(b, 2) + " ? " + StrF(c, 2) + " = " + StrF(proc_3(a, b, c), 2))
  PrintN(StrF(a, 2) + " ? " + StrF(b, 2) + " = " + StrF(proc_3(a, b), 2))

  Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
  CloseConsole()
EndIf

;*** If the forward Declaration above are not used then the following Procedure
;definitions each have to be placed before the call to the respective procedure.

;Procedure defined with no arguments and that returns a string
Procedure.s booTwo()
  ProcedureReturn "booTwo"
EndProcedure

;Procedure defined with two arguments and that returns an float
Procedure.f moo(x.f, y.f)
  ProcedureReturn x * y
EndProcedure

;Procedure defined with two arguments and an optional argument and that returns an float
Procedure.f cmoo(x.f, y.f, m.f = 0)
  ProcedureReturn (x * y) + m
EndProcedure


                         forward is fibonacci ( n --> n )

  [ dup  2 < if done
    dup  1 - fibonacci
    swap 2 - fibonacci + ] resolves fibonacci ( n --> n )


#lang racket

(define (no-arg) (void))

(define (two-args a b) (void)) ;arguments are always named

(define (varargs . args) (void)) ;the extra arguments are stored in a list

(define (varargs2 a . args) (void)) ;one obligatory argument and the rest are contained in the list

(define (optional-arg (a 5)) (void)) ;a defaults to 5


          define('multiply(a,b)') :(mul_end)
multiply  multiply = a * b        :(return)
mul_end

* Test
          output = multiply(10.1,12.2)
          output = multiply(10,12)
end


var factorial // forward declaration

factorial = Fn.new { |n| (n <= 1) ? 1 : factorial.call(n-1) * n }

System.print(factorial.call(5))


fcn{"Hello World"}   // no expected args
fcn(){"Hello World"} // ditto

fcn{vm.arglist}(1,2)   // ask the VM for the passed in args -->L(1,2)
fcn f(a,b){a+b}  // fcn(1,2,3) works just fine
fcn f(args){}(1,2,3)  //args = 1
fcn(args){vm.arglist.sum()}(1,2,3) //-->6

fcn(a=1,b=2){vm.arglist}()  //-->L(1,2)
fcn(a=1,b=2){vm.arglist}(5) //-->L(5,2)
fcn(a=1,b){vm.arglist}()    //-->L(1), error if you try to use b
fcn(a,b=2){vm.arglist}(5)   //-->L(5,2)
fcn(a,b=2,c){vm.arglist}(1) //-->L(1,2)

fcn(){vm.nthArg(1)}(5,6)           //-->6
fcn{vm.numArgs}(1,2,3,4,5,6,7,8,9) //-->9
fcn{vm.argsMatch(...)}   // a somewhat feeble attempt arg pattern matching based on type (vs value)

   // you can do list assignment in the prototype:
fcn(a,[(b,c)],d){vm.arglist}(1,L(2,3,4),5) //-->L(1,L(2,3,4),5)
fcn(a,[(b,c)],d){"%s,%s,%s,%s".fmt(a,b,c,d)}(1,L(2,3,4),5) //-->1,2,3,5

   // no type enforcement but you can give a hint to the compiler
fcn([Int]n){n.sin()} //--> syntax error as Ints don't do sin


(in-package "ACL2")

(set-state-ok t)

(defun read-all-objects (limit channel state)
   (mv-let (eof obj state)
           (read-object channel state)
      (if (or eof (zp limit))
          (mv nil state)
          (mv-let (so-far state)
                  (read-all-objects (- limit 1) channel state)
             (mv (cons obj so-far) state)))))

(defun list-starters (xs)
   (cond ((endp xs) nil)
         ((consp (first xs))
          (append (if (symbolp (first (first xs)))
                      (list (first (first xs)))
                      nil)
                  (list-starters (rest (first xs)))
                  (list-starters (rest xs))))
         (t (list-starters (rest xs)))))

(defun invoked-functions (filename state)
   (mv-let (channel state)
           (open-input-channel filename :object state)
      (mv-let (code state)
              (read-all-objects 1000 channel state)
         (mv (list-starters code) state))))

(defun increment-for (key alist)
   (cond ((endp alist) (list (cons key 1)))
         ((equal key (car (first alist)))
          (cons (cons key (1+ (cdr (first alist))))
                (rest alist)))
         (t (cons (first alist)
                  (increment-for key (rest alist))))))

(defun symbol-freq-table (symbols)
   (if (endp symbols)
       nil
       (increment-for (first symbols)
                      (symbol-freq-table (rest symbols)))))

(defun insert-freq-table (pair alist)
   (cond ((endp alist)
          (list pair))
         ((> (cdr pair) (cdr (first alist)))
          (cons pair alist))
         (t (cons (first alist)
                  (insert-freq-table pair (rest alist))))))

(defun isort-freq-table (alist)
   (if (endp alist)
       nil
       (insert-freq-table (first alist)
                          (isort-freq-table (rest alist)))))

(defun main (state)
   (mv-let (fns state)
           (invoked-functions "function-freq.lisp" state)
      (mv (take 10 (isort-freq-table
                    (symbol-freq-table fns))) state)))


source: to :block read arg\0
frequencies: #[]

inspectBlock: function [blk][
    loop blk 'item [
        case []
            when? [word? item][
                sItem: to :string item
                if set? sItem ->
                    if function? var sItem [
                        if? key? frequencies sItem ->
                            set frequencies sItem (get frequencies sItem)+1
                        else ->
                            set frequencies sItem 1
                    ]
            ]

            when? [or? block? item
                       inline? item] ->
                inspectBlock item

            else []
    ]
]

inspectBlock source

inspect frequencies


# syntax: GAWK -f FUNCTION_FREQUENCY.AWK filename(s).AWK
#
# sorting:
#   PROCINFO["sorted_in"] is used by GAWK
#   SORTTYPE is used by Thompson Automation's TAWK
#
BEGIN {
# create array of keywords to be ignored by lexer
    asplit("BEGIN:END:atan2:break:close:continue:cos:delete:" \
           "do:else:exit:exp:for:getline:gsub:if:in:index:int:"  \
           "length:log:match:next:print:printf:rand:return:sin:" \
           "split:sprintf:sqrt:srand:strftime:sub:substr:system:tolower:toupper:while",
           keywords,":")
# build the symbol-state table
    split("00:00:00:00:00:00:00:00:00:00:" \
          "20:10:10:12:12:11:07:00:00:00:" \
          "08:08:08:08:08:33:08:00:00:00:" \
          "08:44:08:36:08:08:08:00:00:00:" \
          "08:44:45:42:42:41:08",machine,":")
# parse the input
    state = 1
    for (;;) {
      symb = lex() # get next symbol
      nextstate = substr(machine[state symb],1,1)
      act = substr(machine[state symb],2,1)
      # perform required action
      if (act == "0") { # do nothing
      }
      else if (act == "1") { # found a function call
        if (!(inarray(tok,names))) {
          names[++nnames] = tok
        }
        ++xnames[tok]
      }
      else if (act == "2") { # found a variable or array
        if (tok in Local) {
          tok = tok "(" funcname ")"
          if (!(inarray(tok,names))) {
            names[++nnames] = tok
          }
          ++xnames[tok]
        }
        else {
          tok = tok "()"
          if (!(inarray(tok,names))) {
            names[++nnames] = tok
          }
          ++xnames[tok]
        }
      }
      else if (act == "3") { # found a function definition
        funcname = tok
      }
      else if (act == "4") { # found a left brace
        braces++
      }
      else if (act == "5") { # found a right brace
        braces--
        if (braces == 0) {
          delete Local
          funcname = ""
          nextstate = 1
        }
      }
      else if (act == "6") { # found a local variable declaration
        Local[tok] = 1
      }
      else if (act == "7") { # found end of file
        break
      }
      else if (act == "8") { # found an error
        printf("error: FILENAME=%s, FNR=%d\n",FILENAME,FNR)
        exit(1)
      }
      state = nextstate # finished with current token
    }
# format function names
    for (i=1; i<=nnames; i++) {
      if (index(names[i],"(") == 0) {
        tmp_arr[xnames[names[i]]][names[i]] = ""
      }
    }
# print function names
    PROCINFO["sorted_in"] = "@ind_num_desc" ; SORTTYPE = 9
    for (i in tmp_arr) {
      PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
      for (j in tmp_arr[i]) {
        if (++shown <= 10) {
          printf("%d %s\n",i,j)
        }
      }
    }
    exit(0)
}
function asplit(str,arr,fs,  i,n,temp_asplit) {
    n = split(str,temp_asplit,fs)
    for (i=1; i<=n; i++) {
      arr[temp_asplit[i]]++
    }
}
function inarray(val,arr,  j) {
    for (j in arr) {
      if (arr[j] == val) {
        return(j)
      }
    }
    return("")
}
function lex() {
    for (;;) {
      if (tok == "(eof)") {
        return(7)
      }
      while (length(line) == 0) {
        if (getline line == 0) {
          tok = "(eof)"
          return(7)
        }
      }
      sub(/^[ \t]+/,"",line)           # remove white space,
      sub(/^"([^"]|\\")*"/,"",line)    # quoted strings,
      sub(/^\/([^\/]|\\\/)+\//,"",line) # regular expressions,
      sub(/^#.*/,"",line)              # and comments
      if (line ~ /^function /) {
        tok = "function"
        line = substr(line,10)
        return(1)
      }
      else if (line ~ /^{/) {
        tok = "{"
        line = substr(line,2)
        return(2)
      }
      else if (line ~ /^}/) {
        tok = "}"
        line = substr(line,2)
        return(3)
      }
      else if (match(line,/^[A-Za-z_][A-Za-z_0-9]*\[/)) {
        tok = substr(line,1,RLENGTH-1)
        line = substr(line,RLENGTH+1)
        return(5)
      }
      else if (match(line,/^[A-Za-z_][A-Za-z_0-9]*\(/)) {
        tok = substr(line,1,RLENGTH-1)
        line = substr(line,RLENGTH+1)
        if (!(tok in keywords)) { return(6) }
      }
      else if (match(line,/^[A-Za-z_][A-Za-z_0-9]*/)) {
        tok = substr(line,1,RLENGTH)
        line = substr(line,RLENGTH+1)
        if (!(tok in keywords)) { return(4) }
      }
      else {
        match(line,/^[^A-Za-z_{}]/)
        tok = substr(line,1,RLENGTH)
        line = substr(line,RLENGTH+1)
      }
    }
}


package main

import "fmt"

type FCNode struct {
    name     string
    weight   int
    coverage float64
    children []*FCNode
    parent   *FCNode
}

func newFCN(name string, weight int, coverage float64) *FCNode {
    return &FCNode{name, weight, coverage, nil, nil}
}

func (n *FCNode) addChildren(nodes []*FCNode) {
    for _, node := range nodes {
        node.parent = n
        n.children = append(n.children, node)
    }
    n.updateCoverage()
}

func (n *FCNode) setCoverage(value float64) {
    if n.coverage != value {
        n.coverage = value
        // update any parent's coverage
        if n.parent != nil {
            n.parent.updateCoverage()
        }
    }
}

func (n *FCNode) updateCoverage() {
    v1 := 0.0
    v2 := 0
    for _, node := range n.children {
        v1 += float64(node.weight) * node.coverage
        v2 += node.weight
    }
    n.setCoverage(v1 / float64(v2))
}

func (n *FCNode) show(level int) {
    indent := level * 4
    nl := len(n.name) + indent
    fmt.Printf("%*s%*s  %3d   | %8.6f |\n", nl, n.name, 32-nl, "|", n.weight, n.coverage)
    if len(n.children) == 0 {
        return
    }
    for _, child := range n.children {
        child.show(level + 1)
    }
}

var houses = []*FCNode{
    newFCN("house1", 40, 0),
    newFCN("house2", 60, 0),
}

var house1 = []*FCNode{
    newFCN("bedrooms", 1, 0.25),
    newFCN("bathrooms", 1, 0),
    newFCN("attic", 1, 0.75),
    newFCN("kitchen", 1, 0.1),
    newFCN("living_rooms", 1, 0),
    newFCN("basement", 1, 0),
    newFCN("garage", 1, 0),
    newFCN("garden", 1, 0.8),
}

var house2 = []*FCNode{
    newFCN("upstairs", 1, 0),
    newFCN("groundfloor", 1, 0),
    newFCN("basement", 1, 0),
}

var h1Bathrooms = []*FCNode{
    newFCN("bathroom1", 1, 0.5),
    newFCN("bathroom2", 1, 0),
    newFCN("outside_lavatory", 1, 1),
}

var h1LivingRooms = []*FCNode{
    newFCN("lounge", 1, 0),
    newFCN("dining_room", 1, 0),
    newFCN("conservatory", 1, 0),
    newFCN("playroom", 1, 1),
}

var h2Upstairs = []*FCNode{
    newFCN("bedrooms", 1, 0),
    newFCN("bathroom", 1, 0),
    newFCN("toilet", 1, 0),
    newFCN("attics", 1, 0.6),
}

var h2Groundfloor = []*FCNode{
    newFCN("kitchen", 1, 0),
    newFCN("living_rooms", 1, 0),
    newFCN("wet_room_&_toilet", 1, 0),
    newFCN("garage", 1, 0),
    newFCN("garden", 1, 0.9),
    newFCN("hot_tub_suite", 1, 1),
}

var h2Basement = []*FCNode{
    newFCN("cellars", 1, 1),
    newFCN("wine_cellar", 1, 1),
    newFCN("cinema", 1, 0.75),
}

var h2UpstairsBedrooms = []*FCNode{
    newFCN("suite_1", 1, 0),
    newFCN("suite_2", 1, 0),
    newFCN("bedroom_3", 1, 0),
    newFCN("bedroom_4", 1, 0),
}

var h2GroundfloorLivingRooms = []*FCNode{
    newFCN("lounge", 1, 0),
    newFCN("dining_room", 1, 0),
    newFCN("conservatory", 1, 0),
    newFCN("playroom", 1, 0),
}

func main() {
    cleaning := newFCN("cleaning", 1, 0)

    house1[1].addChildren(h1Bathrooms)
    house1[4].addChildren(h1LivingRooms)
    houses[0].addChildren(house1)

    h2Upstairs[0].addChildren(h2UpstairsBedrooms)
    house2[0].addChildren(h2Upstairs)
    h2Groundfloor[1].addChildren(h2GroundfloorLivingRooms)
    house2[1].addChildren(h2Groundfloor)
    house2[2].addChildren(h2Basement)
    houses[1].addChildren(house2)

    cleaning.addChildren(houses)
    topCoverage := cleaning.coverage
    fmt.Printf("TOP COVERAGE = %8.6f\n\n", topCoverage)
    fmt.Println("NAME HIERARCHY                 | WEIGHT | COVERAGE |")
    cleaning.show(0)

    h2Basement[2].setCoverage(1) // change Cinema node coverage to 1
    diff := cleaning.coverage - topCoverage
    fmt.Println("\nIf the coverage of the Cinema node were increased from 0.75 to 1")
    fmt.Print("the top level coverage would increase by ")
    fmt.Printf("%8.6f to %8.6f\n", diff, topCoverage+diff)
    h2Basement[2].setCoverage(0.75) // restore to original value if required
}


      INSTALL @lib$+"SORTLIB"
      Sort% = FN_sortinit(1,0) : REM Descending

      Valid$ = "[email protected]_`abcdefghijklmnopqrstuvwxyz"
      DIM func$(1000), cnt%(1000)
      nFunc% = 0

      file% = OPENIN("*.bbc")
      WHILE NOT EOF#file%
        ll% = BGET#file%
        no% = BGET#file% + 256*BGET#file%
        INPUT #file%, l$

        i% = 1
        REPEAT
          j% = INSTR(l$, CHR$&A4, i%) : REM Token for 'FN'
          k% = INSTR(l$, CHR$&F2, i%) : REM Token for 'PROC'
          IF k% IF j%=0 OR j%>k% THEN
            i% = k%
            f$ = "PROC"
          ELSE
            i% = j%
            f$ = "FN"
          ENDIF
          IF i% THEN
            REPEAT
              i% += 1
              f$ += MID$(l$, i%, 1)
            UNTIL INSTR(Valid$, MID$(l$, i%+1, 1)) = 0
            FOR j% = 0 TO nFunc%-1
              IF f$ = func$(j%) EXIT FOR
            NEXT
            IF j% >= nFunc% nFunc% += 1
            func$(j%) = f$
            cnt%(j%) += 1
          ENDIF
        UNTIL i%=0
      ENDWHILE
      CLOSE #file%

      C% = nFunc%
      CALL Sort%, cnt%(0), func$(0)

      IF C% > 10 C% = 10
      FOR i% = 0 TO C%-1
        PRINT func$(i%) " (" ; cnt%(i%) ")"
      NEXT