Babylonian spiral: Difference between revisions

m (remove draft label)
Line 78:
 
This could be made significantly faster with a better estimator (or with a better implementation of J compiled to javascript).
 
=={{header|jq}}==
{{Works with|jq}}
'''Also works with gojq, the Go implementation of jq'''
 
This entry is adapted from the Python and Wren entries but
with an unabashedly stream-oriented approach, as this
minimizes memory requirements.
 
In particular, the main function, `babylonianSpiral`, will generate
points indefinitely, with the main limitation being the arithmetic
precision imposed by the implementation of jq being used. Since gojq,
the Go implementation of jq, supports unbounded integer arithmetic,
this means that, from a practical perspective, the accuracy of the
stream is assured when using gojq no matter how many points are
generated.
 
Since gnuplot does not require the specification beforehand of
the "xrange" or "yrange", the output of `babylonianSpiral` can be
directly piped to gnuplot, as illustrated below.
<syntaxhighlight lang=jq>
# Emit an unbounded stream of points of the Babylonian spiral:
def babylonianSpiral:
 
def heading($x):
def tau: 6.283185307179586;
# Note: the Python modulo operator is not the same as Wren's or jq's
fmod($x + tau; tau);
 
[0,0],
[0,1],
( { dxys: [0,1], # the last point
dsq : 1,
sumx: 0,
sumy: 1 }
| foreach range(2; infinite) as $k (.;
.dxys as [ $x, $y ]
| atan2($y; $x) as $theta
| .candidates = []
| until(.candidates != [];
.dsq += 1
| .i = 0
| until(.i >= $k;
(.i*.i) as $a
| if $a > ((.dsq/2)|floor) then .i = $k # i.e., break
else .j = (.dsq|sqrt|floor) + 1
| until(.j <= 0;
(.j*.j) as $b
| if ($a + $b) < .dsq then .j = -1 # i.e., break
elif ($a + $b) == .dsq
then .candidates += [ [.i, .j], [-.i, .j], [.i, -.j], [-.i, -.j],
[.j, .i], [-.j, .i], [.j, -.i], [-.j, -.i] ]
else .
end
| .j += -1 )
| .i += 1
end ) )
# Python: lambda d: (θ - atan2(d[1], d[0])) % tau
| .dxys = (.candidates | min_by( heading( ($theta - atan2(.[1]; .[0])) ) ))
| .sumx += .dxys[0]
| .sumy += .dxys[1];
[.sumx, .sumy] )
);
 
# Emit a stream of the first $n points:
def Points($n):
limit($n; babylonianSpiral);
</syntaxhighlight>
 
'''Print the first 40 in groups of 10 per line'''
<syntaxhighlight lang=jq>
"The first 40 Babylonian spiral points are:",
([Points(40)] | _nwise(10) | map(tostring) | join(" ") )
</syntaxhighlight>
 
'''For plotting 10000 points'''
<syntaxhighlight lang=jq>
Points(10000) | join(" ")
</syntaxhighlight>
 
'''Visualizing 10000 points with gnuplot'''
 
Assuming the .jq program generates points along the lines of:
 
Points(10000) | join(" ")
 
the following invocation of jq and gnuplot will produce a .png file
showing the Babylonian spiral with the given number of points:
<pre>
jq -rnf babylonian-spiral.jq | gnuplot -c <(cat <<EOF
reset
set terminal pngcairo
set output 'example-babylonian-spiral.png'
plot "/dev/stdin" with dots
EOF
)
</pre>
 
 
=={{header|Julia}}==
2,442

edits