#lang racket
(struct node (edges ; edges (or forward links)
              link ; suffix link (backward links)
              len) ; the length of the node
  #:mutable)

(define (new-node link len) (node (make-hash) link len))

(struct eertree (nodes
                 rto ; odd length root node, or node -1
                 rte ; even length root node, or node 0
                 S ; accumulated input string, T=S[1..i]
                 max-suf-t) ; maximum suffix of tree T
  #:mutable)

(define (new-eertree)
  (let* ((rto (new-node #f -1))
         (rte (new-node rto 0)))
    (eertree null rto rte (list 0) rte)))

(define (eertree-get-max-suffix-pal et start-node a)
  #| We traverse the suffix-palindromes of T in the order of decreasing length.
     For each palindrome we read its length k and compare T[i-k] against a
     until we get an equality or arrive at the -1 node. |#
  (match et
    [(eertree nodes rto rte (and S (app length i)) max-suf-t)
     (let loop ((u start-node))
       (let ((k (node-len u)))
         (if (or (eq? u rto) (= (list-ref S (- i k 1)) a))
             u
             (let ((u→ (node-link u)))
               (when (eq? u u→) (error 'eertree-get-max-suffix-pal "infinite loop"))
               (loop u→)))))]))

(define (eertree-add! et a)
  #| We need to find the maximum suffix-palindrome P of Ta
     Start by finding maximum suffix-palindrome Q of T.
     To do this, we traverse the suffix-palindromes of T
     in the order of decreasing length, starting with maxSuf(T) |#
  (match (eertree-get-max-suffix-pal et (eertree-max-suf-t et) a)
    [(node Q.edges Q.→ Q.len)
     ;; We check Q to see whether it has an outgoing edge labeled by a.
     (define new-node? (not (hash-has-key? Q.edges a)))
     (when new-node?
       (define P (new-node #f (+ Q.len 2))) ; We create the node P of length Q+2
       (set-eertree-nodes! et (append (eertree-nodes et) (list P)))
       (define P→
         (if (= (node-len P) 1)
             (eertree-rte et) ; if P = a, create the suffix link (P,0)
             ;; It remains to c reate the suffix link from P if |P|>1.
             ;; Just continue traversing suffix-palindromes of T starting with the suffix link of Q.
             (hash-ref (node-edges (eertree-get-max-suffix-pal et Q.→ a)) a)))
       (set-node-link! P P→)
       (hash-set! Q.edges a P)) ; create the edge (Q,P)

     (set-eertree-max-suf-t! et (hash-ref Q.edges a)) ; P becomes the new maxSufT
     (set-eertree-S! et (append (eertree-S et) (list a))) ; Store accumulated input string
     new-node?]))

(define (eertree-get-sub-palindromes et)
  (define (inr nd (node-path (list nd)) (char-path/rev null))
    ;; Each node represents a palindrome, which can be reconstructed by the path from the root node to
    ;; each non-root node.
    (let ((deeper ; Traverse all edges, since they represent other palindromes
           (for/fold ((result null)) (([→-name nd2] (in-hash (node-edges nd))))
             ; The lnk-name is the character used for this edge
             (append result (inr nd2 (append node-path (list nd2)) (cons →-name char-path/rev)))))
          (root-node? (or (eq? (eertree-rto et) nd) (eq? (eertree-rte et) nd))))
      (if root-node? ; Don't add root nodes
          deeper
          (let ((even-string? (eq? (car node-path) (eertree-rte et)))
                (char-path (reverse char-path/rev)))
            (cons (append char-path/rev (if even-string? char-path (cdr char-path))) deeper)))))
  inr)

(define (eertree-get-palindromes et)
  (define sub (eertree-get-sub-palindromes et))
  (append (sub (eertree-rto et))
          (sub (eertree-rte et))))

(module+ main
  (define et (new-eertree))
  ;; eertree works in integer space, so we'll map to/from char space here
  (for ((c "eertree")) (eertree-add! et (char->integer c)))
  (map (compose list->string (curry map integer->char)) (eertree-get-palindromes et)))


my $str = "eertree";
my @pal = ();
my ($strrev,$strpal);

for (1 .. $str.chars) -> $n {
   for (1 .. $str.chars) -> $m {
      $strrev = "";
      $strpal = $str.substr($n-1, $m);
      if ($strpal ne "") {
         for ($strpal.chars ... 1) -> $p {
            $strrev ~= $strpal.substr($p-1,1);
         }
         ($strpal eq $strrev) and @pal.push($strpal);
      }
   }
}

say @pal.unique;


/*REXX program creates a list of (unique) sub─palindromes that exist in an input string.*/
parse arg x .                                    /*obtain optional input string from CL.*/
if x=='' | x==","  then x= 'eertree'             /*Not specified?  Then use the default.*/
L= length(x)                                     /*the length (in chars) of input string*/
@.= .                                            /*@ tree indicates uniqueness of pals. */
$=                                               /*list of unsorted & unique palindromes*/
   do     j=1  for L                             /*start at the left side of the string.*/
       do k=1  for L                             /*traverse from left to right of string*/
       parse var  x   =(j)  y   +(k)             /*extract a substring from the string. */
       if reverse(y)\==y | @.y\==.  then iterate /*Partial string a palindrome?  Skip it*/
       @.y= y                                    /*indicate a sub─palindrome was found. */
       $= $' '  y                                /*append the sub─palindrome to the list*/
       end   /*k*/                               /* [↑]  an extra blank is inserted.    */
   end       /*j*/

say '──────── The input string that is being used: '     space(x)
say '──────── The number of sub─palindromes found: '     words($)
say '──────── The  list  of sub─palindromes found: '     strip($)
                                                 /*stick a fork in it,  we're all done. */


# Project : Eertree

str = "eertree"
pal = []
for n=1 to len(str)
    for m=1 to len(str)
        strrev = ""
        strpal = substr(str, n, m)
        if strpal != ""
           for p=len(strpal) to 1 step -1
               strrev = strrev + strpal[p]
           next
           if strpal = strrev
              add(pal, strpal)
           ok
        ok
    next
next
sortpal = sort(pal)
for n=len(sortpal) to 2 step -1
    if sortpal[n] = sortpal[n-1]
       del(sortpal, n)
    ok
next
see sortpal + nl


class Node
    def initialize(length, edges = {}, suffix = 0)
        @length = length
        @edges = edges
        @suffix = suffix
    end

    attr_reader :length
    attr_reader :edges
    attr_accessor :suffix
end

EVEN_ROOT = 0
ODD_ROOT = 1

def eertree(s)
    tree = [
        Node.new(0, {}, ODD_ROOT),
        Node.new(-1, {}, ODD_ROOT)
    ]
    suffix = ODD_ROOT
    s.each_char.with_index { |c, i|
        n = suffix
        k = 0
        loop do
            k = tree[n].length
            b = i - k - 1
            if b >= 0 and s[b] == c then
                break
            end
            n = tree[n].suffix
        end
        if tree[n].edges.key?(c) then
                suffix = tree[n].edges[c]
            next
        end
        suffix = tree.length
        tree << Node.new(k + 2)
        tree[n].edges[c] = suffix
        if tree[suffix].length == 1 then
            tree[suffix].suffix = 0
            next
        end
        loop do
            n = tree[n].suffix
            b = i - tree[n].length - 1
            if b >= 0 and s[b] == c then
                break
            end
        end
        tree[suffix].suffix = tree[n].edges[c]
    }
    return tree
end

def subPalindromes(tree)
    s = []

    children = lambda { |n,p,f|
        for c,v in tree[n].edges
            m = tree[n].edges[c]
            p = c + p + c
            s << p
            f.call(m, p, f)
        end
    }

    children.call(0, '', children)

    for c,n in tree[1].edges
        s << c
        children.call(n, c, children)
    end

    return s
end

tree = eertree("eertree")
print subPalindromes(tree), "\n"


Module Module1

    Class Node
        Public Sub New(Len As Integer)
            Length = Len
            Edges = New Dictionary(Of Char, Integer)
        End Sub

        Public Sub New(len As Integer, edg As Dictionary(Of Char, Integer), suf As Integer)
            Length = len
            Edges = If(IsNothing(edg), New Dictionary(Of Char, Integer), edg)
            Suffix = suf
        End Sub

        Property Edges As Dictionary(Of Char, Integer)
        Property Length As Integer
        Property Suffix As Integer
    End Class

    ReadOnly EVEN_ROOT As Integer = 0
    ReadOnly ODD_ROOT As Integer = 1

    Function Eertree(s As String) As List(Of Node)
        Dim tree As New List(Of Node) From {
            New Node(0, New Dictionary(Of Char, Integer), ODD_ROOT),
            New Node(-1, New Dictionary(Of Char, Integer), ODD_ROOT)
        }
        Dim suffix = ODD_ROOT
        Dim n As Integer
        Dim k As Integer

        For i = 1 To s.Length
            Dim c = s(i - 1)
            n = suffix
            While True
                k = tree(n).Length
                Dim b = i - k - 2
                If b >= 0 AndAlso s(b) = c Then
                    Exit While
                End If
                n = tree(n).Suffix
            End While
            If tree(n).Edges.ContainsKey(c) Then
                suffix = tree(n).Edges(c)
                Continue For
            End If
            suffix = tree.Count
            tree.Add(New Node(k + 2))
            tree(n).Edges(c) = suffix
            If tree(suffix).Length = 1 Then
                tree(suffix).Suffix = 0
                Continue For
            End If
            While True
                n = tree(n).Suffix
                Dim b = i - tree(n).Length - 2
                If b >= 0 AndAlso s(b) = c Then
                    Exit While
                End If
            End While
            Dim a = tree(n)
            Dim d = a.Edges(c)
            Dim e = tree(suffix)
            e.Suffix = d
        Next

        Return tree
    End Function

    Function SubPalindromes(tree As List(Of Node)) As List(Of String)
        Dim s As New List(Of String)
        Dim children As Action(Of Integer, String) = Sub(n As Integer, p As String)
                                                         For Each c In tree(n).Edges.Keys
                                                             Dim m = tree(n).Edges(c)
                                                             Dim p1 = c + p + c
                                                             s.Add(p1)
                                                             children(m, p1)
                                                         Next
                                                     End Sub
        children(0, "")
        For Each c In tree(1).Edges.Keys
            Dim m = tree(1).Edges(c)
            Dim ct = c.ToString()
            s.Add(ct)
            children(m, ct)
        Next
        Return s
    End Function

    Sub Main()
        Dim tree = Eertree("eertree")
        Dim result = SubPalindromes(tree)
        Dim listStr = String.Join(", ", result)
        Console.WriteLine("[{0}]", listStr)
    End Sub

End Module


class Node {
    construct new() {
        _edges = {}    // edges (or forward links)
        _link = null   // suffix link (backward links)
        _len = 0       // the length of the node
    }

    edges    { _edges }
    link     { _link }
    link=(l) { _link = l }
    len      { _len }
    len=(l)  { _len = l }
}

class Eertree {
    construct new(str) {
        _nodes = []
        _rto = Node.new()  // odd length root node, or node -1
        _rte = Node.new()  // even length root node, or node 0
        _s = "0"           // accumulated input string, T = S[1..i]
        _maxSufT = _rte    // maximum suffix of tree T

        // Initialize and build the tree
        _rte.link = _rto
        _rto.link = _rte
        _rto.len  = -1
        _rte.len  = 0
        for (ch in str) add_(ch)
    }

    nodes { _nodes }

    getMaxSuffixPal_(startNode, a) {
        // We traverse the suffix-palindromes of T in the order of decreasing length.
        // For each palindrome we read its length k and compare T[i-k] against a
        // until we get an equality or arrive at the -1 node.
        var u = startNode
        var i = _s.count
        var k = u.len
        while (u != _rto && _s[i - k - 1] != a) {
            if (u == u.link) Fiber.abort("Infinite loop detected")
            u = u.link
            k = u.len
        }
        return u
    }

    add_(a) {
        // We need to find the maximum suffix-palindrome P of Ta
        // Start by finding maximum suffix-palindrome Q of T.
        // To do this, we traverse the suffix-palindromes of T
        // in the order of decreasing length, starting with maxSuf(T)
        var q = getMaxSuffixPal_(_maxSufT, a)
        // We check Q to see whether it has an outgoing edge labeled by a.
        var createANewNode = !q.edges.keys.contains(a)

        if (createANewNode) {
            // We create the node P of length Q + 2
            var p = Node.new()
            _nodes.add(p)
            p.len = q.len + 2
            if (p.len == 1) {
                // if P = a, create the suffix link (P, 0)
                p.link = _rte
            } else {
                // It remains to create the suffix link from P if |P|>1. Just
                // continue traversing suffix-palindromes of T starting with the
                // the suffix link of Q.
                p.link = getMaxSuffixPal_(q.link, a).edges[a]
            }

            // create the edge (Q, P)
            q.edges[a] = p
        }

        // P becomes the new maxSufT
        _maxSufT = q.edges[a]

        // Store accumulated input string
        _s = _s + a

        return createANewNode
    }

    getSubPalindromes() {
        // Traverse tree to find sub-palindromes
        var result = []
        // Odd length words
        getSubPalindromes_(_rto, [_rto], "", result)
        // Even length words
        getSubPalindromes_(_rte, [_rte], "", result)
        return result
    }

    getSubPalindromes_(nd, nodesToHere, charsToHere, result) {
        // Each node represents a palindrome, which can be reconstructed
        // by the path from the root node to each non-root node.

        // Traverse all edges, since they represent other palindromes
        for (lnkName in nd.edges.keys) {
            var nd2 = nd.edges[lnkName]
            getSubPalindromes_(nd2, nodesToHere + [nd2], charsToHere + lnkName, result)
        }

        // Reconstruct based on charsToHere characters.
        if (nd != _rto && nd != _rte) { // Don't print for root nodes
            var assembled = charsToHere[-1..0] +
                ((nodesToHere[0] == _rte) ? charsToHere : charsToHere[1..-1])
            result.add(assembled)
        }
    }
}

var str = "eertree"
System.print("Processing string '%(str)'")
var eertree = Eertree.new(str)
System.print("Number of sub-palindromes: %(eertree.nodes.count)")
var result = eertree.getSubPalindromes()
System.print("Sub-palindromes: %(result)")


class Node{
   fcn init(length){
      var edges=Dictionary(),	# edges (or forward links). (char:Node)
          link=Void,		# suffix link (backward links)
	  sz  =length;		# node length.
    }
}
class Eertree{
   fcn init(string=Void){
      var nodes=List(),
		# two initial root nodes
	  rto=Node(-1), # odd  length root node, or node -1
	  rte=Node(0);  # even length root node, or node  0

      rto.link=rte.link=rto;    # Initialize empty tree
      var S      =Data(Void,0), # accumulated input string, T=S[1..i], byte buffer
          maxSufT=rte;          # maximum suffix of tree T
      if(string) string.pump(addChar);  // go ahead and build the tree
   }
   fcn get_max_suffix_pal(startNode,a){
    # We traverse the suffix-palindromes of T in the order of decreasing length.
    # For each palindrome we read its length k and compare T[i-k] against a
    # until we get an equality or arrive at the -1 node.
      u,i,k := startNode, S.len(), u.sz;
      while(u.id!=rto.id and S.charAt(i - k - 1)!=a){
	 _assert_(u.id!=u.link.id);    # Prevent infinte loop
	 u,k = u.link,u.sz;
      }
      return(u);
   }
   fcn addChar(a){
	# We need to find the maximum suffix-palindrome P of Ta
	# Start by finding maximum suffix-palindrome Q of T.
	# To do this, we traverse the suffix-palindromes of T
	# in the order of decreasing length, starting with maxSuf(T)
      Q:=get_max_suffix_pal(maxSufT,a);
        # We check Q to see whether it has an outgoing edge labeled by a.
      createANewNode:=(not Q.edges.holds(a));
      if(createANewNode){
	 P:=Node(Q.sz + 2); nodes.append(P);
	 if(P.sz==1) P.link=rte;  # if P = a, create the suffix link (P,0)
	 else # It remains to create the suffix link from P if |P|>1. Just
	      # continue traversing suffix-palindromes of T starting with the suffix
	      # link of Q.
	    P.link=get_max_suffix_pal(Q.link,a).edges[a];
	 Q.edges[a]=P;    # create the edge (Q,P)
      }
      maxSufT=Q.edges[a]; # P becomes the new maxSufT
      S.append(a);	  # Store accumulated input string
      return(createANewNode);  // in case anyone wants to know a is new edge
   }
   fcn get_sub_palindromes{
      result:=List();
      sub_palindromes(rto, T(rto),"", result); # Odd length words
      sub_palindromes(rte, T(rte),"", result); # Even length words
      result
   }
   fcn [private] sub_palindromes(nd, nodesToHere, charsToHere, result){
        // nodesToHere needs to be read only
	# Each node represents a palindrome, which can be reconstructed
	# by the path from the root node to each non-root node.

	# Traverse all edges, since they represent other palindromes
      nd.edges.pump(Void,'wrap([(lnkName,nd2)]){
	 sub_palindromes(nd2, nodesToHere+nd2, charsToHere+lnkName, result);
      });

      # Reconstruct based on charsToHere characters.
      if(nd.id!=rto.id and nd.id!=rte.id){ # Don't print for root nodes
	 if(nodesToHere[0].id==rte.id) # Even string
	    assembled:=charsToHere.reverse() + charsToHere;
	 else assembled:=charsToHere.reverse() + charsToHere[1,*]; # Odd string
	 result.append(assembled);
      }
   }
}


F egyptian_divmod(dividend, divisor)
   assert(divisor != 0)
   V (pwrs, dbls) = ([1], [divisor])
   L dbls.last <= dividend
      pwrs.append(pwrs.last * 2)
      dbls.append(pwrs.last * divisor)
   V (ans, accum) = (0, 0)
   L(pwr, dbl) zip(pwrs[((len)-2 ..).step(-1)], dbls[((len)-2 ..).step(-1)])
      I accum + dbl <= dividend
         accum += dbl
         ans += pwr
   R (ans, abs(accum - dividend))

L(i, j) cart_product(0.<13, 1..12)
   assert(egyptian_divmod(i, j) == divmod(i, j))
V (i, j) = (580, 34)
V (d, m) = egyptian_divmod(i, j)
print(‘#. divided by #. using the Egyption method is #. remainder #.’.format(i, j, d, m))


TYPE Answer=[CARD result,reminder]

PROC EgyptianDivision(CARD dividend,divisor Answer POINTER res)
  DEFINE SIZE="16"
  CARD ARRAY powers(SIZE),doublings(SIZE)
  CARD power,doubling,accumulator
  INT i,count

  count=0 power=1 doubling=divisor
  WHILE count<SIZE AND doubling<=dividend
  DO
    powers(count)=power
    doublings(count)=doubling
    count==+1
    power==LSH 1
    doubling==LSH 1
  OD

  i=count-1
  res.result=0
  accumulator=0
  WHILE i>=0
  DO
    IF accumulator+doublings(i)<=dividend THEN
      accumulator==+doublings(i)
      res.result==+powers(i)
    FI
    i==-1
  OD
  res.reminder=dividend-accumulator
RETURN

PROC Main()
  CARD dividend=[580],divisor=[34]
  Answer res

  EgyptianDivision(dividend,divisor,res)
  PrintF("%U / %U = %U reminder %U",dividend,divisor,res.result,res.reminder)
RETURN


with Ada.Text_IO;

procedure Egyptian_Division is

  procedure Divide  (a : Natural; b : Positive; q, r : out Natural) is
    doublings : array (0..31) of Natural;  -- The natural type holds values < 2^32 so no need going beyond
    m, sum, last_index_touched : Natural := 0;
  begin
    for i in doublings'Range loop
      m := b * 2**i;
      exit when m > a ;
      doublings (i) := m;
      last_index_touched := i;
    end loop;
    q := 0;
    for i in reverse doublings'First .. last_index_touched loop
        m := sum + doublings (i);
        if m <= a then
          sum := m;
          q := q + 2**i;
        end if;
    end loop;
    r := a -sum;
  end Divide;

  q, r : Natural;
begin
  Divide (580,34, q, r);
  Ada.Text_IO.put_line ("Quotient="&q'Img & " Remainder="&r'img);
end Egyptian_Division;


BEGIN
    # performs Egyptian division of dividend by divisor, setting quotient and remainder #
    # this uses 32 bit numbers, so a table of 32 powers of 2 should be sufficient       #
    # ( divisors > 2^30 will probably overflow - this is not checked here )             #
    PROC egyptian division = ( INT dividend, divisor, REF INT quotient, remainder )VOID:
         BEGIN
            [ 1 : 32 ]INT powers of 2, doublings;
            # initialise the powers of 2 and doublings tables #
            powers of 2[ 1 ] := 1;
            doublings  [ 1 ] := divisor;
            INT   table pos  := 1;
            WHILE table pos +:= 1;
                  powers of 2[ table pos ] := powers of 2[ table pos - 1 ] * 2;
                  doublings  [ table pos ] := doublings  [ table pos - 1 ] * 2;
                  doublings[ table pos ] <= dividend
            DO
                SKIP
            OD;
            # construct the accumulator and answer #
            INT accumulator := 0, answer := 0;
            WHILE table pos >=1
            DO
                IF ( accumulator + doublings[ table pos ] ) <= dividend
                THEN
                    accumulator +:= doublings  [ table pos ];
                    answer      +:= powers of 2[ table pos ]
                FI;
                table pos -:= 1
            OD;
            quotient  := answer;
            remainder := ABS ( accumulator - dividend )
        END # egyptian division # ;

    # task test case #
    INT quotient, remainder;
    egyptian division( 580, 34, quotient, remainder );
    print( ( "580 divided by 34 is: ", whole( quotient, 0 ), " remainder: ", whole( remainder, 0 ), newline ) )
END


-- EGYPTIAN DIVISION ------------------------------------

-- eqyptianQuotRem :: Int -> Int -> (Int, Int)
on egyptianQuotRem(m, n)
    script expansion
        on |λ|(ix)
            set {i, x} to ix
            if x > m then
                Nothing()
            else
                Just({ix, {i + i, x + x}})
            end if
        end |λ|
    end script

    script collapse
        on |λ|(ix, qr)
            set {i, x} to ix
            set {q, r} to qr
            if x < r then
                {q + i, r - x}
            else
                qr
            end if
        end |λ|
    end script

    return foldr(collapse, {0, m}, ¬
        unfoldr(expansion, {1, n}))
end egyptianQuotRem

-- TEST -------------------------------------------------
on run
    egyptianQuotRem(580, 34)
end run

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

-- Just :: a -> Maybe a
on Just(x)
    {type:"Maybe", Nothing:false, Just:x}
end Just

-- Nothing :: Maybe a
on Nothing()
    {type:"Maybe", Nothing:true}
end Nothing

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

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

-- > unfoldr (\b -> if b == 0 then Nothing else Just (b, b-1)) 10
-- > [10,9,8,7,6,5,4,3,2,1]
-- unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
on unfoldr(f, v)
    set xr to {v, v} -- (value, remainder)
    set xs to {}
    tell mReturn(f)
        repeat -- Function applied to remainder.
            set mb to |λ|(item 2 of xr)
            if Nothing of mb then
                exit repeat
            else -- New (value, remainder) tuple,
                set xr to Just of mb
                -- and value appended to output list.
                set end of xs to item 1 of xr
            end if
        end repeat
    end tell
    return xs
end unfoldr


egyptianDiv: function [dividend, divisor][
    ensure -> and? dividend >= 0
                   divisor > 0

    if dividend < divisor -> return @[0, dividend]

    powersOfTwo: new [1]
    doublings: new @[divisor]
    d: divisor

    while [true][
        d: 2 * d
        if d > dividend -> break
        'powersOfTwo ++ 2 * last powersOfTwo
        'doublings ++ d
    ]

    answer: 0
    accumulator: 0

    loop (dec size doublings)..0 'i [
        if dividend >= accumulator + doublings\[i] [
            accumulator: accumulator + doublings\[i]
            answer: answer + powersOfTwo\[i]
            if accumulator = dividend -> break
        ]
    ]

    return @[answer, dividend - accumulator]
]

dividend: 580
divisor: 34

[quotient, remainder]: egyptianDiv dividend divisor

print [dividend "divided by" divisor "is" quotient "with remainder" remainder]


divident := 580
divisor := 34

answer := accumulator := 0
obj := []	, div := divisor

while (div < divident)
{
	obj[2**(A_Index-1)] := div				; obj[powers_of_2] := doublings
	div *= 2						; double up
}

while obj.MaxIndex()						; iterate rows "in the reverse order"
{
	if (accumulator + obj[obj.MaxIndex()] <= divident)	; If (accumulator + current doubling) <= dividend
	{
		accumulator += obj[obj.MaxIndex()]		; add current doubling to the accumulator
		answer += obj.MaxIndex()			; add the powers_of_2 value to the answer.
	}
	obj.pop()						; remove current row
}
MsgBox % divident "/" divisor " = " answer ( divident-accumulator > 0 ? " r" divident-accumulator : "")


'---Ported from the c code example to BaCon by bigbass

'==================================================================================
FUNCTION EGYPTIAN_DIVISION(long dividend, long divisor, long remainder) TYPE long
'==================================================================================
'--- remainder is the third  parameter, pass 0 if you do not need the remainder

DECLARE powers[64] TYPE long
DECLARE doublings[64] TYPE long

	LOCAL i TYPE long

	FOR i = 0 TO  63 STEP 1
		powers[i] = 1 << i
		doublings[i] = divisor << i
		IF (doublings[i] > dividend) THEN
			BREAK
		ENDIF
	NEXT

	LOCAL answer TYPE long
	LOCAL accumulator TYPE long
	answer = 0
	accumulator = 0

	WHILE i >= 0
		'--- If the current value of the accumulator added to the
		'--- doublings cell would be less than or equal to the
		'--- dividend then add it to the accumulator
		IF (accumulator + doublings[i] <= dividend) THEN
			accumulator = accumulator + doublings[i]
			answer = answer + powers[i]
		ENDIF
		DECR i
	WEND

	IF remainder THEN
		remainder = dividend - accumulator
		PRINT dividend ," / ", divisor, " = " , answer ," remainder " , remainder

        PRINT "Decoded the answer to a standard fraction"
        PRINT  (remainder + 0.0 )/ (divisor + 0.0) + answer
        PRINT

	ELSE
		PRINT dividend ," / ", divisor , " = " , answer
	ENDIF

	RETURN answer

ENDFUNCTION

	'--- the large number divided by the smaller number
	'--- the third argument is 1 if you want to have a remainder
	'--- and 0 if you dont want to have a remainder

	EGYPTIAN_DIVISION(580,34,1)
	EGYPTIAN_DIVISION(580,34,0)

EGYPTIAN_DIVISION(580,34,1)


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

uint64_t egyptian_division(uint64_t dividend, uint64_t divisor, uint64_t *remainder) {
	// remainder is an out parameter, pass NULL if you do not need the remainder

	static uint64_t powers[64];
	static uint64_t doublings[64];

	int i;

	for(i = 0; i < 64; i++) {
		powers[i] = 1 << i;
		doublings[i] = divisor << i;
		if(doublings[i] > dividend)
			break;
	}

	uint64_t answer = 0;
	uint64_t accumulator = 0;

	for(i = i - 1; i >= 0; i--) {
		// If the current value of the accumulator added to the
		// doublings cell would be less than or equal to the
		// dividend then add it to the accumulator
		if(accumulator + doublings[i] <= dividend) {
			accumulator += doublings[i];
			answer += powers[i];
		}
	}

	if(remainder)
		*remainder = dividend - accumulator;
	return answer;
}

void go(uint64_t a, uint64_t b) {
	uint64_t x, y;
	x = egyptian_division(a, b, &y);
	printf("%llu / %llu = %llu remainder %llu\n", a, b, x, y);
	assert(a == b * x + y);
}

int main(void) {
	go(580, 32);
}


using System;
using System.Collections;

namespace Egyptian_division
{
	class Program
	{
		public static void Main(string[] args)
		{
			Console.Clear();
			Console.WriteLine();
			Console.WriteLine(" Egyptian division ");
			Console.WriteLine();
			Console.Write(" Enter value of dividend : ");
			int dividend = int.Parse(Console.ReadLine());

			Console.Write(" Enter value of divisor : ");
			int divisor = int.Parse(Console.ReadLine());

			Divide(dividend, divisor);

			Console.WriteLine();
			Console.Write("Press any key to continue . . . ");
			Console.ReadKey(true);

		}

		static void Divide(int dividend, int divisor)
		{
			//
			// Local variable declaration and initialization
			//
			int result   = 0;
			int reminder = 0;

			int powers_of_two = 0;
			int doublings 	  = 0;

			int answer 	= 0;
			int accumulator = 0;

			int two = 2;
			int pow = 0;
			int row = 0;

			//
			// Tables declaration
			//
			ArrayList table_powers_of_two = new ArrayList();
			ArrayList table_doublings     = new ArrayList();

			//
			// Fill and Show table values
			//
			Console.WriteLine("                           ");
			Console.WriteLine(" powers_of_2     doublings ");
			Console.WriteLine("                           ");

			// Set initial values
			powers_of_two = 1;
			doublings = divisor;
			while( doublings <= dividend )
			{
				// Set table value
				table_powers_of_two.Add( powers_of_two );
				table_doublings.Add( doublings );

				// Show new table row
				Console.WriteLine("{0,8}{1,16}",powers_of_two, doublings);

				pow++;

				powers_of_two = (int)Math.Pow( two, pow );
				doublings = powers_of_two * divisor;
			}
			Console.WriteLine("                           ");

			//
			// Calculate division and Show table values
			//
			row = pow - 1;
			Console.WriteLine("                                                 ");
			Console.WriteLine(" powers_of_2     doublings   answer   accumulator");
			Console.WriteLine("                                                 ");
			Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop + row);

			pow--;
			while( pow >= 0 && accumulator < dividend )
			{
				// Get values from tables
				doublings = int.Parse(table_doublings[pow].ToString());
				powers_of_two = int.Parse(table_powers_of_two[pow].ToString());

				if(accumulator + int.Parse(table_doublings[pow].ToString()) <= dividend )
				{
					// Set new values
					accumulator += doublings;
					answer += powers_of_two;

					// Show accumulated row values in different collor
					Console.ForegroundColor = ConsoleColor.Green;
					Console.Write("{0,8}{1,16}",powers_of_two, doublings);
					Console.ForegroundColor = ConsoleColor.Green;
					Console.WriteLine("{0,10}{1,12}", answer, accumulator);
					Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop - 2);
				}
				else
				{
					// Show not accumulated row walues
					Console.ForegroundColor = ConsoleColor.DarkGray;
					Console.Write("{0,8}{1,16}",powers_of_two, doublings);
					Console.ForegroundColor = ConsoleColor.Gray;
					Console.WriteLine("{0,10}{1,12}", answer, accumulator);
					Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop - 2);
				}

				pow--;
			}

			Console.WriteLine();
			Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop + row + 2);
			Console.ResetColor();

			// Set result and reminder
			result = answer;
			if( accumulator < dividend )
			{
				reminder = dividend - accumulator;

				Console.WriteLine(" So " + dividend +
				                  " divided by " + divisor +
				                  " using the Egyptian method is \n " + result +
				                  " remainder (" + dividend + " - " + accumulator +
				                  ") or " + reminder);
				Console.WriteLine();
			}
			else
			{
				reminder = 0;

				Console.WriteLine(" So " + dividend +
				                  " divided by " + divisor +
				                  " using the Egyptian method is \n " + result +
				                  " remainder " + reminder);
				Console.WriteLine();
			}
		}
	}
}


#include <cassert>
#include <iostream>

typedef unsigned long ulong;

/*
 * Remainder is an out paramerter. Use nullptr if the remainder is not needed.
 */
ulong egyptian_division(ulong dividend, ulong divisor, ulong* remainder) {
    constexpr int SIZE = 64;
    ulong powers[SIZE];
    ulong doublings[SIZE];
    int i = 0;

    for (; i < SIZE; ++i) {
        powers[i] = 1 << i;
        doublings[i] = divisor << i;
        if (doublings[i] > dividend) {
            break;
        }
    }

    ulong answer = 0;
    ulong accumulator = 0;

    for (i = i - 1; i >= 0; --i) {
        /*
         * If the current value of the accumulator added to the
         * doublings cell would be less than or equal to the
         * dividend then add it to the accumulator
         */
        if (accumulator + doublings[i] <= dividend) {
            accumulator += doublings[i];
            answer += powers[i];
        }
    }

    if (remainder) {
        *remainder = dividend - accumulator;
    }
    return answer;
}

void print(ulong a, ulong b) {
    using namespace std;

    ulong x, y;
    x = egyptian_division(a, b, &y);

    cout << a << " / " << b << " = " << x << " remainder " << y << endl;
    assert(a == b * x + y);
}

int main() {
    print(580, 34);

    return 0;
}


(defun egyptian-division (dividend divisor)
  (let* ((doublings (reverse (loop for n = divisor then (* 2 n)
                                until (> n dividend)
                                collect n)))
         (powers-of-two (reverse (loop for n = 1 then (* 2 n)
                                    repeat (length doublings)
                                    collect n))))
    (loop
       for d in doublings
       for p in powers-of-two
       with accumulator = 0
       with answer = 0
       finally (return (values answer (- dividend (* answer divisor))))
       when (<= (+ accumulator d) dividend)
       do (incf answer p)
          (incf accumulator d))))


import std.stdio;

version(unittest) {
    // empty
} else {
    int main(string[] args) {
        import std.conv;

        if (args.length < 3) {
            stderr.writeln("Usage: ", args[0], " dividend divisor");
            return 1;
        }

        ulong dividend = to!ulong(args[1]);
        ulong divisor = to!ulong(args[2]);
        ulong remainder;

        auto ans = egyptian_division(dividend, divisor, remainder);
        writeln(dividend, " / ", divisor, " = ", ans, " rem ", remainder);

        return 0;
    }
}

ulong egyptian_division(ulong dividend, ulong divisor, out ulong remainder) {
    enum SIZE = 64;
    ulong[SIZE] powers;
    ulong[SIZE] doublings;
    int i;

    for (; i<SIZE; ++i) {
        powers[i] = 1 << i;
        doublings[i] = divisor << i;
        if (doublings[i] > dividend) {
            break;
        }
    }

    ulong answer;
    ulong accumulator;

    for (i=i-1; i>=0; --i) {
        if (accumulator + doublings[i] <= dividend) {
            accumulator += doublings[i];
            answer += powers[i];
        }
    }

    remainder = dividend - accumulator;
    return answer;
}

unittest {
    ulong remainder;

    assert(egyptian_division(580UL, 34UL, remainder) == 17UL);
    assert(remainder == 2);
}


program Egyptian_division;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Math,
  System.Console; //https://github.com/JensBorrisholt/DelphiConsole

type
  TIntegerDynArray = TArray<Integer>;

  TIntegerDynArrayHelper = record helper for TIntegerDynArray
  public
    procedure Add(value: Integer);
  end;

procedure Divide(dividend, divisor: Integer);
var
  result, reminder, powers_of_two, doublings, answer, accumulator, two, pow, row: Integer;
  table_powers_of_two, table_doublings: TIntegerDynArray;
begin
  result := 0;
  reminder := 0;
  powers_of_two := 0;
  doublings := 0;
  answer := 0;
  accumulator := 0;
  two := 2;
  pow := 0;
  row := 0;

  writeln('                           ');
  writeln(' powers_of_2     doublings ');
  writeln('                           ');

  powers_of_two := 1;
  doublings := divisor;
  while doublings <= dividend do
  begin
    table_powers_of_two.Add(powers_of_two);

    table_doublings.Add(doublings);

    Writeln(Format('%8d %16d', [powers_of_two, doublings]));
    Inc(pow);
    powers_of_two := Trunc(IntPower(two, pow));
    doublings := powers_of_two * divisor;
  end;
  writeln('                           ');

  row := pow - 1;
  writeln('                                                 ');
  writeln(' powers_of_2     doublings   answer   accumulator');
  writeln('                                                 ');
  Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop + row);
  Dec(pow);
  while (pow >= 0) and (accumulator < dividend) do
  begin

    doublings := Trunc(table_doublings[pow]);
    powers_of_two := Trunc(table_powers_of_two[pow]);
    if (accumulator + Trunc(table_doublings[pow])) <= dividend then
    begin

      accumulator := accumulator + doublings;
      answer := answer + powers_of_two;

      Console.ForegroundColor := TConsoleColor.Green;
      Write(Format('%8d %16d', [powers_of_two, doublings]));
      Console.ForegroundColor := TConsoleColor.Green;
      writeln(format('%10d %12d', [answer, accumulator]));
      Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop - 2);
    end
    else
    begin

      Console.ForegroundColor := TConsoleColor.DarkGray;
      Write(Format('%8d %16d', [powers_of_two, doublings]));
      Console.ForegroundColor := TConsoleColor.Gray;
      writeln(format('%10d %12d', [answer, accumulator]));
      Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop - 2);
    end;
    Dec(pow);
  end;
  writeln;
  Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop + row + 2);
  Console.ResetColor();

  result := answer;
  if accumulator < dividend then
  begin
    reminder := dividend - accumulator;
    Console.WriteLine(' So ' + dividend.ToString + ' divided by ' + divisor.ToString
      + ' using the Egyptian method is '#10' ' + result.ToString +
      ' remainder (' + dividend.ToString + ' - ' + accumulator.ToString +
      ') or ' + reminder.ToString);
    writeln;
  end
  else
  begin
    reminder := 0;
    Console.WriteLine(' So ' + dividend.ToString + ' divided by ' + divisor.ToString
      + ' using the Egyptian method is '#10' ' + result.ToString + ' remainder '
      + reminder.ToString);
    writeln;
  end;
end;

{ TIntegerDynArrayHelper }

procedure TIntegerDynArrayHelper.Add(value: Integer);
begin
  SetLength(self, length(self) + 1);
  Self[high(self)] := value;
end;

function parseInt(s: string): Integer;
var
  c: Char;
  s2: string;
begin
  s2 := '';
  for c in s do
  begin
    if c in ['0'..'9'] then
      s2 := s2 + c;

  end;
  result := s2.ToInteger();
end;

var
  dividend, divisor: Integer;

begin
  Console.Clear();
  writeln;
  writeln(' Egyptian division ');
  writeln;
  Console.Write(' Enter value of dividend : ');
  dividend := parseInt(Console.ReadLine());
  Console.Write(' Enter value of divisor : ');
  divisor := parseInt(Console.ReadLine());
  Divide(dividend, divisor);
  writeln;
  Console.Write('Press any key to continue . . . ');
  Console.ReadKey(true);
end.


-module(egypt).

-export([ediv/2]).

ediv(A, B) ->
    {Twos, Ds} = genpowers(A, [1], [B]),
    {Quot, C} = accumulate(A, Twos, Ds),
    {Quot, abs(C - A)}.

genpowers(A, [_|Ts], [D|Ds]) when D > A -> {Ts, Ds};
genpowers(A, [T|_] = Twos, [D|_] = Ds) -> genpowers(A, [2*T|Twos], [D*2|Ds]).

accumulate(N, Twos, Ds) -> accumulate(N, Twos, Ds, 0, 0).
accumulate(_, [], [], Q, C) -> {Q, C};
accumulate(N, [T|Ts], [D|Ds], Q, C) when (C + D) =< N -> accumulate(N, Ts, Ds, Q+T, C+D);
accumulate(N, [_|Ts], [_|Ds], Q, C) -> accumulate(N, Ts, Ds, Q, C).


// A function to perform Egyptian Division: Nigel Galloway August 11th., 2017
let egyptianDivision N G =
  let rec fn n g = seq{yield (n,g); yield! fn (n+n) (g+g)}
  Seq.foldBack (fun (n,i) (g,e)->if (i<=g) then ((g-i),(e+n)) else (g,e)) (fn 1 G |> Seq.takeWhile(fun (_,g)->g<=N)) (N,0)


USING: assocs combinators formatting kernel make math sequences ;
IN: rosetta-code.egyptian-division

: table ( dividend divisor -- table )
    [ [ 2dup >= ] [ dup , 2 * ] while ] { } make 2nip
    dup length <iota> [ 2^ ] map zip <reversed> ;

: accum ( a b dividend -- c )
    [ 2dup [ first ] [email protected] + ] dip < [ [ + ] 2map ] [ drop ] if ;

: ediv ( dividend divisor -- quotient remainder )
    {
        [ table ]
        [ 2drop { 0 0 } ]
        [ drop [ accum ] curry reduce first2 swap ]
        [ drop - abs ]
    } 2cleave ;

580 34 ediv "580 divided by 34 is %d remainder %d\n" printf


variable tab-end

: build ( m n -- )
    pad tab-end !
    swap >r  1 swap  \ dividend on ret stack
    begin dup [email protected] <= while
        2dup tab-end @ 2!
        [ 2 cells ] literal tab-end +!
        swap dup +
        swap dup +
    repeat 2drop rdrop ;

: e/mod ( m n -- q r )
    over >r build
    0 r>  \ initial quotient = 0, remainder = dividend
    pad tab-end @ [ 2 cells ] literal - do
        dup i @ >= if
            i @ -  swap i cell+ @ +  swap
        then
    [ -2 cells ] literal +loop ;

: .egypt ( m n -- )
    cr 2dup swap . ." divided by " . ." is " e/mod swap . ." remainder " . ;


' version 09-08-2017
' compile with: fbc -s console

Data 580, 34

Dim As UInteger dividend, divisor, answer, accumulator, i
ReDim As UInteger table(1 To 32, 1 To 2)

Read dividend, divisor

i = 1
table(i, 1) = 1 : table(i, 2) = divisor

While table(i, 2) < dividend
    i += 1
    table(i, 1) = table(i -1, 1) * 2
    table(i, 2) = table(i -1, 2) * 2
Wend

i -= 1
answer = table(i, 1)
accumulator = table(i, 2)

While i > 1
    i -= 1
    If table(i,2)+ accumulator <= dividend Then
        answer += table(i, 1)
        accumulator += table(i, 2)
    End If
Wend

Print Str(dividend); " divided by "; Str(divisor); " using Egytian division";
Print " returns "; Str(answer); " mod(ulus) "; Str(dividend-accumulator)

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


package main

import "fmt"

func egyptianDivide(dividend, divisor int) (quotient, remainder int) {
    if dividend < 0 || divisor <= 0 {
        panic("Invalid argument(s)")
    }
    if dividend < divisor {
        return 0, dividend
    }
    powersOfTwo := []int{1}
    doublings := []int{divisor}
    doubling := divisor
    for {
        doubling *= 2
        if doubling > dividend {
            break
        }
        l := len(powersOfTwo)
        powersOfTwo = append(powersOfTwo, powersOfTwo[l-1]*2)
        doublings = append(doublings, doubling)
    }
    answer := 0
    accumulator := 0
    for i := len(doublings) - 1; i >= 0; i-- {
        if accumulator+doublings[i] <= dividend {
            accumulator += doublings[i]
            answer += powersOfTwo[i]
            if accumulator == dividend {
                break
            }
        }
    }
    return answer, dividend - accumulator
}

func main() {
    dividend := 580
    divisor := 34
    quotient, remainder := egyptianDivide(dividend, divisor)
    fmt.Println(dividend, "divided by", divisor, "is", quotient, "with remainder", remainder)
}


class EgyptianDivision {
    /**
     * Runs the method and divides 580 by 34
     *
     * @param args not used
     */
    static void main(String[] args) {
        divide(580, 34)
    }

    /**
     * Divides dividend by divisor using the Egyptian Division-Algorithm and prints the
     * result to the console
     *
     * @param dividend
     * @param divisor
     */
    static void divide(int dividend, int divisor) {
        List<Integer> powersOf2 = new ArrayList<>()
        List<Integer> doublings = new ArrayList<>()

        //populate the powersof2- and doublings-columns
        int line = 0
        while ((Math.pow(2, line) * divisor) <= dividend) { //<- could also be done with a for-loop
            int powerOf2 = (int) Math.pow(2, line)
            powersOf2.add(powerOf2)
            doublings.add(powerOf2 * divisor)
            line++
        }

        int answer = 0
        int accumulator = 0

        //Consider the rows in reverse order of their construction (from back to front of the List<>s)
        for (int i = powersOf2.size() - 1; i >= 0; i--) {
            if (accumulator + doublings.get(i) <= dividend) {
                accumulator += doublings.get(i)
                answer += powersOf2.get(i)
            }
        }

       println(String.format("%d, remainder %d", answer, dividend - accumulator))
    }
}


import Data.List (unfoldr)

egyptianQuotRem :: Integer -> Integer -> (Integer, Integer)
egyptianQuotRem m n =
  let expansion (i, x)
        | x > m = Nothing
        | otherwise = Just ((i, x), (i + i, x + x))
      collapse (i, x) (q, r)
        | x < r = (q + i, r - x)
        | otherwise = (q, r)
  in foldr collapse (0, m) $ unfoldr expansion (1, n)

main :: IO ()
main = print $ egyptianQuotRem 580 34


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

public class EgyptianDivision {

    /**
     * Runs the method and divides 580 by 34
     *
     * @param args not used
     */
    public static void main(String[] args) {

        divide(580, 34);

    }

    /**
     * Divides dividend by divisor using the Egyptian Division-Algorithm and prints the
     * result to the console
     *
     * @param dividend
     * @param divisor
     */
    public static void divide(int dividend, int divisor) {

        List<Integer> powersOf2 = new ArrayList<>();
        List<Integer> doublings = new ArrayList<>();

        //populate the powersof2- and doublings-columns
        int line = 0;
        while ((Math.pow(2, line) * divisor) <= dividend) { //<- could also be done with a for-loop
            int powerOf2 = (int) Math.pow(2, line);
            powersOf2.add(powerOf2);
            doublings.add(powerOf2 * divisor);
            line++;
        }

        int answer = 0;
        int accumulator = 0;

        //Consider the rows in reverse order of their construction (from back to front of the List<>s)
        for (int i = powersOf2.size() - 1; i >= 0; i--) {
            if (accumulator + doublings.get(i) <= dividend) {
                accumulator += doublings.get(i);
                answer += powersOf2.get(i);
            }
        }

        System.out.println(String.format("%d, remainder %d", answer, dividend - accumulator));
    }
}


(() => {
    'use strict';

    // EGYPTIAN DIVISION --------------------------------

    // eqyptianQuotRem :: Int -> Int -> (Int, Int)
    const eqyptianQuotRem = (m, n) => {
        const expansion = ([i, x]) =>
            x > m ? (
                Nothing()
            ) : Just([
                [i, x],
                [i + i, x + x]
            ]);
        const collapse = ([i, x], [q, r]) =>
            x < r ? (
                [q + i, r - x]
            ) : [q, r];
        return foldr(
            collapse,
            [0, m],
            unfoldr(expansion, [1, n])
        );
    };

    // TEST ---------------------------------------------

    // main :: IO ()
    const main = () =>
        showLog(
            eqyptianQuotRem(580, 34)
        );
        // -> [17, 2]

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

    // Just :: a -> Maybe a
    const Just = x => ({
        type: 'Maybe',
        Nothing: false,
        Just: x
    });

    // Nothing :: Maybe a
    const Nothing = () => ({
        type: 'Maybe',
        Nothing: true,
    });

    // flip :: (a -> b -> c) -> b -> a -> c
    const flip = f =>
        1 < f.length ? (
            (a, b) => f(b, a)
        ) : (x => y => f(y)(x));

    // foldr :: (a -> b -> b) -> b -> [a] -> b
    const foldr = (f, a, xs) => xs.reduceRight(flip(f), a);

    // unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
    const unfoldr = (f, v) => {
        let
            xr = [v, v],
            xs = [];
        while (true) {
            const mb = f(xr[1]);
            if (mb.Nothing) {
                return xs
            } else {
                xr = mb.Just;
                xs.push(xr[0])
            }
        }
    };

    // showLog :: a -> IO ()
    const showLog = (...args) =>
        console.log(
            args
            .map(JSON.stringify)
            .join(' -> ')
        );

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


function egyptiandivision(dividend::Int, divisor::Int)
    N         = 64
    powers    = Vector{Int}(N)
    doublings = Vector{Int}(N)

    ind = 0
    for i in 0:N-1
        powers[i+1] = 1 << i
        doublings[i+1] = divisor << i
        if doublings[i+1] > dividend ind = i-1; break end
    end

    ans = acc = 0
    for i in ind:-1:0
        if acc + doublings[i+1] ≤ dividend
            acc += doublings[i+1]
            ans += powers[i+1]
        end
    end

    return ans, dividend - acc
end

q, r = egyptiandivision(580, 34)
println("580 ÷ 34 = $q (remains $r)")

using Base.Test

@testset "Equivalence to divrem builtin function" begin
    for x in rand(1:100, 100), y in rand(1:100, 10)
    @test egyptiandivision(x, y) == divrem(x, y)
    end
end


// version 1.1.4

data class DivMod(val quotient: Int, val remainder: Int)

fun egyptianDivide(dividend: Int, divisor: Int): DivMod {
    require (dividend >= 0 && divisor > 0)
    if (dividend < divisor) return DivMod(0, dividend)
    val powersOfTwo = mutableListOf(1)
    val doublings = mutableListOf(divisor)
    var doubling = divisor
    while (true) {
       doubling *= 2
       if (doubling > dividend) break
       powersOfTwo.add(powersOfTwo[powersOfTwo.lastIndex] * 2)
       doublings.add(doubling)
    }
    var answer = 0
    var accumulator = 0
    for (i in doublings.size - 1 downTo 0) {
        if (accumulator + doublings[i] <= dividend) {
            accumulator += doublings[i]
            answer += powersOfTwo[i]
            if (accumulator == dividend) break
        }
    }
    return DivMod(answer, dividend - accumulator)
}

fun main(args: Array<String>) {
    val dividend = 580
    val divisor = 34
    val (quotient, remainder) = egyptianDivide(dividend, divisor)
    println("$dividend divided by $divisor is $quotient with remainder $remainder")
}


function egyptian_divmod(dividend,divisor)
    local pwrs, dbls = {1}, {divisor}
    while dbls[#dbls] <= dividend do
        table.insert(pwrs, pwrs[#pwrs] * 2)
        table.insert(dbls, pwrs[#pwrs] * divisor)
    end
    local ans, accum = 0, 0

    for i=#pwrs-1,1,-1 do
        if accum + dbls[i] <= dividend then
            accum = accum + dbls[i]
            ans = ans + pwrs[i]
        end
    end

    return ans, math.abs(accum - dividend)
end

local i, j = 580, 34
local d, m = egyptian_divmod(i, j)
print(i.." divided by "..j.." using the Egyptian method is "..d.." remainder "..m)


ClearAll[EgyptianDivide]
EgyptianDivide[dividend_, divisor_] := Module[{table, i, answer, accumulator},
  table = {{1, divisor}};
  i = 1;
  While[Last[Last[table]] < dividend,
   AppendTo[table, 2^i {1, divisor}];
   i++
   ];
  table //= Most;
  answer = 0;
  accumulator = 0;
  Do[
   If[accumulator + t[[2]] <= dividend,
    accumulator += t[[2]];
    answer += t[[1]]
    ]
   ,
   {t, [email protected]}
   ];
  {answer, dividend - accumulator}
  ]
EgyptianDivide[580, 34]


MODULE EgyptianDivision;
FROM FormatString IMPORT FormatString;
FROM Terminal IMPORT WriteString,ReadChar;

PROCEDURE EgyptianDivision(dividend,divisor : LONGCARD; VAR remainder : LONGCARD) : LONGCARD;
CONST
    SZ = 64;
VAR
    powers,doublings : ARRAY[0..SZ] OF LONGCARD;
    answer,accumulator : LONGCARD;
    i : INTEGER;
BEGIN
    FOR i:=0 TO SZ-1 DO
        powers[i] := 1 SHL i;
        doublings[i] := divisor SHL i;
        IF doublings[i] > dividend THEN
            BREAK
        END
    END;

    answer := 0;
    accumulator := 0;
    FOR i:=i-1 TO 0 BY -1 DO
        IF accumulator + doublings[i] <= dividend THEN
            accumulator := accumulator + doublings[i];
            answer := answer + powers[i]
        END
    END;

    remainder := dividend - accumulator;
    RETURN answer
END EgyptianDivision;

VAR
    buf : ARRAY[0..63] OF CHAR;
    div,rem : LONGCARD;
BEGIN
    div := EgyptianDivision(580, 34, rem);
    FormatString("580 divided by 34 is %l remainder %l\n", buf, div, rem);
    WriteString(buf);

    ReadChar
END EgyptianDivision.


import strformat

func egyptianDivision(dividend, divisor: int): tuple[quotient, remainder: int] =
  if dividend < 0 or divisor <= 0:
    raise newException(IOError, "Invalid argument(s)")
  if dividend < divisor:
    return (0, dividend)

  var powersOfTwo: array[sizeof(int) * 8, int]
  var doublings: array[sizeof(int) * 8, int]

  for i, _ in powersOfTwo:
    powersOfTwo[i] = 1 shl i
    doublings[i] = divisor shl i
    if doublings[i] > dividend:
      break

  var answer = 0
  var accumulator = 0
  for i in countdown(len(doublings) - 1, 0):
    if accumulator + doublings[i] <= dividend:
      inc accumulator, doublings[i]
      inc answer, powersOfTwo[i]
      if accumulator == dividend:
        break
  (answer, dividend - accumulator)

let dividend = 580
let divisor = 34
var (quotient, remainder) = egyptianDivision(dividend, divisor)
echo fmt"{dividend} divided by {divisor} is {quotient} with remainder {remainder}"


sub egyptian_divmod {
    my($dividend, $divisor) = @_;
    die "Invalid divisor" if $divisor <= 0;

    my @table = ($divisor);
    push @table, 2*$table[-1] while $table[-1] <= $dividend;

    my $accumulator = 0;
    for my $k (reverse 0 .. $#table) {
        next unless $dividend >= $table[$k];
        $accumulator += 1 << $k;
        $dividend    -= $table[$k];
    }
    $accumulator, $dividend;
}

for ([580,34], [578,34], [7532795332300578,235117]) {
    my($n,$d) = @$_;
    printf "Egyption divmod %s %% %s = %s remainder %s\n", $n, $d, egyptian_divmod( $n, $d )
}


with javascript_semantics
procedure egyptian_division(integer dividend, divisor)
    integer p2 = 1, dbl = divisor, ans = 0, accum = 0
    sequence p2s = {}, dbls = {}, args
    while dbl<=dividend do
        p2s = append(p2s,p2)
        dbls = append(dbls,dbl)
        dbl += dbl
        p2 += p2
    end while
    for i=length(p2s) to 1 by -1 do
        if accum+dbls[i]<=dividend then
            accum += dbls[i]
            ans += p2s[i]
        end if
    end for
    args = {dividend,divisor,ans,abs(accum-dividend)}
    printf(1,"%d divided by %d is: %d remainder %d\n",args)
end procedure

egyptian_division(580,34)


(seed (in "/dev/urandom" (rd 8)))

(de divmod (Dend Disor)
   (cons (/ Dend Disor) (% Dend Disor)) )
(de egyptian (Dend Disor)
   (let
      (P 0
         D Disor
         S
         (make
            (while (>= Dend (setq @@ (+ D D)))
               (yoke
                  (cons
                     (** 2 (swap 'P (inc P)))
                     (swap 'D @@) ) ) ) )
         P (** 2 P) )
      (mapc
         '((L)
            (and
               (>= Dend (+ D (cdr L)))
               (inc 'P (car L))
               (inc 'D (cdr L)) ) )
         S )
      (cons P (abs (- Dend D))) ) )
(for N 1000
   (let (A (rand 1 1000)  B (rand 1 A))
      (test (divmod A B) (egyptian A B)) ) )
(println (egyptian 580 34))


egyptian_divide(Dividend, Divisor, Quotient, Remainder):-
    powers2_multiples(Dividend, [1], Powers, [Divisor], Multiples),
    accumulate(Dividend, Powers, Multiples, 0, Quotient, 0, Acc),
    Remainder is Dividend - Acc.

powers2_multiples(Dividend, Powers, Powers, Multiples, Multiples):-
    Multiples = [M|_],
    2 * M > Dividend,
    !.
powers2_multiples(Dividend, [Power|P], Powers, [Multiple|M], Multiples):-
    Power2 is 2 * Power,
    Multiple2 is 2 * Multiple,
    powers2_multiples(Dividend, [Power2,Power|P], Powers,
                      [Multiple2, Multiple|M], Multiples).

accumulate(_, [], [], Ans, Ans, Acc, Acc):-!.
accumulate(Dividend, [P|Powers], [M|Multiples], Ans1, Answer, Acc1, Acc):-
    Acc1 + M =< Dividend,
    !,
    Acc2 is Acc1 + M,
    Ans2 is Ans1 + P,
    accumulate(Dividend, Powers, Multiples, Ans2, Answer, Acc2, Acc).
accumulate(Dividend, [_|Powers], [_|Multiples], Ans1, Answer, Acc1, Acc):-
    accumulate(Dividend, Powers, Multiples, Ans1, Answer, Acc1, Acc).

test_egyptian_divide(Dividend, Divisor):-
    egyptian_divide(Dividend, Divisor, Quotient, Remainder),
    writef('%w / %w = %w, remainder = %w\n', [Dividend, Divisor,
           Quotient, Remainder]).

main:-
    test_egyptian_divide(580, 34).


from itertools import product

def egyptian_divmod(dividend, divisor):
    assert divisor != 0
    pwrs, dbls = [1], [divisor]
    while dbls[-1] <= dividend:
        pwrs.append(pwrs[-1] * 2)
        dbls.append(pwrs[-1] * divisor)
    ans, accum = 0, 0
    for pwr, dbl in zip(pwrs[-2::-1], dbls[-2::-1]):
        if accum + dbl <= dividend:
            accum += dbl
            ans += pwr
    return ans, abs(accum - dividend)

if __name__ == "__main__":
    # Test it gives the same results as the divmod built-in
    for i, j in product(range(13), range(1, 13)):
            assert egyptian_divmod(i, j) == divmod(i, j)
    # Mandated result
    i, j = 580, 34
    print(f'{i} divided by {j} using the Egyption method is %i remainder %i'
          % egyptian_divmod(i, j))


  [ dup 0 = if
      [ $ "Cannot divide by zero."
        fail ]
    [] unrot
    [ 2dup < not while
      rot over swap join
      unrot dup + again ]
    drop swap
    dup size
    [] 1 rot times
      [ tuck swap join
        swap dup + ]
    drop
    temp put
    0 swap
    witheach
      [ over +
        rot 2dup > iff
          [ nip swap
            0
            temp take
            i^ poke
            temp put ]
          else
            [ swap rot drop ] ]
    - 0 temp take
    witheach +
    swap ]                         is egyptian ( n n --> n n )

  [ over echo
    say " divided by "
    dup echo
    say " is "
    egyptian
    swap echo
    say " remainder "
    echo
    say "." ]                      is task     ( n n -->     )

  580 34 task


Egyptian_division <- function(num, den){
  pow2 = 0
  row = 1

  Table = data.frame(powers_of_2 = 2^pow2,
                     doubling = den)

  while(Table$doubling[nrow(Table)] < num){
    row = row + 1
    pow2 = pow2 + 1

    Table[row, 1] <- 2^pow2
    Table[row, 2] <- 2^pow2 * den
  }

  Table <- Table[-nrow(Table),]
  #print(Table) to see the table

  answer <- 0
  accumulator <- 0

  for (i in nrow(Table):1) {
    if (accumulator + Table$doubling[i] <= num) {
      accumulator <- accumulator + Table$doubling[i]
      answer <- answer + Table$powers_of_2[i]
    }
  }

  remainder = abs(accumulator - num)

  message(paste0("Answer is ", answer, ", remainder ", remainder))

  }

Egyptian_division(580, 34)
Egyptian_division(300, 2)


#lang racket

(define (quotient/remainder-egyptian dividend divisor (trace? #f))
  (define table
    (for*/list ((power_of_2 (sequence-map (curry expt 2) (in-naturals)))
                (doubling (in-value (* divisor power_of_2)))
                #:break (> doubling dividend))
      (list power_of_2 doubling)))

  (when trace?
    (displayln "Table\npow_2\tdoubling")
    (for ((row table)) (printf "~a\t~a~%" (first row) (second row))))

  (define-values (answer accumulator)
    (for*/fold ((answer 0) (accumulator 0))
               ((row (reverse table))
                (acc′ (in-value (+ accumulator (second row)))))
      (when trace? (printf "row:~a\tans/acc:~a ~a\t" row answer accumulator))
      (cond
        [(<= acc′ dividend)
         (define ans′ (+ answer (first row)))
         (when trace? (printf "~a <= ~a -> ans′/acc′:~a ~a~%" acc′ dividend ans′ acc′))
         (values ans′ acc′)]
        [else
         (when trace? (printf "~a > ~a [----]~%" acc′ dividend))
         (values answer accumulator)])))

  (values answer (- dividend accumulator)))

(module+ test
  (require rackunit)
  (let-values (([q r] (quotient/remainder-egyptian 580 34)))
    (check-equal? q 17)
    (check-equal? r 2))

  (let-values (([q r] (quotient/remainder-egyptian 192 3)))
    (check-equal? q 64)
    (check-equal? r 0)))

(module+ main
  (quotient/remainder-egyptian 580 34 #t))


sub egyptian-divmod (Real $dividend is copy where * >= 0, Real $divisor where * > 0) {
    my $accumulator = 0;
    ([1, $divisor], { [.[0] + .[0], .[1] + .[1]] } … ^ *.[1] > $dividend)
      .reverse.map: { $dividend -= .[1], $accumulator += .[0] if $dividend >= .[1] }
    $accumulator, $dividend;
}

#TESTING
for 580,34, 578,34, 7532795332300578,235117 -> $n, $d {
    printf "%s divmod %s = %s remainder %s\n",
        $n, $d, |egyptian-divmod( $n, $d )
}


/*REXX program performs division on positive integers using the Egyptian division method*/
numeric digits 1000                              /*support gihugic numbers & be gung-ho.*/
parse arg n d .                                  /*obtain optional arguments from the CL*/
if d=='' | d==","  then do;  n= 580;    d= 34    /*Not specified?  Then use the defaults*/
                        end
call EgyptDiv n, d                               /*invoke the Egyptian Division function*/
parse var result q r                             /*extract the quotient & the remainder.*/
say n   ' divided by '       d       " is "       q       ' with a remainder of '      r
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
EgyptDiv: procedure;  parse arg num,dem          /*obtain the numerator and denominator.*/
          p= 1;                       t= dem     /*initialize the double & power values.*/
                        do #=1  until t>num      /*construct the power & doubling lists.*/
                        pow.#= p;     p= p + p   /*build power  entry; bump power value.*/
                        dbl.#= t;     t= t + t   /*  "  doubling  "  ;   " doubling val.*/
                        end   /*#*/
          acc=0;  ans=0                          /*initialize accumulator & answer to 0 */
                        do s=#   by -1   for #   /* [↓]  process the table "backwards". */
                        sum= acc + dbl.s         /*compute the sum (to be used for test)*/
                        if sum>num  then iterate /*Is sum to big?  Then ignore this step*/
                        acc= sum                 /*use the "new" sum for the accumulator*/
                        ans= ans + pow.s         /*calculate the (newer) running answer.*/
                        end   /*s*/
          return ans  num-acc                    /*return the answer and the remainder. */


load "stdlib.ring"

table = newlist(32, 2)
dividend = 580
divisor = 34

i = 1
table[i][1] = 1
table[i][2] = divisor

while table[i] [2] < dividend
      i = i + 1
      table[i][1] = table[i -1] [1] * 2
      table[i][2] = table[i -1] [2] * 2
end
i = i - 1
answer = table[i][1]
accumulator = table[i][2]

while i > 1
      i = i - 1
      if table[i][2]+ accumulator <= dividend
         answer = answer + table[i][1]
         accumulator = accumulator + table[i][2]
      ok
end

see string(dividend)  + " divided by " + string(divisor) + " using egytian division" + nl
see " returns " + string(answer) + " mod(ulus) " + string(dividend-accumulator)


def egyptian_divmod(dividend, divisor)
  table = [[1, divisor]]
  table << table.last.map{|e| e*2} while table.last.first * 2 <= dividend
  answer, accumulator = 0, 0
  table.reverse_each do |pow, double|
    if accumulator + double <= dividend
      accumulator += double
      answer += pow
    end
  end
  [answer, dividend - accumulator]
end

puts "Quotient = %s Remainder = %s" % egyptian_divmod(580, 34)


fn egyptian_divide(dividend: u32, divisor: u32) -> (u32, u32) {
    let dividend = dividend as u64;
    let divisor = divisor as u64;

    let pows = (0..32).map(|p| 1 << p);
    let doublings = (0..32).map(|p| divisor << p);

    let (answer, sum) = doublings
        .zip(pows)
        .rev()
        .skip_while(|(i, _)| i > &dividend )
        .fold((0, 0), |(answer, sum), (double, power)| {
            if sum + double < dividend {
                (answer + power, sum + double)
            } else {
                (answer, sum)
            }
        });

    (answer as u32, (dividend - sum) as u32)
}

fn main() {
    let (div, rem) = egyptian_divide(580, 34);
    println!("580 divided by 34 is {} remainder {}", div, rem);
}


object EgyptianDivision extends App {

  private def divide(dividend: Int, divisor: Int): Unit = {
    val powersOf2, doublings = new collection.mutable.ListBuffer[Integer]

    //populate the powersof2- and doublings-columns
    var line = 0
    while ((math.pow(2, line) * divisor) <= dividend) {
      val powerOf2 = math.pow(2, line).toInt
      powersOf2 += powerOf2
      doublings += (powerOf2 * divisor)
      line += 1
    }

    var answer, accumulator = 0
    //Consider the rows in reverse order of their construction (from back to front of the List)
    var i = powersOf2.size - 1
    for (i <- powersOf2.size - 1 to 0 by -1)
      if (accumulator + doublings(i) <= dividend) {
        accumulator += doublings(i)
        answer += powersOf2(i)
      }

    println(f"$answer%d, remainder ${dividend - accumulator}%d")
  }

  divide(580, 34)

}


func egyptian_divmod(dividend, divisor) {
  var table = [[1, divisor]]
  table << table[-1].map{|e| 2*e } while (2*table[-1][0] <= dividend)
  var (answer, accumulator) = (0, 0)
  table.reverse.each { |pair|
    var (pow, double) = pair...
    if (accumulator + double <= dividend) {
      accumulator += double
      answer += pow
    }
  }
  return (answer, dividend - accumulator)
}

say ("Quotient = %s Remainder = %s" % egyptian_divmod(580, 34))


extension BinaryInteger {
  @inlinable
  public func egyptianDivide(by divisor: Self) -> (quo: Self, rem: Self) {
    let table =
      (0...).lazy
        .map({i -> (Self, Self) in
          let power = Self(2).power(Self(i))

          return (power, power * divisor)
        })
        .prefix(while: { $0.1 <= self })
        .reversed()

    let (answer, acc) = table.reduce((Self(0), Self(0)), {cur, row in
      let ((ans, acc), (power, doubling)) = (cur, row)

      return acc + doubling <= self ? (ans + power, doubling + acc) : cur
    })

    return (answer, Self((acc - self).magnitude))
  }

  @inlinable
  public func power(_ n: Self) -> Self {
    return stride(from: 0, to: n, by: 1).lazy.map({_ in self }).reduce(1, *)
  }
}

let dividend = 580
let divisor = 34
let (quo, rem) = dividend.egyptianDivide(by: divisor)

print("\(dividend) divided by \(divisor) = \(quo) rem \(rem)")


templates egyptianDivision
  def dividend: $(1);
  def divisor: $(2);
  def table: [ { powerOf2: 1"1", doubling: ($divisor)"1" } -> \(
    when <{doubling: <..$dividend>}> do
      $ !
      { powerOf2: $.powerOf2 * 2, doubling: $.doubling * 2 } -> #
  \)];
  @: { answer: 0"1", accumulator: 0"1" };
  $table(last..1:-1)... -> #
  [email protected] !

  when <{doubling: <[email protected]>}> do
    @: { answer: [email protected] + $.powerOf2, accumulator: [email protected] + $.doubling };
end egyptianDivision

[580"1", 34"1"] -> egyptianDivision -> 'Quotient: $.answer; Remainder: $: 580"1" - $.accumulator;' -> !OUT::write


Option Explicit

Private Type MyTable
    powers_of_2 As Long
    doublings As Long
End Type

Private Type Assemble
    answer As Long
    accumulator As Long
End Type

Private Type Division
    Quotient As Long
    Remainder As Long
End Type

Private Type DivEgyp
    Dividend As Long
    Divisor As Long
End Type

Private Deg As DivEgyp

Sub Main()
Dim d As Division
    Deg.Dividend = 580
    Deg.Divisor = 34
    d = Divise(CreateTable)
    Debug.Print "Quotient = " & d.Quotient & " Remainder = " & d.Remainder
End Sub

Private Function CreateTable() As MyTable()
Dim t() As MyTable, i As Long
    Do
        i = i + 1
        ReDim Preserve t(i)
        t(i).powers_of_2 = 2 ^ (i - 1)
        t(i).doublings = Deg.Divisor * t(i).powers_of_2
    Loop While 2 * t(i).doublings <= Deg.Dividend
    CreateTable = t
End Function

Private Function Divise(t() As MyTable) As Division
Dim a As Assemble, i As Long
    a.accumulator = 0
    a.answer = 0
    For i = UBound(t) To LBound(t) Step -1
        If a.accumulator + t(i).doublings <= Deg.Dividend Then
            a.accumulator = a.accumulator + t(i).doublings
            a.answer = a.answer + t(i).powers_of_2
        End If
    Next
    Divise.Quotient = a.answer
    Divise.Remainder = Deg.Dividend - a.accumulator
End Function


Module Module1

    Function EgyptianDivision(dividend As ULong, divisor As ULong, ByRef remainder As ULong) As ULong
        Const SIZE = 64
        Dim powers(SIZE) As ULong
        Dim doublings(SIZE) As ULong
        Dim i = 0

        While i < SIZE
            powers(i) = 1 << i
            doublings(i) = divisor << i
            If doublings(i) > dividend Then
                Exit While
            End If
            i = i + 1
        End While

        Dim answer As ULong = 0
        Dim accumulator As ULong = 0
        i = i - 1
        While i >= 0
            If accumulator + doublings(i) <= dividend Then
                accumulator += doublings(i)
                answer += powers(i)
            End If
            i = i - 1
        End While

        remainder = dividend - accumulator
        Return answer
    End Function

    Sub Main(args As String())
        If args.Length < 2 Then
            Dim name = Reflection.Assembly.GetEntryAssembly().Location
            Console.Error.WriteLine("Usage: {0} dividend divisor", IO.Path.GetFileNameWithoutExtension(name))
            Return
        End If

        Dim dividend = CULng(args(0))
        Dim divisor = CULng(args(1))
        Dim remainder As ULong

        Dim ans = EgyptianDivision(dividend, divisor, remainder)
        Console.WriteLine("{0} / {1} = {2} rem {3}", dividend, divisor, ans, remainder)
    End Sub

End Module


fn egyptian_divide(dividend int, divisor int) ?(int, int) {

    if dividend < 0 || divisor <= 0 {
        panic("Invalid argument(s)")
    }
    if dividend < divisor {
        return 0, dividend
    }
    mut powers_of_two := [1]
    mut doublings := [divisor]
    mut doubling := divisor
    for {
        doubling *= 2
        if doubling > dividend {
            break
        }
        l := powers_of_two.len
        powers_of_two << powers_of_two[l-1]*2
        doublings << doubling
    }
    mut answer := 0
    mut accumulator := 0
    for i := doublings.len - 1; i >= 0; i-- {
        if accumulator+doublings[i] <= dividend {
            accumulator += doublings[i]
            answer += powers_of_two[i]
            if accumulator == dividend {
                break
            }
        }
    }
    return answer, dividend - accumulator
}

fn main() {
    dividend := 580
    divisor := 34
    quotient, remainder := egyptian_divide(dividend, divisor)?
    println("$dividend divided by $divisor is $quotient with remainder $remainder")
}


var egyptianDivide = Fn.new { |dividend, divisor|
    if (dividend < 0 || divisor <= 0) Fiber.abort("Invalid argument(s).")
    if (dividend < divisor) return [0, dividend]
    var powersOfTwo = [1]
    var doublings = [divisor]
    var doubling = divisor
    while (true) {
        doubling = 2 * doubling
        if (doubling > dividend) break
        powersOfTwo.add(powersOfTwo[-1]*2)
        doublings.add(doubling)
    }
    var answer = 0
    var accumulator = 0
    for (i in doublings.count-1..0) {
        if (accumulator + doublings[i] <= dividend) {
            accumulator = accumulator + doublings[i]
            answer = answer + powersOfTwo[i]
            if (accumulator == dividend) break
        }
    }
    return [answer, dividend - accumulator]
}

var dividend = 580
var divisor = 34
var res = egyptianDivide.call(dividend, divisor)
System.print("%(dividend) ÷ %(divisor) = %(res[0]) with remainder %(res[1]).")


fcn egyptianDivmod(dividend,divisor){
   table:=[0..].pump(List, 'wrap(n){	// (2^n,divisor*2^n)
      r:=T( p:=(2).pow(n), s:=divisor*p); (s<=dividend) and r or Void.Stop });
   accumulator:=0;
   foreach p2,d in (table.reverse()){
      if(dividend>=d){ accumulator+=p2; dividend-=d; }
   }
   return(accumulator,dividend);
}


#include <iostream>
#include <locale>
#include <unordered_map>

#include <primesieve.hpp>

class prime_gaps {
public:
    prime_gaps() { last_prime_ = iterator_.next_prime(); }
    uint64_t find_gap_start(uint64_t gap);
private:
    primesieve::iterator iterator_;
    uint64_t last_prime_;
    std::unordered_map<uint64_t, uint64_t> gap_starts_;
};

uint64_t prime_gaps::find_gap_start(uint64_t gap) {
    auto i = gap_starts_.find(gap);
    if (i != gap_starts_.end())
        return i->second;
    for (;;) {
        uint64_t prev = last_prime_;
        last_prime_ = iterator_.next_prime();
        uint64_t diff = last_prime_ - prev;
        gap_starts_.emplace(diff, prev);
        if (gap == diff)
            return prev;
    }
}

int main() {
    std::cout.imbue(std::locale(""));
    const uint64_t limit = 100000000000;
    prime_gaps pg;
    for (uint64_t pm = 10, gap1 = 2;;) {
        uint64_t start1 = pg.find_gap_start(gap1);
        uint64_t gap2 = gap1 + 2;
        uint64_t start2 = pg.find_gap_start(gap2);
        uint64_t diff = start2 > start1 ? start2 - start1 : start1 - start2;
        if (diff > pm) {
            std::cout << "Earliest difference > " << pm
                      << " between adjacent prime gap starting primes:\n"
                      << "Gap " << gap1 << " starts at " << start1 << ", gap "
                      << gap2 << " starts at " << start2 << ", difference is "
                      << diff << ".\n\n";
            if (pm == limit)
                break;
            pm *= 10;
        } else {
            gap1 = gap2;
        }
    }
}


// Earliest difference between prime gaps. Nigel Galloway: December 1st., 2021
let fN y=let i=System.Collections.Generic.SortedDictionary<int64,int64>()
         let fN()=i|>Seq.pairwise|>Seq.takeWhile(fun(n,g)->g.Key=n.Key+2L)|>Seq.tryFind(fun(n,g)->abs(n.Value-g.Value)>y)
         (fun(n,g)->let e=g-n in match i.TryGetValue(e) with (false,_)->i.Add(e,n); fN() |_->None)
[1..9]|>List.iter(fun g->let fN=fN(pown 10 g) in let n,i=(primes64()|>Seq.skip 1|>Seq.pairwise|>Seq.map fN|>Seq.find Option.isSome).Value
                         printfn $"%10d{pown 10 g} -> distance between start of gap %d{n.Key}=%d{n.Value} and start of gap %d{i.Key}=%d{i.Value} is %d{abs((n.Value)-(i.Value))}")


package main

import (
    "fmt"
    "rcu"
)

func main() {
    limit := int(1e9)
    gapStarts := make(map[int]int)
    primes := rcu.Primes(limit * 5)
    for i := 1; i < len(primes); i++ {
        gap := primes[i] - primes[i-1]
        if _, ok := gapStarts[gap]; !ok {
            gapStarts[gap] = primes[i-1]
        }
    }
    pm := 10
    gap1 := 2
    for {
        for _, ok := gapStarts[gap1]; !ok; {
            gap1 += 2
        }
        start1 := gapStarts[gap1]
        gap2 := gap1 + 2
        if _, ok := gapStarts[gap2]; !ok {
            gap1 = gap2 + 2
            continue
        }
        start2 := gapStarts[gap2]
        diff := start2 - start1
        if diff < 0 {
            diff = -diff
        }
        if diff > pm {
            cpm := rcu.Commatize(pm)
            cst1 := rcu.Commatize(start1)
            cst2 := rcu.Commatize(start2)
            cd := rcu.Commatize(diff)
            fmt.Printf("Earliest difference > %s between adjacent prime gap starting primes:\n", cpm)
            fmt.Printf("Gap %d starts at %s, gap %d starts at %s, difference is %s.\n\n", gap1, cst1, gap2, cst2, cd)
            if pm == limit {
                break
            }
            pm *= 10
        } else {
            gap1 = gap2
        }
    }
}


BEGIN # compute some Egytian fractions #
    PR precision 2000 PR # set the number of digits for LONG LONG INT #
    PROC gcd = ( LONG LONG INT a, b )LONG LONG INT:
        IF b = 0 THEN
            IF a < 0 THEN
                - a
            ELSE
                a
            FI
        ELSE
            gcd( b, a MOD b )
        FI ; # gcd #
    MODE RATIONAL       = STRUCT( LONG LONG INT num, den );
    MODE LISTOFRATIONAL = STRUCT( RATIONAL element, REF LISTOFRATIONAL next );
    REF LISTOFRATIONAL  nil list of rational = NIL;
    OP   TOSTRING = (           INT a )STRING: whole( a, 0 );
    OP   TOSTRING = (      LONG INT a )STRING: whole( a, 0 );
    OP   TOSTRING = ( LONG LONG INT a )STRING: whole( a, 0 );
    OP   TOSTRING = (      RATIONAL a )STRING:
         IF den OF a = 1
         THEN TOSTRING num OF a
         ELSE TOSTRING num OF a + "/" + TOSTRING den OF a
         FI ; # TOSTRING #
    OP   TOSTRING = ( REF LISTOFRATIONAL lr )STRING:
         BEGIN
             REF LISTOFRATIONAL p      := lr;
             STRING             result := "[";
             WHILE p ISNT nil list of rational DO
                 result +:= TOSTRING element OF p;
                 IF next OF p IS nil list of rational THEN
                     p := NIL
                 ELSE
                     p := next OF p;
                     result +:= " + "
                 FI
             OD;
             result + "]"
         END ; # TOSTRING #
    OP   CEIL = ( LONG LONG REAL v )LONG LONG INT:
         IF LONG LONG INT result := ENTIER v;
            ABS v > ABS result
         THEN result + 1
         ELSE result
         FI ;  # CEIL #
    OP   EGYPTIAN = ( RATIONAL rp )REF LISTOFRATIONAL:
         IF RATIONAL r := rp;
            num OF r = 0 OR num OF r = 1
         THEN HEAP LISTOFRATIONAL := ( r, nil list of rational )
         ELSE
            REF LISTOFRATIONAL result     := nil list of rational;
            REF LISTOFRATIONAL end result := nil list of rational;
            PROC add = ( RATIONAL r )VOID:
                 IF end result IS nil list of rational THEN
                    result     := HEAP LISTOFRATIONAL := ( r, nil list of rational );
                    end result := result
                 ELSE
                    next OF end result := HEAP LISTOFRATIONAL := ( r, nil list of rational );
                    end result         := next OF end result
                 FI ; # add #
            IF num OF r > den OF r THEN
                add( RATIONAL( num OF r OVER den OF r, 1 ) );
                r := ( num OF r MOD den OF r, den OF r )
            FI;
            PROC mod func = ( LONG LONG INT m, n )LONG LONG INT: ( ( m MOD n ) + n ) MOD n;
            WHILE num OF r /= 0 DO
                LONG LONG INT q = CEIL( den OF r / num OF r );
                add( RATIONAL( 1, q ) );
                r := RATIONAL( mod func( - ( den OF r ), num OF r ), ( den OF r ) * q )
            OD;
            result
         FI ; # EGYPTIAN #
    BEGIN # task test cases #
        []RATIONAL test cases = ( RATIONAL( 43, 48 ), RATIONAL( 5, 121 ), RATIONAL( 2014, 59 ) );
        FOR r pos FROM LWB test cases TO UPB test cases DO
            print( ( TOSTRING test cases[ r pos ], " -> ", TOSTRING EGYPTIAN test cases[ r pos ], newline ) )
        OD;
        # find the fractions with the most terms and the largest denominator #
        print( ( "For rationals with numerator and denominator in 1..99:", newline ) );
        RATIONAL           largest denominator  := ( 0, 1 );
        REF LISTOFRATIONAL max denominator list := nil list of rational;
        LONG LONG INT      max denominator      := 0;
        RATIONAL           most terms           := ( 0, 1 );
        REF LISTOFRATIONAL most terms list      := nil list of rational;
        INT                max terms            := 0;
        FOR num TO 99 DO
            FOR den TO 99 DO
                RATIONAL           r  = RATIONAL( num, den );
                REF LISTOFRATIONAL e := EGYPTIAN r;
                REF LISTOFRATIONAL p := e;
                INT terms := 0;
                WHILE p ISNT nil list of rational DO
                   terms +:= 1;
                   IF den OF element OF p > max denominator THEN
                       largest denominator  := r;
                       max denominator      := den OF element OF p;
                       max denominator list := e
                   FI;
                   p := next OF p
                OD;
                IF terms > max terms THEN
                    most terms      := r;
                    max terms       := terms;
                    most terms list := e
                FI
            OD
        OD;
        print( ( "    ", TOSTRING most terms, " has the most terms: ", TOSTRING max terms, newline
               , "    ", TOSTRING most terms list, newline
               )
             );
        print( ( "    ", TOSTRING largest denominator, " has the largest denominator:", newline
               , "    ", TOSTRING max denominator list, newline
               )
             )
    END
END


import java.util.HashMap;
import java.util.Map;

public class PrimeGaps {
    private Map<Integer, Integer> gapStarts = new HashMap<>();
    private int lastPrime;
    private PrimeGenerator primeGenerator = new PrimeGenerator(1000, 500000);

    public static void main(String[] args) {
        final int limit = 100000000;
        PrimeGaps pg = new PrimeGaps();
        for (int pm = 10, gap1 = 2;;) {
            int start1 = pg.findGapStart(gap1);
            int gap2 = gap1 + 2;
            int start2 = pg.findGapStart(gap2);
            int diff = start2 > start1 ? start2 - start1 : start1 - start2;
            if (diff > pm) {
                System.out.printf(
                    "Earliest difference > %,d between adjacent prime gap starting primes:\n"
                    + "Gap %,d starts at %,d, gap %,d starts at %,d, difference is %,d.\n\n",
                    pm, gap1, start1, gap2, start2, diff);
                if (pm == limit)
                    break;
                pm *= 10;
            } else {
                gap1 = gap2;
            }
        }
    }

    private int findGapStart(int gap) {
        Integer start = gapStarts.get(gap);
        if (start != null)
            return start;
        for (;;) {
            int prev = lastPrime;
            lastPrime = primeGenerator.nextPrime();
            int diff = lastPrime - prev;
            gapStarts.putIfAbsent(diff, prev);
            if (diff == gap)
                return prev;
        }
    }
}


using Formatting
using Primes

function primegaps(limit = 10^9)
    c(n) = format(n, commas=true)
    pri = primes(limit * 5)
    gapstarts = Dict{Int, Int}()
    for i in 2:length(pri)
        get!(gapstarts, pri[i] - pri[i - 1], pri[i - 1])
    end
    pm, gap1 = 10, 2
    while true
        while !haskey(gapstarts, gap1)
            gap1 += 2
        end
        start1 = gapstarts[gap1]
        gap2 = gap1 + 2
        if !haskey(gapstarts, gap2)
            gap1 = gap2 + 2
            continue
        end
        start2 = gapstarts[gap2]
        if ((diff = abs(start2 - start1)) > pm)
            println("Earliest difference > $(c(pm)) between adjacent prime gap starting primes:")
            println("Gap $gap1 starts at $(c(start1)), gap $(c(gap2)) starts at $(c(start2)), difference is $(c(diff)).\n")
            pm == limit && break
            pm *= 10
        else
            gap1 = gap2
        end
    end
end

primegaps()


program primesieve;
// sieving small ranges of 65536
//{$O+,R+}
{$IFDEF FPC}
  {$MODE DELPHI}{$OPTIMIZATION ON,ALL}{$CODEALIGN proc=32}
  uses
    sysutils;
{$ENDIF}
{$IFDEF WINDOWS}
  {$APPTYPE CONSOLE}
{$ENDIF}

const
  smlPrimes :array [0..10] of Byte = (2,3,5,7,11,13,17,19,23,29,31);
  maxPreSievePrime = 17;
  sieveSize = 1 shl 15;//32768*2 ->max count of FoundPrimes = 6542
type
  tSievePrim = record
                 svdeltaPrime:word;//diff between actual and new prime
                 svSivOfs:word;//-> sieveSize< 1 shl 16
                 svSivNum:LongWord;// 1 shl (16+32) = 2.8e14
               end;
var
{$Align 16}
  //primes up to 1E6-> sieving to 1E12
  sievePrimes : array[0..78497] of tSievePrim;
{$Align 16}
  preSieve :array[0..3*5*7*11*13*17-1] of Byte;
{$Align 16}
  Sieve :array[0..sieveSize-1] of Byte;
{$Align 16}
  FoundPrimes : array[0..6542] of LongWord;
{$Align 16}
  Gaps  : array[0..255] Of Uint64;
{$Align 16}
  Limit,OffSet : Uint64;

  SieveMaxIdx,
  preSieveOffset,
  SieveNum,
  FoundPrimesCnt,
  PrimPos,
  LastInsertedSievePrime :NativeUInt;

procedure CopyPreSieveInSieve;forward;
procedure CollectPrimes;forward;
procedure sieveOneSieve;forward;

procedure preSieveInit;
var
  i,pr,j,umf : NativeInt;
Begin
  fillchar(preSieve[0],SizeOf(preSieve),#1);
  i := 1;// starts with pr = 3
  umf := 1;
  repeat
    IF preSieve[i] <> 0 then
    Begin
      pr := 2*i+1;
      j := i;
      repeat
        preSieve[j] := 0;
        inc(j,pr);
      until j> High(preSieve);
      umf := umf*pr;
    end;
    inc(i);
  until umf>High(preSieve);
  preSieveOffset := 0;
end;

procedure CalcSievePrimOfs(lmt:NativeUint);
var
  i,pr : NativeUInt;
  sq : Uint64;
begin
  pr := 0;
  i := 0;
  repeat
    with sievePrimes[i] do
    Begin
      pr := pr+svdeltaPrime;
      IF sqr(pr)  < (SieveSize*2) then
      Begin
        svSivNum := 0;
        svSivOfs := (pr*pr-1) DIV 2;
      end
      else
      Begin
        SieveMaxIdx := i;
        pr := pr-svdeltaPrime;
        BREAK;
      end;
    end;
    inc(i);
  until i > lmt;

  for i := i to lmt do
  begin
    with sievePrimes[i] do
    Begin
      pr := pr+svdeltaPrime;
      sq := sqr(pr);
      svSivNum := sq DIV (2*SieveSize);
      svSivOfs := ( (sq - Uint64(svSivNum)*(2*SieveSize))-1)DIV 2;
    end;
  end;
end;

procedure InitSieve;
begin
  preSieveOffset := 0;
  SieveNum :=0;
  CalcSievePrimOfs(PrimPos-1);
end;

procedure InsertSievePrimes;
var
  j    :NativeUINt;
  i,pr : NativeUInt;
begin
  i := 0;
  //ignore first primes already sieved with
  if SieveNum = 0 then
    repeat
      inc(i);
    until FoundPrimes[i] > maxPreSievePrime;

  pr :=0;
  j := Uint64(SieveNum)*SieveSize*2-LastInsertedSievePrime;
  with sievePrimes[PrimPos] do
  Begin
    pr := FoundPrimes[i];
    svdeltaPrime := pr+j;
    j := pr;
    end;
  inc(PrimPos);
  for i := i+1 to FoundPrimesCnt-1 do
  Begin
    IF PrimPos > High(sievePrimes) then
      BREAK;
    with sievePrimes[PrimPos] do
    Begin
      pr := FoundPrimes[i];
      svdeltaPrime := (pr-j);
      j := pr;
    end;
    inc(PrimPos);
  end;
  LastInsertedSievePrime :=Uint64(SieveNum)*(SieveSize*2)+pr;
end;

procedure sievePrimesInit;
var
  i,j,pr:NativeInt;
Begin
  LastInsertedSievePrime := 0;

  PrimPos := 0;
  preSieveOffset := 0;
  SieveNum :=0;
  CopyPreSieveInSieve;
  i := 1; // start with 3
  repeat
    while Sieve[i] = 0 do
      inc(i);
    pr := 2*i+1;
    inc(i);
    j := ((pr*pr)-1) DIV 2;
    if j > High(Sieve) then
      BREAK;
    repeat
      Sieve[j] := 0;
      inc(j,pr);
    until j > High(Sieve);
  until false;

  CollectPrimes;
  InsertSievePrimes;
  IF PrimPos < High(sievePrimes) then
  Begin
    InitSieve;
    //Erste Sieb nochmals, aber ohne Eintrag
    CopyPreSieveInSieve;
    sieveOneSieve;
    repeat
      inc(SieveNum);
      CopyPreSieveInSieve;
      sieveOneSieve;
      CollectPrimes;
      InsertSievePrimes;
   until PrimPos > High(sievePrimes);
  end;
end;

procedure OutGaps(g1,g2,delta:NativeUint);
begin
  if g2= 0  then
    writeln(2*g1:4,2*g1+2:4,delta:13,Gaps[g1]:13,Gaps[g1+1]:13)
  else
   writeln(2*g2-1:4,2*g1:4,delta:13,Gaps[g1-1]:13,Gaps[g1]:13);
end;
function GetDiffval(val1,val2: NativeInt): NativeInt;
begin
  if val1*val2 = 0 then
    EXIT(0);
  dec(val1,val2);
  if val1<0 then
    val1 :=-val1;
  GetDiffval := val1;
end;

procedure CheckGaps;
var
  val1,val2,val3,i,DekaLimit : NativeInt;
Begin
  writeln('Gap1 Gap2   difference       first       second  prime');
  dekaLimit := 10;
  i := 1;
  repeat
    val1 := Gaps[i];
    if val1 <> 0 then
    Begin
      val2 := GetDiffval(val1,Gaps[i-1]);
      val3 := GetDiffval(val1,Gaps[i+1]);
      while (val2>DekaLimit) or (val3>DekaLimit) do
      begin
        writeln(DekaLimit:21,'<');
        if val2 = 0 then
        begin
          if val3 > 0 then
            OutGaps(i,0,val3);
        end
        else
        begin
          if val3 = 0 then
            OutGaps(i,1,val2)
          else
          Begin
            if val3 > val2 then
              OutGaps(i,0,val3)
            else
              OutGaps(i,1,val2);
          end;
        end;
        DekaLimit := 10*DekaLimit;
      end;
    end;
    inc(i);
  until i>=254;
end;

procedure CopyPreSieveInSieve;
var
  lmt : NativeInt;
Begin
  lmt := preSieveOffset+sieveSize;
  lmt := lmt-(High(preSieve)+1);
  IF lmt<= 0 then
  begin
    Move(preSieve[preSieveOffset],Sieve[0],sieveSize);
    if lmt <> 0 then
      inc(preSieveOffset,sieveSize)
    else
      preSieveOffset := 0;
  end
  else
  begin
    Move(preSieve[preSieveOffset],Sieve[0],sieveSize-lmt);
    Move(preSieve[0],Sieve[sieveSize-lmt],lmt);
    preSieveOffset := lmt
  end;
end;

procedure CollectPrimes;
var
   pSieve : pbyte;
   pFound : pLongWord;
   i,idx : NativeInt;
Begin
  pFound := @FoundPrimes[0];
  idx := 0;
  i := 0;
  IF SieveNum = 0 then
  Begin
    repeat
      pFound[idx] := smlPrimes[idx];
      inc(idx);
    until smlPrimes[idx]>maxPreSievePrime;
    i := (smlPrimes[idx] -1) DIV 2;
  end;

  pSieve := @Sieve[0];
  repeat
    pFound[idx]:= 2*i+1;
    inc(idx,pSieve[i]);
    inc(i);
  until i>High(Sieve);
  FoundPrimesCnt:= idx;
end;

procedure sieveOneSieve;
var
  i,j,pr,dSievNum :NativeUint;
Begin
  pr := 0;
  For i := 0 to SieveMaxIdx do
    with sievePrimes[i] do
    begin
      pr := pr+svdeltaPrime;
      IF svSivNum = sieveNum then
      Begin
        j := svSivOfs;
        repeat
          Sieve[j] := 0;
          inc(j,pr);
        until j > High(Sieve);

        dSievNum := j DIV SieveSize;
        svSivOfs := j-dSievNum*SieveSize;
        inc(svSivNum,dSievNum);
      end;
    end;

  i := SieveMaxIdx+1;
  repeat
    if i > High(SievePrimes) then
      BREAK;
    with sievePrimes[i] do
    begin
      if svSivNum > sieveNum then
      Begin
        SieveMaxIdx := I-1;
        Break;
      end;
      pr := pr+svdeltaPrime;
      j := svSivOfs;
      repeat
        Sieve[j] := 0;
        inc(j,pr);
      until j > High(Sieve);
      dSievNum := j DIV SieveSize;
      svSivOfs := j-dSievNum*SieveSize;
      inc(svSivNum,dSievNum);
      inc(i);
    end;
  until false;
end;

var
  T1,T0,CNT,ActPrime,LastPrime,delta : Int64;
  i: Int32;

begin
  T0 := GetTickCount64;
  Limit := 10*1000*1000*1000;//158*1000*1000*1000;
  preSieveInit;
  sievePrimesInit;

  InitSieve;
  offset := 0;
  Cnt := 1;//==2
  LastPrime := 2;

  repeat
    CopyPreSieveInSieve;sieveOneSieve;CollectPrimes;
    inc(Cnt,FoundPrimesCnt);
    //collect first occurrence of gap
    i := 0;
    repeat
      ActPrime := Offset+FoundPrimes[i];
      delta := (ActPrime - LastPrime) shr 1;
      If Gaps[delta] = 0 then
        Gaps[delta] := LastPrime;
      LastPrime := ActPrime;
      inc(i);
    until (i >= FoundPrimesCnt);

    inc(SieveNum);
    inc(offset,2*SieveSize);
  until SieveNum > (Limit DIV (2*SieveSize));
  CheckGaps;
  T1 := GetTickCount64;
  OffSet := Uint64(SieveNum-1)*(2*SieveSize);

  i := FoundPrimesCnt;
  repeat
    dec(i);
    dec(cnt);
  until (i = 0) OR (OffSet+FoundPrimes[i]<Limit);
  writeln;
  writeln(cnt,' in ',Limit,' takes ',T1-T0,' ms');
  {$IFDEF WINDOWS}
  writeln('Press <Enter>');readln;
  {$ENDIF}
end.


#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

typedef int64_t integer;

struct Pair {
    integer md;
    int tc;
};

integer mod(integer x, integer y) {
    return ((x % y) + y) % y;
}

integer gcd(integer a, integer b) {
    if (0 == a) return b;
    if (0 == b) return a;
    if (a == b) return a;
    if (a > b) return gcd(a - b, b);
    return gcd(a, b - a);
}

void write0(bool show, char *str) {
    if (show) {
        printf(str);
    }
}

void write1(bool show, char *format, integer a) {
    if (show) {
        printf(format, a);
    }
}

void write2(bool show, char *format, integer a, integer b) {
    if (show) {
        printf(format, a, b);
    }
}

struct Pair egyptian(integer x, integer y, bool show) {
    struct Pair ret;
    integer acc = 0;
    bool first = true;

    ret.tc = 0;
    ret.md = 0;

    write2(show, "Egyptian fraction for %lld/%lld: ", x, y);
    while (x > 0) {
        integer z = (y + x - 1) / x;
        if (z == 1) {
            acc++;
        } else {
            if (acc > 0) {
                write1(show, "%lld + ", acc);
                first = false;
                acc = 0;
                ret.tc++;
            } else if (first) {
                first = false;
            } else {
                write0(show, " + ");
            }
            if (z > ret.md) {
                ret.md = z;
            }
            write1(show, "1/%lld", z);
            ret.tc++;
        }
        x = mod(-y, x);
        y = y * z;
    }
    if (acc > 0) {
        write1(show, "%lld", acc);
        ret.tc++;
    }
    write0(show, "\n");

    return ret;
}

int main() {
    struct Pair p;
    integer nm = 0, dm = 0, dmn = 0, dmd = 0, den = 0;;
    int tm, i, j;

    egyptian(43, 48, true);
    egyptian(5, 121, true); // final term cannot be represented correctly
    egyptian(2014, 59, true);

    tm = 0;
    for (i = 1; i < 100; i++) {
        for (j = 1; j < 100; j++) {
            p = egyptian(i, j, false);
            if (p.tc > tm) {
                tm = p.tc;
                nm = i;
                dm = j;
            }
            if (p.md > den) {
                den = p.md;
                dmn = i;
                dmd = j;
            }
        }
    }
    printf("Term max is %lld/%lld with %d terms.\n", nm, dm, tm); // term max is correct
    printf("Denominator max is %lld/%lld\n", dmn, dmd);           // denominator max is not correct
    egyptian(dmn, dmd, true);                                     // enough digits cannot be represented without bigint

    return 0;
}


#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Earliest_difference_between_prime_gaps
use warnings;
use ntheory qw( primes );

my @gaps;
my $primeref = primes( 1e9 );
for my $i ( 2 .. $#$primeref )
  {
  my $diff = $primeref->[$i] - $primeref->[$i - 1];
  $gaps[ $diff >> 1 ] //= $primeref->[$i - 1];
  }
my %first;
for my $i ( 1 .. $#gaps )
  {
  defined $gaps[$i] && defined $gaps[$i-1] or next;
  my $diff = abs $gaps[$i] - $gaps[$i-1];
  for my $m ( map 10 ** $_, 1 .. 10 )
    {
    $diff > $m and !$first{$m}++ and
      print "above $m gap @{[$i * 2 - 2 ]} abs( $gaps[$i-1] - $gaps[$i] )\n";
    }
  }


with javascript_semantics
constant limit = iff(platform()=JS?1e7:1e8),
         gslim = 250
sequence primes = get_primes_le(limit*4),
         gapstarts = repeat(0,gslim)
for i=2 to length(primes) do
    integer gap = primes[i]-primes[i-1]
    if gapstarts[gap]=0 then
        gapstarts[gap] = primes[i-1]
    end if
end for

integer pm = 10, gap1 = 2
while true do
    while gapstarts[gap1]=0 do gap1 += 2 end while
    integer start1 = gapstarts[gap1],
            gap2 = gap1 + 2
    if gapstarts[gap2]=0 then
        gap1 = gap2 + 2
    else
        integer start2 = gapstarts[gap2],
                diff = abs(start2 - start1)
        if diff>pm then
            printf(1,"Earliest difference >%,d between adjacent prime gap starting primes:\n",{pm})
            printf(1,"Gap %d starts at %,d, gap %d starts at %,d, difference is %,d.\n\n",
                         {gap1,        start1,  gap2,        start2,            diff})
            if pm=limit then exit end if
            pm *= 10
        else
            gap1 = gap2
        end if
    end if
end while