Option Explicit
Option Base 0

Private Const intBase As Integer = 0

Private Type tPoint
	X As Double
	Y As Double
End Type
Private Type tCircle
	Centre As tPoint
	Radius As Double
End Type

Private Sub sApollonius()
    Dim Circle1 As tCircle
    Dim Circle2 As tCircle
    Dim Circle3 As tCircle
    Dim CTanTanTan(intBase + 0 to intBase + 7) As tCircle

    With Circle1
        With .Centre
            .X = 0
            .Y = 0
        End With
        .Radius = 1
    End With

    With Circle2
        With .Centre
            .X = 4
            .Y = 0
        End With
        .Radius = 1
    End With

    With Circle3
        With .Centre
            .X = 2
            .Y = 4
        End With
        .Radius = 2
    End With

    Call fApollonius(Circle1,Circle2,Circle3,CTanTanTan()))

End Sub

Public Function fApollonius(ByRef C1 As tCircle, _
                            ByRef C2 As tCircle, _
                            ByRef C3 As tCircle, _
                            ByRef CTanTanTan() As tCircle) As Boolean
' Solves the Problem of Apollonius (finding a circle tangent to three other circles in the plane)
' (x_s - x_1)^2 + (y_s - y_1)^2 = (r_s - Tan_1 * r_1)^2
' (x_s - x_2)^2 + (y_s - y_2)^2 = (r_s - Tan_2 * r_2)^2
' (x_s - x_3)^2 + (y_s - y_3)^2 = (r_s - Tan_3 * r_3)^2
' x_s = M + N * r_s
' y_s = P + Q * r_s

' Parameters:
'   C1, C2, C3 (circles in the problem)
'   Tan1 := An indication if the solution should be externally or internally tangent (+1/-1) to Circle1 (C1)
'   Tan2 := An indication if the solution should be externally or internally tangent (+1/-1) to Circle2 (C2)
'   Tan3 := An indication if the solution should be externally or internally tangent (+1/-1) to Circle3 (C3)

    Dim Tangent(intBase + 0 To intBase + 7, intBase + 0 To intBase + 2) As Integer
    Dim lgTangent As Long
    Dim Tan1 As Integer
    Dim Tan2 As Integer
    Dim Tan3 As Integer

    Dim v11 As Double
    Dim v12 As Double
    Dim v13 As Double
    Dim v14 As Double
    Dim v21 As Double
    Dim v22 As Double
    Dim v23 As Double
    Dim v24 As Double
    Dim w12 As Double
    Dim w13 As Double
    Dim w14 As Double
    Dim w22 As Double
    Dim w23 As Double
    Dim w24 As Double

    Dim p As Double
    Dim Q As Double
    Dim M As Double
    Dim N As Double

    Dim A As Double
    Dim b As Double
    Dim c As Double
    Dim D As Double

    'Check if circle centers are colinear
    If fColinearPoints(C1.Centre, C2.Centre, C3.Centre) Then
        fApollonius = False
        Exit Function
    End If

    Tangent(intBase + 0, intBase + 0) = -1
    Tangent(intBase + 0, intBase + 1) = -1
    Tangent(intBase + 0, intBase + 2) = -1

    Tangent(intBase + 1, intBase + 0) = -1
    Tangent(intBase + 1, intBase + 1) = -1
    Tangent(intBase + 1, intBase + 2) = 1

    Tangent(intBase + 2, intBase + 0) = -1
    Tangent(intBase + 2, intBase + 1) = 1
    Tangent(intBase + 2, intBase + 2) = -1

    Tangent(intBase + 3, intBase + 0) = -1
    Tangent(intBase + 3, intBase + 1) = 1
    Tangent(intBase + 3, intBase + 2) = 1

    Tangent(intBase + 4, intBase + 0) = 1
    Tangent(intBase + 4, intBase + 1) = -1
    Tangent(intBase + 4, intBase + 2) = -1

    Tangent(intBase + 5, intBase + 0) = 1
    Tangent(intBase + 5, intBase + 1) = -1
    Tangent(intBase + 5, intBase + 2) = 1

    Tangent(intBase + 6, intBase + 0) = 1
    Tangent(intBase + 6, intBase + 1) = 1
    Tangent(intBase + 6, intBase + 2) = -1

    Tangent(intBase + 7, intBase + 0) = 1
    Tangent(intBase + 7, intBase + 1) = 1
    Tangent(intBase + 7, intBase + 2) = 1

    For lgTangent = LBound(Tangent) To UBound(Tangent)
        Tan1 = Tangent(lgTangent, intBase + 0)
        Tan2 = Tangent(lgTangent, intBase + 1)
        Tan3 = Tangent(lgTangent, intBase + 2)

        v11 = 2 * (C2.Centre.X - C1.Centre.X)
        v12 = 2 * (C2.Centre.Y - C1.Centre.Y)
        v13 = (C1.Centre.X * C1.Centre.X) _
            - (C2.Centre.X * C2.Centre.X) _
            + (C1.Centre.Y * C1.Centre.Y) _
            - (C2.Centre.Y * C2.Centre.Y) _
            - (C1.Radius * C1.Radius) _
            + (C2.Radius * C2.Radius)
        v14 = 2 * (Tan2 * C2.Radius - Tan1 * C1.Radius)

        v21 = 2 * (C3.Centre.X - C2.Centre.X)
        v22 = 2 * (C3.Centre.Y - C2.Centre.Y)
        v23 = (C2.Centre.X * C2.Centre.X) _
            - (C3.Centre.X * C3.Centre.X) _
            + (C2.Centre.Y * C2.Centre.Y) _
            - (C3.Centre.Y * C3.Centre.Y) _
            - (C2.Radius * C2.Radius) _
            + (C3.Radius * C3.Radius)
        v24 = 2 * ((Tan3 * C3.Radius) - (Tan2 * C2.Radius))

        w12 = v12 / v11
        w13 = v13 / v11
        w14 = v14 / v11

        w22 = (v22 / v21) - w12
        w23 = (v23 / v21) - w13
        w24 = (v24 / v21) - w14

        p = -w23 / w22
        Q = w24 / w22
        M = -(w12 * p) - w13
        N = w14 - (w12 * Q)

        A = (N * N) + (Q * Q) - 1
        b = 2 * ((M * N) - (N * C1.Centre.X) + (p * Q) - (Q * C1.Centre.Y) + (Tan1 * C1.Radius))
        c = (C1.Centre.X * C1.Centre.X) _
          + (M * M) _
          - (2 * M * C1.Centre.X) _
          + (p * p) _
          + (C1.Centre.Y * C1.Centre.Y) _
          - (2 * p * C1.Centre.Y) _
          - (C1.Radius * C1.Radius)

        'Find a root of a quadratic equation (requires the circle centers not to be e.g. colinear)
        D = (b * b) - (4 * A * c)

        With CTanTanTan(lgTangent)
            .Radius = (-b - VBA.Sqr(D)) / (2 * A)
            .Centre.X = M + (N * .Radius)
            .Centre.Y = p + (Q * .Radius)
        End With

    Next lgTangent

    fApollonius = True

End Function


import "/dynamic" for Tuple

var Circle = Tuple.create("Circle", ["x", "y", "r"])

var solveApollonius = Fn.new { |c1, c2, c3, s1, s2, s3|
    var x1 = c1.x
    var y1 = c1.y
    var r1 = c1.r

    var x2 = c2.x
    var y2 = c2.y
    var r2 = c2.r

    var x3 = c3.x
    var y3 = c3.y
    var r3 = c3.r

    var v11 = 2 * x2 - 2 * x1
    var v12 = 2 * y2 - 2 * y1
    var v13 = x1 * x1 - x2 * x2 + y1 * y1 - y2 * y2 - r1 * r1 + r2 * r2
    var v14 = 2 * s2 * r2 - 2 * s1 * r1

    var v21 = 2 * x3 - 2 * x2
    var v22 = 2 * y3 - 2 * y2
    var v23 = x2 * x2 - x3 * x3 + y2 * y2 - y3 * y3 - r2 * r2 + r3 * r3
    var v24 = 2 * s3 * r3 - 2 * s2 * r2

    var w12 = v12 / v11
    var w13 = v13 / v11
    var w14 = v14 / v11

    var w22 = v22 / v21 - w12
    var w23 = v23 / v21 - w13
    var w24 = v24 / v21 - w14

    var p = -w23 / w22
    var q =  w24 / w22
    var m = -w12 * p - w13
    var n =  w14 - w12 * q

    var a = n * n +  q * q - 1
    var b = 2 * m * n - 2 * n * x1 + 2 * p * q - 2 * q * y1 + 2 * s1 * r1
    var c = x1 * x1 + m * m - 2 * m * x1 + p * p + y1 * y1 - 2 * p * y1 - r1 * r1

    var d = b * b - 4 * a * c
    var rs = (-b - d.sqrt) / (2 * a)
    var xs = m + n * rs
    var ys = p + q * rs
    return Circle.new(xs, ys, rs)
}

var c1 = Circle.new(0, 0, 1)
var c2 = Circle.new(4, 0, 1)
var c3 = Circle.new(2, 4, 2)
System.print("Circle%(solveApollonius.call(c1, c2, c3,  1,  1,  1))")
System.print("Circle%(solveApollonius.call(c1, c2, c3, -1, -1, -1))")


is_prime=: 1&p:@(+/)

is_prime_triangle=: {{
  NB. y is index into L and thus analogous to *a
  p=. is_prime L{~y+0 1
  if. N=y do. p return.end.
  i=. Y=. y+1
  if. p do. if. is_prime_triangle Y do. 1 return.end.end.
  while. M>i=.i+2 do.
    if. is_prime L{~y,i do.
      L=: (L{~Y,i) (i,Y)} L
      if. is_prime_triangle Y do. 1 return.end.
      L=: (L{~Y,i) (i,Y)} L
    end.
  end.
  0
}}

prime_triangle_counter=: {{
  NB. y is index into L and thus analogous to *a
  p=. is_prime L{~y+0 1
  if. N=y do.
    count=: count+p return.
  end.
  i=. Y=. y+1
  if. p do. prime_triangle_counter Y end.
  while. M>i=. i+2 do.
    if. is_prime L{~y,i do.
      L=: (L{~Y,i) (i,Y)} L
      prime_triangle_counter Y
      L=: (L{~Y,i) (i,Y)} L
    end.
  end.
  count
}}

prime_triangles=: {{
  for_k. i.y-1 do.
    L=: l=. 1+i.1+M=: 1+N=: k
    count=: 0
    prime_triangle_counter 0
    L=: l
    assert is_prime_triangle 0
    echo (8":count),' | ',3":L
  end.
}}


public class PrimeTriangle {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for (int i = 2; i <= 20; ++i) {
            int[] a = new int[i];
            for (int j = 0; j < i; ++j)
                a[j] = j + 1;
            if (findRow(a, 0, i))
                printRow(a);
        }
        System.out.println();
        StringBuilder s = new StringBuilder();
        for (int i = 2; i <= 20; ++i) {
            int[] a = new int[i];
            for (int j = 0; j < i; ++j)
                a[j] = j + 1;
            if (i > 2)
                s.append(" ");
            s.append(countRows(a, 0, i));
        }
        System.out.println(s);
        long finish = System.currentTimeMillis();
        System.out.printf("\nElapsed time: %d milliseconds\n", finish - start);
    }

    private static void printRow(int[] a) {
        for (int i = 0; i < a.length; ++i) {
            if (i != 0)
                System.out.print(" ");
            System.out.printf("%2d", a[i]);
        }
        System.out.println();
    }

    private static boolean findRow(int[] a, int start, int length) {
        if (length == 2)
            return isPrime(a[start] + a[start + 1]);
        for (int i = 1; i + 1 < length; i += 2) {
            if (isPrime(a[start] + a[start + i])) {
                swap(a, start + i, start + 1);
                if (findRow(a, start + 1, length - 1))
                    return true;
                swap(a, start + i, start + 1);
            }
        }
        return false;
    }

    private static int countRows(int[] a, int start, int length) {
        int count = 0;
        if (length == 2) {
            if (isPrime(a[start] + a[start + 1]))
                ++count;
        } else {
            for (int i = 1; i + 1 < length; i += 2) {
                if (isPrime(a[start] + a[start + i])) {
                    swap(a, start + i, start + 1);
                    count += countRows(a, start + 1, length - 1);
                    swap(a, start + i, start + 1);
                }
            }
        }
        return count;
    }

    private static void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }

    private static boolean isPrime(int n) {
        return ((1L << n) & 0x28208a20a08a28acL) != 0;
    }
}


import Data.Ord
import Data.List

divisors :: (Integral a) => a -> [a]
divisors n = filter ((0 ==) . (n `mod`)) [1 .. (n `div` 2)]

main :: IO ()
main = do
  putStrLn "divisors of 1 to 10:"
  mapM_ (print . divisors) [1 .. 10]
  putStrLn "a number with the most divisors within 1 to 20000 (number, count):"
  print $ maximumBy (comparing snd)
    [(n, length $ divisors n) | n <- [1 .. 20000]]


factors=: [: /:[email protected], */&>@{@((^ [email protected]>:)&.>/)@q:~&__
properDivisors=: factors -. ]


package main

import (
    "fmt"
    "math/rand"
    "time"
)

type mapping struct {
    item string
    pr   float64
}

func main() {
    // input mapping
    m := []mapping{
        {"aleph", 1 / 5.},
        {"beth", 1 / 6.},
        {"gimel", 1 / 7.},
        {"daleth", 1 / 8.},
        {"he", 1 / 9.},
        {"waw", 1 / 10.},
        {"zayin", 1 / 11.},
        {"heth", 1759 / 27720.}} // adjusted so that probabilities add to 1

    // cumulative probability
    cpr := make([]float64, len(m)-1)
    var c float64
    for i := 0; i < len(m)-1; i++ {
        c += m[i].pr
        cpr[i] = c
    }

    // generate
    const samples = 1e6
    occ := make([]int, len(m))
    rand.Seed(time.Now().UnixNano())
    for i := 0; i < samples; i++ {
        r := rand.Float64()
        for j := 0; ; j++ {
            if r < cpr[j] {
                occ[j]++
                break
            }
            if j == len(cpr)-1 {
                occ[len(cpr)]++
                break
            }
        }
    }

    // report
    fmt.Println("  Item  Target   Generated")
    var totalTarget, totalGenerated float64
    for i := 0; i < len(m); i++ {
        target := m[i].pr
        generated := float64(occ[i]) / samples
        fmt.Printf("%6s  %8.6f  %8.6f\n", m[i].item, target, generated)
        totalTarget += target
        totalGenerated += generated
    }
    fmt.Printf("Totals  %8.6f  %8.6f\n", totalTarget, totalGenerated)
}


using Combinatorics, Primes

function primetriangle(nrows::Integer)
    nrows < 2 && error("number of rows requested must be > 1")
    pmask, spinlock = primesmask(2 * (nrows + 1)), Threads.SpinLock()
    counts, rowstrings = [1; zeros(Int, nrows - 1)], ["" for _ in 1:nrows]
    for r in 2:nrows
        @Threads.threads for e in collect(permutations(2:2:r))
            p = zeros(Int, r - 1)
            for o in permutations(3:2:r)
                i = 0
                for (x, y) in zip(e, o)
                    p[i += 1] = x
                    p[i += 1] = y
                end
                length(e) > length(o) && (p[i += 1] = e[end])
                if pmask[p[i] + r + 1] && pmask[p[begin] + 1] && all(j -> pmask[p[j] + p[j + 1]], 1:r-2)
                    lock(spinlock)
                    if counts[r] == 0
                        rowstrings[r] = "  1" * prod([lpad(n, 3) for n in p]) * lpad(r + 1, 3) * "\n"
                    end
                    counts[r] += 1
                    unlock(spinlock)
                end
            end
        end
    end
    println("  1  2\n" * prod(rowstrings), "\n", counts)
end

@time primetriangle(16)


use strict;
use warnings;
use feature 'say';
use ntheory 'is_prime';
use List::MoreUtils qw(zip slideatatime);
use Algorithm::Combinatorics qw(permutations);

say '1 2';

my @count = (0, 0, 1);

for my $n (3..17) {
    my @even_nums = grep { 0 == $_ % 2 } 2..$n-1;
    my @odd_nums  = grep { 1 == $_ % 2 } 3..$n-1;
    for my $e (permutations [@even_nums]) {
        next if $$e[0] == 8 or $$e[0] == 14;
        my $nope = 0;
        for my $o (permutations [@odd_nums]) {
            my @list = (zip(@$e, @$o), $n);                 # 'zip' makes a list with a gap if more evens than odds
            splice @list, -2, -1 if not defined $list[-2];  # in which case splice out 'undef' in next-to-last position
            my $it = slideatatime(1, 2, @list);
            while ( my @rr = $it->() ) {
                last unless defined $rr[1];
                $nope++ and last unless is_prime $rr[0]+$rr[1];
            }
            unless ($nope) {
                say '1 ' . join ' ', @list unless $count[$n];
                $count[$n]++;
            }
            $nope = 0;
        }
    }
}

say "\n" . join ' ', @count[2..$#count];


import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class Proper{
    public static List<Integer> properDivs(int n){
        List<Integer> divs = new LinkedList<Integer>();
        if(n == 1) return divs;
        divs.add(1);
        for(int x = 2; x < n; x++){
            if(n % x == 0) divs.add(x);
        }

        Collections.sort(divs);

        return divs;
    }

    public static void main(String[] args){
        for(int x = 1; x <= 10; x++){
            System.out.println(x + ": " + properDivs(x));
        }

        int x = 0, count = 0;
        for(int n = 1; n <= 20000; n++){
            if(properDivs(n).size() > count){
                x = n;
                count = properDivs(n).size();
            }
        }
        System.out.println(x + ": " + count);
    }
}


import System.Random (newStdGen, randomRs)

dataBinCounts :: [Float] -> [Float] -> [Int]
dataBinCounts thresholds range =
  let sampleSize = length range
      xs = ((-) sampleSize . length . flip filter range . (<)) <$> thresholds
  in zipWith (-) (xs ++ [sampleSize]) (0 : xs)

main :: IO ()
main = do
  g <- newStdGen
  let fractions = recip <$> [5 .. 11] :: [Float]
      expected = fractions ++ [1 - sum fractions]
      actual =
        ((/ 1000000.0) . fromIntegral) <$>
        dataBinCounts (scanl1 (+) expected) (take 1000000 (randomRs (0, 1) g))

      piv n = take n . (++ repeat ' ')

  putStrLn "       expected     actual"
  mapM_ putStrLn $
    zipWith3
      (\l s c -> piv 7 l ++ piv 13 (show s) ++ piv 12 (show c))
      ["aleph", "beth", "gimel", "daleth", "he", "waw", "zayin", "heth"]
      expected
      actual


REAL :: trials=1E6, n=8, map(n), limit(n), expected(n), outcome(n)

expected = 1 / ($ + 4)
expected(n) = 1 - SUM(expected) + expected(n)

map = expected
map = map($) + map($-1)

DO i = 1, trials
   random = RAN(1)
   limit = random > map
   item = INDEX(limit, 0)
   outcome(item) = outcome(item) + 1
ENDDO
outcome = outcome / trials

DLG(Text=expected, Text=outcome, Y=0)


with javascript_semantics
atom t0 = time()
sequence can_follow, arrang
bool bFirst = true

function ptrs(integer res, n, done)
    -- prime triangle recursive sub-procedure
    -- on entry, arrang[done] is set and arrang[$]==n.
    -- find something/everything that fits between them.
    integer ad = arrang[done]
    if n-done<=1 then
        if can_follow[ad][n] then
            if bFirst then
                printf(1,"%s\n",join(arrang,fmt:="%d"))
                bFirst = false
            end if
            res += 1
        end if
    else
        done += 1
        -- as per talk page, we only need to examine odd
        -- numbers following an even number & vice versa
        for i=done to n-1 by 2 do
            integer ai = arrang[i]
            if can_follow[ad][ai] then
                integer aid = arrang[done]
                arrang[i] = aid
                arrang[done] = ai
                res = ptrs(res,n,done)
                arrang[i] = ai
                arrang[done] = aid
            end if
        end for
    end if
    return res
end function

function prime_triangle(integer n)
    can_follow = repeat(repeat(false,n),n)
    for i=1 to n do
        for j=1 to n do
            can_follow[i][j] = is_prime(i+j)
        end for
    end for
    arrang = tagset(n)
    bFirst = true
    return ptrs(0,n,1)
end function

sequence res = apply(tagset(20,2),prime_triangle)
printf(1,"%s\n",join(res,fmt:="%d"))
?elapsed(time()-t0)


(function () {

    // Proper divisors
    function properDivisors(n) {
        if (n < 2) return [];
        else {
            var rRoot = Math.sqrt(n),
                intRoot = Math.floor(rRoot),

                lows = range(1, intRoot).filter(function (x) {
                    return (n % x) === 0;
                });

            return lows.concat(lows.slice(1).map(function (x) {
                return n / x;
            }).reverse().slice((rRoot === intRoot) | 0));
        }
    }

    // [m..n]
    function range(m, n) {
        var a = Array(n - m + 1),
            i = n + 1;
        while (i--) a[i - 1] = i;
        return a;
    }

    var tblOneToTen = [
            ['Number', 'Proper Divisors', 'Count']
        ].concat(range(1, 10).map(function (x) {
            var ds = properDivisors(x);

            return [x, ds.join(', '), ds.length];
        })),

        dctMostBelow20k = range(1, 20000).reduce(function (a, x) {
            var lng = properDivisors(x).length;

            return lng > a.divisorCount ? {
                n: x,
                divisorCount: lng
            } : a;
        }, {
            n: 0,
            divisorCount: 0
        });

    // [[a]] -> bool -> s -> s
    function wikiTable(lstRows, blnHeaderRow, strStyle) {
        return '{| class="wikitable" ' + (
            strStyle ? 'style="' + strStyle + '"' : ''
        ) + lstRows.map(function (lstRow, iRow) {
            var strDelim = ((blnHeaderRow && !iRow) ? '!' : '|');

            return '\n|-\n' + strDelim + ' ' + lstRow.map(function (v) {
                return typeof v === 'undefined' ? ' ' : v;
            }).join(' ' + strDelim + strDelim + ' ');
        }).join('') + '\n|}';
    }

    return wikiTable(
        tblOneToTen,
        true
    ) + '\n\nMost proper divisors below 20,000:\n\n  ' + JSON.stringify(
        dctMostBelow20k
    );

})();


record Item(value, probability)

procedure find_item (items, v)
  sum := 0.0
  every item := !items do {
    if v < sum+item.probability
     then return item.value
     else sum +:= item.probability
  }
  fail # v exceeded 1.0
end

# -- helper procedures

# count the number of occurrences of i in list l,
# assuming the items are strings
procedure count (l, i)
  result := 0.0
  every x := !l do
    if x == i then result +:= 1
  return result
end

procedure rand_float ()
  return ?1000/1000.0
end

# -- test the procedure
procedure main ()
  items := [
    Item("aleph",   1/5.0),
    Item("beth",    1/6.0),
    Item("gimel",   1/7.0),
    Item("daleth",  1/8.0),
    Item("he",      1/9.0),
    Item("waw",     1/10.0),
    Item("zayin",   1/11.0),
    Item("heth",    1759/27720.0)
  ]

  # collect a sample of results
  sample := []
  every (1 to 1000000) do push (sample, find_item(items, rand_float ()))

  # return comparison of expected vs actual probability
  every item := !items do
    write (right(item.value, 7) || " " ||
           left(item.probability, 15) || " " ||
           left(count(sample, item.value)/*sample, 6))
end


my @count = 0, 0, 1;
my $lock = Lock.new;
put (1,2);

for 3..17 -> $n {
    my @even = (2..^$n).grep: * %% 2;
    my @odd  = (3..^$n).grep: so * % 2;
    @even.permutations.race.map: -> @e {
        quietly next if @e[0] == 8|14;
        my $nope = 0;
        for @odd.permutations -> @o {
            quietly next unless (@e[0] + @o[0]).is-prime;
            my @list;
            for (@list = (flat (roundrobin(@e, @o)), $n)).rotor(2 => -1) {
                $nope++ and last unless .sum.is-prime;
            }
            unless $nope {
                put '1 ', @list unless @count[$n];
                $lock.protect({ @count[$n]++ });
            }
            $nope = 0;
        }
    }
}
put "\n", @count[2..*];


fn is_prime(n: u32) -> bool {
    assert!(n < 64);
    ((1u64 << n) & 0x28208a20a08a28ac) != 0
}

fn prime_triangle_row(a: &mut [u32]) -> bool {
    if a.len() == 2 {
        return is_prime(a[0] + a[1]);
    }
    for i in (1..a.len() - 1).step_by(2) {
        if is_prime(a[0] + a[i]) {
            a.swap(i, 1);
            if prime_triangle_row(&mut a[1..]) {
                return true;
            }
            a.swap(i, 1);
        }
    }
    false
}

fn prime_triangle_count(a: &mut [u32]) -> u32 {
    let mut count = 0;
    if a.len() == 2 {
        if is_prime(a[0] + a[1]) {
            count += 1;
        }
    } else {
        for i in (1..a.len() - 1).step_by(2) {
            if is_prime(a[0] + a[i]) {
                a.swap(i, 1);
                count += prime_triangle_count(&mut a[1..]);
                a.swap(i, 1);
            }
        }
    }
    count
}

fn print(a: &[u32]) {
    if a.is_empty() {
        return;
    }
    print!("{:2}", a[0]);
    for x in &a[1..] {
        print!(" {:2}", x);
    }
    println!();
}

fn main() {
    use std::time::Instant;
    let start = Instant::now();
    for n in 2..21 {
        let mut a: Vec<u32> = (1..=n).collect();
        if prime_triangle_row(&mut a) {
            print(&a);
        }
    }
    println!();
    for n in 2..21 {
        let mut a: Vec<u32> = (1..=n).collect();
        if n > 2 {
            print!(" ");
        }
        print!("{}", prime_triangle_count(&mut a));
    }
    println!();
    let time = start.elapsed();
    println!("\nElapsed time: {} milliseconds", time.as_millis());
}


import Foundation

func isPrime(_ n: Int) -> Bool {
    guard n > 0 && n < 64 else {
        return false
    }
    return ((UInt64(1) << n) & 0x28208a20a08a28ac) != 0
}

func primeTriangleRow(_ a: inout [Int], start: Int, length: Int) -> Bool {
    if length == 2 {
        return isPrime(a[start] + a[start + 1])
    }
    for i in stride(from: 1, to: length - 1, by: 2) {
        let index = start + i
        if isPrime(a[start] + a[index]) {
            a.swapAt(index, start + 1)
            if primeTriangleRow(&a, start: start + 1, length: length - 1) {
                return true
            }
            a.swapAt(index, start + 1)
        }
    }
    return false
}

func primeTriangleCount(_ a: inout [Int], start: Int, length: Int) -> Int {
    var count = 0
    if length == 2 {
        if isPrime(a[start] + a[start + 1]) {
            count += 1
        }
    } else {
        for i in stride(from: 1, to: length - 1, by: 2) {
            let index = start + i
            if isPrime(a[start] + a[index]) {
                a.swapAt(index, start + 1)
                count += primeTriangleCount(&a, start: start + 1, length: length - 1)
                a.swapAt(index, start + 1)
            }
        }
    }
    return count
}

func printRow(_ a: [Int]) {
    if a.count == 0 {
        return
    }
    print(String(format: "%2d", a[0]), terminator: "")
    for x in a[1...] {
        print(String(format: " %2d", x), terminator: "")
    }
    print()
}

let startTime = CFAbsoluteTimeGetCurrent()

for n in 2...20 {
    var a = Array(1...n)
    if primeTriangleRow(&a, start: 0, length: n) {
        printRow(a)
    }
}
print()

for n in 2...20 {
    var a = Array(1...n)
    if n > 2 {
        print(" ", terminator: "")
    }
    print("\(primeTriangleCount(&a, start: 0, length: n))", terminator: "")
}
print()

let endTime = CFAbsoluteTimeGetCurrent()
print("\nElapsed time: \(endTime - startTime) seconds")


def count(stream): reduce stream as $i (0; . + 1);

# unordered
def proper_divisors:
  . as $n
  | if $n > 1 then 1,
      ( range(2; 1 + (sqrt|floor)) as $i
        | if ($n % $i) == 0 then $i,
            (($n / $i) | if . == $i then empty else . end)
         else empty
	 end)
    else empty
    end;

# The first integer in 1 .. n inclusive
# with the maximal number of proper divisors in that range:
def most_proper_divisors(n):
  reduce range(1; n+1) as $i
    ( [null, 0];
      count( $i | proper_divisors ) as $count
      | if $count > .[1] then [$i, $count] else . end);


function properdivisors{T<:Integer}(n::T)
    0 < n || throw(ArgumentError("number to be factored must be ≥ 0, got $n"))
    1 < n || return T[]
    !isprime(n) || return T[one(T), n]
    f = factor(n)
    d = T[one(T)]
    for (k, v) in f
        c = T[k^i for i in 0:v]
        d = d*c'
        d = reshape(d, length(d))
    end
    sort!(d)
    return d[1:end-1]
end

lo = 1
hi = 10
println("List the proper divisors for ", lo, " through ", hi, ".")
for i in lo:hi
    println(@sprintf("%4d", i), " ", properdivisors(i))
end

hi = 2*10^4
println("\nFind the numbers within [", lo, ",", hi, "] having the most divisors.")

maxdiv = 0
nlst = Int[]

for i in lo:hi
    ndiv = length(properdivisors(i))
    if ndiv > maxdiv
        maxdiv = ndiv
        nlst = [i]
    elseif ndiv == maxdiv
        push!(nlst, i)
    end
end

println(nlst, " have the maximum proper divisor count of ", maxdiv, ".")


// version 1.0.5-2

fun listProperDivisors(limit: Int) {
    if (limit < 1) return
    for(i in 1..limit) {
        print(i.toString().padStart(2) + " -> ")
        if (i == 1) {
            println("(None)")
            continue
        }
        (1..i/2).filter{ i % it == 0 }.forEach { print(" $it") }
        println()
    }
}

fun countProperDivisors(n: Int): Int {
    if (n < 2) return 0
    return (1..n/2).count { (n % it) == 0 }
}

fun main(args: Array<String>) {
    println("The proper divisors of the following numbers are :\n")
    listProperDivisors(10)
    println()
    var count: Int
    var maxCount = 0
    val most: MutableList<Int> = mutableListOf(1)
    for (n in 2..20000) {
        count = countProperDivisors(n)
        if (count == maxCount)
            most.add(n)
        else if (count > maxCount) {
            maxCount = count
            most.clear()
            most.add(n)
        }
    }
    println("The following number(s) have the most proper divisors, namely " + maxCount + "\n")
    for (n in most) println(n)
}


main=: verb define
  hdr=.  '       target   actual  '
  lbls=. ; ,:&.> ;:'aleph beth gimel daleth he waw zayin heth'
  prtn=. +/\ pt=. (, 1-+/)1r1%5+i.7
  da=.   prtn I. ?y # 0
  pa=.   y%~ +/ da =/ i.8
  hdr, lbls,. 9j6 ": |: pt,:pa
)

Note 'named abbreviations'
     hdr  (header)
     lbls (labels)
     pt   (target proportions)
     prtn (partitions corresponding to target proportions)
     da   (distribution of actual values among partitions)
     pa   (actual proportions)
)


public class Prob{
	static long TRIALS= 1000000;

	private static class Expv{
		public String name;
		public int probcount;
		public double expect;
		public double mapping;

		public Expv(String name, int probcount, double expect, double mapping){
			this.name= name;
			this.probcount= probcount;
			this.expect= expect;
			this.mapping= mapping;
		}
	}

	static Expv[] items=
			{new Expv("aleph", 0, 0.0, 0.0), new Expv("beth", 0, 0.0, 0.0),
					new Expv("gimel", 0, 0.0, 0.0),
					new Expv("daleth", 0, 0.0, 0.0),
					new Expv("he", 0, 0.0, 0.0), new Expv("waw", 0, 0.0, 0.0),
					new Expv("zayin", 0, 0.0, 0.0),
					new Expv("heth", 0, 0.0, 0.0)};

	public static void main(String[] args){
		int i, j;
		double rnum, tsum= 0.0;

		for(i= 0, rnum= 5.0;i < 7;i++, rnum+= 1.0){
			items[i].expect= 1.0 / rnum;
			tsum+= items[i].expect;
		}
		items[7].expect= 1.0 - tsum;

		items[0].mapping= 1.0 / 5.0;
		for(i= 1;i < 7;i++){
			items[i].mapping= items[i - 1].mapping + 1.0 / ((double)i + 5.0);
		}
		items[7].mapping= 1.0;

		for(i= 0;i < TRIALS;i++){
			rnum= Math.random();
			for(j= 0;j < 8;j++){
				if(rnum < items[j].mapping){
					items[j].probcount++;
					break;
				}
			}
		}

		System.out.printf("Trials: %d\n", TRIALS);
		System.out.printf("Items:          ");
		for(i= 0;i < 8;i++)
			System.out.printf("%-8s ", items[i].name);
		System.out.printf("\nTarget prob.:   ");
		for(i= 0;i < 8;i++)
			System.out.printf("%8.6f ", items[i].expect);
		System.out.printf("\nAttained prob.: ");
		for(i= 0;i < 8;i++)
			System.out.printf("%8.6f ", (double)(items[i].probcount)
					/ (double)TRIALS);
		System.out.printf("\n");

	}
}


Option Strict On
Option Explicit On

Imports System.IO

''' <summary>Find solutions to the "Prime Triangle" - a triangle of numbers that sum to primes.</summary>
Module vMain

    Public Const maxNumber As Integer = 20 ' Largest number we will consider.
    Dim prime(2 * maxNumber) As Boolean    ' prime sieve.

    ''' <returns>The number of possible arrangements of the integers for a row in the prime triangle.</returns>
    Public Function countArrangements(ByVal n As Integer) As Integer
        If n < 2 Then ' No solutions for n < 2.
            Return 0
        ElseIf n < 4 Then
            ' For 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3.
            For i As Integer = 1 To n
                Console.Out.Write(i.ToString.PadLeft(3))
            Next i
            Console.Out.WriteLine()
            Return 1
        Else
            ' 4 or more - must find the solutions.
            Dim printSolution As Boolean = true
            Dim used(n) As Boolean
            Dim number(n) As Integer
            ' The triangle row must have 1 in the leftmost and n in the rightmost elements.
            ' The numbers must alternate between even and odd in order for the sums to be prime.
            For i As Integer = 0 To n - 1
                number(i) = i Mod 2
            Next i
            used(1) = True
            number(n) = n
            used(n) = True
            ' Find the intervening numbers and count the solutions.
            Dim count As Integer = 0
            Dim p As Integer = 2
            Do While p > 0
                Dim p1 As Integer = number(p - 1)
                Dim current As Integer = number(p)
                Dim [next] As Integer = current + 2
                Do While [next] < n AndAlso (Not prime(p1 + [next]) Or used([next]))
                    [next] += 2
                Loop
                If [next] >= n Then
                    [next] = 0
                End If
                If p = n - 1 Then
                    ' We are at the final number before n.
                    ' It must be the final even/odd number preceded by the final odd/even number.
                    If [next] <> 0 Then
                        ' Possible solution.
                        If prime([next] + n) Then
                            ' Found a solution.
                            count += 1
                            If printSolution Then
                                For i As Integer = 1 To n - 2
                                     Console.Out.Write(number(i).ToString.PadLeft(3))
                                Next i
                                Console.Out.WriteLine([next].ToString.PadLeft(3) & n.ToString.PadLeft(3))
                                printSolution = False
                            End If
                        End If
                        [next] = 0
                    End If
                    ' Backtrack for more solutions.
                    p -= 1
                    ' There will be a further backtrack as next is 0 ( there could only be one possible number at p - 1 ).
                End If
                If [next] <> 0 Then
                    ' have a/another number that can appear at p.
                    used(current) = False
                    used([next]) = True
                    number(p) = [next]
                    ' Haven't found all the intervening digits yet.
                    p += 1
                ElseIf p <= 2 Then
                    ' No more solutions.
                    p = 0
                Else
                    ' Can't find a number for this position, backtrack.
                    used(number(p)) = False
                    number(p) = p Mod 2
                    p -= 1
                End If
            Loop
            Return count
        End If
    End Function

    Public Sub Main
        prime(2) = True
        For i As Integer = 3 To UBound(prime) Step  2
            prime(i) = True
        Next i
        For i As Integer = 3 To Convert.ToInt32(Math.Floor(Math.Sqrt(Ubound(prime)))) Step 2
            If prime(i) Then
                For s As Integer = i * i To Ubound(prime) Step i + i
                    prime(s) = False
                Next s
            End If
        Next i

        Dim  arrangements(maxNumber) As Integer
        For n As Integer = 2 To UBound(arrangements)
            arrangements(n) = countArrangements(n)
        Next n
        For n As Integer = 2 To UBound(arrangements)
            Console.Out.Write(" " & arrangements(n))
        Next n
        Console.Out.WriteLine()

    End Sub

End Module


-- Return a table of the proper divisors of n
function propDivs (n)
    if n < 2 then return {} end
    local divs, sqr = {1}, math.sqrt(n)
    for d = 2, sqr do
        if n % d == 0 then
            table.insert(divs, d)
            if d ~= sqr then table.insert(divs, n/d) end
        end
    end
    table.sort(divs)
    return divs
end

-- Show n followed by all values in t
function show (n, t)
    io.write(n .. ":\t")
    for _, v in pairs(t) do io.write(v .. " ") end
    print()
end

-- Main procedure
local mostDivs, numDivs, answer = 0
for i = 1, 10 do show(i, propDivs(i)) end
for i = 1, 20000 do
    numDivs = #propDivs(i)
    if numDivs > mostDivs then
        mostDivs = numDivs
        answer = i
    end
end
print(answer .. " has " .. mostDivs .. " proper divisors.")


ProperDivisors[n_Integer /; n > 0] := [email protected]@n;


var probabilities = {
    aleph:  1/5.0,
    beth:   1/6.0,
    gimel:  1/7.0,
    daleth: 1/8.0,
    he:     1/9.0,
    waw:    1/10.0,
    zayin:  1/11.0,
    heth:   1759/27720
};

var sum = 0;
var iterations = 1000000;
var cumulative = {};
var randomly = {};
for (var name in probabilities) {
    sum += probabilities[name];
    cumulative[name] = sum;
    randomly[name] = 0;
}
for (var i = 0; i < iterations; i++) {
    var r = Math.random();
    for (var name in cumulative) {
        if (r <= cumulative[name]) {
            randomly[name]++;
            break;
        }
    }
}
for (var name in probabilities)
    // using WSH
    WScript.Echo(name + "\t" + probabilities[name] + "\t" + randomly[name]/iterations);


using Printf

p = [1/i for i in 5:11]
plen = length(p)
q = [0.0, [sum(p[1:i]) for i = 1:plen]]
plab = [char(i) for i in 0x05d0:(0x05d0+plen)]
hi = 10^6
push!(p, 1.0 - sum(p))
plen += 1

accum = zeros(Int, plen)

for i in 1:hi
    accum[sum(rand() .>= q)] += 1
end

r = accum/hi

println("Rates at which items are selected (", hi, " trials).")
println(" Item  Expected   Actual")
for i in 1:plen
    println(@sprintf("   \u2067%s   %8.6f  %8.6f", plab[i], p[i], r[i]))
end

println()
println("Rates at which items are selected (", hi, " trials).")
println(" Item         Count   Expected   Actual")
for i in 1:plen
    println(@sprintf("   %s yields  %6d   %8.6f  %8.6f",
                     plab[i], accum[i], p[i], r[i]))
end


import "./fmt" for Fmt

var canFollow = []
var arrang = []
var bFirst = true

var pmap = {}
for (i in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]) {
    pmap[i] = true
}

var ptrs
ptrs = Fn.new { |res, n, done|
    var ad = arrang[done-1]
    if (n - done <= 1) {
        if (canFollow[ad-1][n-1]) {
            if (bFirst) {
                Fmt.print("$2d", arrang)
                bFirst = false
            }
            res = res + 1
        }
    } else {
        done = done + 1
        var i = done - 1
        while (i <= n-2) {
            var ai = arrang[i]
            if (canFollow[ad-1][ai-1]) {
                arrang.swap(i, done-1)
                res = ptrs.call(res, n, done)
                arrang.swap(i, done-1)
            }
            i = i + 2
        }
    }
    return res
}

var primeTriangle = Fn.new { |n|
    canFollow = List.filled(n, null)
    for (i in 0...n) {
        canFollow[i] = List.filled(n, false)
        for (j in 0...n) canFollow[i][j] = pmap.containsKey(i+j+2)
    }
    bFirst = true
    arrang = (1..n).toList
    return ptrs.call(0, n, 1)
}

var counts = []
for (i in 2..20) {
    counts.add(primeTriangle.call(i))
}
System.print()
System.print(counts.join(" "))


function D=pd(N)
K=1:ceil(N/2);
D=K(~(rem(N, K)));


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

PROCEDURE WriteInt(n : INTEGER);
VAR buf : ARRAY[0..15] OF CHAR;
BEGIN
    FormatString("%i", buf, n);
    WriteString(buf)
END WriteInt;

PROCEDURE proper_divisors(n : INTEGER; print_flag : BOOLEAN) : INTEGER;
VAR count,i : INTEGER;
BEGIN
    count := 0;
    FOR i:=1 TO n-1 DO
        IF n MOD i = 0 THEN
            INC(count);
            IF print_flag THEN
                WriteInt(i);
                WriteString(" ")
            END
        END
    END;
    IF print_flag THEN WriteLn END;
    RETURN count;
END proper_divisors;

VAR
    buf : ARRAY[0..63] OF CHAR;
    i,max,max_i,v : INTEGER;
BEGIN
    FOR i:=1 TO 10 DO
        WriteInt(i);
        WriteString(": ");
        proper_divisors(i, TRUE)
    END;

    max := 0;
    max_i := 1;

    FOR i:=1 TO 20000 DO
        v := proper_divisors(i, FALSE);
        IF v>= max THEN
            max := v;
            max_i := i
        END
    END;

    FormatString("%i with %i divisors\n", buf, max_i, max);
    WriteString(buf);

    ReadChar
END ProperDivisors.


// version 1.0.6

fun main(args: Array<String>) {
    val letters  = arrayOf("aleph", "beth", "gimel", "daleth", "he", "waw", "zayin", "heth")
    val actual   = IntArray(8)
    val probs    = doubleArrayOf(1/5.0, 1/6.0, 1/7.0, 1/8.0, 1/9.0, 1/10.0, 1/11.0, 0.0)
    val cumProbs = DoubleArray(8)

    cumProbs[0] = probs[0]
    for (i in 1..6) cumProbs[i] = cumProbs[i - 1] + probs[i]
    cumProbs[7] = 1.0
    probs[7] = 1.0 - cumProbs[6]
    val n = 1000000
    (1..n).forEach {
        val rand = Math.random()
        when {
             rand <= cumProbs[0] -> actual[0]++
             rand <= cumProbs[1] -> actual[1]++
             rand <= cumProbs[2] -> actual[2]++
             rand <= cumProbs[3] -> actual[3]++
             rand <= cumProbs[4] -> actual[4]++
             rand <= cumProbs[5] -> actual[5]++
             rand <= cumProbs[6] -> actual[6]++
             else                -> actual[7]++
        }
    }

    var sumActual = 0.0
    println("Letter\t Actual    Expected")
    println("------\t--------   --------")
    for (i in 0..7) {
        val generated = actual[i].toDouble() / n
        println("${letters[i]}\t${String.format("%8.6f   %8.6f", generated, probs[i])}")
        sumActual += generated
    }
    println("\t--------   --------")
    println("\t${"%8.6f".format(sumActual)}   1.000000")
}


import strformat

proc properDivisors(n: int) =
  var count = 0
  for i in 1..<n:
    if n mod i == 0:
      inc count
      write(stdout, fmt"{i} ")
  write(stdout, "\n")

proc countProperDivisors(n: int): int =
  var nn = n
  var prod = 1
  var count = 0
  while nn mod 2 == 0:
    inc count
    nn = nn div 2
  prod *= (1 + count)
  for i in countup(3, n, 2):
    count = 0
    while nn mod i == 0:
      inc count
      nn = nn div i
    prod *= (1 + count)
  if nn > 2:
    prod *= 2
  prod - 1

for i in 1..10:
  write(stdout, fmt"{i:2}: ")
  properDivisors(i)

var max = 0
var maxI = 1

for i in 1..20000:
  var v = countProperDivisors(i)
  if v >= max:
    max = v
    maxI = i

echo fmt"{maxI} with {max} divisors"


MODULE ProperDivisors;
IMPORT
  Out;

CONST
    initialSize = 128;
TYPE
  Result* = POINTER TO ResultDesc;
  ResultDesc = RECORD
    found-: LONGINT; (* number of slots in pd *)
    pd-: POINTER TO ARRAY OF LONGINT;
    cap: LONGINT;   (* Capacity *)
  END;

VAR
  i,found,max,idxMx: LONGINT;
  mx: ARRAY 32 OF LONGINT;
  rs: Result;

  PROCEDURE (r: Result) Init(size: LONGINT);
  BEGIN
    r.found := 0;
    r.cap := size;
    NEW(r.pd,r.cap);
  END Init;

  PROCEDURE (r: Result) Add(n: LONGINT);
  BEGIN
    (* Out.String("--->");Out.LongInt(n,0);Out.String(" At: ");Out.LongInt(r.found,0);Out.Ln; *)
    IF (r.found < LEN(r.pd^) - 1) THEN
      r.pd[r.found] := n;
    ELSE
      (* expand pd for more room *)
    END;
    INC(r.found);
  END Add;

  PROCEDURE (r:Result) Show();
  VAR
    i: LONGINT;
  BEGIN
      Out.String("(Result:");Out.LongInt(r.found + 1,0);(* Out.String("/");Out.LongInt(r.cap,0);*)
      Out.String("-");
      IF r.found > 0 THEN
        FOR i:= 0 TO r.found - 1 DO
          Out.LongInt(r.pd[i],0);
          IF i = r.found - 1 THEN Out.Char(')') ELSE Out.Char(',') END
        END
      END;
      Out.Ln
  END Show;

  PROCEDURE (r:Result) Reset();
  BEGIN
    r.found := 0;
  END Reset;

  PROCEDURE GetFor(n: LONGINT;VAR rs: Result);
  VAR
    i: LONGINT;
  BEGIN
    IF n > 1 THEN
      rs.Add(1);i := 2;
      WHILE (i < n) DO
        IF (n MOD i) = 0 THEN rs.Add(i) END;
        INC(i)
      END
    END;
  END GetFor;

BEGIN
  NEW(rs);rs.Init(initialSize);
  FOR i := 1 TO 10 DO
    Out.LongInt(i,4);Out.Char(':');
    GetFor(i,rs);
    rs.Show();
    rs.Reset();
  END;
  Out.LongInt(100,4);Out.Char(':');GetFor(100,rs);rs.Show();rs.Reset();
  max := 0;idxMx := 0;found := 0;
  FOR i := 1 TO 20000 DO
    GetFor(i,rs);
    IF rs.found > max THEN
      idxMx:= 0;mx[idxMx] := i;max := rs.found
    ELSIF rs.found = max THEN
      INC(idxMx);mx[idxMx] := i
    END;
    rs.Reset()
  END;
  Out.String("Found: ");Out.LongInt(idxMx + 1,0);
  Out.String(" Numbers with most proper divisors ");
  Out.LongInt(max,0);Out.String(": ");Out.Ln;
  FOR i := 0 TO idxMx DO
    Out.LongInt(mx[i],0);Out.Ln
  END
END ProperDivisors.


names$="aleph beth gimel daleth he waw zayin heth"
dim sum(8)
dim counter(8)

s = 0
for i = 1 to 7
    s = s+1/(i+4)
    sum(i)=s
next

N =1000000     '  number of throws

for i =1 to N
    rand =rnd( 1)
    for j = 1 to 7
        if sum(j)> rand then exit for
    next
    counter(j)=counter(j)+1
next

print "Observed", "Intended"
for i = 1 to 8
    print word$(names$, i), using( "#.#####", counter(i)  /N), using( "#.#####", 1/(i+4))
next


items = {}
items["aleph"]  = 1/5.0
items["beth"]   = 1/6.0
items["gimel"]  = 1/7.0
items["daleth"] = 1/8.0
items["he"]     = 1/9.0
items["waw"]    = 1/10.0
items["zayin"]  = 1/11.0
items["heth"]   = 1759/27720

num_trials = 1000000

samples = {}
for item, _ in pairs( items ) do
    samples[item] = 0
end

math.randomseed( os.time() )
for i = 1, num_trials do
    z = math.random()

    for item, _ in pairs( items ) do
	if z < items[item] then
	    samples[item] = samples[item] + 1
	    break;
	else
 	    z = z - items[item]
	end
    end
end

for item, _ in pairs( items ) do
    print( item, samples[item]/num_trials, items[item] )
end


use Collection;

class Proper{
  function : Main(args : String[]) ~ Nil {
    for(x := 1; x <= 10; x++;) {
      Print(x, ProperDivs(x));
    };

    x := 0;
    count := 0;

    for(n := 1; n <= 20000; n++;) {
      if(ProperDivs(n)->Size() > count) {
        x := n;
        count := ProperDivs(n)->Size();
      };
    };
    "{$x}: {$count}"->PrintLine();
  }

  function : ProperDivs(n : Int) ~ IntVector {
    divs := IntVector->New();

    if(n = 1) {
      return divs;
    };
    divs->AddBack(1);

    for(x := 2; x < n; x++;) {
      if(n % x = 0) {
        divs->AddBack(x);
      };
    };
    divs->Sort();

    return divs;
  }

  function : Print(x : Int, result : IntVector) ~ Nil {
    "{$x}: "->Print();
    result->ToArray()->ToString()->PrintLine();
  }
}


function probChoice
    choices = {'aleph' 'beth' 'gimel' 'daleth' 'he' 'waw' 'zayin' 'heth'};
    w = [1/5 1/6 1/7 1/8 1/9 1/10 1/11 1759/27720];
    R = randsample(length(w), 1e6, true, w);
    T = tabulate(R);
    fprintf('Value\tCount\tPercent\tGoal\n')
    for k = 1:size(T, 1)
        fprintf('%6s\t%.f\t%.2f%%\t%.2f%%\n', ...
            choices{k}, T(k, 2), T(k, 3), 100*w(k))
    end
end


Integer method: properDivs  self 2 / seq filter(#[ self swap mod 0 == ]) }

10 seq apply(#[ dup print " : " print properDivs println ])
20000 seq map(#[ dup properDivs size Pair new ]) reduce(#maxKey) println


import tables, random, strformat, times

var start = cpuTime()

const
  NumTrials = 1_000_000
  Probabilities = {"aleph": 1 / 5, "beth": 1 / 6, "gimel": 1 / 7, "daleth": 1 / 8,
                   "he": 1 / 9, "waw": 1 / 10, "zayin": 1 / 11, "heth": 1759 / 27720}.toTable

var samples: CountTable[string]

randomize()

for i in 1 .. NumTrials:
  var z = rand(1.0)
  for item, prob in Probabilities.pairs:
    if z < prob:
      samples.inc(item)
      break
    else:
      z -= prob

var s1, s2 = 0.0

echo " Item    Target     Results   Differences"
echo "======  ========   ========   ==========="
for item, prob in Probabilities.pairs:
  let r = samples[item] / NumTrials
  s1 += r * 100
  s2 += prob * 100
  echo &"{item:<6}  {prob:.6f}   {r:.6f}   {100 * (1 - r / prob):9.6f} %"
echo "======  ========   ======== "
echo &"Total:  {s2:^8.2f}   {s1:^8.2f}"
echo &"\nExecution time: {cpuTime()-start:.2f} s"


let p = [
    "Aleph",   1.0 /. 5.0;
    "Beth",    1.0 /. 6.0;
    "Gimel",   1.0 /. 7.0;
    "Daleth",  1.0 /. 8.0;
    "He",      1.0 /. 9.0;
    "Waw",     1.0 /. 10.0;
    "Zayin",   1.0 /. 11.0;
    "Heth", 1759.0 /. 27720.0;
  ]

let rec take k = function
  | (v, p)::tl -> if k < p then v else take (k -. p) tl
  | _ -> invalid_arg "take"

let () =
  let n = 1_000_000 in
  Random.self_init();
  let h = Hashtbl.create 3 in
  List.iter (fun (v, _) -> Hashtbl.add h v 0) p;
  let tot = List.fold_left (fun acc (_, p) -> acc +. p) 0.0 p in
  for i = 1 to n do
    let sel = take (Random.float tot) p in
    let n = Hashtbl.find h sel in
    Hashtbl.replace h sel (succ n)  (* count the number of each item *)
  done;
  List.iter (fun (v, p) ->
    let d = Hashtbl.find h v in
    Printf.printf "%s \t %f %f\n" v p (float d /. float n)
  ) p


{$IFDEF FPC}{$MODE DELPHI}{$ELSE}{$APPTYPE CONSOLE}{$ENDIF}
uses
  sysutils;
const
  MAXPROPERDIVS = 1920;
type
  tRes = array[0..MAXPROPERDIVS] of LongWord;
  tPot = record
           potPrim,
           potMax :LongWord;
         end;

  tprimeFac = record
                 pfPrims : array[1..10] of tPot;
                 pfCnt,
                 pfNum   : LongWord;
               end;
  tSmallPrimes = array[0..6541] of longWord;

var
  SmallPrimes: tSmallPrimes;

procedure InitSmallPrimes;
var
  pr,testPr,j,maxprimidx: Longword;
  isPrime : boolean;
Begin
  maxprimidx := 0;
  SmallPrimes[0] := 2;
  pr := 3;
  repeat
    isprime := true;
    j := 0;
    repeat
      testPr := SmallPrimes[j];
      IF testPr*testPr > pr then
        break;
      If pr mod testPr = 0 then
      Begin
        isprime := false;
        break;
      end;
      inc(j);
    until false;

    if isprime then
    Begin
      inc(maxprimidx);
      SmallPrimes[maxprimidx]:= pr;
    end;
    inc(pr,2);
  until pr > 1 shl 16 -1;
end;

procedure PrimeFacOut(primeDecomp:tprimeFac);
var
  i : LongWord;
begin
  with primeDecomp do
  Begin
    write(pfNum,' = ');
    For i := 1 to pfCnt-1 do
      with pfPrims[i] do
        If potMax = 1 then
          write(potPrim,'*')
        else
          write(potPrim,'^',potMax,'*');
    with pfPrims[pfCnt] do
      If potMax = 1 then
        write(potPrim)
      else
        write(potPrim,'^',potMax);
  end;
end;

procedure PrimeDecomposition(n:LongWord;var res:tprimeFac);
var
  i,pr,cnt,quot{to minimize divisions} : LongWord;
Begin
  res.pfNum := n;
  res.pfCnt:= 0;
  i := 0;
  cnt := 0;
  repeat
    pr := SmallPrimes[i];
    IF pr*pr>n then
      Break;

    quot := n div pr;
    IF pr*quot = n then
      with res do
      Begin
        inc(pfCnt);
        with pfPrims[pfCnt] do
        Begin
          potPrim := pr;
          potMax := 0;
          repeat
            n := quot;
            quot := quot div pr;
            inc(potMax);
          until pr*quot <> n;
        end;
      end;
     inc(i);
  until false;
  //a big prime left over?
  IF n <> 1 then
    with res do
    Begin
      inc(pfCnt);
      with pfPrims[pfCnt] do
      Begin
        potPrim := n;
        potMax := 1;
      end;
    end;
end;

function CntProperDivs(const primeDecomp:tprimeFac):LongWord;
//count of proper divisors
var
   i: LongWord;
begin
  result := 1;
  with primeDecomp do
    For i := 1 to pfCnt do
      result := result*(pfPrims[i].potMax+1);
  //remove
  dec(result);
end;

function findProperdivs(n:LongWord;var res:TRes):LongWord;
//simple trial division to get a sorted list of all proper divisors
var
  i,j: LongWord;
Begin
  result := 0;
  i := 1;
  j := n;
  while j>i do
  begin
    j := n DIV i;
    IF i*j = n then
    Begin
      //smaller factor part at the beginning upwards
      res[result]:= i;
      IF i <> j then
        //bigger factor at the end downwards
        res[MAXPROPERDIVS-result]:= j
      else
        //n is square number
        res[MAXPROPERDIVS-result]:= 0;
      inc(result);
    end;
    inc(i);
  end;

  If result>0 then
  Begin
    //move close together
    i := result;
    j := MAXPROPERDIVS-result+1;
    result := 2*result-1;
    repeat
      res[i] := res[j];
      inc(j);
      inc(i);
    until i > result;

    if res[result-1] = 0 then
      dec(result);
  end;
end;

procedure AllFacsOut(n: Longword);
var
  res:TRes;
  i,k,j:LongInt;
Begin
   j := findProperdivs(n,res);
   write(n:5,' : ');
   For k := 0 to j-2 do write(res[k],',');
   IF j>=1 then
     write(res[j-1]);
   writeln;
end;

var
  primeDecomp: tprimeFac;
  rs : tRes;
  i,j,max,maxcnt: LongWord;
BEGIN
  InitSmallPrimes;
  For i := 1 to 10 do
    AllFacsOut(i);
  writeln;
  max    := 0;
  maxCnt := 0;
  For i := 1 to 20*1000 do
  Begin
    PrimeDecomposition(i,primeDecomp);
    j := CntProperDivs(primeDecomp);
    IF j> maxCnt then
    Begin
      maxcnt := j;
      max := i;
    end;
  end;
  PrimeDecomposition(max,primeDecomp);
  j := CntProperDivs(primeDecomp);

  PrimeFacOut(primeDecomp);writeln('  ',j:10,' factors'); writeln;
  //https://en.wikipedia.org/wiki/Highly_composite_number <= HCN
  //http://wwwhomes.uni-bielefeld.de/achim/highly.txt the first 1200 HCN
  max := 3491888400;
  PrimeDecomposition(max,primeDecomp);
  j := CntProperDivs(primeDecomp);
  PrimeFacOut(primeDecomp);writeln('  ',j:10,' factors'); writeln;
END.


use ntheory qw/divisors/;
sub proper_divisors {
  my $n = shift;
  # Like Pari/GP, divisors(0) = (0,1) and divisors(1) = ()
  return 1 if $n == 0;
  my @d = divisors($n);
  pop @d;  # divisors are in sorted order, so last entry is the input
  @d;
}
say "$_: ", join " ", proper_divisors($_) for 1..10;
# 1. For the max, we can do a traditional loop.
my($max,$ind) = (0,0);
for (1..20000) {
  my $nd = scalar proper_divisors($_);
 ($max,$ind) = ($nd,$_) if $nd > $max;
}
say "$max $ind";
# 2. Or we can use List::Util's max with decoration (this exploits its implementation)
{
  use List::Util qw/max/;
  no warnings 'numeric';
  say max(map { scalar(proper_divisors($_)) . " $_" } 1..20000);
}


global function factors(atom n, integer include1=0)
--
-- returns a list of all integer factors of n
--  if include1 is 0 (the default), result does not contain either 1 or n
--  if include1 is 1 the result contains 1 and n
--  if include1 is -1 the result contains 1 but not n
--
    if n=0 then return {} end if
    check_limits(n,"factors")
    sequence lfactors = {}, hfactors = {}
    atom hfactor
    integer p = 2,
            lim = floor(sqrt(n))

    if include1!=0 then
        lfactors = {1}
        if n!=1 and include1=1 then
            hfactors = {n}
        end if
    end if
    while p<=lim do
        if remainder(n,p)=0 then
            lfactors = append(lfactors,p)
            hfactor = n/p
            if hfactor=p then exit end if
            hfactors = prepend(hfactors,hfactor)
        end if
        p += 1
    end while
    return lfactors & hfactors
end function


use List::Util qw(first sum);
use constant TRIALS => 1e6;

sub prob_choice_picker {
  my %options = @_;
  my ($n, @a) = 0;
  while (my ($k,$v) = each %options) {
      $n += $v;
      push @a, [$n, $k];
  }
  return sub {
      my $r = rand;
      ( first {$r <= $_->[0]} @a )->[1];
  };
}

my %ps =
  (aleph  => 1/5,
   beth   => 1/6,
   gimel  => 1/7,
   daleth => 1/8,
   he     => 1/9,
   waw    => 1/10,
   zayin  => 1/11);
$ps{heth} = 1 - sum values %ps;

my $picker = prob_choice_picker %ps;
my %results;
for (my $n = 0 ; $n < TRIALS ; ++$n) {
    ++$results{$picker->()};
}

print "Event   Occurred  Expected  Difference\n";
foreach (sort {$results{$b} <=> $results{$a}} keys %results) {
    printf "%-6s  %f  %f  %f\n",
        $_, $results{$_}/TRIALS, $ps{$_},
        abs($results{$_}/TRIALS - $ps{$_});
}


<?php
function ProperDivisors($n) {
  yield 1;
  $large_divisors = [];
  for ($i = 2; $i <= sqrt($n); $i++) {
    if ($n % $i == 0) {
      yield $i;
      if ($i*$i != $n) {
        $large_divisors[] = $n / $i;
      }
    }
  }
  foreach (array_reverse($large_divisors) as $i) {
    yield $i;
  }
}

assert([1, 2, 4, 5, 10, 20, 25, 50] ==
        iterator_to_array(ProperDivisors(100)));

foreach (range(1, 10) as $n) {
  echo "$n =>";
  foreach (ProperDivisors($n) as $divisor) {
    echo " $divisor";
  }
  echo "\n";
}

$divisorsCount = [];
for ($i = 1; $i < 20000; $i++) {
  $divisorsCount[sizeof(iterator_to_array(ProperDivisors($i)))][] = $i;
}
ksort($divisorsCount);

echo "Numbers with most divisors: ", implode(", ", end($divisorsCount)), ".\n";
echo "They have ", key($divisorsCount), " divisors.\n";


with javascript_semantics
constant lim = 1000000,
{names, probs} = columnize({{"aleph",   1/5},
                            {"beth",    1/6},
                            {"gimel",   1/7},
                            {"daleth",  1/8},
                            {"he",      1/9},
                            {"waw",     1/10},
                            {"zayin",   1/11},
                            {"heth",    1759/27720}})
sequence results = repeat(0,length(names))
for j=1 to lim do
    atom r = rnd()
    for i=1 to length(probs) do
        r -= probs[i]
        if r<=0 then
            results[i]+=1
            exit
        end if
    end for
end for

printf(1,"  Name   Actual Expected\n")
for i=1 to length(probs) do
    printf(1,"%6s %8.6f %8.6f\n",{names[i],results[i]/lim,probs[i]})
end for


go =>
  println(11111=proper_divisors(11111)),
  nl,
  foreach(N in 1..10)
    println(N=proper_divisors(N))
  end,
  nl,

  find_most_divisors(20_000),
  nl.

% Proper divisors of number N
proper_divisors(N) = Divisors =>
  Div1 = [ I : I in 1..ceiling(sqrt(N)), N mod I == 0],
  Divisors = (Div1 ++ [N div I : I in Div1]).sort_remove_dups().delete(N).

% Find the number(s) with the most proper divisors below Limit
find_most_divisors(Limit) =>
  MaxN = [],
  MaxNumDivisors = [],
  MaxLen = 1,

  foreach(N in 1..Limit, not prime(N))
    D = proper_divisors(N),
    Len = D.len,
    % Get all numbers with most proper divisors
    if Len = MaxLen then
      MaxN := MaxN ++ [N],
      MaxNumDivisors := MaxNumDivisors ++ [[N=D]]
    elseif Len > MaxLen then
      MaxLen := Len,
      MaxN := [N],
      MaxNumDivisors := [N=D]
    end
  end,

  println(maxN=MaxN),
  println(maxLen=MaxLen),
  nl.


# Generate all proper divisors.
(de propdiv (N)
   (head -1 (filter
      '((X) (=0 (% N X)))
      (range 1 N) )) )

# Obtaining the values from 1 to 10 inclusive.
(mapcar propdiv (range 1 10))
# Output:
# (NIL (1) (1) (1 2) (1) (1 2 3) (1) (1 2 4) (1 3) (1 2 5))


*process source xref;
 (subrg):
 cpd: Proc Options(main);
 p9a=time();
 Dcl (p9a,p9b) Pic'(9)9';
 Dcl cnt(3) Bin Fixed(31) Init((3)0);
 Dcl x Bin Fixed(31);
 Dcl pd(300) Bin Fixed(31);
 Dcl sumpd   Bin Fixed(31);
 Dcl npd     Bin Fixed(31);
 Dcl hi      Bin Fixed(31) Init(0);
 Dcl (xl(10),xi) Bin Fixed(31);
 Dcl i       Bin Fixed(31);
 Do x=1 To 10;
   Call proper_divisors(x,pd,npd);
   Put Edit(x,' -> ',(pd(i) Do i=1 To npd))(Skip,f(2),a,10(f(2)));
   End;
 xi=0;
 Do x=1 To 20000;
   Call proper_divisors(x,pd,npd);
   Select;
     When(npd>hi) Do;
       xi=1;
       xl(1)=x;
       hi=npd;
       End;
     When(npd=hi) Do;
       xi+=1;
       xl(xi)=x;
       End;
     Otherwise;
     End;
   End;
 Put Edit(hi,' -> ',(xl(i) Do i=1 To xi))(Skip,f(3),a,10(f(6)));

 x= 166320; Call proper_divisors(x,pd,npd);
 Put Edit(x,' -> ',npd)(Skip,f(8),a,f(4));
 x=1441440; Call proper_divisors(x,pd,npd);
 Put Edit(x,' -> ',npd)(Skip,f(8),a,f(4));

 p9b=time();
 Put Edit((p9b-p9a)/1000,' seconds elapsed')(Skip,f(6,3),a);
 Return;

 proper_divisors: Proc(n,pd,npd);
 Dcl (n,pd(300),npd) Bin Fixed(31);
 Dcl (d,delta)       Bin Fixed(31);
 npd=0;
 If n>1 Then Do;
   If mod(n,2)=1 Then  /* odd number  */
     delta=2;
   Else                /* even number */
     delta=1;
   Do d=1 To n/2 By delta;
     If mod(n,d)=0 Then Do;
       npd+=1;
       pd(npd)=d;
       End;
     End;
   End;
 End;

 End;


/# Rosetta Code problem: http://rosettacode.org/wiki/Probabilistic_choice
by Galileo, 05/2022 #/

include ..\Utilitys.pmt

( ( "aleph" 0.200000 0 ) ( "beth" 0.166667 0 ) ( "gimel" 0.142857 0 ) ( "daleth" 0.125000 0 )
  ( "he" 0.111111 0 ) ( "waw" 0.100000 0 ) ( "zayin" 0.090909 0 ) ( "heth" 0.063456 0 ) )
len 1 swap 2 tolist var lprob

1000000 var trial

trial for drop
    rand >ps
    0 >ps
    lprob for var i
        ( i 2 ) sget ps> +
        tps swap dup >ps < if
           ( i 3 ) sget 1 + ( i 3 ) sset
           exitfor
        endif
    endfor
    ps> ps> drop drop
endfor

( "item" "\t" "actual" "\t\t" "theoretical" ) lprint nl nl
lprob for drop
    pop swap
    1 get "\t" rot 3 get trial / "\t" rot 2 get nip "\n" 6 tolist lprint
endfor


(let (Count 1000000  Denom 27720  N Denom)
   (let Probs
      (mapcar
         '((I S)
            (prog1 (cons N (*/ Count I) 0 S)
               (dec 'N (/ Denom I)) ) )
         (range 5 12)
         '(aleph beth gimel daleth he waw zayin heth) )
      (do Count
         (inc (cddr (rank (rand 1 Denom) Probs T))) )
      (let Fmt (-6 12 12)
         (tab Fmt NIL "Probability" "Result")
         (for X Probs
            (tab Fmt
               (cdddr X)
               (format (cadr X) 6)
               (format (caddr X) 6) ) ) ) ) )


 probch: Proc Options(main);
 Dcl prob(8) Dec Float(15) Init((1/5.0),      /* aleph  */
                                (1/6.0),      /* beth   */
                                (1/7.0),      /* gimel  */
                                (1/8.0),      /* daleth */
                                (1/9.0),      /* he     */
                                (1/10.0),     /* waw    */
                                (1/11.0),     /* zayin  */
                                (1759/27720));/* heth   */
 Dcl what(8) Char(6) Init('aleph ','beth  ','gimel ','daleth',
                          'he    ','waw   ','zayin ','heth  ');
 Dcl ulim(0:8) Dec Float(15) Init((9)0);
 Dcl i Bin Fixed(31);
 Dcl ifloat Dec Float(15);
 Dcl one    Dec Float(15) Init(1);
 Dcl num    Dec Float(15) Init(1759);
 Dcl denom  Dec Float(15) Init(27720);
 Dcl x      Dec Float(15) Init(0);
 Dcl pr     Dec Float(15) Init(0);
 Dcl (n,nn) Bin Fixed(31);
 Dcl cnt(8) Bin Fixed(31) Init((8)0);
 nn=1000000;
 Do i=1 To 8;
   ifloat=i+4;
   If i<8 Then
     prob(i)=one/ifloat;
   Else
     prob(i)=num/denom;
   Ulim(i)=ulim(i-1)+prob(i);
   /* Put Skip list(i,prob(i),ulim(i));*/
   End;
 Do n=1 To nn;
   x=random();
   Do i=1 To 8;
     If x<ulim(i) Then Leave;
     End;
   cnt(i)+=1;
   End;
 Put Edit('letter    occurs    frequency  expected ')(Skip,a);
 Put Edit('------    ------   ---------- ----------')(Skip,a);
 Do i=1 To 8;
   pr=float(cnt(i))/float(nn);
   Put Edit(what(i),cnt(i),pr,prob(i))(Skip,a,f(10),x(2),2(f(11,8)));
   End;
 End;


function proper-divisor ($n) {
    if($n -ge 2) {
        $lim = [Math]::Floor([Math]::Sqrt($n))
        $less, $greater = @(1), @()
        for($i = 2; $i -lt $lim; $i++){
            if($n%$i -eq 0) {
                $less += @($i)
                $greater = @($n/$i) + $greater
            }
        }
        if(($lim -ne 1) -and ($n%$lim -eq 0)) {$less += @($lim)}
        $($less + $greater)
    } else {@()}
}
"$(proper-divisor 100)"
"$(proper-divisor 496)"
"$(proper-divisor 2048)"


divisor(N, Divisor) :-
    UpperBound is round(sqrt(N)),
    between(1, UpperBound, D),
    0 is N mod D,
    (
        Divisor = D
     ;
        LargerDivisor is N/D,
        LargerDivisor =\= D,
        Divisor = LargerDivisor
    ).

proper_divisor(N, D) :-
    divisor(N, D),
    D =\= N.

%% Task 1
%

proper_divisors(N, Ds) :-
    setof(D, proper_divisor(N, D), Ds).

%% Task 2
%

show_proper_divisors_of_range(Low, High) :-
    findall( N:Ds,
             ( between(Low, High, N),
               proper_divisors(N, Ds) ),
             Results ),
    maplist(writeln, Results).

%% Task 3
%

proper_divisor_count(N, Count) :-
    proper_divisors(N, Ds),
    length(Ds, Count).

find_most_proper_divisors_in_range(Low, High, Result) :-
    aggregate_all( max(Count, N),
                   ( between(Low, High, N),
                     proper_divisor_count(N, Count) ),
                   max(MaxCount, Num) ),
    Result = (num(Num)-divisor_count(MaxCount)).


$character = [PSCustomObject]@{
    aleph  = [PSCustomObject]@{Expected=1/5       ; Alpha="א"}
    beth   = [PSCustomObject]@{Expected=1/6       ; Alpha="ב"}
    gimel  = [PSCustomObject]@{Expected=1/7       ; Alpha="ג"}
    daleth = [PSCustomObject]@{Expected=1/8       ; Alpha="ד"}
    he     = [PSCustomObject]@{Expected=1/9       ; Alpha="ה"}
    waw    = [PSCustomObject]@{Expected=1/10      ; Alpha="ו"}
    zayin  = [PSCustomObject]@{Expected=1/11      ; Alpha="ז"}
    heth   = [PSCustomObject]@{Expected=1759/27720; Alpha="ח"}
}

$sum        = 0
$iterations = 1000000
$cumulative = [ordered]@{}
$randomly   = [ordered]@{}

foreach ($name in $character.PSObject.Properties.Name)
{
    $sum += $character.$name.Expected
    $cumulative.$name = $sum
    $randomly.$name = 0
}

for ($i = 0; $i -lt $iterations; $i++)
{
    $random = Get-Random -Minimum 0.0 -Maximum 1.0

    foreach ($name in $cumulative.Keys)
    {
        if ($random -le $cumulative.$name)
        {
            $randomly.$name++
            break
        }
    }
}

foreach ($name in $character.PSObject.Properties.Name)
{
    [PSCustomObject]@{
        Name      = $name
        Expected  = $character.$name.Expected
        Actual    = $randomly.$name / $iterations
        Character = $character.$name.Alpha
    }
}


EnableExplicit

Procedure ListProperDivisors(Number, List Lst())
  If Number < 2 : ProcedureReturn : EndIf
  Protected i
  For i = 1 To Number / 2
    If Number % i = 0
      AddElement(Lst())
      Lst() = i
    EndIf
  Next
EndProcedure

Procedure.i CountProperDivisors(Number)
  If Number < 2 : ProcedureReturn 0 : EndIf
  Protected i, count = 0
  For i = 1 To Number / 2
    If Number % i = 0
      count + 1
    EndIf
  Next
  ProcedureReturn count
EndProcedure

Define n, count, most = 1, maxCount = 0
If OpenConsole()
  PrintN("The proper divisors of the following numbers are : ")
  PrintN("")
  NewList lst()
  For n = 1 To 10
    ListProperDivisors(n, lst())
    Print(RSet(Str(n), 3) + " -> ")
    If ListSize(lst()) = 0
      Print("(None)")
    Else
      ForEach lst()
        Print(Str(lst()) + " ")
      Next
    EndIf
    ClearList(lst())
    PrintN("")
  Next
  For n = 2 To 20000
    count = CountProperDivisors(n)
    If count > maxCount
      maxCount = count
      most = n
    EndIf
  Next
  PrintN("")
  PrintN(Str(most) + " has the most proper divisors, namely " + Str(maxCount))
  PrintN("")
  PrintN("Press any key to close the console")
  Repeat: Delay(10) : Until Inkey() <> ""
  CloseConsole()
EndIf


#times=1000000

Structure Item
  name.s
  prob.d
  Amount.i
EndStructure

If OpenConsole()
  Define i, j, d.d, e.d, txt.s
  Dim Mapps.Item(7)
  Mapps(0)\name="aleph": Mapps(0)\prob=1/5.0
  Mapps(1)\name="beth":  Mapps(1)\prob=1/6.0
  Mapps(2)\name="gimel": Mapps(2)\prob=1/7.0
  Mapps(3)\name="daleth":Mapps(3)\prob=1/8.0
  Mapps(4)\name="he":    Mapps(4)\prob=1/9.0
  Mapps(5)\name="waw":   Mapps(5)\prob=1/10.0
  Mapps(6)\name="zayin": Mapps(6)\prob=1/11.0
  Mapps(7)\name="heth":  Mapps(7)\prob=1759/27720.0

  For i=1 To #times
    d=Random(#MAXLONG)/#MAXLONG  ; Get a random number
    e=0.0
    For j=0 To ArraySize(Mapps())
      e+Mapps(j)\prob            ; Get span for current itme
      If d<=e                    ; Check if it is within this span?
        Mapps(j)\Amount+1        ; If so, count it.
        Break
      EndIf
    Next j
  Next i

  PrintN("Sample times: "+Str(#times)+#CRLF$)
  For j=0 To ArraySize(Mapps())
      d=Mapps(j)\Amount/#times
      txt=LSet(Mapps(j)\name,7)+" should be "+StrD(Mapps(j)\prob)+" is "+StrD(d)
      PrintN(txt+" | Deviatation "+RSet(StrD(100.0-100.0*Mapps(j)\prob/d,3),6)+"%")
  Next

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


  [ factors -1 split drop ]      is properdivisors ( n --> [ )

  10 times [ i^ 1+ properdivisors echo cr ]

  0 0
  20000 times
    [ i^ 1+ properdivisors size
      2dup < iff
        [ dip [ 2drop i^ 1+ ] ]
      else drop ]
  swap echo say " has "
  echo say " proper divisors." cr


import random, bisect

def probchoice(items, probs):
  '''\
  Splits the interval 0.0-1.0 in proportion to probs
  then finds where each random.random() choice lies
  '''

  prob_accumulator = 0
  accumulator = []
  for p in probs:
    prob_accumulator += p
    accumulator.append(prob_accumulator)

  while True:
    r = random.random()
    yield items[bisect.bisect(accumulator, r)]

def probchoice2(items, probs, bincount=10000):
  '''\
  Puts items in bins in proportion to probs
  then uses random.choice() to select items.

  Larger bincount for more memory use but
  higher accuracy (on avarage).
  '''

  bins = []
  for item,prob in zip(items, probs):
    bins += [item]*int(bincount*prob)
  while True:
    yield random.choice(bins)

def tester(func=probchoice, items='good bad ugly'.split(),
                    probs=[0.5, 0.3, 0.2],
                    trials = 100000
                    ):
  def problist2string(probs):
    '''\
    Turns a list of probabilities into a string
    Also rounds FP values
    '''
    return ",".join('%8.6f' % (p,) for p in probs)

  from collections import defaultdict

  counter = defaultdict(int)
  it = func(items, probs)
  for dummy in xrange(trials):
    counter[it.next()] += 1
  print "\n##\n## %s\n##" % func.func_name.upper()
  print "Trials:              ", trials
  print "Items:               ", ' '.join(items)
  print "Target probability:  ", problist2string(probs)
  print "Attained probability:", problist2string(
    counter[x]/float(trials) for x in items)

if __name__ == '__main__':
  items = 'aleph beth gimel daleth he waw zayin heth'.split()
  probs = [1/(float(n)+5) for n in range(len(items))]
  probs[-1] = 1-sum(probs[:-1])
  tester(probchoice, items, probs, 1000000)
  tester(probchoice2, items, probs, 1000000)


# Proper divisors. 12/10/16 aev
require(numbers);
V <- sapply(1:20000, Sigma, k = 0, proper = TRUE); ind <- which(V==max(V));
cat("  *** max number of divisors:", max(V), "\n"," *** for the following indices:",ind, "\n");


#lang racket
(require math)
(define (proper-divisors n) (drop-right (divisors n) 1))
(for ([n (in-range 1 (add1 10))])
  (printf "proper divisors of: ~a\t~a\n" n (proper-divisors n)))
(define most-under-20000
  (for/fold ([best '(1)]) ([n (in-range 2 (add1 20000))])
    (define divs (proper-divisors n))
    (if (< (length (cdr best)) (length divs)) (cons n divs) best)))
(printf "~a has ~a proper divisors\n"
        (car most-under-20000) (length (cdr most-under-20000)))


  [ $ "bigrat.qky" loadfile ] now!

( --------------- zen object orientation -------------- )

  [ immovable
    ]this[ swap do ]done[ ]     is object     ( [ -->   )

  [ ]'[ ]                       is method     (   --> [ )

  [ method
      [ dup share
        swap put ] ]            is localise   (   -->   )

  [ method [ release ] ]        is delocalise (   -->   )

( ------------------ rand-gen methods ----------------- )

  [ method
      [ dup take
        2 split drop
        ' [ 0 0 ] join
        swap put ] ]            is reset-gen  (   --> [ )

  [ method
      [ dup take
        dup 2 peek 1+
        swap 2 poke
        dup 1 peek random
        over 0 peek <
        if
          [ dup 3 peek 1+
            swap 3 poke ]
      swap put ] ]              is rand-gen   (   --> [ )

  [ method
      [ dup echo say ": "
        share
        dup 2 peek dup echo
        say " trials" cr
        say "    Actual: "
        over 3 peek
        swap 10 point$ echo$ cr
        say "  Expected: "
        dup 0 peek
        swap 1 peek
        10 point$ echo$ cr
        cr ] ]                  is report     (   --> [ )

( ------------------ rand-gen objects ----------------- )

  [ object [    1     5 0 0 ] ] is aleph    (   [ -->   )
  [ object [    1     6 0 0 ] ] is beth     (   [ -->   )
  [ object [    1     7 0 0 ] ] is gimel    (   [ -->   )
  [ object [    1     8 0 0 ] ] is daleth   (   [ -->   )
  [ object [    1     9 0 0 ] ] is he       (   [ -->   )
  [ object [    1    10 0 0 ] ] is waw      (   [ -->   )
  [ object [    1    11 0 0 ] ] is zayin    (   [ -->   )
  [ object [ 1759 27720 0 0 ] ] is heth     (   [ -->   )

 ' [ aleph beth gimel daleth he waw zayin heth ]

  dup witheach [ reset-gen swap do ]

  dup witheach
    [ 1000000 times
        [ rand-gen over do ]
      drop ]

  witheach [ report swap do ]


prob = c(aleph=1/5, beth=1/6, gimel=1/7, daleth=1/8, he=1/9, waw=1/10, zayin=1/11, heth=1759/27720)
  # Note that R doesn't actually require the weights
  # vector for rmultinom to sum to 1.
hebrew = c(rmultinom(1, 1e6, prob))
d = data.frame(
    Requested = prob,
    Obtained = hebrew/sum(hebrew))
print(d)


#lang racket
;;; returns a probabalistic choice from the sequence choices
;;; choices generates two values -- the chosen value and a
;;; probability (weight) of the choice.
;;;
;;; Note that a hash where keys are choices and values are probabilities
;;; is such a sequence.
;;;
;;; if the total probability < 1 then choice could return #f
;;; if the total probability > 1 then some choices may be impossible
(define (probabalistic-choice choices)
  (let-values
      (((_ choice) ;; the fold provides two values, we only need the second
                   ;; the first will always be a negative number showing that
                   ;; I've run out of random steam
        (for/fold
            ((rnd (random))
             (choice #f))
          (((v p) choices)
           #:break (<= rnd 0))
          (values (- rnd p) v))))
    choice))

;;; ditto, but all probabilities must be exact rationals
;;; the optional lcd
;;;
;;; not the most efficient, since it provides a wrapper (and demo)
;;; for p-c/i-w below
(define (probabalistic-choice/exact
         choices
         #:gcd (GCD (/ (apply gcd (hash-values choices)))))
  (probabalistic-choice/integer-weights
   (for/hash (((k v) choices))
     (values k (* v GCD)))
   #:sum-of-weights GCD))

;;; this proves useful in Rock-Paper-Scissors
(define (probabalistic-choice/integer-weights
         choices
         #:sum-of-weights (sum-of-weights (apply + (hash-values choices))))
  (let-values
      (((_ choice)
        (for/fold
            ((rnd (random sum-of-weights))
             (choice #f))
          (((v p) choices)
           #:break (< rnd 0))
          (values (- rnd p) v))))
    choice))

(module+ test
  (define test-samples (make-parameter 1000000))

  (define (test-p-c-function f w)
    (define test-selection (make-hash))
    (for* ((i (in-range 0 (test-samples)))
           (c (in-value (f w))))
      (when (zero? (modulo i 100000)) (eprintf "~a," (quotient i 100000)))
      (hash-update! test-selection c add1 0))
    (printf "~a~%choice\tcount\texpected\tratio\terror~%" f)
    (for* (((k v) (in-hash test-selection))
           (e (in-value (* (test-samples) (hash-ref w k)))))
      (printf "~a\t~a\t~a\t~a\t~a%~%"
              k v e
              (/ v (test-samples))
              (real->decimal-string
               (exact->inexact (* 100 (/ (- v e) e)))))))

  (define test-weightings/rosetta
    (hash
     'aleph 1/5
     'beth 1/6
     'gimel 1/7
     'daleth 1/8
     'he 1/9
     'waw 1/10
     'zayin 1/11
     'heth 1759/27720; adjusted so that probabilities add to 1
     ))

  (define test-weightings/50:50 (hash 'woo 1/2 'yay 1/2))
  (define test-weightings/1:2:3 (hash 'woo 1 'yay 2 'foo 3))

  (test-p-c-function probabalistic-choice test-weightings/50:50)
  (test-p-c-function probabalistic-choice/exact test-weightings/50:50)
  (test-p-c-function probabalistic-choice test-weightings/rosetta)
  (test-p-c-function probabalistic-choice/exact test-weightings/rosetta))


constant TRIALS = 1e6;

constant @event = <aleph beth gimel daleth he waw zayin heth>;

constant @P = flat (1 X/ 5 .. 11), 1759/27720;
constant @cP = [\+] @P;

my atomicint @results[+@event];
(^TRIALS).race.map: { @results[ @cP.first: { $_ > once rand }, :k ]⚛++; }

say  'Event    Occurred Expected  Difference';
for ^@results {
    my ($occurred, $expected) = @results[$_], @P[$_] * TRIALS;
    printf "%-9s%8.0f%9.1f%12.1f\n",
            @event[$_],
                $occurred,
                     $expected,
                          abs $occurred - $expected;
}


sub propdiv (\x) {
    my @l = 1 if x > 1;
    (2 .. x.sqrt.floor).map: -> \d {
        unless x % d { @l.push: d; my \y = x div d; @l.push: y if y != d }
    }
    @l
}

put "$_ [{propdiv($_)}]" for 1..10;

my @candidates;
loop (my int $c = 30; $c <= 20_000; $c += 30) {
#(30, *+30 …^ * > 500_000).race.map: -> $c {
    my \mx = +propdiv($c);
    next if mx < @candidates - 1;
    @candidates[mx].push: $c
}

say "max = {@candidates - 1}, candidates = {@candidates.tail}";


/*REXX*/

Call time 'R'
Do x=1 To 10
  Say x '->' proper_divisors(x)
  End

hi=1
Do x=1 To 20000
  /* If x//1000=0 Then Say x */
  npd=count_proper_divisors(x)
  Select
    When npd>hi Then Do
      list.npd=x
      hi=npd
      End
    When npd=hi Then
      list.hi=list.hi x
    Otherwise
      Nop
    End
  End

Say hi '->' list.hi

Say ' 166320 ->' count_proper_divisors(166320)
Say '1441440 ->' count_proper_divisors(1441440)

Say time('E') 'seconds elapsed'
Exit

proper_divisors: Procedure
Parse Arg n
If n=1 Then Return ''
pd=''
/* Optimization reduces 37 seconds to 28 seconds */
If n//2=1 Then  /* odd number  */
  delta=2
Else            /* even number */
  delta=1
Do d=1 To n%2 By delta
  If n//d=0 Then
    pd=pd d
  End
Return space(pd)

count_proper_divisors: Procedure
Parse Arg n
Return words(proper_divisors(n))


let p = [
    ("Aleph",   1.0 /. 5.0),
    ("Beth",    1.0 /. 6.0),
    ("Gimel",   1.0 /. 7.0),
    ("Daleth",  1.0 /. 8.0),
    ("He",      1.0 /. 9.0),
    ("Waw",     1.0 /. 10.0),
    ("Zayin",   1.0 /. 11.0),
    ("Heth", 1759.0 /. 27720.0),
  ]

let prob_take = (arr, k) => {
  let rec aux = (i, k) => {
    let (v, p) = arr[i]
    if k < p { v } else { aux(i+1, (k -. p)) }
  }
  aux(0, k)
}

{
  let n = 1_000_000
  let h = Belt.HashMap.String.make(~hintSize=10)

  Js.Array2.forEach(p, ((v, _)) =>
    Belt.HashMap.String.set(h, v, 0)
  )

  let tot = Js.Array2.reduce(p, (acc, (_, prob)) => acc +. prob, 0.0)

  for _ in 1 to n {
    let sel = prob_take(p, tot *. Js.Math.random())
    let _n = Belt.HashMap.String.get(h, sel)
    let n = Belt.Option.getExn(_n)
    Belt.HashMap.String.set(h, sel, (n+1))  /* count the number of each item */
  }
  Printf.printf("Event    expected occurred\n")
  Js.Array2.forEach(p, ((v, p)) => {
      let _d = Belt.HashMap.String.get(h, v)
      let d = Belt.Option.getExn(_d)
      Printf.printf("%s \t %8.5g %8.5g\n", v, p, float(d) /. float(n))
    }
  )
}


/*REXX program displays results of probabilistic choices, gen random #s per probability.*/
parse arg trials digs seed .                     /*obtain the optional arguments from CL*/
if trials=='' | trials==","  then trials= +1e6   /*Not specified?  Then use the default.*/
if   digs=='' |   digs==","  then   digs=   15   /* "      "         "   "   "     "    */
if datatype(seed, 'W')  then call random ,,seed  /*allows repeatability for RANDOM nums.*/
numeric digits digs                              /*use a specific number of decimal digs*/
names= 'aleph beth gimel daleth he waw zayin heth ───totals───►'   /*names of the cells.*/
hi= 100000                                                         /*max REXX RANDOM num*/
z= words(names);             #= z - 1            /*#: the number of actual/usable names.*/
$= 0                                             /*initialize sum of the probabilities. */
           do n=1  for #;    prob.n= 1 / (n+4);     if n==#  then prob.n= 1759 / 27720
           $= $ + prob.n;   Hprob.n= prob.n * hi /*spread the range of probabilities.   */
           end   /*n*/
prob.z= $                                        /*define the value of the ───totals───.*/
@.= 0                                            /*initialize all counters in the range.*/
@.z= trials                                      /*define the last counter of  "    "   */
           do j=1  for trials;    r= random(hi)  /*gen  TRIAL  number of random numbers.*/
               do k=1  for #                     /*for each cell, compute  percentages. */
               if r<=Hprob.k  then @.k= @.k + 1  /* "    "    "  range, bump the counter*/
               end   /*k*/
           end       /*j*/
_= '═'                                           /*_:  padding used by the  CENTER  BIF.*/
w= digs + 6                                      /*W:  display width for the percentages*/
d= 4 + max( length(trials), length('count') )    /* [↓]  display a formatted top header.*/
say center('name',15,_)  center('count',d,_) center('target %',w,_) center('actual %',w,_)

     do cell=1  for z                            /*display each of the cells and totals.*/
     say  ' '   left( word(names, cell), 13)             right(@.cell, d-2)  " " ,
                left( format(   prob.cell   * 100, d),   w-2) ,
                left( format( @.cell/trials * 100, d),   w-2)   /* [↓]  foot title. [↓] */
     if cell==#  then say  center(_,15,_)   center(_,d,_)    center(_,w,_)   center(_,w,_)
     end   /*c*/                                 /*stick a fork in it,  we are all done.*/


# Project : Proper divisors

limit = 10
for n=1 to limit
    if n=1
       see "" + 1 + " -> (None)" + nl
       loop
    ok
    see "" + n + " -> "
    for m=1 to n-1
        if n%m = 0
           see " " + m
        ok
    next
    see nl
next


require "prime"

class Integer
  def proper_divisors
    return [] if self == 1
    primes = prime_division.flat_map{|prime, freq| [prime] * freq}
    (1...primes.size).each_with_object([1]) do |n, res|
      primes.combination(n).map{|combi| res << combi.inject(:*)}
    end.flatten.uniq
  end
end

(1..10).map{|n| puts "#{n}: #{n.proper_divisors}"}

size, select = (1..20_000).group_by{|n| n.proper_divisors.size}.max
select.each do |n|
  puts "#{n} has #{size} divisors"
end


# Project : Probabilistic choice

cnt = list(8)
item = ["aleph","beth","gimel","daleth","he","waw","zayin","heth"]
prob  = [1/5.0, 1/6.0, 1/7.0, 1/8.0, 1/9.0, 1/10.0, 1/11.0, 1759/27720]

for trial = 1 to 1000000
    r = random(10)/10
    p = 0
    for i = 1 to len(prob)
        p = p + prob[i]
        if r < p
           cnt[i] = cnt[i] + 1
           loop
        ok
    next
next

see "item     actual    theoretical" + nl
for i = 1 to len(item)
    see "" + item[i] + "    " + cnt[i]/1000000 + "    " + prob[i] + nl
next


probabilities = {
  "aleph"  => 1/5.0,
  "beth"   => 1/6.0,
  "gimel"  => 1/7.0,
  "daleth" => 1/8.0,
  "he"     => 1/9.0,
  "waw"    => 1/10.0,
  "zayin"  => 1/11.0,
}
probabilities["heth"] = 1.0 - probabilities.each_value.inject(:+)
ordered_keys = probabilities.keys

sum, sums = 0.0, {}
ordered_keys.each do |key|
  sum += probabilities[key]
  sums[key] = sum
end

actual = Hash.new(0)

samples = 1_000_000
samples.times do
  r = rand
  for k in ordered_keys
    if r < sums[k]
      actual[k] += 1
      break
    end
  end
end

puts  "key     expected    actual        diff"
for k in ordered_keys
  act = Float(actual[k]) / samples
  val = probabilities[k]
  printf "%-8s%.8f  %.8f  %6.3f %%\n", k, val, act, 100*(act-val)/val
end


trait ProperDivisors {
    fn proper_divisors(&self) -> Option<Vec<u64>>;
}

impl ProperDivisors for u64 {
    fn proper_divisors(&self) -> Option<Vec<u64>> {
        if self.le(&1) {
            return None;
        }
        let mut divisors: Vec<u64> = Vec::new();

        for i in 1..*self {
            if *self % i == 0 {
                divisors.push(i);
            }
        }
        Option::from(divisors)
    }
}

fn main() {
    for i in 1..11 {
        println!("Proper divisors of {:2}: {:?}", i,
                 i.proper_divisors().unwrap_or(vec![]));
    }

    let mut most_idx: u64 = 0;
    let mut most_divisors: Vec<u64> = Vec::new();
    for i in 1..20_001 {
        let divs = i.proper_divisors().unwrap_or(vec![]);
        if divs.len() > most_divisors.len() {
            most_divisors = divs;
            most_idx = i;
        }
    }
    println!("In 1 to 20000, {} has the most proper divisors at {}", most_idx,
             most_divisors.len());
}


$lines

$constant false = 0
$constant true = FFFFH

rem - compute p mod q
function mod(p, q = integer) = integer
end = p - q * (p/q)

rem - count, and optionally display, proper divisors of n
function divisors(n, display = integer) = integer
  var i, limit, count, start, delta = integer
  if mod(n, 2) = 0 then
    begin
      start = 2
      delta = 1
    end
  else
    begin
      start = 3
      delta = 2
    end
  if n < 2 then count = 0 else count = 1
  if display and (count = 1) then print using "#####"; 1;
  i = start
  limit = n / start
  while i <= limit do
    begin
      if mod(n, i) = 0 then
        begin
          if display then print using "#####"; i;
          count = count + 1
        end
      i = i + delta
      if count = 1 then limit = n / i
    end
  if display then print
end = count

rem - main program begins here
var i, ndiv, highdiv, highnum = integer

print "Proper divisors of first 10 numbers:"
for i = 1 to 10
  print using "### : "; i;
  ndiv = divisors(i, true)
next i

print "Searching for number with most divisors ..."
highdiv = 1
highnum = 1
for i = 1 to 20000
  ndiv = divisors(i, false)
  if ndiv > highdiv then
    begin
      highdiv = ndiv
      highnum = i
    end
next i
print "Searched up to"; i
print highnum; " has the most divisors: "; highdiv

end


def properDivisors(n: Int) = (1 to n/2).filter(i => n % i == 0)
def format(i: Int, divisors: Seq[Int]) = f"$i%5d    ${divisors.length}%2d   ${divisors mkString " "}"

println(f"    n   cnt   PROPER DIVISORS")
val (count, list) = (1 to 20000).foldLeft( (0, List[Int]()) ) { (max, i) =>
    val divisors = properDivisors(i)
    if (i <= 10 || i == 100) println( format(i, divisors) )
    if (max._1 < divisors.length) (divisors.length, List(i))
    else if (max._1 == divisors.length) (divisors.length, max._2 ::: List(i))
    else max
}

list.foreach( number => println(f"$number%5d    ${properDivisors(number).length}") )


extern crate rand;

use rand::distributions::{IndependentSample, Sample, Weighted, WeightedChoice};
use rand::{weak_rng, Rng};

const DATA: [(&str, f64); 8] = [
    ("aleph", 1.0 / 5.0),
    ("beth", 1.0 / 6.0),
    ("gimel", 1.0 / 7.0),
    ("daleth", 1.0 / 8.0),
    ("he", 1.0 / 9.0),
    ("waw", 1.0 / 10.0),
    ("zayin", 1.0 / 11.0),
    ("heth", 1759.0 / 27720.0),
];

const SAMPLES: usize = 1_000_000;

/// Generate a mapping to be used by `WeightedChoice`
fn gen_mapping() -> Vec<Weighted<usize>> {
    DATA.iter()
        .enumerate()
        .map(|(i, &(_, p))| Weighted {
            // `WeightedChoice` requires `u32` weights rather than raw probabilities.  For each
            // probability, we convert it to a `u32` weight, and associate it with an index. We
            // multiply by a constant because small numbers such as 0.2 when casted to `u32`
            // become `0`.  This conversion decreases the accuracy of the mapping, which is why we
            // provide an implementation which uses `f64`s for the best accuracy.
            weight: (p * 1_000_000_000.0) as u32,
            item: i,
        })
        .collect()
}

/// Generate a mapping of the raw probabilities
fn gen_mapping_float() -> Vec<f64> {
    // This does the work of `WeightedChoice::new`, splitting a number into various ranges.  The
    // `item` of `Weighted` is represented here merely by the probability's position in the `Vec`.
    let mut running_total = 0.0;
    DATA.iter()
        .map(|&(_, p)| {
            running_total += p;
            running_total
        })
        .collect()
}

/// An implementation of `WeightedChoice` which uses probabilities rather than weights.  Refer to
/// the `WeightedChoice` source for serious usage.
struct WcFloat {
    mapping: Vec<f64>,
}

impl WcFloat {
    fn new(mapping: &[f64]) -> Self {
        Self {
            mapping: mapping.to_vec(),
        }
    }

    // This is roughly the same logic as `WeightedChoice::ind_sample` (though is likely slower)
    fn search(&self, sample_prob: f64) -> usize {
        let idx = self.mapping
            .binary_search_by(|p| p.partial_cmp(&sample_prob).unwrap());
        match idx {
            Ok(i) | Err(i) => i,
        }
    }
}

impl IndependentSample<usize> for WcFloat {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> usize {
        // Because we know the total is exactly 1.0, we can merely use a raw float value.
        // Otherwise caching `Range::new(0.0, running_total)` and sampling with
        // `range.ind_sample(&mut rng)` is recommended.
        let sample_prob = rng.next_f64();
        self.search(sample_prob)
    }
}

impl Sample<usize> for WcFloat {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> usize {
        self.ind_sample(rng)
    }
}

fn take_samples<R: Rng, T>(rng: &mut R, wc: &T) -> [usize; 8]
where
    T: IndependentSample<usize>,
{
    let mut counts = [0; 8];
    for _ in 0..SAMPLES {
        let sample = wc.ind_sample(rng);
        counts[sample] += 1;
    }
    counts
}

fn print_mapping(counts: &[usize]) {
    println!("Item   | Expected | Actual   ");
    println!("-------+----------+----------");
    for (&(name, expected), &count) in DATA.iter().zip(counts.iter()) {
        let real = count as f64 / SAMPLES as f64;
        println!("{:6} | {:.6} | {:.6}", name, expected, real);
    }
}

fn main() {
    let mut rng = weak_rng();

    println!("    ~~~ U32 METHOD ~~~");
    let mut mapping = gen_mapping();
    let wc = WeightedChoice::new(&mut mapping);

    let counts = take_samples(&mut rng, &wc);
    print_mapping(&counts);

    println!();

    println!("   ~~~ FLOAT METHOD ~~~");
    // initialize the float version of `WeightedChoice`
    let mapping = gen_mapping_float();
    let wc = WcFloat::new(&mapping);

    let counts = take_samples(&mut rng, &wc);
    print_mapping(&counts);
}


object ProbabilisticChoice extends App {
  import scala.collection.mutable.LinkedHashMap

  def weightedProb[A](prob: LinkedHashMap[A,Double]): A = {
    require(prob.forall{case (_, p) => p > 0 && p < 1})
    assume(prob.values.sum == 1)
    def weighted(todo: Iterator[(A,Double)], rand: Double, accum: Double = 0): A = todo.next match {
      case (s, i) if rand < (accum + i) => s
      case (_, i) => weighted(todo, rand, accum + i)
    }
    weighted(prob.toIterator, scala.util.Random.nextDouble)
  }

  def weightedFreq[A](freq: LinkedHashMap[A,Int]): A = {
    require(freq.forall{case (_, f) => f >= 0})
    require(freq.values.sum > 0)
    def weighted(todo: Iterator[(A,Int)], rand: Int, accum: Int = 0): A = todo.next match {
      case (s, i) if rand < (accum + i) => s
      case (_, i) => weighted(todo, rand, accum + i)
    }
    weighted(freq.toIterator, scala.util.Random.nextInt(freq.values.sum))
  }

  // Tests:

  val probabilities = LinkedHashMap(
    'aleph  -> 1.0/5,
    'beth   -> 1.0/6,
    'gimel  -> 1.0/7,
    'daleth -> 1.0/8,
    'he     -> 1.0/9,
    'waw    -> 1.0/10,
    'zayin  -> 1.0/11,
    'heth   -> 1759.0/27720
  )

  val frequencies = LinkedHashMap(
    'aleph  -> 200,
    'beth   -> 167,
    'gimel  -> 143,
    'daleth -> 125,
    'he     -> 111,
    'waw    -> 100,
    'zayin  -> 91,
    'heth   -> 63
  )

  def check[A](original: LinkedHashMap[A,Double], results: Seq[A]) {
    val freq = results.groupBy(x => x).mapValues(_.size.toDouble/results.size)
    original.foreach{case (k, v) =>
      val a = v/original.values.sum
      val b = freq(k)
      val c = if (Math.abs(a - b) < 0.001) "ok" else "**"
      println(f"$k%10s  $a%.4f  $b%.4f  $c")
    }
    println(" "*10 + f"  ${1}%.4f  ${freq.values.sum}%.4f")
  }

  println("Checking weighted probabilities:")
  check(probabilities, for (i <- 1 to 1000000) yield weightedProb(probabilities))
  println
  println("Checking weighted frequencies:")
  check(frequencies.map{case (a, b) => a -> b.toDouble}, for (i <- 1 to 1000000) yield weightedFreq(frequencies))
}


$ include "seed7_05.s7i";

const proc: writeProperDivisors (in integer: n) is func
  local
    var integer: i is 0;
  begin
    for i range 1 to n div 2 do
      if n rem i = 0 then
        write(i <& " ");
      end if;
    end for;
    writeln;
  end func;

const func integer: countProperDivisors (in integer: n) is func
  result
    var integer: count is 0;
  local
    var integer: i is 0;
  begin
    for i range 1 to n div 2 step succ(n rem 2) do
      if n rem i = 0 then
        incr(count);
      end if;
    end for;
  end func;

const proc: main is func
  local
    var integer: i is 0;
    var integer: v is 0;
    var integer: max is 0;
    var integer: max_i is 1;
  begin
    for i range 1 to 10 do
      write(i <& ": ");
      writeProperDivisors(i);
    end for;
    for i range 1 to 20000 do
      v := countProperDivisors(i);
      if v > max then
        max := v;
        max_i := i;
      end if;
    end for;
    writeln(max_i <& " with " <& max <& " divisors");
  end func;


func propdiv (n) {
    n.divisors.slice(0, -2)
}

{|i| printf("%2d: %s\n", i, propdiv(i)) } << 1..10

var max = 0
var candidates = []

for i in (1..20_000) {
    var divs = propdiv(i).len
    if (divs > max) {
        candidates = []
        max = divs
    }
    candidates << i if (divs == max)
}

say "max = #{max}, candidates = #{candidates}"


(use-modules (ice-9 format))

(define (random-choice probs)
  (define choice (random 1.0))
  (define (helper val prob-lis)
    (let ((nval (- val (cadar prob-lis))))
      (if
       (< nval 0)
       (caar prob-lis)
       (helper nval (cdr prob-lis)))))
  (helper choice probs))

(define (add-result result delta table)
  (cond
   ((null? table) (list (list result delta)))
   ((eq? (caar table) result)
    (cons (list result (+ (cadar table) delta)) (cdr table)))
   (#t (cons (car table) (add-result result delta (cdr table))))))

(define (choices trials probs)
  (define (helper trial-num freq-table)
    (if
     (= trial-num trials)
     freq-table
     (helper
      (+ trial-num 1)
      (add-result (random-choice probs) (/ 1 trials) freq-table))))
  (helper 0 '()))

(define (format-results probs results)
  (for-each
   (lambda (x)
     (format
      #t
      "~10a~10,5f~10,5f~%"
      (car x)
      (cadr x)
      (cadr (assoc (car x) results))))
   probs))

(define probs
  '((aleph 1/5) (beth 1/6) (gimel 1/7) (daleth 1/8)
    (he 1/9) (waw 1/10) (zayin 1/11) (heth 1759/27720)))

(format-results probs (choices 1000000 probs))


func properDivs1(n: Int) -> [Int] {

    return filter (1 ..< n) { n % $0 == 0 }
}


dim _proper_divisors(100)

sub proper_divisors(n)
	dim i
	dim _proper_divisors_count = 0
	if n <> 1 then
		for i = 1 to (n \ 2)
			if n %% i = 0 then
				_proper_divisors_count = _proper_divisors_count + 1
				_proper_divisors(_proper_divisors_count) = i
			end if
		next
	end if
	return _proper_divisors_count
end sub

sub show_proper_divisors(n, tabbed)
	dim cnt = proper_divisors(n)
	print str$(n) + ":"; tab(4);"(" + str$(cnt) + " items) ";
	dim j
	for j = 1 to cnt
		if tabbed then
			print str$(_proper_divisors(j)),
		else
			print str$(_proper_divisors(j));
		end if
		if (j < cnt) then print ",";
	next
	print
end sub

dim i
for i = 1 to 10
    show_proper_divisors(i, false)
next

dim c
dim maxindex = 0
dim maxlength = 0
for t = 1 to 20000
	c = proper_divisors(t)
	if c > maxlength then
		maxindex = t
		maxlength = c
	end if
next

print "A maximum at ";
show_proper_divisors(maxindex, false)


$ include "seed7_05.s7i";
  include "float.s7i";

const type: letter is new enum
    aleph, beth, gimel, daleth, he, waw, zayin, heth
  end enum;

const func string: str (in letter: aLetter) is
    return [] ("aleph", "beth", "gimel", "daleth", "he", "waw", "zayin", "heth") [succ(ord(aLetter))];

enable_output(letter);

const array [letter] integer: table is [letter] (
    5544, 4620, 3960, 3465, 3080, 2772, 2520, 1759);

const func letter: randomLetter is func
  result
    var letter: resultLetter is aleph;
  local
    var integer: number is 0;
  begin
    number := rand(1, 27720);
    while number > table[resultLetter] do
      number -:= table[resultLetter];
      incr(resultLetter);
    end while;
  end func;

const proc: main is func
  local
    var integer: count is 0;
    var letter: aLetter is aleph;
    var array [letter] integer: occurrence is letter times 0;
  begin
    for count range 1 to 1000000 do
      aLetter := randomLetter;
      incr(occurrence[aLetter]);
    end for;
    writeln("Name   Count  Ratio    Expected");
    for aLetter range letter.first to letter.last do
      writeln(aLetter rpad 7 <& occurrence[aLetter] lpad 6 <&
              flt(occurrence[aLetter]) / 10000.9 digits 4 lpad 8 <& "%" <&
              100.0 * flt(table[aLetter]) / 27720.0 digits 4 lpad 8 <& "%");
    end for;
  end func;


define TRIALS = 1e4;

func prob_choice_picker(options) {
    var n = 0;
    var a = [];
    options.each { |k,v|
        n += v;
        a << [n, k];
    }
    func {
        var r = 1.rand;
        a.first{|e| r <= e[0] }[1];
    }
}

var ps = Hash(
   aleph  => 1/5,
   beth   => 1/6,
   gimel  => 1/7,
   daleth => 1/8,
   he     => 1/9,
   waw    => 1/10,
   zayin  => 1/11
)

ps{:heth} = (1 - ps.values.sum)

var picker = prob_choice_picker(ps)
var results = Hash()

TRIALS.times {
    results{picker()} := 0 ++;
}

say "Event   Occurred  Expected  Difference";
for k,v in (results.sort_by {|k| results{k} }.reverse) {
    printf("%-6s  %f  %f  %f\n",
        k, v/TRIALS, ps{k},
        abs(v/TRIALS - ps{k})
    );
}


proc properDivisors {n} {
    if {$n == 1} return
    set divs 1
    for {set i 2} {$i*$i <= $n} {incr i} {
	if {!($n % $i)} {
	    lappend divs $i
	    if {$i*$i < $n} {
		lappend divs [expr {$n / $i}]
	    }
	}
    }
    return $divs
}

for {set i 1} {$i <= 10} {incr i} {
    puts "$i => {[join [lsort -int [properDivisors $i]] ,]}"
}
set maxI [set maxC 0]
for {set i 1} {$i <= 20000} {incr i} {
    set c [llength [properDivisors $i]]
    if {$c > $maxC} {
	set maxI $i
	set maxC $c
    }
}
puts "max: $maxI => (...$maxC…)"


Public Sub Proper_Divisor()
Dim t() As Long, i As Long, l As Long, j As Long, c As Long
    For i = 1 To 10
        Debug.Print "Proper divisor of " & i & " : " & Join(S(i), ", ")
    Next
    For i = 2 To 20000
        l = UBound(S(i)) + 1
        If l > c Then c = l: j = i
    Next
    Debug.Print "Number in the range 1 to 20,000 with the most proper divisors is : " & j
    Debug.Print j & " count " & c & " proper divisors"
End Sub

Private Function S(n As Long) As String()
'returns the proper divisors of n
Dim j As Long, t() As String, c As Long
    't = list of proper divisor of n
    If n > 1 Then
        For j = 1 To n \ 2
            If n Mod j = 0 Then
                ReDim Preserve t(c)
                t(c) = j
                c = c + 1
            End If
        Next
    End If
    S = t
End Function


package require Tcl 8.5

set map [dict create]
set sum 0.0

foreach name {aleph beth gimel daleth he waw zayin} \
        prob {1/5.0 1/6.0 1/7.0 1/8.0 1/9.0 1/10.0 1/11.0} \
{
    set prob [expr $prob]
    set sum [expr {$sum + $prob}]
    dict set map $name [dict create probability $prob limit $sum count 0]
}
dict set map heth [dict create probability [expr {1.0 - $sum}] limit 1.0 count 0]

set samples 1000000
for {set i 0} {$i < $samples} {incr i} {
    set n [expr {rand()}]
    foreach name [dict keys $map] {
        if {$n <= [dict get $map $name limit]} {
            set count [dict get $map $name count]
            dict set map $name count [incr count]
            break
        }
    }
}

puts "using $samples samples:"
puts [format "%-10s %-21s %-9s %s" "" expected actual difference]

dict for {name submap} $map {
    dict with submap {
        set actual [expr {$count * 1.0 / $samples}]
        puts [format "%-10s %-21s %-9s %4.2f%%" $name $probability $actual \
                [expr {abs($actual - $probability)/$probability*100.0}]
             ]
    }
}


Module Module1

    Function ProperDivisors(number As Integer) As IEnumerable(Of Integer)
        Return Enumerable.Range(1, number / 2).Where(Function(divisor As Integer) number Mod divisor = 0)
    End Function

    Sub Main()
        For Each number In Enumerable.Range(1, 10)
            Console.WriteLine("{0}: {{{1}}}", number, String.Join(", ", ProperDivisors(number)))
        Next

        Dim record = Enumerable.Range(1, 20000).Select(Function(number) New With {.Number = number, .Count = ProperDivisors(number).Count()}).OrderByDescending(Function(currentRecord) currentRecord.Count).First()
        Console.WriteLine("{0}: {1}", record.Number, record.Count)
    End Sub

End Module