Babylonian spiral: Difference between revisions

m
→‎{{header|Wren}}: Made displayed image a bit smaller.
(Added Wren)
m (→‎{{header|Wren}}: Made displayed image a bit smaller.)
 
(70 intermediate revisions by 12 users not shown)
Line 1:
{{draft task}}
f
 
The '''Babylonian spiral''' is a sequence of points in the plane that are created so as to
continuously minimally increase in vector length and minimally bend in vector direction,
Line 8:
; Examples
 
P(01) and P(12) are defined to be at (x = 0, y = 0) and (x = 0, y = 1). The first vector is
from P(1) to P(2). It is vertical and of length 1. Note that the square of that length is 1.
 
Line 26:
 
Show in your program how to calculate and plot the first 10000 points in the sequence. Your result
should look similar to the graph shown at the OEIS: [[File:From_oies_A@97346_A297347_plot2a.png]]
should look similar to the page at https://oeis.org/plot2a?name1=A297346&name2=A297347&tform1=untransformed&tform2=untransformed&shift=0&radiop1=xy&drawlines=true".
 
 
; See also
Line 35 ⟶ 34:
;* [[oeis:A297347|OEIS:A297347 - List of successive y-coordinates in the Babylonian Spiral.]]
 
 
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
 
#include <cmath>
#include <iomanip>
#include <iostream>
#include <numbers>
#include <vector>
 
typedef std::pair<int32_t, int32_t> point;
 
std::vector<point> babylonian_spiral(int32_t step_count) {
const double tau = 2 * std::numbers::pi;
 
std::vector<int32_t> squares(step_count + 1);
for ( int32_t i = 0; i < step_count; ++i ) {
squares[i] = i * i;
}
std::vector<point> points { point(0, 0), point (0, 1) };
int32_t norm = 1;
 
for ( int32_t step = 0; step < step_count - 2; ++step ) {
point previousPoint = points.back();
const double theta = atan2(previousPoint.second, previousPoint.first);
std::vector<point> candidates;
while ( candidates.empty() ) {
norm += 1;
for ( int32_t i = 0; i < step_count; ++i ) {
int32_t a = squares[i];
if ( a > norm / 2 ) {
break;
}
for ( int32_t j = sqrt(norm) + 1; j >= 0; --j ) {
int32_t b = squares[j];
if ( a + b < norm ) {
break;
}
if ( a + b == norm ) {
std::vector<point> next_points = { point(i, j), point(-i, j), point(i, -j), point(-i, -j),
point(j, i), point(-j, i), point(j, -i), point(-j, -i) };
candidates.reserve(next_points.size());
std::move(next_points.begin(), next_points.end(), std::back_inserter(candidates));
}
}
}
}
 
point minimum;
double minimum_value = tau;
for ( point candidate : candidates ) {
double value = fmod(theta - atan2(candidate.second, candidate.first) + tau, tau);
if ( value < minimum_value ) {
minimum_value = value;
minimum = candidate;
}
}
 
points.push_back(minimum);
}
 
for ( uint64_t i = 0; i < points.size() - 1; ++i ) {
points[i + 1] = point(points[i].first + points[i + 1].first, points[i].second + points[i + 1].second);
}
return points;
}
 
int main() {
std::vector<point> points = babylonian_spiral(40);
std::cout << "The first 40 points of the Babylonian spiral are:" << std::endl;
for ( int32_t i = 0, column = 0; i < 40; ++i ) {
std::string point_str = "(" + std::to_string(points[i].first) + ", " + std::to_string(points[i].second) + ")";
std::cout << std::setw(10) << point_str;
if ( ++column % 10 == 0 ) {
std::cout << std::endl;
}
}
}
</syntaxhighlight>
{{ out }}
<pre>
The first 40 points of the Babylonian spiral are:
(0, 0) (0, 1) (1, 2) (3, 2) (5, 1) (7, -1) (7, -4) (6, -7) (4, -10) (0, -10)
(-4, -9) (-7, -6) (-9, -2) (-9, 3) (-8, 8) (-6, 13) (-2, 17) (3, 20) (9, 20) (15, 19)
(21, 17) (26, 13) (29, 7) (29, 0) (28, -7) (24, -13) (17, -15) (10, -12) (4, -7) (4, 1)
(5, 9) (7, 17) (13, 23) (21, 26) (28, 21) (32, 13) (32, 4) (31, -5) (29, -14) (24, -22)
</pre>
 
=={{header|J}}==
 
It's convenient, here, to use complex numbers to represent the coordinate pairs.
 
Implementation:
 
<syntaxhighlight lang="j">
require'stats'
bspir=: {{
r=. 0
e=. 2>.<.+:%:y
for_qd.
(y-1){.(</.~ *:@|) (/:|) (#~ (=<.)@:*:@:|) j./"1 (2 comb e),,.~1+i.e
do.
d=. ~.(,+)(,-)(,j.);qd
ar=. 12 o. -~/_2{.r
ad=. (- 2p1 * >:&ar) 12 o. d
-r=. r, ({:r)+d{~ (i. >./) ad
end.
}}
</syntaxhighlight>
 
Task example:
 
<syntaxhighlight lang="j"> 4 10$bspir 40
0 0j1 1j2 3j2 5j1 7j_1 7j_4 6j_7 4j_10 0j_10
_4j_9 _7j_6 _9j_2 _9j3 _8j8 _6j13 _2j17 3j20 9j20 15j19
21j17 26j13 29j7 29 28j_7 24j_13 17j_15 10j_12 4j_7 4j1
5j9 7j17 13j23 21j26 28j21 32j13 32j4 31j_5 29j_14 24j_22
</syntaxhighlight>
 
Also:
 
<syntaxhighlight lang="j">
require'plot'
plot bspir 40
plot bspir 1e4
</syntaxhighlight>
 
There's an online example of these two cases [https://jsoftware.github.io/j-playground/bin/html2/#code=require'plot%20stats'%0Abspir%3D%3A%20%7B%7B%0A%20%20r%3D.%200%0A%20%20e%3D.%202%3E.%3C.%2B%3A%25%3Ay%0A%20%20for_qd.%0A%20%20%20%20%28y-1%29%7B.%28%3C%2F.~%20*%3A%40%7C%29%20%28%2F%3A%7C%29%20%28%23~%20%28%3D%3C.%29%40%3A*%3A%40%3A%7C%29%20j.%2F%221%20%282%20comb%20e%29%2C%2C.~1%2Bi.e%0A%20%20do.%0A%20%20%20%20d%3D.%20~.%28%2C%2B%29%28%2C-%29%28%2Cj.%29%3Bqd%0A%20%20%20%20ar%3D.%2012%20o.%20-~%2F_2%7B.r%0A%20%20%20%20ad%3D.%20%28-%202p1%20*%20%3E%3A%26ar%29%2012%20o.%20d%0A%20%20%20%20-r%3D.%20r%2C%20%28%7B%3Ar%29%2Bd%7B~%20%28i.%20%3E.%2F%29%20ad%0A%20%20end.%0A%7D%7D%0A%0Aplot%20bspir%2040%0Aplot%20bspir%201e4 here] (follow the link, select the right pane, then hit control-R or select Edit Run &gt; All Lines from the menu, this might take a couple seconds, depending on your machine, and this url may need to be updated in the future).
 
This could be made significantly faster with a better estimator (or with a better implementation of J compiled to javascript).
 
=={{header|Java}}==
<syntaxhighlight lang="java">
 
import java.awt.Point;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
 
public final class BabylonianSpiral {
 
public static void main(String[] aArgs) throws IOException {
List<Point> points = babylonianSpiral(10_000);
System.out.println("The first 40 points of the Babylonian spiral are:");
for ( int i = 0, column = 0; i < 40; i++ ) {
System.out.print(String.format("%9s%s",
"(" + points.get(i).x + ", " + points.get(i).y + ")", ( ++column % 10 == 0 ) ? "\n" : " "));
}
System.out.println();
String text = svgText(points, 800);
Files.write(Paths.get("C:/Users/psnow/Desktop/BabylonianSpiralJava.svg"), text.getBytes());
}
private static List<Point> babylonianSpiral(int aStepCount) {
final double tau = 2 * Math.PI;
List<Integer> squares = IntStream.rangeClosed(0, aStepCount).map( i -> i * i ).boxed().toList();
List<Point> points = Stream.of( new Point(0, 0), new Point(0, 1) ).collect(Collectors.toList());
int norm = 1;
for ( int step = 0; step < aStepCount - 2; step++ ) {
Point previousPoint = points.get(points.size() - 1);
final double theta = Math.atan2(previousPoint.y, previousPoint.x);
Set<Point> candidates = new HashSet<Point>();
while ( candidates.isEmpty() ) {
norm += 1;
for ( int i = 0; i < aStepCount; i++ ) {
int a = squares.get(i);
if ( a > norm / 2 ) {
break;
}
for ( int j = (int) Math.sqrt(norm) + 1; j >= 0; j-- ) {
int b = squares.get(j);
if ( a + b < norm ) {
break;
}
if ( a + b == norm ) {
candidates.addAll(
List.of( new Point(i, j), new Point(-i, j), new Point(i, -j), new Point(-i, -j),
new Point(j, i), new Point(-j, i), new Point(j, -i), new Point(-j, -i) ));
}
}
}
}
Comparator<Point> comparatorPoint = (one, two) -> Double.compare(
( theta - Math.atan2(one.y, one.x) + tau ) % tau, ( theta - Math.atan2(two.y, two.x) + tau ) % tau);
Point minimum = candidates.stream().min(comparatorPoint).get();
points.add(minimum);
}
for ( int i = 0; i < points.size() - 1; i++ ) {
points.set(i + 1, new Point(points.get(i).x + points.get(i + 1).x, points.get(i).y + points.get(i + 1).y));
}
return points;
}
 
private static String svgText(List<Point> aPoints, int aSize) {
StringBuilder text = new StringBuilder();
text.append("<svg xmlns='http://www.w3.org/2000/svg'");
text.append(" width='" + aSize + "' height='" + aSize + "'>\n");
text.append("<rect width='100%' height='100%' fill='cyan'/>\n");
text.append("<path stroke-width='1' stroke='black' fill='cyan' d='");
for ( int i = 0; i < aPoints.size(); i++ ) {
text.append(( i == 0 ? "M" : "L" ) +
( 150 + aPoints.get(i).x / 20 ) + ", " + ( 525 - aPoints.get(i).y / 20 ) + " ");
}
text.append("'/>\n</svg>\n");
return text.toString();
}
}
</syntaxhighlight>
{{ out }}
[[Media:BabylonianSpiralJava.svg]]
<pre>
The first 40 points of the Babylonian spiral are:
(0, 0) (0, 1) (1, 2) (3, 2) (5, 1) (7, -1) (7, -4) (6, -7) (4, -10) (0, -10)
(-4, -9) (-7, -6) (-9, -2) (-9, 3) (-8, 8) (-6, 13) (-2, 17) (3, 20) (9, 20) (15, 19)
(21, 17) (26, 13) (29, 7) (29, 0) (28, -7) (24, -13) (17, -15) (10, -12) (4, -7) (4, 1)
(5, 9) (7, 17) (13, 23) (21, 26) (28, 21) (32, 13) (32, 4) (31, -5) (29, -14) (24, -22)
</pre>
 
=={{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}}==
{{trans|Python}}
<syntaxhighlight lang="julia">""" Rosetta Code task rosettacode.org/wiki/Babylonian_spiral """
 
using GLMakie
 
const squarecache = Int[]
 
"""
Get the points for a Babylonian spiral of `nsteps` steps. Origin is at (0, 0)
with first step one unit in the positive direction along the vertical (y) axis.
See also: oeis.org/A256111, oeis.org/A297346, oeis.org/A297347
"""
function babylonianspiral(nsteps)
if length(squarecache) <= nsteps
append!(squarecache, map(x -> x * x, length(squarecache):nsteps))
end
# first line segment is 1 unit in vertical direction, with y vertical, x horizontal
xydeltas, δ² = [(0, 0), (0, 1)], 1
for _ in 1:nsteps-2
x, y = xydeltas[end]
θ = atan(y, x)
candidates = Tuple{Int64,Int64}[]
while isempty(candidates)
δ² += 1
for (k, a) in enumerate(squarecache)
a > δ² ÷ 2 && break
for j in isqrt(δ²)+1:-1:1
b = squarecache[j+1]
a + b < δ² && break
if a + b == δ²
i = k - 1
push!(
candidates,
(i, j),
(-i, j),
(i, -j),
(-i, -j),
(j, i),
(-j, i),
(j, -i),
(-j, -i),
)
end
end
end
end
_, idx = findmin(p -> mod1(θ - atan(p[2], p[1]), 2π), candidates)
push!(xydeltas, candidates[idx])
end
return accumulate((a, b) -> (a[1] + b[1], a[2] + b[2]), xydeltas)
end
 
println("The first 40 Babylonian spiral points are:")
for (i, p) in enumerate(babylonianspiral(40))
print(rpad(p, 10), i % 10 == 0 ? "\n" : "")
end
 
lines(babylonianspiral(10_000), linewidth = 1)
</syntaxhighlight>{{out}}
<pre>
The first 40 Babylonian spiral points are:
(0, 0) (0, 1) (1, 2) (3, 2) (5, 1) (7, -1) (7, -4) (6, -7) (4, -10) (0, -10)
(-4, -9) (-7, -6) (-9, -2) (-9, 3) (-8, 8) (-6, 13) (-2, 17) (3, 20) (9, 20) (15, 19)
(21, 17) (26, 13) (29, 7) (29, 0) (28, -7) (24, -13) (17, -15) (10, -12) (4, -7) (4, 1)
(5, 9) (7, 17) (13, 23) (21, 26) (28, 21) (32, 13) (32, 4) (31, -5) (29, -14) (24, -22)
</pre>
[[File:babylonuanspiral.png]]
 
=== iterator version ===
See Python generator version.
<syntaxhighlight lang="julia">using DataStructures
using Plots
 
struct SquareSums end
 
function Base.iterate(ss::SquareSums, state = (1, PriorityQueue{Tuple{Int, Int, Int}, Int}()))
i, sums = state
while isempty(sums) || i^2 <= peek(sums)[2]
enqueue!(sums, (i^2, i, 0) => i^2)
i += 1
end
nextsum, xy = peek(sums)[2], Tuple{Int, Int}[]
while !isempty(sums) && peek(sums)[2] == nextsum # pop all vectors with same length
nextsum, a, b = dequeue!(sums)
push!(xy, (a, b))
if a > b
hsq = a^2 + (b + 1)^2
enqueue!(sums, (hsq, a, b + 1) => hsq)
end
end
return xy, (i, sums)
end
 
function babylonian_spiral(N)
dx, dy, points = 0, 1, [(0, 0)]
for xys in SquareSums()
for i in 1:length(xys)
a, b = xys[i]
a != b && push!(xys, (b, a))
a != 0 && push!(xys, (-a, b), (b, -a))
b != 0 && push!(xys, (a, -b), (-b, a))
a * b != 0 && push!(xys, (-a, -b), (-b, -a))
end
filter!(p -> p[1] * dy - p[2] * dx >= 0, xys)
_, idx = findmax(p -> p[1] * dx + p[2] * dy, xys)
dx, dy = xys[idx]
push!(points, (points[end][1] + dx, points[end][2] + dy))
length(points) >= N && break
end
return @view points[begin:N]
end
 
println("The first 40 Babylonian spiral points are:")
for (i, p) in enumerate(babylonian_spiral(40))
print(rpad(p, 10), i % 10 == 0 ? "\n" : "")
end
 
Plots.plot(babylonian_spiral(10_000))
</syntaxhighlight>
 
 
=={{header|MATLAB}}==
 
=== Directly translate Julia code ===
 
{{trans|Julia}}
<syntaxhighlight lang="MATLAB}}">
% Rosetta Code task rosettacode.org/wiki/Babylonian_spiral
 
clear all;close all;clc;
% Example usage
fprintf("The first 40 Babylonian spiral points are:\n");
spiral_points = babylonianspiral(40);
for i = 1:size(spiral_points, 1)
fprintf('(%d, %d) ', spiral_points(i, 1), spiral_points(i, 2));
if mod(i, 10) == 0
fprintf('\n');
end
end
 
% For plotting the spiral (requires MATLAB plotting functions)
spiral_points = babylonianspiral(10000);
plot(spiral_points(:, 1), spiral_points(:, 2), 'LineWidth', 1);
 
 
function points = babylonianspiral(nsteps)
% Get the points for a Babylonian spiral of `nsteps` steps. Origin is at (0, 0)
% with first step one unit in the positive direction along the vertical (y) axis.
% See also: oeis.org/A256111, oeis.org/A297346, oeis.org/A297347
persistent squarecache;
if isempty(squarecache)
squarecache = [];
end
 
if length(squarecache) <= nsteps
squarecache = [squarecache, arrayfun(@(x) x^2, length(squarecache):nsteps)];
end
 
xydeltas = [0, 0; 0, 1];
deltaSq = 1;
for i = 1:nsteps-2
x = xydeltas(end, 1);
y = xydeltas(end, 2);
theta = atan2(y, x);
candidates = [];
while isempty(candidates)
deltaSq = deltaSq + 1;
for k = 1:length(squarecache)
a = squarecache(k);
if a > deltaSq / 2
break;
end
for j = floor(sqrt(deltaSq)):-1:1
b = squarecache(j+1);
if a + b < deltaSq
break;
end
if a + b == deltaSq
i = k - 1;
candidates = [candidates; i, j; -i, j; i, -j; -i, -j; ...
j, i; -j, i; j, -i; -j, -i];
end
end
end
end
[~, idx] = min(arrayfun(@(n) mod(theta - atan2(candidates(n, 2), candidates(n, 1)), 2*pi), 1:size(candidates, 1)));
xydeltas = [xydeltas; candidates(idx, :)];
end
 
points = cumsum(xydeltas);
end
</syntaxhighlight>
{{out}}
<pre>
The first 40 Babylonian spiral points are:
(0, 0) (0, 1) (1, 2) (3, 2) (5, 1) (7, -1) (7, -4) (6, -7) (4, -10) (0, -10)
(-4, -9) (-7, -6) (-9, -2) (-9, 3) (-8, 8) (-6, 13) (-2, 17) (3, 20) (9, 20) (15, 19)
(21, 17) (26, 13) (29, 7) (29, 0) (28, -7) (24, -13) (17, -15) (10, -12) (4, -7) (4, 1)
(5, 9) (7, 17) (13, 23) (21, 26) (28, 21) (32, 13) (32, 4) (31, -5) (29, -14) (24, -22)
</pre>
 
[[File:BabylonianSpiral.png ]]
 
=={{header|Nim}}==
{{trans|Python}}
{{libheader|gnuplotlib.nim}}
<syntaxhighlight lang="Nim">import std/[math, strformat, strutils]
 
type Vector = tuple[x, y: int]
 
func `+`(a, b: Vector): Vector =
## Return the sum of two vectors.
(a.x + b.x, a.y + b.y)
 
func isqrt(n: int): int =
## Return the integer square root of "n".
int(sqrt(n.toFloat))
 
 
proc babylonianSpiral(nsteps: int): seq[Vector] =
## Get the points for each step along a Babylonia spiral of `nsteps` steps.
## Origin is at (0, 0) with first step one unit in the positive direction along
## the vertical (y) axis. The other points are selected to have integer x and y
## coordinates, progressively concatenating the next longest vector with integer
## x and y coordinates on the grid. The direction change of the new vector is
## chosen to be nonzero and clockwise in a direction that minimizes the change
## in direction from the previous vector.
 
var xyDeltas: seq[Vector] = @[(0, 0), (0, 1)]
var δsquared = 1
for _ in 0..nsteps - 3:
let (x, y) = xyDeltas[^1]
let θ = arctan2(y.toFloat, x.toFloat)
var candidates: seq[Vector]
while candidates.len == 0:
inc δsquared, 1
for i in 0..<nsteps:
let a = i * i
if a > δsquared div 2:
break
for j in countdown(isqrt(δsquared) + 1, 1):
let b = j * j
if a + b < δsquared:
break
if a + b == δsquared:
candidates.add [(i, j), (-i, j), (i, -j), (-i, -j), (j, i), (-j, i), (j, -i), (-j, -i)]
var p: Vector
var minVal = TAU
for candidate in candidates:
let val = floorMod(θ - arctan2(candidate.y.toFloat, candidate.x.toFloat), TAU)
if val < minVal:
minVal = val
p = candidate
xyDeltas.add p
 
result = cumsummed(xyDeltas)
 
let points10000 = babylonianSpiral(10_000)
 
 
### Task ###
echo "The first 40 Babylonian spiral points are:"
for i, p in points10000[0..39]:
stdout.write alignLeft(&"({p.x}, {p.y})", 10)
stdout.write if (i + 1) mod 10 == 0: "\n" else: ""
 
 
### Stretch task ###
 
import gnuplot
 
var x, y: seq[float]
for p in points10000:
x.add p.x.toFloat
y.add p.y.toFloat
 
withGnuPlot:
cmd "set size ratio -1"
plot(x, y, "Babylonian spiral", "with lines lc black lw 1")
png("babylonian_spiral.png")
</syntaxhighlight>
 
{{out}}
<pre>The first 40 Babylonian spiral points are:
(0, 0) (0, 1) (1, 2) (1, 2) (3, 2) (5, 1) (5, 1) (5, 1) (7, -1) (7, -4)
(6, -7) (6, -7) (6, -7) (4, -10) (4, -10) (4, -10) (0, -10) (-4, -9) (-7, -6) (-7, -6)
(-9, -2) (-9, -2) (-9, -2) (-9, -2) (-9, -2) (-9, 3) (-8, 8) (-8, 8) (-8, 8) (-6, 13)
(-6, 13) (-6, 13) (-2, 17) (-2, 17) (3, 20) (3, 20) (9, 20) (15, 19) (15, 19) (15, 19)
</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang="perl">use strict;
use warnings;
use feature <say state>;
use constant TAU => 2 * 2 * atan2(1, 0);
 
sub B_spiral {
my($nsteps) = @_;
my @squares = map $_**2, 0..$nsteps+1;
my @dxys = ([0, 0], [0, 1]);
my $dsq = 1;
 
for (1 .. $nsteps-2) {
my ($x,$y) = @{$dxys[-1]};
our $theta = atan2 $y, $x;
my @candidates;
 
until (@candidates) {
$dsq++;
for my $i (0..$#squares) {
my $a = $squares[$i];
next if $a > $dsq/2;
for my $j ( reverse 0 .. 1 + int sqrt $dsq ) {
my $b = $squares[$j];
next if ($a + $b) < $dsq;
if ($dsq == $a + $b) {
push @candidates, ( [$i, $j], [-$i, $j], [$i, -$j], [-$i, -$j],
[$j, $i], [-$j, $i], [$j, -$i], [-$j, -$i] );
}
}
}
}
 
sub comparer {
my $i = ($theta - atan2 $_[1], $_[0]);
my $z = $i - int($i / TAU) * TAU;
$z < 0 ? TAU + $z : $z;
}
 
push @dxys, (sort { comparer(@$b) < comparer(@$a) } @candidates)[0];
}
 
map { state($x,$y); $x += $$_[0]; $y += $$_[1]; [$x,$y] } @dxys;
}
 
my @points = map { sprintf "(%3d,%4d)", @$_ } B_spiral(40);
say "The first 40 Babylonian spiral points are:\n" .
join(' ', @points) =~ s/.{1,88}\K/\n/gr;</syntaxhighlight>
{{out}}
<pre>The first 40 Babylonian spiral points are:
( 0, 0) ( 0, 1) ( 1, 2) ( 3, 2) ( 5, 1) ( 7, -1) ( 7, -4) ( 6, -7)
( 4, -10) ( 0, -10) ( -4, -9) ( -7, -6) ( -9, -2) ( -9, 3) ( -8, 8) ( -6, 13)
( -2, 17) ( 3, 20) ( 9, 20) ( 15, 19) ( 21, 17) ( 26, 13) ( 29, 7) ( 29, 0)
( 28, -7) ( 24, -13) ( 17, -15) ( 10, -12) ( 4, -7) ( 4, 1) ( 5, 9) ( 7, 17)
( 13, 23) ( 21, 26) ( 28, 21) ( 32, 13) ( 32, 4) ( 31, -5) ( 29, -14) ( 24, -22)</pre>
=={{header|Phix}}==
{{libheader|Phix/pGUI}}
{{libheader|Phix/online}}
You can run this online [http://phix.x10.mx/p2js/Babylonian_spiral.htm here]. Use left/right arrow keys to show less/more edges.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo/rosetta/Babylonian_spiral.exw
-- ==================================
--</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">next_step</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">last_distance</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Find "the next longest vector with integral endpoints on a Cartesian grid"</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">next_distance</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">100</span><span style="color: #0000FF;">*</span><span style="color: #000000;">last_distance</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">// Set high so we can minimize</span>
<span style="color: #000000;">nmax</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">last_distance</span><span style="color: #0000FF;">))</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">2</span>
<span style="color: #000080;font-style:italic;">// ^ The farthest we could possibly go in one direction</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">next_steps</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nmax</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">*</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">mmin</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">last_distance</span><span style="color: #0000FF;">-</span><span style="color: #000000;">n2</span><span style="color: #0000FF;">)))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">mmin</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nmax</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">test_distance</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">*</span><span style="color: #000000;">m</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">test_distance</span><span style="color: #0000FF;">></span><span style="color: #000000;">last_distance</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">test_distance</span><span style="color: #0000FF;">></span><span style="color: #000000;">next_distance</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">test_distance</span><span style="color: #0000FF;"><</span><span style="color: #000000;">next_distance</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">next_distance</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test_distance</span>
<span style="color: #000000;">next_steps</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">next_steps</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">n</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">next_steps</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">next_steps</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">next_distance</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- first two points</span>
<span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- taken as given</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">distance</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">px</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">py</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- position</span>
<span style="color: #000000;">pdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pdy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- previous delta</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">make_spiral</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">npoints</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// Make a Babylonian spiral of npoints.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deltas</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t4</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">0.4</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">npoints</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">deltas</span><span style="color: #0000FF;">,</span><span style="color: #000000;">distance</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_step</span><span style="color: #0000FF;">(</span><span style="color: #000000;">distance</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">max_dot</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ldx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pdx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ldy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pdy</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">delta</span> <span style="color: #008080;">in</span> <span style="color: #000000;">deltas</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ty</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">delta</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">d</span> <span style="color: #008080;">in</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">tx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ty</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">tx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ty</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">tx</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">ty</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">tx</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">ty</span><span style="color: #0000FF;">}}</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ldx</span><span style="color: #0000FF;">*</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">-</span><span style="color: #000000;">ldy</span><span style="color: #0000FF;">*</span><span style="color: #000000;">dx</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">dot</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ldx</span><span style="color: #0000FF;">*</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ldy</span><span style="color: #0000FF;">*</span><span style="color: #000000;">dy</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dot</span><span style="color: #0000FF;">></span><span style="color: #000000;">max_dot</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">max_dot</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dot</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">pdx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pdy</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">px</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">pdx</span>
<span style="color: #000000;">py</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">pdy</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">px</span>
<span style="color: #000000;">y</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">py</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()></span><span style="color: #000000;">t4</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">make_spiral</span><span style="color: #0000FF;">(</span><span style="color: #000000;">40</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The first 40 Babylonian spiral points are:\n%s\n"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #7060A8;">join_by</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">({</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">}),</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">"(%3d,%3d)"</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">include</span> <span style="color: #7060A8;">IupGraph</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">graph</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">timer</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">mt</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- {number, minmax, tick}</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- add more/remove steps as desired</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">20</span><span style="color: #0000FF;">,</span><span style="color: #000000;">20</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">40</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">60</span><span style="color: #0000FF;">,</span><span style="color: #000000;">70</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,</span><span style="color: #000000;">220</span><span style="color: #0000FF;">,</span><span style="color: #000000;">40</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">200</span><span style="color: #0000FF;">,</span><span style="color: #000000;">350</span><span style="color: #0000FF;">,</span><span style="color: #000000;">50</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">400</span><span style="color: #0000FF;">,</span><span style="color: #000000;">700</span><span style="color: #0000FF;">,</span><span style="color: #000000;">100</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">800</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1200</span><span style="color: #0000FF;">,</span><span style="color: #000000;">200</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">400</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3000</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">100000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">150000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">50000</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">150000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">150000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">50000</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">200000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">400000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">100000</span><span style="color: #0000FF;">}}</span>
<span style="color: #000080;font-style:italic;">-- perfectly doable, but test yer patience:
-- {250000,400000,100000},
-- {500000,1200000,400000<nowiki>}}</nowiki></span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">mdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- index to mt</span>
<span style="color: #000000;">max_mdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">get_data</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*graph*/</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mt</span><span style="color: #0000FF;">[</span><span style="color: #000000;">mdx</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">title</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Babylonian spiral (%,d)"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">mt</span><span style="color: #0000FF;">[$][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">title</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">" (calculating %,d/%,d)"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">),</span><span style="color: #000000;">mt</span><span style="color: #0000FF;">[$][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">graph</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"GTITLE"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">title</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">xn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">n</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">yn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">n</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">IupSetAttributes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">graph</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"XMIN=%d,XMAX=%d,XTICK=%d"</span><span style="color: #0000FF;">,{-</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">IupSetAttributes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">graph</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"YMIN=%d,YMAX=%d,YTICK=%d"</span><span style="color: #0000FF;">,{-</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">xn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">yn</span><span style="color: #0000FF;">,</span><span style="color: #004600;">CD_RED</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">key_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_ESC</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (standard practice for me)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_F5</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (let browser reload work)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_LEFT</span> <span style="color: #008080;">then</span> <span style="color: #000000;">mdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mdx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_RIGHT</span> <span style="color: #008080;">then</span> <span style="color: #000000;">mdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mdx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">max_mdx</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">IupUpdate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">graph</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CONTINUE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">timer_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandln</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">max_mdx</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mt</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VISIBLE"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RUN"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">next_target</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mt</span><span style="color: #0000FF;">[</span><span style="color: #000000;">max_mdx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">make_spiral</span><span style="color: #0000FF;">(</span><span style="color: #000000;">next_target</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">next_target</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">max_mdx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">mdx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">max_mdx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">mdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">max_mdx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">IupRedraw</span><span style="color: #0000FF;">(</span><span style="color: #000000;">graph</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_IGNORE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">graph</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGraph</span><span style="color: #0000FF;">(</span><span style="color: #000000;">get_data</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RASTERSIZE=640x480,XMARGIN=35"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">graph</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`TITLE="Babylonian spiral",MINSIZE=270x430`</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">graph</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"GRIDCOLOR"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">CD_LIGHT_GREY</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"K_ANY"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"key_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">graph</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">timer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupTimer</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"timer_cb"</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
The first 40 Babylonian spiral points are:
( 0, 0) ( 0, 1) ( 1, 2) ( 3, 2) ( 5, 1) ( 7, -1) ( 7, -4) ( 6, -7) ( 4,-10) ( 0,-10)
( -4, -9) ( -7, -6) ( -9, -2) ( -9, 3) ( -8, 8) ( -6, 13) ( -2, 17) ( 3, 20) ( 9, 20) ( 15, 19)
( 21, 17) ( 26, 13) ( 29, 7) ( 29, 0) ( 28, -7) ( 24,-13) ( 17,-15) ( 10,-12) ( 4, -7) ( 4, 1)
( 5, 9) ( 7, 17) ( 13, 23) ( 21, 26) ( 28, 21) ( 32, 13) ( 32, 4) ( 31, -5) ( 29,-14) ( 24,-22)
</pre>
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">""" Rosetta Code task rosettacode.org/wiki/Babylonian_spiral """
 
from itertools import accumulate
Line 62 ⟶ 898:
xydeltas = [(0, 0), (0, 1)]
δsquared = 1
for _ in range(nsteps - 2):
x, y = xydeltas[-1]
θ = atan2(y, x)
Line 91 ⟶ 927:
 
# stretch portion of task
plot(*zip(*points10000), color="navy", linewidth=0.2)
axis('scaled')
show()
</langsyntaxhighlight>{{out}}
<pre>
The first 40 Babylonian spiral points are:
Line 102 ⟶ 938:
(5, 9) (7, 17) (13, 23) (21, 26) (28, 21) (32, 13) (32, 4) (31, -5) (29, -14) (24, -22)
</pre>
[[File:babspiral.png]]
 
 
=== With priority queue ===
Use a priority queue to generate all x, y combinations. The advantage is that we don't need to do any real math, and it is much faster.
<syntaxhighlight lang="python">from itertools import islice, count
import matplotlib.pyplot as plt
import heapq
 
def twosquares():
q, n = [], 1
 
while True:
while not q or n*n <= q[0][0]:
heapq.heappush(q, (n*n, n, 0))
n += 1
 
s, xy = q[0][0], []
 
while q and q[0][0] == s: # pop all vectors with same length
s, a, b = heapq.heappop(q)
xy.append((a, b))
if a > b:
heapq.heappush(q, (a*a + (b+1)*(b+1), a, b + 1))
 
yield tuple(xy)
 
def gen_dirs():
d = (0, 1)
for v in twosquares():
# include symmetric vectors
v += tuple((b, a) for a, b in v if a != b)
v += tuple((a, -b) for a, b in v if b)
v += tuple((-a, b) for a, b in v if a)
 
# filter using dot and cross product
d = max((a*d[0] + b*d[1], a, b) for a, b in v if a*d[1] - b*d[0] >= 0)[1:]
yield d
 
def positions():
p = (0, 0)
for d in gen_dirs():
yield p
p = (p[0] + d[0], p[1] + d[1])
 
print(list(islice(positions(), 40)))
 
plt.plot(*zip(*list(islice(positions(), 100000))), lw=0.4)
plt.gca().set_aspect(1)
plt.show()</syntaxhighlight>
 
=={{header|Raku}}==
{{trans|Wren}}
 
===Translation===
<syntaxhighlight lang="raku" line>sub babylonianSpiral (\nsteps) {
my @squareCache = (0..nsteps).hyper.map: *²;
my @dxys = [0, 0], [0, 1];
my $dsq = 1;
 
for ^(nsteps-2) {
my \Θ = atan2 |@dxys[*-1][1,0];
my @candidates;
 
until @candidates.elems {
$dsq++;
for @squareCache.kv -> \i, \a {
last if a > $dsq/2;
for reverse 0 .. $dsq.sqrt.ceiling -> \j {
last if $dsq > (a + my \b = @squareCache[j]);
next if $dsq != a + b;
@candidates.append: [i, j], [-i, j], [i, -j], [-i, -j],
[j, i], [-j, i], [j, -i], [-j, -i]
}
}
}
@dxys.push: @candidates.min: { ( Θ - atan2 |.[1,0] ) % τ };
}
 
[\»+«] @dxys
}
 
# The task
say "The first $_ Babylonian spiral points are:\n",
(babylonianSpiral($_).map: { sprintf '(%3d,%4d)', @$_ }).batch(10).join("\n") given 40;
 
# Stretch
use SVG;
 
'babylonean-spiral-raku.svg'.IO.spurt: SVG.serialize(
svg => [
:width<100%>, :height<100%>,
:rect[:width<100%>, :height<100%>, :style<fill:white;>],
:polyline[ :points(flat babylonianSpiral(10000)),
:style("stroke:red; stroke-width:6; fill:white;"),
:transform("scale (.05, -.05) translate (1000,-10000)")
],
],
);</syntaxhighlight>
{{out}}
<pre>
The first 40 Babylonian spiral points are:
( 0, 0) ( 0, 1) ( 1, 2) ( 3, 2) ( 5, 1) ( 7, -1) ( 7, -4) ( 6, -7) ( 4, -10) ( 0, -10)
( -4, -9) ( -7, -6) ( -9, -2) ( -9, 3) ( -8, 8) ( -6, 13) ( -2, 17) ( 3, 20) ( 9, 20) ( 15, 19)
( 21, 17) ( 26, 13) ( 29, 7) ( 29, 0) ( 28, -7) ( 24, -13) ( 17, -15) ( 10, -12) ( 4, -7) ( 4, 1)
( 5, 9) ( 7, 17) ( 13, 23) ( 21, 26) ( 28, 21) ( 32, 13) ( 32, 4) ( 31, -5) ( 29, -14) ( 24, -22)</pre>
 
{{out|Stretch goal}} (offsite SVG image - 96 Kb) - [https://raw.githubusercontent.com/thundergnat/rc/master/img/babylonean-spiral-raku.svg babylonean-spiral-raku.svg]
 
===Independent implementation===
 
Exact same output; about one tenth the execution time.
 
<syntaxhighlight lang="raku" line>my @next = { :x(1), :y(1), :2hyp },;
 
sub next-interval (Int $int) {
@next.append: (0..$int).map: { %( :x($int), :y($_), :hyp($int² + .²) ) };
@next = |@next.sort: *.<hyp>;
}
 
my @spiral = [\»+«] lazy gather {
my $interval = 1;
take [0,0];
take my @tail = 0,1;
loop {
my \Θ = atan2 |@tail[1,0];
my @this = @next.shift;
@this.push: @next.shift while @next and @next[0]<hyp> == @this[0]<hyp>;
my @candidates = @this.map: {
my (\i, \j) = .<x y>;
next-interval(++$interval) if $interval == i;
|((i,j),(-i,j),(i,-j),(-i,-j),(j,i),(-j,i),(j,-i),(-j,-i))
}
take @tail = |@candidates.min: { ( Θ - atan2 |.[1,0] ) % τ };
}
}
 
# The task
say "The first $_ Babylonian spiral points are:\n",
@spiral[^$_].map({ sprintf '(%3d,%4d)', |$_ }).batch(10).join: "\n" given 40;
 
# Stretch
use SVG;
 
'babylonean-spiral-raku.svg'.IO.spurt: SVG.serialize(
svg => [
:width<100%>, :height<100%>,
:rect[:width<100%>, :height<100%>, :style<fill:white;>],
:polyline[ :points(flat @spiral[^10000]),
:style("stroke:red; stroke-width:6; fill:white;"),
:transform("scale (.05, -.05) translate (1000,-10000)")
],
],
);</syntaxhighlight>
{{out|Same output}}
 
=={{header|Wren}}==
{{trans|Python}}
{{libheader|Wren-traitDOME}}
{{libheader|Wren-iterate}}
{{libheader|Wren-seq}}
{{libheader|Wren-fmt}}
{{libheader|Wren-plot}}
<lang ecmascript>import "./trait" for Indexed
Generates an image similar to the OEIS one.
<syntaxhighlight lang="wren">import "dome" for Window
import "graphics" for Canvas, Color
import "./iterate" for Indexed, Stepped
import "./seq" for Lst
import "./fmt" for Fmt
import "io./plot" for FileAxes
 
// Python modulo operator (not same as Wren's)
Line 171 ⟶ 1,167:
 
// find first 10,000 points
var points10000Points10000 = babylonianSpiral.call(9998) // first two added automatically
 
// print first 40 to terminal
System.print("The first 40 Babylonian spiral points are:")
for (chunk in Lst.chunks(points10000Points10000[0..39], 10)) Fmt.print("$-10s9s", chunk)
 
class Main {
// create .csv file for all 10,000 points for display by an external plotter
construct new() {
File.create("babylonian_spiral.csv") { |file|
Window.title = "Babylonian spiral"
for (p in points10000) {
fileCanvas.writeBytesresize("%(p[0])1000, %(p[1])\n"1000)
Window.resize(1000, 1000)
Canvas.cls(Color.white)
var axes = Axes.new(100, 900, 800, 800, -1000..11000, -5000..10000)
axes.draw(Color.black, 2)
var xMarks = Stepped.new(0..10000, 2000)
var yMarks = Stepped.new(-5000..10000, 5000)
axes.label(xMarks, yMarks, Color.black, 2, Color.black)
axes.line(-1000, 10000, 11000, 10000, Color.black, 2)
axes.line(11000, -5000, 11000, 10000, Color.black, 2)
axes.lineGraph(Points10000, Color.black, 2)
}
 
} </lang>
init() {}
 
update() {}
 
draw(alpha) {}
}
 
var Game = Main.new()</syntaxhighlight>
 
{{out}}
<pre>
The first 40 Babylonian spiral points are:
[0, 0] [0, 1] [1, 2] [3, 2] [5, 1] [7, -1] [7, -4] [6, -7] [4, -10] [0, -10]
[-4, -9] [-7, -6] [-9, -2] [-9, 3] [-8, 8] [-6, 13] [-2, 17] [3, 20] [9, 20] [15, 19]
[21, 17] [26, 13] [29, 7] [29, 0] [28, -7] [24, -13] [17, -15] [10, -12] [4, -7] [4, 1]
[5, 9] [7, 17] [13, 23] [21, 26] [28, 21] [32, 13] [32, 4] [31, -5] [29, -14] [24, -22]
</pre>
 
[[File:Wren-Babylonian_spiral.png|600px]]
9,485

edits