Weather routing: Difference between revisions

m
→‎{{header|Phix}}: syntax coloured, made p2js compatible
m (Removed useless import (commented).)
m (→‎{{header|Phix}}: syntax coloured, made p2js compatible)
Line 1,245:
 
=={{header|Phix}}==
{{trans|Go}}
<lang Phix>-- demo/rosetta/Weather_Routing.exw
<!--<lang Phix>(phixonline)-->
function to_numbers(sequence s)
<span style="color: #000080;font-style:italic;">--
for i=1 to length(s) do
-- demo\rosetta\Weather_Routing.exw
s[i] = to_number(s[i])
-- ================================
end for
--</span>
return s
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
end function
<span style="color: #008080;">constant</span> <span style="color: #000000;">polar_csv</span> <span style="color: #0000FF;">=</span> <span style="font-size: 75%; color: #008000;">"""
 
TWA\TWS;0;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;35;40;60;70
function getpolardata(string s)
40;0;0.53;0.54;0.49;0.4;0.31;0.21;0.16;0.11;0.08;0.05;0.03;0.02;0.01;0;0;0;0;0;0;0;0;0;0;0;0;0;0;-0.01;-0.05;-0.1;-0.11
--
41;0;0.61;0.62;0.56;0.47;0.36;0.25;0.19;0.14;0.1;0.07;0.04;0.02;0.01;0.01;0;0;0;0;0;0;0;0;0;0;0;0;0;0;-0.04;-0.09;-0.1
-- A sailing polar file is a CSV file, with ';' used as the comma separator instead of a comma.
44;0;0.89;0.91;0.82;0.69;0.56;0.42;0.33;0.24;0.18;0.13;0.08;0.05;0.03;0.02;0.01;0.01;0;0;0;0;0;0;0;0;0;0;0;0;-0.02;-0.06;-0.06
-- The first line of the file contains labels for the wind velocities that make up columns, and
45;0;0.99;1.02;0.92;0.78;0.64;0.49;0.39;0.29;0.22;0.15;0.1;0.07;0.04;0.02;0.01;0.01;0;0;0;0;0;0;0;0;0;0;0;0;-0.01;-0.05;-0.05
-- the first entry of each row makes up a column of angle of sailing direction from wind in degrees
46;0;1.11;1.14;1.02;0.87;0.73;0.57;0.45;0.35;0.26;0.18;0.13;0.08;0.05;0.03;0.02;0.01;0.01;0;0;0;0;0;0;0;0;0;0;0;-0.01;-0.04;-0.05
--
47;0;1.23;1.25;1.14;0.97;0.82;0.66;0.53;0.41;0.31;0.22;0.15;0.1;0.07;0.04;0.02;0.02;0.01;0.01;0;0;0;0;0;0;0;0;0;0;-0.01;-0.03;-0.04
sequence lines = split_any(s,"\r\n"),
48;0;1.37;1.37;1.26;1.08;0.93;0.76;0.61;0.48;0.36;0.26;0.19;0.13;0.08;0.05;0.03;0.02;0.01;0.01;0.01;0;0;0;0;0;0;0;0;0;0;-0.02;-0.03
winds = to_numbers(split(lines[1],";")[2..$]),
49;0;1.5;1.5;1.39;1.2;1.05;0.87;0.71;0.56;0.42;0.31;0.22;0.15;0.1;0.07;0.04;0.03;0.02;0.01;0.01;0;0;0;0;0;0;0;0;0;0;-0.02;-0.02
degrees = {}, speeds = {}
50;0;1.65;1.64;1.52;1.33;1.18;1;0.81;0.65;0.49;0.37;0.26;0.19;0.13;0.08;0.05;0.04;0.03;0.02;0.01;0.01;0;0;0;0;0;0;0;0;0;-0.01;-0.02
for i=2 to length(lines) do
51;0;1.79;1.77;1.67;1.46;1.32;1.13;0.92;0.74;0.57;0.43;0.31;0.22;0.15;0.1;0.07;0.05;0.03;0.02;0.02;0.01;0.01;0;0;0;0;0;0;0;0;-0.01;-0.02
sequence l = to_numbers(split(lines[i],";"))
53;0;2.1;2.07;1.99;1.76;1.62;1.4;1.14;0.95;0.74;0.57;0.43;0.31;0.22;0.16;0.1;0.08;0.06;0.04;0.03;0.02;0.01;0.01;0.01;0;0;0;0;0;0;-0.01;-0.01
if length(l)!=length(winds)+1 then ?9/0 end if
54;0;2.26;2.22;2.16;1.92;1.78;1.55;1.28;1.06;0.84;0.65;0.5;0.37;0.27;0.19;0.13;0.1;0.07;0.06;0.04;0.03;0.02;0.01;0.01;0;0;0;0;0;0;0;-0.01
degrees = append(degrees,l[1])
55;0;2.43;2.39;2.34;2.09;1.95;1.7;1.42;1.18;0.95;0.74;0.57;0.43;0.32;0.23;0.16;0.12;0.09;0.07;0.05;0.04;0.03;0.02;0.01;0.01;0;0;0;0;0;0;-0.01
speeds = append(speeds,l[2..$])
60;0;3.29;3.33;3.33;3.08;2.93;2.64;2.29;1.98;1.66;1.36;1.1;0.88;0.68;0.53;0.39;0.32;0.26;0.21;0.17;0.13;0.1;0.07;0.05;0.04;0.03;0.02;0.01;0;0;0;0
end for
70;0;5.2;5.53;5.74;5.59;5.5;5.22;4.84;4.46;3.94;3.51;3.08;2.65;2.26;1.9;1.55;1.38;1.22;1.06;0.92;0.78;0.66;0.55;0.46;0.37;0.3;0.24;0.18;0.03;0;0;0
return {winds, degrees, speeds}
80;0;6.8;7.43;7.97;8.02;8.23;8.34;8.2;7.9;7.37;6.91;6.43;5.9;5.32;4.72;4.12;3.83;3.55;3.25;2.96;2.67;2.4;2.13;1.88;1.65;1.43;1.22;1.04;0.37;0.09;0.01;0
end function
90;0;7.59;8.5;9.4;9.73;10.4;11.16;11.53;11.56;11.3;11.05;10.77;10.44;9.83;9.07;8.34;8;7.65;7.27;6.88;6.46;6.04;5.61;5.15;4.74;4.33;3.88;3.51;1.72;0.67;0.12;0.03
 
100;0;7.34;8.25;9.16;9.86;10.5;11.95;12.79;13.5;14.02;14.4;14.37;14.5;14.4;13.92;13.52;13.19;12.79;12.51;12.1;11.66;11.22;10.77;10.26;9.72;9.2;8.58;8.01;4.87;2.51;0.7;0.23
--
110;0;7.09;7.97;8.84;9.74;10.09;11.85;12.75;13.84;14.99;16.02;16.33;17.1;17.83;17.99;18.32;18.14;17.81;17.84;17.6;17.3;17.05;16.83;16.53;16.03;15.59;15.03;14.37;10.26;6.41;2.32;0.86
-- winds is a list of wind speeds
120;0;6.59;7.42;8.3;9.1;9.56;10.83;11.6;13.1;13.87;14.66;15.75;16.67;17.63;18.43;19.62;20.17;20.6;21.12;21.55;21.75;21.91;22.07;21.9;21.58;21.29;20.92;20.29;16.47;12.03;5.49;2.26
-- degrees is a list of angles in degrees of direction relative to the wind
129;0;6.14;6.93;7.83;8.52;9.09;9.89;10.57;12.42;12.87;13.43;15.23;16.16;17.08;18.07;19.48;20.35;21.22;21.93;22.85;23.44;23.98;24.55;24.59;24.55;24.51;24.46;24;21.56;17.75;9.64;4.25
-- (note 0 degrees is directly into the wind, 180 degrees is directly downwind)
130;0;6.07;6.87;7.76;8.44;9.02;9.8;10.48;12.29;12.73;13.27;15.08;16.03;16.97;17.96;19.36;20.25;21.15;21.88;22.82;23.44;24.03;24.6;24.66;24.68;24.67;24.64;24.24;22;18.33;10.11;4.5
-- each speeds[i] is an array of length(winds) for each degrees[i]
135;0;5.72;6.57;7.36;8.02;8.65;9.38;10.11;11.52;11.97;12.55;13.85;15.31;16.31;17.33;18.54;19.48;20.35;21.28;22.3;23.08;24.09;24.63;24.69;24.78;24.79;24.91;24.82;23.74;20.98;12.39;5.78
--
136;0;5.66;6.5;7.28;7.93;8.57;9.3;10.04;11.34;11.82;12.42;13.62;15.06;16.17;17.2;18.35;19.29;20.15;21.12;22.15;22.96;24.07;24.6;24.67;24.76;24.75;24.85;24.81;23.98;21.45;12.8;6.03
constant {winds, degrees, speeds} = getpolardata(get_text("polar.csv"))
139;0;5.42;6.31;6.92;7.67;8.34;9.08;9.86;10.86;11.32;12.03;12.99;14.3;15.73;16.76;17.76;18.71;19.53;20.6;21.66;22.54;23.92;24.44;24.53;24.64;24.58;24.65;24.67;24.47;22.68;13.79;6.73
-- (note the distributed version uses a literal string constant instead)
140;0;5.35;6.22;6.79;7.59;8.26;9;9.8;10.72;11.16;11.89;12.79;14.06;15.5;16.62;17.57;18.51;19.32;20.43;21.49;22.4;23.84;24.36;24.46;24.58;24.51;24.57;24.61;24.56;23.02;14.08;6.96
constant R = 6372800 -- Earth's approximate radius in meters
141;0;5.29;6.12;6.67;7.48;8.18;8.93;9.74;10.57;11.02;11.77;12.62;13.82;15.26;16.47;17.38;18.32;19.04;20.28;21.31;22.07;23.53;24;24.21;24.29;24.43;24.48;24.55;24.61;23.33;14.31;7.18
constant timeinterval = 10 -- the minutes duration for each TimeSlice
142;0;5.23;6.02;6.57;7.39;8.1;8.86;9.67;10.43;10.88;11.64;12.45;13.59;15.03;16.24;17.14;18.06;18.77;19.98;21.01;21.75;23.18;23.65;23.86;23.95;24.34;24.39;24.48;24.61;23.61;14.54;7.4
 
143;0;5.16;5.93;6.45;7.3;8;8.78;9.54;10.27;10.75;11.5;12.28;13.36;14.8;16.01;16.9;17.81;18.5;19.69;20.72;21.43;22.84;23.31;23.52;23.61;24.05;24.27;24.41;24.57;23.85;14.8;7.6
function deg2rad(atom deg) return remainder(deg*PI/180+2*PI,2*PI) end function
144;0;5.09;5.83;6.33;7.23;7.92;8.66;9.41;10.13;10.62;11.39;12.13;13.13;14.57;15.78;16.65;17.56;18.24;19.41;20.43;21.12;22.5;22.97;23.19;23.28;23.73;24.08;24.33;24.49;24.04;15;7.8
function rad2deg(atom rad) return remainder (rad*(180/PI)+360,360) end function
145;0;5.02;5.73;6.23;7.15;7.85;8.55;9.28;9.98;10.51;11.27;11.98;12.92;14.35;15.56;16.42;17.31;17.97;19.13;20.14;20.82;22.17;22.64;22.87;22.96;23.42;23.81;24.23;24.41;24.19;15.14;7.98
function sind(atom deg) return sin(deg2rad(deg)) end function
146;0;4.96;5.64;6.12;7.07;7.77;8.43;9.15;9.84;10.38;11.16;11.83;12.71;14.12;15.35;16.19;17.07;17.72;18.86;19.86;20.51;21.84;22.31;22.56;22.65;23.12;23.48;23.94;24.33;24.3;15.3;8.16
function cosd(atom deg) return cos(deg2rad(deg)) end function
148;0;4.82;5.45;5.91;6.9;7.59;8.21;8.89;9.55;10.14;10.89;11.55;12.29;13.7;14.92;15.74;16.6;17.23;18.32;19.3;19.91;21.2;21.67;21.95;22.05;22.53;22.87;23.38;24.13;24.39;15.52;8.46
function asind(atom deg) return rad2deg(arcsin(deg)) end function
149;0;4.76;5.35;5.81;6.78;7.49;8.09;8.78;9.42;10.01;10.76;11.41;12.1;13.48;14.71;15.52;16.36;16.98;18.06;19.03;19.63;20.89;21.37;21.67;21.77;22.26;22.61;23.12;23.98;24.37;15.57;8.58
function atand(atom x,y) return rad2deg(atan2(x,y)) end function
150;0;4.69;5.26;5.7;6.67;7.37;7.96;8.64;9.26;9.86;10.6;11.24;11.89;13.26;14.48;15.29;16.11;16.73;17.79;18.74;19.33;20.55;21.04;21.37;21.48;21.98;22.34;22.83;23.69;24.11;15.6;8.67
 
155;0;4.33;4.74;5.16;6.16;6.79;7.33;7.96;8.51;9.15;9.81;10.4;10.85;12.14;13.37;14.1;14.87;15.48;16.42;17.3;17.8;18.88;19.39;19.86;20;20.54;20.97;21.45;22.25;22.77;15.38;8.89
function haversine(atom lat1, lon1, lat2, lon2)
160;0;4.09;4.41;4.83;5.77;6.39;6.94;7.55;8.04;8.67;9.28;9.83;10.24;11.46;12.69;13.39;14.11;14.73;15.6;16.41;16.87;17.85;18.4;18.97;19.15;19.72;20.2;20.65;21.35;21.84;14.95;8.74
--
162;0;4;4.29;4.69;5.62;6.23;6.77;7.38;7.86;8.48;9.07;9.6;10;11.18;12.42;13.1;13.81;14.43;15.27;16.06;16.5;17.43;18;18.62;18.81;19.39;19.89;20.33;20.99;21.48;14.76;8.61
-- Calculate the haversine function for two points on the Earth's surface.
168;0;3.74;3.93;4.35;5.15;5.75;6.31;6.93;7.34;7.92;8.45;8.95;9.35;10.44;11.68;12.32;12.99;13.63;14.39;15.11;15.5;16.31;16.94;17.7;17.92;18.53;19.08;19.49;19.99;20.46;14.34;8.3
--
170;0;3.69;3.85;4.27;5.04;5.65;6.22;6.82;7.23;7.8;8.31;8.8;9.22;10.27;11.51;12.15;12.81;13.45;14.19;14.9;15.28;16.06;16.7;17.51;17.73;18.34;18.91;19.31;19.77;20.22;14.24;8.24
-- Given two latitude, longitude pairs in degrees for a point on the Earth,
174;0;3.57;3.69;4.11;4.83;5.43;6.01;6.62;7;7.55;8.03;8.5;8.93;9.95;11.19;11.81;12.45;13.11;13.81;14.48;14.84;15.57;16.24;17.11;17.35;17.98;18.57;18.95;19.33;19.77;14.03;8.13
-- get distance in meters and the initial direction of travel in degrees for
180;0;3.51;3.6;4.03;4.71;5.31;5.91;6.51;6.88;7.41;7.88;8.33;8.79;9.78;11.02;11.63;12.26;12.93;13.61;14.26;14.61;15.31;15.99;16.9;17.15;17.79;18.39;18.77;19.09;19.52;13.87;8.07
-- movement from point 1 to point 2.
"""</span>
--
atom dlat = lat2 - lat1,
dlon = lon2 - lon1,
a = power(sind(dlat/2),2) + cosd(lat1)*cosd(lat2)*power(sind(dlon/2),2),
c = 2.0 * asind(sqrt(a)),
theta = atand(sind(dlon)*cosd(lat2),
cosd(lat1)*sind(lat2) - sind(lat1)*cosd(lat2)*cosd(dlon))
theta = remainder(theta+360, 360)
return {R*c*0.5399565, theta}
end function
 
function find_range(atom v, sequence s)
-- Returns the indexes of s of the first >=v, and the last <=v
for i=1 to length(s) do
if s[i]>=v then
for j=length(s) to 1 by -1 do
if s[j]<=v then return {i,j} end if
end for
exit
end if
end for
return {-1,-1}
end function
 
function boatspeed(atom pointofsail, windspeed)
--
-- Calculate the expected sailing speed in a specified direction in knots,
-- given a desired point of sail in degrees, and wind speed in knots (for
-- the previously loaded sailing polar data)
--
integer {ld,ud} = find_range(pointofsail, degrees),
{lv,uv} = find_range(windspeed, winds)
if find(-1,{ld, ud, lv, uv}) then return -1 end if
atom wu = winds[uv],
wl = winds[lv],
du = degrees[ud],
dl = degrees[ld],
f
if ld==ud then
f = iff(uv==lv ? 1 :
(wu-windspeed)/(wu-wl))
elsif uv==lv then
f = (du-pointofsail)/(du-dl)
else
f = ((du-pointofsail)/(du-dl)+
(wu-windspeed)/(wu-wl))/2
end if
atom su = speeds[ud,uv],
sl = speeds[ld,lv],
res = su - f*(su-sl)
return res
end function
 
function sailingspeed(atom azimuth, pointofsail, ws)
--
-- Calculate the expected net boat speed in a desired direction versus the wind (azimuth).
-- This is generally different from the actual boat speed in its actual direction.
-- Directions are in degrees (pointofsail is the ship direction from wind),
-- and velocity of wind (ws) is in knots.
--
return boatspeed(pointofsail, ws) * cosd(abs(pointofsail-azimuth))
end function
 
struct SurfaceParameters
--
-- wind and surface current, direction and velocity, for a given position
-- directions are in degrees from north, and velocities are in knots.
--
public atom winddirection,
windvelocity,
currentdirection,
currentvelocity
end struct
 
function bestvectorspeed(atom dirtravel, SurfaceParameters p)
--
-- Calculate the net direction and velocity of a sailing ship.
--
atom wd = p.winddirection,
wv = p.windvelocity,
cd = p.currentdirection,
cv = p.currentvelocity,
azimuth = remainder(dirtravel-wd,360)
if azimuth<0 then azimuth += 360 end if
if azimuth>180 then azimuth = 360-azimuth end if
atom vmg = boatspeed(azimuth, wv),
other = -1
integer idx = -1
for i=1 to length(degrees) do
atom ss = sailingspeed(azimuth, degrees[i], wv)
if ss>other then {other,idx} = {ss,i} end if
end for
if other>vmg then
azimuth = degrees[idx]
vmg = other
end if
atom dirchosen = deg2rad(wd + azimuth),
dircurrent = deg2rad(cd),
wx = vmg * sin(dirchosen),
wy = vmg * cos(dirchosen),
curx = cv * sin(dircurrent),
cury = cv * cos(dircurrent)
return sqrt(power(wx+curx,2) + power(wy+cury,2))
end function
 
function sailsegmenttime(SurfaceParameters p, atom lat1, lon1, lat2, lon2)
--
-- Calculate the trip time in minutes from (lat1, lon1) to the destination (lat2, lon2).
-- Uses the data in SurfaceParameters p for wind and current velocity and direction.
--
atom {distance, direction} = haversine(lat1, lon1, lat2, lon2),
velocity = bestvectorspeed(direction, p)
-- minutes/s * m / (knots * (m/s / knot)) = minutes
atom res = (1/60) * distance / (velocity * 1.94384)
return res
end function
 
--
-- The data is selected so the best time path is slightly longer than the
-- shortest length path. The forbidden regions are x, representing land or reef.
-- The allowed sailing points are . and start and finish are S and F.
--
constant chart = split("""
...S.....
x......x.
....x..x.
x...xx.x.
x...xx.x.
..xxxx.xx
x..xxx...
.......xx
x..F..x.x""",'\n')
 
function minimum_time_route(sequence timeframe, start, finish)
--
-- Get the fastest route from start to finish for some detailed sea/ship parameters.
-- timeframe is a massive 200 * 9x9 * {pt,SurfaceParameters}
-- note that polar data (ie winds, degrees, speeds) is static here, for simplicity.
--
atom t0 = time(),
mintime = 1000.0
integer xmax = length(chart[1]),
ymax = length(chart),
{py,px} = start
sequence todo = {start},
costs = repeat(repeat(-1,xmax),ymax), -- (lowest durations)
paths = repeat(repeat(0,xmax),ymax), -- (single backlinks)
minpath = {}
costs[py,px] = 0
while length(todo) do
{py,px} = todo[1]
todo = todo[2..$]
atom duration = costs[py,px]
integer sdx = remainder(floor(round(duration)/timeinterval),length(timeframe))+1
sequence s = timeframe[sdx]
for nx=px-1 to px+1 do
for ny=py-1 to py+1 do
if (nx!=px or ny!=py)
and nx>=1 and nx<=xmax
and ny>=1 and ny<=ymax
and chart[ny,nx]!='x' then
sequence gp1 = s[py,px], -- {pt,SurfaceParameters}
gp2 = s[ny,nx] -- ""
atom {lat1, lon1} = gp1[1],
{lat2, lon2} = gp2[1]
SurfaceParameters sp = gp1[2]
atom nt = duration + sailsegmenttime(sp, lat1, lon1, lat2, lon2)
if costs[ny,nx]=-1 or nt<costs[ny,nx] then
-- a larger (than 9x9) simulation might benefit from not
-- putting any already-too-long routes back on the todo
-- list and/or processing todo lowest duration first.
costs[ny,nx] = nt
paths[ny,nx] = {py,px}
if not find({ny,nx},todo) then
todo = append(todo,{ny,nx})
end if
elsif nt==costs[ny,nx] then
-- (Should multiple same-time routes exist, we could store
-- multiple back-links and whip up a simple [recursive]
-- routine to rebuild them all. Or just ignore them.)
?9/0
end if
end if
end for
end for
s = {} -- (simplify debugging)
end while
timeframe = {} -- (simplify debugging)
{py,px} = finish
mintime = costs[py,px]
minpath = {finish}
while true do
object pyx = paths[py,px]
if pyx=0 then exit end if
minpath = prepend(minpath,pyx)
paths[py,px] = 0 -- (be safe, why not)
{py,px} = pyx
end while
if minpath[1]!=start then ?9/0 end if
return {minpath,elapsed(mintime*60),elapsed(time()-t0)}
end function
<span style="color: #008080;">function</span> <span style="color: #000000;">to_numbers</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
function surfacebylongitude(atom lon)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
-- Create regional wind patterns on the map.
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
sequence p = iff(lon < -155.03 ? { -5.0, 8, 150, 0.5} :
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
iff(lon < -155.99 ? {-90.0, 20, 150, 0.4} :
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span>
{180.0, 25, 150, 0.3}))
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
SurfaceParameters res = new(p)
return res
end function
 
procedure mutatetimeslices(sequence slices)
-- Vary wind speeds over time.
for i=1 to length(slices) do
sequence s = slices[i]
for j=1 to length(s) do
sequence sj = s[j]
for k=1 to length(sj) do
SurfaceParameters p = sj[k][2]
p.windvelocity = p.windvelocity * (1+0.002*i)
end for
end for
end for
end procedure
<span style="color: #008080;">function</span> <span style="color: #000000;">getpolardata</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
sequence slices = repeat(null,200)
<span style="color: #000080;font-style:italic;">--
for s=1 to length(slices) do
-- A sailing polar file is a CSV file, with ';' used as the comma separator instead of a comma.
sequence gpoints = repeat(null,9)
-- The first line of the file contains labels for the wind velocities that make up columns, and
for i=1 to 9 do
-- the first entry of each row makes up a column of angle of sailing direction from wind in degrees
atom lat = 19.78 - 2/60 + i/60
--</span>
gpoints[i] = repeat(null,9)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split_any</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\r\n"</span><span style="color: #0000FF;">),</span>
for j=1 to 9 do
<span style="color: #000000;">winds</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">to_numbers</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #008000;">";"</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]),</span>
atom lon = -155.0 - 6/60 + j/60
<span style="color: #000000;">degrees</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000000;">speeds</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
gpoints[i][j] = {{lat,lon}, surfacebylongitude(lon)}
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">sequence</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">to_numbers</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">";"</span><span style="color: #0000FF;">))</span>
end for
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)!=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">winds</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
slices[s] = gpoints
<span style="color: #000000;">degrees</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">degrees</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
end for
<span style="color: #000000;">speeds</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">speeds</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$])</span>
mutatetimeslices(slices)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
constant fmt = """
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">winds</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degrees</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">speeds</span><span style="color: #0000FF;">}</span>
The route taking the least time found was:
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
%v
which has duration %s [route found in %s]
<span style="color: #000080;font-style:italic;">--
"""
-- winds is a list of wind speeds
printf(1,fmt,minimum_time_route(slices,{1,4},{9,4}))</lang>
-- degrees is a list of angles in degrees of direction relative to the wind
-- (note 0 degrees is directly into the wind, 180 degrees is directly downwind)
-- each speeds[i] is an array of length(winds) for each degrees[i]
--</span>
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">winds</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degrees</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">speeds</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">getpolardata</span><span style="color: #0000FF;">(</span><span style="color: #000000;">polar_csv</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--constant {winds, degrees, speeds} = getpolardata(get_text("polar.csv")) -- alt</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">R</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">6372800</span> <span style="color: #000080;font-style:italic;">-- Earth's approximate radius in meters</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">timeinterval</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">-- the minutes duration for each TimeSlice</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">deg2rad</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">deg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deg</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</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;">rad2deg</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">rad</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">remainder</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">rad</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">180</span><span style="color: #0000FF;">/</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">360</span><span style="color: #0000FF;">,</span><span style="color: #000000;">360</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;">sind</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">deg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deg2rad</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deg</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;">cosd</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">deg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deg2rad</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deg</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;">asind</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">deg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">rad2deg</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">arcsin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deg</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;">atand</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</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: #008080;">return</span> <span style="color: #000000;">rad2deg</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">atan2</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: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">haversine</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon2</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Calculate the haversine function for two points on the Earth's surface.
--
-- Given two latitude, longitude pairs in degrees for a point on the Earth,
-- get distance in meters and the initial direction of travel in degrees for
-- movement from point 1 to point 2.
--</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">dlat</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lat2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">dlon</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lon2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlat</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">cosd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat1</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">cosd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat2</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlon</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2.0</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">asind</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)),</span>
<span style="color: #000000;">theta</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">atand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlon</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">cosd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">cosd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat1</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">sind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat2</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">sind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat1</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">cosd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat2</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">cosd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlon</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">theta</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">theta</span><span style="color: #0000FF;">+</span><span style="color: #000000;">360</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">360</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">R</span><span style="color: #0000FF;">*</span><span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.5399565</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">theta</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;">find_range</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Returns the indexes of s of the first &gt;=v, and the last &lt;=v</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]>=</span><span style="color: #000000;">v</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]<=</span><span style="color: #000000;">v</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</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;">for</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;">return</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;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">boatspeed</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">pointofsail</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">windspeed</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Calculate the expected sailing speed in a specified direction in knots,
-- given a desired point of sail in degrees, and wind speed in knots (for
-- the previously loaded sailing polar data)
--</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">ld</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ud</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">find_range</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pointofsail</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degrees</span><span style="color: #0000FF;">),</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">lv</span><span style="color: #0000FF;">,</span><span style="color: #000000;">uv</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">find_range</span><span style="color: #0000FF;">(</span><span style="color: #000000;">windspeed</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">winds</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ld</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ud</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lv</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">uv</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">wu</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">winds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uv</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">wl</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">winds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lv</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">du</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">degrees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ud</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">dl</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">degrees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ld</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">f</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ld</span><span style="color: #0000FF;">==</span><span style="color: #000000;">ud</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">uv</span><span style="color: #0000FF;">==</span><span style="color: #000000;">lv</span> <span style="color: #0000FF;">?</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">:</span>
<span style="color: #0000FF;">(</span><span style="color: #000000;">wu</span><span style="color: #0000FF;">-</span><span style="color: #000000;">windspeed</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">wu</span><span style="color: #0000FF;">-</span><span style="color: #000000;">wl</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">uv</span><span style="color: #0000FF;">==</span><span style="color: #000000;">lv</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">du</span><span style="color: #0000FF;">-</span><span style="color: #000000;">pointofsail</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">du</span><span style="color: #0000FF;">-</span><span style="color: #000000;">dl</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">du</span><span style="color: #0000FF;">-</span><span style="color: #000000;">pointofsail</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">du</span><span style="color: #0000FF;">-</span><span style="color: #000000;">dl</span><span style="color: #0000FF;">)+</span>
<span style="color: #0000FF;">(</span><span style="color: #000000;">wu</span><span style="color: #0000FF;">-</span><span style="color: #000000;">windspeed</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">wu</span><span style="color: #0000FF;">-</span><span style="color: #000000;">wl</span><span style="color: #0000FF;">))/</span><span style="color: #000000;">2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">su</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">speeds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ud</span><span style="color: #0000FF;">,</span><span style="color: #000000;">uv</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">sl</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">speeds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ld</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lv</span><span style="color: #0000FF;">],</span>
<span style="color: #000080;font-style:italic;">-- res = su + f*(sl-su) -- (original)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">su</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">su</span><span style="color: #0000FF;">-</span><span style="color: #000000;">sl</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (equivalent)
-- res = sl + (1-f)*(su-sl) -- (also equivalent)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">sailingspeed</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">azimuth</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pointofsail</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ws</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Calculate the expected net boat speed in a desired direction versus the wind (azimuth).
-- This is generally different from the actual boat speed in its actual direction.
-- Directions are in degrees (pointofsail is the ship direction from wind),
-- and velocity of wind (ws) is in knots.
--</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">boatspeed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pointofsail</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ws</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">cosd</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pointofsail</span><span style="color: #0000FF;">-</span><span style="color: #000000;">azimuth</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;">bestvectorspeed</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">dirtravel</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">surfaceparameters</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Calculate the net direction and velocity of a sailing ship.
--</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">winddirection</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">windvelocity</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">currentdirection</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">currentvelocity</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">surfaceparameters</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">azimuth</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dirtravel</span><span style="color: #0000FF;">-</span><span style="color: #000000;">winddirection</span><span style="color: #0000FF;">,</span><span style="color: #000000;">360</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">azimuth</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">azimuth</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">360</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">azimuth</span><span style="color: #0000FF;">></span><span style="color: #000000;">180</span> <span style="color: #008080;">then</span> <span style="color: #000000;">azimuth</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">360</span><span style="color: #0000FF;">-</span><span style="color: #000000;">azimuth</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">vmg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">boatspeed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">azimuth</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">windvelocity</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">other</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">degrees</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">ss</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sailingspeed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">azimuth</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degrees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">windvelocity</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ss</span><span style="color: #0000FF;">></span><span style="color: #000000;">other</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">other</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">ss</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</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;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">other</span><span style="color: #0000FF;">></span><span style="color: #000000;">vmg</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">azimuth</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">degrees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">vmg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">other</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">dirchosen</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deg2rad</span><span style="color: #0000FF;">(</span><span style="color: #000000;">winddirection</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">azimuth</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">dircurrent</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deg2rad</span><span style="color: #0000FF;">(</span><span style="color: #000000;">currentdirection</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">wx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">vmg</span> <span style="color: #0000FF;">*</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dirchosen</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">wy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">vmg</span> <span style="color: #0000FF;">*</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dirchosen</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">curx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">currentvelocity</span> <span style="color: #0000FF;">*</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dircurrent</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">cury</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">currentvelocity</span> <span style="color: #0000FF;">*</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dircurrent</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">wx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">curx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">wy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">cury</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</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;">sailsegmenttime</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">surfaceparameters</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon2</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Calculate the trip time in minutes from (lat1, lon1) to the destination (lat2, lon2).
-- Uses the data in surfaceparameters for wind and current velocity and direction.
--</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">distance</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">direction</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">haversine</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">velocity</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bestvectorspeed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">direction</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">surfaceparameters</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- minutes/s * m / (knots * (m/s / knot)) = minutes</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">60</span><span style="color: #0000FF;">)</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;">velocity</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">1.94384</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">--
-- The data is selected so the best time path is slightly longer than the
-- shortest length path. The forbidden regions are x, representing land or reef.
-- The allowed sailing points are . and start and finish are S and F.
-- </span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">chart</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
...S.....
x......x.
....x..x.
x...xx.x.
x...xx.x.
..xxxx.xx
x..xxx...
.......xx
x..F..x.x"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">minimum_time_route</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">timeframe</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">start</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">finish</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Get the fastest route from start to finish for some detailed sea/ship parameters.
-- timeframe is a massive 200 * 9x9 * {pt,surfaceparameters}
-- note that polar data (ie winds, degrees, speeds) is static here, for simplicity.
--</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">mintime</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1000.0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">xmax</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">chart</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]),</span>
<span style="color: #000000;">ymax</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">chart</span><span style="color: #0000FF;">),</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">start</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">todo</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">start</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">costs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">xmax</span><span style="color: #0000FF;">),</span><span style="color: #000000;">ymax</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- (lowest durations)</span>
<span style="color: #000000;">paths</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">xmax</span><span style="color: #0000FF;">),</span><span style="color: #000000;">ymax</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- (single backlinks)</span>
<span style="color: #000000;">minpath</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">todo</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">todo</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">todo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">todo</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">duration</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">duration</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">timeinterval</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timeframe</span><span style="color: #0000FF;">))+</span><span style="color: #000000;">1</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">timeframe</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">nx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">px</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">px</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">ny</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: #008080;">to</span> <span style="color: #000000;">py</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">px</span> <span style="color: #008080;">or</span> <span style="color: #000000;">ny</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">py</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">nx</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">nx</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">xmax</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">ny</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ny</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">ymax</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">chart</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'x'</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">gp1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">],</span> <span style="color: #000080;font-style:italic;">-- {pt,surfaceparameters}</span>
<span style="color: #000000;">gp2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- ""</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">lat1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">gp1</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">gp2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">surfaceparameters</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">gp1</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">nt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">duration</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">sailsegmenttime</span><span style="color: #0000FF;">(</span><span style="color: #000000;">surfaceparameters</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">]=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">nt</span><span style="color: #0000FF;"><</span><span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- a larger (than 9x9) simulation might benefit from not
-- putting any already-too-long routes back on the todo
-- list and/or processing todo lowest duration first.</span>
<span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nt</span>
<span style="color: #000000;">paths</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">({</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">},</span><span style="color: #000000;">todo</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">todo</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">todo</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">nt</span><span style="color: #0000FF;">==</span><span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- (Should multiple same-time routes exist, we could store
-- multiple back-links and whip up a simple [recursive]
-- routine to rebuild them all. Or just ignore them.)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</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;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- (simplify debugging)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">timeframe</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- (simplify debugging)</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">finish</span>
<span style="color: #000000;">mintime</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">minpath</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">finish</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">pyx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">paths</span><span style="color: #0000FF;">[</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pyx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</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: #000000;">minpath</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">prepend</span><span style="color: #0000FF;">(</span><span style="color: #000000;">minpath</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pyx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">paths</span><span style="color: #0000FF;">[</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- (be safe, why not)</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">px</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pyx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">minpath</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">start</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">minpath</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mintime</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</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;">surfacebylongitude</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">lon</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Create regional wind patterns on the map.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">surfaceparameters</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lon</span> <span style="color: #0000FF;"><</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">155.03</span> <span style="color: #0000FF;">?</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">5.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">150</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.5</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">:</span>
<span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lon</span> <span style="color: #0000FF;"><</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">155.99</span> <span style="color: #0000FF;">?</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">90.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">150</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.4</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">:</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">180.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">25</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">150</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.3</span><span style="color: #0000FF;">}))</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">surfaceparameters</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">slices</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #004600;">null</span><span style="color: #0000FF;">,</span><span style="color: #000000;">200</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">mutatetimeslices</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">-- Vary wind speeds over time.</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">slices</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">slices</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sj</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sj</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">windvelocity</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sj</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">windvelocity</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0.002</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i</span>
<span style="color: #000000;">sj</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">windvelocity</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sj</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">slices</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</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: #008080;">for</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">slices</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">gpoints</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #004600;">null</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">lat</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">19.78</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">/</span><span style="color: #000000;">60</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">/</span><span style="color: #000000;">60</span>
<span style="color: #000000;">gpoints</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #004600;">null</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">lon</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">155.0</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">/</span><span style="color: #000000;">60</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">/</span><span style="color: #000000;">60</span>
<span style="color: #000000;">gpoints</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">lat</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lon</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">surfacebylongitude</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lon</span><span style="color: #0000FF;">)}</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;">slices</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">gpoints</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">mutatetimeslices</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">fmt</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
The route taking the least time found was:
%v
which has duration %s [route found in %s]
"""</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: #000000;">fmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">minimum_time_route</span><span style="color: #0000FF;">(</span><span style="color: #000000;">slices</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">9</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: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</lang>-->
{{out}}
<pre>
7,813

edits