Shape-Machine: Difference between revisions
m →{{header|Phix}}: clarified bit sizes |
|||
Line 376: | Line 376: | ||
</syntaxhighlight> |
</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
64-bit (which uses 80-bit floats) |
|||
64-bit |
|||
<pre> |
<pre> |
||
4.00000000000000000000 |
4.00000000000000000000 |
||
Line 388: | Line 388: | ||
Took 281 iterations. |
Took 281 iterations. |
||
</pre> |
</pre> |
||
32-bit (which uses 64-bit floats, as does JavaScript output from p2js) |
|||
32-bit |
|||
<pre> |
<pre> |
||
4.0000000000000000 |
4.0000000000000000 |
Revision as of 08:25, 14 July 2024
Task
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
ALGOL 68
Non-terminating
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
begin
real a;
integer n;
read( 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
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
BASIC
NOTE FROM THE CREATOR OF THE TASK:i haven't tested this code on other interpriters of BASIC
10 INPUT I$
20 LET I = I + 3
30 LET I = I * 0.86
40 PRINT I
50 GOTO 20
BASIC256
input integer i re: # i += 3 i *= 0.86 ? i goto re
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.
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 --> ")
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")
- Output:
Enter starting value --> 4 Enter number of decimal places --> 36 4.000000 --> 18.428571428571428571428571428571428566 to 36 places after 556 repetitions
Oberon-07
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
count := count + 1;
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.
6.020000 7.757201 9.251192 10.536025 11.640982 ... 18.428562 18.428564 18.428566 18.428568 18.428568 97 repetitions
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)
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.)
Wren
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
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