Shape-Machine
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
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
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
Chipmunk Basic
100 cls
110 cnt = 1
120 input prev
130 while 1
140 sgte = (prev+3)*0.86
150 if prev = sgte then exit while
160 print sgte
170 prev = sgte
180 cnt = cnt+1
190 wend
200 print "Took ";cnt;"iterations."
210 end
Commodore 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
- 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 cnt = 1
Input " ", prev
Do
sgte = (prev + 3) * 0.86
If prev = sgte Then Exit Do
Print sgte
prev = sgte
cnt += 1
Loop
Print !"\nTook"; cnt; " 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.
GW-BASIC
The MSX BASIC solution works without any changes.
Liberty 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
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
MSX Basic
10 cnt = 1
20 input prev
30 'while 1
40 sgte = (prev+3)*0.86
50 if prev = sgte then goto 100
60 print sgte
70 prev = sgte
80 cnt = cnt+1
90 goto 30
100 print "Took";cnt;"iterations."
110 end
OxygenBasic
uses console
double prev, sgte
int cnt
cnt = 1
input() prev
do
sgte = (prev + 3) * 0.86
if prev = sgte then exit do
printl sgte
prev = sgte
cnt ++
loop
printl cr "Took " cnt " iterations."
waitkey
PureBasic
OpenConsole()
Define.d prev, sgte
Define.i cnt = 1
Define.s kbd$
kbd$ = Input()
prev = ValD(kbd$)
While #True
sgte = (prev + 3) * 0.86
If prev = sgte
Break
EndIf
PrintN(StrD(sgte))
prev = sgte
cnt + 1
Wend
PrintN(#CRLF$ + "Took " + Str(cnt) + " iterations.")
PrintN(#CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
QBasic
DIM prev AS DOUBLE, sgte AS DOUBLE
DIM cnt AS INTEGER
cnt = 1
INPUT prev
sgte = (prev + 3) * .86
WHILE prev <> sgte
PRINT sgte
prev = sgte
cnt = cnt + 1
sgte = (prev + 3) * .86
WEND
PRINT "Took "; cnt; " iterations."
END
QB64
The QBasic solution works without any changes.
Quite 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
Run BASIC
rem Shape-Machine
cnt = 1
input prev
sgte = (prev + 3) * 0.86
while prev <> sgte
print sgte
prev = sgte
cnt = cnt + 1
sgte = (prev + 3) * 0.86
wend
print "Took "; cnt; " iterations."
end
True BASIC
LET cnt = 1
INPUT prev
LET sgte = (prev + 3) * .86
DO WHILE prev <> sgte
PRINT sgte
LET prev = sgte
LET cnt = cnt + 1
LET sgte = (prev + 3) * .86
LOOP
PRINT "Took "; cnt; " iterations."
END
XBasic
PROGRAM "Shape-Machine"
VERSION "0.0000"
DECLARE FUNCTION Entry ()
FUNCTION Entry ()
cnt& = 1
kbd$ = INLINE$("")
prev# = DOUBLE(kbd$)
DO
sgte# = (prev# + 3) * 0.86
IF prev# = sgte# THEN EXIT DO
PRINT sgte#
prev# = sgte#
INC cnt&
LOOP
PRINT "Took"; cnt&; " iterations."
END FUNCTION
END PROGRAM
Yabasic
c = 1
input " " prev
do
sgte = (prev + 3) * 0.86
if prev = sgte break
print sgte
prev = sgte
c = c + 1
loop
print "Took ", c, " iterations."
end
- Output:
Same as FreeBASIC entry.
C++
#include <cstdint>
#include <iomanip>
#include <iostream>
int main() {
double user_choice;
std::cout << "Enter a number: ";
std::cin >> user_choice;
const double epsilon = 0.000'000'000'000'1;
uint32_t iterations = 0;
double previous = 0.0;
double current = user_choice;
while ( std::abs(current - previous) > epsilon ) {
previous = current;
current = ( current + 3.0 ) * 0.86;
iterations++;
}
std::cout << user_choice << " converged to " << std::fixed << std::setprecision(12)
<< current << " after " << iterations << " iterations." << std::endl;
}
- Output:
Enter a number: -72 -72 converged to 18.428571428571 after 217 iterations.
DuckDB
In the following, the way the functions are invoked will determine the precision of the computation, as illustrated by the two results shown.
To make it easy to write variations, a table-valued function is first defined:
create or replace function shape_machine_table(start, r) as table (
with recursive cte as (
select 0 as i, (start-1) as prev, start as x,
union all
select i+1 as i,
x as prev,
(x+3) * r as x
from cte
where x != prev
)
from cte
);
# Report the number of iterations required to achieve quiescence, and
# the value at quiescence:
create or replace function shape_machine_quiescence(start, r) as (
select (last(i), last(x))
from shape_machine_table(start, r)
);
.print FLOAT results:
select shape_machine_quiescence(0.0::FLOAT, 0.86);
.print DOUBLE results:
select shape_machine_quiescence(0.0::DOUBLE, 0.86);
- Output:
FLOAT results: ┌────────────────────────────────────────────────────┐ │ shape_machine_quiescence(CAST(0.0 AS FLOAT), 0.86) │ │ struct(integer, float) │ ├────────────────────────────────────────────────────┤ │ (99, 18.428568) │ └────────────────────────────────────────────────────┘ DOUBLE results: ┌─────────────────────────────────────────────────────┐ │ shape_machine_quiescence(CAST(0.0 AS DOUBLE), 0.86) │ │ struct(integer, double) │ ├─────────────────────────────────────────────────────┤ │ (233, 18.428571428571416) │ └─────────────────────────────────────────────────────┘
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)
FutureBasic
The results make better sense when the precision of the floats is carried to 15 decimal places for each iteration.
include "NSLog.incl"
begin globals
double nxt
NSInteger cnt
end globals
local fn ShapeMachine( prv as double )
while (YES)
nxt = (prv + 3) * 0.86
if prv == nxt
NSLog( @"\n\tTook %d iterations.\n\n", cnt )
exit fn
end if
NSLog( @"%3d. %.15f", cnt, nxt )
prv = nxt
cnt++
wend
end fn
cnt = 1
fn ShapeMachine( 4 )
HandleEvents
- Output:
1. 6.020000000000000 2. 7.757199999999999 3. 9.251192000000000 4. 10.536025120000000 5. 11.640981603200000 6. 12.591244178752000 7. 13.408469993726719 8. 14.111284194604979 9. 14.715704407360279 10. 15.235505790329839 11. 15.682534979683661 12. 16.066980082527948 13. 16.397602870974033 14. 16.681938469037668 15. 16.926467083372394 16. 17.136761691700258 17. 17.317615054862223 18. 17.473148947181510 19. 17.606908094576099 20. 17.721940961335445 21. 17.820869226748481 22. 17.905947535003694 23. 17.979114880103175 24. 18.042038796888729 25. 18.096153365324305 26. 18.142691894178903 27. 18.182715028993854 28. 18.217134924934715 29. 18.246736035443856 30. 18.272192990481717 31. 18.294085971814276 32. 18.312913935760278 33. 18.329105984753838 34. 18.343031146888300 35. 18.355006786323937 36. 18.365305836238587 37. 18.374163019165184 38. 18.381780196482058 39. 18.388330968974568 40. 18.393964633318127 41. 18.398809584653588 42. 18.402976242802087 43. 18.406559568809794 44. 18.409641229176422 45. 18.412291457091722 46. 18.414570653098881 47. 18.416530761665037 48. 18.418216455031931 49. 18.419666151327462 50. 18.420912890141619 51. 18.421985085521790 52. 18.422907173548740 53. 18.423700169251916 54. 18.424382145556649 55. 18.424968645178719 56. 18.425473034853699 57. 18.425906809974180 58. 18.426279856577793 59. 18.426600676656900 60. 18.426876581924933 61. 18.427113860455442 62. 18.427317919991680 63. 18.427493411192845 64. 18.427644333625846 65. 18.427774126918226 66. 18.427885749149674 67. 18.427981744268720 68. 18.428064300071100 69. 18.428135298061147 70. 18.428196356332585 71. 18.428248866446022 72. 18.428294025143579 73. 18.428332861623478 74. 18.428366260996189 75. 18.428394984456723 76. 18.428419686632783 77. 18.428440930504191 78. 18.428459200233604 79. 18.428474912200898 80. 18.428488424492773 81. 18.428500045063785 82. 18.428510038754855 83. 18.428518633329176 84. 18.428526024663093 85. 18.428532381210260 86. 18.428537847840822 87. 18.428542549143106 88. 18.428546592263071 89. 18.428550069346240 90. 18.428553059637768 91. 18.428555631288479 92. 18.428557842908091 93. 18.428559744900959 94. 18.428561380614823 95. 18.428562787328747 96. 18.428563997102721 97. 18.428565037508339 98. 18.428565932257172 99. 18.428566701741168 100. 18.428567363497404 101. 18.428567932607766 102. 18.428568422042680 103. 18.428568842956704 104. 18.428569204942765 105. 18.428569516250779 106. 18.428569783975668 107. 18.428570014219073 108. 18.428570212228401 109. 18.428570382516423 110. 18.428570528964123 111. 18.428570654909144 112. 18.428570763221863 113. 18.428570856370801 114. 18.428570936478888 115. 18.428571005371843 116. 18.428571064619785 117. 18.428571115573014 118. 18.428571159392792 119. 18.428571197077801 120. 18.428571229486909 121. 18.428571257358740 122. 18.428571281328516 123. 18.428571301942522 124. 18.428571319670567 125. 18.428571334916686 126. 18.428571348028349 127. 18.428571359304382 128. 18.428571369001769 129. 18.428571377341520 130. 18.428571384513706 131. 18.428571390681785 132. 18.428571395986335 133. 18.428571400548247 134. 18.428571404471491 135. 18.428571407845482 136. 18.428571410747114 137. 18.428571413242519 138. 18.428571415388568 139. 18.428571417234167 140. 18.428571418821384 141. 18.428571420186390 142. 18.428571421360296 143. 18.428571422369853 144. 18.428571423238072 145. 18.428571423984742 146. 18.428571424626877 147. 18.428571425179115 148. 18.428571425654038 149. 18.428571426062472 150. 18.428571426413725 151. 18.428571426715802 152. 18.428571426975591 153. 18.428571427199007 154. 18.428571427391145 155. 18.428571427556385 156. 18.428571427698490 157. 18.428571427820700 158. 18.428571427925803 159. 18.428571428016191 160. 18.428571428093925 161. 18.428571428160776 162. 18.428571428218266 163. 18.428571428267709 164. 18.428571428310228 165. 18.428571428346796 166. 18.428571428378245 167. 18.428571428405291 168. 18.428571428428551 169. 18.428571428448553 170. 18.428571428465755 171. 18.428571428480549 172. 18.428571428493271 173. 18.428571428504213 174. 18.428571428513624 175. 18.428571428521717 176. 18.428571428528677 177. 18.428571428534664 178. 18.428571428539811 179. 18.428571428544238 180. 18.428571428548043 181. 18.428571428551315 182. 18.428571428554132 183. 18.428571428556552 184. 18.428571428558634 185. 18.428571428560424 186. 18.428571428561966 187. 18.428571428563291 188. 18.428571428564432 189. 18.428571428565412 190. 18.428571428566254 191. 18.428571428566979 192. 18.428571428567601 193. 18.428571428568137 194. 18.428571428568599 195. 18.428571428568993 196. 18.428571428569335 197. 18.428571428569626 198. 18.428571428569878 199. 18.428571428570095 200. 18.428571428570280 201. 18.428571428570439 202. 18.428571428570578 203. 18.428571428570695 204. 18.428571428570798 205. 18.428571428570887 206. 18.428571428570962 207. 18.428571428571026 208. 18.428571428571082 209. 18.428571428571132 210. 18.428571428571175 211. 18.428571428571210 212. 18.428571428571242 213. 18.428571428571267 214. 18.428571428571288 215. 18.428571428571306 216. 18.428571428571324 217. 18.428571428571338 218. 18.428571428571349 219. 18.428571428571360 220. 18.428571428571370 221. 18.428571428571377 222. 18.428571428571384 223. 18.428571428571392 224. 18.428571428571395 225. 18.428571428571399 226. 18.428571428571402 227. 18.428571428571406 228. 18.428571428571409 229. 18.428571428571413 230. 18.428571428571416 Took 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
Java
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Scanner;
public final class ShapeMachine {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Enter a number: ");
final BigDecimal userChoice = reader.nextBigDecimal();
System.out.print("Enter a number of decimal places: ");
final int decimalPlaces = reader.nextInt();
reader.close();
final BigDecimal epsilon = BigDecimal.TEN.pow(-decimalPlaces - 1, MathContext.DECIMAL128);
int iterations = 0;
BigDecimal previous = BigDecimal.ZERO;
BigDecimal current = userChoice;
while ( current.subtract(previous).abs().compareTo(epsilon) > 0 ) {
previous = current;
current = current.add(THREE).multiply(ZERO86);
iterations += 1;
}
final BigDecimal result = current.setScale(decimalPlaces, RoundingMode.HALF_UP);
System.out.println(userChoice + " converged to " + result + " after " + iterations + " iterations.");
}
private static final BigDecimal THREE = new BigDecimal("3.0");
private static final BigDecimal ZERO86 = new BigDecimal("0.86");
}
- Output:
Enter a number: -72 Enter a number of decimal places: 30 -72 converged to 18.428571428571428571428571428571 after 492 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
M2000 Interpreter
An OOP example. Tests for different type of variable. Decimal point is "," for Greeks (by default the decimal point is the systme one, we can use GREEK or LATIN or LOCALE 1032 or any other language ID). For code always decimal point is ".".
superclass MainTest {
unique:
document Doc$
module PutValue {
.Doc$<=letter$+{
}
}
public:
property counter{value}=0
function result {
for superclass {
=.Doc$
}
}
module Test1 (thisType, ThisValue) {
select case thistype
case 0
single a
case 1
double a
case 3
currency a
case else
decimal a
end select
a=ThisValue
aa=a
.[counter]++
long long i=1
do
o=a
a+=3 ' double literal value
a*=.86 ' double literal value
if o=a then exit
i++
always
for superclass {
.PutValue format$("{0:8} {1:2:-12} {2::-3} {3}",type$(aa), aa, i, a)
}
}
}
document result$
dim a(0 to 3)=MainTest
for i=0 to 3
a(i).test1 i, 4
a(i).test1 i, 123456789
result$ = "test on a("+i+") so far:"+a(i).counter+{
}
next
result$ = "Results" + {
}+a(1).result()
clipboard result$
Print #-2, result$
- Output:
test on a(0) so far:2 test on a(0) so far:2 test on a(1) so far:2 test on a(2) so far:2 test on a(3) so far:2 Results Single 4.00 97 18.42857 Single 1.23E+8 203 18.42858 Double 4.00 231 18.4285714285714 Double 123456789.00 336 18.4285714285714 Decimal 4.00 423 18.428571428571428571428571426 Decimal 123456789.00 528 18.428571428571428571428571432 Currency 4.00 72 18.4283 Currency 123456789.00 176 18.4289
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
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;
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.
- Output:
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
PascalABC.NET
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.
- 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
« 0
DO OVER 3. + .86 *
SWAP 1 +
UNTIL ROT PICK3 == END
"count" →TAG
» 'TASK' STO
4 TASK
- Output:
2: 18.4285714283 1: count:163
Direct approach
'X=(X+3)*86/100' SOLVEVX
- Output:
1: X=129/7
Rust
fn converge(start_value: f64) -> (f64, i32) {
let mut current = start_value;
let mut previous = start_value + 5.0;
let mut i: i32 = 0;
loop {
if (previous - current).abs() <= f64::EPSILON {
return (current, i);
}
previous = current;
current += 3.0;
current *= 0.86;
i += 1;
}
}
fn main() {
let start_value = 4.0;
let (end_value, iterations) = converge(start_value);
println!(
"\n{} --> {} to epsilon of {} after {} repetitions\n",
start_value,
end_value,
f64::EPSILON,
iterations
);
}
- Output:
4 --> 18.428571428571416 to epsilon of 0.0000000000000002220446049250313 after 231 repetitions
V (Vlang)
import os
fn main() {
mut prev, mut next := f64(0), f64(0)
mut count := 1
for prev < 1 {
prev = os.input_opt("Enter a number: ") or {panic(err)}.f64()
}
for {
println("${next}")
next = (prev + 3) * 0.86
if prev == next {break}
prev = next
count++
}
print("Took ${count} iterations.")
}
- Output:
Enter a number: 4 0.0 6.02 7.757199999999999 9.251192 10.53602512 11.6409816032 12.591244178752 13.408469993726719 14.111284194604979 14.71570440736028 ... 18.428571428571384 18.42857142857139 18.428571428571395 18.4285714285714 18.428571428571402 18.428571428571406 18.42857142857141 18.428571428571413 18.428571428571416 Took 231 iterations.
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
- Draft Programming Tasks
- Simple
- ALGOL 68
- ALGOL W
- BASIC
- ANSI BASIC
- Applesoft BASIC
- BASIC256
- Chipmunk Basic
- Commodore BASIC
- FreeBASIC
- GW-BASIC
- Liberty BASIC
- Minimal BASIC
- MSX Basic
- OxygenBasic
- PureBasic
- QBasic
- QB64
- Quite BASIC
- Run BASIC
- True BASIC
- XBasic
- Yabasic
- C++
- DuckDB
- EasyLang
- FutureBasic
- F Sharp
- Java
- Jq
- Julia
- M2000 Interpreter
- Oberon-07
- Pascal
- Free Pascal
- PascalABC.NET
- Phix
- Python
- Quackery
- Raku
- RPL
- Rust
- V (Vlang)
- Wren
- Wren-ioutil
- XPL0