-- demo\rosetta\Abelian_sandpile_model.exw
include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer

sequence board = {{0,0,0},
                  {0,0,0},
                  {0,0,0}}

procedure drop(integer y, x)
    sequence moves = {}
    while true do
        board[y,x] += 1
        if board[y,x]>=4 then
            board[y,x] -= 4
            moves &= {{y,x-1},{y,x+1},{y-1,x},{y+1,x}}
        end if
        -- extend board if rqd (maintain a border of zeroes)
        if x=1 then                             -- extend left
            for i=1 to length(board) do
                board[i] = prepend(board[i],0)
            end for
            for i=1 to length(moves) do
                moves[i][2] += 1
            end for
        elsif x=length(board[1]) then           -- extend right
            for i=1 to length(board) do
                board[i] = append(board[i],0)
            end for
        end if
        -- (copy the all-0 lines from the other end...)
        if y=1 then                             -- extend up
            board = prepend(board,board[$])
            for i=1 to length(moves) do
                moves[i][1] += 1
            end for
        elsif y=length(board) then              -- extend down
            board = append(board,board[1])
        end if
        if length(moves)=0 then exit end if
        {y,x} = moves[$]
        moves = moves[1..$-1]
    end while
    IupUpdate(canvas)
end procedure

function timer_cb(Ihandle /*ih*/)
    integer y = floor(length(board)/2)+1,
            x = floor(length(board[1])/2)+1
    drop(y,x)
    return IUP_DEFAULT
end function

function redraw_cb(Ihandle ih, integer /*posx*/, integer /*posy*/)
    IupGLMakeCurrent(ih)
    cdCanvasActivate(cddbuffer)
    cdCanvasClear(cddbuffer)
    for y=1 to length(board) do
        for x=1 to length(board[1]) do
            integer c = board[y][x]
            if c!=0 then
                integer colour = {CD_VIOLET,CD_RED,CD_BLUE}[c]
                cdCanvasPixel(cddbuffer, x, y, colour)
            end if
        end for
    end for
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
    IupGLMakeCurrent(ih)
    atom res = IupGetDouble(NULL, "SCREENDPI")/25.4
    cddbuffer = cdCreateCanvas(CD_GL, "300x100 %g", {res})
    cdCanvasSetBackground(cddbuffer, CD_PARCHMENT)
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()
    canvas = IupGLCanvas("RASTERSIZE=300x100")
    IupSetCallbacks({canvas}, {"ACTION", Icallback("redraw_cb"),
                               "MAP_CB", Icallback("map_cb")})
    dlg = IupDialog(canvas,"TITLE=\"Abelian sandpile model\"")
    IupShow(dlg)
    Ihandle timer = IupTimer(Icallback("timer_cb"), 10)
    IupMainLoop()
    IupClose()
end procedure

main()


PROGRAM EXAMPLE
  IMPLICIT NONE

  INTEGER :: i, j

  DO i = 0, 3
    DO j = 0, 6
       WRITE(*, "(I10)", ADVANCE="NO") Ackermann(i, j)
    END DO
    WRITE(*,*)
  END DO

CONTAINS

  RECURSIVE FUNCTION Ackermann(m, n) RESULT(ack)
    INTEGER :: ack, m, n

    IF (m == 0) THEN
      ack = n + 1
    ELSE IF (n == 0) THEN
      ack = Ackermann(m - 1, 1)
    ELSE
      ack = Ackermann(m - 1, Ackermann(m, n - 1))
    END IF
  END FUNCTION Ackermann

END PROGRAM EXAMPLE


abundant?: function [n]-> (2*n) < sum factors n

print "the first 25 abundant odd numbers:"
[i, found]: @[new 1, new 0]
while [found<25][
    if abundant? i [
        inc 'found
        print [i "=> sum:" sum factors i]
    ]
    'i + 2
]

[i, found]: @[new 1, new 0]
while [found<1000][
    if abundant? i [
        inc 'found
    ]
    'i + 2
]
print ["the 1000th abundant odd number:" i-2 "=> sum:" sum factors i-2]

i: new 1 + 10^9
while ø [
    if abundant? i [
        print ["the first abundant odd number greater than one billion (10^9):" i "=> sum:" sum factors i]
        break
    ]
    'i + 2
]


Abundant(num){
	sum := 0, str := ""
	for n, bool in proper_divisors(num)
		sum += n,  str .= (str?"+":"") n
	return sum > num ? str " = " sum : 0
}
proper_divisors(n) {
	Array := []
	if n = 1
		return Array
	Array[1] := true
	x := Floor(Sqrt(n))
	loop, % x+1
		if !Mod(n, i:=A_Index+1) && (floor(n/i) < n)
			Array[floor(n/i)] := true
	Loop % n/x
		if !Mod(n, i:=A_Index+1) && (i < n)
			Array[i] := true
	return Array
}


import numpy as np
import matplotlib.pyplot as plt

def iterate(grid):
    changed = False
    for ii, arr in enumerate(grid):
        for jj, val in enumerate(arr):
            if val > 3:
                grid[ii, jj] -= 4
                if ii > 0:
                    grid[ii - 1, jj] += 1
                if ii < len(grid)-1:
                    grid[ii + 1, jj] += 1
                if jj > 0:
                    grid[ii, jj - 1] += 1
                if jj < len(grid)-1:
                    grid[ii, jj + 1] += 1
                changed = True
    return grid, changed

def simulate(grid):
    while True:
        grid, changed = iterate(grid)
        if not changed:
            return grid

if __name__ == '__main__':
    start_grid = np.zeros((10, 10))
    start_grid[4:5, 4:5] = 64
    final_grid = simulate(start_grid.copy())
    plt.figure()
    plt.gray()
    plt.imshow(start_grid)
    plt.figure()
    plt.gray()
    plt.imshow(final_grid)


sub cleanup { print "\e[0m\e[?25h\n"; exit(0) }

signal(SIGINT).tap: { cleanup(); exit(0) }

unit sub MAIN ($stack = 1000, :$hide-progress = False );

my @color = "\e[38;2;0;0;0m█",
            "\e[38;2;255;0;0m█",
            "\e[38;2;255;255;0m█",
            "\e[38;2;0;0;255m█",
            "\e[38;2;255;255;255m█"
            ;

my ($h, $w) = qx/stty size/.words».Int;
my $buf = $w * $h;
my @buffer = 0 xx $buf;
my $done;

@buffer[$w * ($h div 2) + ($w div 2) - 1] = $stack;

print "\e[?25l\e[48;5;232m";

repeat {
    $done = True;
    loop (my int $row; $row < $h; $row = $row + 1) {
        my int $rs = $row * $w; # row start
        my int $re = $rs  + $w; # row end
        loop (my int $idx = $rs; $idx < $re; $idx = $idx + 1) {
            if @buffer[$idx] >= 4 {
                my $grains = @buffer[$idx] div 4;
                @buffer[ $idx - $w ] += $grains if $row > 0;
                @buffer[ $idx - 1  ] += $grains if $idx - 1 >= $rs;
                @buffer[ $idx + $w ] += $grains if $row < $h - 1;
                @buffer[ $idx + 1  ] += $grains if $idx + 1 < $re;
                @buffer[ $idx ] %= 4;
                $done = False;
            }
        }
    }
    unless $hide-progress {
        print "\e[1;1H", @buffer.map( { @color[$_ min 4] }).join;
    }
} until $done;

print "\e[1;1H", @buffer.map( { @color[$_ min 4] }).join;

cleanup;


' version 28-10-2016
' compile with: fbc -s console
' to do A(4, 2) the stack size needs to be increased
' compile with: fbc -s console -t 2000

Function ackerman (m As Long, n As Long) As Long

    If m = 0 Then ackerman = n +1

    If m > 0 Then
        If n = 0 Then
            ackerman = ackerman(m -1, 1)
        Else
            If n > 0 Then
                ackerman = ackerman(m -1, ackerman(m, n -1))
            End If
        End If
    End If
End Function

' ------=< MAIN >=------

Dim As Long m, n
Print

For m = 0 To 4
    Print Using "###"; m;
    For n = 0 To 10
        ' A(4, 1) or higher will run out of stack memory (default 1M)
        ' change n = 1 to n = 2 to calculate A(4, 2), increase stack!
        If m = 4 And n = 1 Then Exit For
        Print Using "######"; ackerman(m, n);
    Next
    Print
Next

' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End


# syntax: GAWK -f ABUNDANT_ODD_NUMBERS.AWK
# converted from C
BEGIN {
    print("   index     number        sum")
    fmt = "%8s %10d %10d\n"
    n = 1
    for (c=0; c<25; n+=2) {
      if (n < sum_proper_divisors(n)) {
        printf(fmt,++c,n,sum)
      }
    }
    for (; c<1000; n+=2) {
      if (n < sum_proper_divisors(n)) {
        c++
      }
    }
    printf(fmt,1000,n-2,sum)
    for (n=1000000001; ; n+=2) {
      if (n < sum_proper_divisors(n)) {
        break
      }
    }
    printf(fmt,"1st > 1B",n,sum)
    exit(0)
}
function sum_proper_divisors(n,  j) {
    sum = 1
    for (i=3; i<sqrt(n)+1; i+=2) {
      if (n % i == 0) {
        sum += i + (i == (j = n / i) ? 0 : j)
      }
    }
    return(sum)
}


numimpar = 1
contar = 0
sumaDiv = 0

function SumaDivisores(n)
	# Devuelve la suma de los divisores propios de n
	suma = 1
	i = int(sqr(n))

	for d = 2 to i
		if n % d = 0 then
			suma += d
			otroD = n \ d
			if otroD <> d Then suma += otroD
		end if
	Next d
	Return suma
End Function

# Encontrar los números requeridos por la tarea:
# primeros 25 números abundantes impares
Print "Los primeros 25 números impares abundantes:"
While contar < 25
	sumaDiv = SumaDivisores(numimpar)
	If sumaDiv > numimpar Then
		contar += 1
		Print numimpar & " suma divisoria adecuada: " & sumaDiv
	End If
	numimpar += 2
End While

# 1000er número impar abundante
While contar < 1000
	sumaDiv = SumaDivisores(numimpar)
	If sumaDiv > numimpar Then contar += 1
	numimpar += 2
End While
Print Chr(10) & "1000º número impar abundante:"
Print "   " & (numimpar - 2) & " suma divisoria adecuada: " & sumaDiv

# primer número impar abundante > mil millones (millardo)
numimpar = 1000000001
encontrado = False
While Not encontrado
	sumaDiv = SumaDivisores(numimpar)
	If sumaDiv > numimpar Then
		encontrado = True
		Print Chr(10) & "Primer número impar abundante > 1 000 000 000:"
		Print "    " & numimpar & " suma divisoria adecuada: " & sumaDiv
	End If
	numimpar += 2
End While
End


// This is the main algorithm.
//
// It loops over the current state of the sandpile and updates it on-the-fly.
fn advance(field: &mut Vec<Vec<usize>>, boundary: &mut [usize; 4]) -> bool
{
    // This variable is used to check whether we changed anything in the array. If no, the loop terminates.
    let mut done = false;

    for y in boundary[0]..boundary[2]
    {
        for x in boundary[1]..boundary[3]
        {
            if field[y][x] >= 4
            {
                // This part was heavily inspired by the Pascal version. We subtract 4 as many times as we can
                // and distribute it to the neighbors. Also, in case we have outgrown the current boundary, we
                // update it to once again contain the entire sandpile.

                // The amount that gets added to the neighbors is the amount here divided by four and (implicitly) floored.
                // The remaining sand is just current modulo 4.
                let rem: usize = field[y][x] / 4;
                field[y][x] %= 4;

                // The isize casts are necessary because usize can not go below 0.
                // Also, the reason why x and y are compared to boundary[2]-1 and boundary[3]-1 is because for loops in
                // Rust are upper bound exclusive. This means a loop like 0..5 will only go over 0,1,2,3 and 4.
                if y as isize - 1 >= 0 {field[y-1][x] += rem; if y == boundary[0] {boundary[0]-=1;}}
                if x as isize - 1 >= 0 {field[y][x-1] += rem; if x == boundary[1] {boundary[1]-=1;}}
                if y+1 < field.len() {field[y+1][x] += rem; if x == boundary[2]-1 {boundary[2]+=1;}}
                if x+1 < field.len() {field[y][x+1] += rem; if y == boundary[3]-1 {boundary[3]+=1;}}

                done = true;
            }
        }
    }

    done
}

// This function can be used to display the sandpile in the console window.
//
// Each row is mapped onto chars and those characters are then collected into a string.
// These are then printed to the console.
//
// Eg.: [0,1,1,2,3,0] -> [' ','░','░','▒','▓',' ']-> " ░░▒▓ "
fn display(field: &Vec<Vec<usize>>)
{
    for row in field
    {
        let char_row = {
            row.iter().map(|c| {match c {
                0 => ' ',
                1 => '░',
                2 => '▒',
                3 => '▓',
                _ => '█'
            }}).collect::<String>()
        };
        println!("{}", char_row);
    }
}

// This function writes the end result to a file called "output.ppm".
//
// PPM is a very simple image format, however, it entirely uncompressed which leads to huge image sizes.
// Even so, for demonstrative purposes it's perfectly good to use. For something more robust, look into PNG libraries.
//
// Read more about the format here: http://netpbm.sourceforge.net/doc/ppm.html
fn write_pile(pile: &Vec<Vec<usize>>) {
    use std::fs::File;
    use std::io::Write;

    // We first create the file (or erase its contents if it already existed).
    let mut file = File::create("./output.ppm").unwrap();

    // Then we add the image signature, which is "P3 <newline>[width of image] [height of image]<newline>[maximum value of color]<newline>".
    write!(file, "P3\n{} {}\n255\n", pile.len(), pile.len()).unwrap();

    for row in pile {
        // For each row, we create a new string which has more or less enough capacity to hold the entire row.
        // This is for performance purposes, but shouldn't really matter much.
        let mut line = String::with_capacity(row.len() * 14);

        // We map each value in the field to a color.
        // These are just simple RGB values, 0 being the background, the rest being the "sand" itself.
        for elem in row {
            line.push_str(match elem {
                0 => "100 40 15 ",
                1 => "117 87 30 ",
                2 => "181 134 47 ",
                3 => "245 182 66 ",
                _ => unreachable!(),
            });
        }

        // Finally we write this string into the file.
        write!(file, "{}\n", line).unwrap();
    }
}

fn main() {
    // This is how big the final image will be. Currently the end result would be a 16x16 picture.
    let field_size = 16;
    let mut playfield = vec![vec![0; field_size]; field_size];

    // We put the initial sand in the exact middle of the field.
    // This isn't necessary per se, but it ensures that sand can fully topple.
    //
    // The boundary is initially just the single tile which has the sand in it, however, as the algorithm
    // progresses, this will grow larger too.
    let mut boundary = [field_size/2-1, field_size/2-1, field_size/2, field_size/2];
    playfield[field_size/2 - 1][field_size/2 - 1] = 16;

    // This is the main loop. We update the field until it returns false, signalling that the pile reached its
    // final state.
    while advance(&mut playfield, &mut boundary) {};

    // Once this happens, we simply display the result. Uncomment the line below to write it to a file.
    // Calling display with large field sizes is not recommended as it can easily become too large for the console.
    display(&playfield);
    //write_pile(&playfield);
}


; A two-dimensional grid of values...

; Create an empty (all cells 0) grid of the specified size.
; Optionally, fill all cells with given value.
(define make-grid
  (lambda (size-x size-y . opt-value)
    (cons size-x (make-vector (* size-x size-y) (if (null? opt-value) 0 (car opt-value))))))

; Return the vector of all values of a grid.
(define grid-vector
  (lambda (grid)
    (cdr grid)))

; Return the X size of a grid.
(define grid-size-x
  (lambda (grid)
    (car grid)))

; Return the Y size of a grid.
(define grid-size-y
  (lambda (grid)
    (/ (vector-length (cdr grid)) (car grid))))

; Return #t if the specified x/y is within the range of the given grid.
(define grid-in-range
  (lambda (grid x y)
    (and (>= x 0) (>= y 0) (< x (grid-size-x grid)) (< y (grid-size-y grid)))))

; Return the value from the specified cell of the given grid.
; Note:  Returns 0 if x/y is out of range.
(define grid-ref
  (lambda (grid x y)
    (if (grid-in-range grid x y)
      (vector-ref (cdr grid) (+ x (* y (car grid))))
      0)))

; Store the given value into the specified cell of the given grid.
; Note:  Does nothing if x/y is out of range.
(define grid-set!
  (lambda (grid x y val)
    (when (grid-in-range grid x y)
      (vector-set! (cdr grid) (+ x (* y (car grid))) val))))

; Display the given grid, leaving correct spacing for maximum value.
; Optionally, uses a specified digit count for spacing.
; Returns the digit count of the largest grid value.
; Note:  Assumes the values in the grid are all non-negative integers.
(define grid-display
  (lambda (grid . opt-digcnt)
    ; Return count of digits in printed representation of integer.
    (define digit-count
      (lambda (int)
        (if (= int 0) 1 (1+ (exact (floor (log int 10)))))))
    ; Display the grid, leaving correct spacing for maximum value.
    (let* ((maxval (fold-left max 0 (vector->list (grid-vector grid))))
           (digcnt (if (null? opt-digcnt) (digit-count maxval) (car opt-digcnt))))
      (do ((y 0 (1+ y)))
          ((>= y (grid-size-y grid)))
        (do ((x 0 (1+ x)))
            ((>= x (grid-size-x grid)))
          (printf " ~vd" digcnt (grid-ref grid x y)))
        (printf "~%"))
      digcnt)))

; Implementation of the Abelian Sandpile Model using the above grid...

; Topple the specified cell of the given Abelian Sandpile Model grid.
; If number of grains in cell is less than 4, does nothing and returns #f.
; Otherwise, distributes 4 grains from the cell to its nearest neighbors and returns #t.
(define asm-topple
  (lambda (asm x y)
    (if (< (grid-ref asm x y) 4)
      #f
      (begin
        (grid-set! asm x y (- (grid-ref asm x y) 4))
        (grid-set! asm (1- x) y (1+ (grid-ref asm (1- x) y)))
        (grid-set! asm (1+ x) y (1+ (grid-ref asm (1+ x) y)))
        (grid-set! asm x (1- y) (1+ (grid-ref asm x (1- y))))
        (grid-set! asm x (1+ y) (1+ (grid-ref asm x (1+ y))))
        #t))))

; Repeatedly topple unstable cells in the given Abelian Sandpile Model grid
; until all cells are stable.
(define asm-stabilize
  (lambda (asm)
    (let loop ((any-toppled #f))
      (do ((y 0 (1+ y)))
          ((>= y (grid-size-y asm)))
        (do ((x 0 (1+ x)))
            ((>= x (grid-size-x asm)))
          (when (asm-topple asm x y)
            (set! any-toppled #t))))
      (when any-toppled
        (loop #f)))))

; Test the Abelian Sandpile Model on a simple grid...

(let ((asm (make-grid 9 9)))
  (grid-set! asm 4 4 64)
  (printf "Before:~%")
  (let ((digcnt (grid-display asm)))
    (asm-stabilize asm)
    (printf "After:~%")
    (grid-display asm digcnt)))


#include <stdio.h>
#include <math.h>

// The following function is for odd numbers ONLY
// Please use "for (unsigned i = 2, j; i*i <= n; i ++)" for even and odd numbers
unsigned sum_proper_divisors(const unsigned n) {
  unsigned sum = 1;
  for (unsigned i = 3, j; i < sqrt(n)+1; i += 2) if (n % i == 0) sum += i + (i == (j = n / i) ? 0 : j);
  return sum;
}

int main(int argc, char const *argv[]) {
  unsigned n, c;
  for (n = 1, c = 0; c < 25; n += 2) if (n < sum_proper_divisors(n)) printf("%u: %u\n", ++c, n);

  for ( ; c < 1000; n += 2) if (n < sum_proper_divisors(n)) c ++;
  printf("\nThe one thousandth abundant odd number is: %u\n", n);

  for (n = 1000000001 ;; n += 2) if (n < sum_proper_divisors(n)) break;
  printf("The first abundant odd number above one billion is: %u\n", n);

  return 0;
}


Sub SetupPile(a As Integer, b As Integer)
Application.ScreenUpdating = False
For i = 1 To a
For j = 1 To b
Cells(i, j).value = ""
Cells(i, j).Select

With Selection.Borders(xlEdgeLeft)
    .LineStyle = xlContinuous
    .Weight = xlMedium
End With
With Selection.Borders(xlEdgeTop)
    .LineStyle = xlContinuous
    .Weight = xlMedium
End With
With Selection.Borders(xlEdgeBottom)
    .LineStyle = xlContinuous
    .Weight = xlMedium
End With
With Selection.Borders(xlEdgeRight)
    .LineStyle = xlContinuous
    .Weight = xlMedium
End With

With Selection
    .HorizontalAlignment = xlCenter
    .VerticalAlignment = xlCenter
End With

Next j
Next i
Application.ScreenUpdating = True
End Sub

Sub Abelian_Sandpile()
Dim PileWidth As Integer
Dim PileHeight As Integer
Dim FieldArray() As Integer

Debug.Print "Start:" & Now()

'Set Size of Playing Field
PileWidth = 25
PileHeight = 25

ReDim FieldArray(PileWidth - 1, PileHeight - 1)

'Paint Basic Grid
SetupPile PileWidth, PileHeight

'Drop sand amount into middle of playing field
SandDropAmount = 1000
'Get around excel's incorrect rounding
SandDropColumn = Round((PileWidth / 2) + 0.001, 0)
SandDropRow = Round((PileHeight / 2) + 0.001, 0)

Cells(SandDropRow, SandDropColumn) = SandDropAmount
FieldArray(SandDropRow - 1, SandDropColumn - 1) = SandDropAmount

Continue = False

'Check if Pile is already stabilized at the start
For i = 1 To PileWidth 'Col
For j = 1 To PileHeight 'Row
If FieldArray(j - 1, i - 1) > 3 Then Continue = True
Next j
Next i

'While not stabilized
While Continue
For i = 1 To PileWidth
For j = 1 To PileHeight
    If FieldArray(j - 1, i - 1) > 3 Then
    'Reduce by 4
    FieldArray(j - 1, i - 1) = FieldArray(j - 1, i - 1) - 4
    'Increase Neighbours
    't
    If j >= 2 Then FieldArray(j - 2, i - 1) = FieldArray(j - 2, i - 1) + 1
    'r
    If i < PileWidth Then FieldArray(j - 1, i) = FieldArray(j - 1, i) + 1
    'b
    If j < PileHeight Then FieldArray(j, i - 1) = FieldArray(j, i - 1) + 1
    'l
    If i >= 2 Then FieldArray(j - 1, i - 2) = FieldArray(j - 1, i - 2) + 1
    'Next round
    GoTo Nextone
    End If
Next j
Next i

Nextone:

'Check if now stabilized
Continue = False
For i = 1 To PileWidth
For j = 1 To PileHeight
'Paint every step if needed
'Cells(j, i) = FieldArray(j - 1, i - 1)

If FieldArray(j - 1, i - 1) > 3 Then Continue = True
Next j
Next i

Wend

'Print out final step
For i = 1 To PileWidth
For j = 1 To PileHeight
Cells(j, i) = FieldArray(j - 1, i - 1)
Next j
Next i

'Make field square and remove 0
Cells.Select
Selection.ColumnWidth = 2
Selection.RowHeight = 13.5
Selection.Replace What:="0", Replacement:="", LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Range("A1").Select

Range(Cells(1, 1), Cells(PileHeight, PileWidth)).Select

'Conditional Format
Selection.FormatConditions.AddColorScale ColorScaleType:=3
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
Selection.FormatConditions(1).ColorScaleCriteria(1).Type = xlConditionValueLowestValue
With Selection.FormatConditions(1).ColorScaleCriteria(1).FormatColor
    .Color = 8109667
    .TintAndShade = 0
End With
Selection.FormatConditions(1).ColorScaleCriteria(2).Type = xlConditionValuePercentile
Selection.FormatConditions(1).ColorScaleCriteria(2).value = 50
With Selection.FormatConditions(1).ColorScaleCriteria(2).FormatColor
    .Color = 8711167
    .TintAndShade = 0
End With
Selection.FormatConditions(1).ColorScaleCriteria(3).Type = xlConditionValueHighestValue
With Selection.FormatConditions(1).ColorScaleCriteria(3).FormatColor
    .Color = 7039480
    .TintAndShade = 0
End With
Range("A1").Select

Debug.Print "W,H,A:" & PileWidth & "," & PileHeight & "," & SandDropAmount
Debug.Print "End:" & Now()

End Sub


import os
import strings

const dim = 16

// Outputs the result to the terminal using UTF-8 block characters.
fn draw_pile(pile [][]int) {
    chars:= [` `,`░`,`▓`,`█`]
    for row in pile {
        mut line := []rune{len: row.len}
        for i, e in row {
            mut elem := e
            if elem > 3 { // only possible when algorithm not yet completed.
                elem = 3
            }
            line[i] = chars[elem]
        }
        println(line.string())
    }
}

// Creates a .ppm file in the current directory, which contains
// a colored image of the pile.
fn write_pile(pile [][]int) {
    mut file := os.create("output.ppm") or {panic('ERROR creating file')}
    defer {
file.close()
}
    // Write the signature, image dimensions and maximum color value to the file.
    file.writeln("P3\n$dim $dim\n255") or {panic('ERROR writing ln')}
    bcolors := ["125 0 25 ", "125 80 0 ", "186 118 0 ", "224 142 0 "]
    mut line := strings.new_builder(128)
    for row in pile {
        for elem in row {
            line.write_string(bcolors[elem])
        }
        file.write_string('${line.str()}\n') or {panic('ERROR writing str')}
        line = strings.new_builder(128)
    }
}

// Main part of the algorithm, a simple, recursive implementation of the model.
fn handle_pile(x int, y int, mut pile [][]int) {
    if pile[y][x] >= 4 {
        pile[y][x] -= 4
        // Check each neighbor, whether they have enough "sand" to collapse and if they do,
        // recursively call handle_pile on them.
        if y > 0 {
            pile[y-1][x]++
            if pile[y-1][x] >= 4 {
                handle_pile(x, y-1, mut pile)
            }
        }
        if x > 0 {
            pile[y][x-1]++
            if pile[y][x-1] >= 4 {
                handle_pile(x-1, y, mut pile)
            }
        }
        if y < dim-1 {
            pile[y+1][x]++
            if pile[y+1][x] >= 4 {
                handle_pile(x, y+1, mut pile)
            }
        }
        if x < dim-1 {
            pile[y][x+1]++
            if pile[y][x+1] >= 4 {
                handle_pile(x+1, y, mut pile)
            }
        }

        // Uncomment this line to show every iteration of the program.
        // Not recommended with large input values.
        // draw_pile(pile)

        // Finally call the fntion on the current cell again,
        // in case it had more than 4 particles.
        handle_pile(x, y, mut pile)
    }
}

fn main() {
    // Create 2D grid and set size using the 'dim' constant.
    mut pile := [][]int{len: dim, init: []int{len: dim}}

    // Place some sand particles in the center of the grid and start the algorithm.
    hdim := int(dim/2 - 1)
    pile[hdim][hdim] = 16
    handle_pile(hdim, hdim, mut pile)
    draw_pile(pile)

    // Uncomment this to save the final image to a file
    // after the recursive algorithm has ended.
    // write_pile(pile)
}


import "/fmt" for Fmt

class Sandpile {
    // 'a' is a list of integers in row order
    construct new(a) {
        var count = a.count
        _rows = count.sqrt.floor
        if (_rows * _rows != count) Fiber.abort("The matrix of values must be square.")
        _a = a
        _neighbors = List.filled(count, 0)
        for (i in 0...count) {
            _neighbors[i] = []
            if (i % _rows > 0)     _neighbors[i].add(i-1)
            if ((i + 1)%_rows > 0) _neighbors[i].add(i+1)
            if (i - _rows >= 0)    _neighbors[i].add(i-_rows)
            if (i + _rows < count) _neighbors[i].add(i+_rows)
        }
    }

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

    // topples until stable
    topple() {
        while (!isStable) {
            for (i in 0..._a.count) {
                if (_a[i] > 3) {
                    _a[i] = _a[i] - 4
                    for (j in _neighbors[i]) _a[j] = _a[j] + 1
                }
            }
        }
    }

    toString {
        var s = ""
        for (i in 0..._rows) {
            for (j in 0..._rows) s = s + Fmt.swrite("$2d ", _a[_rows*i + j])
            s = s + "\n"
        }
        return s
    }
}

var printAcross = Fn.new { |str1, str2|
    var r1 = str1.split("\n")
    var r2 = str2.split("\n")
    var rows = r1.count - 1
    var cr = (rows/2).floor
    for (i in 0...rows) {
        var symbol = (i == cr) ? "->" : "  "
        Fmt.print("$s $s $s", r1[i], symbol, r2[i])
    }
    System.print()
}

var a1 = List.filled(25, 0)
a1[12] = 4
var a2 = List.filled(25, 0)
a2[12] = 6
var a3 = List.filled(25, 0)
a3[12] = 16
var a4 = List.filled(100, 0)
a4[55] = 64
for (a in [a1, a2, a3, a4]) {
    var s = Sandpile.new(a)
    var str1 = s.toString
    s.topple()
    var str2 = s.toString
    printAcross.call(str1, str2)
}


def
  ackermann( 0, n ) = n + 1
  ackermann( m, 0 ) = ackermann( m - 1, 1 )
  ackermann( m, n ) = ackermann( m - 1, ackermann(m, n - 1) )

for m <- 0..3, n <- 0..4
  printf( 'Ackermann( %d, %d ) = %d\n', m, n, ackermann(m, n) )


using static System.Console;
using System.Collections.Generic;
using System.Linq;

public static class AbundantOddNumbers
{
    public static void Main() {
        WriteLine("First 25 abundant odd numbers:");
        foreach (var x in AbundantNumbers().Take(25)) WriteLine(x.Format());
        WriteLine();
        WriteLine($"The 1000th abundant odd number: {AbundantNumbers().ElementAt(999).Format()}");
        WriteLine();
        WriteLine($"First abundant odd number > 1b: {AbundantNumbers(1_000_000_001).First().Format()}");
    }

    static IEnumerable<(int n, int sum)> AbundantNumbers(int start = 3) =>
        start.UpBy(2).Select(n => (n, sum: n.DivisorSum())).Where(x => x.sum > x.n);

    static int DivisorSum(this int n) => 3.UpBy(2).TakeWhile(i => i * i <= n).Where(i => n % i == 0)
        .Select(i => (a:i, b:n/i)).Sum(p => p.a == p.b ? p.a : p.a + p.b) + 1;

    static IEnumerable<int> UpBy(this int n, int step) {
        for (int i = n; ; i+=step) yield return i;
    }

    static string Format(this (int n, int sum) pair) => $"{pair.n:N0} with sum {pair.sum:N0}";
}


def  Size = 200;
char Pile1(Size*Size), Pile2(Size*Size);
int  Spigot, I, X, Y;
[SetVid($13);   \VGA 320x200x8
FillMem(Pile1, 0, Size*Size);
FillMem(Pile2, 0, Size*Size);
Spigot:= 400_000;
repeat  I:= 0;
        for Y:= 0 to Size-1 do
            for X:= 0 to Size-1 do
                [if X=Size/2 & Y=Size/2 then
                    [Spigot:= Spigot-4;
                     Pile1(I):= Pile1(I)+4;
                    ];
                if Pile1(I) >= 4 then
                    [Pile1(I):= Pile1(I)-4;
                     Pile2(I-1):= Pile2(I-1)+1;
                     Pile2(I+1):= Pile2(I+1)+1;
                     Pile2(I-Size):= Pile2(I-Size)+1;
                     Pile2(I+Size):= Pile2(I+Size)+1;
                    ];
                Point(X, Y, Pile1(I)*2);
                I:= I+1;
                ];
        I:= Pile1;  Pile1:= Pile2;  Pile2:= I;
until   Spigot < 4;
]


fun ackermann(m: int, n: int): int =
  if m == 0 then n + 1
  else if n == 0 then ackermann(m-1, 1)
  else ackermann(m - 1, ackermann(m, n-1))


#include <algorithm>
#include <iostream>
#include <numeric>
#include <sstream>
#include <vector>

std::vector<int> divisors(int n) {
    std::vector<int> divs{ 1 };
    std::vector<int> divs2;

    for (int i = 2; i*i <= n; i++) {
        if (n%i == 0) {
            int j = n / i;
            divs.push_back(i);
            if (i != j) {
                divs2.push_back(j);
            }
        }
    }
    std::copy(divs2.crbegin(), divs2.crend(), std::back_inserter(divs));

    return divs;
}

int sum(const std::vector<int>& divs) {
    return std::accumulate(divs.cbegin(), divs.cend(), 0);
}

std::string sumStr(const std::vector<int>& divs) {
    auto it = divs.cbegin();
    auto end = divs.cend();
    std::stringstream ss;

    if (it != end) {
        ss << *it;
        it = std::next(it);
    }
    while (it != end) {
        ss << " + " << *it;
        it = std::next(it);
    }

    return ss.str();
}

int abundantOdd(int searchFrom, int countFrom, int countTo, bool printOne) {
    int count = countFrom;
    int n = searchFrom;
    for (; count < countTo; n += 2) {
        auto divs = divisors(n);
        int tot = sum(divs);
        if (tot > n) {
            count++;
            if (printOne && count < countTo) {
                continue;
            }
            auto s = sumStr(divs);
            if (printOne) {
                printf("%d < %s = %d\n", n, s.c_str(), tot);
            } else {
                printf("%2d. %5d < %s = %d\n", count, n, s.c_str(), tot);
            }
        }
    }
    return n;
}

int main() {
    using namespace std;

    const int max = 25;
    cout << "The first " << max << " abundant odd numbers are:\n";
    int n = abundantOdd(1, 0, 25, false);

    cout << "\nThe one thousandth abundant odd number is:\n";
    abundantOdd(n, 25, 1000, true);

    cout << "\nThe first abundant odd number above one billion is:\n";
    abundantOdd(1e9 + 1, 0, 1, true);

    return 0;
}


include "NSLog.incl"

local fn Ackerman( m as NSInteger, n as NSInteger ) as NSInteger
NSInteger result

select
  case m == 0 : result = ( n + 1 )
  case n == 0 : result = fn Ackerman( ( m - 1 ), 1 )
  case else   : result = fn Ackerman( ( m - 1 ), fn Ackerman( m, ( n - 1 ) ) )
end select
end fn = result

NSInteger          m, n
CFMutableStringRef mutStr

mutStr = fn StringWithCapacity( 0 )

for m = 0 to 3
  for n = 0 to 9
    StringAppendString( mutStr, fn StringWithFormat( @"fn Ackerman( %ld, %ld ) = %ld\n", m, n, fn Ackerman( m, n ) ) )
  next
next

NSLog( @"%@", mutStr )

HandleEvents


% Integer square root
isqrt = proc (s: int) returns (int)
    x0: int := s / 2
    if x0 = 0 then
        return(s)
    else
        x1: int := (x0 + s/x0) / 2
        while x1 < x0 do
            x0 := x1
            x1 := (x0 + s/x0) / 2
        end
        return(x0)
    end
end isqrt

% Calculate aliquot sum (for odd numbers only)
aliquot = proc (n: int) returns (int)
    sum: int := 1
    for i: int in int$from_to_by(3, isqrt(n)+1, 2) do
        if n//i = 0 then
            j: int := n / i
            sum := sum + i
            if i ~= j then
                sum := sum + j
            end
        end
    end
    return(sum)
end aliquot

% Generate abundant odd numbers
abundant_odd = iter (n: int) yields (int)
    while true do
        if n < aliquot(n) then yield(n) end
        n := n + 2
    end
end abundant_odd

start_up = proc ()
    po: stream := stream$primary_output()

    count: int := 0
    for n: int in abundant_odd(1) do
        count := count + 1
        if count <= 25 cor count = 1000 then
            stream$putl(po, int$unparse(count)
                        || ":\t"
                        || int$unparse(n)
                        || "\taliquot: "
                        || int$unparse(aliquot(n)))
            if count = 1000 then break end
        end
    end

    for n: int in abundant_odd(1000000001) do
        stream$putl(po, "First above 1 billion: "
                        || int$unparse(n)
                        || " aliquot: "
                        || int$unparse(aliquot(n)))
        break
    end
end start_up


;; * Loading the external libraries
(eval-when (:compile-toplevel :load-toplevel)
  (ql:quickload '("cl-annot" "iterate" "alexandria")))

;; * The package definition
(defpackage :abundant-numbers
  (:use :common-lisp :cl-annot :iterate)
  (:import-from :alexandria :butlast))
(in-package :abundant-numbers)

(annot:enable-annot-syntax)

;; * Calculating the divisors
@inline
(defun divisors (n)
  "Returns the divisors of N without sorting them."
  @type fixnum n
  (iter
    (for divisor from (isqrt n) downto 1)
    (for (values m rem) = (floor n divisor))
    @type fixnum divisor
    (when (zerop rem)
      (collecting divisor into result)
      (adjoining m into result))
    (finally (return result))))

;; * Calculating the sum of divisors
(defun sum-of-divisors (n)
  "Returns the sum of the proper divisors of N."
  @type fixnum n
  (reduce #'+ (butlast (divisors n))))

;; * Task 1
(time
 (progn
   (format t "   Task 1~%")
   (iter
     (with i = 0)
     (for n from 1 by 2)
     (for sum-of-divisors = (sum-of-divisors n))
     @type fixnum i n sum-of-divisors
     (while (< i 25))
     (when (< n sum-of-divisors)
       (incf i)
       (format t "~5D: ~6D ~7D~%" i n sum-of-divisors)))

   ;; * Task 2
   (format t "~%   Task 2~%")
   (iter
     (with i = 0)
     (until (= i 1000))
     (for n from 1 by 2)
     (for sum-of-divisors = (sum-of-divisors n))
     @type fixnum i n sum-of-divisors
     (when (< n sum-of-divisors)
       (incf i))
     (finally (format t "~5D: ~6D ~7D~%" i n sum-of-divisors)))

   ;; * Task 3
   (format t "~%   Task 3~%")
   (iter
     (for n from (1+ (expt 10 9)) by 2)
     (for sum-of-divisors = (sum-of-divisors n))
     @type fixnum n sum-of-divisors
     (until (< n sum-of-divisors))
     (finally (format t "~D ~D~%~%" n sum-of-divisors)))))


Public Function Ackermann(m As Float, n As Float) As Float
  If m = 0 Then
    Return n + 1
  End If
  If n = 0 Then
    Return Ackermann(m - 1, 1)
  End If
  Return Ackermann(m - 1, Ackermann(m, n - 1))
End

Public Sub Main()
  Dim m, n As Float
  For m = 0 To 3
    For n = 0 To 4
      Print "Ackermann("; m; ", "; n; ") = "; Ackermann(m, n)
    Next
  Next
End


import std.stdio;

int[] divisors(int n) {
    import std.range;

    int[] divs = [1];
    int[] divs2;

    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            int j = n / i;
            divs ~= i;
            if (i != j) {
                divs2 ~= j;
            }
        }
    }
    divs ~= retro(divs2).array;

    return divs;
}

int abundantOdd(int searchFrom, int countFrom, int countTo, bool printOne) {
    import std.algorithm.iteration;
    import std.array;
    import std.conv;

    int count = countFrom;
    int n = searchFrom;
    for (; count < countTo; n += 2) {
        auto divs = divisors(n);
        int tot = sum(divs);
        if (tot > n) {
            count++;
            if (printOne && count < countTo) {
                continue;
            }
            auto s = divs.map!(to!string).join(" + ");
            if (printOne) {
                writefln("%d < %s = %d", n, s, tot);
            } else {
                writefln("%2d. %5d < %s = %d", count, n, s, tot);
            }
        }
    }
    return n;
}

void main() {
    const int max = 25;
    writefln("The first %d abundant odd numbers are:", max);
    int n = abundantOdd(1, 0, 25, false);

    writeln("\nThe one thousandth abundant odd number is:");
    abundantOdd(n, 25, 1000, true);

    writeln("\nThe first abundant odd number above one billion is:");
    abundantOdd(cast(int)(1e9 + 1), 0, 1, true);
}


program AbundantOddNumbers;

{$APPTYPE CONSOLE}

uses
  SysUtils;

function SumProperDivisors(const N: Cardinal): Cardinal;
var
  I, J: Cardinal;
begin
  Result := 1;
  I := 3;
  while I < Sqrt(N)+1 do begin
    if N mod I = 0 then begin
      J := N div I;
      Inc(Result, I);
      if I <> J then Inc(Result, J);
    end;
    Inc(I, 2);
  end;
end;

var
  C, N: Cardinal;
begin
  N := 1;
  C := 0;
  while C < 25 do begin
    Inc(N, 2);
    if N < SumProperDivisors(N) then begin
      Inc(C);
      WriteLn(Format('%u: %u', [C, N]));
    end;
  end;

  while C < 1000 do begin
    Inc(N, 2);
    if N < SumProperDivisors(N) then Inc(C);
  end;
  WriteLn(Format('The one thousandth abundant odd number is: %u', [N]));

  N := 1000000001;
  while N >= SumProperDivisors(N) do Inc(N, 2);
  WriteLn(Format('The first abundant odd number above one billion is: %u', [N]));

end.


ack := function(m, n)
  if m = 0 then
    return n + 1;
  elif (m > 0) and (n = 0) then
    return ack(m - 1, 1);
  elif (m > 0) and (n > 0) then
    return ack(m - 1, ack(m, n - 1));
  else
    return fail;
  fi;
end;


def A (m n)
   cond
      (equal? m 0)
          + n 1
      (equal? n 0)
          A (- m 1) 1
      else
          A (- m 1)
             A m (- n 1)


// Abundant odd numbers. Nigel Galloway: August 1st., 2021
let fN g=Seq.initInfinite(int64>>(+)1L)|>Seq.takeWhile(fun n->n*n<=g)|>Seq.filter(fun n->g%n=0L)|>Seq.sumBy(fun n->let i=g/n in n+(if i=n then 0L else i))
let aon n=Seq.initInfinite(int64>>(*)2L>>(+)n)|>Seq.map(fun g->(g,fN g))|>Seq.filter(fun(n,g)->2L*n<g)
aon 1L|>Seq.take 25|>Seq.iter(fun(n,g)->printfn "The sum of the divisors of %d is %d" n g)
let n,g=aon 1L|>Seq.item 999 in printfn "\nThe 1000th abundant odd number is %d. The sum of it's divisors is %d" n g
let n,g=aon 1000000001L|>Seq.head in printfn "\nThe first abundant odd number greater than 1000000000 is %d. The sum of it's divisors is %d" n g


USING: arrays formatting io kernel lists lists.lazy math
math.primes.factors sequences tools.memory.private ;
IN: rosetta-code.abundant-odd-numbers

: σ ( n -- sum ) divisors sum ;
: abundant? ( n -- ? ) [ σ ] [ 2 * ] bi > ;
: abundant-odds-from ( n -- list )
    dup even? [ 1 + ] when
    [ 2 + ] lfrom-by [ abundant? ] lfilter ;

: first25 ( -- seq ) 25 1 abundant-odds-from ltake list>array ;
: 1,000th ( -- n ) 999 1 abundant-odds-from lnth ;
: first>10^9 ( -- n ) 1,000,000,001 abundant-odds-from car ;

GENERIC: show ( obj -- )
M: integer show dup σ [ commas ] [email protected] "%-6s σ = %s\n" printf ;
M: array show [ show ] each ;

: abundant-odd-numbers-demo ( -- )
    first25 "First 25 abundant odd numbers:"
    1,000th "1,000th abundant odd number:"
    first>10^9 "First abundant odd number > one billion:"
    [ print show nl ] [email protected] ;

MAIN: abundant-odd-numbers-demo


///ackermann(m,n)
var m, n;
m = argument0;
n = argument1;
if(m=0)
    {
    return (n+1)
    }
else if(n == 0)
    {
    return (ackermann(m-1,1,1))
    }
else
    {
    return (ackermann(m-1,ackermann(m,n-1,2),1))
    }


program main
use,intrinsic :: iso_fortran_env, only : int8, int16, int32, int64
implicit none
integer,parameter          :: dp=kind(0.0d0)
character(len=*),parameter :: g='(*(g0,1x))'
integer                    :: j, icount
integer,allocatable        :: list(:)
real(kind=dp)              :: tally

   write(*,*)'N sum'
   icount=0                       ! number of abundant odd numbers found
   do j=1,huge(0)-1,2             ! loop through odd numbers for candidates
      list=divisors(j)            ! git list of divisors for current value
      tally= sum([real(list,kind=dp)]) ! sum divisors
      if(tally>2*j .and. iand(j,1) /= 0) then ! count an abundant odd number
         icount=icount+1
         select case(icount)  ! if one of the values targeted print it
         case(1:25,1000);write(*,g)icount,':',j!, list
         end select
      endif
      if(icount.gt.1000)exit ! quit after last targeted value is found
   enddo

   do j=1000000001,huge(0),2
      list=divisors(j)
      tally= sum([real(list,kind=dp)])
      if(tally>2*j .and. iand(j,1) /= 0) then
         write(*,g)'First abundant odd number greater than one billion:',j

         exit
      endif
   enddo

contains

function divisors(num) result (numbers)
!> brute force divisors
integer,intent(in) :: num
integer :: i
integer,allocatable :: numbers(:)
   numbers=[integer :: ]
   do i=1 , int(sqrt(real(num)))
      if (mod(num , i)  .eq. 0) numbers=[numbers, i,num/i]
   enddo
end function divisors

end program main


Declare Function SumaDivisores(n As Integer) As Integer

Dim numimpar As Integer = 1
Dim contar As Integer = 0
Dim sumaDiv As Integer = 0

Function SumaDivisores(n As Integer) As Integer
    ' Devuelve la suma de los divisores propios de n
    Dim suma As Integer = 1
    Dim As Integer d, otroD

    For d = 2 To Cint(Sqr(n))
        If n Mod d = 0 Then
            suma += d
            otroD = n \ d
            If otroD <> d Then suma += otroD
        End If
    Next d
    Return suma
End Function

' Encontrar los números requeridos por la tarea:

' primeros 25 números abundantes impares
Print "Los primeros 25 números impares abundantes:"
Do While contar < 25
    sumaDiv = SumaDivisores(numimpar)
    If sumaDiv > numimpar Then
        contar += 1
        Print using "######"; numimpar;
        Print " suma divisoria adecuada: " & sumaDiv
    End If
    numimpar += 2
Loop

' 1000er número impar abundante
Do While contar < 1000
    sumaDiv = SumaDivisores(numimpar)
    If sumaDiv > numimpar Then contar += 1
    numimpar += 2
Loop
Print Chr(10) & "1000º número impar abundante:"
Print "    " & (numimpar - 2) & " suma divisoria adecuada: " & sumaDiv

' primer número impar abundante > mil millones (millardo)
numimpar = 1000000001
Dim encontrado As Boolean = False
Do While Not encontrado
    sumaDiv = SumaDivisores(numimpar)
    If sumaDiv > numimpar Then
        encontrado = True
        Print Chr(10) & "Primer número impar abundante > 1 000 000 000:"
        Print "    " & numimpar & " suma divisoria adecuada: " & sumaDiv
    End If
    numimpar += 2
Loop
End


isAbundantOdd[n] := sum[allFactors[n, true, false]] > n

n = 3
count = 0

println["The first 25 abundant odd numbers:"]
do
{
   if isAbundantOdd[n]
   {
      println["$n: proper divisor sum " + sum[allFactors[n, 1, false]]]
      count = count + 1
   }

   n = n + 2
} while count < 25

println["\nThe thousandth abundant odd number:"]
n = 1
count = 0
do
{
   n = n + 2

   if isAbundantOdd[n]
      count = count + 1

} until count == 1000

println["$n: proper divisor sum " + sum[allFactors[n, 1, false]]]

println["\nThe first abundant odd number over 1 billion:"]
n = 10^9 + 1
count = 0
do
   n = n + 2
until isAbundantOdd[n]

println["$n: proper divisor sum " + sum[allFactors[n, 1, false]]]


func Ackermann(m, n uint) uint {
	switch 0 {
	case m:
		return n + 1
	case n:
		return Ackermann(m - 1, 1)
	}
	return Ackermann(m - 1, Ackermann(m, n - 1))
}


include "NSLog.incl"

local fn SumOfProperDivisors( n as NSUInteger ) as NSUinteger
NSUinteger sum = 1

cln for (unsigned i = 3, j; i < sqrt(n)+1; i += 2) if (n % i == 0) sum += i + (i == (j = n / i) ? 0 : j);
end fn = sum

NSUinteger n, c
cln for (n = 1, c = 0; c < 25; n += 2 ) if ( n < SumOfProperDivisors( n ) ) NSLog( @"%2lu: %lu", ++c, n );

cln for ( ; c < 1000; n += 2 ) if ( n < SumOfProperDivisors( n ) ) c ++;
NSLog( @"\nThe one thousandth abundant odd number is: %lu\n", n )

cln for ( n = 1000000001 ;; n += 2 ) if ( n < SumOfProperDivisors( n ) ) break;
NSLog( @"The first abundant odd number above one billion is: %lu\n", n )

HandleEvents


package main

import (
    "fmt"
    "strconv"
)

func divisors(n int) []int {
    divs := []int{1}
    divs2 := []int{}
    for i := 2; i*i <= n; i++ {
        if n%i == 0 {
            j := n / i
            divs = append(divs, i)
            if i != j {
                divs2 = append(divs2, j)
            }
        }
    }
    for i := len(divs2) - 1; i >= 0; i-- {
        divs = append(divs, divs2[i])
    }
    return divs
}

func sum(divs []int) int {
    tot := 0
    for _, div := range divs {
        tot += div
    }
    return tot
}

func sumStr(divs []int) string {
    s := ""
    for _, div := range divs {
        s += strconv.Itoa(div) + " + "
    }
    return s[0 : len(s)-3]
}

func abundantOdd(searchFrom, countFrom, countTo int, printOne bool) int {
    count := countFrom
    n := searchFrom
    for ; count < countTo; n += 2 {
        divs := divisors(n)
        if tot := sum(divs); tot > n {
            count++
            if printOne && count < countTo {
                continue
            }
            s := sumStr(divs)
            if !printOne {
                fmt.Printf("%2d. %5d < %s = %d\n", count, n, s, tot)
            } else {
                fmt.Printf("%d < %s = %d\n", n, s, tot)
            }
        }
    }
    return n
}

func main() {
    const max = 25
    fmt.Println("The first", max, "abundant odd numbers are:")
    n := abundantOdd(1, 0, 25, false)

    fmt.Println("\nThe one thousandth abundant odd number is:")
    abundantOdd(n, 25, 1000, true)

    fmt.Println("\nThe first abundant odd number above one billion is:")
    abundantOdd(1e9+1, 0, 1, true)
}


V command_table_text =
|‘add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
  compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
  3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
  forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
  locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
  msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
  refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
  2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1’

V user_words = ‘riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin’

F find_abbreviations_length(command_table_text)
   ‘ find the minimal abbreviation length for each word.
        a word that does not have minimum abbreviation length specified
        gets it's full lengths as the minimum.
   ’
   [String = Int] command_table
   V input_list = command_table_text.split((‘ ’, "\n"), group_delimiters' 1B)
   V i = 0

   V word = ‘’
   L i < input_list.len | word != ‘’
      I word == ‘’
         word = input_list[i++]
      V abbr_len = I i < input_list.len {input_list[i++]} E String(word.len)
      X.try
         command_table[word] = Int(abbr_len)
         word = ‘’
      X.catch ValueError
         command_table[word] = word.len
         word = abbr_len
   R command_table

F find_abbreviations(command_table)
   ‘ for each command insert all possible abbreviations’
   [String = String] abbreviations
   L(command, min_abbr_len) command_table
      L(l) min_abbr_len .. command.len
         V abbr = command[0 .< l].lowercase()
         abbreviations[abbr] = command.uppercase()
   R abbreviations

F parse_user_string(user_string, abbreviations)
   V user_words = user_string.split(‘ ’, group_delimiters' 1B).map(word -> word.lowercase())
   V commands = user_words.map(user_word -> @abbreviations.get(user_word, ‘*error*’))
   R commands.join(‘ ’)

V command_table = find_abbreviations_length(command_table_text)
V abbreviations_table = find_abbreviations(command_table)

V full_words = parse_user_string(user_words, abbreviations_table)

print(‘user words: ’user_words)
print(‘full words: ’full_words)


class Abundant {
    static List<Integer> divisors(int n) {
        List<Integer> divs = new ArrayList<>()
        divs.add(1)
        List<Integer> divs2 = new ArrayList<>()

        int i = 2
        while (i * i < n) {
            if (n % i == 0) {
                int j = (int) (n / i)
                divs.add(i)
                if (i != j) {
                    divs2.add(j)
                }
            }
            i++
        }

        Collections.reverse(divs2)
        divs.addAll(divs2)
        return divs
    }

    static int abundantOdd(int searchFrom, int countFrom, int countTo, boolean printOne) {
        int count = countFrom
        int n = searchFrom

        while (count < countTo) {
            List<Integer> divs = divisors(n)
            int tot = divs.stream().reduce(Integer.&sum).orElse(0)

            if (tot > n) {
                count++
                if (!printOne || count >= countTo) {
                    String s = divs.stream()
                            .map(Integer.&toString)
                            .reduce { a, b -> a + " + " + b }
                            .orElse("")
                    if (printOne) {
                        System.out.printf("%d < %s = %d\n", n, s, tot)
                    } else {
                        System.out.printf("%2d. %5d < %s = %d\n", count, n, s, tot)
                    }
                }
            }

            n += 2
        }

        return n
    }

    static void main(String[] args) {
        int max = 25

        System.out.printf("The first %d abundant odd numbers are:\n", max)
        int n = abundantOdd(1, 0, 25, false)

        System.out.println("\nThe one thousandth abundant odd number is:")
        abundantOdd(n, 25, 1000, true)

        System.out.println("\nThe first abundant odd number above one billion is:")
        abundantOdd((int) (1e9 + 1), 0, 1, true)
    }
}


/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program abbrSimple64.s   */
/* store list of command in a file commandSimple.txt */
/* and run the program  abbrSimple64 commandSimple.txt */

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

.equ BUFFERSIZE,   1000
.equ NBMAXIELEMENTS, 100

/*******************************************/
/* Structures                               */
/********************************************/
/* command structure      */
    .struct  0
command_name_address:                   // name
    .struct  command_name_address + 8
command_min:                            // minimum letters
    .struct  command_min + 8
command_end:
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessTitre:            .asciz "Nom du fichier : "
szCarriageReturn:      .asciz "\n"
szMessErreur:          .asciz "Error detected.\n"
szMessErrBuffer:       .asciz "buffer size too less !!"
szMessCtrlCom:         .asciz "Command : @   minimum : @ \n"
szMessErrorAbr:        .asciz "*error*"
szMessInput:           .asciz "Enter command (or <ctrl-c> to stop) : "

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
sZoneConv:      .skip 24
qAdrFicName:    .skip 8
iTabAdrCmd:     .skip command_end * NBMAXIELEMENTS
sBufferCmd:     .skip BUFFERSIZE
sBuffer:        .skip BUFFERSIZE
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                            // INFO: main
    mov x0,sp                    // stack address for load parameter
    bl traitFic                  // read file and store value in array
    cmp x0,#-1
    beq 100f                     // error ?
    ldr x0,qAdriTabAdrCmd
    bl controlLoad

1:
    ldr x0,qAdrszMessInput       // display input message
    bl affichageMess
    mov x0,#STDIN                // Linux input console
    ldr x1,qAdrsBuffer           // buffer address
    mov x2,#BUFFERSIZE           // buffer size
    mov x8, #READ                // request to read datas
    svc 0                        // call system
    sub x0,x0,#1
    mov x2,#0
    strb w2,[x1,x0]              // replace character 0xA by zéro final
    cbnz x0,2f                   // null string ?
    mov x0,x1
    b 3f
2:
    ldr x0,qAdrsBuffer
    ldr x1,qAdriTabAdrCmd
    bl controlCommand            // control text command
3:
    mov x2,x0                    // display result
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess

    b 1b                         // loop

99:
    ldr x0,qAdrszMessErrBuffer
    bl affichageMess
100:                                 // standard end of the program
    mov x0, #0                       // return code
    mov x8, #EXIT                    // request to exit program
    svc #0                           // perform the system call

qAdrszCarriageReturn:      .quad szCarriageReturn
qAdrszMessErrBuffer:       .quad szMessErrBuffer
qAdrsZoneConv:             .quad sZoneConv
qAdrszMessInput:           .quad szMessInput
/******************************************************************/
/*      control abbrevation command                               */
/******************************************************************/
/* x0 contains string input command */
/* x1 contains address table string command */
controlCommand:                  // INFO: controlCommand
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[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
    mov x8,x0
    mov x9,x1
    mov x10,#command_end          // length item
    bl computeLength              // length input command
    mov x4,x0                     // save length input
    mov x2,#0                     // indice
    mov x3,#0                     // find counter
1:
    mov x0,x8
    madd x6,x2,x10,x9              // compute address
    ldr x1,[x6,#command_name_address]  // load a item
    cbz x1,5f                     // end ?
    bl comparStringSpe            //
    cbz x0,4f                     // no found other search
    ldr x5,[x6,#command_min]
    cmp x5,#0                     // minimum = zéro ?
    ble 2f
    cmp x4,x5                     // input < command capital letters
    blt 4f                        // no correct

    add x3,x3,#1                  // else increment counter
    mov x7,x1                     // and save address command
    b 4f
2:
    mov x0,x1
    bl computeLength              // length table command
    cmp x0,x4                     // length input commant <> lenght table command
    bne 4f                        // no correct
    add x3,x3,#1                  // else increment counter
    mov x7,x1                     // and save address command
4:
    add x2,x2,#1                  // increment indice
    b 1b                          // and loop
5:
    cmp x3,#1                     // no find or multiple find ?
    bne 99f                       // error
                                  // one find
    mov x0,x7                     // length command table
    bl computeLength
    cmp x4,x0                     // length input > command ?
    bgt 99f                       // error

    mov x4,#0x20                  // 5 bit to 1
    mov x2,#0
6:
    ldrb w3,[x7,x2]
    cbz w3,7f
    bic x3,x3,x4                  // convert to capital letter
    strb w3,[x8,x2]
    add x2,x2,#1
    b 6b
7:
    strb w3,[x8,x2]
    mov x0,x8                     // return string input address
    b 100f
99:
    ldr x0,qAdrszMessErrorAbr     // return string "error"
100:
    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 x2,x3,[sp],16             // restaur des  2 registres
    ldp x1,lr,[sp],16             // restaur des  2 registres
    ret
qAdrszMessErreur:           .quad szMessErreur
qAdrszMessErrorAbr:         .quad szMessErrorAbr
/******************************************************************/
/*     comparaison first letters String                                          */
/******************************************************************/
/* x0 contains first String   */
/* x1 contains second string */
/* x0 return 0 if not find else returns number letters OK */
comparStringSpe:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    mov x2,#0
1:
    ldrb w3,[x0,x2]           // input
    orr w4,w3,#0x20           // convert capital letter
    ldrb w5,[x1,x2]           // table
    orr w6,w5,#0x20           // convert capital letter
    cmp w4,w6
    bne 2f
    cbz w3,3f                 // end strings ?
    add x2,x2,#1
    b 1b
2:
   cbz w3,3f                  // fist letters Ok
   mov x0,#0                  // no ok
   b 100f
3:
   mov x0,x2
100:
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*     compute length  String                                          */
/******************************************************************/
/* x0 contains  String   */
/* x0 return length */
computeLength:                   // INFO: functionFN
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    mov x1,#0
1:
    ldrb w2,[x0,x1]
    cbz w2,2f                    // end ?
    add x1,x1,#1
    b 1b
2:
    mov x0,x1                  // return length in x0
100:
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*     read file                                                   */
/******************************************************************/
/* x0 contains address stack begin           */
traitFic:                             // INFO: traitFic
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,fp,[sp,-16]!          // save  registres
    mov fp,x0                         //  fp <- start address
    ldr x4,[fp]                       // number of Command line arguments
    cmp x4,#1
    ble 99f
    add x5,fp,#16                      // second parameter address
    ldr x5,[x5]
    ldr x0,qAdrqAdrFicName
    str x5,[x0]
    ldr x0,qAdrszMessTitre
    bl affichageMess                  // display string
    mov x0,x5
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess                  // display carriage return

    mov x0,AT_FDCWD
    mov x1,x5                         // file name
    mov x2,#O_RDWR                    // flags
    mov x3,#0                         // mode
    mov x8, #OPEN                     // call system OPEN
    svc 0
    cmp x0,#0                         // error ?
    ble 99f
    mov x7,x0                         // File Descriptor
    ldr x1,qAdrsBufferCmd             // buffer address
    mov x2,#BUFFERSIZE                // buffer size
    mov x8,#READ                      // read file
    svc #0
    cmp x0,#0                         // error ?
    blt 99f
    // extraction datas
    ldr x1,qAdrsBufferCmd             // buffer address
    add x1,x1,x0
    mov x0,#0                         // store zéro final
    strb w0,[x1]
    ldr x0,qAdriTabAdrCmd             // key string command table
    ldr x1,qAdrsBufferCmd             // buffer address
    bl extracDatas
                                      // close file
    mov x0,x7
    mov x8, #CLOSE
    svc 0
    mov x0,#0
    b 100f
99:                                   // error
    ldr x0,qAdrszMessErreur           // error message
    bl   affichageMess
    mov x0,#-1
100:
    ldp x8,fp,[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 x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrqAdrFicName:              .quad qAdrFicName
qAdrszMessTitre:              .quad szMessTitre
qAdrsBuffer:                  .quad sBuffer
qAdrsBufferCmd:               .quad sBufferCmd
qAdriTabAdrCmd:               .quad iTabAdrCmd
/******************************************************************/
/*     extrac digit file buffer                                   */
/******************************************************************/
/* x0 contains strings address           */
/* x1 contains buffer address         */
extracDatas:                     // INFO: extracDatas
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,fp,[sp,-16]!          // save  registres
    mov x7,x0
    mov x6,x1
    mov x8,#0                    // top command name
    mov x2,#0                    // string buffer indice
    mov x4,x1                    // start string
    mov x5,#0                    // string index
1:
    ldrb w3,[x6,x2]
    cbz w3,4f                    // end
    cmp x3,#0xA
    beq 2f
    cmp x3,#' '                  // end string
    beq 3f
    add x2,x2,#1
    b 1b
2:
    mov x3,#0
    strb w3,[x6,x2]
    ldrb w3,[x6,x2]
    cmp w3,#0xD
    bne 21f
    add x2,x2,#2
    b 4f
21:
    add x2,x2,#1
    b 4f

3:
    mov x3,#0
    strb w3,[x6,x2]
    add x2,x2,#1
4:
    mov x0,x4
    ldrb w1,[x0]                // load first byte
    cmp w1,#'0'                 // it is à digit ?
    blt 5f
    cmp w1,#'9'
    bgt 5f
    mov x1,#command_end
    madd x1,x5,x1,x7              // compute address to store
    mov x0,x4
    bl conversionAtoD            // conversion ascii digit
    str x0,[x1,#command_min]     // and store in minimum
    mov x8,#0                    // line command ok
    add x5,x5,#1                    // increment indice
    b 7f
5:
    cmp x8,#0                    // other name ?
    beq 6f
    mov x0,#0                    // yes store zéro in minimum in prec
    mov x1,#command_end
    madd x1,x5,x1,x7
    add x1,x1,#command_min
    str x0,[x1]
    add x5,x5,#1                    // and increment indice
6:
    mov x8,#1                    // load name
    mov x1,#command_end
    madd x1,x5,x1,x7              // store name in table
    str x4,[x1,#command_name_address]
7:                               // loop suppress spaces
    ldrb w3,[x6,x2]
    cmp w3,#0
    beq 100f
    cmp w3,#' '
    cinc x2,x2,eq
    beq 7b

    add x4,x6,x2                 // new start address
    b 1b
100:
    ldp x8,fp,[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 x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*     control load                                      */
/******************************************************************/
/* x0 contains string table           */
controlLoad:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    mov x5,x0
    mov x6,#0
    mov x2,#command_end
1:
    madd x3,x6,x2,x5             // compute item address
    ldr x1,[x3,#command_name_address]
    cbz x1,100f
    ldr x0,qAdrszMessCtrlCom
    bl strInsertAtCharInc
    mov x4,x0
    ldr x0,[x3,#command_min]
    ldr x1,qAdrsZoneConv
    bl conversion10              // call decimal conversion
    mov x0,x4
    ldr x1,qAdrsZoneConv         // insert conversion in message
    bl strInsertAtCharInc
    bl affichageMess             // display message
    add x6,x6,#1
    b 1b

100:
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrszMessCtrlCom:       .quad szMessCtrlCom

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


with Ada.Characters.Handling;
with Ada.Containers.Vectors;
with Ada.Strings.Fixed;
with Ada.Strings.Maps.Constants;
with Ada.Strings.Unbounded;
with Ada.Text_IO;

procedure Abbreviations_Simple is

   use Ada.Strings.Unbounded;
   subtype Ustring is Unbounded_String;

   type Word_Entry is record
      Word : Ustring;
      Min  : Natural;
   end record;

   package Command_Vectors
   is new Ada.Containers.Vectors (Index_Type   => Positive,
                                  Element_Type => Word_Entry);

   Commands      : Command_Vectors.Vector;
   Last_Word     : Ustring;
   Last_Was_Word : Boolean := False;

   procedure Append (Word_List : String) is
      use Ada.Strings;

      function Is_Word (Item : String) return Boolean
      is (Fixed.Count (Item, Maps.Constants.Letter_Set) /= 0);

      procedure Process (Token : String) is
      begin
         if Is_Word (Token) then
            if Last_Was_Word then
               Commands.Append ((Word => Last_Word,
                                 Min  => Length (Last_Word)));
            end if;
            Last_Word     := To_Unbounded_String (Token);
            Last_Was_Word := True;

         else  -- Token is expected to be decimal
            Commands.Append ((Word => Last_Word,
                              Min  => Natural'Value (Token)));
            Last_Was_Word := False;
         end if;
      end Process;

      Token_First : Positive := Word_List'First;
      Token_Last  : Natural;
   begin
      while Token_First in Word_List'Range loop

         Fixed.Find_Token (Word_List, Maps.Constants.Alphanumeric_Set,
                           Token_First, Inside,
                           Token_First, Token_Last);
         exit when Token_Last = 0;

         Process (Word_List (Token_First .. Token_Last));

         Token_First := Token_Last + 1;
      end loop;
   end Append;

   function Match (Word : String) return String is
      use Ada.Characters.Handling;
      use Ada.Strings.Fixed;
      Result : Ustring := To_Unbounded_String ("*error*");
      Min    : Natural := 0;
      Upper_Word : constant String := To_Upper (Word);
   begin
      if Upper_Word = "" then
         return "";
      end if;

      for Candidate of Commands loop
         declare
            Upper_Cand : constant String  := To_Upper (To_String (Candidate.Word));
            Length     : constant Natural := Natural'Max (Candidate.Min,
                                                          Upper_Word'Length);
            Upper_Abbrev_Cand : constant String := Head (Upper_Cand, Length);
            Upper_Abbrev_Word : constant String := Head (Upper_Word, Length);
         begin
            if Upper_Word = Upper_Cand
              and then Upper_Word'Length > Min
            then
               Result := To_Unbounded_String (Upper_Cand);
               Min    := Upper_Word'Length;
            elsif Upper_Abbrev_Word = Upper_Abbrev_Cand
              and then Upper_Abbrev_Word'Length > Min
            then
               Result := To_Unbounded_String (Upper_Cand);
               Min    := Upper_Abbrev_Word'Length;
            end if;
         end;
      end loop;
      return To_String (Result);
   end Match;

   procedure Put_Match (To : String) is
      use Ada.Text_IO;
   begin
      Put ("Match to '");  Put (To);
      Put ("' is '");      Put (Match (To));
      Put_Line ("'");
   end Put_Match;

   procedure A (Item : String) renames Append;
begin
   A ("add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3");
   A ("compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate");
   A ("3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2");
   A ("forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load");
   A ("locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2");
   A ("msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3");
   A ("refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left");
   A ("2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1");

   Put_Match ("riG");
   Put_Match ("rePEAT");
   Put_Match ("copies");
   Put_Match ("put");
   Put_Match ("mo");
   Put_Match ("rest");
   Put_Match ("types");
   Put_Match ("fup.");
   Put_Match ("6");
   Put_Match ("poweRin");
   Put_Match ("");
end Abbreviations_Simple;


def ack ( m, n ) {
    assert m >= 0 && n >= 0 : 'both arguments must be non-negative'
    m == 0 ? n + 1 : n == 0 ? ack(m-1, 1) : ack(m-1, ack(m, n-1))
}


import Data.List (nub)

divisorSum :: Integral a => a -> a
divisorSum n =
  sum
    . map (\i -> sum $ nub [i, n `quot` i])
    . filter ((== 0) . (n `rem`))
    $ takeWhile ((<= n) . (^ 2)) [1 ..]

oddAbundants :: Integral a => a -> [(a, a)]
oddAbundants n =
  [ (i, divisorSum i) | i <- [n ..], odd i, divisorSum i > i * 2 ]

printAbundant :: (Int, Int) -> IO ()
printAbundant (n, s) =
  putStrLn
    $  show n
    ++ " with "
    ++ show s
    ++ " as the sum of all proper divisors."

main :: IO ()
main = do
  putStrLn "The first 25 odd abundant numbers are:"
  mapM_ printAbundant . take 25 $ oddAbundants 1
  putStrLn "The 1000th odd abundant number is:"
  printAbundant $ oddAbundants 1 !! 1000
  putStrLn "The first odd abundant number above 1000000000 is:"
  printAbundant . head . oddAbundants $ 10 ^ 9


# "Simple" abbreviations                                               #

# returns the next word from text, updating pos                        #
PRIO NEXTWORD = 1;
OP   NEXTWORD = ( REF INT pos, STRING text )STRING:
     BEGIN
        # skip spaces #
        WHILE IF pos > UPB text THEN FALSE ELSE text[ pos ] = " " FI DO pos +:= 1 OD;
        # get the word #
        STRING word := "";
        WHILE IF pos > UPB text THEN FALSE ELSE text[ pos ] /= " " FI DO
            word +:= text[ pos ];
            pos +:= 1
        OD;
        word
     END # NEXTWORD # ;
# returns text converted to upper case                                 #
OP   TOUPPER  = ( STRING text )STRING:
     BEGIN
        STRING result := text;
        FOR ch pos FROM LWB result TO UPB result DO
            IF is lower( result[ ch pos ] ) THEN result[ ch pos ] := to upper( result[ ch pos ] ) FI
        OD;
        result
     END # TOUPPER # ;
# returns text converted to an INT or -1 if text is not a number         #
OP   TOINT    = ( STRING text )INT:
     BEGIN
        INT  result     := 0;
        BOOL is numeric := TRUE;
        FOR ch pos FROM UPB text BY -1 TO LWB text WHILE is numeric DO
            CHAR c = text[ ch pos ];
            is numeric := ( c >= "0" AND c <= "9" );
            IF is numeric THEN ( result *:= 10 ) +:= ABS c - ABS "0" FI
        OD;
        IF is numeric THEN result ELSE -1 FI
     END # TOINT # ;
# returns the length of word                                             #
OP LENGTH = ( STRING word )INT: 1 + ( UPB word - LWB word );
# counts the number of commands in commands                              #
PROC count commands = ( STRING commands )INT:
     BEGIN
        INT    result         := 0;
        INT    pos            := LWB commands;
        WHILE  STRING command := pos NEXTWORD commands; command /= "" DO
            IF TOINT command < 0 THEN
                # not an abbreviation length                             #
                result +:= 1
            FI
        OD;
        result
     END # count commands # ;

# list of "commands" -  the words are optionally followed by the minimum #
#                       length of abbreviation - if there isn't a number #
#                       the command can only appear in full              #
STRING commands
   = "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 "
   + "compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate "
   + "3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 "
   + "forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load "
   + "locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 "
   + "msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 "
   + "refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left "
   + "2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1 "
   ;
# build the tables of the commands and their minimum lengths             #
PROC load commands = ( STRING commands )VOID:
     BEGIN
        INT    cmd pos        := 0;
        INT    pos            := LWB command table;
        WHILE  STRING command := pos NEXTWORD commands; command /= "" DO
            INT len := TOINT command;
            IF len >= 0 THEN
                # have an abbreviation length                            #
                IF cmd pos > 0 THEN min abbreviation[ cmd pos ] := len FI
            ELSE
                # new command                                            #
                cmd pos +:= 1;
                command table[    cmd pos ] := TOUPPER command;
                min abbreviation[ cmd pos ] := LENGTH  command
            FI
        OD
     END # load commands # ;
# searches for word in command table and returns the full command      #
# matching the possible abbreviation or *error* if there is no match   #
OP   EXPAND  = ( STRING word )STRING:
     IF word = ""
     THEN # empty word #
        ""
     ELSE # non-empty word #
        INT    word len    = LENGTH word;
        STRING upper word := TOUPPER word;
        STRING result     := "*error*";
        FOR cmd pos FROM LWB command table TO UPB command table
        WHILE  STRING command := command table[ cmd pos ];
               IF word len < min abbreviation[ cmd pos ] OR word len > LENGTH command
               THEN # word is too short or too long - try the next command #
                   TRUE
               ELIF upper word = command[ LWB command : ( LWB command - 1 ) + word len ]
               THEN # found the command #
                   result := command;
                   FALSE
               ELSE # word doexn't match - try the next command #
                   TRUE
               FI
        DO SKIP OD;
        result
     FI # EXPAND # ;

# tests the EXPAND operator                                            #
PROC test expand = ( STRING words )VOID:
     BEGIN
        STRING results := "", separator := "";
        INT    pos   := LWB words;
        WHILE STRING word = pos NEXTWORD words; word /= "" DO
            results +:= separator + EXPAND word;
            separator := " "
        OD;
        print( ( "Input:  ", words, newline ) );
        print( ( "Output: ", results, newline ) )
     END # test expand # ;

# build the command table                                              #
[ 1 : count commands( commands ) ]STRING command table;
[ 1 : UPB command table          ]INT    min abbreviation;
load commands( commands );

# task test cases                                                      #
test expand( "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin" )


use fmt;

fn ackermann(m: u64, n: u64) u64 = {
	if (m == 0) {
		return n + 1;
	};
	if (n == 0) {
		return ackermann(m - 1, 1);
	};
	return ackermann(m - 1, ackermann(m, n - 1));
};

export fn main() void = {
	for (let m = 0u64; m < 4; m += 1) {
		for (let n = 0u64; n < 10; n += 1) {
			fmt::printfln("A({}, {}) = {}", m, n, ackermann(m, n))!;
		};
		fmt::println()!;
	};
};


import java.util.ArrayList;
import java.util.List;

public class AbundantOddNumbers {
    private static List<Integer> list = new ArrayList<>();
    private static List<Integer> result = new ArrayList<>();

    public static void main(String[] args) {
        System.out.println("First 25: ");
        abundantOdd(1,100000, 25, false);

        System.out.println("\n\nThousandth: ");
        abundantOdd(1,2500000, 1000, true);

        System.out.println("\n\nFirst over 1bn:");
        abundantOdd(1000000001, 2147483647, 1, false);
    }
    private static void abundantOdd(int start, int finish, int listSize, boolean printOne) {
        for (int oddNum = start; oddNum < finish; oddNum += 2) {
            list.clear();
            for (int toDivide = 1; toDivide < oddNum; toDivide+=2) {
                if (oddNum % toDivide == 0)
                    list.add(toDivide);
            }
            if (sumList(list) > oddNum) {
                if(!printOne)
                    System.out.printf("%5d <= %5d \n",oddNum, sumList(list) );
                result.add(oddNum);
            }
            if(printOne && result.size() >= listSize)
                System.out.printf("%5d <= %5d \n",oddNum, sumList(list) );

            if(result.size() >= listSize) break;
        }
    }
    private static int sumList(List list) {
        int sum = 0;
        for (int i = 0; i < list.size(); i++) {
            String temp = list.get(i).toString();
            sum += Integer.parseInt(temp);
        }
        return sum;
    }
}


#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* command_table =
  "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 "
  "compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate "
  "3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 "
  "forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load "
  "locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 "
  "msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 "
  "refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left "
  "2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1";

typedef struct command_tag {
    char* cmd;
    size_t length;
    size_t min_len;
    struct command_tag* next;
} command_t;

// str is assumed to be all uppercase
bool command_match(const command_t* command, const char* str) {
    size_t olen = strlen(str);
    return olen >= command->min_len && olen <= command->length
        && strncmp(str, command->cmd, olen) == 0;
}

// convert string to uppercase
char* uppercase(char* str, size_t n) {
    for (size_t i = 0; i < n; ++i)
        str[i] = toupper((unsigned char)str[i]);
    return str;
}

void fatal(const char* message) {
    fprintf(stderr, "%s\n", message);
    exit(1);
}

void* xmalloc(size_t n) {
    void* ptr = malloc(n);
    if (ptr == NULL)
        fatal("Out of memory");
    return ptr;
}

void* xrealloc(void* p, size_t n) {
    void* ptr = realloc(p, n);
    if (ptr == NULL)
        fatal("Out of memory");
    return ptr;
}

char** split_into_words(const char* str, size_t* count) {
    size_t size = 0;
    size_t capacity = 16;
    char** words = xmalloc(capacity * sizeof(char*));
    size_t len = strlen(str);
    for (size_t begin = 0; begin < len; ) {
        size_t i = begin;
        for (; i < len && isspace((unsigned char)str[i]); ++i) {}
        begin = i;
        for (; i < len && !isspace((unsigned char)str[i]); ++i) {}
        size_t word_len = i - begin;
        if (word_len == 0)
            break;
        char* word = xmalloc(word_len + 1);
        memcpy(word, str + begin, word_len);
        word[word_len] = 0;
        begin += word_len;
        if (capacity == size) {
            capacity *= 2;
            words = xrealloc(words, capacity * sizeof(char*));
        }
        words[size++] = word;
    }
    *count = size;
    return words;
}

command_t* make_command_list(const char* table) {
    command_t* cmd = NULL;
    size_t count = 0;
    char** words = split_into_words(table, &count);
    for (size_t i = 0; i < count; ++i) {
        char* word = words[i];
        command_t* new_cmd = xmalloc(sizeof(command_t));
        size_t word_len = strlen(word);
        new_cmd->length = word_len;
        new_cmd->min_len = word_len;
        new_cmd->cmd = uppercase(word, word_len);
        if (i + 1 < count) {
            char* eptr = 0;
            unsigned long min_len = strtoul(words[i + 1], &eptr, 10);
            if (min_len > 0 && *eptr == 0) {
                free(words[i + 1]);
                new_cmd->min_len = min_len;
                ++i;
            }
        }
        new_cmd->next = cmd;
        cmd = new_cmd;
    }
    free(words);
    return cmd;
}

void free_command_list(command_t* cmd) {
    while (cmd != NULL) {
        command_t* next = cmd->next;
        free(cmd->cmd);
        free(cmd);
        cmd = next;
    }
}

const command_t* find_command(const command_t* commands, const char* word) {
    for (const command_t* cmd = commands; cmd != NULL; cmd = cmd->next) {
        if (command_match(cmd, word))
            return cmd;
    }
    return NULL;
}

void test(const command_t* commands, const char* input) {
    printf(" input: %s\n", input);
    printf("output:");
    size_t count = 0;
    char** words = split_into_words(input, &count);
    for (size_t i = 0; i < count; ++i) {
        char* word = words[i];
        uppercase(word, strlen(word));
        const command_t* cmd_ptr = find_command(commands, word);
        printf(" %s", cmd_ptr ? cmd_ptr->cmd : "*error*");
        free(word);
    }
    free(words);
    printf("\n");
}

int main() {
    command_t* commands = make_command_list(command_table);
    const char* input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin";
    test(commands, input);
    free_command_list(commands);
    return 0;
}


ack :: Int -> Int -> Int
ack 0 n = succ n
ack m 0 = ack (pred m) 1
ack m n = ack (pred m) (ack m (pred n))

main :: IO ()
main = mapM_ print $ uncurry ack <$> [(0, 0), (3, 4)]


(() => {
    'use strict';
    const main = () => {

        // abundantTuple :: Int -> [(Int, Int)]
        const abundantTuple = n => {
            // Either a list containing the tuple of N
            // and its divisor sum (if n is abundant),
            // or otherwise an empty list.
            const x = divisorSum(n);
            return n < x ? ([
                Tuple(n)(x)
            ]) : [];
        };

        // divisorSum :: Int -> Int
        const divisorSum = n => {
            // Sum of the divisors of n.
            const
                floatRoot = Math.sqrt(n),
                intRoot = Math.floor(floatRoot),
                lows = filter(x => 0 === n % x)(
                    enumFromTo(1)(intRoot)
                );
            return sum(lows.concat(map(quot(n))(
                intRoot === floatRoot ? (
                    lows.slice(1, -1)
                ) : lows.slice(1)
            )));
        };

        // TEST ---------------------------------------
        console.log(
            'First 25 abundant odd numbers, with their divisor sums:'
        )
        console.log(unlines(map(showTuple)(
            take(25)(
                concatMapGen(abundantTuple)(
                    enumFromThen(1)(3)
                )
            )
        )));
        console.log(
            '\n\n1000th abundant odd number, with its divisor sum:'
        )
        console.log(showTuple(
            take(1)(drop(999)(
                concatMapGen(abundantTuple)(
                    enumFromThen(1)(3)
                )
            ))[0]
        ))
        console.log(
            '\n\nFirst abundant odd number above 10^9, with divisor sum:'
        )
        const billion = Math.pow(10, 9);
        console.log(showTuple(
            take(1)(
                concatMapGen(abundantTuple)(
                    enumFromThen(1 + billion)(3 + billion)
                )
            )[0]
        ))
    };

    // GENERAL REUSABLE FUNCTIONS -------------------------

    // Tuple (,) :: a -> b -> (a, b)
    const Tuple = a => b => ({
        type: 'Tuple',
        '0': a,
        '1': b,
        length: 2
    });

    // concatMapGen :: (a -> [b]) -> Gen [a] -> Gen [b]
    const concatMapGen = f =>
        function*(xs) {
            let
                x = xs.next(),
                v = undefined;
            while (!x.done) {
                v = f(x.value);
                if (0 < v.length) {
                    yield v[0];
                }
                x = xs.next();
            }
        };

    // drop :: Int -> [a] -> [a]
    // drop :: Int -> Generator [a] -> Generator [a]
    // drop :: Int -> String -> String
    const drop = n => xs =>
        Infinity > length(xs) ? (
            xs.slice(n)
        ) : (take(n)(xs), xs);

    // dropAround :: (a -> Bool) -> [a] -> [a]
    // dropAround :: (Char -> Bool) -> String -> String
    const dropAround = p => xs => dropWhile(p)(
        dropWhileEnd(p)(xs)
    );

    // dropWhile :: (a -> Bool) -> [a] -> [a]
    // dropWhile :: (Char -> Bool) -> String -> String
    const dropWhile = p => xs => {
        const lng = xs.length;
        return 0 < lng ? xs.slice(
            until(i => i === lng || !p(xs[i]))(
                i => 1 + i
            )(0)
        ) : [];
    };

    // dropWhileEnd :: (a -> Bool) -> [a] -> [a]
    // dropWhileEnd :: (Char -> Bool) -> String -> String
    const dropWhileEnd = p => xs => {
        let i = xs.length;
        while (i-- && p(xs[i])) {}
        return xs.slice(0, i + 1);
    };

    // enumFromThen :: Int -> Int -> Gen [Int]
    const enumFromThen = x =>
        // A non-finite stream of integers,
        // starting with x and y, and continuing
        // with the same interval.
        function*(y) {
            const d = y - x;
            let v = y + d;
            yield x;
            yield y;
            while (true) {
                yield v;
                v = d + v;
            }
        };

    // enumFromTo :: Int -> Int -> [Int]
    const enumFromTo = m => n =>
        Array.from({
            length: 1 + n - m
        }, (_, i) => m + i);

    // filter :: (a -> Bool) -> [a] -> [a]
    const filter = f => xs => xs.filter(f);

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

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

    // map :: (a -> b) -> [a] -> [b]
    const map = f => xs =>
        (Array.isArray(xs) ? (
            xs
        ) : xs.split('')).map(f);

    // quot :: Int -> Int -> Int
    const quot = n => m => Math.floor(n / m);

    // show :: a -> String
    const show = JSON.stringify;

    // showTuple :: Tuple -> String
    const showTuple = tpl =>
        '(' + enumFromTo(0)(tpl.length - 1)
        .map(x => unQuoted(show(tpl[x])))
        .join(',') + ')';

    // sum :: [Num] -> Num
    const sum = xs => xs.reduce((a, x) => a + x, 0);

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = n => xs =>
        'GeneratorFunction' !== xs.constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];
        }));

    // unlines :: [String] -> String
    const unlines = xs => xs.join('\n');

    // until :: (a -> Bool) -> (a -> a) -> a -> a
    const until = p => f => x => {
        let v = x;
        while (!p(v)) v = f(v);
        return v;
    };

    // unQuoted :: String -> String
    const unQuoted = s =>
        dropAround(x => 34 === x.codePointAt(0))(
            s
        );

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


#include <algorithm>
#include <cctype>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

const char* command_table =
  "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 "
  "compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate "
  "3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 "
  "forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load "
  "locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 "
  "msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 "
  "refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left "
  "2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1";

class command {
public:
    command(const std::string&, size_t);
    const std::string& cmd() const { return cmd_; }
    size_t min_length() const { return min_len_; }
    bool match(const std::string&) const;
private:
    std::string cmd_;
    size_t min_len_;
};

// cmd is assumed to be all uppercase
command::command(const std::string& cmd, size_t min_len)
    : cmd_(cmd), min_len_(min_len) {}

// str is assumed to be all uppercase
bool command::match(const std::string& str) const {
    size_t olen = str.length();
    return olen >= min_len_ && olen <= cmd_.length()
        && cmd_.compare(0, olen, str) == 0;
}

bool parse_integer(const std::string& word, int& value) {
    try {
        size_t pos;
        int i = std::stoi(word, &pos, 10);
        if (pos < word.length())
            return false;
        value = i;
        return true;
    } catch (const std::exception& ex) {
        return false;
    }
}

// convert string to uppercase
void uppercase(std::string& str) {
    std::transform(str.begin(), str.end(), str.begin(),
        [](unsigned char c) -> unsigned char { return std::toupper(c); });
}

class command_list {
public:
    explicit command_list(const char*);
    const command* find_command(const std::string&) const;
private:
    std::vector<command> commands_;
};

command_list::command_list(const char* table) {
    std::istringstream is(table);
    std::string word;
    std::vector<std::string> words;
    while (is >> word) {
        uppercase(word);
        words.push_back(word);
    }
    for (size_t i = 0, n = words.size(); i < n; ++i) {
        word = words[i];
        // if there's an integer following this word, it specifies the minimum
        // length for the command, otherwise the minimum length is the length
        // of the command string
        int len = word.length();
        if (i + 1 < n && parse_integer(words[i + 1], len))
            ++i;
        commands_.push_back(command(word, len));
    }
}

const command* command_list::find_command(const std::string& word) const {
    auto iter = std::find_if(commands_.begin(), commands_.end(),
        [&word](const command& cmd) { return cmd.match(word); });
    return (iter != commands_.end()) ? &*iter : nullptr;
}

std::string test(const command_list& commands, const std::string& input) {
    std::string output;
    std::istringstream is(input);
    std::string word;
    while (is >> word) {
        if (!output.empty())
            output += ' ';
        uppercase(word);
        const command* cmd_ptr = commands.find_command(word);
        if (cmd_ptr)
            output += cmd_ptr->cmd();
        else
            output += "*error*";
    }
    return output;
}

int main() {
    command_list commands(command_table);
    std::string input("riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin");
    std::string output(test(commands, input));
    std::cout << " input: " << input << '\n';
    std::cout << "output: " << output << '\n';
    return 0;
}


class RosettaDemo
{
    static public function main()
    {
        Sys.print(ackermann(3, 4));
    }

    static function ackermann(m : Int, n : Int)
    {
        if (m == 0)
        {
            return n + 1;
        }
        else if (n == 0)
        {
            return ackermann(m-1, 1);
        }
        return ackermann(m-1, ackermann(m, n-1));
    }
}


# The factors, unsorted
def factors:
  . as $num
  | reduce range(1; 1 + sqrt|floor) as $i
      ([];
       if ($num % $i) == 0 then
         ($num / $i) as $r
         | if $i == $r then . + [$i] else . + [$i, $r] end
       else .
       end) ;

def abundant_odd_numbers:
  range(1; infinite; 2)
  | (factors | add) as $sum
  | select($sum > 2*.)
  | [., $sum] ;


using Primes

function propfact(n)
    f = [one(n)]
    for (p, x) in factor(n)
        f = reduce(vcat, [f*p^i for i in 1:x], init=f)
    end
    pop!(f)
    sort(f)
end

isabundant(n) = sum(propfact(n)) > n
prettyprintfactors(n) = (a = propfact(n); println("$n has proper divisors $a, these sum to $(sum(a))."))

function oddabundantsfrom(startingint, needed, nprint=0)
    n = isodd(startingint) ? startingint : startingint + 1
    count = one(n)
    while count <= needed
        if isabundant(n)
            if nprint == 0
                prettyprintfactors(n)
            elseif nprint == count
                prettyprintfactors(n)
            end
            count += 1
        end
        n += 2
    end
end

println("First 25 abundant odd numbers:")
oddabundantsfrom(2, 25)

println("The thousandth abundant odd number:")
oddabundantsfrom(2, 1001, 1000)

println("The first abundant odd number greater than one billion:")
oddabundantsfrom(1000000000, 1)


fun divisors(n: Int): List<Int> {
    val divs = mutableListOf(1)
    val divs2 = mutableListOf<Int>()

    var i = 2
    while (i * i <= n) {
        if (n % i == 0) {
            val j = n / i
            divs.add(i)
            if (i != j) {
                divs2.add(j)
            }
        }
        i++
    }

    divs.addAll(divs2.reversed())

    return divs
}

fun abundantOdd(searchFrom: Int, countFrom: Int, countTo: Int, printOne: Boolean): Int {
    var count = countFrom
    var n = searchFrom

    while (count < countTo) {
        val divs = divisors(n)
        val tot = divs.sum()
        if (tot > n) {
            count++
            if (!printOne || count >= countTo) {
                val s = divs.joinToString(" + ")
                if (printOne) {
                    println("$n < $s = $tot")
                } else {
                    println("%2d. %5d < %s = %d".format(count, n, s, tot))
                }
            }
        }

        n += 2
    }

    return n
}

fun main() {
    val max = 25
    println("The first $max abundant odd numbers are:")
    val n = abundantOdd(1, 0, 25, false)

    println("\nThe one thousandth abundant odd number is:")
    abundantOdd(n, 25, 1000, true)

    println("\nThe first abundant odd number above one billion is:")
    abundantOdd((1e9 + 1).toInt(), 0, 1, true)
}