oo::class create AbstractQueue {
    method enqueue item {
        error "not implemented"
    }
    method dequeue {} {
        error "not implemented"
    }
    self unexport create new
}


text: 'Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$\'dollar\'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.'

align: action text; position;

    # split text into 2D array of lines and words
    lines : { for text.split ~\$?\r?\n~ { for a.split '$' a end } end }

    # calculate max required width for each column
    widths: { for lines for a here[b]: a.length.max here[b]? ends }

    spaces: action out ("%%%ds" in).format '' end

    # formatting functions
    left: action word; width;
        pad: width-word.length
        print "%s%s " word spaces pad
    end
    right: action word; width;
        pad: width-word.length
        print "%s%s " spaces pad word
    end
    center: action word; width;
        pad: (width-word.length)/2
        print "%s%s%s " spaces pad.floor word spaces pad.ceil
    end

    if position.match ~^(left|center|right)$~ for lines
        for a local[position] a widths[b] end say ''
    ends say ''
end

align text 'left'
align text 'center'
align text 'right'


class Format(text, width) {
    method align(j) {
        text.map { |row|
            row.range.map { |i|
                '%-*s ' % (width[i],
                  '%*s' % (row[i].len + (width[i]-row[i].len * j/2), row[i]));
            }.join("");
        }.join("\n") + "\n";
    }
}

func Formatter(text) {
    var textArr = [];
    var widthArr = [];

    text.each_line {
        var words = .split('$');
        textArr.append(words);

        words.each_kv { |i, word|
            if (i == widthArr.len) {
                widthArr.append(word.len);
            }
            elsif (word.len > widthArr[i]) {
                widthArr[i] = word.len;
            }
        }
    }

    return Format(textArr, widthArr);
}

enum |left, middle, right|;
const text = <<'EOT';
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
EOT

var f = Formatter(text);

say f.align(left);
say f.align(middle);
say f.align(right);


class Sandpile

  def initialize(ar) = @grid = ar

  def to_a = @grid.dup

  def + (other)
    res = self.to_a.zip(other.to_a).map{|row1, row2| row1.zip(row2).map(&:sum) }
    Sandpile.new(res)
  end

  def stable? = @grid.flatten.none?{|v| v > 3}

  def avalanche
    topple until stable?
    self
  end

  def == (other) = self.avalanche.to_a == other.avalanche.to_a

  def topple
    a = @grid
    a.each_index do |row|
       a[row].each_index do |col|
        next if a[row][col] < 4
        a[row+1][col] += 1 unless row == a.size-1
        a[row-1][col] += 1 if row > 0
        a[row][col+1] += 1 unless col == a.size-1
        a[row][col-1] += 1 if col > 0
        a[row][col]   -= 4
      end
    end
    self
  end

  def to_s = "\n" + @grid.map {|row| row.join(" ") }.join("\n")

end

puts "Sandpile:"
puts demo = Sandpile.new( [[4,3,3], [3,1,2],[0,2,3]] )
puts "\nAfter the avalanche:"
puts demo.avalanche
puts "_" * 30,""

s1 = Sandpile.new([[1, 2, 0], [2, 1, 1], [0, 1, 3]] )
puts "s1: #{s1}"
s2 = Sandpile.new([[2, 1, 3], [1, 0, 1], [0, 1, 0]] )
puts "\ns2: #{s2}"
puts "\ns1 + s2 == s2 + s1: #{s1 + s2 == s2 + s1}"
puts "_" * 30,""

s3    = Sandpile.new([[3, 3, 3], [3, 3, 3], [3, 3, 3]] )
s3_id = Sandpile.new([[2, 1, 2], [1, 0, 1], [2, 1, 2]] )
puts "s3 + s3_id == s3: #{s3 + s3_id == s3}"
puts "s3_id + s3_id == s3_id: #{s3_id + s3_id == s3_id}"


public abstract class Animal : Object {
  public void eat() {
    print("Chomp! Chomp!\n");
  }

  public abstract void talk();
}

public class Mouse : Animal {
  public override void talk() {
    print("Squeak! Squeak!\n");
  }
}

public class Dog : Animal {
  public override void talk() {
    print("Woof! Woof!\n");
  }
}

void main() {
  Dog mike = new Dog();
  Mouse scott = new Mouse();

  mike.talk();
  mike.eat();
  scott.talk();
  scott.eat();
}


MustInherit Class Base

   Protected Sub New()

   End Sub

   Public Sub StandardMethod()
       'code
   End Sub

   Public Overridable Sub Method_Can_Be_Replaced()
       'code
   End Sub

   Public MustOverride Sub Method_Must_Be_Replaced()

End Class


text :=
'Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$''dollar''$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
'.

printSep :=
    [:colLengths |
        Stdout nextPut:$+.
        colLengths do:[:len | Stdout next:len put:$-; nextPut:$+ ].
        Stdout cr.
    ].

printRows :=
    [:text :box :justifyEach |
        lines := StringCollection fromString:text.
        rowSet := lines collect:[:line | line splitBy:$$ ].
        maxNumCols := (rowSet collect:[:row | row size]) max.
        maxLengths := rowSet
                        inject:(Array new:maxNumCols withAll:0)
                        into:[:maxesSoFar :row|
                                maxesSoFar
                                    with:(row paddedTo:maxNumCols with:'')
                                    collect:[:maxLen :col | maxLen max: col size]].
        rowSet do:[:row |
            |first|

            box ifTrue:[ printSep value:maxLengths ].
            first := true.
            (box ifTrue:[row paddedTo:maxLengths size with:''] ifFalse:[row])
            with: (box ifTrue:[maxLengths] ifFalse:[maxLengths to:row size])
            do:[:col :len |
                first ifTrue:[ box ifTrue:[Stdout nextPutAll:'|']. first := false.].
                Stdout print:(justifyEach value:col value:len).
                Stdout nextPutAll:(box ifTrue:'|' ifFalse:' ')
            ].
            Stdout cr.
        ].
        box ifTrue:[ printSep value:maxLengths ].
    ].

printRightJustified :=
    [:text :box | printRows value:text value:box value:[:col :len | (col leftPaddedTo:len)]].

printLeftJustified :=
    [:text :box | printRows value:text value:box value:[:col :len | (col paddedTo:len)]].

printCentered :=
    [:text :box | printRows value:text value:box value:[:col :len | col centerPaddedTo:len]].

Stdout printCR:'Left justified:'.
printLeftJustified value:text value:false.

Stdout cr; printCR:'Right justified:'.
printRightJustified value:text value:false.

Stdout cr; printCR:'Centered:'.
printCentered value:text value:false.

Stdout cr; printCR:'Left justified with box:'.
printLeftJustified value:text value:true.

Stdout cr; printCR:'Right justified with box:'.
printRightJustified value:text value:true.

Stdout cr; printCR:'Centered with box:'.
printCentered value:text value:true.


F sum_proper_divisors(n)
   R I n < 2 {0} E sum((1 .. n I/ 2).filter(it -> (@n % it) == 0))

V deficient = 0
V perfect = 0
V abundant = 0

L(n) 1..20000
   V sp = sum_proper_divisors(n)
   I sp < n
      deficient++
   E I sp == n
      perfect++
   E I sp > n
      abundant++

print(‘Deficient = ’deficient)
print(‘Perfect   = ’perfect)
print(‘Abundant  = ’abundant)


import strings

struct Sandpile {
mut:
    a [9]int
}

const (
neighbors = [
    [1, 3], [0, 2, 4], [1, 5], [0, 4, 6], [1, 3, 5, 7], [2, 4, 8], [3, 7], [4, 6, 8], [5, 7]
]
)

// 'a' is in row order
fn new_sandpile(a [9]int) Sandpile { return Sandpile{a} }

fn (s &Sandpile) plus(other &Sandpile) Sandpile {
    mut b := [9]int{}
    for i in 0..9 {
        b[i] = s.a[i] + other.a[i]
    }
    return Sandpile{b}
}

fn (s &Sandpile) is_stable() bool {
    for e in s.a {
        if e > 3 {
            return false
        }
    }
    return true
}

// just topples once so we can observe intermediate results
fn (mut s Sandpile) topple() {
    for i in 0..9 {
        if s.a[i] > 3 {
            s.a[i] -= 4
            for j in neighbors[i] {
                s.a[j]++
            }
            return
        }
    }
}

fn (s Sandpile) str() string {
    mut sb := strings.new_builder(64)
    for i in 0..3 {
        for j in 0..3 {
            sb.write_string("${u8(s.a[3*i+j])} ")
        }
        sb.write_string("\n")
    }
    return sb.str()
}

fn main() {
    println("Avalanche of topplings:\n")
    mut s4 := new_sandpile([4, 3, 3, 3, 1, 2, 0, 2, 3]!)
    println(s4)
    for !s4.is_stable() {
        s4.topple()
        println(s4)
    }

    println("Commutative additions:\n")
    s1 := new_sandpile([1, 2, 0, 2, 1, 1, 0, 1, 3]!)
    s2 := new_sandpile([2, 1, 3, 1, 0, 1, 0, 1, 0]!)
    mut s3_a := s1.plus(s2)
    for !s3_a.is_stable() {
        s3_a.topple()
    }
    mut s3_b := s2.plus(s1)
    for !s3_b.is_stable() {
        s3_b.topple()
    }
    println("$s1\nplus\n\n$s2\nequals\n\n$s3_a")
    println("and\n\n$s2\nplus\n\n$s1\nalso equals\n\n$s3_b")

    println("Addition of identity sandpile:\n")
    s3 := new_sandpile([3, 3, 3, 3, 3, 3, 3, 3, 3]!)
    s3_id := new_sandpile([2, 1, 2, 1, 0, 1, 2, 1, 2]!)
    s4 = s3.plus(s3_id)
    for !s4.is_stable() {
        s4.topple()
    }
    println("$s3\nplus\n\n$s3_id\nequals\n\n$s4")

    println("Addition of identities:\n")
    mut s5 := s3_id.plus(s3_id)
    for !s5.is_stable() {
        s5.topple()
    }
    print("$s3_id\nplus\n\n$s3_id\nequals\n\n$s5")
}


import "/fmt" for Fmt

class Sandpile {
    static init() {
        __neighbors = [
            [1, 3], [0, 2, 4], [1, 5], [0, 4, 6], [1, 3, 5, 7], [2, 4, 8], [3, 7], [4, 6, 8], [5, 7]
        ]
    }

    // 'a' is a list of 9 integers in row order
    construct new(a) {
        _a = a
    }

    a { _a }

    +(other) {
        var b = List.filled(9, 0)
        for (i in 0..8) b[i] = _a[i] + other.a[i]
        return Sandpile.new(b)
    }

    isStable { _a.all { |i| i <= 3 } }

    // just topples once so we can observe intermediate results
    topple() {
        for (i in 0..8) {
            if (_a[i] > 3) {
                _a[i] = _a[i] - 4
                for (j in __neighbors[i]) _a[j] = _a[j] + 1
                return
            }
        }
    }

    toString {
        var s = ""
        for (i in 0..2) {
            for (j in 0..2) s = s + "%(a[3*i + j]) "
            s = s + "\n"
        }
        return s
    }
}

Sandpile.init()
System.print("Avalanche of topplings:\n")
var s4 = Sandpile.new([4, 3, 3, 3, 1, 2, 0, 2, 3])
System.print(s4)
while (!s4.isStable) {
    s4.topple()
    System.print(s4)
}

System.print("Commutative additions:\n")
var s1 = Sandpile.new([1, 2, 0, 2, 1, 1, 0, 1, 3])
var s2 = Sandpile.new([2, 1, 3, 1, 0, 1, 0, 1, 0])
var s3_a = s1 + s2
while (!s3_a.isStable) s3_a.topple()
var s3_b = s2 + s1
while (!s3_b.isStable) s3_b.topple()
Fmt.print("$s\nplus\n\n$s\nequals\n\n$s", s1, s2, s3_a)
Fmt.print("and\n\n$s\nplus\n\n$s\nalso equals\n\n$s", s2, s1, s3_b)

System.print("Addition of identity sandpile:\n")
var s3 = Sandpile.new(List.filled(9, 3))
var s3_id = Sandpile.new([2, 1, 2, 1, 0, 1, 2, 1, 2])
s4 = s3 + s3_id
while (!s4.isStable) s4.topple()
Fmt.print("$s\nplus\n\n$s\nequals\n\n$s", s3, s3_id, s4)

System.print("Addition of identities:\n")
var s5 = s3_id + s3_id
while (!s5.isStable) s5.topple()
Fmt.write("$s\nplus\n\n$s\nequals\n\n$s", s3_id, s3_id, s5)


interface Beast {
    kind() string
    name() string
    cry() string
}

struct Dog {
    kind string
    name string
}

fn (d Dog) kind() string { return d.kind }

fn (d Dog) name() string { return d.name }

fn (d Dog) cry() string { return "Woof" }

struct Cat {
    kind string
    name string
}

fn (c Cat) kind() string { return c.kind }

fn (c Cat) name() string { return c.name }

fn (c Cat) cry() string { return "Meow" }

fn bprint(b Beast) {
    println("${b.name()}, who's a ${b.kind()}, cries: ${b.cry()}.")
}

fn main() {
    d := Dog{"labrador", "Max"}
    c := Cat{"siamese", "Sammy"}
    bprint(d)
    bprint(c)
}


import "/fmt" for Fmt

class Beast{
    kind {}
    name {}
    cry() {}
    print() { System.print("%(name), who's a %(kind), cries: %(Fmt.q(cry())).") }
}

class Dog is Beast {
    construct new(kind, name) {
        _kind = kind
        _name = name
    }
    kind { _kind }
    name { _name }
    cry() { "Woof" }
}

class Cat is Beast {
    construct new(kind, name) {
        _kind = kind
        _name = name
    }
    kind { _kind }
    name { _name }
    cry() { "Meow" }
}

var d = Dog.new("labrador", "Max")
var c = Cat.new("siamese", "Sammy")
d.print()
c.print()


*              Since we don't know how much text we'll be reading in,
*              we store the words and field widths in tables
               Words = TABLE()
               Widths = TABLE()

*              Match text from start of string to the first dollar sign
               WordPat = POS(0) BREAK('$') . Word LEN(1) REM . Rest

*              We output the results aligned three different ways; these are the
*              labels for those sections of output:
               Labels = ARRAY(3)
               Labels<1> = "Left-justified"
               Labels<2> = "Right-justified"
               Labels<3> = "Centered"

*              There are built-in functions for left- and right- justification,
*              but not necessarily one for centering (depending on
*              implementation).  So we define one.
               DEFINE('CPAD(Word,Width)Z,Left')      :(END_CPAD)

CPAD           Z = SIZE(Word)
               Left = Z + (Width - Z) / 2
               CPAD = RPAD(LPAD(Word, Left), Width)  :(RETURN)
END_CPAD

*              Read in our text a line at a time and split into words on '$'
InLineLoop     Line = INPUT                          :F(DoneReading)
               LineCount = LineCount + 1
               Column = 0
InWordLoop     Column = Column + 1

*              Separate Line into Word, Line=Rest at first dollar sign
               Line WordPat = Rest                   :S(CheckMax)

*              If there was no '$', the whole line is the next word
               Word = Line
               Line =

*              Keep track of the largest number of columns on any line
CheckMax       LE(Column, MaxColumn)                 :S(StoreWord)
               MaxColumn = Column

StoreWord      Words<LineCount ',' Column> = Word

*              And the size of the longest word in each column
               GT(SIZE(Word),Widths<Column>)         :F(NoNewMaxWidth)
               Widths<Column> = SIZE(Word)

*              Loop if the line isn't empty yet
NoNewMaxWidth  GT(Size(Line))                        :S(InWordLoop) F(InLineLoop)
DoneReading

*              Now we print the results out in the three justification styles
               Style = 0
StyleLoop      Style = Style + 1
               GT(Style, 3)                          :S(END)
               OUTPUT =
               OUTPUT =  Labels<Style> ':'

               I = 0
OutLineLoop    I = I + 1
               GT(I, LineCount)                      :S(StyleLoop)

*              Build up the output line by fields starting with the null string
               Line =
               J = 0
OutWordLoop    J = J + 1
               GT(J, MaxColumn)                      :S(PrintLine)
               Word = Words<I ',' J>
               GT(SIZE(Word))                        :F(PrintLine)

*              Place the word within the column according to the pass we're on
               EQ(Style, 1)                          :F(NotLeft)
*              Left-justified
               Word = RPAD(Word, Widths<J>)          :(AddWord)

NotLeft        EQ(Style, 2)                          :F(NotRight)
*              Right-justified
               Word = LPAD(Word, Widths<J>)          :(AddWord)

*              Centered
NotRight       Word = CPAD(Word, Widths<J>)

*              Add word to line and loop
AddWord        Line = Line GT(SIZE(Line)) ' '
               Line = Line Word                      :(OutWordLoop)

*              Print the line
PrintLine      OUTPUT = Line                         :(OutLineLoop)

END


fun curry f x y = f (x, y)
fun uncurry f (x, y) = f x y

fun maxWidths ([], widths) = widths
  | maxWidths (strings, []) = map size strings
  | maxWidths (s :: ss, w :: ws) = Int.max (size s, w) :: maxWidths (ss, ws)

val alignL = uncurry (StringCvt.padRight #" ")
and alignR = uncurry (StringCvt.padLeft #" ")

fun alignC (w, s) =
  alignL (w, alignR ((w + size s) div 2, s))

fun formatTable tab =
  let
    val columnWidths = foldl maxWidths [] tab
  in
    fn f => String.concatWith "\n"
      (map (String.concatWith " " o curry (ListPair.map f) columnWidths) tab)
  end

val readTable =
  map (String.fields (curry op= #"$"))
  o String.tokens (curry op= #"\n")
  o TextIO.inputAll

(* test stdin with all alignments *)
val () = print (String.concatWith "\n\n"
  (map (formatTable (readTable TextIO.stdIn)) [alignL, alignC, alignR]) ^ "\n")


*        Abundant, deficient and perfect number  08/05/2016
ABUNDEFI CSECT
         USING  ABUNDEFI,R13       set base register
SAVEAR   B      STM-SAVEAR(R15)    skip savearea
         DC     17F'0'             savearea
STM      STM    R14,R12,12(R13)    save registers
         ST     R13,4(R15)         link backward SA
         ST     R15,8(R13)         link forward SA
         LR     R13,R15            establish addressability
         SR     R10,R10            deficient=0
         SR     R11,R11            perfect  =0
         SR     R12,R12            abundant =0
         LA     R6,1               i=1
LOOPI    C      R6,NN              do i=1 to nn
         BH     ELOOPI
         SR     R8,R8              sum=0
         LR     R9,R6              i
         SRA    R9,1               i/2
         LA     R7,1               j=1
LOOPJ    CR     R7,R9              do j=1 to i/2
         BH     ELOOPJ
         LR     R2,R6              i
         SRDA   R2,32
         DR     R2,R7              i//j=0
         LTR    R2,R2              if i//j=0
         BNZ    NOTMOD
         AR     R8,R7              sum=sum+j
NOTMOD   LA     R7,1(R7)           j=j+1
         B      LOOPJ
ELOOPJ   CR     R8,R6              if sum?i
         BL     SLI                      <
         BE     SEI                      =
         BH     SHI                      >
SLI      LA     R10,1(R10)         deficient+=1
         B      EIF
SEI      LA     R11,1(R11)         perfect  +=1
         B      EIF
SHI      LA     R12,1(R12)         abundant +=1
EIF      LA     R6,1(R6)           i=i+1
         B      LOOPI
ELOOPI   XDECO  R10,XDEC           edit deficient
         MVC    PG+10(5),XDEC+7
         XDECO  R11,XDEC           edit perfect
         MVC    PG+24(5),XDEC+7
         XDECO  R12,XDEC           edit abundant
         MVC    PG+39(5),XDEC+7
         XPRNT  PG,80              print buffer
         L      R13,4(0,R13)       restore savearea pointer
         LM     R14,R12,12(R13)    restore registers
         XR     R15,R15            return code = 0
         BR     R14                return to caller
NN       DC     F'20000'
PG       DC     CL80'deficient=xxxxx perfect=xxxxx abundant=xxxxx'
XDEC     DS     CL12
         REGEQU
         END    ABUNDEFI


LIMIT:	equ	20000
	cpu	8086
	org	100h
	mov	ax,data		; Set DS and ES to point right after the
	mov	cl,4		; program, so we can store the array there
	shr	ax,cl
	mov	dx,cs
	add	ax,dx
	inc	ax
	mov	ds,ax
	mov	es,ax
	mov	ax,1		; Set each element to 1 at the beginning
	xor	di,di
	mov	cx,LIMIT+1
	rep	stosw
	mov	[2],cx		; Except the value for 1, which is 0
	mov 	bp,LIMIT/2	; BP = limit / 2 - keep values ready in regs
	mov	di,LIMIT	; DI = limit
oloop:	inc	ax		; Let AX be the outer loop counter (divisor)
	cmp	ax,bp		; Are we there yet?
	ja	clsfy		; If so, stop
	mov	dx,ax		; Let DX be the inner loop counter (number)
iloop:	add	dx,ax
	cmp	dx,di		; Are we there yet?
	ja	oloop		; Loop
	mov	bx,dx		; Each entry is 2 bytes wide
	shl	bx,1
	add 	[bx],ax		; Add divisor to number
	jmp	iloop
clsfy:	xor	bp,bp		; BP = deficient number counter
	xor	dx,dx		; DX = perfect number counter
	xor	cx,cx 		; CX = abundant number counter
	xor	bx,bx		; BX = current number under consideration
	mov	si,2		; SI = pointer to divsum of current number
cloop:	inc	bx		; Next number
	cmp	bx,di		; Are we done yet?
	ja	done		; If so, stop
	lodsw			; Otherwise, get divsum of current number
	cmp	ax,bx		; Compare to current number
	jb	defic		; If smaller, the number is deficient
	je	prfct		; If equal, the number is perfect
	inc	cx		; Otherwise, the number is abundant
	jmp	cloop
defic:	inc	bp
	jmp	cloop
prfct:	inc	dx
	jmp	cloop
done:	mov	ax,cs		; Set DS and ES back to the code segment
	mov	ds,ax
	mov	es,ax
	mov	di,dx		; Move the perfect numbers to DI
	mov	dx,sdef		; Print "Deficient"
	call	prstr
	mov	ax,bp		; Print amount of deficient numbers
	call	prnum
	mov	dx,sper		; Print "Perfect"
	call	prstr
	mov	ax,di		; Print amount of perfect numbers
	call	prnum
	mov	dx,sabn		; Print "Abundant"
	call 	prstr
	mov	ax,cx		; Print amount of abundant numbers
prnum:	mov	bx,snum		; Print number in AX
pdgt:	xor	dx,dx
	div	word [ten]	; Extract digit
	dec	bx		; Move pointer
	add	dl,'0'
	mov	[bx],dl		; Store digit
	test	ax,ax		; Any more digits?
	jnz	pdgt
	mov	dx,bx		; Print string
prstr:	mov	ah,9
	int	21h
	ret
ten:	dw	10		; Divisor for number output routine
sdef:	db	'Deficient: $'
sper:	db	'Perfect: $'
sabn:	db	'Abundant: $'
	db	'.....'
snum:	db	13,10,'$'
data:	equ	$


#[derive(Clone)]
struct Box {
    piles: [[u8; 3]; 3],
}

impl Box {
    fn init(piles: [[u8; 3]; 3]) -> Box {
        let a = Box { piles };

        if a.piles.iter().any(|&row| row.iter().any(|&pile| pile >= 4)) {
            return a.avalanche();
        } else {
            return a;
        }
    }

    fn avalanche(&self) -> Box {
        let mut a = self.clone();
        for (i, row) in self.piles.iter().enumerate() {
            for (j, pile) in row.iter().enumerate() {
                if *pile >= 4u8 {
                    if i > 0 {
                        a.piles[i - 1][j] += 1u8
                    }
                    if i < 2 {
                        a.piles[i + 1][j] += 1u8
                    }
                    if j > 0 {
                        a.piles[i][j - 1] += 1u8
                    }
                    if j < 2 {
                        a.piles[i][j + 1] += 1u8
                    }
                    a.piles[i][j] -= 4;
                }
            }
        }
        Box::init(a.piles)
    }

    fn add(&self, a: &Box) -> Box {
        let mut b = Box {
            piles: [[0u8; 3]; 3],
        };
        for (row, columns) in b.piles.iter_mut().enumerate() {
            for (col, pile) in columns.iter_mut().enumerate() {
                *pile = self.piles[row][col] + a.piles[row][col]
            }
        }
        Box::init(b.piles)
    }
}

fn main() {
    println!(
        "The piles demonstration avalanche starts as:\n{:?}\n{:?}\n{:?}",
        [4, 3, 3],
        [3, 1, 2],
        [0, 2, 3]
    );
    let s0 = Box::init([[4u8, 3u8, 3u8], [3u8, 1u8, 2u8], [0u8, 2u8, 3u8]]);
    println!(
        "And ends as:\n{:?}\n{:?}\n{:?}",
        s0.piles[0], s0.piles[1], s0.piles[2]
    );
    let s1 = Box::init([[1u8, 2u8, 0u8], [2u8, 1u8, 1u8], [0u8, 1u8, 3u8]]);
    let s2 = Box::init([[2u8, 1u8, 3u8], [1u8, 0u8, 1u8], [0u8, 1u8, 0u8]]);
    let s1_2 = s1.add(&s2);
    let s2_1 = s2.add(&s1);
    println!(
        "The piles in s1 + s2 are:\n{:?}\n{:?}\n{:?}",
        s1_2.piles[0], s1_2.piles[1], s1_2.piles[2]
    );
    println!(
        "The piles in s2 + s1 are:\n{:?}\n{:?}\n{:?}",
        s2_1.piles[0], s2_1.piles[1], s2_1.piles[2]
    );
    let s3 = Box::init([[3u8; 3]; 3]);
    let s3_id = Box::init([[2u8, 1u8, 2u8], [1u8, 0u8, 1u8], [2u8, 1u8, 2u8]]);
    let s4 = s3.add(&s3_id);
    println!(
        "The piles in s3 + s3_id are:\n{:?}\n{:?}\n{:?}",
        s4.piles[0], s4.piles[1], s4.piles[2]
    );
    let s5 = s3_id.add(&s3_id);
    println!(
        "The piles in s3_id + s3_id are:\n{:?}\n{:?}\n{:?}",
        s5.piles[0], s5.piles[1], s5.piles[2]
    );
}


class Stream{	// Mostly virtural base class
   var [proxy protected]
      isBroken = fcn { _broken.isSet() },
      isClosed = fcn { return(_closed.isSet() or _broken.isSet()); };
   fcn init{
      var [protected]
         _closed	= Atomic.Bool(True),
	 _broken	= Atomic.Bool(False),
	 whyBroken	= Void;
   }
   fcn clear	  { _closed.clear(); _broken.clear(); return(self.topdog); }
   fcn open       { return(topdog.init(vm.pasteArgs())); }
   fcn toStream   { return(self); }
   fcn close      { _closed.set(); return(self.topdog); }
   fcn flush      { return(self.topdog); }
   fcn read       { throw(Exception.TheEnd); }	// destructive or advance
   fcn readln     { throw(Exception.TheEnd); }
   fcn write(x)	  { return(self.topdog); }
   fcn writeln(x) { return(self.topdog); }
   fcn walker	  { return((0).walker(*,wap((self.topdog.read.fpM(""))))); }
}


import Foundation

extension String {
  func dropLastIf(_ char: Character) -> String {
    if last == char {
      return String(dropLast())
    } else {
      return self
    }
  }
}

enum Align {
  case left, center, right
}

func getLines(input: String) -> [String] {
  input
    .components(separatedBy: "\n")
    .map({ $0.replacingOccurrences(of: " ", with: "").dropLastIf("$") })
}

func getColWidths(from: String) -> [Int] {
  var widths = [Int]()
  let lines = getLines(input: from)

  for line in lines {
    let lens = line.components(separatedBy: "$").map({ $0.count })

    for (i, len) in lens.enumerated() {
      if i < widths.count {
        widths[i] = max(widths[i], len)
      } else {
        widths.append(len)
      }
    }
  }

  return widths
}

func alignCols(input: String, align: Align = .left) -> String {
  let widths = getColWidths(from: input)
  let lines = getLines(input: input)
  var res = ""

  for line in lines {
    for (str, width) in zip(line.components(separatedBy: "$"), widths) {
      let blanks = width - str.count
      let pre: Int, post: Int

      switch align {
      case .left:
        (pre, post) = (0, blanks)
      case .center:
        (pre, post) = (blanks / 2, (blanks + 1) / 2)
      case .right:
        (pre, post) = (blanks, 0)
      }

      res += String(repeating: " ", count: pre)
      res += str
      res += String(repeating: " ", count: post)
      res += " "
    }

    res += "\n"
  }

  return res
}

let input = """
            Given$a$text$file$of$many$lines,$where$fields$within$a$line$
            are$delineated$by$a$single$'dollar'$character,$write$a$program
            that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
            column$are$separated$by$at$least$one$space.
            Further,$allow$for$each$word$in$a$column$to$be$either$left$
            justified,$right$justified,$or$center$justified$within$its$column.
            """

print(alignCols(input: input))
print()
print(alignCols(input: input, align: .center))
print()
print(alignCols(input: input, align: .right))


package require Tcl 8.5

set text {Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.}

array set max {}
foreach line [split $text \n] {
    set col 0
    set thisline [split $line \$]
    lappend words $thisline
    foreach word $thisline {
        set max([incr col]) [expr {[info exists max($col)]
                                    ? max($max($col), [string length $word])
                                    : [string length $word]
                            }]
    }
}

proc justify {word position width} {
    switch -exact -- $position {
        left {
            return [format "%-*s" $width $word]
        }
        center {
            set lpadw [expr {($width - [string length $word])/2}]
            return [format "%s%-*s" [string repeat " " $lpadw] [incr width -$lpadw] $word]
        }
        right {
            return [format "%*s" $width $word]
        }
    }
}

foreach position {left center right} {
    foreach thisline $words {
        set col 0
        set line ""
        foreach word $thisline {
            append line [justify $word $position $max([incr col])] " "
        }
        puts [string trimright $line]
    }
    puts ""
}


/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */
/* program numberClassif64.s   */

/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"

.equ NBDIVISORS,             1000

/*******************************************/
/* Initialized data                        */
/*******************************************/
.data
szMessStartPgm:          .asciz "Program 64 bits start \n"
szMessEndPgm:            .asciz "Program normal end.\n"
szMessErrorArea:         .asciz "\033[31mError : area divisors too small.\n"
szMessError:             .asciz "\033[31mError  !!!\n"
szMessErrGen:            .asciz "Error end program.\n"
szMessNbPrem:            .asciz "This number is prime !!!.\n"
szMessOverflow:          .asciz "Overflow function isPrime.\n"

szCarriageReturn:        .asciz "\n"

/* datas message display */
szMessResult:            .asciz "Number déficients : @ perfects : @ abundants : @ \n"

/*******************************************/
/* UnInitialized data                      */
/*******************************************/
.bss
.align 4
sZoneConv:               .skip 24
tbZoneDecom:             .skip 8 * NBDIVISORS       // facteur 8 octets
/*******************************************/
/*  code section                           */
/*******************************************/
.text
.global main
main:                               // program start
    ldr x0,qAdrszMessStartPgm       // display start message
    bl affichageMess

    mov x4,#1
    mov x3,#0
    mov x6,#0
    mov x7,#0
    mov x8,#0
    ldr x9,iNBMAX
1:
    mov x0,x4                       //  number
    //=================================
    ldr x1,qAdrtbZoneDecom
    bl decompFact                // create area of divisors
    cmp x0,#0                    // error ?
    blt 2f
    lsl x5,x4,#1                 // number * 2
    cmp x5,x1                    // compare number and sum
    cinc x7,x7,eq                // perfect
    cinc x6,x6,gt                // deficient
    cinc x8,x8,lt                // abundant

2:
    add x4,x4,#1
    cmp x4,x9
    ble 1b

    //================================

    mov x0,x6                        // deficient
    ldr x1,qAdrsZoneConv
    bl conversion10                  // convert ascii string
    ldr x0,qAdrszMessResult
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc               // and put in message
    mov x5,x0
    mov x0,x7                        // perfect
    ldr x1,qAdrsZoneConv
    bl conversion10                  // convert ascii string
    mov x0,x5
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc               // and put in message
    mov x5,x0
    mov x0,x8                        // abundant
    ldr x1,qAdrsZoneConv
    bl conversion10                  // convert ascii string
    mov x0,x5
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc               // and put in message
    bl affichageMess

    ldr x0,qAdrszMessEndPgm         // display end message
    bl affichageMess
    b 100f
99:                                 // display error message
    ldr x0,qAdrszMessError
    bl affichageMess
100:                                // standard end of the program
    mov x0, #0                      // return code
    mov x8, #EXIT                   // request to exit program
    svc 0                           // perform system call
qAdrszMessStartPgm:        .quad szMessStartPgm
qAdrszMessEndPgm:          .quad szMessEndPgm
qAdrszMessError:           .quad szMessError
qAdrszCarriageReturn:      .quad szCarriageReturn
qAdrtbZoneDecom:           .quad tbZoneDecom

qAdrszMessResult:          .quad szMessResult
qAdrsZoneConv:             .quad sZoneConv

iNBMAX:                    .quad 20000
/******************************************************************/
/*     decomposition en facteur                                               */
/******************************************************************/
/* x0 contient le nombre à decomposer */
/* x1 contains factor area address */
decompFact:
    stp x3,lr,[sp,-16]!        // save  registres
    stp x4,x5,[sp,-16]!        // save  registres
    stp x6,x7,[sp,-16]!        // save  registres
    stp x8,x9,[sp,-16]!        // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    mov x5,x1
    mov x1,x0
    cmp x0,1
    beq 100f
    mov x8,x0                    // save number
    bl isPrime                   // prime ?
    cmp x0,#1
    beq 98f                      // yes is prime
    mov x1,#1
    str x1,[x5]                  // first factor
    mov x12,#1                   // divisors sum
    mov x4,#1                    // indice divisors table
    mov x1,#2                    // first divisor
    mov x6,#0                    // previous divisor
    mov x7,#0                    // number of same divisors
2:
    mov x0,x8                    // dividende
    udiv x2,x0,x1                //  x1 divisor x2 quotient x3 remainder
    msub x3,x2,x1,x0
    cmp x3,#0
    bne 5f                       // if remainder <> zero  -> no divisor
    mov x8,x2                    // else quotient -> new dividende
    cmp x1,x6                    // same divisor ?
    beq 4f                       // yes
    mov x7,x4                    // number factors in table
    mov x9,#0                    // indice
21:
    ldr x10,[x5,x9,lsl #3 ]      // load one factor
    mul x10,x1,x10               // multiply
    str x10,[x5,x7,lsl #3]       // and store in the table
    add x12,x12,x10
    add x7,x7,#1                 // and increment counter
    add x9,x9,#1
    cmp x9,x4
    blt 21b
    mov x4,x7
    mov x6,x1                    // new divisor
    b 7f
4:                               // same divisor
    sub x9,x4,#1
    mov x7,x4
41:
    ldr x10,[x5,x9,lsl #3 ]
    cmp x10,x1
    sub x13,x9,1
    csel x9,x13,x9,ne
    bne 41b
    sub x9,x4,x9
42:
    ldr  x10,[x5,x9,lsl #3 ]
    mul x10,x1,x10
    str x10,[x5,x7,lsl #3]       // and store in the table
    add x12,x12,x10
    add x7,x7,#1                 // and increment counter
    add x9,x9,#1
    cmp x9,x4
    blt 42b
    mov x4,x7
    b 7f                         // and loop

    /* not divisor -> increment next divisor */
5:
    cmp x1,#2                    // if divisor = 2 -> add 1
    add x13,x1,#1                // add 1
    add x14,x1,#2                // else add 2
    csel x1,x13,x14,eq
    b 2b

    /* divisor -> test if new dividende is prime */
7:
    mov x3,x1                    // save divisor
    cmp x8,#1                    // dividende = 1 ? -> end
    beq 10f
    mov x0,x8                    // new dividende is prime ?
    mov x1,#0
    bl isPrime                   // the new dividende is prime ?
    cmp x0,#1
    bne 10f                      // the new dividende is not prime

    cmp x8,x6                    // else dividende is same divisor ?
    beq 9f                       // yes
    mov x7,x4                    // number factors in table
    mov x9,#0                    // indice
71:
    ldr x10,[x5,x9,lsl #3 ]      // load one factor
    mul x10,x8,x10               // multiply
    str x10,[x5,x7,lsl #3]       // and store in the table
    add x12,x12,x10
    add x7,x7,#1                 // and increment counter
    add x9,x9,#1
    cmp x9,x4
    blt 71b
    mov x4,x7
    mov x7,#0
    b 11f
9:
    sub x9,x4,#1
    mov x7,x4
91:
    ldr x10,[x5,x9,lsl #3 ]
    cmp x10,x8
    sub x13,x9,#1
    csel x9,x13,x9,ne
    bne 91b
    sub x9,x4,x9
92:
    ldr  x10,[x5,x9,lsl #3 ]
    mul x10,x8,x10
    str x10,[x5,x7,lsl #3]       // and store in the table
    add x12,x12,x10
    add x7,x7,#1                 // and increment counter
    add x9,x9,#1
    cmp x9,x4
    blt 92b
    mov x4,x7
    b 11f

10:
    mov x1,x3                    // current divisor = new divisor
    cmp x1,x8                    // current divisor  > new dividende ?
    ble 2b                       // no -> loop

    /* end decomposition */
11:
    mov x0,x4                    // return number of table items
    mov x1,x12                   // return sum
    mov x3,#0
    str x3,[x5,x4,lsl #3]        // store zéro in last table item
    b 100f

98:
    //ldr x0,qAdrszMessNbPrem
    //bl   affichageMess
    add x1,x8,1
    mov x0,#0                   // return code
    b 100f
99:
    ldr x0,qAdrszMessError
    bl   affichageMess
    mov x0,#-1                  // error code
    b 100f

100:
    ldp x10,x11,[sp],16          // restaur des  2 registres
    ldp x8,x9,[sp],16          // restaur des  2 registres
    ldp x6,x7,[sp],16          // restaur des  2 registres
    ldp x4,x5,[sp],16          // restaur des  2 registres
    ldp x3,lr,[sp],16          // restaur des  2 registres
    ret                        // retour adresse lr x30
qAdrszMessErrGen:          .quad szMessErrGen
qAdrszMessNbPrem:          .quad szMessNbPrem
/***************************************************/
/*   Verification si un nombre est premier         */
/***************************************************/
/* x0 contient le nombre à verifier */
/* x0 retourne 1 si premier  0 sinon */
isPrime:
    stp x1,lr,[sp,-16]!        // save  registres
    stp x2,x3,[sp,-16]!        // save  registres
    mov x2,x0
    sub x1,x0,#1
    cmp x2,0
    beq 99f                    // retourne zéro
    cmp x2,2                   // pour 1 et 2 retourne 1
    ble 2f
    mov x0,#2
    bl moduloPux64
    bcs 100f                   // erreur overflow
    cmp x0,#1
    bne 99f                    // Pas premier
    cmp x2,3
    beq 2f
    mov x0,#3
    bl moduloPux64
    blt 100f                   // erreur overflow
    cmp x0,#1
    bne 99f

    cmp x2,5
    beq 2f
    mov x0,#5
    bl moduloPux64
    bcs 100f                   // erreur overflow
    cmp x0,#1
    bne 99f                    // Pas premier

    cmp x2,7
    beq 2f
    mov x0,#7
    bl moduloPux64
    bcs 100f                   // erreur overflow
    cmp x0,#1
    bne 99f                    // Pas premier

    cmp x2,11
    beq 2f
    mov x0,#11
    bl moduloPux64
    bcs 100f                   // erreur overflow
    cmp x0,#1
    bne 99f                    // Pas premier

    cmp x2,13
    beq 2f
    mov x0,#13
    bl moduloPux64
    bcs 100f                   // erreur overflow
    cmp x0,#1
    bne 99f                    // Pas premier
2:
    cmn x0,0                   // carry à zero pas d'erreur
    mov x0,1                   // premier
    b 100f
99:
    cmn x0,0                   // carry à zero pas d'erreur
    mov x0,#0                  // Pas premier
100:
    ldp x2,x3,[sp],16          // restaur des  2 registres
    ldp x1,lr,[sp],16          // restaur des  2 registres
    ret                        // retour adresse lr x30

/**************************************************************/
/********************************************************/
/*   Calcul modulo de b puissance e modulo m  */
/*    Exemple 4 puissance 13 modulo 497 = 445         */
/********************************************************/
/* x0  nombre  */
/* x1 exposant */
/* x2 modulo   */
moduloPux64:
    stp x1,lr,[sp,-16]!        // save  registres
    stp x3,x4,[sp,-16]!        // save  registres
    stp x5,x6,[sp,-16]!        // save  registres
    stp x7,x8,[sp,-16]!        // save  registres
    stp x9,x10,[sp,-16]!        // save  registres
    cbz x0,100f
    cbz x1,100f
    mov x8,x0
    mov x7,x1
    mov x6,1                   // resultat
    udiv x4,x8,x2
    msub x9,x4,x2,x8           // contient le reste
1:
    tst x7,1
    beq 2f
    mul x4,x9,x6
    umulh x5,x9,x6
    //cbnz x5,99f
    mov x6,x4
    mov x0,x6
    mov x1,x5
    bl divisionReg128U
    cbnz x1,99f                // overflow
    mov x6,x3
2:
    mul x8,x9,x9
    umulh x5,x9,x9
    mov x0,x8
    mov x1,x5
    bl divisionReg128U
    cbnz x1,99f                // overflow
    mov x9,x3
    lsr x7,x7,1
    cbnz x7,1b
    mov x0,x6                  // result
    cmn x0,0                   // carry à zero pas d'erreur
    b 100f
99:
    ldr x0,qAdrszMessOverflow
    bl  affichageMess
    cmp x0,0                   // carry à un car erreur
    mov x0,-1                  // code erreur

100:
    ldp x9,x10,[sp],16          // restaur des  2 registres
    ldp x7,x8,[sp],16          // restaur des  2 registres
    ldp x5,x6,[sp],16          // restaur des  2 registres
    ldp x3,x4,[sp],16          // restaur des  2 registres
    ldp x1,lr,[sp],16          // restaur des  2 registres
    ret                        // retour adresse lr x30
qAdrszMessOverflow:         .quad  szMessOverflow
/***************************************************/
/*   division d un nombre de 128 bits par un nombre de 64 bits */
/***************************************************/
/* x0 contient partie basse dividende */
/* x1 contient partie haute dividente */
/* x2 contient le diviseur */
/* x0 retourne partie basse quotient */
/* x1 retourne partie haute quotient */
/* x3 retourne le reste */
divisionReg128U:
    stp x6,lr,[sp,-16]!        // save  registres
    stp x4,x5,[sp,-16]!        // save  registres
    mov x5,#0                  // raz du reste R
    mov x3,#128                // compteur de boucle
    mov x4,#0                  // dernier bit
1:
    lsl x5,x5,#1               // on decale le reste de 1
    tst x1,1<<63               // test du bit le plus à gauche
    lsl x1,x1,#1               // on decale la partie haute du quotient de 1
    beq 2f
    orr  x5,x5,#1              // et on le pousse dans le reste R
2:
    tst x0,1<<63
    lsl x0,x0,#1               // puis on decale la partie basse
    beq 3f
    orr x1,x1,#1               // et on pousse le bit de gauche dans la partie haute
3:
    orr x0,x0,x4               // position du dernier bit du quotient
    mov x4,#0                  // raz du bit
    cmp x5,x2
    blt 4f
    sub x5,x5,x2                // on enleve le diviseur du reste
    mov x4,#1                   // dernier bit à 1
4:
                               // et boucle
    subs x3,x3,#1
    bgt 1b
    lsl x1,x1,#1               // on decale le quotient de 1
    tst x0,1<<63
    lsl x0,x0,#1              // puis on decale la partie basse
    beq 5f
    orr x1,x1,#1
5:
    orr x0,x0,x4                  // position du dernier bit du quotient
    mov x3,x5
100:
    ldp x4,x5,[sp],16          // restaur des  2 registres
    ldp x6,lr,[sp],16          // restaur des  2 registres
    ret                        // retour adresse lr x30

/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"


PROC FillSumOfDivisors(CARD ARRAY pds CARD size,maxNum,offset)
  CARD i,j

  FOR i=0 TO size-1
  DO
    pds(i)=1
  OD
  FOR i=2 TO maxNum DO
    FOR j=i+i TO maxNum STEP i
    DO
      IF j>=offset THEN
        pds(j-offset)==+i
      FI
    OD
  OD
RETURN

PROC Main()
  DEFINE MAXNUM="20000"
  DEFINE HALFNUM="10000"
  CARD ARRAY pds(HALFNUM+1)
  CARD def,perf,abud,i,sum,offset
  BYTE CRSINH=$02F0 ;Controls visibility of cursor

  CRSINH=1 ;hide cursor
  Put(125) PutE() ;clear the screen
  PrintE("Please wait...")

  def=1 perf=0 abud=0
  FillSumOfDivisors(pds,HALFNUM+1,HALFNUM,0)
  FOR i=2 TO HALFNUM
  DO
    sum=pds(i)
    IF sum<i THEN def==+1
    ELSEIF sum=i THEN perf==+1
    ELSE abud==+1 FI
  OD

  offset=HALFNUM
  FillSumOfDivisors(pds,HALFNUM+1,MAXNUM,offset)
  FOR i=HALFNUM+1 TO MAXNUM
  DO
    sum=pds(i-offset)
    IF sum<i THEN def==+1
    ELSEIF sum=i THEN perf==+1
    ELSE abud==+1 FI
  OD

  PrintF("  Numbers: %I%E",MAXNUM)
  PrintF("Deficient: %I%E",def)
  PrintF("  Perfect: %I%E",perf)
  PrintF("  Abudant: %I%E",abud)
RETURN


#lang transd

MainModule : {
  txt:
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.",
  tabl: Table(),
  n: 0,
  colWidths: Vector<Int>(),

  print: (λ centered Bool(false)
    (for n in Seq(0 (num-rows tabl)) do
      (with row (get-row tabl n)
        (for m in Seq(0 (num-cols tabl)) do
          (with wid (+ 1.0 (get colWidths @idx))
                word (get row m) wl 0.0 lef 0
            (if centered  (= wl (size String(word))) (= lef (/ (- wid wl) 2.0))
              (textout width: lef "" width: wl word width: (- wid (+ wl lef)) "")
            else
              (textout width: wid (get row m)))))
        (lout ""))
    )
  ),

  _start: (λ
    (load-table tabl txt fieldSep: "$" :emptyEls)

    (for i in Seq(0 (num-cols tabl)) do (= n 0)
        (tsd-query tabl
             reduce: [i]
                 as: [[String()]]
              using: (λ (set n (max (size (get @row 0)) n))))
        (append colWidths n)
    )
    (textout :right "") (print)
    (lout :left "") (print)
    (lout "") (print true)
  )
}


with Ada.Text_IO, Generic_Divisors;

procedure ADB_Classification is
   function Same(P: Positive) return Positive is (P);
   package Divisor_Sum is new Generic_Divisors
     (Result_Type => Natural, None => 0, One => Same, Add =>  "+");

   type Class_Type is (Deficient, Perfect, Abundant);

   function Class(D_Sum, N: Natural) return Class_Type is
      (if D_Sum < N then Deficient
       elsif D_Sum = N then Perfect
       else Abundant);

   Cls: Class_Type;
   Results: array (Class_Type) of Natural := (others => 0);

   package NIO is new Ada.Text_IO.Integer_IO(Natural);
   package CIO is new Ada.Text_IO.Enumeration_IO(Class_Type);
begin
   for N in 1 .. 20_000 loop
      Cls := Class(Divisor_Sum.Process(N), N);
      Results(Cls) := Results(Cls)+1;
   end loop;
   for Class in Results'Range loop
      CIO.Put(Class, 12);
      NIO.Put(Results(Class), 8);
      Ada.Text_IO.New_Line;
   end loop;
   Ada.Text_IO.Put_Line("--------------------");
   Ada.Text_IO.Put("Sum         ");
   NIO.Put(Results(Deficient)+Results(Perfect)+Results(Abundant), 8);
   Ada.Text_IO.New_Line;
   Ada.Text_IO.Put_Line("====================");
end ADB_Classification;


BEGIN # classify the numbers 1 : 20 000 as abudant, deficient or perfect #
    INT abundant count    := 0;
    INT deficient count   := 0;
    INT perfect count     := 0;
    INT abundant example  := 0;
    INT deficient example := 0;
    INT perfect example   := 0;
    INT max number         = 20 000;
    # construct a table of the proper divisor sums                 #
    [ 1 : max number ]INT pds;
    pds[ 1 ] := 0;
    FOR i FROM 2 TO UPB pds DO pds[ i ] := 1 OD;
    FOR i FROM 2 TO UPB pds DO
        FOR j FROM i + i BY i TO UPB pds DO pds[ j ] +:= i OD
    OD;
    # classify the numbers                                         #
    FOR n TO max number DO
        IF     INT pd sum = pds[ n ];
               pd sum < n
        THEN
            # have a deficient number                              #
            deficient count    +:= 1;
            deficient example   := n
        ELIF   pd sum = n
        THEN
            # have a perfect number                                #
            perfect count      +:= 1;
            perfect example     := n
        ELSE # pd sum > n #
            # have an abundant number                              #
            abundant count     +:= 1;
            abundant example    := n
        FI
    OD;
    # displays the classification, count and example                   #
    PROC show result = ( STRING classification, INT count, example )VOID:
         print( ( "There are "
                , whole( count, -8 )
                , " "
                , classification
                , " numbers up to "
                , whole( max number, 0 )
                , " e.g.: "
                , whole( example, 0 )
                , newline
                )
              );

    # show how many of each type of number there are and an example    #
    show result( "abundant ",  abundant count,  abundant example  );
    show result( "deficient", deficient count, deficient example );
    show result( "perfect  ",   perfect count,   perfect example   )
END


INTEGER PROC FNBlockChangeColumnAlignLeftB( INTEGER columnTotalI, INTEGER spaceTotalI, INTEGER buffer1I )
 INTEGER B = FALSE
 INTEGER downB = TRUE
 INTEGER minI = 1
 INTEGER I = 0
 INTEGER J = 0
 INTEGER K = 0
 INTEGER L = 0
 INTEGER buffer2I = 0
 STRING s[255] = ""
 INTEGER wordRightB = FALSE
 STRING s1[255] = Query( WordSet )
 IF ( NOT ( IsBlockInCurrFile() ) ) Warn( "Please mark a block" ) B = FALSE RETURN( B ) ENDIF // return from the current procedure if no block is marked
 Set( BREAK, ON )
 PushPosition()
 PushBlock()
 Set( WordSet, ChrSet( "a-zA-Z0-9_,." ) )
 PushPosition()
 buffer2I = CreateTempBuffer()
 PopPosition()
 PushPosition()
 PushBlock()
 DO 100 TIMES
  AddLine( "", buffer2I )
 ENDDO
 PopBlock()
 PopPosition()
 GotoBlockBegin()
 I = minI - 1
 WHILE ( ( IsCursorInBlock() ) AND ( downB ) )
  IF NOT LFind( "^$", "cgx" )
   BegLine()
   REPEAT
    s = GetWord()
    IF NOT ( s == "" )
     s = Trim( s )
     I = I + 1
     IF ( I > columnTotalI )
      I = minI
     ENDIF
     J = Length( s )
     PushPosition()
     PushBlock()
     GotoBufferId( buffer2I )
     GotoLine( I )
     //
     IF ( CurrLineLen() == 0 )
      BegLine()
      InsertText( Format( Str( J ), " " ), _INSERT_ )
     ELSE
      K = Val( Trim( GetText( 1, MAXSTRINGLEN ) ) )
      IF ( J > K )
       BegLine()
       DelToEol()
       BegLine()
       InsertText( Str( J ), _INSERT_ )
      ENDIF
     ENDIF
     PopBlock()
     PopPosition()
     wordRightB = WordRight()
    ENDIF
   UNTIL ( s == "" ) OR ( NOT wordRightB )
  ENDIF
  downB = Down()
 ENDWHILE
 GotoBlockBegin()
 I = minI - 1
 L = 1
 K = 1
 WHILE ( ( IsCursorInBlock() ) AND ( downB ) )
  IF NOT LFind( "^$", "cgx" )
   BegLine()
   REPEAT
    B = FALSE
    s = GetWord()
    IF NOT ( s == "" )
     s = Trim( s )
     I = I + 1
     IF ( I > columnTotalI )
      I = minI
      K = 1
      L = L + 1
     ENDIF
     //
     PushPosition()
     PushBlock()
     GotoBufferId( buffer2I )
     GotoLine( I )
     J = Val( Trim( GetText( 1, MAXSTRINGLEN ) ) )
     PopPosition()
     PopBlock()
     PushPosition()
     PushBlock()
     GotoBufferId( buffer1I )
     GotoLine( L )
     GotoColumn( K )
     InsertText( s, _INSERT_ )
     K = K + J + spaceTotalI
     PopBlock()
     PopPosition()
     wordRightB = WordRight()
    ENDIF
   UNTIL ( s == "" ) OR ( NOT wordRightB )
  ENDIF
  AddLine( "", buffer1I )
  downB = Down()
 ENDWHILE
 OneWindow()
 VWindow()
 GotoWindow( 1 )
 GotoBufferId( buffer2I )
 GotoWindow( 2 )
 GotoBufferId( buffer1I )
 B = TRUE
 Set( WordSet, s1 )
 PopPosition()
 PopBlock()
 RETURN( B )
END
//
PROC Main()
 STRING s1[255] = "12" // change this
 STRING s2[255] = "2" // change this
 INTEGER bufferI = 0
 PushPosition()
 bufferI = CreateTempBuffer()
 PopPosition()
 IF ( NOT ( Ask( "block: change: column: align: left: columnTotalI = ", s1, _EDIT_HISTORY_ ) ) AND ( Length( s1 ) > 0 ) ) RETURN() ENDIF
 IF ( NOT ( Ask( "block: change: column: align: left: spaceTotalI = ", s2, _EDIT_HISTORY_ ) ) AND ( Length( s2 ) > 0 ) ) RETURN() ENDIF
 Message( FNBlockChangeColumnAlignLeftB( Val( s1 ), Val( s2 ), bufferI ) ) // gives e.g. TRUE
 GotoBufferId( bufferI )
END


$$ MODE TUSCRIPT
MODE DATA
$$ SET exampletext=*
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
$$ MODE TUSCRIPT
SET nix=SPLIT (exampletext,":$:",c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12)
LOOP l1=1,12
SET colum=CONCAT ("c",l1)
SET newcolum=CONCAT ("new",l1)
SET @newcolum="", length=MAX LENGTH (@colum), space=length+2
 LOOP n,[email protected]
 SET newcell=CENTER (l2,space)
 SET @newcolum=APPEND (@newcolum,"~",newcell)
 ENDLOOP
 SET @newcolum=SPLIT  (@newcolum,":~:")
ENDLOOP
SET exampletext=JOIN(new1,"$",new2,new3,new4,new5,new6,new7,new8,new9,new10,new11,new12)


begin % count abundant, perfect and deficient numbers up to 20 000        %
    integer MAX_NUMBER;
    MAX_NUMBER := 20000;
    begin
        integer array pds ( 1 :: MAX_NUMBER );
        integer aCount, dCount, pCount, dSum;
        % construct a table of proper divisor sums                        %
        pds( 1 ) := 0;
        for i := 2 until MAX_NUMBER do pds( i ) := 1;
        for i := 2 until MAX_NUMBER do begin
            for j := i + i step i until MAX_NUMBER do pds( j ) := pds( j ) + i
        end for_i ;
        aCount := dCount := pCOunt := 0;
        for i := 1 until 20000 do begin
            dSum := pds( i );
            if      dSum > i then aCount := aCount + 1
            else if dSum < i then dCount := dCOunt + 1
            else %  dSum = i    % pCount := pCount + 1
        end for_i ;
        write( "Abundant  numbers up to 20 000: ", aCount );
        write( "Perfect   numbers up to 20 000: ", pCount );
        write( "Deficient numbers up to 20 000: ", dCount )
    end
end.


on aliquotSum(n)
    if (n < 2) then return 0
    set sum to 1
    set sqrt to n ^ 0.5
    set limit to sqrt div 1
    if (limit = sqrt) then
        set sum to sum + limit
        set limit to limit - 1
    end if
    repeat with i from 2 to limit
        if (n mod i is 0) then set sum to sum + i + n div i
    end repeat

    return sum
end aliquotSum

on task()
    set {deficient, perfect, abundant} to {0, 0, 0}
    repeat with n from 1 to 20000
        set s to aliquotSum(n)
        if (s < n) then
            set deficient to deficient + 1
        else if (s > n) then
            set abundant to abundant + 1
        else
            set perfect to perfect + 1
        end if
    end repeat

    return {deficient:deficient, perfect:perfect, abundant:abundant}
end task

task()


@(collect)
@  (coll)@{item /[^$]+/}@(end)
@(end)
@; nc = number of columns
@; pi = padded items (data with row lengths equalized with empty strings)
@; cw = vector of max column widths
@; ce = center padding
@(bind nc @[apply max [mapcar length item]])
@(bind pi @(mapcar (op append @1 (repeat '("") (- nc (length @1)))) item))
@(bind cw @(vector-list
             (mapcar (op apply max [mapcar length @1])
                     ;; matrix transpose trick cols become rows:
                     [apply mapcar [cons list pi]])))
@(bind ns "")
@(output)
@  (repeat)
@    (rep :counter i)@{pi @[cw i]} @(end)
@  (end)
@  (repeat)
@    (rep :counter i)@{pi @(- [cw i])} @(end)
@  (end)
@  (repeat)
@    (rep :counter i)@\
     @{ns @(trunc (- [cw i] (length pi)) 2)}@\
     @{pi @(- [cw i] (trunc (- [cw i] (length pi)) 2))} @(end)
@  (end)
@(end)


cat <<EOF_OUTER > just-nocenter.sh
#!/bin/sh

td() {
cat <<'EOF'
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
EOF
}

rows=$( td | wc -l )

# get the number of fields
fields=$(td | rs -c'$' -g1 -h | awk '{print $2}')

# get the max of the value widths
cwidth=$(td | rs -c'$' -g1 -w1 2>/dev/null | awk 'BEGIN{w=0}{if(length>w){w=length}}END{print w}')

# compute the minimum line width for the columns
lwidth=$(( (1 + cwidth) * fields ))

# left adjusted columns
td | rs -c'$' -g1 -zn -w$lwidth

echo ""

# right adjusted columns
td | rs -c'$' -g1 -znj -w$lwidth

echo ""

exit
EOF_OUTER


/* ARM assembly Raspberry PI  */
/* program numberClassif.s   */

 /* REMARK 1 : this program use routines in a include file
   see task Include a file language arm assembly
   for the routine affichageMess conversion10
   see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

.equ NBDIVISORS,             1000

/*******************************************/
/* Initialized data                        */
/*******************************************/
.data
szMessStartPgm:          .asciz "Program start \n"
szMessEndPgm:            .asciz "Program normal end.\n"
szMessErrorArea:         .asciz "\033[31mError : area divisors too small.\n"
szMessError:             .asciz "\033[31mError  !!!\n"
szMessErrGen:            .asciz "Error end program.\n"
szMessNbPrem:            .asciz "This number is prime !!!.\n"
szMessResultFact:        .asciz "@ "

szCarriageReturn:        .asciz "\n"

/* datas message display */
szMessResult:            .asciz "Number déficients : @ perfects : @ abundants : @ \n"

/*******************************************/
/* UnInitialized data                      */
/*******************************************/
.bss
.align 4
sZoneConv:               .skip 24
tbZoneDecom:             .skip 4 * NBDIVISORS       // facteur 4 octets
/*******************************************/
/*  code section                           */
/*******************************************/
.text
.global main
main:                               @ program start
    ldr r0,iAdrszMessStartPgm       @ display start message
    bl affichageMess

    mov r4,#1
    mov r3,#0
    mov r6,#0
    mov r7,#0
    mov r8,#0
    ldr r9,iNBMAX
1:
    mov r0,r4                       @  number
    //=================================
    ldr r1,iAdrtbZoneDecom
    bl decompFact                @ create area of divisors
    cmp r0,#0                    @ error ?
    blt 2f
    lsl r5,r4,#1                 @ number * 2
    cmp r5,r1                    @ compare number and sum
    addeq r7,r7,#1               @ perfect
    addgt r6,r6,#1               @ deficient
    addlt r8,r8,#1               @ abundant

2:
    add r4,r4,#1
    cmp r4,r9
    ble 1b

    //================================

    mov r0,r6                        @ deficient
    ldr r1,iAdrsZoneConv
    bl conversion10                  @ convert ascii string
    ldr r0,iAdrszMessResult
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc               @ and put in message
    mov r5,r0
    mov r0,r7                        @ perfect
    ldr r1,iAdrsZoneConv
    bl conversion10                  @ convert ascii string
    mov r0,r5
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc               @ and put in message
    mov r5,r0
    mov r0,r8                        @ abundant
    ldr r1,iAdrsZoneConv
    bl conversion10                  @ convert ascii string
    mov r0,r5
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc               @ and put in message
    bl affichageMess

    ldr r0,iAdrszMessEndPgm         @ display end message
    bl affichageMess
    b 100f
99:                                 @ display error message
    ldr r0,iAdrszMessError
    bl affichageMess
100:                                @ standard end of the program
    mov r0, #0                      @ return code
    mov r7, #EXIT                   @ request to exit program
    svc 0                           @ perform system call
iAdrszMessStartPgm:        .int szMessStartPgm
iAdrszMessEndPgm:          .int szMessEndPgm
iAdrszMessError:           .int szMessError
iAdrszCarriageReturn:      .int szCarriageReturn
iAdrtbZoneDecom:           .int tbZoneDecom

iAdrszMessResult:          .int szMessResult
iAdrsZoneConv:             .int sZoneConv

iNBMAX:                    .int 20000

/******************************************************************/
/*     factor decomposition                                               */
/******************************************************************/
/* r0 contains number */
/* r1 contains address of divisors area */
/* r0 return divisors items in table */
/* r1 return the sum of divisors  */
decompFact:
    push {r3-r12,lr}              @ save  registers
    cmp r0,#1
    moveq r1,#1
    beq 100f
    mov r5,r1
    mov r8,r0                    @ save number
    bl isPrime                   @ prime ?
    cmp r0,#1
    beq 98f                      @ yes is prime
    mov r1,#1
    str r1,[r5]                  @ first factor
    mov r12,#1                   @ divisors sum
    mov r10,#1                   @ indice divisors table
    mov r9,#2                    @ first divisor
    mov r6,#0                    @ previous divisor
    mov r7,#0                    @ number of same divisors

    /*  division loop  */
2:
    mov r0,r8                    @ dividende
    mov r1,r9                    @ divisor
    bl division                  @ r2 quotient r3 remainder
    cmp r3,#0
    beq 3f                       @ if remainder  zero  ->  divisor

        /* not divisor -> increment next divisor */
    cmp r9,#2                    @ if divisor = 2 -> add 1
    addeq r9,#1
    addne r9,#2                  @ else add 2
    b 2b

       /* divisor   compute the new factors of number */
3:
    mov r8,r2                    @ else quotient -> new dividende
    cmp r9,r6                    @ same divisor ?
    beq 4f                       @ yes

    mov r0,r5                    @ table address
    mov r1,r10                   @ number factors in table
    mov r2,r9                    @ divisor
    mov r3,r12                   @ somme
    mov r4,#0
    bl computeFactors
    mov r10,r1
    mov r12,r0
    mov r6,r9                    @ new divisor
    b 7f

4:                               @ same divisor
    sub r7,r10,#1
5:                              @ search in table the first use of divisor
    ldr r3,[r5,r7,lsl #2 ]
    cmp r3,r9
    subne r7,#1
    bne 5b
                                 @ and compute new factors after factors
    sub r4,r10,r7                @ start indice
    mov r0,r5
    mov r1,r10
    mov r2,r9                    @ divisor
    mov r3,r12
    bl computeFactors
    mov r12,r0
    mov r10,r1

    /* divisor -> test if new dividende is prime */
7:
    cmp r8,#1                    @ dividende = 1 ? -> end
    beq 10f
    mov r0,r8                    @ new dividende is prime ?
    mov r1,#0
    bl isPrime                   @ the new dividende is prime ?
    cmp r0,#1
    bne 10f                      @ the new dividende is not prime

    cmp r8,r6                    @ else dividende is same divisor ?
    beq 8f                       @ yes

    mov r0,r5
    mov r1,r10
    mov r2,r8
    mov r3,r12
    mov r4,#0
    bl computeFactors
    mov r12,r0
    mov r10,r1
    mov r7,#0
    b 11f
8:
    sub r7,r10,#1
9:
    ldr r3,[r5,r7,lsl #2 ]
    cmp r3,r8
    subne r7,#1
    bne 9b

    mov r0,r5
    mov r1,r10
    sub r4,r10,r7
    mov r2,r8
    mov r3,r12
    bl computeFactors
    mov r12,r0
    mov r10,r1

    b 11f

10:
    cmp r9,r8                    @ current divisor  > new dividende ?
    ble 2b                       @ no -> loop

    /* end decomposition */
11:
    mov r0,r10                  @ return number of table items
    mov r1,r12                  @ return sum
    mov r3,#0
    str r3,[r5,r10,lsl #2]      @ store zéro in last table item
    b 100f

98:                             @ prime number
    //ldr r0,iAdrszMessNbPrem
    //bl   affichageMess
    add r1,r8,#1
    mov r0,#0                   @ return code
    b 100f
99:
    ldr r0,iAdrszMessError
    bl   affichageMess
    mov r0,#-1                  @ error code
    b 100f
100:
    pop {r3-r12,lr}             @ restaur registers
    bx lr
iAdrszMessNbPrem:           .int szMessNbPrem

/*   r0 table factors address */
/*   r1 number factors in table */
/*   r2 new divisor */
/*   r3 sum  */
/*   r4 start indice */
/*   r0 return sum */
/*   r1 return number factors in table */
computeFactors:
    push {r2-r6,lr}              @ save registers
    mov r6,r1                    @ number factors in table
1:
    ldr r5,[r0,r4,lsl #2 ]       @ load one factor
    mul r5,r2,r5                 @ multiply
    str r5,[r0,r1,lsl #2]        @ and store in the table

    add r3,r5
    add r1,r1,#1                 @ and increment counter
    add r4,r4,#1
    cmp r4,r6
    blt 1b
    mov r0,r3
100:                             @ fin standard de la fonction
    pop {r2-r6,lr}               @ restaur des registres
    bx lr                        @ retour de la fonction en utilisant lr
/***************************************************/
/*   check if a number is prime              */
/***************************************************/
/* r0 contains the number            */
/* r0 return 1 if prime  0 else */
@2147483647
@4294967297
@131071
isPrime:
    push {r1-r6,lr}    @ save registers
    cmp r0,#0
    beq 90f
    cmp r0,#17
    bhi 1f
    cmp r0,#3
    bls 80f            @ for 1,2,3 return prime
    cmp r0,#5
    beq 80f            @ for 5 return prime
    cmp r0,#7
    beq 80f            @ for 7 return prime
    cmp r0,#11
    beq 80f            @ for 11 return prime
    cmp r0,#13
    beq 80f            @ for 13 return prime
    cmp r0,#17
    beq 80f            @ for 17 return prime
1:
    tst r0,#1          @ even ?
    beq 90f            @ yes -> not prime
    mov r2,r0          @ save number
    sub r1,r0,#1       @ exposant n - 1
    mov r0,#3          @ base
    bl moduloPuR32     @ compute base power n - 1 modulo n
    cmp r0,#1
    bne 90f            @ if <> 1  -> not prime

    mov r0,#5
    bl moduloPuR32
    cmp r0,#1
    bne 90f

    mov r0,#7
    bl moduloPuR32
    cmp r0,#1
    bne 90f

    mov r0,#11
    bl moduloPuR32
    cmp r0,#1
    bne 90f

    mov r0,#13
    bl moduloPuR32
    cmp r0,#1
    bne 90f

    mov r0,#17
    bl moduloPuR32
    cmp r0,#1
    bne 90f
80:
    mov r0,#1        @ is prime
    b 100f
90:
    mov r0,#0        @ no prime
100:                 @ fin standard de la fonction
    pop {r1-r6,lr}   @ restaur des registres
    bx lr            @ retour de la fonction en utilisant lr
/********************************************************/
/*   Calcul modulo de b puissance e modulo m  */
/*    Exemple 4 puissance 13 modulo 497 = 445         */
/*                                             */
/********************************************************/
/* r0  nombre  */
/* r1 exposant */
/* r2 modulo   */
/* r0 return result  */
moduloPuR32:
    push {r1-r7,lr}    @ save registers
    cmp r0,#0          @ verif <> zero
    beq 100f
    cmp r2,#0          @ verif <> zero
    beq 100f           @ TODO: v鲩fier les cas d erreur
1:
    mov r4,r2          @ save modulo
    mov r5,r1          @ save exposant
    mov r6,r0          @ save base
    mov r3,#1          @ start result

    mov r1,#0          @ division de r0,r1 par r2
    bl division32R
    mov r6,r2          @ base <- remainder
2:
    tst r5,#1          @  exposant even or odd
    beq 3f
    umull r0,r1,r6,r3
    mov r2,r4
    bl division32R
    mov r3,r2          @ result <- remainder
3:
    umull r0,r1,r6,r6
    mov r2,r4
    bl division32R
    mov r6,r2          @ base <- remainder

    lsr r5,#1          @ left shift 1 bit
    cmp r5,#0          @ end ?
    bne 2b
    mov r0,r3
100:                   @ fin standard de la fonction
    pop {r1-r7,lr}     @ restaur des registres
    bx lr              @ retour de la fonction en utilisant lr

/***************************************************/
/*   division number 64 bits in 2 registers by number 32 bits */
/***************************************************/
/* r0 contains lower part dividende   */
/* r1 contains upper part dividende   */
/* r2 contains divisor   */
/* r0 return lower part quotient    */
/* r1 return upper part quotient    */
/* r2 return remainder               */
division32R:
    push {r3-r9,lr}    @ save registers
    mov r6,#0          @ init upper upper part remainder  !!
    mov r7,r1          @ init upper part remainder with upper part dividende
    mov r8,r0          @ init lower part remainder with lower part dividende
    mov r9,#0          @ upper part quotient
    mov r4,#0          @ lower part quotient
    mov r5,#32         @ bits number
1:                     @ begin loop
    lsl r6,#1          @ shift upper upper part remainder
    lsls r7,#1         @ shift upper  part remainder
    orrcs r6,#1
    lsls r8,#1         @ shift lower  part remainder
    orrcs r7,#1
    lsls r4,#1         @ shift lower part quotient
    lsl r9,#1          @ shift upper part quotient
    orrcs r9,#1
                       @ divisor sustract  upper  part remainder
    subs r7,r2
    sbcs  r6,#0        @ and substract carry
    bmi 2f             @ n駡tive ?

                       @ positive or equal
    orr r4,#1          @ 1 -> right bit quotient
    b 3f
2:                     @ negative
    orr r4,#0          @ 0 -> right bit quotient
    adds r7,r2         @ and restaur remainder
    adc  r6,#0
3:
    subs r5,#1         @ decrement bit size
    bgt 1b             @ end ?
    mov r0,r4          @ lower part quotient
    mov r1,r9          @ upper part quotient
    mov r2,r7          @ remainder
100:                   @ function end
    pop {r3-r9,lr}     @ restaur registers
    bx lr

/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"


#import std

text =

-[Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.]-

pad = sep`$*; @FS ~&rSSSK7+ (zipp` ^*D\~& leql$^)*rSSK7+ zipp0^*D/leql$^ ~&

just_left   = mat` *+ pad
just_right  = mat` *+ pad; ==` ~-rlT**
just_center = mat` *+ pad; ==` ~-rK30PlrK31PTT**

#show+

main = mat0 <.just_left,just_center,just_right> text


Public Sub TestSplit(Optional align As String = "left", Optional spacing As Integer = 1)
  Dim word() As String
  Dim colwidth() As Integer
  Dim ncols As Integer
  Dim lines(6) As String
  Dim nlines As Integer

  'check arguments
  If Not (align = "left" Or align = "right" Or align = "center") Then
    MsgBox "TestSplit: wrong argument 'align': " & align
    Exit Sub
  End If
  If spacing < 0 Then
    MsgBox "TestSplit: wrong argument: 'spacing' cannot be negative."
    Exit Sub
  End If

  ' Sample Input (should be from a file)
  nlines = 6
  lines(1) = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
  lines(2) = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
  lines(3) = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
  lines(4) = "column$are$separated$by$at$least$one$space."
  lines(5) = "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
  lines(6) = "justified,$right$justified,$or$center$justified$within$its$column."

  'first pass: count columns and column widths
  'the words are not kept in memory
  ncols = -1
  For l = 1 To nlines
    word = Split(RTrim(lines(l)), "$")
    If UBound(word) > ncols Then
      ncols = UBound(word)
      ReDim Preserve colwidth(ncols)
    End If
    For i = 0 To UBound(word)
      If Len(word(i)) > colwidth(i) Then colwidth(i) = Len(word(i))
    Next i
  Next l

  'discard possibly empty columns at the right
  '(this assumes there is at least one non-empty column)
  While colwidth(ncols) = 0
    ncols = ncols - 1
  Wend

  'second pass: print in columns
  For l = 1 To nlines
    word = Split(RTrim(lines(l)), "$")
    For i = 0 To UBound(word)
      a = word(i)
      w = colwidth(i)
      If align = "left" Then
        Debug.Print a + String$(w - Len(a), " ");
      ElseIf align = "right" Then
        Debug.Print String$(w - Len(a), " ") + a;
      ElseIf align = "center" Then
        d = Int((w - Len(a)) / 2)
        Debug.Print String$(d, " ") + a + String$(w - (d + Len(a)), " ");
      End If
      If i < ncols Then Debug.Print Spc(spacing);
    Next i
    Debug.Print
  Next l
End Sub


properDivisors: function [n]->
    (factors n) -- n

abundant: new 0 deficient: new 0 perfect: new 0

loop 1..20000 'x [
    s: sum properDivisors x

    case [s]
        when? [<x] -> inc 'deficient
        when? [>x] -> inc 'abundant
        else       -> inc 'perfect
]

print ["Found" abundant "abundant,"
               deficient "deficient and"
               perfect "perfect numbers."]


Loop
{
    m := A_index
    ; getting factors=====================
    loop % floor(sqrt(m))
    {
        if ( mod(m, A_index) == "0" )
        {
            if ( A_index ** 2 == m )
            {
                list .= A_index . ":"
                sum := sum + A_index
                continue
            }
            if ( A_index != 1 )
            {
                list .= A_index . ":" . m//A_index . ":"
                sum := sum + A_index + m//A_index
            }
            if ( A_index == "1" )
            {
                list .= A_index . ":"
                sum := sum + A_index
            }
        }
    }
    ; Factors obtained above===============
    if ( sum == m ) && ( sum != 1 )
    {
        result := "perfect"
        perfect++
    }
    if ( sum > m )
    {
        result := "Abundant"
        Abundant++
    }
    if ( sum < m ) or ( m == "1" )
    {
        result := "Deficient"
        Deficient++
    }
    if ( m == 20000 )
    {
        MsgBox % "number: " . m . "`nFactors:`n" . list . "`nSum of Factors: " . Sum . "`nResult: " . result . "`n_______________________`nTotals up to: " . m . "`nPerfect: " . perfect . "`nAbundant: " . Abundant . "`nDeficient: " . Deficient
        ExitApp
    }
    list := ""
    sum := 0
}

esc::ExitApp


' Align columns - RC - VBScript
	Const nr=16, nc=16
	ReDim d(nc),t(nr), wor(nr,nc)
	i=i+1: t(i) = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
	i=i+1: t(i) = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
	i=i+1: t(i) = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
	i=i+1: t(i) = "column$are$separated$by$at$least$one$space."
	i=i+1: t(i) = "Further,$allow$for$each$word$in$a$column$To$be$either$left$"
	i=i+1: t(i) = "justified,$right$justified,$or$center$justified$within$its$column."
	For r=1 to nr
		If t(r)="" Then Exit For
		w=xRTrim(t(r),"$")
		m=Split(w,"$")
		For c=1 To UBound(m)+1
			wor(r,c)=m(c-1)
			If Len(wor(r,c))>d(c) Then d(c)=Len(wor(r,c))
		Next 'c
		If c>cols Then cols=c
	Next 'r
	rows=r-1
	tt=Array("Left","Right","Center")
	For n=1 To 3
		Wscript.Echo
		Wscript.Echo "*****" & tt(n-1) & "*****"
		For r=1 To rows
			w=""
			For c=1 To cols
				x=wor(r,c): s=Space(d(c))
				Select Case n
					Case 1: w=w &" "& Left   (x & s,d(c))
					Case 2: w=w &" "& Right  (s & x,d(c))
					Case 3: w=w &" "& xCentre(x,d(c)," ")
				End Select 'n
			Next 'c
			Wscript.Echo Mid(w,2)
		Next 'r
	Next 'n

Function xCentre(c, n, Pad)
    Dim j
    If n > Len(c) Then
		j = (n - Len(c)) \  2
		If (n - Len(c)) Mod 2 <> 0 Then j = j + 1
		xCentre = Mid(String(j, Pad) & c & String(j, Pad), 1, n)
    Else
		xCentre = c
    End If
End Function 'xCentre

Function xRTrim(c, Pad)
	Dim i2, l, cc
	cc = "": l = Len(c)
	If l > 0 Then
		i2 = l
		Do While (Mid(c, i2, 1) = Pad And i2 > 1)
			i2 = i2 - 1
		Loop
		If i2 = 1 And Mid(c, i2, 1) = Pad Then i2 = 0
		If i2 > 0 Then cc = Mid(c, 1, i2)
	End If
	xRTrim = cc
End Function 'xRTrim


#!/bin/gawk -f
function sumprop(num,   i,sum,root) {
if (num == 1) return 0
sum=1
root=sqrt(num)
for ( i=2; i < root; i++) {
    if (num % i == 0 )
    {
    sum = sum + i + num/i
    }
    }
if (num % root == 0)
   {
    sum = sum + root
   }
return sum
}

BEGIN{
limit = 20000
abundant = 0
defiecient =0
perfect = 0

for (j=1; j < limit+1; j++)
    {
    sump = sumprop(j)
    if (sump < j) deficient = deficient + 1
    if (sump == j) perfect = perfect + 1
    if (sump > j) abundant = abundant + 1
    }
print "For 1 through " limit
print "Perfect: " perfect
print "Abundant: " abundant
print "Deficient: " deficient
}


@echo off
setlocal enabledelayedexpansion

:_main

for /l %%i in (1,1,20000) do (

  echo Processing %%i

  call:_P %%i
  set Pn=!errorlevel!
  if !Pn! lss %%i set /a deficient+=1
  if !Pn!==%%i set /a perfect+=1
  if !Pn! gtr %%i set /a abundant+=1
  cls
)

echo Deficient - %deficient% ^| Perfect - %perfect% ^| Abundant - %abundant%
pause>nul

:_P
setlocal enabledelayedexpansion
set sumdivisers=0

set /a upperlimit=%1-1

for /l %%i in (1,1,%upperlimit%) do (
  set /a isdiviser=%1 %% %%i
  if !isdiviser!==0 set /a sumdivisers+=%%i
)

exit /b %sumdivisers%


RS(10, "$")		// Field separator
#11 = 1			// Align: 1 = left, 2 = center, 3 = right

// Reset column widths. Max 50 columns
for (#1=40; #1<90; #1++) { #@1 = 0 }

// Find max width of each column
BOF
Repeat(ALL) {
    for (#1=40; #1<90; #1++) {
        Match(@10, ADVANCE)			// skip field separator if any
	#2 = Cur_Pos
	Search("|{|@(10),|N}", NOERR)		// field separator or end of line
	#3 = Cur_Pos - #2			// width of text
	if (#3 > #@1) { #@1 = #3 }
	if (At_EOL) { Break }
    }
    Line(1, ERRBREAK)
}

// Convert lines
BOF
Repeat(ALL) {
    for (#1=40; #1<90; #1++) {
	#2 = Cur_Pos
	Search("|{|@(10),|N}", NOERR)
	if (At_EOL==0) { Del_Char(Chars_Matched) }
	#3 = #@1 - Cur_Pos + #2			// number of spaces to insert
	#4 = 0
	if (#11 == 2) { #4 = #3/2; #3 -= #4 }	// Center
	if (#11 == 3) { #4 = #3;   #3 = 0 }	// Right justify
	Set_Marker(1, Cur_Pos)
	Goto_Pos(#2)
	Ins_Char(' ', COUNT, #4)		// add spaces before the word
	Goto_Pos(Marker(1))
	Ins_Char(' ', COUNT, #3+1)		// add spaces after the word
	if (At_EOL) { Break }
    }
    Line(1, ERRBREAK)
}


10 DEFINT A-Z: LM=20000
20 DIM P(LM)
30 FOR I=1 TO LM: P(I)=-32767: NEXT
40 FOR I=1 TO LM/2: FOR J=I+I TO LM STEP I: P(J)=P(J)+I: NEXT: NEXT
50 FOR I=1 TO LM
60 X=I-32767
70 IF P(I)<X THEN D=D+1 ELSE IF P(I)=X THEN P=P+1 ELSE A=A+1
80 NEXT
90 PRINT "DEFICIENT:";D
100 PRINT "PERFECT:";P
110 PRINT "ABUNDANT:";A


get "libhdr"
manifest $( maximum = 20000 $)

let calcpdivs(p, max) be
$(  for i=0 to max do p!i := 0
    for i=1 to max/2
    $(  let j = i+i
        while 0 < j <= max
        $(  p!j := p!j + i
            j := j + i
        $)
    $)
$)

let classify(p, n, def, per, ab) be
$(  let z = 0<=p!n<n -> def, p!n=n -> per, ab
    !z := !z + 1
$)

let start() be
$(  let p = getvec(maximum)
    let def, per, ab = 0, 0, 0

    calcpdivs(p, maximum)
    for i=1 to maximum do classify(p, i, @def, @per, @ab)

    writef("Deficient numbers: %N*N", def)
    writef("Perfect numbers: %N*N", per)
    writef("Abundant numbers: %N*N", ab)
    freevec(p)
$)


Sub AlignCols(Lines, Optional Align As AlignmentConstants, Optional Sep$ = "$", Optional Sp% = 1)
Dim i&, j&, D&, L&, R&: ReDim W(UBound(Lines)): ReDim C&(0)

  For j = 0 To UBound(W)
    W(j) = Split(Lines(j), Sep)
    If UBound(W(j)) > UBound(C) Then ReDim Preserve C(UBound(W(j)))
    For i = 0 To UBound(W(j)): If Len(W(j)(i)) > C(i) Then C(i) = Len(W(j)(i))
  Next i, j

  For j = 0 To UBound(W): For i = 0 To UBound(W(j))
    D = C(i) - Len(W(j)(i))
    L = Choose(Align + 1, 0, D, D \ 2)
    R = Choose(Align + 1, D, 0, D - L) + Sp
    Debug.Print Space(L); W(j)(i); Space(R); IIf(i < UBound(W(j)), "", vbLf);
  Next i, j
End Sub


Module Module1
    Private Delegate Function Justification(s As String, width As Integer) As String

    Private Function AlignColumns(lines As String(), justification As Justification) As String()
        Const Separator As Char = "$"c
        ' build input container table and calculate columns count
        Dim containerTbl As String()() = New String(lines.Length - 1)() {}
        Dim columns As Integer = 0
        For i As Integer = 0 To lines.Length - 1
            Dim row As String() = lines(i).TrimEnd(Separator).Split(Separator)
            If columns < row.Length Then
                columns = row.Length
            End If
            containerTbl(i) = row
        Next
        ' create formatted container table
        Dim formattedTable As String()() = New String(containerTbl.Length - 1)() {}
        For i As Integer = 0 To formattedTable.Length - 1
            formattedTable(i) = New String(columns - 1) {}
        Next
        For j As Integer = 0 To columns - 1
            ' get max column width
            Dim columnWidth As Integer = 0
            For i As Integer = 0 To containerTbl.Length - 1
                If j < containerTbl(i).Length AndAlso columnWidth < containerTbl(i)(j).Length Then
                    columnWidth = containerTbl(i)(j).Length
                End If
            Next
            ' justify column cells
            For i As Integer = 0 To formattedTable.Length - 1
                If j < containerTbl(i).Length Then
                    formattedTable(i)(j) = justification(containerTbl(i)(j), columnWidth)
                Else
                    formattedTable(i)(j) = New [String](" "c, columnWidth)
                End If
            Next
        Next
        ' create result
        Dim result As String() = New String(formattedTable.Length - 1) {}
        For i As Integer = 0 To result.Length - 1
            result(i) = [String].Join(" ", formattedTable(i))
        Next
        Return result
    End Function

    Private Function JustifyLeft(s As String, width As Integer) As String
        Return s.PadRight(width)
    End Function
    Private Function JustifyRight(s As String, width As Integer) As String
        Return s.PadLeft(width)
    End Function
    Private Function JustifyCenter(s As String, width As Integer) As String
        Return s.PadLeft((width + s.Length) / 2).PadRight(width)
    End Function

    Sub Main()
        Dim input As String() = {"Given$a$text$file$of$many$lines,$where$fields$within$a$line$", "are$delineated$by$a$single$'dollar'$character,$write$a$program", "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$", "column$are$separated$by$at$least$one$space.", "Further,$allow$for$each$word$in$a$column$to$be$either$left$", "justified,$right$justified,$or$center$justified$within$its$column."}

        For Each line As String In AlignColumns(input, AddressOf JustifyLeft)
            Console.WriteLine(line)
        Next
        Console.ReadLine()
    End Sub

End Module


( clk$:?t0
& ( multiples
  =   prime multiplicity
    .     !arg:(?prime.?multiplicity)
        & !multiplicity:0
        & 1
      |   !prime^!multiplicity*(.!multiplicity)
        + multiples$(!prime.-1+!multiplicity)
  )
& ( P
  =   primeFactors prime exp poly S
    .   !arg^1/67:?primeFactors
      & ( !primeFactors:?^1/67&0
        |   1:?poly
          &   whl
            ' ( !primeFactors:%?prime^?exp*?primeFactors
              & !poly*multiples$(!prime.67*!exp):?poly
              )
          & -1+!poly+1:?poly
          & 1:?S
          & (   !poly
              :   ?
                + (#%@?s*?&!S+!s:?S&~)
                + ?
            | 1/2*!S
            )
        )
  )
& 0:?deficient:?perfect:?abundant
& 0:?n
&   whl
  ' ( 1+!n:~>20000:?n
    &   P$!n
      : ( <!n&1+!deficient:?deficient
        | !n&1+!perfect:?perfect
        | >!n&1+!abundant:?abundant
        )
    )
& out$(deficient !deficient perfect !perfect abundant !abundant)
& clk$:?t1
& out$(flt$(!t1+-1*!t0,2) sec)
& clk$:?t2
& ( P
  =   f h S
    .   0:?f
      & 0:?S
      &   whl
        ' ( 1+!f:?f
          & !f^2:~>!n
          & (   !arg*!f^-1:~/:?g
              & !S+!f:?S
              & ( !g:~!f&!S+!g:?S
                |
                )
            |
            )
          )
      & 1/2*!S
  )
& 0:?deficient:?perfect:?abundant
& 0:?n
&   whl
  ' ( 1+!n:~>20000:?n
    &   P$!n
      : ( <!n&1+!deficient:?deficient
        | !n&1+!perfect:?perfect
        | >!n&1+!abundant:?abundant
        )
    )
& out$(deficient !deficient perfect !perfect abundant !abundant)
& clk$:?t3
& out$(flt$(!t3+-1*!t2,2) sec)
);


#include<stdio.h>
#define de 0
#define pe 1
#define ab 2

int main(){
	int sum = 0, i, j;
	int try_max = 0;
	//1 is deficient by default and can add it deficient list
	int   count_list[3] = {1,0,0};
	for(i=2; i <= 20000; i++){
		//Set maximum to check for proper division
		try_max = i/2;
		//1 is in all proper division number
		sum = 1;
		for(j=2; j<try_max; j++){
			//Check for proper division
			if (i % j)
				continue; //Pass if not proper division
			//Set new maximum for divisibility check
			try_max = i/j;
			//Add j to sum
			sum += j;
			if (j != try_max)
				sum += try_max;
		}
		//Categorize summation
		if (sum < i){
			count_list[de]++;
			continue;
		}
		if (sum > i){
			count_list[ab]++;
			continue;
		}
		count_list[pe]++;
	}
	printf("\nThere are %d deficient," ,count_list[de]);
	printf(" %d perfect," ,count_list[pe]);
	printf(" %d abundant numbers between 1 and 20000.\n" ,count_list[ab]);
return 0;
}


const text = "Given\$a\$text\$file\$of\$many\$lines,\$where\$fields\$within\$a\$line\$
are\$delineated\$by\$a\$single\$'dollar'\$character,\$write\$a\$program
that\$aligns\$each\$column\$of\$fields\$by\$ensuring\$that\$words\$in\$each\$
column\$are\$separated\$by\$at\$least\$one\$space.
Further,\$allow\$for\$each\$word\$in\$a\$column\$to\$be\$either\$left\$
justified,\$right\$justified,\$or\$center\$justified\$within\$its\$column."

struct Formatter {
mut:
    text  [][]string
    width []int
}

fn new_formatter(text string) Formatter {
    mut f := Formatter{}
    for line in text.split_into_lines() {
        mut words := line.split("\$")
        for words[words.len-1] == "" {
            words = words[..words.len-1]
        }
        f.text << words
        for i, word in words {
            if i == f.width.len {
                f.width << word.len
            } else if word.len > f.width[i] {
                f.width[i] = word.len
            }
        }
    }
    return f
}

enum Justify {
    left = 0
    middle
    right
}

fn (f Formatter) print(j Justify) {
    for line in f.text {
        for i, word in line {
            match j {
                .left {
                    print('$word${' '.repeat(f.width[i]-word.len)} ')
                }
                .middle {
                    mut extra := 0
                    if (f.width[i]%2==1 && word.len%2==0) || (f.width[i]%2==0 && word.len%2==1) {
                        extra++
                    }
                    print('${' '.repeat((f.width[i]-word.len)/2)}$word${' '.repeat((f.width[i]-word.len)/2+extra)} ')
                }
                .right {
                    print('${' '.repeat(f.width[i]-word.len)}$word ')
                }
            }
        }
        println("")
    }
    println("")
}

fn main() {
    f := new_formatter(text)
    f.print(Justify.left)
    f.print(Justify.middle)
    f.print(Justify.right)
}


import "io" for File
import "/fmt" for Fmt

var LEFT = 0
var RIGHT = 1
var CENTER = 2
var justStrs = ["LEFT", "RIGHT", "CENTER"]

// Gets a list of lines in the file with each line split into fields.
var getLines = Fn.new { |fileName|
    var contents = File.read(fileName)
    var lines = contents.split("\n") // use "\r\n" on Windows
    for (i in 0...lines.count) {
        lines[i] = lines[i].trim().trimEnd("$")
        if (lines[i] == "") { // get rid of final blank line, if any
            lines = lines[0..-2]
            break
        }
        lines[i] = lines[i].split("$")
    }
    return lines
}

var alignCols = Fn.new { |lines, just|
    // find maximum number of columns
    var nCols = lines.reduce(0) { |acc, line| (line.count > acc) ? line.count : acc }
    // find maximum width for each column
    var maxWids = List.filled(nCols, 0)
    for (line in lines) {
        for (i in 0...line.count) {
            var width = line[i].count
            if (width > maxWids[i]) maxWids[i] = width
        }
    }
    System.print("With %(justStrs[just]) justification:")
    for (line in lines) {
        for (i in 0...line.count) {
            var width = maxWids[i] + 1
            if (just == LEFT) {
                System.write(Fmt.s(-width, line[i]))
            } else if (just == RIGHT) {
                System.write(Fmt.s(width, line[i]))
            } else if (just == CENTER) {
                System.write(Fmt.m(width, line[i]))
            }
        }
        System.print()
    }
    System.print()
}

var fileName = "align_cols.txt"
var lines = getLines.call(fileName)
for (i in 0..2) alignCols.call(lines, i)


using System;
using System.Linq;

public class Program
{
    public static void Main()
    {
        int abundant, deficient, perfect;
        var sw = System.Diagnostics.Stopwatch.StartNew();
        ClassifyNumbers.UsingSieve(20000, out abundant, out deficient, out perfect); sw.Stop();
        Console.WriteLine($"Abundant: {abundant}, Deficient: {deficient}, Perfect: {perfect}  {sw.Elapsed.TotalMilliseconds} ms");
        sw.Restart();
        ClassifyNumbers.UsingOptiDivision(20000, out abundant, out deficient, out perfect);
        Console.WriteLine($"Abundant: {abundant}, Deficient: {deficient}, Perfect: {perfect}  {sw.Elapsed.TotalMilliseconds} ms");
        sw.Restart();
        ClassifyNumbers.UsingDivision(20000, out abundant, out deficient, out perfect);
        Console.WriteLine($"Abundant: {abundant}, Deficient: {deficient}, Perfect: {perfect}  {sw.Elapsed.TotalMilliseconds} ms");
    }
}

public static class ClassifyNumbers
{
    //Fastest way, but uses memory
    public static void UsingSieve(int bound, out int abundant, out int deficient, out int perfect) {
        abundant = perfect = 0;
        //For very large bounds, this array can get big.
        int[] sum = new int[bound + 1];
        for (int divisor = 1; divisor <= bound >> 1; divisor++)
            for (int i = divisor << 1; i <= bound; i += divisor)
                sum[i] += divisor;
        for (int i = 1; i <= bound; i++) {
            if (sum[i] > i) abundant++;
            else if (sum[i] == i) perfect++;
        }
        deficient = bound - abundant - perfect;
    }

    //Slower, optimized, but doesn't use storage
    public static void UsingOptiDivision(int bound, out int abundant, out int deficient, out int perfect) {
        abundant = perfect = 0; int sum = 0;
        for (int i = 2, d, r = 1; i <= bound; i++) {
            if ((d = r * r - i) < 0) r++;
            for (int x = 2; x < r; x++) if (i % x == 0) sum += x + i / x;
            if (d == 0) sum += r;
            switch (sum.CompareTo(i)) { case 0: perfect++; break; case 1: abundant++; break; }
            sum = 1;
        }
        deficient = bound - abundant - perfect;
    }

    //Much slower, doesn't use storage and is un-optimized
    public static void UsingDivision(int bound, out int abundant, out int deficient, out int perfect) {
        abundant = perfect = 0;
        for (int i = 2; i <= bound; i++) {
            int sum = Enumerable.Range(1, (i + 1) / 2)
                .Where(div => i % div == 0).Sum();
            switch (sum.CompareTo(i)) {
                case 0: perfect++; break;
                case 1: abundant++; break;
            }
        }
        deficient = bound - abundant - perfect;
    }
}


theString$ = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
theString$ = theString$ + "are$delineated$by$a$single$'dollar'$character,$write$a$program"
theString$ = theString$ + "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
theString$ = theString$ + "column$are$separated$by$at$least$one$space."
theString$ = theString$ + "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
theString$ = theString$ + "justified,$right$justified,$or$center$justified$within$its$column."

x = shoTable(theString$, "left", 6)
x = shoTable(theString$, "right", 6)
x = shoTable(theString$, "center", 6)
end

sub word$(sr$, wn, delim$)
    local i, j, n, sd, sl, sl2
    local s$, res$, d$

    d$ = delim$
    j = wn
    if j = 0  j = j+1
    res$ = "" : s$ = sr$
    if d$ = ""  d$ = " "
    sd = len(d$) : sl = len(s$)
    do
        n = instr(s$,d$)
        j = j - 1
        if j = 0 then
            if n = 0 then res$ = s$ else res$ = mid$(s$, 1, n-1) : fi
            return res$
        fi
        if n = 0  return res$
        if n = sl-sd then res$ = "" : return res$ : fi
        sl2 = sl-n
        s$ = mid$(s$, n+1, sl2)
        sl = sl2
    loop
    return res$
end sub

sub shoTable(theString$, align$, across)
    local i, a$, b$

    print "------------ align:", align$, " -- across:", across, " ------------"
    dim siz(across)
    b$ = "                                          "
    while word$(theString$, i+1, "$") <> ""
        siz(mod(i, across)) = max(siz(mod(i, across)), len(word$(theString$, i+1, "$")))
        i = i+1
    wend
    for i = 0 to across - 1
        siz(i) = siz(i)+1
        if siz(i) and 1   siz(i) = siz(i)+1
    next i

    i = 0
    a$ = word$(theString$, i+1, "$")
    while a$ <> ""
        s = siz(mod(i, across)) - len(a$)
        if align$ = "right"   a$ = left$(b$, s) + a$
        if align$ = "left"    a$ = a$ + left$(b$, s)
        if align$ = "center"  a$ = left$(b$, int(s / 2)) + a$ + left$(b$, int(s / 2) + (s and 1))
        print "|", a$;
        i  = i + 1
        if mod(i, across) = 0  print "|"
        a$ = word$(theString$, i+1, "$")
    wend
    print
end sub


fcn format(text,how){
   words:=text.split("$").apply("split").flatten();
   max:=words.reduce(fcn(p,n){ n=n.len(); n>p and n or p },0);
   wordsPerCol:=80/(max+1);
   fmt:=(switch(how){
      case(-1){ "%%-%ds ".fmt(max).fmt }
      case(0) { fcn(max,w){
            a:=(max-w.len())/2; b:=max-w.len() - a; String(" "*a,w," "*b);
         }.fp(max)
      }
      case(1){ "%%%ds ".fmt(max).fmt }
   });
   w:=words.walker(); d:=Data(0,Int);
   do{ w.pump(wordsPerCol,d,fmt).append("\n") } while(not w.atEnd);
   d.text;
}


#include <iostream>
#include <algorithm>
#include <vector>

std::vector<int> findProperDivisors ( int n ) {
   std::vector<int> divisors ;
   for ( int i = 1 ; i < n / 2 + 1 ; i++ ) {
      if ( n % i == 0 )
	 divisors.push_back( i ) ;
   }
   return divisors  ;
}

int main( ) {
   std::vector<int> deficients , perfects , abundants , divisors ;
   for ( int n = 1 ; n < 20001 ; n++ ) {
      divisors = findProperDivisors( n ) ;
      int sum = std::accumulate( divisors.begin( ) , divisors.end( ) , 0 ) ;
      if ( sum < n ) {
	 deficients.push_back( n ) ;
      }
      if ( sum == n ) {
	 perfects.push_back( n ) ;
      }
      if ( sum > n ) {
	 abundants.push_back( n ) ;
      }
   }
   std::cout << "Deficient : " << deficients.size( ) << std::endl ;
   std::cout << "Perfect   : " << perfects.size( ) << std::endl ;
   std::cout << "Abundant  : " << abundants.size( ) << std::endl ;
   return 0 ;
}


 5 BORDER 2
10 DATA 6
20 DATA "The$problem$of$Speccy$"
30 DATA "is$the$screen.$"
40 DATA "Need$adapt$text$sample$"
50 DATA "for$show$the$result$"
60 DATA "without$problem$,right?$"
70 DATA "But$see$the$code.$"
80 REM First find the maximum length of a 'word'
90 LET max=0: LET d$="$"
100 READ nlines
110 FOR l=1 TO nlines
120 READ t$
130 GO SUB 1000
150 NEXT l
155 LET s$="                                "( TO max)
160 REM Now display the aligned text:
170 LET m$="l": GO SUB 2000: PRINT
180 LET m$="r": GO SUB 2000: PRINT
190 LET m$="c": GO SUB 2000
200 STOP
1000 REM Maximum length of a word
1010 LET lt=LEN t$: LET p=1: LET lw=0
1020 FOR i=1 TO lt
1030 IF t$(i)=d$ THEN LET lw=i-p: LET p=i: IF lw>max THEN LET max=lw
1040 NEXT i
1050 RETURN
2000 REM Show aligned text
2010 RESTORE 20
2020 FOR l=1 TO nlines
2030 READ t$
2040 GO SUB 3000
2050 NEXT l
2060 RETURN
3000 REM Show words
3010 LET lt=LEN t$: LET p=1: LET lw=0
3020 FOR i=1 TO lt
3030 IF t$(i)<>d$ THEN GO TO 3090
3035 LET lw=i-p
3040 LET p$=t$(p TO i-1): LET p=i+1: LET z$=s$
3050 IF m$="l" THEN LET z$( TO lw)=p$
3060 IF m$="r" THEN LET z$(max-lw+1 TO )=p$
3070 IF m$="c" THEN LET z$((max/2)-(lw/2) TO )=p$
3080 PRINT z$;
3090 NEXT i
3095 PRINT
3100 RETURN


shared void run() {

	function divisors(Integer int) =>
			if(int <= 1) then {} else (1..int / 2).filter((Integer element) => element.divides(int));

	function classify(Integer int) => sum {0, *divisors(int)} <=> int;

	value counts = (1..20k).map(classify).frequencies();

	print("deficient: ``counts[smaller] else "none"``");
	print("perfect:   ``counts[equal] else "none"``");
	print("abundant:  ``counts[larger] else "none"``");
}


(defn pad-class
  [n]
  (let [divs (filter #(zero? (mod n %)) (range 1 n))
        divs-sum (reduce + divs)]
    (cond
      (< divs-sum n) :deficient
      (= divs-sum n) :perfect
      (> divs-sum n) :abundant)))

(def pad-classes (map pad-class (map inc (range))))

(defn count-classes
  [n]
  (let [classes (take n pad-classes)]
    {:perfect (count (filter #(= % :perfect) classes))
     :abundant (count (filter #(= % :abundant) classes))
     :deficient (count (filter #(= % :deficient) classes))}))


% Generate proper divisors from 1 to max
proper_divisors = proc (max: int) returns (array[int])
    divs: array[int] := array[int]$fill(1, max, 0)
    for i: int in int$from_to(1, max/2) do
        for j: int in int$from_to_by(i*2, max, i) do
            divs[j] := divs[j] + i
        end
    end
    return(divs)
end proper_divisors

% Classify all the numbers for which we have divisors
classify = proc (divs: array[int]) returns (int, int, int)
    def, per, ab: int
    def, per, ab := 0, 0, 0
    for i: int in array[int]$indexes(divs) do
        if     divs[i]<i then def := def + 1
        elseif divs[i]=i then per := per + 1
        elseif divs[i]>i then ab := ab + 1
        end
    end
    return(def, per, ab)
end classify

% Find amount of deficient, perfect, and abundant numbers up to 20000
start_up = proc ()
    max = 20000

    po: stream := stream$primary_output()

    def, per, ab: int := classify(proper_divisors(max))
    stream$putl(po, "Deficient: " || int$unparse(def))
    stream$putl(po, "Perfect:   " || int$unparse(per))
    stream$putl(po, "Abundant:  " || int$unparse(ab))
end start_up