V Small = [‘zero’, ‘one’, ‘two’, ‘three’, ‘four’,
           ‘five’, ‘six’, ‘seven’, ‘eight’, ‘nine’,
           ‘ten’, ‘eleven’, ‘twelve’, ‘thirteen’, ‘fourteen’,
           ‘fifteen’, ‘sixteen’, ‘seventeen’, ‘eighteen’, ‘nineteen’]

V Tens = [‘’, ‘’, ‘twenty’, ‘thirty’, ‘forty’, ‘fifty’, ‘sixty’, ‘seventy’, ‘eighty’, ‘ninety’]

V Illions = [‘’, ‘ thousand’, ‘ million’, ‘ billion’, ‘ trillion’, ‘ quadrillion’, ‘ quintillion’]

F say(Int64 =n) -> String
   V result = ‘’
   I n < 0
      result = ‘negative ’
      n = -n

   I n < 20
      result ‘’= Small[Int(n)]

   E I n < 100
      result ‘’= Tens[Int(n I/ 10)]
      V m = n % 10
      I m != 0
         result ‘’= ‘-’Small[Int(m)]

   E I n < 1000
      result ‘’= Small[Int(n I/ 100)]‘ hundred’
      V m = n % 100
      I m != 0
         result ‘’= ‘ ’say(m)

   E
      V sx = ‘’
      V i = 0
      L n > 0
         V m = n % 1000
         n I/= 1000
         I m != 0
            V ix = say(m)‘’Illions[i]
            I sx.len > 0
               ix ‘’= ‘ ’sx
            sx = ix
         i++
      result ‘’= sx

   R result

F fourIsMagic(=n)
   V s = say(n).capitalize()
   V result = s
   L n != 4
      n = s.len
      s = say(n)
      result ‘’= ‘ is ’s‘, ’s
   R result‘ is magic.’

L(n) [Int64(0), 4, 6, 11, 13, 75, 100, 337, -164, 7FFF'FFFF'FFFF'FFFF]
   print(fourIsMagic(n))


-- forwardDifference :: Num a => [a] -> [a]
on forwardDifference(xs)
    zipWith(my subtract, xs, rest of xs)
end forwardDifference

-- nthForwardDifference :: Num a => Int -> [a] -> [a]
on nthForwardDifference(xs, i)
    |index|(iterate(forwardDifference, xs), 1 + i)
end nthForwardDifference

-------------------------- TEST ---------------------------
on run
    script show
        on |λ|(xs, i)
            ((i - 1) as string) & " -> " & showList(xs)
        end |λ|
    end script

    unlines(map(show, ¬
        take(10, ¬
            iterate(forwardDifference, ¬
                {90, 47, 58, 29, 22, 32, 55, 5, 55, 73}))))
end run

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

-- Just :: a -> Maybe a
on Just(x)
    -- Constructor for an inhabited Maybe (option type) value.
    -- Wrapper containing the result of a computation.
    {type:"Maybe", Nothing:false, Just:x}
end Just

-- Nothing :: Maybe a
on Nothing()
    -- Constructor for an empty Maybe (option type) value.
    -- Empty wrapper returned where a computation is not possible.
    {type:"Maybe", Nothing:true}
end Nothing

-- index (!!) :: [a] -> Int -> Maybe a
-- index (!!) :: Gen [a] -> Int -> Maybe a
-- index (!!) :: String -> Int -> Maybe Char
on |index|(xs, i)
    if script is class of xs then
        repeat with j from 1 to i
            set v to |λ|() of xs
        end repeat
        if missing value is not v then
            Just(v)
        else
            Nothing()
        end if
    else
        if length of xs < i then
            Nothing()
        else
            Just(item i of xs)
        end if
    end if
end |index|

-- intercalate :: String -> [String] -> String
on intercalate(delim, xs)
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, delim}
    set str to xs as text
    set my text item delimiters to dlm
    str
end intercalate

-- iterate :: (a -> a) -> a -> Gen [a]
on iterate(f, x)
    script
        property v : missing value
        property g : mReturn(f)'s |λ|
        on |λ|()
            if missing value is v then
                set v to x
            else
                set v to g(v)
            end if
            return v
        end |λ|
    end script
end iterate

-- length :: [a] -> Int
on |length|(xs)
    set c to class of xs
    if list is c or string is c then
        length of xs
    else
        (2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)
    end if
end |length|

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    -- The list obtained by applying f
    -- to each element of xs.
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

-- min :: Ord a => a -> a -> a
on min(x, y)
    if y < x then
        y
    else
        x
    end if
end min

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

-- showList :: [a] -> String
on showList(xs)
    "[" & intercalate(", ", map(my str, xs)) & "]"
end showList

-- str :: a -> String
on str(x)
    x as string
end str

-- subtract :: Num -> Num -> Num
on subtract(x, y)
    y - x
end subtract

-- take :: Int -> [a] -> [a]
-- take :: Int -> String -> String
on take(n, xs)
    set c to class of xs
    if list is c then
        if 0 < n then
            items 1 thru min(n, length of xs) of xs
        else
            {}
        end if
    else if string is c then
        if 0 < n then
            text 1 thru min(n, length of xs) of xs
        else
            ""
        end if
    else if script is c then
        set ys to {}
        repeat with i from 1 to n
            set v to |λ|() of xs
            if missing value is v then
                return ys
            else
                set end of ys to v
            end if
        end repeat
        return ys
    else
        missing value
    end if
end take

-- unlines :: [String] -> String
on unlines(xs)
    -- A single string formed by the intercalation
    -- of a list of strings with the newline character.
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, linefeed}
    set s to xs as text
    set my text item delimiters to dlm
    s
end unlines

-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
    set lng to min(|length|(xs), |length|(ys))
    if 1 > lng then return {}
    set xs_ to take(lng, xs) -- Allow for non-finite
    set ys_ to take(lng, ys) -- generators like cycle etc
    set lst to {}
    tell mReturn(f)
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs_, item i of ys_)
        end repeat
        return lst
    end tell
end zipWith


puts:		equ	9h	; MS-DOS syscall to print a string
		cpu	8086
		bits	16
		org	100h
section		.text
		;;;	Read number from the MS-DOS command line
		;;;	The task says numbers up to 999999 need to be
		;;;	supported, so we can't get away with using MUL.
		mov	cl,[80h]	; Is there an argument?
		test	cl,cl
		jnz	havearg
		mov	ah,puts		; If not, print "no input"
		mov	dx,errinput
		int	21h
		ret			; And stop.
havearg:	mov	si,82h		; Start of argument string
		xor	ch,ch		; CX = argument length
		dec	cx		; Minus one (space before argument)
		xor	ax,ax		; Accumulator starts out at 0
		xor	dx,dx
numloop:	mov	bp,ax		; DX:AX *= 10
		mov	di,dx
		add	ax,ax		; ... *2
		adc	dx,dx
		add	ax,ax		; ... *4
		adc	dx,dx
		add	ax,bp		; ... *5
		adc	dx,di
		add	ax,ax		; ... *10
		adc	dx,dx
		mov	bx,ax
		lodsb			; Get digit
		sub	al,'0'
		xor	ah,ah
		add	ax,bx		; Add digit
		adc	dx,0
		loop	numloop		; Next digit if there is one
		;;;	DX:AX now contains the binary representation of
		;;;	the decimal input.
		cmp	dx,0Fh		; Check that DX:AX <= 999999
		jb	donum
		cmp	ax,4240h	; 0F4240h = 1000000
		jb	donum
		mov	ah,puts		; Otherwise, print error message
		mov	dx,errhigh
		int	21h
		ret
		;;;	DX:AX = current number
donum:		push	dx		; Keep number
		push	ax
		mov	di,numstring	; Create the string for the number
		call	cardinal
		mov	[di],byte '$'
		xor	[numstring],byte 32	; Capitalize first letter
.print:		mov	dx,numstring	; Print the string
		mov	ah,puts
		int	21h
		mov	dx,is		; print ' is ',
		int	21h
		pop	ax		; Retrieve number
		pop	dx
		test	dx,dx		; DX:AX = 4 = magic
		jnz	.nomagic	; DX <> 0 = not magic
		cmp	ax,4		; If AX=4 then magic
		je	.magic
.nomagic:	sub	di,numstring	; Calculate length of string
		xor	dx,dx		; Set DX:AX to DI
		mov	ax,di
		push	dx		; Store new number on stack
		push	ax
		mov	di,numstring	; Make string for new number
		call	cardinal
		mov	[di],byte '$'
		mov	dx,numstring	; Print the string
		mov	ah,puts
		int	21h
		mov	dx,commaspace	; Print comma and space
		int	21h
		jmp 	.print		; Then use next number as input
.magic:		mov	dx,magic 	; print "magic.",
		mov	ah,puts
		int	21h
		ret			; and stop
		;;;	Subroutine: assuming 0 <= DX:AX <= 999999, write
		;;;	cardinal representation at ES:DI.
cardinal:	mov	bp,ax
		or	bp,dx
		jz	.zero		; If it is zero, return 'Zero'
		mov	bp,1000		; Otherwise, get 1000s part
		div	bp
		test	ax,ax		; Above 1000?
		jz	.hundreds_dx	; If not, just find hundreds
		push	dx		; Otherwise, save <1000s part,
		call	.hundreds	; get string for how many thousands,
		mov	si,thousand	; Then add ' thousand',
		call	stradd
		pop	dx		; Restore <1000 part,
		test	dx,dx		; Even thousands?
		jnz	.hundreds_spc	; Then add hundreds
		ret			; Otherwise we're done
.hundreds_spc:	mov	al,' '		; Add space betweeen thousand and rest
		stosb
.hundreds_dx:	mov	ax,dx
.hundreds:	mov	bp,100		; Get hundreds part
		xor	dx,dx
		div	bp		; AX=100s
		test	ax,ax		; If zero, no hundreds
		jz	.tens_dx
		dec	ax		; Otherwise, look up in singles
		shl	ax,1		; table,
		mov	bx,ax
		mov	si,[single+bx]
		call	stradd		; Add to the output string,
		mov	si,hundred	; Add ' hundred',
		call	stradd
		test	dx,dx		; Is there any more?
		jne	.tens_spc	; If so, add tens
		ret			; Otherwise we're done
.tens_spc:	mov	al,' '		; Add space between 'hundred' and tens
		stosb
.tens_dx:	mov	ax,dx		; Tens in AX (from hundreds)
.tens:		aam			; AH=10s digit, AL=1s digit
		test	ah,ah		; If 10s digit is 0, single digit
		jz	.ones
		cmp	ah,1		; If 10s digit is 1, teens
		jz	.teens
		mov	bl,ah		; Look up tens digit in tens table
		sub	bl,2
		shl	bl,1
		xor	bh,bh
		mov	si,[tens+bx]	; Add to the output string
		call	stradd
		test	al,al		; Ones digit left?
		jne	.ones_dash	; If so, add dash and ones digit
		ret			; Otherwise we're done
.ones_dash:	mov	[di],byte '-'
		inc	di
.ones:		mov	bl,al		; Look up ones digit in ones table
		dec	bl
		shl	bl,1
		xor	bh,bh
		mov	si,[single+bx]
		jmp	stradd
.teens:		mov	bl,al		; Look up ones digit in teens table
		shl	bl,1
		xor	bh,bh
		mov	si,[teens+bx]
		jmp	stradd
.zero:		mov	si,zero
		;;;	Copy $-terminated string at DS:SI to ES:DI, except
		;;;	the terminator.
stradd:		push	ax		; Keep AX register
.loop:		lodsb			; Get byte from DS:SI
		cmp 	al,'$'		; Are we there yet?
		je	.out		; If so, stop
		stosb			; Otherwise, store at ES:DI
		jmp	.loop
.out:		pop	ax
		ret
section		.data
single:		dw	one,two,three,four
		dw	five,six,seven,eight,nine
teens:		dw	ten,eleven,twelve,thirteen,fourteen
		dw	fifteen,sixteen,seventeen,eighteen,nineteen
tens:		dw	twenty,thirty,forty,fifty
		dw	sixty,seventy,eighty,ninety
zero:		db	'zero$'
one:		db	'one$'
two:		db	'two$'
three:		db	'three$'
four:		db	'four$'
five:		db	'five$'
six:		db	'six$'
seven:		db	'seven$'
eight:		db	'eight$'
nine:		db	'nine$'
ten:		db	'ten$'
eleven:		db	'eleven$'
twelve:		db	'twelve$'
thirteen:	db	'thirteen$'
fourteen:	db	'fourteen$'
fifteen:	db	'fifteen$'
sixteen:	db	'sixteen$'
seventeen:	db	'seventeen$'
eighteen:	db	'eighteen$'
nineteen:	db	'nineteen$'
twenty:		db	'twenty$'
thirty:		db	'thirty$'
forty:		db	'forty$'
fifty:		db	'fifty$'
sixty:		db	'sixty$'
seventy:	db	'seventy$'
eighty:		db	'eighty$'
ninety:		db	'ninety$'
hundred:	db	' hundred$'
thousand:	db	' thousand$'
is:		db	' is $'
magic:		db	'magic.$'
commaspace:	db	', $'
errinput:	db	'No input$'
errhigh:	db	'Max input 999999$'
section		.bss
numstring:	resb	1024


; element-wise subtraction of two blocks. e.g.
; vsub [1 2 3] [1 2 3] ; [0 0 0]
vsub: function [u v][
    map couple u v 'pair -> pair\0 - pair\1
]

differences: function [block][
    order: attr "order"
    if order = null -> order: 1
    loop 1..order 'n -> block: vsub block drop block 1
    return block
]

print differences .order: 4 [90.5 47 58 29 22 32 55 5 55 73.5]
print differences [1 2 3 4 5 6 7]


MsgBox % diff("2,3,4,3",1)
MsgBox % diff("2,3,4,3",2)
MsgBox % diff("2,3,4,3",3)
MsgBox % diff("2,3,4,3",4)

diff(list,ord) { ; high order forward differences of a list
   Loop %ord% {
      L =
      Loop Parse, list, `, %A_Space%%A_Tab%
         If (A_Index=1)
            p := A_LoopField
         Else
            L .= "," A_LoopField-p, p := A_LoopField
      list := SubStr(L,2)
   }
   Return list
}


magic←{
    t20←'one' 'two' 'three' 'four' 'five' 'six' 'seven' 'eight' 'nine'
    t20←t20,'ten' 'eleven' 'twelve' 'thirteen' 'fourteen' 'fifteen' 'sixteen'
    t20←t20,'seventeen' 'eighteen' 'nineteen'
    tens←'twenty' 'thirty' 'forty' 'fifty' 'sixty' 'seventy' 'eighty' 'ninety'
    spell←{
        ⍵=0:'zero'
        {
            ⍵=0:''
            ⍵<20:⍵⊃t20
            ⍵<100:∊tens[(⌊⍵÷10)-1],((0≠≢r)/'-'),r←∇10|⍵
            ⍵<1000:(∇⌊⍵÷100),' hundred',((0≠≢r)/' '),r←∇100|⍵
            ⍵<1e6:(∇⌊⍵÷1000),' thousand',((0≠≢r)/' '),r←∇1000|⍵
            ⍵<1e9:(∇⌊⍵÷1e6),' million',((0≠≢r)/' '),r←∇1e6|⍵
            ⍵<1e12:(∇⌊⍵÷1e9),' billion',((0≠≢r)/' '),r←∇1e9|⍵
            ⍵<1e15:(∇⌊⍵÷1e12),' trillion',((0≠≢r)/' '),r←∇1e12|⍵
            ⍵<1e18:(∇⌊⍵÷1e15),' quadrillion',((0≠≢r)/' '),r←∇1e15|⍵
            ⍵<1e21:(∇⌊⍵÷1e18),' quintillion',((0≠≢r)/' '),r←∇1e18|⍵
            'Overflow' ⎕SIGNAL 11
        }⍵
    }
    1(819⌶)@1⊢{
        n←spell ⍵
        ⍵=4:n,' is magic.'
        n,' is ',(spell ≢n),', ',∇≢n
    }⍵
}


(* Uses a Foundation number formatter for brevity. *)
use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"

on getNumberFormatter(localeID, numberStyle)
    set formatter to current application's class "NSNumberFormatter"'s new()
    tell formatter to setLocale:(current application's class "NSLocale"'s localeWithLocaleIdentifier:(localeID))
    tell formatter to setNumberStyle:(numberStyle)

    return formatter
end getNumberFormatter

on join(listOfText, delimiter)
    set astid to AppleScript's text item delimiters
    set AppleScript's text item delimiters to delimiter
    set txt to listOfText as text
    set AppleScript's text item delimiters to astid

    return txt
end join

on fourIsMagic(n)
    set n to n as number
    if (n is 4) then return "Four is magic."

    set formatter to getNumberFormatter("en_US", current application's NSNumberFormatterSpellOutStyle)

    set nName to (formatter's stringFromNumber:(n)) as text
    if (nName begins with "minus") then
        set nName to "Negative " & text from word 2 to -1 of nName
    else -- Crude ID-based capitalisation. Good enough for English number names.
        set nName to character id ((id of character 1 of nName) - 32) & text 2 thru -1 of nName
    end if

    set output to {}
    repeat until (n is 4)
        set n to (count nName)
        set lenName to (formatter's stringFromNumber:(n)) as text
        set end of output to nName & " is " & lenName
        set nName to lenName
    end repeat
    set end of output to "four is magic."

    return join(output, ", ")
end fourIsMagic

local tests, output, n
set tests to {-19, 0, 4, 25, 32, 111, 1.234565789E+9}
set output to {}
repeat with n in tests
    set end of output to fourIsMagic(n)
end repeat
return join(output, linefeed)


      DIM A(9)
      A() = 90.0, 47.0, 58.0, 29.0, 22.0, 32.0, 55.0, 5.0, 55.0, 73.0
      PRINT "Original array: " FNshowarray(A())
      PROCforward_difference(1, A(), B())
      PRINT "Forward diff 1: " FNshowarray(B())
      PROCforward_difference(2, A(), C())
      PRINT "Forward diff 2: " FNshowarray(C())
      PROCforward_difference(9, A(), D())
      PRINT "Forward diff 9: " FNshowarray(D())
      END

      DEF PROCforward_difference(n%, a(), RETURN b())
      LOCAL c%, i%, j%
      DIM b(DIM(a(),1) - n%)
      FOR i% = 0 TO DIM(b(),1)
        b(i%) = a(i% + n%)
        c% = 1
        FOR j% = 1 TO n%
          c% = -INT(c% * (n% - j% + 1) / j% + 0.5)
          b(i%) += c% * a(i% + n% - j%)
        NEXT
      NEXT
      ENDPROC

      DEF FNshowarray(a())
      LOCAL i%, a$
      FOR i% = 0 TO DIM(a(),1)
        a$ += STR$(a(i%)) + ", "
      NEXT
      = LEFT$(LEFT$(a$))


FDiff ← {{-˜´˘2↕𝕩}⍟𝕨 𝕩}

•Show 1 FDiff 90‿47‿58‿29‿22‿32‿55‿5‿55‿73
•Show 2 FDiff 90‿47‿58‿29‿22‿32‿55‿5‿55‿73


Four_is_magic(num){
	nubmer := num
	while (num <> 4)
		result .= (res := spell(num)) " is " spell(num := StrLen(res)) ", "
	return PrettyNumber(nubmer) "  " result "four is magic!"
}
Spell(n) { ; recursive function to spell out the name of a max 36 digit integer, after leading 0s removed
	Static p1=" thousand ",p2=" million ",p3=" billion ",p4=" trillion ",p5=" quadrillion ",p6=" quintillion "
		 , p7=" sextillion ",p8=" septillion ",p9=" octillion ",p10=" nonillion ",p11=" decillion "
		 , t2="twenty",t3="thirty",t4="forty",t5="fifty",t6="sixty",t7="seventy",t8="eighty",t9="ninety"
		 , o0="zero",o1="one",o2="two",o3="three",o4="four",o5="five",o6="six",o7="seven",o8="eight"
		 , o9="nine",o10="ten",o11="eleven",o12="twelve",o13="thirteen",o14="fourteen",o15="fifteen"
		 , o16="sixteen",o17="seventeen",o18="eighteen",o19="nineteen"
	If (11 < d := (StrLen(n)-1)//3)		; #of digit groups of 3
		Return "Number too big"
	If (d)								; more than 3 digits
		Return Spell(SubStr(n,1,-3*d)) p%d% ((s:=SubStr(n,1-3*d)) ? ", " Spell(s) : "")
	i := SubStr(n,1,1)
	If (n > 99)							; 3 digits
		Return o%i% " hundred" ((s:=SubStr(n,2)) ? " " Spell(s) : "")
	If (n > 19)							; n = 20..99
		Return t%i% ((o:=SubStr(n,2)) ? "-" o%o% : "")
	Return o%n%							; n = 0..19
}
PrettyNumber(n) { ; inserts thousands separators into a number string
    Return RegExReplace(n, "\B(?=((\d{3})+$))", ",")
}


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

double* fwd_diff(double* x, unsigned int len, unsigned int order)
{
	unsigned int i, j;
	double* y;

	/* handle two special cases */
	if (order >= len) return 0;

	y = malloc(sizeof(double) * len);
	if (!order) {
		memcpy(y, x, sizeof(double) * len);
		return y;
	}

	/* first order diff goes from x->y, later ones go from y->y */
	for (j = 0; j < order; j++, x = y)
		for (i = 0, len--; i < len; i++)
			y[i] = x[i + 1] - x[i];

	y = realloc(y, sizeof(double) * len);
	return y;
}

int main(void)
{
	double *y, x[] = {90, 47, 58, 29, 22, 32, 55, 5, 55, 73};
	int i, len = sizeof(x) / sizeof(x[0]);

	y = fwd_diff(x, len, 1);
	for (i = 0; i < len - 1; i++)
		printf("%g ", y[i]);
	putchar('\n');

	return 0;
}


# syntax: GAWK -f FOUR_IS_MAGIC.AWK
BEGIN {
    init_numtowords()
    n = split("-1 0 1 2 3 4 5 6 7 8 9 11 21 1995 1000000 1234567890 1100100100100",arr," ")
    for (i=1; i<=n; i++) {
      a = arr[i]
      printf("%s: ",a)
      do {
        if (a == 4) {
          break
        }
        a = numtowords(a)
        b = numtowords(length(a))
        printf("%s is %s, ",a,b)
        a = length(a)
      } while (b !~ /^four$/)
      printf("four is magic.\n")
    }
    exit(0)
}
# source: The AWK Programming Language, page 75
function numtowords(n,  minus,str) {
    if (n < 0) {
      n = n * -1
      minus = "minus "
    }
    if (n == 0) {
      str = "zero"
    }
    else {
      str = intowords(n)
    }
    gsub(/  /," ",str)
    gsub(/ $/,"",str)
    return(minus str)
}
function intowords(n) {
    n = int(n)
    if (n >= 1000000000000) {
      return intowords(n/1000000000000) " trillion " intowords(n%1000000000000)
    }
    if (n >= 1000000000) {
      return intowords(n/1000000000) " billion " intowords(n%1000000000)
    }
    if (n >= 1000000) {
      return intowords(n/1000000) " million " intowords(n%1000000)
    }
    if (n >= 1000) {
      return intowords(n/1000) " thousand " intowords(n%1000)
    }
    if (n >= 100) {
      return intowords(n/100) " hundred " intowords(n%100)
    }
    if (n >= 20) {
      return tens[int(n/10)] " " intowords(n%10)
    }
    return(nums[n])
}
function init_numtowords() {
    split("one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen",nums," ")
    split("ten twenty thirty forty fifty sixty seventy eighty ninety",tens," ")
}


using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static IEnumerable<int> ForwardDifference(IEnumerable<int> sequence, uint order = 1u)
    {
        switch (order)
        {
            case 0u:
                return sequence;
            case 1u:
                return sequence.Skip(1).Zip(sequence, (next, current) => next - current);
            default:
                return ForwardDifference(ForwardDifference(sequence), order - 1u);
        }
    }

    static void Main()
    {
        IEnumerable<int> sequence = new[] { 90, 47, 58, 29, 22, 32, 55, 5, 55, 73 };
        do
        {
            Console.WriteLine(string.Join(", ", sequence));
        } while ((sequence = ForwardDifference(sequence)).Any());
    }
}


#include <vector>
#include <iterator>
#include <algorithm>

// calculate first order forward difference
// requires:
// * InputIterator is an input iterator
// * OutputIterator is an output iterator
// * The value type of InputIterator is copy-constructible and assignable
// * The value type of InputIterator supports operator -
// * The result type of operator- is assignable to the value_type of OutputIterator
// returns: The iterator following the output sequence
template<typename InputIterator, typename OutputIterator>
 OutputIterator forward_difference(InputIterator first, InputIterator last,
                                   OutputIterator dest)
{
  // special case: for empty sequence, do nothing
  if (first == last)
    return dest;

  typedef typename std::iterator_traits<InputIterator>::value_type value_type;

  value_type temp = *first++;
  while (first != last)
  {
    value_type temp2 = *first++;
    *dest++ = temp2 - temp;
    temp = temp2;
  }

  return dest;
}

// calculate n-th order forward difference.
// requires:
// * InputIterator is an input iterator
// * OutputIterator is an output iterator
// * The value type of InputIterator is copy-constructible and assignable
// * The value type of InputIterator supports operator -
// * The result type of operator- is assignable to the value_type of InputIterator
// * The result type of operator- is assignable to the value_type of OutputIterator
// * order >= 0
// returns: The iterator following the output sequence
template<typename InputIterator, typename OutputIterator>
 OutputIterator nth_forward_difference(int order,
                                       InputIterator first, InputIterator last,
                                       OutputIterator dest)
{
  // special case: If order == 0, just copy input to output
  if (order == 0)
    return std::copy(first, last, dest);

  // second special case: If order == 1, just forward to the first-order function
  if (order == 1)
    return forward_difference(first, last, dest);

  // intermediate results are stored in a vector
  typedef typename std::iterator_traits<InputIterator>::value_type value_type;
  std::vector<value_type> temp_storage;

  // fill the vector with the result of the first order forward difference
  forward_difference(first, last, std::back_inserter(temp_storage));

  // the next n-2 iterations work directly on the vector
  typename std::vector<value_type>::iterator begin = temp_storage.begin(),
                                             end = temp_storage.end();
  for (int i = 1; i < order-1; ++i)
    end = forward_difference(begin, end, begin);

  // the final iteration writes directly to the output iterator
  return forward_difference(begin, end, dest);
}

// example usage code
#include <iostream>

int main()
{
  double array[10] = { 90.0, 47.0, 58.0, 29.0, 22.0, 32.0, 55.0, 5.0, 55.0, 73.0 };

  // this stores the results in the vector dest
  std::vector<double> dest;
  nth_forward_difference(1, array, array+10, std::back_inserter(dest));

  // output dest
  std::copy(dest.begin(), dest.end(), std::ostream_iterator<double>(std::cout, " "));
  std::cout << std::endl;

  // however, the results can also be output as they are calculated
  nth_forward_difference(2, array, array+10, std::ostream_iterator<double>(std::cout, " "));
  std::cout << std::endl;

  nth_forward_difference(9, array, array+10, std::ostream_iterator<double>(std::cout, " "));
  std::cout << std::endl;

  nth_forward_difference(10, array, array+10, std::ostream_iterator<double>(std::cout, " "));
  std::cout << std::endl;

  nth_forward_difference(0, array, array+10, std::ostream_iterator<double>(std::cout, " "));
  std::cout << std::endl;

  // finally, the results can also be written into the original array
  // (which of course destroys the original content)
  double* end = nth_forward_difference(3, array, array+10, array);

  for (double* p = array; p < end; ++p)
    std::cout << *p << " ";
  std::cout << std::endl;

  return 0;
}


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

typedef struct named_number_tag {
    const char* name;
    uint64_t number;
} named_number;

const named_number named_numbers[] = {
    { "hundred", 100 },
    { "thousand", 1000 },
    { "million", 1000000 },
    { "billion", 1000000000 },
    { "trillion", 1000000000000 },
    { "quadrillion", 1000000000000000ULL },
    { "quintillion", 1000000000000000000ULL }
};

const named_number* get_named_number(uint64_t n) {
    const size_t names_len = sizeof(named_numbers)/sizeof(named_number);
    for (size_t i = 0; i + 1 < names_len; ++i) {
        if (n < named_numbers[i + 1].number)
            return &named_numbers[i];
    }
    return &named_numbers[names_len - 1];
}

size_t append_number_name(GString* str, uint64_t n) {
    static const char* small[] = {
        "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
        "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
        "sixteen", "seventeen", "eighteen", "nineteen"
    };
    static const char* tens[] = {
        "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"
    };
    size_t len = str->len;
    if (n < 20) {
        g_string_append(str, small[n]);
    }
    else if (n < 100) {
        g_string_append(str, tens[n/10 - 2]);
        if (n % 10 != 0) {
            g_string_append_c(str, '-');
            g_string_append(str, small[n % 10]);
        }
    } else {
        const named_number* num = get_named_number(n);
        uint64_t p = num->number;
        append_number_name(str, n/p);
        g_string_append_c(str, ' ');
        g_string_append(str, num->name);
        if (n % p != 0) {
            g_string_append_c(str, ' ');
            append_number_name(str, n % p);
        }
    }
    return str->len - len;
}

GString* magic(uint64_t n) {
    GString* str = g_string_new(NULL);
    for (unsigned int i = 0; ; ++i) {
        size_t count = append_number_name(str, n);
        if (i == 0)
            str->str[0] = g_ascii_toupper(str->str[0]);
        if (n == 4) {
            g_string_append(str, " is magic.");
            break;
        }
        g_string_append(str, " is ");
        append_number_name(str, count);
        g_string_append(str, ", ");
        n = count;
    }
    return str;
}

void test_magic(uint64_t n) {
    GString* str = magic(n);
    printf("%s\n", str->str);
    g_string_free(str, TRUE);
}

int main() {
    test_magic(5);
    test_magic(13);
    test_magic(78);
    test_magic(797);
    test_magic(2739);
    test_magic(4000);
    test_magic(7893);
    test_magic(93497412);
    test_magic(2673497412U);
    test_magic(10344658531277200972ULL);
    return 0;
}


(defn fwd-diff [nums order]
  (nth (iterate #(map - (next %) %) nums) order))


forward_difference = (arr, n) ->
  # Find the n-th order forward difference for arr using
  # a straightforward recursive algorithm.
  # Assume arr is integers and n <= arr.length.
  return arr if n == 0
  arr = forward_difference(arr, n-1)
  (arr[i+1] - arr[i] for i in [0...arr.length - 1])

arr = [-1, 0, 1, 8, 27, 64, 125, 216]
for n in [0..arr.length]
  console.log n, forward_difference arr, n


(defun forward-difference (list)
  (mapcar #'- (rest list) list))

(defun nth-forward-difference (list n)
  (setf list (copy-list list))
  (loop repeat n do (map-into list #'- (rest list) list))
  (subseq list 0 (- (length list) n)))


#include <iostream>
#include <string>
#include <cctype>
#include <cstdint>

typedef std::uint64_t integer;

const char* small[] = {
    "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
    "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
    "sixteen", "seventeen", "eighteen", "nineteen"
};

const char* tens[] = {
    "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"
};

struct named_number {
    const char* name_;
    integer number_;
};

const named_number named_numbers[] = {
    { "hundred", 100 },
    { "thousand", 1000 },
    { "million", 1000000 },
    { "billion", 1000000000 },
    { "trillion", 1000000000000 },
    { "quadrillion", 1000000000000000ULL },
    { "quintillion", 1000000000000000000ULL }
};

const named_number& get_named_number(integer n) {
    constexpr size_t names_len = std::size(named_numbers);
    for (size_t i = 0; i + 1 < names_len; ++i) {
        if (n < named_numbers[i + 1].number_)
            return named_numbers[i];
    }
    return named_numbers[names_len - 1];
}

std::string cardinal(integer n) {
    std::string result;
    if (n < 20)
        result = small[n];
    else if (n < 100) {
        result = tens[n/10 - 2];
        if (n % 10 != 0) {
            result += "-";
            result += small[n % 10];
        }
    } else {
        const named_number& num = get_named_number(n);
        integer p = num.number_;
        result = cardinal(n/p);
        result += " ";
        result += num.name_;
        if (n % p != 0) {
            result += " ";
            result += cardinal(n % p);
        }
    }
    return result;
}

inline char uppercase(char ch) {
    return static_cast<char>(std::toupper(static_cast<unsigned char>(ch)));
}

std::string magic(integer n) {
    std::string result;
    for (unsigned int i = 0; ; ++i) {
        std::string text(cardinal(n));
        if (i == 0)
            text[0] = uppercase(text[0]);
        result += text;
        if (n == 4) {
            result += " is magic.";
            break;
        }
        integer len = text.length();
        result += " is ";
        result += cardinal(len);
        result += ", ";
        n = len;
    }
    return result;
}

void test_magic(integer n) {
    std::cout << magic(n) << '\n';
}

int main() {
    test_magic(5);
    test_magic(13);
    test_magic(78);
    test_magic(797);
    test_magic(2739);
    test_magic(4000);
    test_magic(7893);
    test_magic(93497412);
    test_magic(2673497412U);
    test_magic(10344658531277200972ULL);
    return 0;
}


T[] forwardDifference(T)(in T[] data, in int level) pure nothrow
in {
    assert(level >= 0 && level < data.length);
} body {
    auto result = data.dup;
    foreach (immutable i; 0 .. level)
        foreach (immutable j, ref el; result[0 .. $ - i - 1])
            el = result[j + 1] - el;
    result.length -= level;
    return result;
}

void main() {
    import std.stdio;

    const data = [90.5, 47, 58, 29, 22, 32, 55, 5, 55, 73.5];
    foreach (immutable level; 0 .. data.length)
        forwardDifference(data, level).writeln;
}


List forwardDifference(List _list) {
  for (int i = _list.length - 1; i > 0; i--) {
    _list[i] = _list[i] - _list[i - 1];
  }

  _list.removeRange(0, 1);
  return _list;
}

void mainAlgorithms() {
  List _intList = [90, 47, 58, 29, 22, 32, 55, 5, 55, 73];

  for (int i = _intList.length - 1; i >= 0; i--) {
    List _list = forwardDifference(_intList);
    print(_list);
  }
}


(require '[clojure.edn :as edn])
(def names { 0 "zero"      1 "one"        2 "two"           3 "three"     4 "four"   5 "five"
             6 "six"       7 "seven"      8 "eight"         9 "nine"     10 "ten"   11 "eleven"
            12 "twelve"   13 "thirteen"  14 "fourteen"     15 "fifteen"
            16 "sixteen"  17 "seventeen" 18 "eighteen"     19 "nineteen"
            20 "twenty"   30 "thirty"    40 "forty"        50 "fifty"    60 "sixty"
            70 "seventy"  80 "eighty"    90 "ninety"      100 "hundred"

            1000          "thousand"     1000000          "million"      1000000000 "billion"
            1000000000000 "trillion"     1000000000000000 "quadrillion"
            1000000000000000000          "quintillion" })

(def powers-of-10 (reverse (sort (filter #(clojure.string/ends-with? (str %) "00") (keys names)))))

(defn name-of [n]
  (let [p (first (filter #(>= n %) powers-of-10))]
    (cond
      (not (nil? p))
        (let [quotient  (quot n p)
              remainder (rem  n p)]
              (str (name-of quotient) " " (names p) (if (> remainder 0) (str " " (name-of remainder)))))

      (and (nil? p) (> n 20))
        (let [remainder  (rem n 10)
              tens       (- n remainder)]
              (str (names tens) (if (> remainder 0) (str " " (name-of remainder)))))

      true
        (names n))))

(defn four-is-magic
  ([n] (four-is-magic n ""))
  ([n prefix]
   (let [name ((if (empty? prefix) clojure.string/capitalize identity) (name-of n))
         new-prefix (str prefix (if (not (empty? prefix)) ", "))]
   (if (= n 4)
    (str new-prefix name " is magic.")
    (let [len (count name)]
      (four-is-magic len (str new-prefix name " is " (name-of len))))))))

(defn report [n]
  (println (str n ": " (four-is-magic n))))

(defn -main [& args]
  (doall (map (comp report edn/read-string) args)))

(if (not= "repl" *command-line-args*)
  (apply -main *command-line-args*))


pragma.enable("accumulator")
/** Single step. */
def forwardDifference(seq :List) {
    return accum [] for i in 0..(seq.size() - 2) {
        _.with(seq[i + 1] - seq[i])
    }
}

/** Iterative implementation of the goal. */
def nthForwardDifference1(var seq :List, n :(int >= 0)) {
    for _ in 1..n { seq := forwardDifference(seq) }
    return seq
}

/** Imperative implementation of the goal. */
def nthForwardDifference2(seq :List, n :(int >= 0)) {
  def buf := seq.diverge()
  def finalSize := seq.size() - n
  for lim in (finalSize..!seq.size()).descending() {
    for i in 0..!lim {
      buf[i] := buf[i + 1] - buf[i]
    }
  }
  return buf.run(0, finalSize)
}

? def sampleData := [90, 47, 58, 29, 22, 32, 55, 5, 55, 73]
> for n in 0..10 {
>   def r1 := nthForwardDifference1(sampleData, n)
>   require(r1 == nthForwardDifference2(sampleData, n))
>   println(r1)
> }


(defun integer-to-text (int)
  (format nil "[email protected](~A~)" (with-output-to-string (out)
                          (loop for n = int then (length c)
                                for c = (format nil "~R" n)
                                while (/= n 4)
                                do (format out "~A is ~R, " c (length c))
                                finally (format out "four is magic.")))))


program Four_is_magic;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

// https://rosettacode.org/wiki/Number_names#Delphi
const
  smallies: array[1..19] of string = ('one', 'two', 'three', 'four', 'five',
    'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen',
    'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen');
  tens: array[2..9] of string = ('twenty', 'thirty', 'forty', 'fifty', 'sixty',
    'seventy', 'eighty', 'ninety');

function domaxies(number: int64): string;
const
  maxies: array[0..5] of string = (' thousand', ' million', ' billion',
    ' trillion', ' quadrillion', ' quintillion');
begin
  domaxies := '';
  if number >= 0 then
    domaxies := maxies[number];
end;

function doHundreds(number: int64): string;
begin
  Result := '';
  if number > 99 then
  begin
    Result := smallies[number div 100];
    Result := Result + ' hundred';
    number := number mod 100;
    if number > 0 then
      Result := Result + ' and ';
  end;
  if number >= 20 then
  begin
    Result := Result + tens[number div 10];
    number := number mod 10;
    if number > 0 then
      Result := Result + '-';
  end;
  if (0 < number) and (number < 20) then
    Result := Result + smallies[number];
end;

function spell(number: int64): string;
var
  scaleFactor: int64;
  maxieStart, h: int64;
begin
  if number = 0 then
    exit('zero');

  scaleFactor := 1000000000000000000;
  Result := '';
  if number < 0 then
  begin
    number := -number;
    Result := 'negative ';
  end;

  maxieStart := 5;
  if number < 20 then
    exit(smallies[number]);
  while scaleFactor > 0 do
  begin
    if number > scaleFactor then
    begin
      h := number div scaleFactor;
      Result := Result + doHundreds(h) + domaxies(maxieStart);
      number := number mod scaleFactor;
      if number > 0 then
        Result := Result + ', ';
    end;
    scaleFactor := scaleFactor div 1000;
    dec(maxieStart);
  end;
end;
//****************************************************\\

const
  numbers: array of Int64 = [0, 4, 6, 11, 13, 75, 100, 337, -164, int64.MaxValue];

function fourIsMagic(n: int64): string;
var
  s: string;
begin
  s := spell(n);
  s[1] := upcase(s[1]);
  var t := s;

  while n <> 4 do
  begin
    n := s.Length;
    s := spell(n);
    t := t + ' is ' + s + ', ' + s;
  end;
  t := t + ' is magic.';
  exit(t);
end;

begin
//  writeln(spell(4));
  for var n in numbers do
    writeln(fourIsMagic(n));
  readln;
end.


defmodule Diff do
  def forward(list,i\\1) do
    forward(list,[],i)
  end

  def forward([_],diffs,1), do: IO.inspect diffs
  def forward([_],diffs,i), do: forward(diffs,[],i-1)
  def forward([val1,val2|vals],diffs,i) do
    forward([val2|vals],diffs++[val2-val1],i)
  end
end

Enum.each(1..9, fn i ->
  Diff.forward([90, 47, 58, 29, 22, 32, 55, 5, 55, 73],i)
end)


//Express an Integer in English Language. Nigel Galloway: September 19th., 2018
let fN=[|[|"";"one";"two";"three";"four";"five";"six";"seven";"eight";"nine"|];
         [|"ten";"eleven";"twelve";"thirteen";"fourteen";"fifteen";"sixteen";"seventeen";"eighteen";"nineteen"|];
         [|"";"";"twenty";"thirty";"fourty";"fifty";"sixty";"seventy";"eighty";"ninety"|]|]
let rec I2α α β=match α with |α when α<20     ->β+fN.[α/10].[α%10]
                             |α when α<100    ->I2α (α%10) (β+fN.[2].[α/10]+if α%10>0 then " " else "")
                             |α when α<1000   ->I2α (α-(α/100)*100) (β+fN.[0].[α/100]+" hunred"+if α%100>0 then " and " else "")
                             |α when α<1000000->I2α (α%1000) (β+(I2α (α/1000) "")+" thousand"+if α%100=0 then "" else if (α-(α/1000)*1000)<100 then " and " else " ")


USING: ascii formatting io kernel make math.text.english regexp
sequences ;
IN: rosetta-code.four-is-magic

! Strip " and " and "," from the output of Factor's number>text
! word with a regular expression.
: number>english ( n -- str )
    number>text R/ and |,/ "" re-replace ;

! Return the length of the input integer's text form.
! e.g. 1 -> 3
: next-len ( n -- m ) number>english length ;

! Given a starting integer, return the sequence of lengths
! terminating with 4.
! e.g. 1 -> { 1 3 5 4 }
: len-chain ( n -- seq )
    [ [ dup 4 = ] [ dup , next-len ] until , ] { } make ;

! Convert a non-four number to its phrase form.
! e.g. 6 -> "six is three, "
: non-four ( n -- str )
    number>english dup length number>english
    "%s is %s, " sprintf ;

! Convert any number to its phrase form.
! e.g. 4 -> "four is magic."
: phrase ( n -- str )
    dup 4 = [ drop "four is magic." ] [ non-four ] if ;

: say-magic ( n -- )
    len-chain [ phrase ] map concat capitalize print ;

{ 1 4 -11 100 112719908181724 -612312 } [ say-magic ] each


-module(forward_difference).
-export([difference/1, difference/2]).

-export([task/0]).
-define(TEST_DATA,[90, 47, 58, 29, 22, 32, 55, 5, 55, 73]).

difference([X|Xs]) ->
    {Result,_} = lists:mapfoldl(fun (N_2,N_1) -> {N_2 - N_1, N_2} end, X, Xs),
    Result.

difference([],_) -> [];
difference(List,0) -> List;
difference(List,Order) -> difference(difference(List),Order-1).

task() ->
    io:format("Initial: ~p~n",[?TEST_DATA]),
    [io:format("~3b: ~p~n",[N,difference(?TEST_DATA,N)]) || N <- lists:seq(0,length(?TEST_DATA))],
    ok.


let rec ForwardDifference input n =
    match n with
    | _ when input = [] || n < 0 -> []      // If there's no more input, just return an empty list
    | 0 -> input                            // If n is zero, we're done - return the input
    | _ -> ForwardDifference                // otherwise, recursively difference..
            (input.Tail                     // All but the first element
            |> Seq.zip input                // tupled with itself
            |> Seq.map (fun (a, b) -> b-a)  // Subtract the i'th element from the (i+1)'th
            |> Seq.toList) (n-1)            // Make into a list and do an n-1 difference on it


MODULE FOUR_IS_MAGIC
    IMPLICIT NONE
    CHARACTER(8), DIMENSION(20) :: SMALL_NUMS
    CHARACTER(7), DIMENSION(8) :: TENS
    CHARACTER(7) :: HUNDRED
    CHARACTER(8) :: THOUSAND
    CHARACTER(8) :: MILLION
    CHARACTER(8) :: BILLION
    CHARACTER(9) :: TRILLION
    CHARACTER(11) :: QUADRILLION
    CHARACTER(11) :: QUINTILLION
    CHARACTER(1) :: SEPARATOR
    CHARACTER(1) :: SPACE

    CONTAINS

    SUBROUTINE INIT_ARRAYS

        SMALL_NUMS(1) = "zero"
        SMALL_NUMS(2) = "one"
        SMALL_NUMS(3) = "two"
        SMALL_NUMS(4) = "three"
        SMALL_NUMS(5) = "four"
        SMALL_NUMS(6) = "five"
        SMALL_NUMS(7) = "six"
        SMALL_NUMS(8) = "seven"
        SMALL_NUMS(9) = "eight"
        SMALL_NUMS(10) = "nine"
        SMALL_NUMS(11) = "ten"
        SMALL_NUMS(12) = "eleven"
        SMALL_NUMS(13) = "twelve"
        SMALL_NUMS(14) = "thirteen"
        SMALL_NUMS(15) = "fourteen"
        SMALL_NUMS(16) = "fifteen"
        SMALL_NUMS(17) = "sixteen"
        SMALL_NUMS(18) = "seventeen"
        SMALL_NUMS(19) = "eighteen"
        SMALL_NUMS(20) = "nineteen"

        TENS(1) = "twenty"
        TENS(2) = "thirty"
        TENS(3) = "forty"
        TENS(4) = "fifty"
        TENS(5) = "sixty"
        TENS(6) = "seventy"
        TENS(7) = "eight"
        TENS(8) = "ninety"

        HUNDRED = "hundred"
        THOUSAND = "thousand"
        MILLION = "million"
        BILLION = "billion"
        TRILLION = "trillion"
        QUADRILLION = "quadrillion"
        QUINTILLION = "quintillion"
        SEPARATOR = "-"
        SPACE = " "

    END SUBROUTINE INIT_ARRAYS

    RECURSIVE FUNCTION STRING_REPRESENTATION(NUM) RESULT(NUM_AS_STR)
        INTEGER(16), INTENT(IN) :: NUM
        CHARACTER(1000) :: NUM_AS_STR
        INTEGER(16), DIMENSION(9) :: COMPONENTS

        CALL INIT_ARRAYS()

        COMPONENTS = GET_COMPONENTS(NUM)

        NUM_AS_STR = TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(9), QUINTILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(8), QUADRILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(7), TRILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(6), BILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(5), MILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(4), THOUSAND)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(3), HUNDRED)))

        IF (COMPONENTS(2) .EQ. 1) THEN
            NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // SPACE // TRIM(ADJUSTL(SMALL_NUMS(10 + COMPONENTS(1) + 1)))
        ELSE

            IF (COMPONENTS(1) .GT. 0) THEN
                IF (COMPONENTS(2) .GT. 0) THEN
                    NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // SPACE // TRIM(ADJUSTL(TENS(COMPONENTS(2) - 1))) // SEPARATOR
                    NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // TRIM(ADJUSTL(SMALL_NUMS(COMPONENTS(1) + 1)))
                ELSE
                    NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // SPACE // TRIM(ADJUSTL(SMALL_NUMS(COMPONENTS(1) + 1)))
                ENDIF
            ELSE IF (COMPONENTS(2) .GT. 0) THEN
                NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // SPACE // TRIM(ADJUSTL(TENS(COMPONENTS(2) - 1)))
            ENDIF
        ENDIF

    END FUNCTION STRING_REPRESENTATION

    FUNCTION GET_COMPONENTS(NUM)
        INTEGER(16), INTENT(IN) :: NUM
        INTEGER(16), DIMENSION(9) :: GET_COMPONENTS
        INTEGER(16) :: I_UNITS
        INTEGER(16) :: I_TENS
        INTEGER(16) :: I_HUNDREDS
        INTEGER(16) :: I_THOUSANDS
        INTEGER(16) :: I_MILLIONS
        INTEGER(16) :: I_BILLIONS
        INTEGER(16) :: I_TRILLIONS
        INTEGER(16) :: I_QUADRILLIONS
        INTEGER(16) :: I_QUINTILLIONS
        REAL(16) DIVIDE_TEMP

        I_UNITS = NUM

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000000000000000))/1000000000000000000
        I_QUINTILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_QUINTILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_QUINTILLIONS*1000000000000000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000000000000))/1000000000000000
        I_QUADRILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_QUADRILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_QUADRILLIONS*1000000000000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000000000))/1000000000000
        I_TRILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_TRILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_TRILLIONS*1000000000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000000))/1000000000
        I_BILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_BILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_BILLIONS*1000000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000))/1000000

        I_MILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_MILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_MILLIONS*1000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000))/1000

        I_THOUSANDS = FLOOR(DIVIDE_TEMP)

        IF (I_THOUSANDS .NE. 0) THEN
           I_UNITS = I_UNITS - I_THOUSANDS*1000
        ENDIF

        DIVIDE_TEMP = I_UNITS/1E2
        I_HUNDREDS = FLOOR(DIVIDE_TEMP)

        IF (I_HUNDREDS .NE. 0) THEN
           I_UNITS = I_UNITS - I_HUNDREDS*1E2
        ENDIF

        DIVIDE_TEMP = I_UNITS/10.
        I_TENS =  FLOOR(DIVIDE_TEMP)

        IF (I_TENS .NE. 0) THEN
           I_UNITS = I_UNITS - I_TENS*10
        ENDIF

        GET_COMPONENTS(1) = I_UNITS
        GET_COMPONENTS(2) = I_TENS
        GET_COMPONENTS(3) = I_HUNDREDS
        GET_COMPONENTS(4) = I_THOUSANDS
        GET_COMPONENTS(5) = I_MILLIONS
        GET_COMPONENTS(6) = I_BILLIONS
        GET_COMPONENTS(7) = I_TRILLIONS
        GET_COMPONENTS(8) = I_QUADRILLIONS
        GET_COMPONENTS(9) = I_QUINTILLIONS

    END FUNCTION GET_COMPONENTS

    FUNCTION GET_SUBSET(COUNTER, LABEL) RESULT(OUT_STR)
        CHARACTER(*), INTENT(IN) :: LABEL
        INTEGER(16), INTENT(IN) :: COUNTER
        CHARACTER(100) :: OUT_STR

        OUT_STR = ""

        IF (COUNTER .GT. 0) THEN
            IF (COUNTER .LT. 20) THEN
                OUT_STR = SPACE // TRIM(ADJUSTL(SMALL_NUMS(COUNTER + 1)))
            ELSE
                OUT_STR = SPACE // TRIM(ADJUSTL(STRING_REPRESENTATION(COUNTER)))
            ENDIF
            OUT_STR = TRIM(ADJUSTL(OUT_STR)) // SPACE // TRIM(LABEL)
        ENDIF

    END FUNCTION GET_SUBSET

    SUBROUTINE FIND_MAGIC(NUM)
        INTEGER(16), INTENT(IN) :: NUM
        INTEGER(16) :: CURRENT, LEN_SIZE
        CHARACTER(1000) :: CURRENT_STR, CURRENT_STR_LEN
        CHARACTER(1000) :: OUT_STR

        CURRENT = NUM
        OUT_STR = ""

        DO WHILE (CURRENT .NE. 4)
            CURRENT_STR = STRING_REPRESENTATION(CURRENT)
            LEN_SIZE = LEN_TRIM(ADJUSTL(CURRENT_STR))
            CURRENT_STR_LEN = STRING_REPRESENTATION(LEN_SIZE)
            OUT_STR = TRIM(ADJUSTL(OUT_STR)) // SPACE // TRIM(ADJUSTL(CURRENT_STR))
            OUT_STR = TRIM(ADJUSTL(OUT_STR)) // " is " // TRIM(ADJUSTL(CURRENT_STR_LEN)) // ","
            CURRENT = LEN_SIZE
        ENDDO

        WRITE(*,*) TRIM(ADJUSTL(OUT_STR)) // SPACE // "four is magic."
    END SUBROUTINE FIND_MAGIC

END MODULE FOUR_IS_MAGIC

PROGRAM TEST_NUM_NAME
        USE FOUR_IS_MAGIC
        IMPLICIT NONE

        INTEGER(2) I
        INTEGER(16), DIMENSION(10) :: TEST_NUMS = (/5, 13, 78, 797, 2739, 4000, 7893, 93497412, 2673497412, 10344658531277200972/)
        CHARACTER(1000) :: NUM_NAME

        DO I=1, SIZE(TEST_NUMS)
            CALL FIND_MAGIC(TEST_NUMS(I))
        ENDDO
END PROGRAM


USING: kernel math math.vectors sequences ;
IN: rosetacode

: 1-order ( seq -- seq' )
    [ rest-slice ] keep v- ;

: n-order ( seq n -- seq' )
    dup 0 <=
    [ drop ] [ [ 1-order ] times ] if ;


: forward-difference
  dup 0
  ?do
     swap rot over i 1+ - 0
     ?do dup i cells + dup cell+ @ over @ - swap ! loop
     swap rot
  loop -
;

create a
  90 , 47 , 58 , 29 , 22 , 32 , 55 , 5 , 55 , 73 ,

: test a 10 9 forward-difference bounds ?do i ? loop ;

test


MODULE DIFFERENCE
  IMPLICIT NONE

  CONTAINS

  SUBROUTINE Fdiff(a, n)
    INTEGER, INTENT(IN) :: a(:), n
    INTEGER :: b(SIZE(a))
    INTEGER :: i, j, arraysize

    b = a
    arraysize = SIZE(b)
    DO i = arraysize-1, arraysize-n, -1
      DO j = 1, i
        b(j) = b(j+1) - b(j)
      END DO
    END DO
    WRITE (*,*) b(1:arraysize-n)
  END SUBROUTINE Fdiff
END MODULE DIFFERENCE


#define floor(x) ((x*2.0-0.5) Shr 1)

Dim Shared veintes(1 To 20) As String*9 => _
{"zero", "one", "two", "three", "four", "five", "six", _
"seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", _
"fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}

Dim Shared decenas(1 To 8) As String*7 => _
{"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}

Type myorder
    var1 As Double
    var2 As String*8
End Type
Dim Shared orders(1 To 4) As myorder => _
{(10^12,"trillion"), (10^9,"billion"), (10^6,"million"), (10^3,"thousand")}

Function centenas(n As Integer) As String
    If n < 20 Then
        Return veintes((n Mod 20)+1)
    Elseif (n Mod 10) = 0 Then
        Return decenas((floor(n/10) Mod 10)-1)
    End If
    Return decenas((floor(n/10) Mod 10)-1) & "-" & veintes((n Mod 10)+1)
End Function

Function miles(n As Integer) As String
    If n < 100 Then
        Return centenas(n)
    Elseif (n Mod 100) = 0 Then
        Return veintes((floor(n/100) Mod 20)+1) & " centenas"
    End If
    Return veintes((floor(n/100) Mod 20)+1) & " centenas " & centenas(n Mod 100)
End Function

Function triplet(n As Integer) As String
    Dim As Integer order, high, low
    Dim As String nombre, res = ""
    For i As Integer = 1 To Ubound(orders)
        order = orders(i).var1
        nombre = orders(i).var2
        high = floor(n/order)
        low = (n Mod order)
        If high <> 0 Then res &= miles(high) & " " & nombre
        n = low
        If low = 0 Then Exit For : End If
        If Len(res) And high <> 0 Then res &= " "
    Next i
    If n <> 0 Or res="" Then
        res &= miles(floor(n))
    End If
    Return res
End Function

Function deletrear(n As Integer) As String
    Dim As String res = ""
    If n < 0 Then
        res = "negative "
        n = -n
    End If
    res &= triplet(n)

    Return res
End Function

Function fourIsMagic(n As Integer) As String
    Dim As String s = deletrear(n)
    s = Mid(Ucase(s), 1, 1) & Mid(s, 2, Len(s))
    Dim As String t = s
    While n <> 4
        n = Len(s)
        s = deletrear(n)
        t &= " is " & s & ", " & s
    Wend
    t &= " is magic."
    Return t
End Function

Dim As Longint tests(1 To 21) = _
{-21, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, _
34, 123, 456, 1024, 1234, 12345, 123456, 1010101}

For i As Integer = 1 To Ubound(tests)
    Print Using "#######: &"; tests(i); fourIsMagic(tests(i))
Next i
Sleep


function forward_difference( a() as uinteger ) as uinteger ptr
    dim as uinteger ptr b = allocate( sizeof(uinteger) * (ubound(a)-1) )
    for i as uinteger = 0 to ubound(a)-1
        *(b+i) = a(i+1)-a(i)
    next i
    return b
end function

dim as uinteger a(0 to 15) = {2, 3, 5, 7, 11, 13, 17, 19,_
                         23, 29, 31, 37, 41, 43, 47, 53}
dim as uinteger i

dim as uinteger ptr b = forward_difference( a() )

for i = 0 to ubound(a)-1
    print *(b+i)
next i


package main

import "fmt"

func main() {
    a := []int{90, 47, 58, 29, 22, 32, 55, 5, 55, 73}
    fmt.Println(a)
    fmt.Println(fd(a, 9))
}

func fd(a []int, ord int) []int {
    for i := 0; i < ord; i++ {
        for j := 0; j < len(a)-i-1; j++ {
            a[j] = a[j+1] - a[j]
        }
    }
    return a[:len(a)-ord]
}


package main

import (
	"fmt"
	"math"
	"strings"
)

func main() {
	for _, n := range [...]int64{
		0, 4, 6, 11, 13, 75, 100, 337, -164,
		math.MaxInt64,
	} {
		fmt.Println(fourIsMagic(n))
	}
}

func fourIsMagic(n int64) string {
	s := say(n)
	s = strings.ToUpper(s[:1]) + s[1:]
	t := s
	for n != 4 {
		n = int64(len(s))
		s = say(n)
		t += " is " + s + ", " + s
	}
	t += " is magic."
	return t
}

// Following is from https://rosettacode.org/wiki/Number_names#Go

var small = [...]string{"zero", "one", "two", "three", "four", "five", "six",
	"seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen",
	"fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}
var tens = [...]string{"", "", "twenty", "thirty", "forty",
	"fifty", "sixty", "seventy", "eighty", "ninety"}
var illions = [...]string{"", " thousand", " million", " billion",
	" trillion", " quadrillion", " quintillion"}

func say(n int64) string {
	var t string
	if n < 0 {
		t = "negative "
		// Note, for math.MinInt64 this leaves n negative.
		n = -n
	}
	switch {
	case n < 20:
		t += small[n]
	case n < 100:
		t += tens[n/10]
		s := n % 10
		if s > 0 {
			t += "-" + small[s]
		}
	case n < 1000:
		t += small[n/100] + " hundred"
		s := n % 100
		if s > 0 {
			t += " " + say(s)
		}
	default:
		// work right-to-left
		sx := ""
		for i := 0; n > 0; i++ {
			p := n % 1000
			n /= 1000
			if p > 0 {
				ix := say(p) + illions[i]
				if sx != "" {
					ix += " " + sx
				}
				sx = ix
			}
		}
		t += sx
	}
	return t
}


forwardDifference :: Num a => [a] -> [a]
forwardDifference = tail >>= zipWith (-)

nthForwardDifference :: Num a => [a] -> Int -> [a]
nthForwardDifference = (!!) . iterate forwardDifference

main :: IO ()
main =
  mapM_ print $
  take 10 (iterate forwardDifference [90, 47, 58, 29, 22, 32, 55, 5, 55, 73])


REAL :: n=10, list(n)

list = ( 90, 47, 58, 29, 22, 32, 55, 5, 55, 73 )
WRITE(Format='i1, (i6)') 0, list

DO i = 1, n-1
  ALIAS(list,1,  diff,n-i) ! rename list(1 ... n-i) with diff
  diff = list($+1) - diff  ! $ is the running left hand array index
  WRITE(Format='i1, (i6)') i, diff
ENDDO

END


module Main where

import Data.List (find)
import Data.Char (toUpper)

firstNums :: [String]
firstNums =
  [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
    "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
  ]

tens :: [String]
tens = ["twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]

biggerNumbers :: [(Int, String)]
biggerNumbers =
  [(100, "hundred"), (1000, "thousand"), (1000000, "million"), (1000000000, "billion"), (1000000000000, "trillion")]

cardinal :: Int -> String
cardinal n
  | n' < 20 =
    negText ++ firstNums !! n'
  | n' < 100 =
    negText ++ tens !! (n' `div` 10 - 2) ++ if n' `mod` 10 /= 0 then "-" ++ firstNums !! (n' `mod` 10) else ""
  | otherwise =
    let (num, name) =
          maybe
            (last biggerNumbers)
            fst
            (find (\((num_, _), (num_', _)) -> n' < num_') (zip biggerNumbers (tail biggerNumbers)))
        smallerNum = cardinal (n' `div` num)
     in negText ++ smallerNum ++ " " ++ name ++ if n' `mod` num /= 0 then " " ++ cardinal (n' `mod` num) else ""
  where
    n' = abs n
    negText = if n < 0 then "negative " else ""

capitalized :: String -> String
capitalized (x : xs) = toUpper x : xs
capitalized [] = []

magic :: Int -> String
magic =
  go True
  where
    go first num =
      let cardiNum = cardinal num
       in (if first then capitalized else id) cardiNum ++ " is "
            ++ if num == 4
              then "magic."
              else cardinal (length cardiNum) ++ ", " ++ go False (length cardiNum)

main :: IO ()
main = do
  putStrLn $ magic 3
  putStrLn $ magic 15
  putStrLn $ magic 4
  putStrLn $ magic 10
  putStrLn $ magic 20
  putStrLn $ magic (-13)
  putStrLn $ magic 999999


names =. 'one';'two';'three';'four';'five';'six';'seven';'eight';'nine';'ten';'eleven';'twelve';'thirteen';'fourteen';'fifteen';'sixteen';'seventeen';'eighteen';'nineteen'

tens =. '';'twenty';'thirty';'forty';'fifty';'sixty';'seventy';'eighty';'ninety'

NB. selects the xth element from list y
lookup =: >@{:@{.

NB. string formatting
addspace =: ((' '"_, ]) ` ]) @. (<&0 @ {: @ $)

NB. numbers in range 1 to 19
s1 =: lookup&names

NB. numbers in range 20 to 99
s2d=: (lookup&tens @ <. @ %&10) , addspace @ (s1 @ (10&|))

NB. numbers in range 100 to 999
s3d =: s1 @ (<[email protected]%&100), ' hundred', addspace @ s2d @ (100&|)

NB. numbers in range 1 to 999
s123d =: s1 ` s2d ` s3d @. (>& 19 + >&99)

NB. numbers in range 1000 to 999999
s456d =: (s123d @<[email protected]%&1000), ' thousand', addspace @ s123d @ (1000&|)

NB. stringify numbers in range 1 to 999999
stringify =: s123d ` s456d @. (>&999)

NB. takes an int and returns an int of the length of the string of the input
lengthify =: {: @ $ @ stringify

NB. determines the string that should go after ' is '
what =: ((stringify @ lengthify), (', '"_)) ` ('magic'"_) @. (=&4)

runonce =: stringify , ' is ', what

run =: runonce, ((run @ lengthify) ` (''"_) @. (=&4))

doall =: run"0

inputs =: 4 8 16 25 89 365 2586 25865 369854

doall inputs


procedure main(A)    # Compute all forward difference orders for argument list
    every order := 1 to (*A-1) do showList(order, fdiff(A, order))
end

procedure fdiff(A, order)
    every 1 to order do {
        every put(B := [], A[i := 2 to *A] - A[i-1])
        A := B
        }
   return A
end

procedure showList(order, L)
    writes(right(order,3),": ")
    every writes(!L," ")
    write()
end


public class FourIsMagic {

    public static void main(String[] args) {
        for ( long n : new long[] {6, 60, 89, 300, 670, 2000, 2467, 20000, 24500,200000, 230000, 246571, 2300000, 2465712, 20000000, 24657123, 230000000, 245000000, -246570000, 123456789712345l, 8777777777777777777L, Long.MAX_VALUE}) {
            String magic = fourIsMagic(n);
            System.out.printf("%d = %s%n", n, toSentence(magic));
        }
    }

    private static final String toSentence(String s) {
        return s.substring(0,1).toUpperCase() + s.substring(1) + ".";
    }

    private static final String[] nums = new String[] {
            "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
            "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
    };

    private static final String[] tens = new String[] {"zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};

    private static final String fourIsMagic(long n) {
        if ( n == 4 ) {
            return numToString(n) + " is magic";
        }
        String result = numToString(n);
        return result + " is " + numToString(result.length()) + ", " + fourIsMagic(result.length());
    }

    private static final String numToString(long n) {
        if ( n < 0 ) {
            return "negative " + numToString(-n);
        }
        int index = (int) n;
        if ( n <= 19 ) {
            return nums[index];
        }
        if ( n <= 99 ) {
            return tens[index/10] + (n % 10 > 0 ? " " + numToString(n % 10) : "");
        }
        String label = null;
        long factor = 0;
        if ( n <= 999 ) {
            label = "hundred";
            factor = 100;
        }
        else if ( n <= 999999) {
            label = "thousand";
            factor = 1000;
        }
        else if ( n <= 999999999) {
            label = "million";
            factor = 1000000;
        }
        else if ( n <= 999999999999L) {
            label = "billion";
            factor = 1000000000;
        }
        else if ( n <= 999999999999999L) {
            label = "trillion";
            factor = 1000000000000L;
        }
        else if ( n <= 999999999999999999L) {
            label = "quadrillion";
            factor = 1000000000000000L;
        }
        else {
            label = "quintillion";
            factor = 1000000000000000000L;
        }
        return numToString(n / factor) + " " + label + (n % factor > 0 ? " " + numToString(n % factor ) : "");
    }

}


import java.util.Arrays;
public class FD {
    public static void main(String args[]) {
        double[] a = {90, 47, 58, 29, 22, 32, 55, 5, 55, 73};
        System.out.println(Arrays.toString(dif(a, 1)));
        System.out.println(Arrays.toString(dif(a, 2)));
        System.out.println(Arrays.toString(dif(a, 9)));
        System.out.println(Arrays.toString(dif(a, 10)));      //let's test
        System.out.println(Arrays.toString(dif(a, 11)));
        System.out.println(Arrays.toString(dif(a, -1)));
        System.out.println(Arrays.toString(dif(a, 0)));
    }

    public static double[] dif(double[] a, int n) {
        if (n < 0)
            return null; // if the programmer was dumb

        for (int i = 0; i < n && a.length > 0; i++) {
            double[] b = new double[a.length - 1];
            for (int j = 0; j < b.length; j++){
                b[j] = a[j+1] - a[j];
            }
            a = b; //"recurse"
        }
        return a;
    }
}


# The num2text routines are from the "Number names" task, updated for Julia 1.0

const stext = ["one", "two", "three", "four", "five",
               "six", "seven", "eight", "nine"]
const teentext = ["eleven", "twelve", "thirteen", "fourteen",
                  "fifteen", "sixteen", "seventeen",
                  "eighteen", "nineteen"]
const tenstext = ["ten", "twenty", "thirty", "forty", "fifty",
                  "sixty", "seventy", "eighty", "ninety"]
const ordstext = ["million", "billion", "trillion",
                  "quadrillion", "quintillion", "sextillion",
                  "septillion", "octillion", "nonillion",
                  "decillion", "undecillion", "duodecillion",
                  "tredecillion", "quattuordecillion", "quindecillion",
                  "sexdecillion", "septendecillion", "octodecillion",
                  "novemdecillion", "vigintillion"]

function normalize_digits!(a)
    while  0 < length(a) && a[end] == 0
        pop!(a)
    end
    return length(a)
end

function digits2text!(d, use_short_scale=true)
    ndig = normalize_digits!(d)
    0 < ndig || return ""
    if ndig < 7
        s = ""
        if 3 < ndig
            t = digits2text!(d[1:3])
            s = digits2text!(d[4:end])*" thousand"
            0 < length(t) || return s
            if occursin("and", t)
                return s*" "*t
            else
                return s*" and "*t
            end
        end
        if ndig == 3
            s *= stext[pop!(d)]*" hundred"
            ndig = normalize_digits!(d)
            0 < ndig || return s
            s *= " and "
        end
        1 < ndig || return s*stext[pop!(d)]
        j, i = d
        j != 0 || return s*tenstext[i]
        i != 1 || return s*teentext[j]
        return s*tenstext[i]*"-"*stext[j]
    end
    s = digits2text!(d[1:6])
    d = d[7:end]
    dgrp = use_short_scale ? 3 : 6
    ord = 0
    while(dgrp < length(d))
        ord += 1
        t = digits2text!(d[1:dgrp])
        d = d[(dgrp+1):end]
        0 < length(t) || continue
        t = t*" "*ordstext[ord]
        if length(s) == 0
            s = t
        else
            s = t*" "*s
        end
    end
    ord += 1
    t = digits2text!(d)*" "*ordstext[ord]
    0 < length(s) || return t
    return t*" "*s
end

function num2text(n, use_short_scale=true)
    -1 < n || return "minus "*num2text(-n, use_short_scale)
    0 < n || return "zero"
    toobig = use_short_scale ? big(10)^66 : big(10)^126
    n < toobig || return "too big to say"
    return digits2text!(digits(n, base=10), use_short_scale)
end

function magic(n)
    str = uppercasefirst(num2text(n))
    n = length(str)
    while true
        numtext = num2text(n)
        str *= " is " * numtext
        if numtext == "four"
            break
        end
        str *= ", " * numtext
        n = length(numtext)
    end
    println(str[1:7] == "Four is" ? "Four is magic." : "$str, four is magic.")
end

for n in [0, 4, 6, 11, 13, 75, 337, -164, 9_876_543_209]
    magic(n)
end


// version 1.1.4-3

val names = mapOf(
    1 to "one",
    2 to "two",
    3 to "three",
    4 to "four",
    5 to "five",
    6 to "six",
    7 to "seven",
    8 to "eight",
    9 to "nine",
    10 to "ten",
    11 to "eleven",
    12 to "twelve",
    13 to "thirteen",
    14 to "fourteen",
    15 to "fifteen",
    16 to "sixteen",
    17 to "seventeen",
    18 to "eighteen",
    19 to "nineteen",
    20 to "twenty",
    30 to "thirty",
    40 to "forty",
    50 to "fifty",
    60 to "sixty",
    70 to "seventy",
    80 to "eighty",
    90 to "ninety"
)
val bigNames = mapOf(
    1_000L to "thousand",
    1_000_000L to "million",
    1_000_000_000L to "billion",
    1_000_000_000_000L to "trillion",
    1_000_000_000_000_000L to "quadrillion",
    1_000_000_000_000_000_000L to "quintillion"
)

fun numToText(n: Long): String {
    if (n == 0L) return "zero"
    val neg = n < 0L
    val maxNeg = n == Long.MIN_VALUE
    var nn = if (maxNeg) -(n + 1) else if (neg) -n else n
    val digits3 = IntArray(7)
    for (i in 0..6) {  // split number into groups of 3 digits from the right
        digits3[i] = (nn % 1000).toInt()
        nn /= 1000
    }

    fun threeDigitsToText(number: Int) : String {
        val sb = StringBuilder()
        if (number == 0) return ""
        val hundreds = number / 100
        val remainder = number % 100
        if (hundreds > 0) {
            sb.append(names[hundreds], " hundred")
            if (remainder > 0) sb.append(" ")
        }
        if (remainder > 0) {
            val tens = remainder / 10
            val units = remainder % 10
            if (tens > 1) {
                sb.append(names[tens * 10])
                if (units > 0) sb.append("-", names[units])
            }
            else sb.append(names[remainder])
        }
        return sb.toString()
    }

    val strings = Array<String>(7) { threeDigitsToText(digits3[it]) }
    var text = strings[0]
    var big = 1000L
    for (i in 1..6) {
        if (digits3[i] > 0) {
            var text2 = strings[i] + " " + bigNames[big]
            if (text.length > 0) text2 += " "
            text = text2 + text
        }
        big *= 1000
    }
    if (maxNeg) text = text.dropLast(5) + "eight"
    if (neg) text = "negative " + text
    return text
}

fun fourIsMagic(n: Long): String {
    if (n == 4L) return "Four is magic."
    var text = numToText(n).capitalize()
    val sb = StringBuilder()
    while (true) {
        val len = text.length.toLong()
        if (len == 4L) return sb.append("$text is four, four is magic.").toString()
        val text2 = numToText(len)
        sb.append("$text is $text2, ")
        text = text2
    }
}

fun main(args: Array<String>) {
    val la = longArrayOf(0, 4, 6, 11, 13, 75, 100, 337, -164, 9_223_372_036_854_775_807L)
    for (i in la) {
        println(fourIsMagic(i))
        println()
    }
}


(() => {
    'use strict';

    // forwardDifference :: Num a => [a] -> [a]
    const forwardDifference = xs =>
        zipWith(subtract)(xs)(tail(xs));

    // nthForwardDifference :: Num a => [a] -> Int -> [a]
    const nthForwardDifference = xs =>
        index(iterate(forwardDifference)(xs)).Just;

    //----------------------- TEST ------------------------
    // main :: IO ()
    const main = () =>
        unlines(
            take(10)(
                iterate(forwardDifference)(
                    [90, 47, 58, 29, 22, 32, 55, 5, 55, 73]
                )
            ).map((x, i) => justifyRight(2)('x')(i) + (
                ' -> '
            ) + JSON.stringify(x))
        );

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

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

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

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

    // index (!!) :: [a] -> Int -> Maybe a
    // index (!!) :: Generator (Int, a) -> Int -> Maybe a
    // index (!!) :: String -> Int -> Maybe Char
    const index = xs => i => {
        const s = xs.constructor.constructor.name;
        return 'GeneratorFunction' !== s ? (() => {
            const v = xs[i];
            return undefined !== v ? Just(v) : Nothing();
        })() : Just(take(i)(xs), xs.next().value);
    };

    // iterate :: (a -> a) -> a -> Gen [a]
    const iterate = f =>
        function*(x) {
            let v = x;
            while (true) {
                yield(v);
                v = f(v);
            }
        };

    // justifyRight :: Int -> Char -> String -> String
    const justifyRight = n =>
        // The string s, preceded by enough padding (with
        // the character c) to reach the string length n.
        c => s => n > s.length ? (
            s.padStart(n, c)
        ) : s;

    // length :: [a] -> Int
    const length = xs =>
        // Returns Infinity over objects without finite
        // length. This enables zip and zipWith to choose
        // the shorter argument when one is non-finite,
        // like cycle, repeat etc
        (Array.isArray(xs) || 'string' === typeof xs) ? (
            xs.length
        ) : Infinity;

    // map :: (a -> b) -> [a] -> [b]
    const map = f =>
        // The list obtained by applying f
        // to each element of xs.
        // (The image of xs under f).
        xs => (
            Array.isArray(xs) ? (
                xs
            ) : xs.split('')
        ).map(f);

    // subtract :: Num -> Num -> Num
    const subtract = x =>
        y => y - x;

    // tail :: [a] -> [a]
    const tail = xs =>
        // A new list consisting of all
        // items of xs except the first.
        0 < xs.length ? xs.slice(1) : [];

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

    // unlines :: [String] -> String
    const unlines = xs =>
        // A single string formed by the intercalation
        // of a list of strings with the newline character.
        xs.join('\n');

    // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    const zipWith = f => xs => ys => {
        const
            lng = Math.min(length(xs), length(ys)),
            [as, bs] = [xs, ys].map(take(lng));
        return Array.from({
            length: lng
        }, (_, i) => f(as[i])(
            bs[i]
        ));
    };

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


-- Four is magic, in Lua, 6/16/2020 db
local oneslist = { [0]="", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }
local teenlist = { [0]="ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }
local tenslist = { [0]="", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" }
local lionlist = { [0]="", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", "decillion" }
local abs, floor = math.abs, math.floor

local function numname(num)
  if (num == 0) then return "zero" end
  local absnum, lion, result = abs(num), 0, ""
  local function dashed(s) return s=="" and s or "-"..s end
  local function spaced(s) return s=="" and s or " "..s end
  while (absnum > 0) do
    local word, ones, tens, huns = "", absnum%10, floor(absnum/10)%10, floor(absnum/100)%10
    if (tens==0) then word = oneslist[ones]
    elseif (tens==1) then word = teenlist[ones]
    else word = tenslist[tens] .. dashed(oneslist[ones]) end
    if (huns > 0) then word = oneslist[huns] .. " hundred" .. spaced(word) end
    if (word ~= "") then result = word .. spaced(lionlist[lion]) .. spaced(result) end
    absnum = floor(absnum / 1000)
    lion = lion + 1
  end
  if (num < 0) then result = "negative " .. result end
  return result
end

local function fourismagic(num)
  local function fim(num)
    local name = numname(num)
    if (num == 4) then
      return name .. " is magic."
    else
      local what = numname(#name)
      return name .. " is " .. what .. ", " .. fim(#name)
    end
  end
  local result = fim(num):gsub("^%l", string.upper)
  return result
end

local numbers = { -21,-1, 0,1,2,3,4,5,6,7,8,9, 12,34,123,456,1024,1234,12345,123456,1010101 }
for _, num in ipairs(numbers) do
  print(num, fourismagic(num))
end


# If n is a non-negative number and if input is
# a (possibly empty) array of numbers,
# emit an array, even if the input list is too short:
def ndiff(n):
  if n==0 then .
  elif n == 1 then . as $in | [range(1;length) | $in[.] - $in[.-1]]
  else ndiff(1) | ndiff(n-1)
  end;


ndiff(A::Array, n::Integer) = n < 1 ? A : diff(ndiff(A, n-1))

s = [90, 47, 58, 29, 22, 32, 55, 5, 55, 73]
println.(collect(ndiff(s, i) for i in 0:9))


// version 1.1.2

fun forwardDifference(ia: IntArray, order: Int): IntArray {
    if (order < 0) throw IllegalArgumentException("Order must be non-negative")
    if (order == 0) return ia
    val size = ia.size
    if (size == 0) return ia  // same empty array
    if (order >= size) return intArrayOf()  // new empty array
    var old = ia
    var new = old
    var count = order
    while (count-- >= 1) {
       new = IntArray(old.size - 1)
       for (i in 0 until new.size) new[i] = old[i + 1] - old[i]
       old = new
    }
    return new
}

fun printArray(ia: IntArray) {
    print("[")
    for (i in 0 until ia.size) {
        print("%5d".format(ia[i]))
        if (i < ia .size - 1) print(", ")
    }
    println("]")
}

fun main(args: Array<String>) {
    val ia = intArrayOf(90, 47, 58, 29, 22, 32, 55, 5, 55, 73)
    for (order in 0..ia.size) {
        val fd = forwardDifference(ia, order)
        print("%2d".format(order) + ":  ")
        printArray(fd)
    }
}


magic[num_] := Capitalize[ StringRiffle[ Partition[
    FixedPointList[IntegerName[StringLength[#], "Cardinal"] &, IntegerName[num, "Cardinal"]],
    2, 1] /. {n_, n_} :> {n, "magic"}, ", ", " is "] <> "."]


import strutils

const

  Small = ["zero",    "one",     "two",       "three",    "four",
           "five",    "six",     "seven",     "eight",    "nine",
           "ten",     "eleven",  "twelve",    "thirteen", "fourteen",
           "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]

  Tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]

  Illions = ["", " thousand", " million", " billion", " trillion", " quadrillion", " quintillion"]

#---------------------------------------------------------------------------------------------------

func say(n: int64): string =

  var n = n

  if n < 0:
    result = "negative "
    n = -n

  if n < 20:
    result &= Small[n]

  elif n < 100:
    result &= Tens[n div 10]
    let m = n mod 10
    if m != 0: result &= '-' & Small[m]

  elif n < 1000:
    result &= Small[n div 100] & " hundred"
    let m = n mod 100
    if m != 0: result &= ' ' & m.say()

  else:
    # Work from right to left.
    var sx = ""
    var i = 0
    while n > 0:
      let m = n mod 1000
      n = n div 1000
      if m != 0:
        var ix = m.say() & Illions[i]
        if sx.len > 0: ix &= " " & sx
        sx = ix
      inc i
    result &= sx

#---------------------------------------------------------------------------------------------------

func fourIsMagic(n: int64): string =
  var n = n
  var s = n.say().capitalizeAscii()
  result = s
  while n != 4:
    n = s.len.int64
    s = n.say()
    result &= " is " & s & ", " & s
  result &= " is magic."

#———————————————————————————————————————————————————————————————————————————————————————————————————

for n in [int64 0, 4, 6, 11, 13, 75, 100, 337, -164, int64.high]:
  echo fourIsMagic(n)


use Lingua::EN::Numbers qw(num2en);

sub cardinal {
    my($n) = @_;
    (my $en = num2en($n)) =~ s/\ and|,//g;
    $en;
}

sub magic {
    my($int) = @_;
    my $str;
    while () {
       $str .= cardinal($int) . " is ";
       if ($int == 4) {
           $str .= "magic.\n";
           last
       } else {
           $int = length cardinal($int);
           $str .= cardinal($int) . ", ";
       }
   }
   ucfirst $str;
}

print magic($_) for 0, 4, 6, 11, 13, 75, 337, -164, 9_876_543_209;


with javascript_semantics
--<adapted from demo\rosetta\number_names.exw, which alas outputs ",", "and", uses "minus" instead of "negative", etc...>
constant twenties = {"zero","one","two","three","four","five","six","seven","eight","nine","ten",
    "eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"},
         decades = {"twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"}

function hundred(integer n)
    if n<20 then
        return twenties[mod(n,20)+1]
    elsif mod(n,10)=0 then
        return decades[mod(floor(n/10),10)-1]
    end if
    return decades[mod(floor(n/10),10)-1] & '-' & twenties[mod(n,10)+1]
end function

function thousand(integer n)
    if n<100 then
        return hundred(n)
    elsif mod(n,100)=0 then
        return twenties[mod(floor(n/100),20)+1]&" hundred"
    end if
    return twenties[mod(floor(n/100),20)+1] & " hundred " & hundred(mod(n,100))
end function

constant orders = {{power(10,12),"trillion"},
                   {power(10,9),"billion"},
                   {power(10,6),"million"},
                   {power(10,3),"thousand"}}

function triplet(integer n)
    string res = ""
    for i=1 to length(orders) do
        {atom order, string name} = orders[i]
        atom high = floor(n/order),
             low = mod(n,order)
        if high!=0 then
            res &= thousand(high)&' '&name
        end if
        n = low
        if low=0 then exit end if
        if length(res) and high!=0 then
            res &= " "
        end if
    end for
    if n!=0 or res="" then
        res &= thousand(floor(n))
    end if
    return res
end function

function spell(integer n)
    string res = ""
    if n<0 then
        res = "negative "
        n = -n
    end if
    res &= triplet(n)
    return res
end function
--</adapted from number_names.exw>

function fourIsMagic(atom n)
    string s = spell(n)
    s[1] = upper(s[1])
    string t = s
    while n!=4 do
        n = length(s)
        s = spell(n)
        t &= " is " & s & ", " & s
    end while
    t &= " is magic.\n"
    return t
end function

constant tests = {-7, -1, 0, 1, 2, 3, 4, 23, 1e9, 20140, 100, 130, 151, 999999}
for i=1 to length(tests) do
    puts(1,fourIsMagic(tests[i]))
end for


#!/usr/bin/lasso9

define forwardDiff(values, order::integer=1) => {
  !#order ? return #values->asArray
  local(result = array)
  iterate(#values) => {
    loop_count < #values->size ?
      #result->insert(#values->get(loop_count+1) - #values->get(loop_count))
  }
  #order > 1 ? #result = forwardDiff(#result, #order-1)
  return #result
}

local(data = (:90, 47, 58, 29, 22, 32, 55, 5, 55, 73))
with x in generateSeries(0, #data->size-1)
do stdoutnl(#x + ': ' + forwardDiff(#data, #x))


to fwd.diff :l
  if empty? :l [output []]
  if empty? bf :l [output []]
  output fput (first bf :l)-(first :l) fwd.diff bf :l
end
to nth.fwd.diff :n :l
  if :n = 0 [output :l]
  output nth.fwd.diff :n-1 fwd.diff :l
end

show nth.fwd.diff 9 [90 47 58 29 22 32 55 5 55 73]
[-2921]


function dif(a, b, ...)
  if(b) then return b-a, dif(b, ...) end
end
function dift(t) return {dif(unpack(t))} end
print(unpack(dift{1,3,6,10,15}))


import random
from collections import OrderedDict

numbers = {  # taken from https://en.wikipedia.org/wiki/Names_of_large_numbers#cite_ref-a_14-3
    1: 'one',
    2: 'two',
    3: 'three',
    4: 'four',
    5: 'five',
    6: 'six',
    7: 'seven',
    8: 'eight',
    9: 'nine',
    10: 'ten',
    11: 'eleven',
    12: 'twelve',
    13: 'thirteen',
    14: 'fourteen',
    15: 'fifteen',
    16: 'sixteen',
    17: 'seventeen',
    18: 'eighteen',
    19: 'nineteen',
    20: 'twenty',
    30: 'thirty',
    40: 'forty',
    50: 'fifty',
    60: 'sixty',
    70: 'seventy',
    80: 'eighty',
    90: 'ninety',
    100: 'hundred',
    1000: 'thousand',
    10 ** 6: 'million',
    10 ** 9: 'billion',
    10 ** 12: 'trillion',
    10 ** 15: 'quadrillion',
    10 ** 18: 'quintillion',
    10 ** 21: 'sextillion',
    10 ** 24: 'septillion',
    10 ** 27: 'octillion',
    10 ** 30: 'nonillion',
    10 ** 33: 'decillion',
    10 ** 36: 'undecillion',
    10 ** 39: 'duodecillion',
    10 ** 42: 'tredecillion',
    10 ** 45: 'quattuordecillion',
    10 ** 48: 'quinquadecillion',
    10 ** 51: 'sedecillion',
    10 ** 54: 'septendecillion',
    10 ** 57: 'octodecillion',
    10 ** 60: 'novendecillion',
    10 ** 63: 'vigintillion',
    10 ** 66: 'unvigintillion',
    10 ** 69: 'duovigintillion',
    10 ** 72: 'tresvigintillion',
    10 ** 75: 'quattuorvigintillion',
    10 ** 78: 'quinquavigintillion',
    10 ** 81: 'sesvigintillion',
    10 ** 84: 'septemvigintillion',
    10 ** 87: 'octovigintillion',
    10 ** 90: 'novemvigintillion',
    10 ** 93: 'trigintillion',
    10 ** 96: 'untrigintillion',
    10 ** 99: 'duotrigintillion',
    10 ** 102: 'trestrigintillion',
    10 ** 105: 'quattuortrigintillion',
    10 ** 108: 'quinquatrigintillion',
    10 ** 111: 'sestrigintillion',
    10 ** 114: 'septentrigintillion',
    10 ** 117: 'octotrigintillion',
    10 ** 120: 'noventrigintillion',
    10 ** 123: 'quadragintillion',
    10 ** 153: 'quinquagintillion',
    10 ** 183: 'sexagintillion',
    10 ** 213: 'septuagintillion',
    10 ** 243: 'octogintillion',
    10 ** 273: 'nonagintillion',
    10 ** 303: 'centillion',
    10 ** 306: 'uncentillion',
    10 ** 309: 'duocentillion',
    10 ** 312: 'trescentillion',
    10 ** 333: 'decicentillion',
    10 ** 336: 'undecicentillion',
    10 ** 363: 'viginticentillion',
    10 ** 366: 'unviginticentillion',
    10 ** 393: 'trigintacentillion',
    10 ** 423: 'quadragintacentillion',
    10 ** 453: 'quinquagintacentillion',
    10 ** 483: 'sexagintacentillion',
    10 ** 513: 'septuagintacentillion',
    10 ** 543: 'octogintacentillion',
    10 ** 573: 'nonagintacentillion',
    10 ** 603: 'ducentillion',
    10 ** 903: 'trecentillion',
    10 ** 1203: 'quadringentillion',
    10 ** 1503: 'quingentillion',
    10 ** 1803: 'sescentillion',
    10 ** 2103: 'septingentillion',
    10 ** 2403: 'octingentillion',
    10 ** 2703: 'nongentillion',
    10 ** 3003: 'millinillion'
}
numbers = OrderedDict(sorted(numbers.items(), key=lambda t: t[0], reverse=True))

def string_representation(i: int) -> str:
    """
    Return the english string representation of an integer
    """
    if i == 0:
        return 'zero'

    words = ['negative'] if i < 0 else []
    working_copy = abs(i)

    for key, value in numbers.items():
        if key <= working_copy:
            times = int(working_copy / key)

            if key >= 100:
                words.append(string_representation(times))

            words.append(value)
            working_copy -= times * key

        if working_copy == 0:
            break

    return ' '.join(words)

def next_phrase(i: int):
    """
    Generate all the phrases
    """
    while not i == 4:  # Generate phrases until four is reached
        str_i = string_representation(i)
        len_i = len(str_i)

        yield str_i, 'is', string_representation(len_i)

        i = len_i

    # the last phrase
    yield string_representation(i), 'is', 'magic'

def magic(i: int) -> str:
    phrases = []

    for phrase in next_phrase(i):
        phrases.append(' '.join(phrase))

    return f'{", ".join(phrases)}.'.capitalize()

if __name__ == '__main__':

    for j in (random.randint(0, 10 ** 3) for i in range(5)):
        print(j, ':\n', magic(j), '\n')

    for j in (random.randint(-10 ** 24, 10 ** 24) for i in range(2)):
        print(j, ':\n', magic(j), '\n')


Form 80, 40
Module Forward_difference {
      Print $(0,6)  ' 6 characters column
      Dim a(), b()
      a()=(90,47,58,29,22,32,55,5,55,73)
      Function Diff(a()) {
            for i=0 to len(a())-2: a(i)=a(i+1)-a(i):Next i
            Dim a(len(a())-1) ' redim one less
            =a()
      }
      Print "Original:","",a()
      b()=a()    ' copy a() to b()
      k=1
      While len(b())>1 {
            b()=Diff(b())   ' copy returned array to b()
            Print "Difference ";k;":",b()
            k++
      }
}
Forward_difference


ldiff(u, n) := block([m: length(u)], for j thru n do u: makelist(u[i + 1] - u[i], i, 1, m - j), u);


-V
   Width = 1000
   Height = 1000
   TrunkLength = 400
   ScaleFactor = 0.6
   StartingAngle = 1.5 * math:pi
   DeltaAngle = 0.2 * math:pi

F drawTree(outfile, Float x, Float y; len, theta) -> N
   I len >= 1
      V x2 = x + len * cos(theta)
      V y2 = y + len * sin(theta)
      outfile.write("<line x1='#.6' y1='#.6' x2='#.6' y2='#.6' style='stroke:white;stroke-width:1'/>\n".format(x, y, x2, y2))
      drawTree(outfile, x2, y2, len * ScaleFactor, theta + DeltaAngle)
      drawTree(outfile, x2, y2, len * ScaleFactor, theta - DeltaAngle)

V outsvg = File(‘tree.svg’, ‘w’)
outsvg.write(|‘<?xml version='1.0' encoding='utf-8' standalone='no'?>
               <!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
               <svg width='100%%' height='100%%' version='1.1' xmlns='http://www.w3.org/2000/svg'>
               <rect width="100%" height="100%" fill="black"/>
               ’)
drawTree(outsvg, 0.5 * Width, Height, TrunkLength, StartingAngle)
outsvg.write("</svg>\n")


C:``one`two`three`four`five`six`seven`eight`nine`ten,
  `eleven`twelve`thirteen`fourteen`fifteen`sixteen`seventeen`eighteen`nineteen                             / cardinal numbers <20

T:``ten`twenty`thirty`forty`fifty`sixty`seventy`eighty`ninety                                              / tens
M:``thousand`million`billion`trillion`quadrillion`quintillion`sextillion`septillion                        / magnitudes

st:{                                                                                / stringify <1000
  $[x<20; C x;
    x<100; (T;C)@'10 vs x;
    {C[y],`hundred,$[z=0;`;x z]}[.z.s] . 100 vs x] }

s:{$[x=0; "zero"; {" "sv string except[;`]raze x{$[x~`;x;x,y]}'M reverse til count x} st each 1000 vs x]}  / stringify

fim:{@[;0;upper],[;"four is magic.\n"] raze 1_{y," is ",x,", "}prior s each(count s@)\[x]}                 / four is magic

1 raze fim each 0 4 8 16 25 89 365 2586 25865 369854 40000000001;                                          / tests


# provided by neonira

integerToText <- function(value_n_1) {
  english_words_for_numbers <- list(
    simples = c(
      'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine',
      'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'
    ),
    tens = c('twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'),
    powers = c(
      'hundred'     = 100,
      'thousand'    = 1000,
      'million'     = 1000000,
      'billion'     = 1000000000,
      'trillion'    = 1000000000000,
      'quadrillion' = 1000000000000000,
      'quintillion' = 1000000000000000000
    )
  )

  buildResult <- function(x_s) {
    if (value_n_1 < 0) return(paste('minus', x_s))
    x_s
  }
  withDash <- function(a_s, b_s) paste(a_s, b_s, sep = '-')
  val <- abs(value_n_1)
  if (val < 20L) return(buildResult(english_words_for_numbers$simples[val + 1L]))
  if (val < 100L) {
    tens <- val %/% 10L - 1L
    reminder <- val %% 10L
    if (reminder == 0L) return(buildResult(english_words_for_numbers$ten[tens]))
    return(buildResult(withDash(english_words_for_numbers$ten[tens], Recall(reminder))))
  }

  index <- l <- length(english_words_for_numbers$powers)
  for(power in seq_len(l)) {
    if (val < english_words_for_numbers$powers[power]) {
      index <- power - 1L
      break
    }
  }

  f <- Recall(val %/% english_words_for_numbers$powers[index])
  reminder <- val %% english_words_for_numbers$powers[index]
  if (reminder == 0L) return(buildResult(paste(f, names(english_words_for_numbers$powers)[index])))
  buildResult(paste(f, names(english_words_for_numbers$powers)[index],  Recall(reminder)))
}

magic <- function(value_n_1) {
  text <- vector('character')
  while(TRUE) {
    r <- integerToText(value_n_1)
    nc <- nchar(r)
    complement <- ifelse(value_n_1 == 4L, "is magic", paste("is", integerToText(nc)))
    text[length(text) + 1L] <- paste(r, complement)
    if (value_n_1 == 4L) break
    value_n_1 <- nc
  }

  buildSentence <- function(x_s) paste0(toupper(substr(x_s, 1L, 1L)), substring(x_s, 2L), '.')
  buildSentence(paste(text, collapse = ', '))
}


#lang racket

(require rackunit)

(define smalls
  (map symbol->string
       '(zero one two three four five six seven eight nine ten eleven twelve
         thirteen fourteen fifteen sixteen seventeen eighteen nineteen)))

(define tens
  (map symbol->string
       '(zero ten twenty thirty forty fifty sixty seventy eighty ninety)))

(define larges
  (map symbol->string
       '(thousand million billion trillion quadrillion quintillion sextillion
         septillion octillion nonillion decillion undecillion duodecillion
         tredecillion quattuordecillion quindecillion sexdecillion
         septendecillion octodecillion novemdecillion vigintillion)))

(define (number->words n)
  (define (step div suffix separator [subformat number->words])
    (define-values [q r] (quotient/remainder n div))
    (define S (if suffix (~a (subformat q) " " suffix) (subformat q)))
    (if (zero? r) S (~a S separator (number->words r))))
  (cond [(< n 0) (~a "negative " (number->words (- n)))]
        [(< n 20) (list-ref smalls n)]
        [(< n 100) (step 10 #f "-" (curry list-ref tens))]
        [(< n 1000) (step 100 "hundred" " ")]
        [else (let loop ([N 1000000] [D 1000] [unit larges])
                (cond [(null? unit)
                       (error 'number->words "number too big: ~e" n)]
                      [(< n N) (step D (car unit) " ")]
                      [else (loop (* 1000 N) (* 1000 D) (cdr unit))]))]))

(define (first-cap s)
  (~a (string-upcase (substring s 0 1)) (substring s 1)))

(define (magic word [acc null])
  (if (equal? word "four")
      (string-join (reverse (cons "four is magic." acc)) ", \n")
      (let* ([word-len (string-length word)]
             [words (number->words word-len)])
        (magic words
               (cons (string-append word " is " words) acc)))))

(define (number-magic n)
  (first-cap (magic (number->words n))))

(for ([n (append (range 11)
                 '(-10 23 172 20140 100 130 999999 876000000
                       874143425855745733896030))])
  (displayln n)
  (displayln (number-magic n))
  (newline))


/* NetRexx*************************************************************
* Forward differences
* 18.08.2012 Walter Pachl derived from Rexx
**********************************************************************/
  Loop n=-1 To 11
    differences('90 47 58 29 22 32 55 5 55 73',n)
    End

  method differences(a,n) public static
  --arr=Rexx[11]                       -- array must be declared (zero based)
    arr=''                             -- alternative: indexed string
    m=a.words
    Select
      When n<0 Then Say 'n is negative:' n '<' 0
      When n>m Then Say 'n is too large:' n '>' m
      Otherwise Do
        Loop i=1 To m
          arr[i]=a.word(i)
          End
        Loop i = 1 to n
          t = arr[i]
          Loop j = i+1 to m
            u = arr[j]
            arr[j] = arr[j]-t
            t = u
            end
          end
        ol=''
        Loop i=n+1 to m
          ol=ol arr[i]
          End
        Say n ol
        End
      End


proc dif(s: seq[int]): seq[int] =
  result = newSeq[int](s.len-1)
  for i in 0..<s.high:
    result[i] = s[i+1] - s[i]

proc difn(s: seq[int]; n: int): seq[int] =
  if n > 0: difn(dif(s), n-1)
  else: s

const s = @[90, 47, 58, 29, 22, 32, 55, 5, 55, 73]
echo difn(s, 0)
echo difn(s, 1)
echo difn(s, 2)


DEFINE MAXSIZE="12"

INT ARRAY SinTab=[
  0 4 9 13 18 22 27 31 36 40 44 49 53 58 62 66 71 75 79 83
  88 92 96 100 104 108 112 116 120 124 128 132 136 139 143
  147 150 154 158 161 165 168 171 175 178 181 184 187 190
  193 196 199 202 204 207 210 212 215 217 219 222 224 226
  228 230 232 234 236 237 239 241 242 243 245 246 247 248
  249 250 251 252 253 254 254 255 255 255 256 256 256 256]

INT ARRAY xStack(MAXSIZE),yStack(MAXSIZE),angleStack(MAXSIZE)
BYTE ARRAY lenStack(MAXSIZE),dirStack(MAXSIZE)
BYTE stacksize=[0]

INT FUNC Sin(INT a)
  WHILE a<0 DO a==+360 OD
  WHILE a>360 DO a==-360 OD
  IF a<=90 THEN
    RETURN (SinTab(a))
  ELSEIF a<=180 THEN
    RETURN (SinTab(180-a))
  ELSEIF a<=270 THEN
    RETURN (-SinTab(a-180))
  ELSE
    RETURN (-SinTab(360-a))
  FI
RETURN (0)

INT FUNC Cos(INT a)
RETURN (Sin(a-90))

BYTE FUNC IsEmpty()
  IF stacksize=0 THEN
    RETURN (1)
  FI
RETURN (0)

BYTE FUNC IsFull()
  IF stacksize=MAXSIZE THEN
    RETURN (1)
  FI
RETURN (0)

PROC Push(INT x,y,angle BYTE len,dir)
  IF IsFull() THEN Break() FI
  xStack(stacksize)=x yStack(stacksize)=y
  angleStack(stacksize)=angle lenStack(stacksize)=len
  dirStack(stacksize)=dir
  stacksize==+1
RETURN

PROC Pop(INT POINTER x,y,angle BYTE POINTER len,dir)
  IF IsEmpty() THEN Break() FI
  stacksize==-1
  x^=xStack(stacksize) y^=yStack(stacksize)
  angle^=angleStack(stacksize) len^=lenStack(stacksize)
  dir^=dirStack(stacksize)
RETURN

PROC DrawTree(INT x,y,len,angle,leftAngle,rightAngle)
  BYTE depth,dir

  Plot(x,y)
  x==+Cos(angle)*len/256
  y==-Sin(angle)*len/256
  DrawTo(x,y)

  Push(x,y,angle,len,0)

  WHILE IsEmpty()=0
  DO
    Pop(@x,@y,@angle,@len,@dir)
    IF dir<2 THEN
      Push(x,y,angle,len,dir+1)
      IF dir=0 THEN
        angle==-leftAngle
      ELSE
        angle==+rightAngle
      FI

      len=13*len/16
      Plot(x,y)
      x==+Cos(angle)*len/256
      y==-Sin(angle)*len/256
      DrawTo(x,y)

      IF IsFull()=0 THEN
        Push(x,y,angle,len,0)
      FI
    FI
  OD

RETURN

PROC Main()
  BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6

  Graphics(8+16)
  Color=1
  COLOR1=$BA
  COLOR2=$B2

  DrawTree(140,191,40,110,35,15)

  DO UNTIL CH#$FF OD
  CH=$FF
RETURN


with Ada.Numerics.Elementary_Functions;

with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Video.Rectangles;
with SDL.Events.Events;

procedure Fractal_Tree is

   Width   : constant := 600;
   Height  : constant := 600;
   Level   : constant := 13;
   Length  : constant := 130.0;
   X_Start : constant := 475.0;
   Y_Start : constant := 580.0;
   A_Start : constant := -1.54;
   Angle_1 : constant := 0.10;
   Angle_2 : constant := 0.35;
   C_1     : constant := 0.71;
   C_2     : constant := 0.87;

   Window   : SDL.Video.Windows.Window;
   Renderer : SDL.Video.Renderers.Renderer;
   Event    : SDL.Events.Events.Events;

   procedure Draw_Tree (Level  : in Natural;
                        Length : in Float;
                        Angle  : in Float;
                        X, Y   : in Float)
   is
      use SDL;
      use Ada.Numerics.Elementary_Functions;
      Pi   : constant       := Ada.Numerics.Pi;
      X_2  : constant Float := X + Length * Cos (Angle, 2.0 * Pi);
      Y_2  : constant Float := Y + Length * Sin (Angle, 2.0 * Pi);
      Line : constant SDL.Video.Rectangles.Line_Segment
        := ((C.int (X), C.int (Y)), (C.int (X_2), C.int (Y_2)));
   begin
      if Level > 0 then
         Renderer.Set_Draw_Colour (Colour => (0, 220, 0, 255));
         Renderer.Draw (Line => Line);

         Draw_Tree (Level - 1, C_1 * Length, Angle + Angle_1, X_2, Y_2);
         Draw_Tree (Level - 1, C_2 * Length, Angle - Angle_2, X_2, Y_2);
      end if;
   end Draw_Tree;

   procedure Wait is
      use type SDL.Events.Event_Types;
   begin
      loop
         while SDL.Events.Events.Poll (Event) loop
            if Event.Common.Event_Type = SDL.Events.Quit then
               return;
            end if;
         end loop;
         delay 0.100;
      end loop;
   end Wait;

begin
   if not SDL.Initialise (Flags => SDL.Enable_Screen) then
      return;
   end if;

   SDL.Video.Windows.Makers.Create (Win      => Window,
                                    Title    => "Fractal tree",
                                    Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
                                    Size     => SDL.Positive_Sizes'(Width, Height),
                                    Flags    => 0);
   SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
   Renderer.Set_Draw_Colour ((0, 0, 0, 255));
   Renderer.Fill (Rectangle => (0, 0, Width, Height));

   Draw_Tree (Level, Length, A_Start, X_Start, Y_Start);
   Window.Update_Surface;

   Wait;
   Window.Finalize;
   SDL.Finalise;
end Fractal_Tree;


use Lingua::EN::Numbers; # Version 2.4.0 or higher

sub card ($n) { cardinal($n).subst(/','/, '', :g) }

sub magic (Int $int is copy) {
    my $string;
    loop {
       $string ~= "{ card($int) } is ";
       if $int = ($int == 4) ?? 0 !! card($int).chars {
           $string ~= "{ card($int) }, "
       } else {
           $string ~= "magic.\n";
           last
       }
   }
   $string.tc
}

.&magic.say for 0, 4, 6, 11, 13, 75, 337, -164, 9876543209, 2**256;