BEGIN
    # task 1 #
    BEGIN
        PR precision 32 PR
        print( ( " 32 digit REAL numbers", newline ) );
        [ 1 : 100 ]LONG LONG REAL v;
        v[ 1 ] := 2;
        v[ 2 ] := -4;
        FOR n FROM 3 TO UPB v DO v[ n ] := 111 - ( 1130 / v[ n - 1 ] ) + ( 3000 / ( v[ n - 1 ] * v[ n - 2 ] ) ) OD;
        FOR n FROM  3 TO  8       DO print( ( "n = ", whole( n, 3 ), " ", fixed( v[ n ], -22, 16 ), newline ) ) OD;
        FOR n FROM 20 BY 10 TO 50 DO print( ( "n = ", whole( n, 3 ), " ", fixed( v[ n ], -22, 16 ), newline ) ) OD;
        print( ( "n = 100 ", fixed( v[ 100 ], -22, 16 ), newline ) )
    END;
    BEGIN
        PR precision 120 PR
        print( ( "120 digit REAL numbers", newline ) );
        [ 1 : 100 ]LONG LONG REAL v;
        v[ 1 ] := 2;
        v[ 2 ] := -4;
        FOR n FROM 3 TO UPB v DO v[ n ] := 111 - ( 1130 / v[ n - 1 ] ) + ( 3000 / ( v[ n - 1 ] * v[ n - 2 ] ) ) OD;
        print( ( "n = 100 ", fixed( v[ 100 ], -22, 16 ), newline ) )
    END;
    print( ( newline ) );
    # task 2 #
    BEGIN
        print( ( "single precision REAL numbers...", newline ) );
        REAL chaotic balance := exp( 1 ) - 1;
        print( ( "initial chaotic balance: ", fixed( chaotic balance, -22, 16 ), newline ) );
        FOR i FROM 1 TO 25 DO ( chaotic balance *:= i ) -:= 1 OD;
        print( ( "25 year chaotic balance: ", fixed( chaotic balance, -22, 16 ), newline ) )
    END;
    BEGIN
        print( ( "double precision REAL numbers...", newline ) );
        LONG REAL chaotic balance := long exp( 1 ) - 1;
        print( ( "initial chaotic balance: ", fixed( chaotic balance, -22, 16 ), newline ) );
        FOR i FROM 1 TO 25 DO ( chaotic balance *:= i ) -:= 1 OD;
        print( ( "25 year chaotic balance: ", fixed( chaotic balance, -22, 16 ), newline ) )
    END;
    BEGIN
        PR precision 32 PR
        print( ( "        32 digit REAL numbers...", newline ) );
        LONG LONG REAL chaotic balance := long long exp( 1 ) - 1;
        print( ( "initial chaotic balance: ", fixed( chaotic balance, -22, 16 ), newline ) );
        FOR i FROM 1 TO 25 DO ( chaotic balance *:= i ) -:= 1 OD;
        print( ( "25 year chaotic balance: ", fixed( chaotic balance, -22, 16 ), newline ) )
    END
END


BEGIN {
    do_task1()
    do_task2()
    do_task3()
    exit
}

function do_task1(){
    print "Task 1"
    v[1] = 2
    v[2] = -4
    for (n=3; n<=100; n++) v[n] = 111 - 1130 / v[n-1] + 3000 / (v[n-1] * v[n-2])

    for (i=3; i<=8; i++) print_results(i)
    print_results(20)
    print_results(30)
    print_results(50)
    print_results(100)
}

# This works because all awk variables are global, except when declared locally
function print_results(n){
    printf("n = %d\t%20.16f\n", n, v[n])
}

# This function doesn't need any parameters; declaring balance and i in the function parameters makes them local
function do_task2(      balance, i){
    balance[0] = exp(1)-1
    for (i=1; i<=25; i++) balance[i] = balance[i-1]*i-1
    printf("\nTask 2\nBalance after 25 years: $%12.10f", balance[25])
}

function do_task3(      a, b, f_ab){
    a = 77617
    b = 33096

    f_ab = 333.75 * b^6 + a^2 * (11*a^2*b^2 - b^6 - 121*b^4 - 2) + 5.5*b^8 + a/(2*b)
    printf("\nTask 3\nf(%6.12f, %6.12f) = %10.24f", a, b, f_ab)
}


#include<stdio.h>
#include<gmp.h>

void firstCase(){
	mpf_t a,b,c;

	mpf_inits(a,b,c,NULL);

	mpf_set_str(a,"0.1",10);
	mpf_set_str(b,"0.2",10);
	mpf_add(c,a,b);

	gmp_printf("\n0.1 + 0.2 = %.*Ff",20,c);
}

void pathologicalSeries(){
	int n;
	mpf_t v1, v2, vn, a1, a2, a3, t2, t3, prod;

	mpf_inits(v1,v2,vn, a1, a2, a3, t2, t3, prod,NULL);

	mpf_set_str(v1,"2",10);
	mpf_set_str(v2,"-4",10);
	mpf_set_str(a1,"111",10);
	mpf_set_str(a2,"1130",10);
	mpf_set_str(a3,"3000",10);

	for(n=3;n<=100;n++){
		mpf_div(t2,a2,v2);
		mpf_mul(prod,v1,v2);
		mpf_div(t3,a3,prod);
		mpf_add(vn,a1,t3);
		mpf_sub(vn,vn,t2);

		if((n>=3&&n<=8) || n==20 || n==30 || n==50 || n==100){
			gmp_printf("\nv_%d : %.*Ff",n,(n==3)?1:(n>=4&&n<=7)?6:(n==8)?7:(n==20)?16:(n==30)?24:(n==50)?40:78,vn);
		}

		mpf_set(v1,v2);
		mpf_set(v2,vn);
	}
}

void healthySeries(){
	int n;

	mpf_t num,denom,result;
	mpq_t v1, v2, vn, a1, a2, a3, t2, t3, prod;

	mpf_inits(num,denom,result,NULL);
	mpq_inits(v1,v2,vn, a1, a2, a3, t2, t3, prod,NULL);

	mpq_set_str(v1,"2",10);
	mpq_set_str(v2,"-4",10);
	mpq_set_str(a1,"111",10);
	mpq_set_str(a2,"1130",10);
	mpq_set_str(a3,"3000",10);

	for(n=3;n<=100;n++){
		mpq_div(t2,a2,v2);
		mpq_mul(prod,v1,v2);
		mpq_div(t3,a3,prod);
		mpq_add(vn,a1,t3);
		mpq_sub(vn,vn,t2);

		if((n>=3&&n<=8) || n==20 || n==30 || n==50 || n==100){
			mpf_set_z(num,mpq_numref(vn));
			mpf_set_z(denom,mpq_denref(vn));
			mpf_div(result,num,denom);

			gmp_printf("\nv_%d : %.*Ff",n,(n==3)?1:(n>=4&&n<=7)?6:(n==8)?7:(n==20)?16:(n==30)?24:(n==50)?40:78,result);
		}

		mpq_set(v1,v2);
		mpq_set(v2,vn);
	}
}

int main()
{
	mpz_t rangeProd;

	firstCase();

	printf("\n\nPathological Series : ");

	pathologicalSeries();

	printf("\n\nNow a bit healthier : ");

	healthySeries();

	return 0;
}


#define USE_BIGRATIONAL
#define BANDED_ROWS
#define INCREASED_LIMITS

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Numerics;
using Numerics;

using static Common;
using static Task1;
using static Task2;
using static Task3;

#if !USE_BIGRATIONAL
// Mock structure to make test code work.
struct BigRational
{
    public override string ToString() => "NOT USING BIGRATIONAL";
    public static explicit operator decimal(BigRational value) => -1;
}
#endif

static class Common
{
    public const string FMT_STR = "{0,4}   {1,-15:G9}   {2,-24:G17}   {3,-32}   {4,-32}";
    public static string Headings { get; } =
        string.Format(
            CultureInfo.InvariantCulture,
            FMT_STR,
            new[] { "N", "Single", "Double", "Decimal", "BigRational (rounded as Decimal)" });

    [Conditional("BANDED_ROWS")]
    static void SetConsoleFormat(int n)
    {
        if (n % 2 == 0)
        {
            Console.BackgroundColor = ConsoleColor.Black;
            Console.ForegroundColor = ConsoleColor.White;
        }
        else
        {
            Console.BackgroundColor = ConsoleColor.White;
            Console.ForegroundColor = ConsoleColor.Black;
        }
    }

    public static string FormatOutput(int n, (float sn, double db, decimal dm, BigRational br) x)
    {
        SetConsoleFormat(n);
        return string.Format(CultureInfo.CurrentCulture, FMT_STR, n, x.sn, x.db, x.dm, (decimal)x.br);
    }

    static void Main()
    {
        WrongConvergence();

        Console.WriteLine();
        ChaoticBankSociety();

        Console.WriteLine();
        SiegfriedRump();

        SetConsoleFormat(0);
    }
}


(def converge-to-six ((fn task1 [a b] (lazy-seq (cons a (task1 b (+ (- 111 (/ 1130 b)) (/ 3000 (* b a))))))) 2 -4))
(def values [3 4 5 6 7 8 20 30 50 100])
; print decimal values:
(pprint (sort (zipmap values (map double (map #(nth converge-to-six (dec %)) values)))))
; print rational values:
(pprint (sort (zipmap values (map #(nth converge-to-six (dec %)) values))))


program Pathological_floating_point_problems;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  Velthuis.BigIntegers,
  Velthuis.BigRationals,
  Velthuis.BigDecimals;

type
  TBalance = record
    e, d: BigInteger;
  end;

procedure Sequence(Precision: Integer);
var
  v, v1, c111, c1130, c3000, t2, t3: BigRational;
  n: integer;
begin
  BigDecimal.DefaultPrecision := Precision;
  v1 := 2;
  v := -4;
  n := 2;
  c111 := BigRational(111);
  c1130 := BigRational(1130);
  c3000 := BigRational(3000);

  var r :=
    function(): BigRational
    begin
      t3 := v * v1;
      t3 := BigRational.Create(BigDecimal.Divide(c3000, t3));
      t2 := BigRational.Create(BigDecimal.Divide(c1130, v));
      result := c111 - t2;
      result := result + t3;
    end;

  writeln('  n  sequence value');

  for var x in [3, 4, 5, 6, 7, 8, 20, 30, 50, 100] do
  begin
    while n < x do
    begin
      var tmp := BigRational.Create(v);
      v := BigRational.Create(r());
      v1 := BigRational.Create(tmp);
      inc(n);
    end;

    var f := double(v);
    writeln(format('%3d %19.16f', [n, f]));
  end;
end;

procedure Bank();
var
  balance: TBalance;
  m, one, ef, df: BigInteger;
  e, b: BigDecimal;
begin
  balance.e := 1;
  balance.d := -1;
  one := BigInteger.One;

  for var y := 1 to 25 do
  begin
    m := y;
    balance.e := m * balance.e;
    balance.d := m * balance.d;
    balance.d := balance.d - one;
  end;

  e := BigDecimal.Create('2.71828182845904523536028747135');

  ef := balance.e;
  df := balance.d;

  b := e * ef;
  b := b + df;

  writeln(format('Bank balance after 25 years: $%.2f', [b.AsDouble]));
end;

function f(a, b: Double): Double;
var
  a1, a2, b1, b2, b4, b6, b8, two, t1, t21, t2, t3, t4, t23: BigDecimal;
begin
  var fp :=
    function(x: double): BigDecimal
    begin
      Result := BigDecimal.Create(x);
    end;

  a1 := fp(a);
  b1 := fp(b);
  a2 := a1 * a1;
  b2 := b1 * b1;
  b4 := b2 * b2;
  b6 := b2 * b4;
  b8 := b4 * b4;

  two := fp(2);
  t1 := fp(333.75);
  t1 := t1 * b6;
  t21 := fp(11);
  t21 := t21 * a2 * b2;
  t23 := fp(121);
  t23 := t23 * b4;

  t2 := t21 - b6;
  t2 := (t2 - t23) - two;
  t2 := a2 * t2;

  t3 := fp(5.5);
  t3 := t3 * b8;

  t4 := two * b1;
  t4 := a1 / t4;

  var s := t1 + t2;
  s := s + t3;
  s := s + t4;
  result := s.AsDouble;
end;

procedure Rump();
var
  a, b: Double;
begin
  a := 77617;
  b := 33096;
  writeln(format('Rump f(%g, %g): %g', [a, b, f(a, b)]));
end;

{ TBigRationalHelper }

begin
  for var Precision in [100, 200] do
  begin
    writeln(#10'Precision: ', Precision);
    sequence(Precision);
    bank();
    rump();
  end;

  readln;
end.


USING: formatting fry io kernel locals math math.functions
math.ranges sequences ;
IN: rosetta-code.pathological

: next2 ( x y -- y z )
    swap dupd dupd '[ 111 1130 _ / - 3000 _ _ * / + ] call ;

: pathological-sequence ( -- seq )
    2 -4 100 [ next2 dup ] replicate 2nip { 0 2 -4 } prepend ;

: show-sequence ( -- )
    { 3 4 5 6 7 8 20 30 50 100 } dup pathological-sequence nths
    [ "n = %-3d %21.16f\n" printf ] 2each ;

CONSTANT: e 106246577894593683/39085931702241241
: balance ( n -- x ) [1,b] e 1 - [ * 1 - ] reduce ;

:: f ( a b -- x )
    333+3/4 b 6 ^ * 11 a sq b sq * * b 6 ^ - b 4 ^ 121 * - 2 - a
    sq * b 8 ^ 5+1/2 * a 2 b * / + + + ;

: pathological-demo ( -- )
    "Task 1 - Sequence convergence:" print show-sequence nl

    "Task 2 - Chaotic Bank fund after 25 years:" print
    25 balance "%.16f\n" printf nl

    "Task 3 - Siegfried Rump's example:" print
    77617 33096 f "77617 33096 f = %.16f\n" printf ;

MAIN: pathological-demo


      SUBROUTINE MULLER
       REAL*4 VN,VNL1,VNL2	!The exact precision and dynamic range
       REAL*8 WN,WNL1,WNL2	!Depends on the format's precise usage of bits.
       INTEGER I		!A stepper.
        WRITE (6,1)		!A heading.
    1   FORMAT ("Muller's sequence should converge to six...",/
     1   "  N     Single      Double")
        VNL1 = 2; VN = -4	!Initialise for N = 2.
        WNL1 = 2; WN = -4	!No fractional parts yet.
        DO I = 3,36			!No point going any further.
          VNL2 = VNL1; VNL1 = VN		!Shuffle the values along one place.
          WNL2 = WNL1; WNL1 = WN		!Ready for the next term's calculation.
          VN = 111 - 1130/VNL1 + 3000/(VNL1*VNL2)	!Calculate the next term.
          WN = 111 - 1130/WNL1 + 3000/(WNL1*WNL2)	!In double precision.
          WRITE (6,2) I,VN,WN			!Show both.
    2     FORMAT (I3,F12.7,F21.16)		!With too many fractional digits.
        END DO				!On to the next term.
      END SUBROUTINE MULLER	!That was easy. Too bad the results are wrong.

      SUBROUTINE CBS		!The Chaotic Bank Society.
       INTEGER YEAR	!A stepper.
       REAL*4 V		!The balance.
       REAL*8 W		!In double precision as well.
        V = 1; W = 1		!Initial values, without dozy 1D0 stuff.
        V = EXP(V) - 1		!Actual initial value desired is e - 1..,
        W = EXP(W) - 1		!This relies on double-precision W selecting DEXP.
        WRITE (6,1)		!Here we go.
    1   FORMAT (///"The Chaotic Bank Society in action..."/"Year")
        WRITE (6,2) 0,V,W	!Show the initial deposit.
    2   FORMAT (I3,F16.7,F28.16)
        DO YEAR = 1,25		!Step through some years.
          V = V*YEAR - 1	!The specified procedure.
          W = W*YEAR - 1	!The compiler handles type conversions.
          WRITE (6,2) YEAR,V,W	!The current balance.
        END DO			!On to the following year.
      END SUBROUTINE CBS	!Madness!

      REAL*4 FUNCTION SR4(A,B)	!Siegfried Rump's example function of 1988.
       REAL*4 A,B
        SR4 = 333.75*B**6
     1      + A**2*(11*A**2*B**2 - B**6 - 121*B**4 - 2)
     2      + 5.5*B**8 + A/(2*B)
      END FUNCTION SR4
      REAL*8 FUNCTION SR8(A,B)	!Siegfried Rump's example function.
       REAL*8 A,B
        SR8 = 333.75*B**6	!.75 is exactly represented in binary.
     1      + A**2*(11*A**2*B**2 - B**6 - 121*B**4 - 2)
     2      + 5.5*B**8 + A/(2*B)!.5 is exactly represented in binary.
      END FUNCTION SR8

      PROGRAM POKE
      REAL*4 V	!Some example variables.
      REAL*8 W	!Whose type goes to the inquiry function.
      WRITE (6,1) RADIX(V),DIGITS(V),"single",DIGITS(W),"double"
    1   FORMAT ("Floating-point arithmetic is conducted in base ",I0,/
     1   2(I3," digits for ",A," precision",/))
      WRITE (6,*) "Single precision limit",HUGE(V)
      WRITE (6,*) "Double precision limit",HUGE(W)
      WRITE (6,*)

      CALL MULLER

      CALL CBS

      WRITE (6,10)
   10 FORMAT (///"Evaluation of Siegfried Rump's function of 1988",
     1 " where F(77617,33096) = -0.827396059946821")
      WRITE (6,*) "Single precision:",SR4(77617.0,33096.0)
      WRITE (6,*) "Double precision:",SR8(77617.0D0,33096.0D0)	!Must match the types.
      END


' FB 1.05.0 Win64

' As FB's native types have only 64 bit precision at most we need to use the
' C library, GMP v6.1.0, for arbitrary precision arithmetic

#Include Once "gmp.bi"
mpf_set_default_prec(640) '' 640 bit precision, enough for this exercise

Function v(n As UInteger, prev As __mpf_struct, prev2 As __mpf_struct) As __mpf_struct
  Dim As __mpf_struct a, b, c
  mpf_init(@a) : mpf_init(@b) : mpf_init(@c)
  If n = 0 Then mpf_set_ui(@a, 0UL)
  If n = 1 Then mpf_set_ui(@a, 2UL)
  If n = 2 Then mpf_set_si(@a, -4L)
  If n < 3 Then Return a
  mpf_ui_div(@a, 1130UL, @prev)
  mpf_mul(@b, @prev, @prev2)
  mpf_ui_div(@c, 3000UL, @b)
  mpf_ui_sub(@b, 111UL, @a)
  mpf_add(@a, @b, @c)
  mpf_clear(@b)
  mpf_clear(@c)
  Return a
End Function

Function f(a As Double, b As Double) As __mpf_Struct
  Dim As __mpf_struct temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8
  mpf_init(@temp1) : mpf_init(@temp2) : mpf_init(@temp3) : mpf_init(@temp4)
  mpf_init(@temp5) : mpf_init(@temp6) : mpf_init(@temp7) : mpf_init(@temp8)
  mpf_set_d(@temp1, a)               '' a
  mpf_set_d(@temp2, b)               '' b
  mpf_set_d(@temp3, 333.75)          '' 333.75
  mpf_pow_ui(@temp4, @temp2, 6UL)    '' b ^ 6
  mpf_mul(@temp3, @temp3, @temp4)    '' 333.75 * b^6
  mpf_pow_ui(@temp5, @temp1, 2UL)    '' a^2
  mpf_pow_ui(@temp6, @temp2, 2UL)    '' b^2
  mpf_mul_ui(@temp7, @temp5, 11UL)   '' 11 * a^2
  mpf_mul(@temp7, @temp7, @temp6)    '' 11 * a^2 * b^2
  mpf_sub(@temp7, @temp7, @temp4)    '' 11 * a^2 * b^2 - b^6
  mpf_pow_ui(@temp4, @temp2, 4UL)    '' b^4
  mpf_mul_ui(@temp4, @temp4, 121UL)  '' 121 * b^4
  mpf_sub(@temp7, @temp7, @temp4)    '' 11 * a^2 * b^2 - b^6 - 121 * b^4
  mpf_sub_ui(@temp7, @temp7, 2UL)    '' 11 * a^2 * b^2 - b^6 - 121 * b^4 - 2
  mpf_mul(@temp7, @temp7, @temp5)    '' (11 * a^2 * b^2 - b^6 - 121 * b^4 - 2) * a^2
  mpf_add(@temp3, @temp3, @temp7)    '' 333.75 * b^6 + (11 * a^2 * b^2 - b^6 - 121 * b^4 - 2) * a^2
  mpf_set_d(@temp4, 5.5)             '' 5.5
  mpf_pow_ui(@temp5, @temp2, 8UL)    '' b^8
  mpf_mul(@temp4, @temp4, @temp5)    '' 5.5 * b^8
  mpf_add(@temp3, @temp3, @temp4)    '' 333.75 * b^6 + (11 * a^2 * b^2 - b^6 - 121 * b^4 - 2) * a^2 + 5.5 * b^8
  mpf_mul_ui(@temp4, @temp2, 2UL)    '' 2 * b
  mpf_div(@temp5, @temp1, @temp4)    '' a / (2 * b)
  mpf_add(@temp3, @temp3, @temp5)    '' 333.75 * b^6 + (11 * a^2 * b^2 - b^6 - 121 * b^4 - 2) * a^2 + 5.5 * b^8 + a / (2 * b)
  mpf_clear(@temp1) : mpf_clear(@temp2) : mpf_clear(@temp4) : mpf_clear(@temp5)
  mpf_clear(@temp6) : mpf_clear(@temp7) : mpf_clear(@temp8)
  Return temp3
End Function

Dim As Zstring * 60 z
Dim As __mpf_struct result, prev, prev2
' We cache the two previous results to avoid recursive calls to v
For i As Integer = 1 To 100
  result = v(i, prev, prev2)
  If (i >= 3 AndAlso i <= 8) OrElse i = 20 OrElse i = 30 OrElse i = 50 OrElse i = 100 Then
    gmp_sprintf(@z,"%53.50Ff",@result) '' express result to 50 decimal places
    Print "n ="; i , z
  End If
  prev2 = prev
  prev = result
Next

mpf_clear(@prev) : mpf_clear(@prev2) '' note : prev = result

Dim As __mpf_struct e, balance, ii, temp
mpf_init(@e) : mpf_init(@balance) : mpf_init(@ii) : mpf_init(@temp)
mpf_set_str(@e, "2.71828182845904523536028747135266249775724709369995", 10) '' e to 50 decimal places
mpf_sub_ui(@balance, @e, 1UL)

For i As ULong = 1 To 25
  mpf_set_ui(@ii, i)
  mpf_mul(@temp, @balance, @ii)
  mpf_sub_ui(@balance, @temp, 1UL)
Next

Print
Print "Chaotic B/S balance after 25 years : ";
gmp_sprintf(@z,"%.16Ff",@balance) '' express balance to 16 decimal places
Print z
mpf_clear(@e) : mpf_clear(@balance) : mpf_clear(@ii) : mpf_clear(@temp)

Print
Dim rump As __mpf_struct
rump = f(77617.0, 33096.0)
gmp_sprintf(@z,"%.16Ff", @rump) '' express rump to 16 decimal places
Print "f(77617.0, 33096.0) = "; z

Print
Print "Press any key to quit"
Sleep


package main

import (
    "fmt"
    "math/big"
)

func main() {
    sequence()
    bank()
    rump()
}

func sequence() {
    // exact computations using big.Rat
    var v, v1 big.Rat
    v1.SetInt64(2)
    v.SetInt64(-4)
    n := 2
    c111 := big.NewRat(111, 1)
    c1130 := big.NewRat(1130, 1)
    c3000 := big.NewRat(3000, 1)
    var t2, t3 big.Rat
    r := func() (vn big.Rat) {
        vn.Add(vn.Sub(c111, t2.Quo(c1130, &v)), t3.Quo(c3000, t3.Mul(&v, &v1)))
        return
    }
    fmt.Println("  n  sequence value")
    for _, x := range []int{3, 4, 5, 6, 7, 8, 20, 30, 50, 100} {
        for ; n < x; n++ {
            v1, v = v, r()
        }
        f, _ := v.Float64()
        fmt.Printf("%3d %19.16f\n", n, f)
    }
}

func bank() {
    // balance as integer multiples of e and whole dollars using big.Int
    var balance struct{ e, d big.Int }
    // initial balance
    balance.e.SetInt64(1)
    balance.d.SetInt64(-1)
    // compute balance over 25 years
    var m, one big.Int
    one.SetInt64(1)
    for y := 1; y <= 25; y++ {
        m.SetInt64(int64(y))
        balance.e.Mul(&m, &balance.e)
        balance.d.Mul(&m, &balance.d)
        balance.d.Sub(&balance.d, &one)
    }
    // sum account components using big.Float
    var e, ef, df, b big.Float
    e.SetPrec(100).SetString("2.71828182845904523536028747135")
    ef.SetInt(&balance.e)
    df.SetInt(&balance.d)
    b.Add(b.Mul(&e, &ef), &df)
    fmt.Printf("Bank balance after 25 years: $%.2f\n", &b)
}

func rump() {
    a, b := 77617., 33096.
    fmt.Printf("Rump f(%g, %g): %g\n", a, b, f(a, b))
}

func f(a, b float64) float64 {
    // computations done with big.Float with enough precision to give
    // a correct answer.
    fp := func(x float64) *big.Float { return big.NewFloat(x).SetPrec(128) }
    a1 := fp(a)
    b1 := fp(b)
    a2 := new(big.Float).Mul(a1, a1)
    b2 := new(big.Float).Mul(b1, b1)
    b4 := new(big.Float).Mul(b2, b2)
    b6 := new(big.Float).Mul(b2, b4)
    b8 := new(big.Float).Mul(b4, b4)
    two := fp(2)
    t1 := fp(333.75)
    t1.Mul(t1, b6)
    t21 := fp(11)
    t21.Mul(t21.Mul(t21, a2), b2)
    t23 := fp(121)
    t23.Mul(t23, b4)
    t2 := new(big.Float).Sub(t21, b6)
    t2.Mul(a2, t2.Sub(t2.Sub(t2, t23), two))
    t3 := fp(5.5)
    t3.Mul(t3, b8)
    t4 := new(big.Float).Mul(two, b1)
    t4.Quo(a1, t4)
    s := new(big.Float).Add(t1, t2)
    f64, _ := s.Add(s.Add(s, t3), t4).Float64()
    return f64
}


import java.math.BigDecimal;
import java.math.RoundingMode;

public class FPProblems {
    public static void wrongConvergence() {
        int[] INDEXES = new int[] { 3, 4, 5, 6, 7, 8, 20, 30, 50, 100 };

        // Standard 64-bit floating point
        double[] fpValues = new double[100];
        fpValues[0] = 2.0;
        fpValues[1] = -4.0;
        for (int i = 2; i < fpValues.length; i++) {
            fpValues[i] = 111.0 - 1130.0 / fpValues[i - 1] + 3000.0 / (fpValues[i - 1] * fpValues[i - 2]);
        }

        // Using rational representation
        BigRational[] brValues = new BigRational[100];
        brValues[0] = BigRational.valueOf(2);
        brValues[1] = BigRational.valueOf(-4);
        for (int i = 2; i < brValues.length; i++) {
            // Using intermediate values for better readability
            BigRational clause2 = BigRational.valueOf(1130).divide(brValues[i - 1]);
            BigRational clause3 = BigRational.valueOf(3000).divide(brValues[i - 1].multiply(brValues[i - 2]));
            brValues[i] = BigRational.valueOf(111).subtract(clause2).add(clause3);
        }

        System.out.println("Wrong Convergence Sequence");
        for (int n : INDEXES) {
            BigDecimal value = brValues[n - 1].toBigDecimal(16, RoundingMode.HALF_UP);
            System.out.println("  For index " + n + ", FP value is " + fpValues[n - 1] + ", and rounded BigRational value is " + value.toPlainString());
        }

        return;
    }

    public static void chaoticBankSociety() {
        System.out.println("Chaotic Bank Society");
        double balance = Math.E - 1.0;

        // Calculate e using first 1000 terms of the reciprocal of factorials formula
        BigRational e = BigRational.ONE;
        BigRational d = BigRational.ONE;
        for (int i = 1; i < 1000; i++) {
            d = d.multiply(BigRational.valueOf(i));
            e = e.add(d.reciprocal());
        }
        System.out.println("DEBUG: e=" + e.toBigDecimal(100, RoundingMode.HALF_UP).toPlainString());

        // Alternatively,
        // BigRational e = BigRational.valueOf(Math.E);

        BigRational brBalance = e.subtract(BigRational.ONE);
        for (int year = 1; year <= 25; year++) {
            balance = (balance * year) - 1.0;
            brBalance = brBalance.multiply(BigRational.valueOf(year)).subtract(BigRational.ONE);
            BigDecimal bdValue = brBalance.toBigDecimal(16, RoundingMode.HALF_UP);
            System.out.println("  Year=" + year + ", FP balance=" + balance + ", BigRational balance=" + bdValue.toPlainString());
        }
    }

    public static void siegfriedRump() {
        System.out.println("Siegfried Rump formula");
        double fpValue;
        {
            double a = 77617.0;
            double b = 33096.0;
            fpValue = 333.75 * Math.pow(b, 6) + a * a * (11.0 * a * a * b * b - Math.pow(b, 6) - 121.0 * Math.pow(b, 4) - 2.0) + 5.5 * Math.pow(b, 8) + a / (2.0 * b);
        }

        BigRational brValue;
        {
            BigRational a = BigRational.valueOf(77617);
            BigRational b = BigRational.valueOf(33096);
            BigRational clause1 = BigRational.valueOf(333.75).multiply(b.pow(6));
            BigRational clause2a = BigRational.valueOf(11).multiply(a).multiply(a).multiply(b).multiply(b);
            BigRational clause2b = b.pow(6).add(BigRational.valueOf(121).multiply(b.pow(4))).add(BigRational.valueOf(2));
            BigRational clause2 = a.multiply(a).multiply(clause2a.subtract(clause2b));
            BigRational clause3 = BigRational.valueOf(5.5).multiply(b.pow(8));
            BigRational clause4 = a.divide(b.multiply(BigRational.valueOf(2)));
            brValue = clause1.add(clause2).add(clause3).add(clause4);
        }

        System.out.println("  FP value is " + fpValue);
        System.out.println("  BigRational rounded value is " + brValue.toBigDecimal(64, RoundingMode.HALF_UP).toPlainString());
        System.out.println("  BigRational full value is " + brValue.toString());
    }

    public static void main(String... args) {
        wrongConvergence();

        System.out.println();
        chaoticBankSociety();

        System.out.println();
        siegfriedRump();
    }
}


# Input: the value at which to compute v
def v:
  # Input: cache
  # Output: updated cache
  def v_(n):
    (n|tostring) as $s
    | . as $cache
    | if ($cache | has($s)) then .
      else if n == 1 then $cache["1"] = 2
           elif n == 2 then $cache["2"] = -4
           else ($cache | v_(n-1) | v_(n - 2)) as $new
           | $new[(n-1)|tostring] as $x
 	   | $new[(n-2)|tostring] as $y
           | $new + {($s):  ((111 - (1130 / $x) + (3000 / ($x * $y)))) }
	   end
       end;
    . as $m | {} | v_($m) | .[($m|tostring)] ;


using Printf
# arbitrary precision
setprecision(2000)

# Task 1
function seq(n)
    len = maximum(n)
    r = Vector{BigFloat}(len)
    r[1] = 2
    if len > 1 r[2] = -4 end

    for i in 3:len
        r[i] = 111 - 1130 / r[i-1] + 3000 / (r[i-1] * r[i-2])
    end

    return r[n]
end

n = [1, 2, 3, 5, 10, 100]
v = seq(n)
println("Task 1 - Sequence convergence:\n", join((@sprintf("v%-3i = %23.20f", i, s) for (i, s) in zip(n, v)), '\n'))

# Task 2: solution with big float (precision can be set with setprecision function)
function chaoticbankfund(years::Integer)
    balance = big(e) - 1
    for y in 1:years
        balance = (balance * y) - 1
    end

    return balance
end

println("\nTask 2 - Chaotic Bank fund after 25 years:\n", @sprintf "%.20f" chaoticbankfund(25))

# Task 3: solution with big float
f(a::Union{BigInt,BigFloat}, b::Union{BigInt,BigFloat}) =
    333.75b ^ 6 + a ^ 2 * ( 11a ^ 2 * b ^ 2 - b ^ 6 - 121b ^ 4 - 2 ) + 5.5b ^ 8 + a / 2b

println("\nTask 3 - Siegfried Rump's example:\nf(77617.0, 33096.0) = ", @sprintf "%.20f" f(big(77617.0), big(33096.0)))


// version 1.0.6

import java.math.*

const val LIMIT = 100

val con480  = MathContext(480)
val bigTwo =  BigDecimal(2)
val bigE    = BigDecimal("2.71828182845904523536028747135266249775724709369995") // precise enough!

fun main(args: Array<String>) {
    // v(n) sequence task
    val c1 = BigDecimal(111)
    val c2 = BigDecimal(1130)
    val c3 = BigDecimal(3000)
    var v1 = bigTwo
    var v2 = BigDecimal(-4)
    var v3:  BigDecimal
    for (i in 3 .. LIMIT) {
        v3 = c1 - c2.divide(v2, con480) + c3.divide(v2 * v1, con480)
        println("${"%3d".format(i)} : ${"%19.16f".format(v3)}")
        v1 = v2
        v2 = v3
    }

    // Chaotic Building Society task
    var balance = bigE - BigDecimal.ONE
    for (year in 1..25) balance = balance.multiply(BigDecimal(year), con480) - BigDecimal.ONE
    println("\nBalance after 25 years is ${"%18.16f".format(balance)}")

    // Siegfried Rump task
    val a  = BigDecimal(77617)
    val b  = BigDecimal(33096)
    val c4 = BigDecimal("333.75")
    val c5 = BigDecimal(11)
    val c6 = BigDecimal(121)
    val c7 = BigDecimal("5.5")
    var f  = c4 * b.pow(6, con480) + c7 * b.pow(8, con480) + a.divide(bigTwo * b, con480)
    val c8 = c5 * a.pow(2, con480) * b.pow(2, con480) - b.pow(6, con480) - c6 * b.pow(4, con480) - bigTwo
    f += c8 * a.pow(2, con480)
    println("\nf(77617.0, 33096.0) is ${"%18.16f".format(f)}")
}


import math, strutils, strformat
import decimal
import bignum

####################################################################################################
# Utilities.

proc format[T: DecimalType|Rat](val: T; intLen, fractLen: Positive): string =
  ## Format a decimal or a rational with "intLen" integer digits and "fractLen"
  ## fractional digits.
  let s = when T is DecimalType: ($val).split('.')
          else: ($val.toFloat).split('.')

  result = s[0].align(intLen) & '.'
  if s[1].len < fractLen:
    result.add s[1].alignLeft(fractLen, '0')
  else:
    result.add s[1][0..<fractLen]

proc `^`(a: Rat; b: Natural): Rat =
  ## Missing exponentiation operator for rationals.
  ## Adaptation of operator for floats.
  case b
  of 0: result = newRat(1)
  of 1: result = a
  of 2: result = a * a
  of 3: result = a * a * a
  else:
    var (a, b) = (a.clone, b)
    result = newRat(1)
    while true:
      if (b and 1) != 0:
        result *= a
      b = b shr 1
      if b == 0: break
      a *= a

####################################################################################################
# Task 1.

proc v[T: float|DecimalType|Rat](n: Positive): seq[T] =
  ## Return the "n" first values for sequence "Vn".
  var (v1, v2) = when T is float: (2.0, -4.0)
                 elif T is Rat: (newRat(2), newRat(-4))
                 else: (newDecimal(2), newDecimal(-4))

  result.add default(T)   # Dummy value to start at index one.
  result.add v1
  result.add v2
  for _ in 3..n:
    # Need to change evaluation order to avoid a bug with rationals.
    result.add 3000 / (result[^1] * result[^2]) - 1130 / result[^1] + 111

setPrec(130)  # Default precision is not sufficient.

let vfloat = v[float](100)
let vdecimal = v[DecimalType](100)
let vrational = v[Rat](100)

echo "Task 1"
echo "  n          v(n) float            v(n) decimal           v(n) rational"
for n in [3, 4, 5, 6, 7, 8, 20, 30, 50, 100]:
  echo &"{n:>3}    {vfloat[n]:>20.16f}   {vdecimal[n].format(3, 16)}   {vrational[n].format(3, 16)}"

####################################################################################################
# Task 2.

proc balance[T: float|DecimalType|Rat](): T =
  ## Return the balance after 25 years.
  result = when T is float: E - 1
           elif T is DecimalType: exp(newDecimal(1)) - 1
           else: newInt("17182818284590452353602874713526624977572470") /
                 newInt("10000000000000000000000000000000000000000000")

  var n = when T is float: 1.0 else: 1
  while n <= 25:
    result = result * n - 1
    n += 1

echo "\nTask 2."
echo "Balance after 25 years (float):     ", (&"{balance[float]():.16f}")[0..17]
echo "Balance after 25 years (decimal):   ", balance[DecimalType]().format(1, 16)
echo "Balance after 25 years: (rational): ", balance[Rat]().format(1, 16)

####################################################################################################
# Task 3.

const
  A = 77617
  B = 33096

proc rump[T: float|DecimalType|Rat](a, b: T): T =
  ## Return the value of the Rump's function.
  let C1 = when T is float: 333.75
           elif T is Rat: newRat(333.75)
           else: newDecimal("333.75")
  let C2 = when T is float: 5.5
           elif T is Rat: newRat(5.5)
           else: newDecimal("5.5")
  result = C1 * b^6 + a^2 * (11 * a^2 * b^2 - b^6 - 121 * b^4 - 2) + C2 * b^8 + a / (2 * b)

echo "\nTask 3"

let rumpFloat = rump(A.toFloat, B.toFloat)
let rumpDecimal = rump(newDecimal(A), newDecimal(B))
let rumpRational = rump(newRat(A), newRat(B))

echo &"f({A}, {B}) float =    ", rumpFloat
echo &"f({A}, {B}) decimal =  ", rumpDecimal.format(1, 16)
echo &"f({A}, {B}) rational = ", rumpRational.format(1, 16)


include builtins\bigatom.e
puts(1,"Task 1\n")
constant {fns,fmts} = columnize({{3,1},{4,6},{5,6},{6,6},{7,6},{8,7},{20,16},{30,24},{50,40},{100,78}})
{} = ba_scale(196)
sequence v = {2,-4}
for n=3 to 100 do
--  v = append(v,111 - 1130/v[n-1] + 3000/(v[n-1]*v[n-2]))
    v = append(v,ba_add(ba_sub(111,ba_divide(1130,v[n-1])),ba_divide(3000,ba_multiply(v[n-1],v[n-2]))))
    if n<9 or find(n,{20,30,50,100}) then
--      printf(1,"n = %-3d %20.16f\n", {n, v[n]})
        string fmt = sprintf("%%.%dB",fmts[find(n,fns)])
        printf(1,"n = %-3d %s\n", {n, ba_sprintf(fmt,v[n])})
    end if
end for

puts(1,"\nTask 2\n")
--atom balance = exp(1)-1
--for i=1 to 25 do balance = balance*i-1 end for
--printf(1,"\nTask 2\nBalance after 25 years: $%12.10f", balance)
{} = ba_scale(41)
bigatom balance = ba_sub(ba_euler(42,true),1)
for i=1 to 25 do balance = ba_sub(ba_multiply(balance,i),1) end for
ba_printf(1,"Balance after 25 years: $%.16B\n\n", balance)

puts(1,"Task 3\n")
{} = ba_scale(15)   -- fine!
integer a = 77617,
        b = 33096
--atom pa2 = power(a,2),
--   pb2a211 = 11*pa2*power(b,2),
--   pb4121 = 121*power(b,4),
--   pb6 = power(b,6),
--   pb855 = 5.5*power(b,8),
--   f_ab = 333.75 * pb6 + pa2 * (pb2a211 - pb6 - pb4121 - 2) + pb855 + a/(2*b)
--printf(1,"f(%d, %d) = %.15f\n\n", {a, b, f_ab})
bigatom pa2 = ba_power(a,2),
        pb2a211 = ba_multiply(11,ba_multiply(pa2,ba_power(b,2))),
        pb4121 = ba_multiply(121,ba_power(b,4)),
        pb6 = ba_power(b,6),
        pa2mid = ba_multiply(pa2,ba_sub(ba_sub(ba_sub(pb2a211,pb6),pb4121),2)),
        pb633375 = ba_multiply(333.75,pb6),
        pb855 = ba_multiply(5.5,ba_power(b,8)),
        f_ab = ba_add(ba_add(ba_add(pb633375,pa2mid),pb855),ba_divide(a,ba_multiply(2,b)))
printf(1,"f(%d, %d) = %s\n", {a, b, ba_sprintf("%.15B",f_ab)})


from fractions import Fraction

def muller_seq(n:int) -> float:
    seq = [Fraction(0), Fraction(2), Fraction(-4)]
    for i in range(3, n+1):
        next_value = (111 - 1130/seq[i-1]
            + 3000/(seq[i-1]*seq[i-2]))
        seq.append(next_value)
    return float(seq[n])

for n in [3, 4, 5, 6, 7, 8, 20, 30, 50, 100]:
    print("{:4d} -> {}".format(n, muller_seq(n)))


#lang racket

(define current-do-exact-calculations? (make-parameter exact->inexact))

(define (x n) (if (current-do-exact-calculations?) n (exact->inexact n)))

(define (decimal.18 n)
  (regexp-replace #px"0+$" (real->decimal-string n 18) ""))

(define (task-1 n)
  (let ((c_1 (x 111)) (c_2 (x -1130)) (c_3 (x 3000)))
    (let loop ((v_n-2 (x 2)) (v_n-1 (x -4)) (n (- n 2)))
      (if (= n 0) v_n-1 (loop v_n-1 (+ c_1 (/ c_2 v_n-1) (/ c_3 (* v_n-1 v_n-2))) (- n 1))))))

(define (task-2) ; chaotic bank
   (define e (if (current-do-exact-calculations?)
                 #e2.71828182845904523536028747135266249775724709369995
                 (exp 1)))
  (for/fold ((b (- e 1))) ((y (in-range 1 26))) (- (* b y) 1)))

(define (task-3 a b)
    (+ (* (x #e333.75) (expt b 6))
       (* (expt a 2) (- (* 11 (expt a 2) (expt b 2)) (expt b 6) (* 121 (expt b 4)) 2))
       (* (x #e5.5) (expt b 8))
       (/ a (* b 2))))

(define (all-tests)
  (let ((classic-sum (+ (x #e0.2) (x #e0.1))))
    (printf "Classic example: ~a = ~a~%" classic-sum (decimal.18 classic-sum)))

  (displayln "TASK 1")
  (for ((n (in-list '(3 4 5 6 7 8 20 30 50 100))))
    (printf "n=~a\t~a~%" n (decimal.18 (task-1 n))))

  (printf "TASK 2: balance after 25 years = ~a~%" (decimal.18 (task-2)))

  (let ((t3 (task-3 77617 33096)))
    (printf "TASK 3: f(77617, 33096) = ~a = ~a~%" t3 (decimal.18 t3))))

(module+ main
  (displayln "INEXACT (Floating Point) NUMBERS")
  (parameterize ([current-do-exact-calculations? #f])
    (all-tests))
  (newline)

  (displayln "EXACT (Rational) NUMBERS")
  (parameterize ([current-do-exact-calculations? #t])
    (all-tests)))


say '1st: Convergent series';
my @series = 2.FatRat, -4, { 111 - 1130 / $^v + 3000 / ( $^v * $^u ) } ... *;
for flat 3..8, 20, 30, 50, 100 -> $n {say "n = {$n.fmt("%3d")} @series[$n-1]"};

say "\n2nd: Chaotic bank society";
sub postfix:<!> (Int $n) { [*] 2..$n } # factorial operator
my $years = 25;
my $balance = sum map { 1 / FatRat.new($_!) }, 1 .. $years + 15; # Generate e-1  to sufficient precision with a Taylor series
put "Starting balance, \$(e-1): \$$balance";
for 1..$years -> $i { $balance = $i * $balance - 1 }
printf("After year %d, you will have \$%1.16g in your account.\n", $years, $balance);

print "\n3rd: Rump's example: f(77617.0, 33096.0) = ";
sub f (\a, \b) { 333.75*b⁶ + a²*( 11*a²*b² - b⁶ - 121*b⁴ - 2 ) + 5.5*b⁸ + a/(2*b) }
say f(77617.0, 33096.0).fmt("%0.16g");


/*REXX pgm (pathological FP problem):  a sequence that might converge to a wrong limit. */
parse arg digs show .                            /*obtain optional arguments from the CL*/
if digs=='' | digs==","  then digs= 150          /*Not specified?  Then use the default.*/
if show=='' | show==","  then show=  20          /* "      "         "   "   "     "    */
numeric digits digs                              /*have REXX use "digs" decimal digits. */
#= 2 4 5 6 7 8 9 20 30 50 100                    /*the indices to display value of  V.n */
fin= word(#, words(#) )                          /*find the last (largest) index number.*/
w= length(fin)                                   /*  "   "  length (in dec digs) of FIN.*/
v.1= 2                                           /*the value of the first   V  element. */
v.2=-4                                           /* "    "    "  "  second  "     "     */
      do n=3  to fin;   nm1= n-1;     nm2= n-2   /*compute some values of the V elements*/
      v.n= 111 - 1130/v.nm1 + 3000/(v.nm1*v.nm2) /*   "      a  value  of  a  " element.*/
                                                 /*display digs past the dec. point───┐ */
      if wordpos(n, #)\==0  then say   'v.'left(n, w)       "="        format(v.n, , show)
      end   /*n*/                                /*stick a fork in it,  we're all done. */


# Project : Pathological floating point problems

decimals(8)
v = list(100)
v[1] = 2
v[2] = -4
for n = 3 to 100
      v[n] = (111 - 1130 / v[n-1]) + 3000 / (v[n-1] * v[n-2])
      if n < 9 or n = 20 or n = 30 or n = 50 or n = 100
         see "n = " + n + "   " + v[n] + nl
      ok
next


clear
set obs 100
gen n=_n
gen v=.
replace v=2 in 1
replace v=-4 in 2
replace v=111-1130/v[_n-1]+3000/(v[_n-1]*v[_n-2]) in 3/l
format %20.16f v
list if inlist(n,3,4,5,6,7,8,20,30,50,100), noobs


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

protocol PathologicalFloat: SignedNumeric, Strideable, ExpressibleByFloatLiteral {
  static var e: Self { get }

  static func /(_ lhs: Self, _ rhs: Self) -> Self
}

extension Double: PathologicalFloat {
  static var e: Double { Double("2.71828182845904523536028747135266249")! }
}

extension Float: PathologicalFloat {
  static var e: Float { Float("2.7182818284590")! }
}

extension Decimal: PathologicalFloat {
  static var e: Decimal { Decimal(string: "2.71828182845904523536028747135266249")! }
}

extension BDouble: PathologicalFloat {
  static var e: BDouble { BDouble("2.71828182845904523536028747135266249")! }

  public func advanced(by n: BDouble) -> BDouble { self + n }
  public func distance(to other: BDouble) -> BDouble { abs(self - other) }
}

func badSequence<T: PathologicalFloat>(n: Int) -> T {
  guard n != 1 else { return 2 }
  guard n != 2 else { return -4 }

  var a: T = 2, b: T = -4

  for _ in stride(from: 2, to: n, by: 1) {
    (a, b) = (b, 111 - 1130  / b + 3000 / (a * b))
  }

  return b
}

func chaoticBank<T: PathologicalFloat>(years: T) -> T {
  var balance = T.e - 1

  for year: T in stride(from: 1, through: 25, by: 1) {
    balance = (balance * year) - 1
  }

  return balance
}

func rumpFunction<T: PathologicalFloat>(_ a: T, _ b: T) -> T {
  let aSquared = a.power(2)
  let bSix = b.power(6)

  let f1 = 333.75 * bSix
  let f2 = aSquared * (11 * aSquared * b.power(2) - bSix - 121 * b.power(4) - 2)
  let f3 = 5.5 * b.power(8) + a / (2 * b)

  return f1 + f2 + f3
}

func fmt<T: CVarArg>(_ n: T) -> String { String(format: "%16.16f", n) }

print("Bad sequence")
for i in [3, 4, 5, 6, 7, 8, 20, 30, 50, 100] {
  let vFloat: Float = badSequence(n: i)
  let vDouble: Double = badSequence(n: i)
  let vDecimal: Decimal = badSequence(n: i)
  let vBigDouble: BDouble = badSequence(n: i)

  print("v(\(i)) as Float \(fmt(vFloat)); as Double = \(fmt(vDouble)); as Decimal = \(vDecimal); as BDouble = \(vBigDouble.decimalExpansion(precisionAfterDecimalPoint: 16, rounded: false))")
}

let bankFloat: Float = chaoticBank(years: 25)
let bankDouble: Double = chaoticBank(years: 25)
let bankDecimal: Decimal = chaoticBank(years: 25)
let bankBigDouble: BDouble = chaoticBank(years: 25)

print("\nChaotic bank")
print("After 25 years your bank will be \(bankFloat) if stored as a Float")
print("After 25 years your bank will be \(bankDouble) if stored as a Double")
print("After 25 years your bank will be \(bankDecimal) if stored as a Decimal")
print("After 25 years your bank will be \(bankBigDouble.decimalExpansion(precisionAfterDecimalPoint: 16, rounded: false)) if stored as a BigDouble")

let rumpFloat: Float = rumpFunction(77617.0, 33096.0)
let rumpDouble: Double = rumpFunction(77617.0, 33096.0)
let rumpDecimal: Decimal = rumpFunction(77617.0, 33096.0)
let rumpBigDouble: BDouble = rumpFunction(77617.0, 33096.0)

print("\nRump's function")
print("rump(77617.0, 33096.0) as Float \(rumpFloat); as Double = \(rumpDouble); as Decimal = \(rumpDecimal); as BDouble = \(rumpBigDouble.decimalExpansion(precisionAfterDecimalPoint: 16, rounded: false))")


Imports System.Globalization
Imports System.Numerics
Imports Numerics

#Const USE_BIGRATIONAL = True
#Const BANDED_ROWS = True
#Const INCREASED_LIMITS = True

#If Not USE_BIGRATIONAL Then
' Mock structure to make test code work.
Structure BigRational
    Overrides Function ToString() As String
        Return "NOT USING BIGRATIONAL"
    End Function
    Shared Narrowing Operator CType(value As BigRational) As Decimal
        Return -1
    End Operator
End Structure
#End If

Module Common
    Public Const FMT_STR = "{0,4}   {1,-15:G9}   {2,-24:G17}   {3,-32}   {4,-32}"
    Public ReadOnly Property Headings As String =
        String.Format(CultureInfo.InvariantCulture,
                      FMT_STR,
                      {"N", "Single", "Double", "Decimal", "BigRational (rounded as decimal)"})

    <Conditional("BANDED_ROWS")>
    Sub SetConsoleFormat(n As Integer)
        If n Mod 2 = 0 Then
            Console.BackgroundColor = ConsoleColor.Black
            Console.ForegroundColor = ConsoleColor.White
        Else
            Console.BackgroundColor = ConsoleColor.White
            Console.ForegroundColor = ConsoleColor.Black
        End If
    End Sub

    Function FormatOutput(n As Integer, x As (sn As Single, db As Double, dm As Decimal, br As BigRational)) As String
        SetConsoleFormat(n)
        Return String.Format(CultureInfo.CurrentCulture, FMT_STR, n, x.sn, x.db, x.dm, CDec(x.br))
    End Function

    Sub Main()
        WrongConvergence()
        Console.WriteLine()
        ChaoticBankSociety()

        Console.WriteLine()
        SiegfriedRump()

        SetConsoleFormat(0)
    End Sub
End Module


import "/big" for BigRat
import "/fmt" for Fmt

var LIMIT = 100
var bigE = BigRat.fromDecimal("2.71828182845904523536028747135266249775724709369995")

// v(n) sequence task
var c1 = BigRat.new(111)
var c2 = BigRat.new(1130)
var c3 = BigRat.new(3000)
var v1 = BigRat.two
var v2 = BigRat.new(-4)
for (i in 3..LIMIT) {
    var v3 = c1 - c2/v2 + c3/(v2*v1)
    Fmt.print("$3d : $19s", i, v3.toDecimal(16, true, true))
    v1 = v2
    v2 = v3
}

// Chaotic Building Society task
var balance = bigE - 1
for (year in 1..25) balance = balance * year - 1
System.print("\nBalance after 25 years is %(balance.toDecimal(16))")

// Siegfried Rump task
var a  = BigRat.new(77617)
var b  = BigRat.new(33096)
var c4 = BigRat.new(33375, 100)
var c5 = BigRat.new(11)
var c6 = BigRat.new(121)
var c7 = BigRat.new(11, 2)
var f = c4 * b.pow(6) + c7 * b.pow(8) + a/(b*2)
var c8 = c5 * a.pow(2) * b.pow(2) - b.pow(6) - c6 * b.pow(4) - 2
f = f + c8 * a.pow(2)
System.print("\nf(77617.0, 33096.0) is %(f.toDecimal(16))")


Series:=Walker(fcn(vs){  // just keep appending new values to a list
   vs.append(111.0 - 1130.0/vs[-1] + 3000.0/(vs[-1]*vs[-2])) }.fp(List(2,-4)));
series:=Series.drop(100).value;


with Ada.Text_IO; use Ada.Text_IO;

procedure Pyramid_of_Numbers is

   B_X, B_Y, B_Z : Integer := 0; -- Unknown variables

   type Block_Value is record
      Known   : Integer := 0;
      X, Y, Z : Integer := 0;
   end record;
   X : constant Block_Value := (0, 1, 0, 0);
   Y : constant Block_Value := (0, 0, 1, 0);
   Z : constant Block_Value := (0, 0, 0, 1);
   procedure Add (L : in out Block_Value; R : Block_Value) is
   begin -- Symbolically adds one block to another
      L.Known := L.Known + R.Known;
      L.X := L.X + R.X - R.Z; -- Z is excluded as n(Y - X - Z) = 0
      L.Y := L.Y + R.Y + R.Z;
   end Add;
   procedure Add (L : in out Block_Value; R : Integer) is
   begin -- Symbolically adds a value to the block
      L.Known := L.Known + R;
   end Add;

   function Image (N : Block_Value) return String is
   begin -- The block value, when X,Y,Z are known
      return Integer'Image (N.Known + N.X * B_X + N.Y * B_Y + N.Z * B_Z);
   end Image;

   procedure Solve_2x2 (A11, A12, B1, A21, A22, B2 : Integer) is
   begin -- Don't care about things, supposing an integer solution exists
      if A22 = 0 then
         B_X := B2 / A21;
         B_Y := (B1 - A11*B_X) / A12;
      else
         B_X := (B1*A22 - B2*A12) / (A11*A22 - A21*A12);
         B_Y := (B1 - A11*B_X) / A12;
      end if;
      B_Z := B_Y - B_X;
   end Solve_2x2;

   B : array (1..5, 1..5) of Block_Value; -- The lower triangle contains blocks

begin
   -- The bottom blocks
   Add (B(5,1),X); Add (B(5,2),11); Add (B(5,3),Y); Add (B(5,4),4); Add (B(5,5),Z);

   -- Upward run
   for Row in reverse 1..4 loop
      for Column in 1..Row loop
         Add (B (Row, Column), B (Row + 1, Column));
         Add (B (Row, Column), B (Row + 1, Column + 1));
      end loop;
   end loop;

   -- Now have known blocks 40=(3,1), 151=(1,1) and Y=X+Z to determine X,Y,Z
   Solve_2x2
   (  B(1,1).X, B(1,1).Y, 151 - B(1,1).Known,
      B(3,1).X, B(3,1).Y,  40 - B(3,1).Known
   );

   -- Print the results
   for Row in 1..5 loop
      New_Line;
      for Column in 1..Row loop
         Put (Image (B(Row,Column)));
      end loop;
   end loop;
end Pyramid_of_Numbers;


MODE
  FIELD = REAL,
  VEC = [0]REAL,
  MAT = [0,0]REAL;
MODE BRICK = UNION(INT, CHAR);

FLEX[][]BRICK puzzle = (
           ( 151),
         ( " ", " "),
       (  40, " ", " "),
     ( " ", " ", " ", " "),
   ( "x",  11, "y",  4, "z")
);

PROC mat col = (INT row, col)INT: row*(row-1)OVER 2 + col;
INT col x = mat col(5,1),
    col y = mat col(5,3),
    col z = mat col(5,5);

OP INIT = (REF VEC vec)VOID: FOR elem FROM LWB vec TO UPB vec DO vec[elem]:=0 OD;
OP INIT = (REF MAT mat)VOID: FOR row FROM LWB mat TO UPB mat DO INIT mat[row,] OD;

OP / = (MAT a, MAT b)MAT:( # matrix division #
  [LWB b:UPB b]INT p ;
  INT sign;
  [,]FIELD lu = lu decomp(b, p, sign);
  [LWB a:UPB a, 1 LWB a:2 UPB a]FIELD out;
  FOR col FROM 2 LWB a TO 2 UPB a DO out[,col] := lu solve(b, lu, p, a[,col]) OD;
  out
);

OP / = (VEC a, MAT b)VEC: ( # vector division #
  [LWB a:UPB a,1]FIELD transpose a;
  transpose a[,1]:=a;
  (transpose a/b)[,LWB a]
);

INT upb mat = mat col(UPB puzzle, UPB puzzle);
[upb mat, upb mat] REAL mat; INIT mat;
[upb mat] REAL vec; INIT vec;

INT mat row := LWB mat;
INT known row := UPB mat - UPB puzzle + 1;

# build the simultaneous equation to solve #
FOR row FROM LWB puzzle TO UPB puzzle DO
  FOR col FROM LWB puzzle[row] TO UPB puzzle[row] DO
    IF row < UPB puzzle THEN
      mat[mat row, mat col(row, col)] := 1;
      mat[mat row, mat col(row+1, col)] := -1;
      mat[mat row, mat col(row+1, col+1)] := -1;
      mat row +:= 1
    FI;
    CASE puzzle[row][col] IN
      (INT value):(
        mat[known row, mat col(row, col)] := 1;
        vec[known row] := value;
        known row +:= 1
      ),
      (CHAR variable):SKIP
    ESAC
  OD
OD;

# finally add x - y + z = 0 #
mat[known row, col x] := 1;
mat[known row, col y] := -1;
mat[known row, col z] := 1;

FORMAT real repr = $g(-5,2)$;

CO # print details of the simultaneous equation being solved #
FORMAT
  vec repr = $"("n(2 UPB mat-1)(f(real repr)", ")f(real repr)")"$,
  mat repr = $"("n(1 UPB mat-1)(f(vec repr)", "lx)f(vec repr)")"$;

printf(($"Vec: "l$,vec repr, vec, $l$));
printf(($"Mat: "l$,mat repr, mat, $l$));
END CO

# finally actually solve the equation #
VEC solution vec = vec/mat;

# and wrap up by printing the solution #
FLEX[UPB puzzle]FLEX[0]REAL solution;
FOR row FROM LWB puzzle TO UPB puzzle DO
  solution[row] := LOC[row]REAL;
  FOR col FROM LWB puzzle[row] TO UPB puzzle[row] DO
    solution[row][col] := solution vec[mat col(row, col)]
  OD;
  printf(($n(UPB puzzle-row)(4x)$, $x"("f(real repr)")"$, solution[row], $l$))
OD;

FOR var FROM 1 BY 2 TO 5 DO
  printf(($5x$,$g$,puzzle[UPB puzzle][var],"=", real repr, solution[UPB puzzle][var]))
OD


/* Pascal's pyramid solver
 *
 *               [top]
 *            [   ] [   ]
 *         [mid] [   ] [   ]
 *      [   ] [   ] [   ] [   ]
 *   [ x ] [ a ] [ y ] [ b ] [ z ]
 *             x + z = y
 *
 * This solution makes use of a little bit of mathematical observation,
 * such as the fact that top = 4(a+b) + 7(x+z) and mid = 2x + 2a + z.
 */

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

void pascal(int a, int b, int mid, int top, int* x, int* y, int* z)
{
    double ytemp = (top - 4 * (a + b)) / 7.;
    if(fmod(ytemp, 1.) >= 0.0001)
    {
        x = 0;
        return;
    }
    *y = ytemp;
    *x = mid - 2 * a - *y;
    *z = *y - *x;
}
int main()
{
    int a = 11, b = 4, mid = 40, top = 151;
    int x, y, z;
    pascal(a, b, mid, top, &x, &y, &z);
    if(x != 0)
        printf("x: %d, y: %d, z: %d\n", x, y, z);
    else printf("No solution\n");

    return 0;
}


using System;

namespace Pyramid_of_Numbers
{
        class Program
	{
		public static void Main(string[] args)
		{
			// Set console properties
			Console.Title = " Pyramid of Numbers  /  Pascal's triangle Puzzle";
			Console.SetBufferSize(80,1000);
			Console.SetWindowSize(80,60);
			Console.ForegroundColor = ConsoleColor.Green;

			// Main Program Loop
			ConsoleKeyInfo k = new ConsoleKeyInfo('Y', ConsoleKey.Y,true,true,true);
			while (k.Key == ConsoleKey.Y)
			{
				Console.Clear();

				Console.WriteLine("----------------------------------------------");
				Console.WriteLine(" Pyramid of Numbers / Pascal's triangle Puzzle");
				Console.WriteLine("----------------------------------------------");
				Console.WriteLine();

				//
				// Declare new Pyramid array
				//
				int r = 5;// Number of rows
				int [,] Pyramid = new int[r,r];

				// Set initial Pyramid values
				for (int i = 0; i < r; i++)
				{
					for(int j = 0; j < r; j++)
					{
						Pyramid[i,j] = 0;
					}
				}
				// Show info on created array
				Console.WriteLine(" Pyramid has " + r + " rows");
				Console.WriteLine("--------------------------------------------");

				// Enter Pyramid values
				for(int i = 0; i <= r-1; i++)
				{
					Console.WriteLine(" Enter " + (i+1).ToString() + ". row values:");
					Console.WriteLine("--------------------------------------------");

					for(int j = 0; j < i+1; j++)
					{
						Console.Write(" " + (j+1).ToString() + ". value = ");
						int v = int.Parse(Console.ReadLine());

						Pyramid[i,j] = v;
					}
					Console.WriteLine("--------------------------------------------");
				}

				//
				// Show initial Pyramid values
				//
				Console.WriteLine();
				Console.WriteLine(" Initial Pyramid Values ");
				Console.WriteLine();

				// Show Pyramid values
				for(int i = 0; i <= r-1; i++)
				{
					for(int j = 0; j < i+1; j++)
					{
						Console.Write("{0,4}",Pyramid[i,j]);
					}
					Console.WriteLine();
				}
				Console.WriteLine("--------------------------------------------");

				// Find solution
				Solve_Pyramid(Pyramid);

				Console.WriteLine();
				Console.Write(" Start new calculation <Y/N>  . . . ");
				k = Console.ReadKey(true);
			}
		}

                //
                // Solve Function
                //
		public static void Solve_Pyramid(int [,] Pyramid)
		{
			int r = 5; // Number of rows

			// Calculate Y
			int a = Pyramid[r-1,1];
			int b = Pyramid[r-1,3];
			int c = Pyramid[0,0];

			int y =  (c - (4*a) - (4*b))/7;
			Pyramid[r-1,2] = y;

			// Create copy of Pyramid
			int [,] Pyramid_Copy = new int[r,r];
			Array.Copy(Pyramid,Pyramid_Copy,r*r);

			int n = 0; // solution counter
			for(int x = 0; x < y + 1; x++)
			{
				for(int z = 0; z < y + 1; z++)
				{
					if( (x+z) == y)
					{
						Pyramid[r-1,0]   = x;
						Pyramid[r-1,r-1] = z;

						// Recalculate Pyramid values
						for(int i = r-1; i > 0; i--)
						{
							for(int j = 0; j < i; j++)
							{
								Pyramid[i-1,j] = Pyramid[i,j]+Pyramid[i,j+1];
							}
						}

						// Compare Pyramid values
						bool solved = true;
						for(int i = 0; i < r-1; i++)
						{
							for(int j = 0; j < i+1; j++)
							{
								if(Pyramid_Copy[i,j]>0)
								{
									if(Pyramid[i,j] != Pyramid_Copy[i,j])
									{
										solved = false;
										i = r;
										break;
									}
								}
							}
						}

						if(solved)
						{
							n++;
							Console.WriteLine();
							Console.WriteLine(" Solved Pyramid Values no." + n);
							Console.WriteLine();

							// Show Pyramid values
							for(int i = 0; i <= r-1; i++)
							{
								for(int j = 0; j < i+1; j++)
								{
									Console.Write("{0,4}",Pyramid[i,j]);
								}
								Console.WriteLine();
							}
							Console.WriteLine();
							Console.WriteLine(" X = " + Pyramid[r-1,0] + "   " +
							                  " Y = " + Pyramid[r-1,2] + "   " +
							                  " Z = " + Pyramid[r-1,4]);
							Console.WriteLine();
							Console.WriteLine("--------------------------------------------");
						}

						Array.Copy(Pyramid_Copy,Pyramid,r*r);
					}
				}
			}

			if(n == 0)
			{
				Console.WriteLine();
				Console.WriteLine(" Pyramid has no solution ");
				Console.WriteLine();
			}
		}

	}
}


#include <iostream>
#include <iomanip>

inline int sign(int i) {
    return i < 0 ? -1 : i > 0;
}

inline int& E(int *x, int row, int col) {
    return x[row * (row + 1) / 2 + col];
}

int iter(int *v, int *diff) {
    // enforce boundary conditions
    E(v, 0, 0) = 151;
    E(v, 2, 0) = 40;
    E(v, 4, 1) = 11;
    E(v, 4, 3) = 4;

    // calculate difference from equilibrium
    for (auto i = 1u; i < 5u; i++)
        for (auto j = 0u; j <= i; j++) {
            E(diff, i, j) = 0;
            if (j < i)
                E(diff, i, j) += E(v, i - 1, j) - E(v, i, j + 1) - E(v, i, j);
            if (j)
                E(diff, i, j) += E(v, i - 1, j - 1) - E(v, i, j - 1) - E(v, i, j);
        }

    for (auto i = 0u; i < 4u; i++)
        for (auto j = 0u; j < i; j++)
            E(diff, i, j) += E(v, i + 1, j) + E(v, i + 1, j + 1) - E(v, i, j);

    E(diff, 4, 2) += E(v, 4, 0) + E(v, 4, 4) - E(v, 4, 2);

    // do feedback, check if we are done
    uint sum;
    int e = 0;
    for (auto i = sum = 0u; i < 15u; i++) {
        sum += !!sign(e = diff[i]);

        // 1/5-ish feedback strength on average.  These numbers are highly magical, depending on nodes' connectivities
        if (e >= 4 || e <= -4)
            v[i] += e / 5;
        else if (rand() < RAND_MAX / 4)
            v[i] += sign(e);
    }
    return sum;
}

void show(int *x) {
    for (auto i = 0u; i < 5u; i++)
        for (auto j = 0u; j <= i; j++)
            std::cout << std::setw(4u) << *(x++) << (j < i ? ' ' : '\n');
}

int main() {
    int v[15] = { 0 }, diff[15] = { 0 };
    for (auto i = 1u, s = 1u; s; i++) {
        s = iter(v, diff);
        std::cout << "pass " << i << ": " << s << std::endl;
    }
    show(v);

    return 0;
}


(def bottom [ [0 1 0], [11 0 0], [0 1 1], [4 0 0], [0 0 1] ])

(defn plus  [v1 v2] (vec (map + v1 v2)))
(defn minus [v1 v2] (vec (map - v1 v2)))
(defn scale [n v]   (vec (map #(* n %) v )))

(defn above [row] (map #(apply plus %) (partition 2 1 row)))

(def rows (reverse (take 5 (iterate above bottom))))


import CLPFD
import Constraint (allC, andC)
import Findall (findall)
import List (init, last)

solve :: [[Int]] -> Success
solve [email protected]([n]:rest) =
    domain (concat body) 1 n
  & andC (zipWith atop body rest)
  & labeling [] (concat body)
  where
    xs `atop` ys = andC $ zipWith3 tri xs (init ys) (tail ys)

tri :: Int -> Int -> Int -> Success
tri x y z = x =# y +# z

test (x,y,z) | tri y x z =
    [ [151]
    , [ _,  _]
    , [40,  _, _]
    , [ _,  _, _, _]
    , [ x, 11, y, 4, z]
    ]
main = findall $ solve . test


import std.stdio, std.algorithm;

void iterate(bool doPrint=true)(double[] v, double[] diff) @safe {
    static ref T E(T)(T[] x, in size_t row, in size_t col)
    pure nothrow @safe @nogc {
        return x[row * (row + 1) / 2 + col];
    }

    double tot = 0.0;
    do {
        // Enforce boundary conditions.
        E(v, 0, 0) = 151;
        E(v, 2, 0) = 40;
        E(v, 4, 1) = 11;
        E(v, 4, 3) = 4;

        // Calculate difference from equilibrium.
        foreach (immutable i; 1 .. 5) {
            foreach (immutable j; 0 .. i + 1) {
                E(diff, i, j) = 0;
                if (j < i)
                    E(diff, i, j) += E(v, i - 1, j) - E(v, i, j + 1) - E(v, i, j);
                if (j)
                    E(diff, i, j) += E(v, i - 1, j - 1) - E(v, i, j - 1) - E(v, i, j);
            }
        }

        foreach (immutable i; 1 .. 4)
            foreach (immutable j; 0 .. i)
                E(diff, i, j) += E(v, i + 1, j) + E(v, i + 1, j + 1) - E(v, i, j);

        E(diff, 4, 2) += E(v, 4, 0) + E(v, 4, 4) - E(v, 4, 2);

        // Do feedback, check if we are close enough.
        // 4: scale down the feedback to avoid oscillations.
        v[] += diff[] / 4;
        tot = diff.map!q{ a ^^ 2 }.sum;

        static if (doPrint)
            writeln("dev: ", tot);

        // tot(dx^2) < 0.1 means each cell is no more than 0.5 away
        // from equilibrium. It takes about 50 iterations. After
        // 700 iterations tot is < 1e-25, but that's overkill.
    } while (tot >= 0.1);
}

void main() {
    static void show(in double[] x) nothrow @nogc {
        int idx;
        foreach (immutable i; 0 .. 5)
            foreach (immutable j; 0 .. i+1) {
                printf("%4d%c", cast(int)(0.5 + x[idx]), j < i ? ' ' : '\n');
                idx++;
            }
    }

    double[15] v = 0.0, diff = 0.0;
    iterate(v, diff);
    show(v);
}


USING: arrays backtrack combinators.extras fry grouping.extras
interpolate io kernel math math.ranges sequences ;

: base ( ?x ?z -- seq ) 2dup + swap '[ _ 11 _ 4 _ ] >array ;

: up ( seq -- seq' ) [ [ + ] 2clump-map ] twice ;

: find-solution ( -- x z )
    10 [1,b] dup [ amb-lazy ] [email protected] 2dup base
    up dup first 40 = must-be-true
    up first 151 = must-be-true ;

find-solution [I X = ${1}, Z = ${}I] nl


Function SolveForZ(x As Integer) As Integer
    Dim As Integer a, b, c, d, e, f, g, h, z
    For z = 0 To 20
        e = x + 11
        f = 11 + (x+z)
        g = (x+z) + 4
        h = 4 + z
        If e + f = 40 Then
            c = f + g
            d = g + h
            a = 40 + c
            b = c + d
            If a + b = 151 Then Return z
        End If
    Next z
    Return -1
End Function

Dim As Integer x = -1, z = 0
Do
    x = x + 1
    z = SolveForZ(x)
Loop Until z >= 0

Print "X ="; x
Print "Y ="; x + z
Print "Z ="; z
Sleep


package main

import "fmt"

// representation of an expression in x, y, and z
type expr struct {
    x, y, z float64 // coefficients
    c       float64 // constant term
}

// add two expressions
func addExpr(a, b expr) expr {
    return expr{a.x + b.x, a.y + b.y, a.z + b.z, a.c + b.c}
}

// subtract two expressions
func subExpr(a, b expr) expr {
    return expr{a.x - b.x, a.y - b.y, a.z - b.z, a.c - b.c}
}

// multiply expression by a constant
func mulExpr(a expr, c float64) expr {
    return expr{a.x * c, a.y * c, a.z * c, a.c * c}
}

// given a row of expressions, produce the next row up, by the given
// sum relation between blocks
func addRow(l []expr) []expr {
    if len(l) == 0 {
        panic("wrong")
    }
    r := make([]expr, len(l)-1)
    for i := range r {
        r[i] = addExpr(l[i], l[i+1])
    }
    return r
}

// given expression b in a variable, and expression a,
// take b == 0 and substitute to remove that variable from a.
func substX(a, b expr) expr {
    if b.x == 0 {
        panic("wrong")
    }
    return subExpr(a, mulExpr(b, a.x/b.x))
}

func substY(a, b expr) expr {
    if b.y == 0 {
        panic("wrong")
    }
    return subExpr(a, mulExpr(b, a.y/b.y))
}

func substZ(a, b expr) expr {
    if b.z == 0 {
        panic("wrong")
    }
    return subExpr(a, mulExpr(b, a.z/b.z))
}

// given an expression in a single variable, return value of that variable
func solveX(a expr) float64 {
    if a.x == 0 || a.y != 0 || a.z != 0 {
        panic("wrong")
    }
    return -a.c / a.x
}

func solveY(a expr) float64 {
    if a.x != 0 || a.y == 0 || a.z != 0 {
        panic("wrong")
    }
    return -a.c / a.y
}

func solveZ(a expr) float64 {
    if a.x != 0 || a.y != 0 || a.z == 0 {
        panic("wrong")
    }
    return -a.c / a.z
}

func main() {
    // representation of given information for bottom row
    r5 := []expr{{x: 1}, {c: 11}, {y: 1}, {c: 4}, {z: 1}}
    fmt.Println("bottom row:", r5)

    // given definition of brick sum relation
    r4 := addRow(r5)
    fmt.Println("next row up:", r4)
    r3 := addRow(r4)
    fmt.Println("middle row:", r3)

    // given relation y = x + z
    xyz := subExpr(expr{y: 1}, expr{x: 1, z: 1})
    fmt.Println("xyz relation:", xyz)
    // remove z from third cell using xyz relation
    r3[2] = substZ(r3[2], xyz)
    fmt.Println("middle row after substituting for z:", r3)

    // given cell = 40,
    b := expr{c: 40}
    // this gives an xy relation
    xy := subExpr(r3[0], b)
    fmt.Println("xy relation:", xy)
    // substitute 40 for cell
    r3[0] = b

    // remove x from third cell using xy relation
    r3[2] = substX(r3[2], xy)
    fmt.Println("middle row after substituting for x:", r3)

    // continue applying brick sum relation to get top cell
    r2 := addRow(r3)
    fmt.Println("next row up:", r2)
    r1 := addRow(r2)
    fmt.Println("top row:", r1)

    // given top cell = 151, we have an equation in y
    y := subExpr(r1[0], expr{c: 151})
    fmt.Println("y relation:", y)
    // using xy relation, we get an equation in x
    x := substY(xy, y)
    fmt.Println("x relation:", x)
    // using xyz relation, we get an equation in z
    z := substX(substY(xyz, y), x)
    fmt.Println("z relation:", z)

    // show final answers
    fmt.Println("x =", solveX(x))
    fmt.Println("y =", solveY(y))
    fmt.Println("z =", solveZ(z))
}


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

public class PascalsTrianglePuzzle {

    public static void main(String[] args) {
        Matrix mat = new Matrix(Arrays.asList(1d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, -1d, 0d, 0d),
                                Arrays.asList(0d, 1d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, -1d, 0d),
                                Arrays.asList(0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, -1d, 1d, -1d),
                                Arrays.asList(0d, 0d, 1d, 0d, 0d, 0d, 0d, 0d, 0d, -1d, 0d),
                                Arrays.asList(0d, 0d, 0d, 1d, 0d, 0d, 0d, 0d, 0d, 0d, -1d),
                                Arrays.asList(1d, 1d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d),
                                Arrays.asList(0d, 1d, 1d, 0d, -1d, 0d, 0d, 0d, 0d, 0d, 0d),
                                Arrays.asList(0d, 0d, 1d, 1d, 0d, -1d, 0d, 0d, 0d, 0d, 0d),
                                Arrays.asList(0d, 0d, 0d, 0d, -1d, 0d, 1d, 0d, 0d, 0d, 0d),
                                Arrays.asList(0d, 0d, 0d, 0d, 1d, 1d, 0d, -1d, 0d, 0d, 0d),
                                Arrays.asList(0d, 0d, 0d, 0d, 0d, 0d, 1d, 1d, 0d, 0d, 0d));
        List<Double> b = Arrays.asList(11d, 11d, 0d, 4d, 4d, 40d, 0d, 0d, 40d, 0d, 151d);
        List<Double> solution = cramersRule(mat, b);
        System.out.println("Solution = " + cramersRule(mat, b));
        System.out.printf("X = %.2f%n", solution.get(8));
        System.out.printf("Y = %.2f%n", solution.get(9));
        System.out.printf("Z = %.2f%n", solution.get(10));
    }

    private static List<Double> cramersRule(Matrix matrix, List<Double> b) {
        double denominator = matrix.determinant();
        List<Double> result = new ArrayList<>();
        for ( int i = 0 ; i < b.size() ; i++ ) {
            result.add(matrix.replaceColumn(b, i).determinant() / denominator);
        }
        return result;
    }

    private static class Matrix {

        private List<List<Double>> matrix;

        @Override
        public String toString() {
            return matrix.toString();
        }

        @SafeVarargs
        public Matrix(List<Double> ... lists) {
            matrix = new ArrayList<>();
            for ( List<Double> list : lists) {
                matrix.add(list);
            }
        }

        public Matrix(List<List<Double>> mat) {
            matrix = mat;
        }

        public double determinant() {
            if ( matrix.size() == 1 ) {
                return get(0, 0);
            }
            if ( matrix.size() == 2 ) {
                return get(0, 0) * get(1, 1) - get(0, 1) * get(1, 0);
            }
            double sum = 0;
            double sign = 1;
            for ( int i = 0 ; i < matrix.size() ; i++ ) {
                sum += sign * get(0, i) * coFactor(0, i).determinant();
                sign *= -1;
            }
            return sum;
        }

        private Matrix coFactor(int row, int col) {
            List<List<Double>> mat = new ArrayList<>();
            for ( int i = 0 ; i < matrix.size() ; i++ ) {
                if ( i == row ) {
                    continue;
                }
                List<Double> list = new ArrayList<>();
                for ( int j = 0 ; j < matrix.size() ; j++ ) {
                    if ( j == col ) {
                        continue;
                    }
                    list.add(get(i, j));
                }
                mat.add(list);
            }
            return new Matrix(mat);
        }

        private Matrix replaceColumn(List<Double> b, int column) {
            List<List<Double>> mat = new ArrayList<>();
            for ( int row = 0 ; row < matrix.size() ; row++ ) {
                List<Double> list = new ArrayList<>();
                for ( int col = 0 ; col < matrix.size() ; col++ ) {
                    double value = get(row, col);
                    if ( col == column ) {
                        value = b.get(row);
                    }
                    list.add(value);
                }
                mat.add(list);
            }
            return new Matrix(mat);
        }

        private double get(int row, int col) {
            return matrix.get(row).get(col);
        }

    }

}


function pascal(a::Integer, b::Integer, mid::Integer, top::Integer)
    yd = round((top - 4 * (a + b)) / 7)
    !isinteger(yd) && return 0, 0, 0
    y  = Int(yd)
    x  = mid - 2a - y
    return x, y, y - x
end

x, y, z = pascal(11, 4, 40, 151)
if !iszero(x)
    println("Solution: x = $x, y = $y, z = $z.")
else
    println("There is no solution.")
end


// version 1.1.3

data class Solution(val x: Int, val y: Int, val z: Int)

fun Double.isIntegral(tolerance: Double = 0.0) =
    (this - Math.floor(this)) <= tolerance || (Math.ceil(this) - this) <= tolerance

fun pascal(a: Int, b: Int, mid: Int, top: Int): Solution {
    val yd = (top - 4 * (a + b)) / 7.0
    if (!yd.isIntegral(0.0001)) return Solution(0, 0, 0)
    val y = yd.toInt()
    val x = mid - 2 * a - y
    return Solution(x, y, y - x)
}

fun main(args: Array<String>) {
    val (x, y, z) = pascal(11, 4, 40, 151)
    if (x != 0)
        println("Solution is: x = $x, y = $y, z = $z")
    else
        println("There is no solutuon")
}


b+c==a
d+e==b
e+f==c
g+h==d
h+i==e
i+j==f
l+X==g
l+Y==h
n+Y==i
n+Z==j
X+Z==Y


import strutils

type

  BlockValue = object
    known: int
    x, y, z: int

  Variables = tuple[x, y, z: int]

func `+=`(left: var BlockValue; right: BlockValue) =
  ## Symbolically add one block to another.
  left.known += right.known
  left.x += right.x - right.z    # Z is excluded as n(Y - X - Z) = 0.
  left.y += right.y + right.z

proc toString(n: BlockValue; vars: Variables): string =
  ## Return the representation of the block value, when X, Y, Z are known.
  result = $(n.known + n.x * vars.x + n.y * vars.y + n.z * vars.z)

proc Solve2x2(a11, a12, b1, a21, a22, b2: int): Variables =
  ## Solve a puzzle, supposing an integer solution exists.
  if a22 == 0:
    result.x = b2 div a21
    result.y = (b1 - a11 * result.x) div a12
  else:
    result.x = (b1 * a22 - b2 * a12) div (a11 * a22 - a21 * a12)
    result.y = (b1 - a11 * result.x) div a12
  result.z = result.y - result.x

var blocks : array[1..5, array[1..5, BlockValue]]   # The lower triangle contains blocks.

# The bottom blocks.
blocks[5][1] = BlockValue(x: 1)
blocks[5][2] = BlockValue(known: 11)
blocks[5][3] = BlockValue(y: 1)
blocks[5][4] = BlockValue(known: 4)
blocks[5][5] = BlockValue(z: 1)

# Upward run.
for row in countdown(4, 1):
  for column in 1..row:
    blocks[row][column] += blocks[row + 1][column]
    blocks[row][column] += blocks[row + 1][column + 1]

# Now have known blocks 40=[3][1], 151=[1][1] and Y=X+Z to determine X,Y,Z.
let vars = Solve2x2(blocks[1][1].x,
                    blocks[1][1].y,
                    151 - blocks[1][1].known,
                    blocks[3][1].x,
                    blocks[3][1].y,
                    40 - blocks[3][1].known)

# Print the results.
for row in 1..5:
  var line = ""
  for column in 1..row:
    line.addSep(" ")
    line.add toString(blocks[row][column], vars)
  echo line


%% to compile : ozc -x <file.oz>
functor

import
  System Application FD Search
define

  proc{Quest Root Rules}

    proc{Limit Rc Ls}
      case Ls of nil then skip
      [] X|Xs then
        {Limit Rc Xs}
        case X of N#V then
          Rc.N =: V
        [] N1#N2#N3 then
          Rc.N1 =: Rc.N2 + Rc.N3
        end
      end
    end

    proc {Pyramid R}
      {FD.tuple solution 15 0#FD.sup R}  %% non-negative integers domain
  %%          01      , pyramid format
  %%        02  03
  %%      04  05  06
  %%    07  08  09  10
  %%  11  12  13  14  15
      R.1 =: R.2 + R.3     %% constraints of Pyramid of numbers
      R.2 =: R.4 + R.5
      R.3 =: R.5 + R.6
      R.4 =: R.7 + R.8
      R.5 =: R.8 + R.9
      R.6 =: R.9 + R.10
      R.7 =: R.11 + R.12
      R.8 =: R.12 + R.13
      R.9 =: R.13 + R.14
      R.10 =: R.14 + R.15

      {Limit R Rules}      %% additional constraints

      {FD.distribute ff R}
    end
  in
    {Search.base.one Pyramid Root} %% search for solution
  end

  local
    Root R
  in
    {Quest Root [1#151 4#40 12#11 14#4 13#11#15]} %% supply additional constraint rules
    if {Length Root} >= 1 then
      R = Root.1
      {For 1 15 1
        proc{$ I}
          if {Member I [1 3 6 10]} then
            {System.printInfo R.I#'\n'}
          else
            {System.printInfo R.I#' '}
          end
        end
      }
    else
      {System.showInfo 'No solution found.'}
    end
  end

  {Application.exit 0}
end


Pascals_triangle_puzzle(topvalue=151,leftsidevalue=40,bottomvalue1=11,bottomvalue2=4) = {
y=(topvalue-(4*(bottomvalue1+bottomvalue2)))/7;
x=leftsidevalue-(y+2*bottomvalue1);
z=y-x;
print(x","y","z); }


--
-- demo\rosetta\Pascal_triangle_Puzzle.exw
-- =======================================
--
-- I approached this with a view to solving general pyramid puzzles, not just the one given.
--
-- This little ditty converts the pyramid to rules quite nicely, then uses a modified copy
--  of solveN() from Solving_coin_problems#Phix to solve those simultaneous equations.
--
with javascript_semantics

sequence pyramid = {{151},
                   {"",""},
                  {40,"",""},
                 {"","","",""},
               {"x",11,"y",4,"z"}}

sequence rules = {}

-- each cell in the pyramid is either an integer final value or an equation.
-- initially the equations are strings, we substitute all with triplets of
-- the form {k,x,z} ie k+l*x+m*z, and known values < last row become rules.

for r=5 to 1 by -1 do
    for c=1 to length(pyramid[r]) do
        object prc = pyramid[r][c], equ
        if    prc="x" then  prc = {0,1,0}     -- ie 0 + one x
        elsif prc="y" then  prc = {0,1,1}     -- ie 0 + one x plus one z
        elsif prc="z" then  prc = {0,0,1}     -- ie 0 +            one z
        else
            if prc="" or r<=4 then
                -- examples: x+11 is {0,1,0}+{11,0,0} -> {11,1,0},
                --           11+y is {11,0,0}+{0,1,1} -> {11,1,1},
                --       40=""+"" is {40,0,0}={22,2,1} ==> {18,2,1}
                equ = sq_add(pyramid[r+1][c],pyramid[r+1][c+1])
            end if
            if prc="" then  prc = equ
            else            prc = {prc,0,0}
                            if r<=4 then
                                equ[1] = prc[1]-equ[1]
                                rules = append(rules,equ)
                            end if
            end if
        end if
        pyramid[r][c] = prc
    end for
end for

ppOpt({pp_Nest,1,pp_StrFmt,2,pp_IntCh,false})
?"equations"
pp(pyramid)
?"rules"
pp(rules)   -- {18,2,1} === 18=2x+z
            -- {73,5,6} === 73=5x+6z
puts(1,"=====\n")

assert(length(rules)==2)    -- more work needed!?

-- modified copy of solveN() from Solving_coin_problems.exw as promised, a
-- bit of a sledgehammer to crack a peanut is the phrase you are looking for:
function solveN(sequence rules)
--
-- Based on https://mathcs.clarku.edu/~djoyce/ma105/simultaneous.html
--  aka the ancient Chinese Jiuzhang suanshu ~100 B.C. (!!)
--
-- Example (not related to the task problem):
--  rules = {{18,1,1},{38,1,5}}, ie 18==x+y, 38==x+5y
--  ==> {13,5}, ie x=13, y=5
--
--  In the elimination phase, both x have multipliers of 1, ie both rii and rij are 1,
--  so we can ignore the two sq_mul and just do [sq_sub] (38=x+5y)-(18=x+y)==>(20=4y).
--  Obviously therefore y is 5 and substituting backwards x is 13.
--
-- Example2 (taken from the task problem):
--  rules = {{18,2,1},{73,5,6}}, ie 18==2x+z, 73==5x+6z
--      ==> {{18,2,1},{56,0,7}}, ie rules[2]:=rules[2]*2-rules[1]*5     (eliminate)
--      ==> {{18,2,1},8},        ie rules[2]:=56/7, aka z:=8            (substitute)
--      ==> {{10,2,0},8},        ie rules[1]-=1z                        (substitute)
--      ==> {5,8},               ie rules[1]:=10/2, aka x:=5            (substitute)
--  ==> {5,8}, ie x=5, z=8
--
    sequence ri, rj
    integer l = length(rules), rii, rji
    rules = deep_copy(rules)
    for i=1 to l do
        -- successively eliminate (grow lower left triangle of 0s)
        ri = rules[i]
        assert(length(ri)=l+1)
        rii = ri[i+1]
        assert(rii!=0)  -- (see note below)
        for j=i+1 to l do
            rj = rules[j]
            rji = rj[i+1]
            if rji!=0 then
                rj = sq_sub(sq_mul(rj,rii),sq_mul(ri,rji))
                assert(rj[i+1]==0) -- (job done)
                rules[j] = rj
            end if
        end for
    end for
    for i=l to 1 by -1 do
        -- then substitute each backwards
        ri = rules[i]
        rii = ri[1]/ri[i+1] -- (all else should be 0)
        rules[i] = rii
        for j=i-1 to 1 by -1 do
            rj = rules[j]
            rji = rj[i+1]
            if rji!=0 then
                rules[j] = 0
                rj[1] -= rji*rii
                rj[i+1] = 0
                rules[j] = rj
            end if
        end for
    end for
    return rules
end function

-- Obviously these next two lines directly embody knowledge from the task, and
--  would need changing for an even slightly different version of the problem:
integer {x,z} = solveN(rules),
        y = x+z -- (as per task desc)

printf(1,"x=%d, y=%d, z=%d\n",{x,y,z})

-- finally evaluate all the equations and print it.
for r=1 to length(pyramid) do
    for c=1 to length(pyramid[r]) do
        integer {k, l, m} = pyramid[r][c]
        pyramid[r][c] = k+l*x+m*z
    end for
end for

pp(pyramid)


import cp.

go =>
   puzzle(T, X, Y,Z),
   foreach(TT in T)
     println(TT)
   end,
   println([x=X,y=Y,z=Z]),
   nl,
   fail, % are there any more solutions?
   nl.

% Port of the Prolog solution
puzzle(Ts, X, Y, Z) :-
    Ts =   [ [151],
            [_, _],
          [40, _, _],
         [_, _, _, _],
       [X, 11, Y, 4, Z]],
    Y #= X + Z,
    triangle(Ts),
    Vs = vars(Ts),
    Vs :: 0..10000,
    solve(Vs).

triangle([T|Ts]) :-
  ( Ts = [N|_] -> triangle_(T, N), triangle(Ts) ; true ).

triangle_([], _).
triangle_([T|Ts],[A,B|Rest]) :-
   T #= A + B, triangle_(Ts, [B|Rest]).


:- use_module(library(clpfd)).

puzzle(Ts, X, Y, Z) :-
    Ts =   [ [151],
            [_, _],
          [40, _, _],
         [_, _, _, _],
       [X, 11, Y, 4, Z]],
    Y #= X + Z, triangle(Ts), append(Ts, Vs), Vs ins 0..sup, label(Vs).

triangle([T|Ts]) :- ( Ts = [N|_] -> triangle_(T, N), triangle(Ts) ; true ).

triangle_([], _).
triangle_([T|Ts], [A,B|Rest]) :- T #= A + B, triangle_(Ts, [B|Rest]).

% ?- puzzle(_,X,Y,Z).
% X = 5,
% Y = 13,
% Z = 8 ;


; Known;
; A.
;         [ 151]
;        [a ][b ]
;      [40][c ][d ]
;    [e ][f ][g ][h ]
;  [ X][11][ Y][ 4][ Z]
;
; B.
;  Y = X + Z

Procedure.i SolveForZ(x)
  Protected a,b,c,d,e,f,g,h,z
  For z=0 To 20
    e=x+11: f=11+(x+z): g=(x+z)+4: h=4+z
    If e+f=40
      c=f+g : d=g+h: a=40+c: b=c+d
      If a+b=151
        ProcedureReturn z
      EndIf
    EndIf
  Next z
  ProcedureReturn -1
EndProcedure

Define x=-1, z=0, title$="Pascal's triangle/Puzzle in PureBasic"
Repeat
  x+1
  z=SolveForZ(x)
Until z>=0
MessageRequester(title$,"X="+Str(x)+#CRLF$+"Y="+Str(x+z)+#CRLF$+"Z="+Str(z))


# Pyramid solver
#            [151]
#         [   ] [   ]
#      [ 40] [   ] [   ]
#   [   ] [   ] [   ] [   ]
#[ X ] [ 11] [ Y ] [ 4 ] [ Z ]
#  X -Y + Z = 0

def combine( snl, snr ):

	cl = {}
	if isinstance(snl, int):
		cl['1'] = snl
	elif isinstance(snl, string):
		cl[snl] = 1
	else:
		cl.update( snl)

	if isinstance(snr, int):
		n = cl.get('1', 0)
		cl['1'] = n + snr
	elif isinstance(snr, string):
		n = cl.get(snr, 0)
		cl[snr] = n + 1
	else:
		for k,v in snr.items():
			n = cl.get(k, 0)
			cl[k] = n+v
	return cl

def constrain(nsum, vn ):
	nn = {}
	nn.update(vn)
	n = nn.get('1', 0)
	nn['1'] = n - nsum
	return nn

def makeMatrix( constraints ):
	vmap = set()
	for c in constraints:
		vmap.update( c.keys())
	vmap.remove('1')
	nvars = len(vmap)
	vmap = sorted(vmap)		# sort here so output is in sorted order
	mtx = []
	for c in constraints:
		row = []
		for vv in vmap:
			row.append(float(c.get(vv, 0)))
		row.append(-float(c.get('1',0)))
		mtx.append(row)

	if len(constraints) == nvars:
		print 'System appears solvable'
	elif len(constraints) < nvars:
		print 'System is not solvable - needs more constraints.'
	return mtx, vmap

def SolvePyramid( vl, cnstr ):

	vl.reverse()
	constraints = [cnstr]
	lvls = len(vl)
	for lvln in range(1,lvls):
		lvd = vl[lvln]
		for k in range(lvls - lvln):
			sn = lvd[k]
			ll = vl[lvln-1]
			vn = combine(ll[k], ll[k+1])
			if sn is None:
				lvd[k] = vn
			else:
				constraints.append(constrain( sn, vn ))

	print 'Constraint Equations:'
	for cstr in constraints:
		fset = ('%d*%s'%(v,k) for k,v in cstr.items() )
		print ' + '.join(fset), ' = 0'

	mtx,vmap = makeMatrix(constraints)

	MtxSolve(mtx)

	d = len(vmap)
	for j in range(d):
		print vmap[j],'=', mtx[j][d]

def MtxSolve(mtx):
	# Simple Matrix solver...

	mDim = len(mtx)			# dimension---
	for j in range(mDim):
		rw0= mtx[j]
		f = 1.0/rw0[j]
		for k in range(j, mDim+1):
			rw0[k] *= f

		for l in range(1+j,mDim):
			rwl = mtx[l]
			f = -rwl[j]
			for k in range(j, mDim+1):
				rwl[k] += f * rw0[k]

	# backsolve part ---
	for j1 in range(1,mDim):
		j = mDim - j1
		rw0= mtx[j]
		for l in range(0, j):
			rwl = mtx[l]
			f = -rwl[j]
			rwl[j]    += f * rw0[j]
			rwl[mDim] += f * rw0[mDim]

	return mtx

p = [ [151], [None,None], [40,None,None], [None,None,None,None], ['X', 11, 'Y', 4, 'Z'] ]
addlConstraint = { 'X':1, 'Y':-1, 'Z':1, '1':0 }
SolvePyramid( p, addlConstraint)


#lang racket/base
(require racket/list)

(struct cell (v x z) #:transparent)

(define (cell-add cx cy)
  (cell (+ (cell-v cx) (cell-v cy))
        (+ (cell-x cx) (cell-x cy))
        (+ (cell-z cx) (cell-z cy))))

(define (cell-sub cx cy)
  (cell (- (cell-v cx) (cell-v cy))
        (- (cell-x cx) (cell-x cy))
        (- (cell-z cx) (cell-z cy))))


/*REXX program solves a   (Pascal's)   "Pyramid of Numbers"   puzzle given four values. */
      /* ╔══════════════════════════════════════════════════╗
         ║                             answer               ║
         ║                            /                     ║
         ║              mid          /                      ║
         ║                 \       151                      ║
         ║                  \   ααα   ααα                   ║
         ║                   40    ααα   ααα                ║
         ║               ααα   ααα   ααα   ααα              ║
         ║              x    11     y     4     z           ║
         ║                  /              \                ║
         ║ find:           /                \               ║
         ║ x y z          b                  d              ║
         ╚══════════════════════════════════════════════════╝ */
   do #=2;     _= sourceLine(#);  n= pos('_', _) /* [↓]  this DO loop shows (above) box.*/
   if n\==0  then leave;             say _       /*only display  up to  the above line. */
   end   /*#*/;                      say         /* [↑]  this is a way for in─line doc. */
parse arg  b  d  mid  answer  .                  /*obtain optional variables from the CL*/
if     b=='' |      b==","  then      b=  11     /*Not specified?  Then use the default.*/
if     d=='' |      d==","  then      d=   4     /* "      "         "   "   "     "    */
if    mid='' |    mid==","  then    mid=  40     /* "      "         "   "   "     "    */
if answer='' | answer==","  then answer= 151     /* "      "         "   "   "     "    */
                      big= answer - 4*b - 4*d    /*calculate  BIG  number less constants*/
   do      x=-big  to big
     do    y=-big  to big
     if x+y\==mid - 2*b  then iterate            /*40 = x+2B+Y   ──or──   40-2*11 = x+y */
        do z=-big  to big
        if z \== y - x   then iterate            /*Z  has to equal   Y-X       (Y= X+Z) */
        if x+y*6+z==big  then say right('x =', n)  x  right("y =",n)  y  right('z =',n)  z
        end   /*z*/
     end      /*y*/
   end        /*x*/                              /*stick a fork in it,  we're all done. */


require 'rref'

pyramid = [
           [ 151],
          [nil,nil],
        [40,nil,nil],
      [nil,nil,nil,nil],
    ["x", 11,"y", 4,"z"]
]
pyramid.each{|row| p row}

equations = [[1,-1,1,0]]   # y = x + z

def parse_equation(str)
  eqn = [0] * 4
  lhs, rhs = str.split("=")
  eqn[3] = rhs.to_i
  for term in lhs.split("+")
    case term
    when "x" then eqn[0] += 1
    when "y" then eqn[1] += 1
    when "z" then eqn[2] += 1
    else          eqn[3] -= term.to_i
    end
  end
  eqn
end

-2.downto(-5) do |row|
  pyramid[row].each_index do |col|
    val = pyramid[row][col]
    sum = "%s+%s" % [pyramid[row+1][col], pyramid[row+1][col+1]]
    if val.nil?
      pyramid[row][col] = sum
    else
      equations << parse_equation(sum + "=#{val}")
    end
  end
end

reduced = convert_to(reduced_row_echelon_form(equations), :to_i)

for eqn in reduced
  if eqn[0] + eqn[1] + eqn[2] != 1
    fail "no unique solution! #{equations.inspect} ==> #{reduced.inspect}"
  elsif eqn[0] == 1 then x = eqn[3]
  elsif eqn[1] == 1 then y = eqn[3]
  elsif eqn[2] == 1 then z = eqn[3]
  end
end

puts
puts "x == #{x}"
puts "y == #{y}"
puts "z == #{z}"

answer = []
for row in pyramid
  answer << row.collect {|cell| eval cell.to_s}
end
puts
answer.each{|row| p row}


object PascalTriangle extends App {

  val (x, y, z) = pascal(11, 4, 40, 151)

  def pascal(a: Int, b: Int, mid: Int, top: Int): (Int, Int, Int) = {
    val y = (top - 4 * (a + b)) / 7
    val x = mid - 2 * a - y
    (x, y, y - x)
  }

  println(if (x != 0) s"Solution is: x = $x, y = $y, z = $z" else "There is no solution.")
}


# set up triangle
var rows = 5
var tri = rows.of {|i| (i+1).of { Hash(x => 0, z => 0, v => 0, rhs => nil) } }
tri[0][0]{:rhs} = 151
tri[2][0]{:rhs} = 40
tri[4][0]{:x} = 1
tri[4][1]{:v} = 11
tri[4][2]{:x} = 1
tri[4][2]{:z} = 1
tri[4][3]{:v} = 4
tri[4][4]{:z} = 1

# aggregate from bottom to top
for row in (tri.len ^.. 1) {
    for col in (^tri[row-1]) {
        [:x, :z, :v].each { |key|
            tri[row-1][col]{key} = (tri[row][col]{key} + tri[row][col+1]{key})
        }
    }
}

# find equations
var eqn = gather {
    for r in tri {
        for c in r {
            take([c{:x}, c{:z}, c{:rhs} - c{:v}]) if defined(c{:rhs})
        }
    }
}

# print equations
say "Equations:"
say " x +  z = y"
for x,z,y in eqn { say "#{x}x + #{z}z = #{y}" }

# solve
var f = (eqn[0][1] / eqn[1][1])
{|i| eqn[0][i] -= (f * eqn[1][i]) } << ^3
f = (eqn[1][0] / eqn[0][0])
{|i| eqn[1][i] -= (f * eqn[0][i]) } << ^3

# print solution
say "Solution:"
var x = (eqn[0][2] / eqn[0][0])
var z = (eqn[1][2] / eqn[1][1])
var y = (x + z)
say "x=#{x}, y=#{y}, z=#{z}"


program main;

  class Triangle;
    rand bit [7:0] a,b,c,d,e,f,g,h,X,Y,Z;

    function new();
      randomize;
      $display("     [%0d]",                151);
      $display("    [%0d][%0d]",            a, b);
      $display("   [%0d][%0d][%0d]",        40,c,d);
      $display("  [%0d][%0d][%0d][%0d]",    e,f,g,h);
      $display(" [%0d][%0d][%0d][%0d][%0d]",X,11,Y,4,Z);
    endfunction

    constraint structure {
       151 == a + b;

         a == 40 + c;
         b == c + d;

        40 == e + f;
         c == f + g;
         d == g + h;

         e == X + 11;
         f == 11 + Y;
         g == Y + 4;
         h == 4 + Z;
    };

    constraint extra {
         Y == X + Z;
    };

  endclass

  Triangle answer = new;
endprogram


package require Tcl 8.5
namespace path ::tcl::mathop

set pyramid {
    {151.0 "" "" "" ""}
    {"" "" "" "" ""}
    {40.0 "" "" "" ""}
    {"" "" "" "" ""}
    {x 11.0 y 4.0 z}
}

set equations {{1 -1 1 0}}

proc simplify {terms val} {
    set vars {0 0 0}
    set x 0
    set y 1
    set z 2
    foreach term $terms {
        switch -exact -- $term {
            x - y - z {
                lset vars [set $term] [+ 1 [lindex $vars [set $term]]]
            }
            default {
                set val [- $val $term]
            }
        }
    }
    return [concat $vars $val]
}

for {set row [+ [llength $pyramid] -2]} {$row >= 0} {incr row -1} {
    for {set cell 0} {$cell <= $row} {incr cell } {
	set sum [concat [lindex $pyramid [+ 1 $row] $cell] [lindex $pyramid [+ 1 $row] [+ 1 $cell]]]
	if {[set val [lindex $pyramid $row $cell]] ne ""} {
            lappend equations [simplify $sum $val]
	} else {
            lset pyramid $row $cell  $sum
        }
    }
}

set solution [toRREF $equations]
foreach row $solution {
    lassign $row a b c d
    if {$a + $b + $c > 1} {
        error "problem does not have a unique solution"
    }
    if {$a} {set x $d}
    if {$b} {set y $d}
    if {$c} {set z $d}
}
puts "x=$x"
puts "y=$y"
puts "z=$z"

foreach row $pyramid {
    set newrow {}
    foreach cell $row {
        if {$cell eq ""} {
            lappend newrow ""
        } else {
            lappend newrow [expr [join [string map [list x $x y $y z $z] $cell] +]]
        }
    }
    lappend solved $newrow
}
print_matrix $solved


import "/fmt" for Fmt

var isIntegral = Fn.new { |x, tol| x.fraction.abs <= tol }

var pascal = Fn.new { |a, b, mid, top|
    var yd = (top - 4 * (a + b)) / 7
    if (!isIntegral.call(yd, 0.0001)) return [0, 0, 0]
    var y = yd.truncate
    var x = mid - 2*a - y
    return [x, y, y - x]
}

var sol = pascal.call(11, 4, 40, 151)
if (sol[0] != 0) {
    Fmt.print("Solution is: x = $d, y = $d, z = $d", sol[0], sol[1], sol[2])
} else {
    System.print("There is no solution")
}


proc Print; int N, A, B, C, D, E;
int  I, P;
def  Tab = $09;
[P:= @A;        \point to first number
for I:= N to 5-1 do ChOut(0, Tab);
for I:= 0 to N-1 do
    [IntOut(0, P(I));  ChOut(0, Tab);  ChOut(0, Tab)];
CrLf(0);
];

int N, P, Q, R, S, T, U, V, W, X, Y, Z; \       151
[for X:= 0 to 40-11 do                  \      N   P
    for Z:= 0 to 151-4 do               \    Q   R   S
        [Y:= X+Z;                       \  T   U   V   W
        T:= X+11;                       \X   11  Y   4   Z
        U:= 11+Y;
        V:= Y+4;
        W:= 4+Z;
        if T+U = 40 then
            [R:= U+V;
            S:= V+W;
            N:= 40+R;
            P:= R+S;
            if N+P = 151 then
                [Print(1, 151);
                 Print(2, N, P);
                 Print(3, 40, R, S);
                 Print(4, T, U, V, W);
                 Print(5, X, 11, Y, 4, Z);
                 exit;
                ];
            ];
        ];
]


T.enum Piece
   EMPTY
   BLACK
   WHITE

F isAttacking(queen, pos)
   R queen.x == pos.x
   | queen.y == pos.y
   | abs(queen.x - pos.x) == abs(queen.y - pos.y)

F place(m, n, &pBlackQueens, &pWhiteQueens)
   I m == 0
      R 1B

   V placingBlack = 1B
   L(i) 0 .< n
      L(j) 0 .< n
         V pos = (i, j)
         L(queen) pBlackQueens
            I queen == pos | (!placingBlack & isAttacking(queen, pos))
               L.break
         L.was_no_break
            L(queen) pWhiteQueens
               I queen == pos | (placingBlack & isAttacking(queen, pos))
                  L.break
            L.was_no_break
               I placingBlack
                  pBlackQueens [+]= pos
                  placingBlack = 0B
               E
                  pWhiteQueens [+]= pos
                  I place(m - 1, n, &pBlackQueens, &pWhiteQueens)
                     R 1B
                  pBlackQueens.pop()
                  pWhiteQueens.pop()
                  placingBlack = 1B

   I !placingBlack
      pBlackQueens.pop()
   R 0B

F printBoard(n, blackQueens, whiteQueens)
   V board = [Piece.EMPTY] * (n * n)

   L(queen) blackQueens
      board[queen.x * n + queen.y] = Piece.BLACK

   L(queen) whiteQueens
      board[queen.x * n + queen.y] = Piece.WHITE

   L(b) board
      V i = L.index
      I i != 0 & i % n == 0
         print()
      I b == BLACK
         print(‘B ’, end' ‘’)
      E I b == WHITE
         print(‘W ’, end' ‘’)
      E
         V j = i I/ n
         V k = i - j * n
         I j % 2 == k % 2
            print(‘x ’, end' ‘’)
         E
            print(‘o ’, end' ‘’)
   print("\n")

V nms = [
          (2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (4, 3),
          (5, 1), (5, 2), (5, 3), (5, 4), (5, 5),
          (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6),
          (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (7, 7)
        ]

L(nm) nms
   print(‘#. black and #. white queens on a #. x #. board:’.format(nm[1], nm[1], nm[0], nm[0]))
   [(Int, Int)] blackQueens, whiteQueens
   I place(nm[1], nm[0], &blackQueens, &whiteQueens)
      printBoard(nm[0], blackQueens, whiteQueens)
   E
      print("No solution exists.\n")