Shape-Machine: Difference between revisions

Content deleted Content added
Added Algol W
Chkas (talk | contribs)
Added Easylang
 
(54 intermediate revisions by 14 users not shown)
Line 1:
{{draft task}}'''Task''' [[Category:Simple]]
'''Task''':
Get user input and then add 3, multiply that 0.86 and repeat forever. You can halt the loop and count how many times does the operation happen, this is optional
 
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.
==See Also==
* [https://esolangs.org/wiki/Shape-Machine Esolangs.org page]
Line 16 ⟶ 20:
 
===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).
<syntaxhighlight lang="algol68">
BEGIN
Line 52 ⟶ 56:
231 repetitions
</pre>
 
===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.
 
<syntaxhighlight lang="algol68">
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
</syntaxhighlight>
{{out}}
With 451 as the input value
<pre>
390.44000
338.35840
293.56824
...
18.42858
18.42858
18.42858
120 repetitions
</pre>
 
With 4 as the input value
<pre>
6.02000
7.75720
9.25119
10.53603
11.64098
...
18.42857
18.42857
18.42857
97 repetitions</pre>
 
=={{header|ALGOL W}}==
Line 69 ⟶ 118:
</syntaxhighlight>
{{out}}
With 4 as the input
<pre>
6.02000
Line 83 ⟶ 133:
18.42857
...
</pre>
 
==BASIC==
{{works with|BBC BASIC}}
{{works with|Atari BASIC}}
{{works with|ProgressBASIC}}
<sub>''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''</sub>
<syntaxhighlight lang="BASIC">
10 INPUT I$
20 LET I = I + 3
30 LET I = I * 0.86
40 PRINT I
50 GOTO 20
</syntaxhighlight>
 
==={{header|ANSI BASIC}}===
{{trans|FreeBASIC}}
{{works with|Decimal BASIC}}
<syntaxhighlight lang="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
</syntaxhighlight>
{{out}}
With 4 as the input.
<pre>
6.02
7.7572
9.251192
10.53602512
11.6409816032
12.591244178752
13.4084699937267
</pre>
...
<pre>
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.
</pre>
The output may vary depending on implementation.
 
==={{header|Applesoft BASIC}}===
<pre>
10 INPUT "num:"; I : I = INT(I)
11 LET I = I + 3
12 LET I = I * 0.86
20 PRINT I
21 GOTO 11
</pre>
 
==={{Header|BASIC256}}===
input integer i
re: #
i += 3
i *= 0.86
? i
goto re
 
==={{header|Commodore BASIC}}===
{{trans|FreeBASIC}}
{{works with|Commodore BASIC|3.5}}
<syntaxhighlight lang="basic">
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
</syntaxhighlight>
{{out}}
With 4 as the input.
<pre>
6.02
7.75720001
9.25119201
10.5360251
11.6409816
12.5912442
13.40847
</pre>
...
<pre>
18.4285713
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
18.4285714
TOOK 134 ITERATIONS.
</pre>
 
==={{header|FreeBASIC}}===
<syntaxhighlight lang="vbnet">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</syntaxhighlight>
{{out}}
With 4 as the input
<pre> 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.
</pre>
 
==={{header|Liberty BASIC}}===
{{trans|FreeBASIC}}
{{works with|Just BASIC}}
<syntaxhighlight lang="lb">
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
</syntaxhighlight>
{{out}}
With 4 as the input.
<pre>
6.02
7.7572
9.251192
10.5360251
11.6409816
12.5912442
13.40847
</pre>
...
<pre>
18.4285714
18.4285714
18.4285714
Took 231 iterations.
</pre>
 
==={{header|Minimal BASIC}}===
{{trans|FreeBASIC}}
{{works with|BASICA}}
<syntaxhighlight lang="basic">
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
</syntaxhighlight>
 
=={{header|EasyLang}}==
<syntaxhighlight lang=text>
numfmt 15 0
n = 4
while n <> prev
prev = n
n = (n + 3) * 0.86
cnt += 1
.
print n & " (after " & cnt & " iterations)"
</syntaxhighlight>
{{out}}
<pre>
18.428571428571416 (after 231 iterations)
</pre>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// 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)</syntaxhighlight>
{{out}}
<pre>
starting with -72.87210186675565637415274977684020996093750000000000 produces 18.42857142857141283798227959778159856796264648437500 after 242 iterations
</pre>
 
=={{header|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:
<syntaxhighlight lang="jq">
input | recurse(. + 3 | . * 0.86)
</syntaxhighlight>
 
To examine the first five generated items, we could use the shell's `head` utility, e.g. as follows:
<pre>
$ jq -n ' input | recurse(. + 3 | . * 0.86)' <<< 0 | head -n 5
0
2.58
4.7988
6.706968
8.34799248
</pre>
 
Notice that the output of `recurse` includes the input value.
 
To limit the generator programmatically, one could use the `limit/2` built-in:
<pre>
$ jq -n --argjson n 5 'input | limit($n; recurse(. + 3 | . * 0.86))' <<< 1
1
3.44
5.538399999999999
7.343023999999999
8.89500064
</pre>
 
One way to suppress the first item produced by the generator would be to use `whilst/1`:
<syntaxhighlight lang="jq">
# 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)
</syntaxhighlight>
 
To stop when the generated number satisfies `trunc == 18`,
one could use the following filter:
<syntaxhighlight lang="jq">
whilst(trunc != 18; . + 3 | . * 0.86)
</syntaxhighlight>
 
To determine how many iterations it takes until the truncated value is 18,
one could use `until/2`:
<pre>
$ jq -n '{i:input} | until(.i|trunc == 18; .i += 3 | .i *= 0.86 | .n+=1)' <<< 0
{
"i": 18.003997862641942,
"n": 25
}
</pre>
 
To determine how many iterations it takes until quiescence:
<syntaxhighlight lang="jq">
{a: input}
| until(.aprime == .a;
.i += 1
| .aprime=.a
| .a += 3 | .a *= 0.86)
</syntaxhighlight>
 
Using an initial value of 0, jq produces the result:
<syntaxhighlight lang="jq">
{"a":18.428571428571416,"i":233,"aprime":18.428571428571416}
</syntaxhighlight>
 
=={{header|Julia}}==
<syntaxhighlight lang="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 --> ")
input = something(tryparse(BigFloat, readline()), big"0.0")
print("Enter number of decimal places --> ")
decimals = something(tryparse(Int, readline()), 36)
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")
</syntaxhighlight>{{out}}
<pre>
Enter starting value --> 4
Enter number of decimal places --> 36
4.000000 --> 18.428571428571428571428571428571428566 to 36 places after 556 repetitions
</pre>
 
[[File:Plot of iterations for a range of starting values.svg|center|thumb]]
 
<br />
 
 
=={{header|Oberon-07}}==
{{Trans|ALGOL 68}}
<syntaxhighlight lang="modula2">
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.
</syntaxhighlight>
{{out}}
With 4 as the input value, using [[Oberonc (Oberon-07 compiler for the JVM)]] where REAL is 32-bit:
<pre>
6.020000
7.757201
9.251192
10.536025
11.640982
...
18.428562
18.428564
18.428566
18.428568
18.428568
97 repetitions
</pre>
 
With 4 as the input value, using [[OBNC]] where REAL is 64-bit:
<pre>
6.020000E+00
7.757200E+00
9.251192E+00
1.053603E+01
...
1.842857E+01
1.842857E+01
1.842857E+01
231 repetitions</pre>
 
=={{header|Pascal}}==
==={{header|Free Pascal}}===
Take care on windows<br>
"and the extended type is available on all Intel x86 processors, except on the Windows 64-bit platform"<br>
Here I have used Win11.
<syntaxhighlight lang="pascal">
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;
Writeln('Start with value ',after);
repeat
before := after;
after := (before + offset) * factor;
Inc(iterationsCount);
until before = after;
writeln(before: 0: 20, ' after ', iterationsCount, ' iterations');
{$IFDEF WINDOWS}
readln;
{$ENDIF}
end.
</syntaxhighlight>
{{out}}
<pre>
on Windows
Start with value 4.0000000000000000E+000
18.42857142857141600000 after 231 iterations
 
on Linux
Start with value 4.00000000000000000000E+0000
18.42857142857142856850 after 281 iterations
 
Start with value 1.8428571428571420E+001
18.42857142857142000000 after 1 iterations
</pre>
 
=={{header|PascalABC.NET}}==
<syntaxhighlight lang="delphi">
begin
var count := 0;
var n := ReadInteger;
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.
</syntaxhighlight>
{{out}}
<pre>
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
</pre>
 
=={{header|Phix}}==
<syntaxhighlight lang="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)
</syntaxhighlight>
{{out}}
64-bit (which uses 80-bit floats)
<pre>
4.00000000000000000000
6.01999999999999999998
7.75720000000000000067
9.25119200000000000035
...
18.42857142857142856499
18.42857142857142856672
18.42857142857142856845
Took 281 iterations.
</pre>
32-bit (which uses 64-bit floats, as does JavaScript output from p2js)
<pre>
4.0000000000000000
6.0199999999999996
7.7571999999999992
9.2511919999999996
...
18.4285714285714093
18.4285714285714128
18.4285714285714164
Took 231 iterations.
</pre>
 
=={{header|Python}}==
<syntaxhighlight Lang="Python">
a=int(input())
while True:
a += (a+3)*0.86
a *= 0.86
print(a)
</syntaxhighlight>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="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 ( --> )</syntaxhighlight>
 
{{out}}
 
<pre>Starting value: 4
Number of decimal places: 36
18.428571428571428571428571428571428566 to 36 places after 556 iterations.
</pre>
 
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.
 
<syntaxhighlight lang="Quackery"> [ 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 ( --> )</syntaxhighlight>
 
{{out}}
 
<pre>Starting value: 4
Max denominator: 50
18 3/7 after 56 iterations.
</pre>
 
=={{header|Raku}}==
Line 135 ⟶ 792:
</pre>
 
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.)
<pre style="font-family: consolas, inconsolata, monospace; line-height: normal;">
 
For instance, the 1000th iteration, starting with 4 is exactly equal to:
<syntaxhighlight lang="raku" line>say (4.FatRat, (* + 3) × .86 … *)[999]</syntaxhighlight>
{{out}}
<pre>18.428571428571428571428571428571428571428571428571428571428571428518562611055257476711345657046077536086307719590805662205008932637290716748623508143778473712167435511145273975385354947408188479662139937380449451942842937179508680530588633892945763008511616379084707917069957275072200539351914273993965066030011194811876547904839025263224744832595386782011862097471389181893672211696726485532183264057134602403929706908123592993235863786859888156665186026179826816128847575831458378844885123366878611593252686593421606487555134444315938261367778063531536534964127098858136548553001526656285822374662510184388742700972850063038414950295895060044238800011827580857336812976758443609296077801146559738910594736606435132635929690920618270821813108173656217015589361779205162675360527035288967300528197729261443766412283716792164777168702168039406788952779919915570541752416260293860518467707548712088056167502132216420672641269104901942501949966581723902330182247134406759443834453985391637796764689461663270662662993088449741102622767088092813554110022083926515230853581817905105492221230813528825959115645642043759816744064849863722778041272156387348996418369338438534662612609987037043047038131221189442288876209762806085696386445408093086328602555139121446610496274119187899056474561873403444794760343168250250584159942711177776533259811971409762989699214055857046134462937025863660124732727323402691866232023863821613479844954718192492032583994808226027774091320595373377362720291094591511865887665392365641680216202349251077081257991823441611723818589067580880018475492672710607080810164651535155593521646027992098574736200877274039486002214250862949227962977243520217727369412523884625435318388719886</pre>
 
(Notice that that, while very '''precise''', is only '''accurate''' to 64 decimal places.)
 
=={{header|RPL}}==
===Iterative approach===
{{works with|RPL|HP-49C}}
« 0
'''DO''' OVER 3. + .86 *
SWAP 1 +
'''UNTIL''' ROT PICK3 == '''END'''
"count" →TAG
» '<span style="color:blue">TASK</span>' STO
 
4 <span style="color:blue">TASK</span>
{{out}}
<pre>
2: 18.4285714283
1: count:163
</pre>
===Direct approach===
'X=(X+3)*86/100' SOLVEVX
{{out}}
<pre>
1: X=129/7
</pre>
 
=={{header|Wren}}==
{{libheader|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.
<syntaxhighlight lang="wren">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.")</syntaxhighlight>
 
{{out}}
Sample input/output (abridged):
<pre>
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.
</pre>