# Shape-Machine

Shape-Machine is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Get user input (or store the number somewhere if the programing langauge doesn't support input) and then add 3, multiply that 0.86 and repeat that over and over again.

Optionally, halt the loop when quiescence has been achieved, i.e. when the value does not change, and report that value and the corresponding number of iterations.

## ALGOL 68

### Non-terminating

Translation of: Python
```BEGIN
REAL a := BEGIN INT n; read( n ); n END;
DO
print( ( fixed( a +:= 3 *:= 0.86, -16, 14 ), newline ) )
OD
END```

### Terminating after successive values converge

Based on Raku, using 64-bit floating point (assuming REAL is 64-bit in the implementation you are using - which is very likely these days and true for Algol 68G).

```BEGIN
REAL a      := BEGIN INT n; read( n ); n END;
REAL prev a := IF a = 0 THEN 1 ELSE 0 FI;
INT  count  := 0;
WHILE prev a /= a
DO
count +:= 1;
prev a := a;
print( ( fixed( a +:= 3 *:= 0.86, -16, 14 ), newline ) )
OD;
print( ( whole( count, 0 ), " repetitions" ) )
END```
Output:

With 4 as the input

```6.02000000000000
7.75720000000000
9.25119200000000
10.5360251200000
11.6409816032000
12.5912441787520
13.4084699937267
14.1112841946050
...
18.3988095846536
18.4029762428021
18.4065595688098
...
18.4285714285714
18.4285714285714
18.4285714285714
231 repetitions
```

### 32-bit terminating

If you have an implementation of Algol 68 where SHORT REAL is 32-bit, here's a version that would converge faster to a less precise value. Note that in Algol 68G, both REAL and SHORT REAL are 64-bit. Interestingly, the final value appears to converge to slightly different values depending on the input - presumably because 32-bit floats are more limited in precision.

```BEGIN
INT n; read( ( n, newline ) );
SHORT REAL a      := n;
SHORT REAL prev a := IF a = 0 THEN 1 ELSE 0 FI;
INT  count  := 0;
WHILE prev a /= a
DO
count +:= 1;
prev a := a;
print( ( fixed( a +:= 3 *:= 0.86, -9, 5 ), newline ) )
OD;
print( ( whole( count, 0 ), " repetitions" ) )
END```
Output:

With 451 as the input value

```390.44000
338.35840
293.56824
...
18.42858
18.42858
18.42858
120 repetitions
```

With 4 as the input value

```  6.02000
7.75720
9.25119
10.53603
11.64098
...
18.42857
18.42857
18.42857
97 repetitions```

## ALGOL W

Translation of: Python
```begin
real a;
integer n;
a := n;
while true do begin
a := a + 3;
a := a * 0.86;
write( r_format := "A", r_w := 8, r_d := 5, a )
end
end.```
Output:

With 4 as the input

``` 6.02000
7.75720
9.25119
10.53603
11.64098
12.59124
13.40847
14.11128
...
18.42857
18.42857
18.42857
...
```

## BASIC

Works with: BBC BASIC
Works with: Atari BASIC
Works with: ProgressBASIC

NOTE FROM THE CREATOR OF THE TASK:i haven't tested this code on other interpriters of BASIC. Also \$ is not in the PBASIC keyboard of PB95 8-bit computers

```10 INPUT I\$
20 LET I = I + 3
30 LET I = I * 0.86
40 PRINT I
50 GOTO 20
```

### ANSI BASIC

Translation of: FreeBASIC
Works with: Decimal BASIC
```100 REM Shape-Machine
110 LET Cnt = 1
120 INPUT Prev
130 DO
140    LET Sgte = (Prev + 3) * 0.86
150    IF Prev = Sgte THEN EXIT DO
160    PRINT Sgte
170    LET Prev = Sgte
180    LET Cnt = Cnt + 1
190 LOOP
200 PRINT "Took"; Cnt; "iterations."
210 END
```
Output:

With 4 as the input.

``` 6.02
7.7572
9.251192
10.53602512
11.6409816032
12.591244178752
13.4084699937267
```

...

``` 18.4285714285696
18.4285714285699
18.4285714285701
18.4285714285703
18.4285714285705
18.4285714285706
18.4285714285707
18.4285714285708
18.4285714285709
18.428571428571
18.4285714285711
Took 208 iterations.
```

The output may vary depending on implementation.

### Applesoft BASIC

```10 INPUT "num:"; I : I = INT(I)
11 LET I = I + 3
12 LET I = I * 0.86
20 PRINT I
21 GOTO 11
```

### BASIC256

```input integer i
re: #
i += 3
i *= 0.86
? i
goto re
```

### Commodore BASIC

Translation of: FreeBASIC
Works with: Commodore BASIC version 3.5
```10 REM SHAPE-MACHINE
20 CNT%=1
30 INPUT PREV
40 DO
50 SGTE=(PREV+3)*0.86
60 IF PREV=SGTE THEN EXIT
70 PRINT SGTE
80 PREV=SGTE
90 CNT%=CNT%+1
100 LOOP
110 PRINT "TOOK";CNT%;"ITERATIONS."
120 END
```
Output:

With 4 as the input.

``` 6.02
7.75720001
9.25119201
10.5360251
11.6409816
12.5912442
13.40847
```

...

``` 18.4285713
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
TOOK 134 ITERATIONS.
```

### FreeBASIC

```Dim As Double prev, sgte
Dim As Integer cont = 1

Input " ", prev

Do
sgte = (prev + 3) * 0.86
If prev = sgte Then Exit Do
Print sgte
prev = sgte
cont += 1
Loop

Print "Took"; cont; " iterations."

Sleep
```
Output:

With 4 as the input

``` 6.02
7.757199999999999
9.251192
10.53602512
11.6409816032
12.591244178752
13.40846999372672
14.11128419460498
14.71570440736028
...
18.42857142857134
18.42857142857135
18.42857142857136
18.42857142857137
18.42857142857138
18.42857142857139
18.4285714285714
18.4285714285714
18.42857142857141
18.42857142857141
Took 227 iterations.
```

### Liberty BASIC

Translation of: FreeBASIC
Works with: Just BASIC
```rem Shape-Machine
cnt = 1
input prev
sgte = (prev + 3) * 0.86
do while prev <> sgte
print sgte
prev = sgte
cnt = cnt + 1
sgte = (prev + 3) * 0.86
loop
print "Took "; cnt; " iterations."
end```
Output:

With 4 as the input.

```6.02
7.7572
9.251192
10.5360251
11.6409816
12.5912442
13.40847
```

...

```18.4285714
18.4285714
18.4285714
Took 231 iterations.
```

### Minimal BASIC

Translation of: FreeBASIC
Works with: BASICA
```10 REM Shape-Machine
20 LET C = 1
30 INPUT P
40 LET S = (P+3)*.86
50 IF P = S THEN 100
60 PRINT S
70 LET P = S
80 LET C = C+1
90 GOTO 40
100 PRINT "Took"; C; "iterations."
110 END
```

## EasyLang

```numfmt 15 0
n = 4
while n <> prev
prev = n
n = (n + 3) * 0.86
cnt += 1
.
print n & " (after " & cnt & " iterations)"
```
Output:
```18.428571428571416 (after 231 iterations)
```

## F#

```// Shape-Machine. Nigel Galloway: July 22nd., 2024
let r=System.Random()
let n=Seq.unfold(fun x->Some(x,(x+3.0)*0.86))(r.NextDouble()* -100.0)|>Seq.pairwise|>Seq.takeWhile(fun(n,g)->n<>g)
printfn "starting with %.50f produces %.50f after %d iterations" (fst(Seq.head n)) (fst(Seq.last n)) (Seq.length n)
```
Output:
```starting with -72.87210186675565637415274977684020996093750000000000 produces 18.42857142857141283798227959778159856796264648437500 after 242 iterations
```

## jq

Works with jq, the C implementation of jq

Works with gojq, the Go implementation of jq

Works with jaq, the Rust implementation of jq

In accordance with the basic task description, here is a solution that does not terminate:

`input | recurse(. + 3 | . * 0.86)`

To examine the first five generated items, we could use the shell's `head` utility, e.g. as follows:

```\$ jq -n ' input | recurse(. + 3 | . * 0.86)' <<< 0 | head -n 5
0
2.58
4.7988
6.706968
8.34799248
```

Notice that the output of `recurse` includes the input value.

To limit the generator programmatically, one could use the `limit/2` built-in:

```\$ jq -n --argjson n 5 'input | limit(\$n; recurse(. + 3 | . * 0.86))' <<< 1
1
3.44
5.538399999999999
7.343023999999999
8.89500064
```

One way to suppress the first item produced by the generator would be to use `whilst/1`:

```# like while/2 but emit the final term rather than the first one
def whilst(cond; update):
def _whilst:
if cond then update | (., _whilst) else empty end;
_whilst;

input | whilst(true; . + 3 | .  * 0.86)```

To stop when the generated number satisfies `trunc == 18`, one could use the following filter:

`whilst(trunc != 18; . + 3 | .  * 0.86)`

To determine how many iterations it takes until the truncated value is 18, one could use `until/2`:

```\$ jq -n '{i:input} | until(.i|trunc == 18; .i += 3 | .i *= 0.86 | .n+=1)' <<< 0
{
"i": 18.003997862641942,
"n": 25
}
```

To determine how many iterations it takes until quiescence:

```{a: input}
| until(.aprime == .a;
.i += 1
| .aprime=.a
| .a += 3 | .a  *= 0.86)```

Using an initial value of 0, jq produces the result:

`{"a":18.428571428571416,"i":233,"aprime":18.428571428571416}`

## Julia

```using Printf
using Plots

function converge(startvalue, decimals = 36, maxiters = 10000)
current, previous = startvalue, startvalue + 5
for i in 0:maxiters
if abs(previous - current) <= big"10.0"^(-decimals)
return current, i
end
previous = current
current += 3
current *= big"0.86"
end
error("Too many iterations, over \$maxiters")
end

print("Enter starting value --> ")
print("Enter number of decimal places --> ")
endvalue, iters = converge(input, decimals)
@printf("%f --> %.*f to %d places after %d repetitions",
input, decimals, endvalue, decimals, iters)

startvalues = collect(0:0.1:36)
iterationcounts = [last(converge(BigFloat(x))) for x in startvalues]

plot(startvalues, iterationcounts, xlabel = "Starting input",
ylabel = "Iterations to reach 36 digit precision")
```
Output:
```Enter starting value --> 4
Enter number of decimal places --> 36
4.000000 --> 18.428571428571428571428571428571428566 to 36 places after 556 repetitions
```

## Oberon-07

Translation of: ALGOL 68
```MODULE ShapeMachine;
IMPORT In, Out;

VAR a, prevA : REAL;
n, count : INTEGER;

BEGIN
count := 0;
In.Int( n );
a     := FLT( n );
prevA := 0.0;
WHILE prevA # a
DO
INC(count);
prevA := a;
a     := ( a + 3.0 ) * 0.86;
Out.Real( a, 9 );Out.Ln
END;
Out.Int( count, 0 );Out.String( " repetitions" )
END ShapeMachine.
```
Output:

With 4 as the input value, using Oberonc (Oberon-07 compiler for the JVM) where REAL is 32-bit:

``` 6.020000
7.757201
9.251192
10.536025
11.640982
...
18.428562
18.428564
18.428566
18.428568
18.428568
97 repetitions
```

With 4 as the input value, using OBNC where REAL is 64-bit:

```6.020000E+00
7.757200E+00
9.251192E+00
1.053603E+01
...
1.842857E+01
1.842857E+01
1.842857E+01
231 repetitions```

## Pascal

### Free Pascal

Take care on windows
"and the extended type is available on all Intel x86 processors, except on the Windows 64-bit platform"
Here I have used Win11.

```program ShapeMachine;
const
offset = 3.0;
factor = 0.86;
var
before, after: extended;
iterationsCount: uint32;
begin
//x = (x+offset)*factor
//x/factor-x = offset
//x := offset/(1/factor-1) -> factor must be smaller than 1
after := 4;
//  after := offset/(1/factor-1);
iterationsCount := 0;
repeat
before := after;
after := (before + offset) * factor;
Inc(iterationsCount);
until before = after;
writeln(before: 0: 20, ' after ', iterationsCount, ' iterations');
{\$IFDEF WINDOWS}
{\$ENDIF}
end.
```
Output:
```on Windows
18.42857142857141600000 after 231 iterations

on Linux
18.42857142857142856850 after 281 iterations

18.42857142857142000000 after 1 iterations
```

## PascalABC.NET

```begin
var count := 0;
var next: real := n;
var prev: real;
repeat
Writeln(next);
prev := next;
next := (prev + 3) * 0.86;
count += 1;
until prev = next;
Writeln(count);
end.
```
Output:
```4
4
6.02
7.7572
9.251192
10.53602512
11.6409816032
12.591244178752
13.4084699937267
14.111284194605
14.7157044073603
15.2355057903298
15.6825349796837
16.0669800825279
16.397602870974
16.6819384690377
16.9264670833724
17.1367616917003
17.3176150548622
17.4731489471815
17.6069080945761
17.7219409613354
17.8208692267485
17.9059475350037
...
18.4285714285714
18.4285714285714
18.4285714285714
18.4285714285714
18.4285714285714
18.4285714285714
231
```

## Phix

```with javascript_semantics
--atom n = prompt_number("") -- (not js compatible)
atom n = 4
integer count = 0
do
printf(1,"%.20f\n",n)
atom prev = n
n = (n + 3) * 0.86
count += 1
until n==prev
printf(1,"Took %d iterations.\n",count)
```
Output:

64-bit (which uses 80-bit floats)

```4.00000000000000000000
6.01999999999999999998
7.75720000000000000067
9.25119200000000000035
...
18.42857142857142856499
18.42857142857142856672
18.42857142857142856845
Took 281 iterations.
```

32-bit (which uses 64-bit floats, as does JavaScript output from p2js)

```4.0000000000000000
6.0199999999999996
7.7571999999999992
9.2511919999999996
...
18.4285714285714093
18.4285714285714128
18.4285714285714164
Took 231 iterations.
```

## Python

``` a=int(input())
while True:
a=(a+3)*0.86
print(a)
```

## Quackery

```  [ \$ "bigrat.qky" loadfile ] now!

[ stack ]                              is places ( --> s )

[ \$ "Starting value: " input
\$->v drop
\$ "Number of decimal places: " input
\$->n drop places put
0 temp put
[ 1 temp tally
2dup
3 1 v+ 86 100 v*
2swap 2over places share approx=
until ]
places share point\$ echo\$
say " to "
places take echo
say " places after "
temp take echo
say " iterations." cr ]              is task   ( -->   )```
Output:
```Starting value: 4
Number of decimal places: 36
18.428571428571428571428571428571428566 to 36 places after 556 iterations.
```

However…

If, rather than specifying a precision to a number of decimal places, we apply mediant rounding to the rational representation that Quackery uses, after each iteration, with an appropriate maximum value for the denominator, it quickly homes in on the limit of the computation i.e. eighteen and three sevenths.

```  [ stack ]                               is maxval ( --> s )

[ \$ "Starting value: " input
\$->v drop
\$ "Max denominator: " input
\$->n drop maxval put
0 temp put
[ 1 temp tally
2dup
3 1 v+ 86 100 v*
proper maxval share round improper
2swap 2over v- v0= until ]
maxval release
proper\$ echo\$
say " after " temp take echo
say " iterations." cr ]               is task   ( -->   )```
Output:
```Starting value: 4
Max denominator: 50
18 3/7 after 56 iterations.
```

## Raku

```my \$input = (+prompt()).FatRat;
my \$previous = 0.FatRat;
my \$count;
my \$places = 36;
loop {
\$input += 3;
\$input ×= .86;
last if \$previous.substr(0,\$places) eq \$input.substr(0,\$places);
++\$count;
say (\$previous = \$input).substr(0,\$places);
}
say "\$count repetitions";
```
Output with a 4 fed in at the prompt:
```4
6.02
7.7572
9.251192
10.53602512
11.6409816032
12.591244178752
13.40846999372672
14.1112841946049792
14.715704407360282112
15.23550579032984261632
15.6825349796836646500352
16.066980082527951599030272

...
many, many lines omitted
...

18.428571428571428571428571428571416
18.428571428571428571428571428571418
18.428571428571428571428571428571419
18.428571428571428571428571428571420
18.428571428571428571428571428571421
18.428571428571428571428571428571422
18.428571428571428571428571428571423
18.428571428571428571428571428571424
512 repetitions
```

In the latest iteration of the task instructions, we are to optionally "halt the loop when quiescence has been achieved, i.e. when the value does not change". Unless a precision is specified, "quiescence" will never be achieved. This operation adds more places of precision with every iteration, and will never "quiesce". (Unless run on a processor or with a language that is unable to handle high precision.)

For instance, the 1000th iteration, starting with 4 is exactly equal to:

```say (4.FatRat, (* + 3) × .86 … *)[999]
```
Output:
`18.428571428571428571428571428571428571428571428571428571428571428518562611055257476711345657046077536086307719590805662205008932637290716748623508143778473712167435511145273975385354947408188479662139937380449451942842937179508680530588633892945763008511616379084707917069957275072200539351914273993965066030011194811876547904839025263224744832595386782011862097471389181893672211696726485532183264057134602403929706908123592993235863786859888156665186026179826816128847575831458378844885123366878611593252686593421606487555134444315938261367778063531536534964127098858136548553001526656285822374662510184388742700972850063038414950295895060044238800011827580857336812976758443609296077801146559738910594736606435132635929690920618270821813108173656217015589361779205162675360527035288967300528197729261443766412283716792164777168702168039406788952779919915570541752416260293860518467707548712088056167502132216420672641269104901942501949966581723902330182247134406759443834453985391637796764689461663270662662993088449741102622767088092813554110022083926515230853581817905105492221230813528825959115645642043759816744064849863722778041272156387348996418369338438534662612609987037043047038131221189442288876209762806085696386445408093086328602555139121446610496274119187899056474561873403444794760343168250250584159942711177776533259811971409762989699214055857046134462937025863660124732727323402691866232023863821613479844954718192492032583994808226027774091320595373377362720291094591511865887665392365641680216202349251077081257991823441611723818589067580880018475492672710607080810164651535155593521646027992098574736200877274039486002214250862949227962977243520217727369412523884625435318388719886`

(Notice that that, while very precise, is only accurate to 64 decimal places.)

## RPL

### Iterative approach

Works with: RPL version HP-49C
```« 0
DO OVER 3. + .86 *
SWAP 1 +
UNTIL ROT PICK3 == END
"count" →TAG
```
```4 TASK
```
Output:
```2: 18.4285714283
1: count:163
```

### Direct approach

```'X=(X+3)*86/100' SOLVEVX
```
Output:
```1: X=129/7
```

## Wren

Library: Wren-ioutil

This repeats until the next number (a 64 bit float) equals the previous number which will usually be sometime later than their string/display values (normally limited to 14 digits in Wren CLI) are equal.

```import "./ioutil" for Input

var prev = Input.number("")
var count = 1
while (true) {
var next = (prev + 3) * 0.86
if (prev == next) break
System.print(prev = next)
count = count + 1
}
System.print("Took %(count) iterations.")
```
Output:

Sample input/output (abridged):

```4
6.02
7.7572
9.251192
10.53602512
11.6409816032
12.591244178752
13.408469993727
14.111284194605
14.71570440736
...
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
Took 231 iterations.
```

## XPL0

Translation of: Python
```real A;
[A:= RlIn(0);
while true do
[A:= A+3.;
A:= A*0.86;
RlOut(0, A);
];
]```
Output:
```123
108.36000 95.76960 84.94186 75.63000 67.62180 60.73475 54.81188 49.71822
45.33767 41.57039 38.33054 35.54426 33.14807 31.08734 29.31511 27.79099
26.48026 25.35302 24.38360 23.54989 22.83291 22.21630 21.68602 21.22998
20.83778 20.50049 20.21042 19.96096 19.74643 19.56193 19.40326 19.26680
19.14945 19.04853 18.96173 18.88709 18.82290 18.76769 18.72022 18.67939
18.64427 18.61407 18.58810 18.56577 18.54656 18.53004 18.51584 18.50362
18.49311 18.48408 18.47631 18.46962 18.46388 18.45893 18.45468 18.45103
18.44788 18.44518 18.44285 18.44085 18.43914 18.43766 18.43638 18.43529
18.43435 18.43354 18.43285 18.43225 18.43173 18.43129 18.43091 18.43058
18.43030 18.43006 18.42985 18.42967 18.42952 18.42938 18.42927 18.42917
18.42909 18.42902 18.42895 18.42890 18.42885 18.42881 18.42878 18.42875
18.42873 18.42870 18.42869 18.42867 18.42866 18.42864 18.42863 18.42863
18.42862 18.42861 18.42861 18.42860 18.42860 18.42859 18.42859 18.42859
18.42859 18.42858 18.42858 18.42858 18.42858 18.42858 18.42858 18.42858
18.42858 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857
18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857
18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857
```