Object subclass: Segment [
    |pts|
    Segment class >> new: points [ |a|
      a := super new.
      ^ a init: points
    ]
    init: points [ pts := points copy. ^self ]
    endPoints [ ^pts ]
    "utility methods"
    first [ ^ pts at: 1]
    second [ ^ pts at: 2]
    leftmostEndPoint [
      ^ (self first x > self second x) ifTrue: [ self second ] ifFalse: [ self first ]
    ]
    rightmostEndPoint [
      ^ (self first x > self second x) ifTrue: [ self first ] ifFalse: [ self second ]
    ]
    topmostEndPoint [
      ^ (self first y > self second y) ifTrue: [ self first ] ifFalse: [ self second ]
    ]
    bottommostEndPoint [
      ^ (self first y > self second y) ifTrue: [ self second ] ifFalse: [ self first ]
    ]

    slope [
      (pts at: 1) x ~= (pts at: 2) x
      ifTrue: [ ^ ((pts at: 1) y - (pts at: 2) y) / ((pts at: 1) x - (pts at: 2) x) ]
      ifFalse: [ ^ FloatD infinity ]
    ]

    doesIntersectRayFrom: point [ |p A B|
      (point y = (pts at: 1) y) | (point y = (pts at: 2) y)
      ifTrue: [ p := Point x: (point x) y: (point y) + 0.00001 ]
      ifFalse: [ p := point copy ].
      A := self bottommostEndPoint.
      B := self topmostEndPoint.
      (p y < A y) | (p y > B y) | (p x > (self rightmostEndPoint x))
        ifTrue: [ ^false ]
        ifFalse: [ (p x < (self leftmostEndPoint x))
                     ifTrue: [ ^true ]
                     ifFalse: [ |s|
                        s := Segment new: { A . point }.
			(s slope) >= (self slope)
			  ifTrue: [ ^ true ]
                     ]
                 ].
        ^false
    ]
].

Object subclass: Polygon [
    |polysegs|
    Polygon class >> new [ |a| a := super new. ^ a init. ]
    Polygon class >> fromSegments: segments [ |a|
      a := super new.
      ^ a initWithSegments: segments
    ]
    Polygon class >> fromPoints: pts and: indexes [ |a|
      a := self new.
      indexes do: [ :i |
        a addSegment: ( Segment new: { pts at: (i at: 1) . pts at: (i at: 2) } )
      ].
      ^ a
    ]
    initWithSegments: segments [
      polysegs := segments copy. ^self
    ]
    init [ polysegs := OrderedCollection new. ^ self ]
    addSegment: segment [ polysegs add: segment ]

    pointInside: point [ |cnt|
      cnt := 0.
      polysegs do: [ :s | (s doesIntersectRayFrom: point)
                          ifTrue: [ cnt := cnt + 1 ] ].
      ^ ( cnt \\ 2 = 0 ) not
    ]
].


package require Tcl 8.5

proc point_in_polygon {point polygon} {
    set count 0
    foreach side [sides $polygon] {
        if {[ray_intersects_line $point $side]} {
            incr count
        }
    }
    expr {$count % 2} ;#-- 1 = odd = true, 0 = even = false
}
proc sides polygon {
    lassign $polygon x0 y0
    foreach {x y} [lrange [lappend polygon $x0 $y0] 2 end] {
        lappend res [list $x0 $y0 $x $y]
        set x0 $x
        set y0 $y
    }
    return $res
}
proc ray_intersects_line {point line} {
    lassign $point Px Py
    lassign $line Ax Ay Bx By
    # Reverse line direction if necessary
    if {$By < $Ay} {
	lassign $line Bx By Ax Ay
    }
    # Add epsilon to
    if {$Py == $Ay || $Py == $By} {
	set Py [expr {$Py + abs($Py)/1e6}]
    }
    # Bounding box checks
    if {$Py < $Ay || $Py > $By || $Px > max($Ax,$Bx)} {
	return 0
    } elseif {$Px < min($Ax,$Bx)} {
	return 1
    }
    # Compare dot products to compare (cosines of) angles
    set mRed [expr {$Ax != $Bx ? ($By-$Ay)/($Bx-$Ax) : Inf}]
    set mBlu [expr {$Ax != $Px ? ($Py-$Ay)/($Px-$Ax) : Inf}]
    return [expr {$mBlu >= $mRed}]
}

foreach {point poly} {
    {0 0}	{-1 -1  -1 1  1 1  1 -1}
    {2 2}	{-1 -1  -1 1  1 1  1 -1}
    {0 0}	{-2 -2  -2 2  2 2  2 -2   2 -1  1 1  -1 1  -1 -1  1 -1  2 -1}
    {1.5 1.5}	{-2 -2  -2 2  2 2  2 -2   2 -1  1 1  -1 1  -1 -1  1 -1  2 -1}
    {5 5}	{0 0  2.5 2.5  0 10  2.5 7.5  7.5 7.5  10 10  10 0  7.5 0.1}
    {5 8}	{0 0  2.5 2.5  0 10  2.5 7.5  7.5 7.5  10 10  10 0  7.5 0.1}
    {2 2}	{0 0  2.5 2.5  0 10  2.5 7.5  7.5 7.5  10 10  10 0  7.5 0.1}
    {0 0}	{0 0  2.5 2.5  0 10  2.5 7.5  7.5 7.5  10 10  10 0  7.5 0.1}
    {10 10}	{0 0  2.5 2.5  0 10  2.5 7.5  7.5 7.5  10 10  10 0  7.5 0.1}
    {2.5 2.5}	{0 0  2.5 2.5  0 10  2.5 7.5  7.5 7.5  10 10  10 0  7.5 0.1}
    {-5 5}	{3 0  7 0  10 5  7 10  3 10  0 5}
} {
    puts "$point in $poly = [point_in_polygon $point $poly]"
}


with javascript_semantics
function spout(integer first, curr, sequence s)
    string res
    if first=curr-1 then
        res = sprintf("%d",s[first])
    else
        integer sep = iff(first=curr-2?',':'-')
        res = sprintf("%d%s%d",{s[first],sep,s[curr-1]})
    end if
    return res
end function

function extract_ranges(sequence s)
    integer first = 1
    string out = ""
    if length(s)!=0 then
        for i=2 to length(s) do
            if s[i]!=s[i-1]+1 then
                out &= spout(first,i,s)&','
                first = i
            end if
        end for
        out &= spout(first,length(s)+1,s)
    end if
    return out
end function

constant r = {0,1,2,4,6,7,8,
                 11,12,14,15,16,17,18,19,
              20,21,22,23,24,25,27,28,29,
              30,31,32,33,35,36,37,38,39}
printf(1,"%s\n",{extract_ranges(r)})


#import flo

in =

@lrzyCipPX ~|afatPRZaq ~&EZ+fleq~~lrPrbr2G&& ~&B+fleq~~lrPrbl2G!| -&
   ~&Y+ ~~lrPrbl2G fleq,
   ^E([email protected],@rl fleq\0.)^/~&lr ^(~&r,times)^/[email protected] vid+ minus~~rbbI&-


Imports System.Math

Module RayCasting

    Private square As Integer()() = {New Integer() {0, 0}, New Integer() {20, 0}, New Integer() {20, 20}, New Integer() {0, 20}}
    Private squareHole As Integer()() = {New Integer() {0, 0}, New Integer() {20, 0}, New Integer() {20, 20}, New Integer() {0, 20}, New Integer() {5, 5}, New Integer() {15, 5}, New Integer() {15, 15}, New Integer() {5, 15}}
    Private strange As Integer()() = {New Integer() {0, 0}, New Integer() {5, 5}, New Integer() {0, 20}, New Integer() {5, 15}, New Integer() {15, 15}, New Integer() {20, 20}, New Integer() {20, 0}}
    Private hexagon As Integer()() = {New Integer() {6, 0}, New Integer() {14, 0}, New Integer() {20, 10}, New Integer() {14, 20}, New Integer() {6, 20}, New Integer() {0, 10}}
    Private shapes As Integer()()() = {square, squareHole, strange, hexagon}

    Public Sub Main()
        Dim testPoints As Double()() = {New Double() {10, 10}, New Double() {10, 16}, New Double() {-20, 10}, New Double() {0, 10}, New Double() {20, 10}, New Double() {16, 10}, New Double() {20, 20}}

        For Each shape As Integer()() In shapes
            For Each point As Double() In testPoints
                Console.Write(String.Format("{0} ", Contains(shape, point).ToString.PadLeft(7)))
            Next
            Console.WriteLine()
        Next
    End Sub

    Private Function Contains(shape As Integer()(), point As Double()) As Boolean

        Dim inside As Boolean = False
        Dim length As Integer = shape.Length

        For i As Integer = 0 To length - 1
            If Intersects(shape(i), shape((i + 1) Mod length), point) Then
                inside = Not inside
            End If
        Next

        Return inside
    End Function

    Private Function Intersects(a As Integer(), b As Integer(), p As Double()) As Boolean

        If a(1) > b(1) Then Return Intersects(b, a, p)
        If p(1) = a(1) Or p(1) = b(1) Then p(1) += 0.0001
        If p(1) > b(1) Or p(1) < a(1) Or p(0) >= Max(a(0), b(0)) Then Return False
        If p(0) < Min(a(0), b(0)) Then Return True
        Dim red As Double = (p(1) - a(1)) / (p(0) - a(0))
        Dim blue As Double = (b(1) - a(1)) / (b(0) - a(0))

        Return red >= blue
    End Function
End Module


#include <assert.h>
#include <math.h>
#include <stdio.h>

typedef struct point_tag {
    double x;
    double y;
} point_t;

// Returns the distance from point p to the line between p1 and p2
double perpendicular_distance(point_t p, point_t p1, point_t p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    double d = sqrt(dx * dx + dy * dy);
    return fabs(p.x * dy - p.y * dx + p2.x * p1.y - p2.y * p1.x)/d;
}

// Simplify an array of points using the Ramer–Douglas–Peucker algorithm.
// Returns the number of output points.
size_t douglas_peucker(const point_t* points, size_t n, double epsilon,
                       point_t* dest, size_t destlen) {
    assert(n >= 2);
    assert(epsilon >= 0);
    double max_dist = 0;
    size_t index = 0;
    for (size_t i = 1; i + 1 < n; ++i) {
        double dist = perpendicular_distance(points[i], points[0], points[n - 1]);
        if (dist > max_dist) {
            max_dist = dist;
            index = i;
        }
    }
    if (max_dist > epsilon) {
        size_t n1 = douglas_peucker(points, index + 1, epsilon, dest, destlen);
        if (destlen >= n1 - 1) {
            destlen -= n1 - 1;
            dest += n1 - 1;
        } else {
            destlen = 0;
        }
        size_t n2 = douglas_peucker(points + index, n - index, epsilon, dest, destlen);
        return n1 + n2 - 1;
    }
    if (destlen >= 2) {
        dest[0] = points[0];
        dest[1] = points[n - 1];
    }
    return 2;
}

void print_points(const point_t* points, size_t n) {
    for (size_t i = 0; i < n; ++i) {
        if (i > 0)
            printf(" ");
        printf("(%g, %g)", points[i].x, points[i].y);
    }
    printf("\n");
}

int main() {
    point_t points[] = {
        {0,0}, {1,0.1}, {2,-0.1}, {3,5}, {4,6},
        {5,7}, {6,8.1}, {7,9}, {8,9}, {9,9}
    };
    const size_t len = sizeof(points)/sizeof(points[0]);
    point_t out[len];
    size_t n = douglas_peucker(points, len, 1.0, out, len);
    print_points(out, n);
    return 0;
}


include ..\Utilitys.pmt

( ) var res
( )
(  0  1  2  4  6  7  8 11 12 14
  15 16 17 18 19 20 21 22 23 24
  25 27 28 29 30 31 32 33 35 36
  37 38 39 )

def append
    1 get swap -1 get rot swap
    2 tolist res swap 0 put var res
enddef

def printRes
    res len for
        get
        1 get swap 2 get nip
        over over == if
            drop print
        else
            over over - abs 1 > if "-" else "," endif
            rot print print print
        endif
        "," print
    endfor
    drop
    8 tochar print " " print
enddef

1 get rot swap 0 put swap

len 2 swap 2 tolist for
    get var num
    swap -1 get 1 + num != if
        append
        flush
    endif
    num 0 put swap
endfor
swap
append

clear

printRes


go =>
  Lists = [
            [-6, -3, -2, -1,  0,  1,  3,  4,  5,  7,  8,  9,
             10, 11, 14, 15, 17, 18, 19, 20],
            [ 0,  1,  2,  4,  6,  7,  8, 11, 12, 14, 15, 16, 17,
             18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31,
             32, 33, 35, 36, 37, 38, 39],
            1..20,
            [13],
            [11,12,13,15]
          ].
  foreach(List in Lists)
    println(List),
    println(make_ranges(List)),
    nl
  end,
  nl.

make_ranges(L) = Res =>
  Ranges = [],
  Range = [L[1]],

  % Identify the range
  foreach(I in 2..L.length)
     Li1 = L[I-1],
     Li  = L[I],
     if Li == Li1+1 then
        Range := Range ++ [Li]
     else
        if length(Range) > 0 then
           Ranges := Ranges ++ [Range]
        end,
        Range := [] ++ [Li]
     end
  end,
  % pickup the last range
  if length(Range) > 0 then
     Ranges := Ranges ++ [Range]
  end,
  Res :=  join([get_range(R) : R in Ranges], ",").

% Convert to range representation
get_range(R) =
   cond(R.length == 1,
      R.first().to_string(),
      min(R).to_string() ++ "-" ++ max(R).to_string()).


import "/fmt" for Fmt

class RayCasting {
    static intersects(a, b, p) {
        if (a[1] > b[1]) return intersects(b, a, p)
        if (p[1] == a[1] || p[1] == b[1]) p[1] = p[1] + 0.0001
        if (p[1] > b[1] || p[1] < a[1] || p[0] >= a[0].max(b[0])) return false
        if (p[0] < a[0].min(b[0])) return true
        var red  = (p[1] - a[1]) / (p[0] - a[0])
        var blue = (b[1] - a[1]) / (b[0] - a[0])
        return red >= blue
    }

    static contains(shape, pnt) {
        var inside = false
        var len = shape.count
        for (i in 0...len) {
            if (intersects(shape[i], shape[(i + 1) % len], pnt)) inside = !inside
        }
        return inside
    }

    static square { [[0, 0], [20, 0], [20, 20], [0, 20]] }

    static squareHole { [[0, 0], [20, 0], [20, 20], [0, 20], [5, 5], [15, 5], [15, 15], [5, 15]] }

    static strange { [[0, 0], [5, 5], [0, 20], [5, 15], [15, 15], [20, 20], [20, 0]] }

    static hexagon { [[6, 0], [14, 0], [20, 10], [14, 20], [6, 20], [0, 10]] }

    static shapes { [square, squareHole, strange, hexagon] }
}

var testPoints = [[10, 10], [10, 16], [-20, 10], [0, 10], [20, 10], [16, 10], [20, 20]]
for (shape in RayCasting.shapes) {
    for (pnt in testPoints) Fmt.write("$7s ", RayCasting.contains(shape, pnt))
    System.print()
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace LineSimplification {
    using Point = Tuple<double, double>;

    class Program {
        static double PerpendicularDistance(Point pt, Point lineStart, Point lineEnd) {
            double dx = lineEnd.Item1 - lineStart.Item1;
            double dy = lineEnd.Item2 - lineStart.Item2;

            // Normalize
            double mag = Math.Sqrt(dx * dx + dy * dy);
            if (mag > 0.0) {
                dx /= mag;
                dy /= mag;
            }
            double pvx = pt.Item1 - lineStart.Item1;
            double pvy = pt.Item2 - lineStart.Item2;

            // Get dot product (project pv onto normalized direction)
            double pvdot = dx * pvx + dy * pvy;

            // Scale line direction vector and subtract it from pv
            double ax = pvx - pvdot * dx;
            double ay = pvy - pvdot * dy;

            return Math.Sqrt(ax * ax + ay * ay);
        }

        static void RamerDouglasPeucker(List<Point> pointList, double epsilon, List<Point> output) {
            if (pointList.Count < 2) {
                throw new ArgumentOutOfRangeException("Not enough points to simplify");
            }

            // Find the point with the maximum distance from line between the start and end
            double dmax = 0.0;
            int index = 0;
            int end = pointList.Count - 1;
            for (int i = 1; i < end; ++i) {
                double d = PerpendicularDistance(pointList[i], pointList[0], pointList[end]);
                if (d > dmax) {
                    index = i;
                    dmax = d;
                }
            }

            // If max distance is greater than epsilon, recursively simplify
            if (dmax > epsilon) {
                List<Point> recResults1 = new List<Point>();
                List<Point> recResults2 = new List<Point>();
                List<Point> firstLine = pointList.Take(index + 1).ToList();
                List<Point> lastLine = pointList.Skip(index).ToList();
                RamerDouglasPeucker(firstLine, epsilon, recResults1);
                RamerDouglasPeucker(lastLine, epsilon, recResults2);

                // build the result list
                output.AddRange(recResults1.Take(recResults1.Count - 1));
                output.AddRange(recResults2);
                if (output.Count < 2) throw new Exception("Problem assembling output");
            }
            else {
                // Just return start and end points
                output.Clear();
                output.Add(pointList[0]);
                output.Add(pointList[pointList.Count - 1]);
            }
        }

        static void Main(string[] args) {
            List<Point> pointList = new List<Point>() {
                new Point(0.0,0.0),
                new Point(1.0,0.1),
                new Point(2.0,-0.1),
                new Point(3.0,5.0),
                new Point(4.0,6.0),
                new Point(5.0,7.0),
                new Point(6.0,8.1),
                new Point(7.0,9.0),
                new Point(8.0,9.0),
                new Point(9.0,9.0),
            };
            List<Point> pointListOut = new List<Point>();
            RamerDouglasPeucker(pointList, 1.0, pointListOut);
            Console.WriteLine("Points remaining after simplification:");
            pointListOut.ForEach(p => Console.WriteLine(p));
        }
    }
}


(de rangeextract (Lst)
   (glue ","
      (make
         (while Lst
            (let (N (pop 'Lst)  M N)
               (while (= (inc M) (car Lst))
                  (setq M (pop 'Lst)) )
               (cond
                  ((= N M) (link N))
                  ((= (inc N) M) (link N M))
                  (T (link (list N '- M))) ) ) ) ) ) )


/* Modified 19 November 2011 to meet requirement that there be at  */
/* least 3 items in a run.                                         */
range_extraction:                         /* 17 August 2010 */
   procedure options (main);
   declare (c, d) character (1);
   declare (old, new, initial) fixed binary (31);
   declare in file;
   declare out file output;

   open file (in)  title ('/range2.dat,type(text),recsize(80)' );
   open file (out) output title ('/range2.out,type(text),recsize(70)');

   c = ' '; d = ',';
   get file (in) list (old);
   do forever;
      initial = old;
      on endfile (in) begin;
         put file (out) edit (c, trim(old)) (a);
         stop;
      end;
      get file (in) list (new);
      if new = old+1 then
         do; /* we have a run. */
            on endfile (in) begin;
               if old > initial+1 then d = '-';
                  put file (out) edit (c, trim(initial), d, trim(old) ) (a);
               stop;
            end;
            do while (new = old+1);
               old = new;
               get file (in) list (new);
            end;
            /* At this point, old holds the last in a run;           */
            /* initial holds the first in a run.                     */
            /* if there are only two members in a run, don't use the */
            /* range notation.                                       */
            if old > initial+1 then d = '-';
               put file (out) edit (c, trim(initial), d, trim(old) ) (a);
            old = new;
         end;
      else /* we have an isolated value. */
         do;
            put file (out) edit (c, trim(old)) (a);
            old = new;
         end;
      c, d = ',';
   end;
end range_extraction;


const E = 0.0001;

fcn rayHitsSeg([(Px,Py)],[(Ax,Ay)],[(Bx,By)]){ // --> Bool
   if(Py==Ay or Py==By) Py+=E;
   if(Py<Ay or Py>By or Px>Ax.max(Bx)) False
   else if(Px<Ax.min(Bx))              True
   else try{ ( (Py - Ay)/(Px - Ax) )>=( (By - Ay)/(Bx - Ax) ) } //blue>=red
        catch(MathError){ Px==Ax } // divide by zero == ∞, only blue?
}

fcn pointInPoly(point, polygon){ // --> Bool, polygon is ( (a,b),(c,d).. )
   polygon.filter('wrap([(ab,cd)]){ a,b:=ab; c,d:=cd;
      if(b<=d) rayHitsSeg(point,ab,cd); // left point has smallest y coordinate
      else     rayHitsSeg(point,cd,ab);
   })
   .len().isOdd; // True if crossed an odd number of borders ie inside polygon
}


#include <iostream>
#include <cmath>
#include <utility>
#include <vector>
#include <stdexcept>
using namespace std;

typedef std::pair<double, double> Point;

double PerpendicularDistance(const Point &pt, const Point &lineStart, const Point &lineEnd)
{
	double dx = lineEnd.first - lineStart.first;
	double dy = lineEnd.second - lineStart.second;

	//Normalise
	double mag = pow(pow(dx,2.0)+pow(dy,2.0),0.5);
	if(mag > 0.0)
	{
		dx /= mag; dy /= mag;
	}

	double pvx = pt.first - lineStart.first;
	double pvy = pt.second - lineStart.second;

	//Get dot product (project pv onto normalized direction)
	double pvdot = dx * pvx + dy * pvy;

	//Scale line direction vector
	double dsx = pvdot * dx;
	double dsy = pvdot * dy;

	//Subtract this from pv
	double ax = pvx - dsx;
	double ay = pvy - dsy;

	return pow(pow(ax,2.0)+pow(ay,2.0),0.5);
}

void RamerDouglasPeucker(const vector<Point> &pointList, double epsilon, vector<Point> &out)
{
	if(pointList.size()<2)
		throw invalid_argument("Not enough points to simplify");

	// Find the point with the maximum distance from line between start and end
	double dmax = 0.0;
	size_t index = 0;
	size_t end = pointList.size()-1;
	for(size_t i = 1; i < end; i++)
	{
		double d = PerpendicularDistance(pointList[i], pointList[0], pointList[end]);
		if (d > dmax)
		{
			index = i;
			dmax = d;
		}
	}

	// If max distance is greater than epsilon, recursively simplify
	if(dmax > epsilon)
	{
		// Recursive call
		vector<Point> recResults1;
		vector<Point> recResults2;
		vector<Point> firstLine(pointList.begin(), pointList.begin()+index+1);
		vector<Point> lastLine(pointList.begin()+index, pointList.end());
		RamerDouglasPeucker(firstLine, epsilon, recResults1);
		RamerDouglasPeucker(lastLine, epsilon, recResults2);

		// Build the result list
		out.assign(recResults1.begin(), recResults1.end()-1);
		out.insert(out.end(), recResults2.begin(), recResults2.end());
		if(out.size()<2)
			throw runtime_error("Problem assembling output");
	}
	else
	{
		//Just return start and end points
		out.clear();
		out.push_back(pointList[0]);
		out.push_back(pointList[end]);
	}
}

int main()
{
	vector<Point> pointList;
	vector<Point> pointListOut;

	pointList.push_back(Point(0.0, 0.0));
	pointList.push_back(Point(1.0, 0.1));
	pointList.push_back(Point(2.0, -0.1));
	pointList.push_back(Point(3.0, 5.0));
	pointList.push_back(Point(4.0, 6.0));
	pointList.push_back(Point(5.0, 7.0));
	pointList.push_back(Point(6.0, 8.1));
	pointList.push_back(Point(7.0, 9.0));
	pointList.push_back(Point(8.0, 9.0));
	pointList.push_back(Point(9.0, 9.0));

	RamerDouglasPeucker(pointList, 1.0, pointListOut);

	cout << "result" << endl;
	for(size_t i=0;i< pointListOut.size();i++)
	{
		cout << pointListOut[i].first << "," << pointListOut[i].second << endl;
	}

	return 0;
}


import std.algorithm;
import std.exception : enforce;
import std.math;
import std.stdio;

void main() {
    creal[] pointList = [
        0.0 +  0.0i,
        1.0 +  0.1i,
        2.0 + -0.1i,
        3.0 +  5.0i,
        4.0 +  6.0i,
        5.0 +  7.0i,
        6.0 +  8.1i,
        7.0 +  9.0i,
        8.0 +  9.0i,
        9.0 +  9.0i
    ];
    creal[] pointListOut;

    ramerDouglasPeucker(pointList, 1.0, pointListOut);

    writeln("result");
    for (size_t i=0; i< pointListOut.length; i++) {
        writeln(pointListOut[i].re, ",", pointListOut[i].im);
    }
}

real perpendicularDistance(const creal pt, const creal lineStart, const creal lineEnd) {
    creal d = lineEnd - lineStart;

    //Normalise
    real mag =  hypot(d.re, d.im);
    if (mag > 0.0) {
        d /= mag;
    }

    creal pv = pt - lineStart;

    //Get dot product (project pv onto normalized direction)
    real pvdot = d.re * pv.re + d.im * pv.im;

    //Scale line direction vector
    creal ds = pvdot * d;

    //Subtract this from pv
    creal a = pv - ds;

    return hypot(a.re, a.im);
}

void ramerDouglasPeucker(const creal[] pointList, real epsilon, ref creal[] output) {
    enforce(pointList.length >= 2, "Not enough points to simplify");

    // Find the point with the maximum distance from line between start and end
    real dmax = 0.0;
    size_t index = 0;
    size_t end = pointList.length-1;
    for (size_t i=1; i<end; i++) {
        real d = perpendicularDistance(pointList[i], pointList[0], pointList[end]);
        if (d > dmax) {
            index = i;
            dmax = d;
        }
    }

    // If max distance is greater than epsilon, recursively simplify
    if (dmax > epsilon) {
        // Recursive call
        creal[] firstLine = pointList[0..index+1].dup;
        creal[] lastLine = pointList[index+1..$].dup;

        creal[] recResults1;
        ramerDouglasPeucker(firstLine, epsilon, recResults1);

        creal[] recResults2;
        ramerDouglasPeucker(lastLine, epsilon, recResults2);

        // Build the result list
        output = recResults1 ~ recResults2;

        enforce(output.length>=2, "Problem assembling output");
    } else {
        //Just return start and end points
        output.length = 0;
        output ~= pointList[0];
        output ~= pointList[end];
    }
}


with Ada.Numerics;                       use Ada.Numerics;
with Ada.Numerics.Float_Random;          use Ada.Numerics.Float_Random;
with Ada.Numerics.Elementary_Functions;  use Ada.Numerics.Elementary_Functions;

procedure Normal_Random is
   function Normal_Distribution
            (  Seed  : Generator;
               Mu    : Float := 1.0;
               Sigma : Float := 0.5
            )  return Float is
   begin
      return
         Mu + (Sigma * Sqrt (-2.0 * Log (Random (Seed), 10.0)) * Cos (2.0 * Pi * Random (Seed)));
   end Normal_Distribution;

   Seed         : Generator;
   Distribution : array (1..1_000) of Float;
begin
   Reset (Seed);
   for I in Distribution'Range loop
      Distribution (I) := Normal_Distribution (Seed);
   end loop;
end Normal_Random;


Function DistanciaPerpendicular(tabla() As Double, i As Integer, ini As Integer, fin As Integer) As Double
    Dim As Double dx, dy, mag, pvx, pvy, pvdot, dsx, dsy, ax, ay

    dx = tabla(fin, 1) - tabla(ini, 1)
    dy = tabla(fin, 2) - tabla(ini, 2)

    'Normaliza
    mag = (dx^2 + dy^2)^0.5
    If mag > 0 Then dx /= mag : dy /= mag

    pvx = tabla(i, 1) - tabla(ini, 1)
    pvy = tabla(i, 2) - tabla(ini, 2)

    'Producto escalado (proyecto pv en dirección normalizada)
    pvdot = dx * pvx + dy * pvy

    'Vector de dirección de línea de escala
    dsx = pvdot * dx
    dsy = pvdot * dy

    'Reste esto de pv
    ax = pvx - dsx
    ay = pvy - dsy

    Return (ax^2 + ay^2)^0.5
End Function

Sub DRDP(ListaDePuntos() As Double, ini As Integer, fin As Integer, epsilon As Double)
    Dim As Double dmax, d
    Dim As Integer indice, i
    ' Encuentra el punto con la distancia máxima

    If Ubound(ListaDePuntos) < 2 Then Print "No hay suficientes puntos para simplificar " : Sleep : End

    For i = ini + 1 To fin
        d = DistanciaPerpendicular(ListaDePuntos(), i, ini, fin)
        If d > dmax Then indice = i : dmax = d
    Next

    ' Si la distancia máxima es mayor que épsilon, simplifique de forma recursiva
    If dmax > epsilon Then
        ListaDePuntos(indice, 3) = True
        DRDP(ListaDePuntos(), ini, indice, epsilon)
        DRDP(ListaDePuntos(), indice, fin, epsilon)
    End If
End Sub

Dim As Double matriz(1 To 10, 1 To 3)
Data 0, 0, 1, 0.1, 2, -0.1, 3, 5, 4, 6, 5, 7, 6, 8.1, 7, 9, 8, 9, 9, 9
For i As Integer = Lbound(matriz) To Ubound(matriz)
    Read matriz(i, 1), matriz(i, 2)
Next i

DRDP(matriz(), 1, 10, 1)

Print "Puntos restantes tras de simplificar:"
matriz(1, 3) = True : matriz(10, 3) = True
For i As Integer = Lbound(matriz) To Ubound(matriz)
    If matriz(i, 3) Then Print "(";matriz(i, 1);", "; matriz(i, 2);")  ";
Next i
Sleep


DataSection
  Data.i  33 ;count of elements to be read
  Data.i  0,  1,  2,  4,  6,  7,  8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
  Data.i  25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39
EndDataSection

NewList values()
;setup list
Define elementCount, i
Read.i elementCount
For i = 1 To elementCount
  AddElement(values()): Read.i values()
Next

Procedure.s rangeExtract(List values())
  Protected listSize = ListSize(values()) - 1
  Protected rangeMarker, rangeStart, rangeIncrement, retraceSteps, rangeSize, endOfRange, output.s, sub.s

  ForEach values()
    rangeStart = values():
    sub = Str(rangeStart)
    If NextElement(values())
      retraceSteps = 1
      rangeIncrement = values() - rangeStart
      If rangeIncrement = 1 Or rangeIncrement = -1
        ;found start of possible range
        If ListIndex(values()) <> listSize
          retraceSteps = 2
          rangeSize = 2
          endOfRange = #False
          rangeMarker = values()
          While NextElement(values())
            If values() - rangeMarker <> rangeIncrement
              endOfRange = #True
              Break
            EndIf
            rangeSize + 1
            rangeMarker = values()
          Wend

          If rangeSize > 2
            sub = Str(rangeStart) + "-" + Str(rangeMarker)
            If Not endOfRange
              retraceSteps = 0 ;at end of list
            Else
              retraceSteps = 1
            EndIf
          EndIf
        EndIf
      EndIf

      ;return to the value before look-aheads
      While retraceSteps > 0
        PreviousElement(values()): retraceSteps - 1
      Wend
    EndIf

    output + sub + ","
  Next

  ProcedureReturn RTrim(output, ",")
EndProcedure

If OpenConsole()
  PrintN(rangeExtract(values()))

  Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
  Input()
  CloseConsole()
EndIf


PROC random normal = REAL:  # normal distribution, centered on 0, std dev 1 #
(
  sqrt(-2*log(random)) * cos(2*pi*random)
);

test:(
  [1000]REAL rands;
  FOR i TO UPB rands DO
    rands[i] := 1 + random normal/2
  OD;
  INT limit=10;
  printf(($"("n(limit-1)(-d.6d",")-d.5d" ... )"$, rands[:limit]))
)


rnd: function []-> (random 0 10000)//10000

rands: map 1..1000 'x [
    1 + (sqrt neg 2 * ln rnd) * (cos 2 * pi * rnd)
]

print rands


def range_extract(lst):
    'Yield 2-tuple ranges or 1-tuple single elements from list of increasing ints'
    lenlst = len(lst)
    i = 0
    while i< lenlst:
        low = lst[i]
        while i <lenlst-1 and lst[i]+1 == lst[i+1]: i +=1
        hi = lst[i]
        if   hi - low >= 2:
            yield (low, hi)
        elif hi - low == 1:
            yield (low,)
            yield (hi,)
        else:
            yield (low,)
        i += 1

def printr(ranges):
    print( ','.join( (('%i-%i' % r) if len(r) == 2 else '%i' % r)
                     for r in ranges ) )

if __name__ == '__main__':
    for lst in [[-8, -7, -6, -3, -2, -1, 0, 1, 3, 4, 5, 7,
                 8, 9, 10, 11, 14, 15, 17, 18, 19, 20],
                [0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22,
                 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39]]:
        #print(list(range_extract(lst)))
        printr(range_extract(lst))


Loop 40
   R .= RandN(1,0.5) "`n"  ; mean = 1.0, standard deviation = 0.5
MsgBox %R%

RandN(m,s) { ; Normally distributed random numbers of mean = m, std.dev = s by Box-Muller method
   Static i, Y
   If (i := !i) { ; every other call
      Random U, 0, 1.0
      Random V, 0, 6.2831853071795862
      U := sqrt(-2*ln(U))*s
      Y := m + U*sin(V)
      Return m + U*cos(V)
   }
   Return Y
}


Method "U(_,_)" is
[
	lower : number,
	upper : number
|
	divisor ::= ((1<<32)) ÷ (upper - lower)→double;
	map a pRNG through [i : integer | (i ÷ divisor) + lower]
];

Method "a Marsaglia polar sampler" is
[
	generator for
		[
			yield : [double]→⊤
		|
			source ::= U(-1, 1);
			Repeat [
				x ::= take 1 from source[1];
				y ::= take 1 from source[1];
				s ::= x^2 + y^2;
				If 0 < s < 1 then
				[
					factor ::= ((-2 × ln s) ÷ s) ^ 0.5;
					yield(x × factor);
					yield(y × factor);
				];
			]
		]
];

// the default distribution has mean 0 and std dev 1.0, so we scale the values
sampler ::= map a Marsaglia polar sampler through [d : double | d ÷ 2.0 + 1.0];
values ::= take 1000 from sampler;


mp=: +/ .*           NB. matrix product
norm=: +/&.:*:       NB. vector norm
normalize=: (% norm)^:(0 < norm)

dxy=. [email protected]({: - {.)
pv=. -"1 {.
NB.*perpDist v Calculate perpendicular distance of points from a line
perpDist=: norm"1@(pv ([ -"1 mp"1~ */ ]) dxy) f.

rdp=: verb define
  1 rdp y
  :
  points=. ,:^:(2 > #@$) y
  epsilon=. x
  if. 2 > # points do. points return. end.

  NB. point with the maximum distance from line between start and end
  'imax dmax'=. ((i. , ]) >./) perpDist points
  if. dmax > epsilon do.
    epsilon ((}:@rdp (1+imax)&{.) , (rdp imax&}.)) points
  else.
    ({. ,: {:) points
  end.
)


import javafx.util.Pair;

import java.util.ArrayList;
import java.util.List;

public class LineSimplification {
    private static class Point extends Pair<Double, Double> {
        Point(Double key, Double value) {
            super(key, value);
        }

        @Override
        public String toString() {
            return String.format("(%f, %f)", getKey(), getValue());
        }
    }

    private static double perpendicularDistance(Point pt, Point lineStart, Point lineEnd) {
        double dx = lineEnd.getKey() - lineStart.getKey();
        double dy = lineEnd.getValue() - lineStart.getValue();

        // Normalize
        double mag = Math.hypot(dx, dy);
        if (mag > 0.0) {
            dx /= mag;
            dy /= mag;
        }
        double pvx = pt.getKey() - lineStart.getKey();
        double pvy = pt.getValue() - lineStart.getValue();

        // Get dot product (project pv onto normalized direction)
        double pvdot = dx * pvx + dy * pvy;

        // Scale line direction vector and subtract it from pv
        double ax = pvx - pvdot * dx;
        double ay = pvy - pvdot * dy;

        return Math.hypot(ax, ay);
    }

    private static void ramerDouglasPeucker(List<Point> pointList, double epsilon, List<Point> out) {
        if (pointList.size() < 2) throw new IllegalArgumentException("Not enough points to simplify");

        // Find the point with the maximum distance from line between the start and end
        double dmax = 0.0;
        int index = 0;
        int end = pointList.size() - 1;
        for (int i = 1; i < end; ++i) {
            double d = perpendicularDistance(pointList.get(i), pointList.get(0), pointList.get(end));
            if (d > dmax) {
                index = i;
                dmax = d;
            }
        }

        // If max distance is greater than epsilon, recursively simplify
        if (dmax > epsilon) {
            List<Point> recResults1 = new ArrayList<>();
            List<Point> recResults2 = new ArrayList<>();
            List<Point> firstLine = pointList.subList(0, index + 1);
            List<Point> lastLine = pointList.subList(index, pointList.size());
            ramerDouglasPeucker(firstLine, epsilon, recResults1);
            ramerDouglasPeucker(lastLine, epsilon, recResults2);

            // build the result list
            out.addAll(recResults1.subList(0, recResults1.size() - 1));
            out.addAll(recResults2);
            if (out.size() < 2) throw new RuntimeException("Problem assembling output");
        } else {
            // Just return start and end points
            out.clear();
            out.add(pointList.get(0));
            out.add(pointList.get(pointList.size() - 1));
        }
    }

    public static void main(String[] args) {
        List<Point> pointList = List.of(
                new Point(0.0, 0.0),
                new Point(1.0, 0.1),
                new Point(2.0, -0.1),
                new Point(3.0, 5.0),
                new Point(4.0, 6.0),
                new Point(5.0, 7.0),
                new Point(6.0, 8.1),
                new Point(7.0, 9.0),
                new Point(8.0, 9.0),
                new Point(9.0, 9.0)
        );
        List<Point> pointListOut = new ArrayList<>();
        ramerDouglasPeucker(pointList, 1.0, pointListOut);
        System.out.println("Points remaining after simplification:");
        pointListOut.forEach(System.out::println);
    }
}


#include <iomanip>
#include <iostream>
#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>

using big_float = boost::multiprecision::cpp_dec_float_100;

big_float f(unsigned int n) {
    big_float pi(boost::math::constants::pi<big_float>());
    return exp(sqrt(big_float(n)) * pi);
}

int main() {
    std::cout << "Ramanujan's constant using formula f(N) = exp(pi*sqrt(N)):\n"
        << std::setprecision(80) << f(163) << '\n';
    std::cout << "\nResult with last four Heegner numbers:\n";
    std::cout << std::setprecision(30);
    for (unsigned int n : {19, 43, 67, 163}) {
        auto x = f(n);
        auto c = ceil(x);
        auto pc = 100.0 * (x/c);
        std::cout << "f(" << n << ") = " << x << " = "
            << pc << "% of " << c << '\n';
    }
    return 0;
}


(define make-range
  Start Start -> ["," Start]
  Start End   -> ["," Start "," End] where (= End (+ Start 1))
  Start End   -> ["," Start "-" End])

(define range-extract-0
  Start End []     -> (make-range Start End)
  Start End [A|As] -> (range-extract-0 Start A As) where (= (+ 1 End) A)
  Start End [A|As] -> (append (make-range Start End) (range-extract-0 A A As)))

(define range-extract
  [A |As] -> (FORMAT NIL "~{~a~}" (tail (range-extract-0 A A As))))

(range-extract [ 0  1  2  4  6  7  8 11 12 14
                15 16 17 18 19 20 21 22 23 24
                25 27 28 29 30 31 32 33 35 36
                37 38 39])


RANDOMIZE TIMER 'seeds random number generator with the system time
pi = 3.141592653589793#
DIM a(1 TO 1000) AS DOUBLE
CLS
FOR i = 1 TO 1000
   a(i) = 1 + SQR(-2 * LOG(RND)) * COS(2 * pi * RND)
NEXT i


#include <stdlib.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

double drand()   /* uniform distribution, (0..1] */
{
  return (rand()+1.0)/(RAND_MAX+1.0);
}
double random_normal()  /* normal distribution, centered on 0, std dev 1 */
{
  return sqrt(-2*log(drand())) * cos(2*M_PI*drand());
}
int main()
{
  int i;
  double rands[1000];
  for (i=0; i<1000; i++)
    rands[i] = 1.0 + 0.5*random_normal();
  return 0;
}


private static double randomNormal()
{
	return Math.Cos(2 * Math.PI * tRand.NextDouble()) * Math.Sqrt(-2 * Math.Log(tRand.NextDouble()));
}


/**
 * @typedef {{
 *    x: (!number),
 *    y: (!number)
 * }}
 */
let pointType;

/**
 * @param {!Array<pointType>} l
 * @param {number} eps
 */
const RDP = (l, eps) => {
  const last = l.length - 1;
  const p1 = l[0];
  const p2 = l[last];
  const x21 = p2.x - p1.x;
  const y21 = p2.y - p1.y;

  const [dMax, x] = l.slice(1, last)
      .map(p => Math.abs(y21 * p.x - x21 * p.y + p2.x * p1.y - p2.y * p1.x))
      .reduce((p, c, i) => {
        const v = Math.max(p[0], c);
        return [v, v === p[0] ? p[1] : i + 1];
      }, [-1, 0]);

  if (dMax > eps) {
    return [...RDP(l.slice(0, x + 1), eps), ...RDP(l.slice(x), eps).slice(1)];
  }
  return [l[0], l[last]]
};

const points = [
  {x: 0, y: 0},
  {x: 1, y: 0.1},
  {x: 2, y: -0.1},
  {x: 3, y: 5},
  {x: 4, y: 6},
  {x: 5, y: 7},
  {x: 6, y: 8.1},
  {x: 7, y: 9},
  {x: 8, y: 9},
  {x: 9, y: 9}];

console.log(RDP(points, 1));


package main

import (
    "fmt"
    "github.com/ALTree/bigfloat"
    "math/big"
)

const (
    prec = 256 // say
    ps   = "3.1415926535897932384626433832795028841971693993751058209749445923078164"
)

func q(d int64) *big.Float {
    pi, _ := new(big.Float).SetPrec(prec).SetString(ps)
    t := new(big.Float).SetPrec(prec).SetInt64(d)
    t.Sqrt(t)
    t.Mul(pi, t)
    return bigfloat.Exp(t)
}

func main() {
    fmt.Println("Ramanujan's constant to 32 decimal places is:")
    fmt.Printf("%.32f\n", q(163))
    heegners := [4][2]int64{
        {19, 96},
        {43, 960},
        {67, 5280},
        {163, 640320},
    }
    fmt.Println("\nHeegner numbers yielding 'almost' integers:")
    t := new(big.Float).SetPrec(prec)
    for _, h := range heegners {
        qh := q(h[0])
        c := h[1]*h[1]*h[1] + 744
        t.SetInt64(c)
        t.Sub(t, qh)
        fmt.Printf("%3d: %51.32f ≈ %18d (diff: %.32f)\n", h[0], qh, c, t)
    }
}


#include <random>
#include <functional>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
  random_device seed;
  mt19937 engine(seed());
  normal_distribution<double> dist(1.0, 0.5);
  auto rnd = bind(dist, engine);

  vector<double> v(1000);
  generate(v.begin(), v.end(), rnd);
  return 0;
}


(import '(java.util Random))
(def normals
  (let [r (Random.)]
    (take 1000 (repeatedly #(-> r .nextGaussian (* 0.5) (+ 1.0))))))


       IDENTIFICATION DIVISION.
       PROGRAM-ID. RANDOM.
       AUTHOR.  Bill Gunshannon
       INSTALLATION.  Home.
       DATE-WRITTEN.  14 January 2022.
      ************************************************************
      ** Program Abstract:
      **   Able to get the Mean to be really close to 1.0 but
      **     couldn't get the Standard Deviation any closer than
      **     .3 to .4.
      ************************************************************

       DATA DIVISION.

       WORKING-STORAGE SECTION.

       01  Sample-Size          PIC 9(5)         VALUE 1000.
       01  Total                PIC 9(10)V9(5)  VALUE 0.0.
       01  Arith-Mean           PIC 999V999  VALUE 0.0.
       01  Std-Dev              PIC 999V999  VALUE 0.0.
       01  Seed                 PIC 999V999.
       01  TI                   PIC 9(8).

       01  Idx                  PIC 99999     VALUE 0.
       01  Intermediate         PIC 9(10)V9(5)  VALUE 0.0.
       01  Rnd-Work.
           05  Rnd-Tbl
                   OCCURS 1 TO 99999 TIMES DEPENDING ON Sample-Size.
               10  Rnd              PIC 9V9999999  VALUE 0.0.

       PROCEDURE DIVISION.

       Main-Program.
           ACCEPT TI FROM TIME.
           MOVE FUNCTION RANDOM(TI) TO Seed.
           PERFORM WITH TEST AFTER VARYING Idx
                   FROM 1 BY 1
                   UNTIL Idx = Sample-Size
              COMPUTE Intermediate =
                           (FUNCTION RANDOM() * 2.01)
              MOVE Intermediate TO Rnd(Idx)
           END-PERFORM.
           PERFORM WITH TEST AFTER VARYING Idx
                   FROM 1 BY 1
                   UNTIL Idx = Sample-Size
              COMPUTE Total = Total + Rnd(Idx)
           END-PERFORM.

           COMPUTE Arith-Mean = Total / Sample-Size.
           DISPLAY "Mean: " Arith-Mean.

           PERFORM WITH TEST AFTER VARYING Idx
                   FROM 1 BY 1
                   UNTIL Idx = Sample-Size
              COMPUTE Intermediate =
                      Intermediate + (Rnd(Idx) - Arith-Mean) ** 2
           END-PERFORM.
              COMPUTE Std-Dev = Intermediate / Sample-Size.

           DISPLAY "Std-Dev: " Std-Dev.

           STOP RUN.

       END PROGRAM RANDOM.


const Point = Vector{Float64}

function perpdist(pt::Point, lnstart::Point, lnend::Point)
    d = normalize!(lnend .- lnstart)

    pv = pt .- lnstart
    # Get dot product (project pv onto normalized direction)
    pvdot = dot(d, pv)
    # Scale line direction vector
    ds = pvdot .* d
    # Subtract this from pv
    return norm(pv .- ds)
end

function rdp(plist::Vector{Point}, ϵ::Float64 = 1.0)
    if length(plist) < 2
        throw(ArgumentError("not enough points to simplify"))
    end

    # Find the point with the maximum distance from line between start and end
    distances  = collect(perpdist(pt, plist[1], plist[end]) for pt in plist)
    dmax, imax = findmax(distances)

    # If max distance is greater than epsilon, recursively simplify
    if dmax > ϵ
        fstline = plist[1:imax]
        lstline = plist[imax:end]

        recrst1 = rdp(fstline, ϵ)
        recrst2 = rdp(lstline, ϵ)

        out = vcat(recrst1, recrst2)
    else
        out = [plist[1], plist[end]]
    end

    return out
end

plist = Point[[0.0, 0.0], [1.0, 0.1], [2.0, -0.1], [3.0, 5.0], [4.0, 6.0], [5.0, 7.0], [6.0, 8.1], [7.0, 9.0], [8.0, 9.0], [9.0, 9.0]]
@show plist
@show rdp(plist)


// version 1.1.0

typealias Point = Pair<Double, Double>

fun perpendicularDistance(pt: Point, lineStart: Point, lineEnd: Point): Double {
    var dx = lineEnd.first - lineStart.first
    var dy = lineEnd.second - lineStart.second

    // Normalize
    val mag = Math.hypot(dx, dy)
    if (mag > 0.0) { dx /= mag; dy /= mag }
    val pvx = pt.first - lineStart.first
    val pvy = pt.second - lineStart.second

    // Get dot product (project pv onto normalized direction)
    val pvdot = dx * pvx + dy * pvy

    // Scale line direction vector and substract it from pv
    val ax = pvx - pvdot * dx
    val ay = pvy - pvdot * dy

    return Math.hypot(ax, ay)
}

fun RamerDouglasPeucker(pointList: List<Point>, epsilon: Double, out: MutableList<Point>) {
    if (pointList.size < 2) throw IllegalArgumentException("Not enough points to simplify")

    // Find the point with the maximum distance from line between start and end
    var dmax = 0.0
    var index = 0
    val end = pointList.size - 1
    for (i in 1 until end) {
        val d = perpendicularDistance(pointList[i], pointList[0], pointList[end])
        if (d > dmax) { index = i; dmax = d }
    }

    // If max distance is greater than epsilon, recursively simplify
    if (dmax > epsilon) {
        val recResults1 = mutableListOf<Point>()
        val recResults2 = mutableListOf<Point>()
        val firstLine = pointList.take(index + 1)
        val lastLine  = pointList.drop(index)
        RamerDouglasPeucker(firstLine, epsilon, recResults1)
        RamerDouglasPeucker(lastLine, epsilon, recResults2)

        // build the result list
        out.addAll(recResults1.take(recResults1.size - 1))
        out.addAll(recResults2)
        if (out.size < 2) throw RuntimeException("Problem assembling output")
    }
    else {
        // Just return start and end points
        out.clear()
        out.add(pointList.first())
        out.add(pointList.last())
    }
}

fun main(args: Array<String>) {
    val pointList = listOf(
        Point(0.0, 0.0),
        Point(1.0, 0.1),
        Point(2.0, -0.1),
        Point(3.0, 5.0),
        Point(4.0, 6.0),
        Point(5.0, 7.0),
        Point(6.0, 8.1),
	Point(7.0, 9.0),
	Point(8.0, 9.0),
        Point(9.0, 9.0)
    )
    val pointListOut = mutableListOf<Point>()
    RamerDouglasPeucker(pointList, 1.0, pointListOut)
    println("Points remaining after simplification:")
    for (p in pointListOut) println(p)
}


import Control.Monad (forM_)
import Data.Number.CReal (CReal, showCReal)
import Text.Printf (printf)

ramfun :: CReal -> CReal
ramfun x = exp (pi * sqrt x)

-- Ramanujan's constant.
ramanujan :: CReal
ramanujan = ramfun 163

-- The last four Heegner numbers.
heegners :: [Int]
heegners = [19, 43, 67, 163]

-- The absolute distance to the nearest integer.
intDist :: CReal -> CReal
intDist x = abs (x - fromIntegral (round x))

main :: IO ()
main = do
  let n = 35
  printf "Ramanujan's constant: %s\n\n" (showCReal n ramanujan)
  printf "%3s %34s%20s%s\n\n" " h " "e^(pi*sqrt(h))" "" " Dist. to integer"
  forM_ heegners $ \h ->
    let r = ramfun (fromIntegral h)
        d = intDist r
    in printf "%3d %54s %s\n" h (showCReal n r) (showCReal 15 d)


import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Arrays;
import java.util.List;

public class RamanujanConstant {

    public static void main(String[] args) {
        System.out.printf("Ramanujan's Constant to 100 digits = %s%n%n", ramanujanConstant(163, 100));
        System.out.printf("Heegner numbers yielding 'almost' integers:%n");
        List<Integer> heegnerNumbers = Arrays.asList(19, 43, 67, 163);
        List<Integer> heegnerVals = Arrays.asList(96, 960, 5280, 640320);
        for ( int i = 0 ; i < heegnerNumbers.size() ; i++ ) {
            int heegnerNumber = heegnerNumbers.get(i);
            int heegnerVal = heegnerVals.get(i);
            BigDecimal integer = BigDecimal.valueOf(heegnerVal).pow(3).add(BigDecimal.valueOf(744));
            BigDecimal compute = ramanujanConstant(heegnerNumber, 50);
            System.out.printf("%3d : %50s ~ %18s (diff ~ %s)%n", heegnerNumber, compute, integer, integer.subtract(compute, new MathContext(30)).toPlainString());
        }
    }

    public static BigDecimal ramanujanConstant(int sqrt, int digits) {
        //  For accuracy on lat digit, computations with a few extra digits
        MathContext mc = new MathContext(digits + 5);
        return bigE(bigPi(mc).multiply(bigSquareRoot(BigDecimal.valueOf(sqrt), mc), mc), mc).round(new MathContext(digits));
    }

    //  e = 1 + x/1! + x^2/2! + x^3/3! + ...
    public static BigDecimal bigE(BigDecimal exponent, MathContext mc) {
        BigDecimal e = BigDecimal.ONE;
        BigDecimal ak = e;
        int k = 0;
        BigDecimal min = BigDecimal.ONE.divide(BigDecimal.TEN.pow(mc.getPrecision()));
        while ( true ) {
            k++;
            ak = ak.multiply(exponent).divide(BigDecimal.valueOf(k), mc);
            e = e.add(ak, mc);
            if ( ak.compareTo(min) < 0 ) {
                break;
            }
        }
        return e;

    }

    //  See : https://www.craig-wood.com/nick/articles/pi-chudnovsky/
    public static BigDecimal bigPi(MathContext mc) {
        int k = 0;
        BigDecimal ak = BigDecimal.ONE;
        BigDecimal a = ak;
        BigDecimal b = BigDecimal.ZERO;
        BigDecimal c = BigDecimal.valueOf(640320);
        BigDecimal c3 = c.pow(3);
        double digitePerTerm = Math.log10(c.pow(3).divide(BigDecimal.valueOf(24), mc).doubleValue()) - Math.log10(72);
        double digits = 0;
        while ( digits < mc.getPrecision() ) {
            k++;
            digits += digitePerTerm;
            BigDecimal top = BigDecimal.valueOf(-24).multiply(BigDecimal.valueOf(6*k-5)).multiply(BigDecimal.valueOf(2*k-1)).multiply(BigDecimal.valueOf(6*k-1));
            BigDecimal term = top.divide(BigDecimal.valueOf(k*k*k).multiply(c3), mc);
            ak = ak.multiply(term, mc);
            a = a.add(ak, mc);
            b = b.add(BigDecimal.valueOf(k).multiply(ak, mc), mc);
        }
        BigDecimal total = BigDecimal.valueOf(13591409).multiply(a, mc).add(BigDecimal.valueOf(545140134).multiply(b, mc), mc);
        return BigDecimal.valueOf(426880).multiply(bigSquareRoot(BigDecimal.valueOf(10005), mc), mc).divide(total, mc);
    }

    //  See : https://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number
    public static BigDecimal bigSquareRoot(BigDecimal squareDecimal, MathContext mc) {
        //  Estimate
        double sqrt = Math.sqrt(squareDecimal.doubleValue());
        BigDecimal x0 = new BigDecimal(sqrt, mc);
        BigDecimal two = BigDecimal.valueOf(2);
        while ( true ) {
            BigDecimal x1 = x0.subtract(x0.multiply(x0, mc).subtract(squareDecimal).divide(two.multiply(x0, mc), mc), mc);
            String x1String = x1.toPlainString();
            String x0String = x0.toPlainString();
            if ( x1String.substring(0, x1String.length()-1).compareTo(x0String.substring(0, x0String.length()-1)) == 0 ) {
                break;
            }
            x0 = x1;
        }
        return x0;
    }

}


/*REXX program creates a  range extraction  from a  list of numbers  (can be negative.) */
old=0 1 2 4 6 7 8 11 12 14 15 16 17 18 19 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39
#= words(old)                                    /*number of integers in the number list*/
new=                                             /*the new list, possibly with ranges.  */
     do j=1  to  #;              z= word(old, j) /*obtain Jth number in the  old  list. */
     inc= 1;                   new= new','z      /*append  "    "    to  "   new    "   */
              do k=j+1  to #;    y= word(old, k) /*get the Kth number in the number list*/
              if y\==z+inc  then leave           /*is this number not > previous by inc?*/
              inc= inc + 1;      g= y            /*increase the range, assign  G (good).*/
              end   /*k*/
     if k-1=j   |   g=z+1   then iterate         /*Is the range=0│1?  Then keep truckin'*/
     new= new'-'g;               j= k - 1        /*indicate a range of #s;  change index*/
     end            /*j*/
                                                 /*stick a fork in it,  we're all done. */
new= substr(new, 2)                              /*elide the leading comma in the range.*/
say 'old:'   old;           say 'new:'  new      /*show the old and new range of numbers*/


# Project : Range extraction

int = "0,1,2,4,6,7,8,11,12,14,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39"
int = str2list(substr(int, ",", nl))
sumint = []
intnew = 1
for n=1 to len(int)
     flag = 0
     nr = 0
     intnew = 0
     for m=n to len(int)-1
         if int[m] = int[m+1] - 1
            intnew = m+1
            flag = 1
            nr = nr + 1
         else
            exit
          ok
     next
     if flag = 1 and nr > 1
        if intnew != 0
           add(sumint, [n,intnew])
           n = m
        ok
     else
        add(sumint, [n,""])
     ok
next
showarray(sumint)

func showarray(vect)
       see "["
       svect = ""
       for n = 1 to len(vect)
           if vect[n][2] != ""
              svect = svect +"" + int[vect[n][1]] + "-" + int[vect[n][2]] + ", "
           else
              svect = svect +"" + int[vect[n][1]] + ", "
           ok
       next
       svect = left(svect, len(svect) - 2)
       see svect
       see "]" + nl


(loop for i from 1 to 1000
      collect (1+ (* (sqrt (* -2 (log (random 1.0)))) (cos (* 2 pi (random 1.0))) 0.5)))


n, mean, sd, tau = 1000, 1, 0.5, (2 * Math::PI)
array = Array.new(n) { mean + sd * Math.sqrt(-2 * Math.log(rand)) * Math.cos(tau * rand) }

mean = array.sum / array.size
standev = Math.sqrt( array.sum{ |x| (x - mean) ** 2 } / array.size )
puts "mean = #{mean}, standard deviation = #{standev}"


import std.stdio, std.random, std.math;

struct NormalRandom {
    double mean, stdDev;

    // Necessary because it also defines an opCall.
    this(in double mean_, in double stdDev_) pure nothrow {
        this.mean = mean_;
        this.stdDev = stdDev_;
    }

    double opCall() const /*nothrow*/ {
        immutable r1 = uniform01, r2 = uniform01; // Not nothrow.
        return mean + stdDev * sqrt(-2 * r1.log) * cos(2 * PI * r2);
    }
}

void main() {
    double[1000] array;
    auto nRnd = NormalRandom(1.0, 0.5);
    foreach (ref x; array)
        //x = nRnd;
        x = nRnd();
}


import math

type
  Point = tuple[x, y: float64]

proc pointLineDistance(pt, lineStart, lineEnd: Point): float64 =
  var n, d, dx, dy: float64
  dx = lineEnd.x - lineStart.x
  dy = lineEnd.y - lineStart.y
  n = abs(dx * (lineStart.y - pt.y) - (lineStart.x - pt.x) * dy)
  d = sqrt(dx * dx + dy * dy)
  n / d

proc rdp(points: seq[Point], startIndex, lastIndex: int, ε: float64 = 1.0): seq[Point] =
  var dmax = 0.0
  var index = startIndex

  for i in index+1..<lastIndex:
    var d = pointLineDistance(points[i], points[startIndex], points[lastIndex])
    if d > dmax:
      index = i
      dmax = d

  if dmax > ε:
    var res1 = rdp(points, startIndex, index, ε)
    var res2 = rdp(points, index, lastIndex, ε)

    var finalRes: seq[Point] = @[]
    finalRes.add(res1[0..^2])
    finalRes.add(res2[0..^1])

    result = finalRes
  else:
    result = @[points[startIndex], points[lastIndex]]

var line: seq[Point] = @[(0.0, 0.0), (1.0, 0.1), (2.0, -0.1), (3.0, 5.0), (4.0, 6.0),
                         (5.0, 7.0), (6.0, 8.1), (7.0,  9.0), (8.0, 9.0), (9.0, 9.0)]
echo rdp(line, line.low, line.high)


function slice(a, v) = [ for (i = v) a[i] ];

// Find the distance from the point to the line
function perpendicular_distance(pt, start, end) =
    let (
        d = end - start,
        dn = d / norm(d),
        dp = pt - start,
        // Dot-product of two vectors
        ddot = dn * dp,
        ds = dn * ddot
    )
        norm(dp - ds);

// Find the point with the maximum distance from line between start and end.
// Returns a vector of [dmax, point_index]
function max_distance(pts, cindex=1, iresult=[0,0]) =
    let (
        d = perpendicular_distance(pts[cindex], pts[0],pts[len(pts)-1]),
        result = (d > iresult[0] ? [d, cindex] : iresult)
    )
        (cindex == len(pts) - 1 ?
            iresult :
            max_distance(pts, cindex+1, result));

// Tail recursion optimization is not possible with tree recursion.
//
// It's probably possible to optimize this with tail recursion by converting to
// iterative approach, see
// https://namekdev.net/2014/06/iterative-version-of-ramer-douglas-peucker-line-simplification-algorithm/ .
// It's not possible to use iterative approach without recursion at all because
// of static nature of OpenSCAD arrays.
function ramer_douglas_peucker(points, epsilon=1) =
    let (dmax = max_distance(points))
        // Simplify the line recursively if the max distance is greater than epsilon
        (dmax[0] > epsilon ?
            let (
                lo = ramer_douglas_peucker(
                    slice(points, [0:dmax[1]]), epsilon),
                hi = ramer_douglas_peucker(
                    slice(points, [dmax[1]:len(points)-1]), epsilon)
            )
                concat(slice(lo, [0:len(lo)-2]), hi) :
            [points[0],points[len(points)-1]]);

/* -- Demo -- */

module line(points, thickness=1, dot=2) {
    for (idx = [0:len(points)-2]) {
        translate(points[idx])
            sphere(d=dot);
        hull() {
            translate(points[idx])
                sphere(d=thickness);
            translate(points[idx+1])
                sphere(d=thickness);
        }
    }
    translate(points[len(points)-1])
        sphere(d=dot);
}

function addz(pts, z=0) = [ for (p = pts) [p.x, p.y, z] ];

module demo(pts) {
    rdp = ramer_douglas_peucker(points=pts, epsilon=1);
    echo(rdp);
    color("gray")
        line(points=addz(pts, 0), thickness=0.1, dot=0.3);
    color("red")
        line(points=addz(rdp, 1), thickness=0.1, dot=0.3);
}

$fn=16;
points = [[0,0], [1,0.1], [2,-0.1], [3,5], [4,6], [5,7], [6,8.1], [7,9], [8,9], [9,9]];
demo(points);


use strict;
use warnings;
use feature 'say';
use List::MoreUtils qw(firstidx minmax);

my $epsilon = 1;

sub norm {
    my(@list) = @_;
    my $sum;
    $sum += $_**2 for @list;
    sqrt($sum)
}

sub perpendicular_distance {
    our(@start,@end,@point);
    local(*start,*end,*point) = (shift, shift, shift);
    return 0 if $start[0]==$point[0] && $start[1]==$point[1]
             or   $end[0]==$point[0] &&   $end[1]==$point[1];
    my ( $dx,  $dy)  = (  $end[0]-$start[0],  $end[1]-$start[1]);
    my ($dpx, $dpy)  = ($point[0]-$start[0],$point[1]-$start[1]);
    my $t = norm($dx, $dy);
    $dx /= $t;
    $dy /= $t;
    norm($dpx - $dx*($dx*$dpx + $dy*$dpy), $dpy - $dy*($dx*$dpx + $dy*$dpy));
}

sub Ramer_Douglas_Peucker {
    my(@points) = @_;
    return @points if @points == 2;
    my @d;
    push @d, perpendicular_distance(@points[0, -1, $_]) for 0..@points-1;
    my(undef,$dmax) = minmax @d;
    my $index = firstidx { $_ == $dmax } @d;
    if ($dmax > $epsilon) {
        my @lo = Ramer_Douglas_Peucker( @points[0..$index]);
        my @hi = Ramer_Douglas_Peucker( @points[$index..$#points]);
        return  @lo[0..@lo-2], @hi;
    }
    @points[0, -1];
}

say '(' . join(' ', @$_) . ') '
    for Ramer_Douglas_Peucker( [0,0],[1,0.1],[2,-0.1],[3,5],[4,6],[5,7],[6,8.1],[7,9],[8,9],[9,9] )


First[RealDigits[N[Exp[Pi Sqrt[163]], 200]]]
Table[
 c = N[Exp[Pi Sqrt[h]], 40];
 Log10[1 - FractionalPart[c]]
 ,
 {h, {19, 43, 67, 163}}
]


import strformat, strutils
import decimal

setPrec(75)
let pi = newDecimal("3.1415926535897932384626433832795028841971693993751058209749445923078164")

proc eval(n: int): DecimalType =
  result = exp(pi * sqrt(newDecimal(n)))

func format(n: DecimalType; d: Positive): string =
  ## Return the representation of "n" with "d" digits of precision.
  let parts = ($n).split('.')
  result = parts[0] & '.' & parts[1][0..<d]

echo "Ramanujan’s constant with 50 digits of precision:"
echo eval(163).format(50)

setPrec(50)
echo()
echo "Heegner numbers yielding 'almost' integers:"
for n in [19, 43, 67, 163]:
  let x = eval(n)
  let k = x.roundToInt
  let d = x - k
  let s = if d > 0: "+ " & $d else: "- " & $(-d)
  echo &"{n:3}: {x}... = {k:>18} {s}..."


use strict;
use warnings;
use Math::AnyNum;

sub ramanujan_const {
    my ($x, $decimals) = @_;

    $x = Math::AnyNum->new($x);
    my $prec = (Math::AnyNum->pi * $x->sqrt)/log(10) + $decimals + 1;
    local $Math::AnyNum::PREC = 4*$prec->round->numify;

    exp(Math::AnyNum->pi * $x->sqrt)->round(-$decimals)->stringify;
}

my $decimals = 100;
printf("Ramanujan's constant to $decimals decimals:\n%s\n\n",
    ramanujan_const(163, $decimals));

print "Heegner numbers yielding 'almost' integers:\n";
my @tests = (19, 96, 43, 960, 67, 5280, 163, 640320);

while (@tests) {
    my ($h, $x) = splice(@tests, 0, 2);
    my $c = ramanujan_const($h, 32);
    my $n = Math::AnyNum::ipow($x, 3) + 744;
    printf("%3s: %51s ≈ %18s (diff: %s)\n", $h, $c, $n, ($n - $c)->round(-32));
}


def range_extract(l)
  # pad the list with a big value, so that the last loop iteration will
  # append something to the range
  sorted, range = l.sort.concat([Float::MAX]), []
  canidate_number = sorted.first

  # enumerate over the sorted list in pairs of current number and next by index
  sorted.each_cons(2) do |current_number, next_number|
    # if there is a gap between the current element and its next by index
    if current_number.succ < next_number
      # if current element is our first or our next by index
      if canidate_number == current_number
        # put the first element or next by index into our range as a string
        range << canidate_number.to_s
      else
        # if current element is not the same as the first or next
        # add [first or next, first or next equals current add , else -, current]
        seperator = canidate_number.succ == current_number ? "," : "-"
        range << "%d%s%d" % [canidate_number, seperator, current_number]
      end
      # make the first element the next element
      canidate_number = next_number
    end
  end
  range.join(',')
end

lst = [
    0,  1,  2,  4,  6,  7,  8, 11, 12, 14,
   15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
   25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
   37, 38, 39
]

p rng = range_extract(lst)


use std::ops::Add;

struct RangeFinder<'a, T: 'a> {
    index: usize,
    length: usize,
    arr: &'a [T],
}

impl<'a, T> Iterator for RangeFinder<'a, T> where T: PartialEq + Add<i8, Output=T> + Copy {
    type Item = (T,  Option<T>);
    fn next(&mut self) -> Option<Self::Item> {
        if self.index == self.length {
            return None;
        }
        let lo = self.index;
        while self.index < self.length - 1 && self.arr[self.index + 1] == self.arr[self.index] + 1 {
            self.index += 1
        }
        let hi = self.index;
        self.index += 1;
        if hi - lo > 1 {
            Some((self.arr[lo], Some(self.arr[hi])))
        } else {
            if hi - lo == 1 {
                self.index -= 1
            }
            Some((self.arr[lo], None))
        }
    }
}

impl<'a, T> RangeFinder<'a, T> {
    fn new(a: &'a [T]) -> Self {
        RangeFinder {
            index: 0,
            arr: a,
            length: a.len(),
        }
    }
}

fn main() {
    let input_numbers : &[i8] = &[0,  1,  2,  4,  6,  7,  8, 11, 12, 14,
                                  15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
                                  25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
                                  37, 38, 39];
    for (i, (lo, hi)) in RangeFinder::new(&input_numbers).enumerate() {
        if i > 0 {print!(",")}
        print!("{}", lo);
        if hi.is_some() {print!("-{}", hi.unwrap())}
    }
    println!("");
}


program Randoms;

{$APPTYPE CONSOLE}

uses
  Math;

var
  Values: array[0..999] of Double;
  I: Integer;

begin
//  Randomize;   Commented to obtain reproducible results
  for I:= Low(Values) to High(Values) do
    Values[I]:= RandG(1.0, 0.5);  // Mean = 1.0, StdDev = 0.5
  Writeln('Mean          = ', Mean(Values):6:4);
  Writeln('Std Deviation = ', StdDev(Values):6:4);
  Readln;
end.


var values : array [0..999] of Float;
var i : Integer;

for i := values.Low to values.High do
   values[i] := RandG(1, 0.5);


accum [] for _ in 1..1000 { _.with(entropy.nextGaussian()) }


with javascript_semantics
function rdp(sequence l, atom e)
    if length(l)<2 then crash("not enough points to simplify") end if
    integer idx := 0
    atom dMax := -1,
    {p1x,p1y} := l[1],
    {p2x,p2y} := l[$],
    x21 := p2x - p1x,
    y21 := p2y - p1y
    for i=1 to length(l) do
        atom {px,py} = l[i],
             d = abs(y21*px-x21*py + p2x*p1y-p2y*p1x)
        if d>dMax then
            idx = i
            dMax = d
        end if
    end for
    if dMax>e then
        return rdp(l[1..idx], e) & rdp(l[idx..$], e)[2..$]
    end if
    return {l[1], l[$]}
end function

sequence points = {{0, 0}, {1, 0.1}, {2, -0.1}, {3, 5}, {4, 6},
                   {5, 7}, {6, 8.1}, {7,    9}, {8, 9}, {9, 9}}
?rdp(points, 1)


function perpendicular_distance(array $pt, array $line) {
  // Calculate the normalized delta x and y of the line.
  $dx = $line[1][0] - $line[0][0];
  $dy = $line[1][1] - $line[0][1];
  $mag = sqrt($dx * $dx + $dy * $dy);
  if ($mag > 0) {
    $dx /= $mag;
    $dy /= $mag;
  }

  // Calculate dot product, projecting onto normalized direction.
  $pvx = $pt[0] - $line[0][0];
  $pvy = $pt[1] - $line[0][1];
  $pvdot = $dx * $pvx + $dy * $pvy;

  // Scale line direction vector and subtract from pv.
  $dsx = $pvdot * $dx;
  $dsy = $pvdot * $dy;
  $ax = $pvx - $dsx;
  $ay = $pvy - $dsy;

  return sqrt($ax * $ax + $ay * $ay);
}

function ramer_douglas_peucker(array $points, $epsilon) {
  if (count($points) < 2) {
    throw new InvalidArgumentException('Not enough points to simplify');
  }

  // Find the point with the maximum distance from the line between start/end.
  $dmax = 0;
  $index = 0;
  $end = count($points) - 1;
  $start_end_line = [$points[0], $points[$end]];
  for ($i = 1; $i < $end; $i++) {
    $dist = perpendicular_distance($points[$i], $start_end_line);
    if ($dist > $dmax) {
      $index = $i;
      $dmax = $dist;
    }
  }

  // If max distance is larger than epsilon, recursively simplify.
  if ($dmax > $epsilon) {
    $new_start = ramer_douglas_peucker(array_slice($points, 0, $index + 1), $epsilon);
    $new_end = ramer_douglas_peucker(array_slice($points, $index), $epsilon);
    array_pop($new_start);
    return array_merge($new_start, $new_end);
  }

  // Max distance is below epsilon, so return a line from with just the
  // start and end points.
  return [ $points[0], $points[$end]];
}

$polyline = [
  [0,0],
  [1,0.1],
  [2,-0.1],
  [3,5],
  [4,6],
  [5,7],
  [6,8.1],
  [7,9],
  [8,9],
  [9,9],
];

$result = ramer_douglas_peucker($polyline, 1.0);
print "Result:\n";
foreach ($result as $point) {
  print $point[0] . ',' . $point[1] . "\n";
}


without javascript_semantics -- no mpfr_exp() under p2js (yet), sorry
requires("1.0.0") -- (mpfr_set_default_prec[ision] has been renamed)
include mpfr.e
mpfr_set_default_precision(-120) -- (18 before, 100 after, plus 2 for kicks.)

function q(integer d)
    mpfr pi = mpfr_init()
    mpfr_const_pi(pi)
    mpfr t = mpfr_init(d)
    mpfr_sqrt(t,t)
    mpfr_mul(t,pi,t)
    mpfr_exp(t,t)
    return t
end function

printf(1,"Ramanujan's constant to 100 decimal places is:\n")
printf(1,"%s\n", mpfr_get_fixed(q(163),100))
sequence heegners = {{19, 96},
                     {43, 960},
                     {67, 5280},
                     {163, 640320},
                    }
printf(1,"\nHeegner numbers yielding 'almost' integers:\n")
mpfr t = mpfr_init(), qh
mpz c = mpz_init()
for i=1 to length(heegners) do
    integer {h0,h1} = heegners[i]
    qh = q(h0)
    mpz_ui_pow_ui(c,h1,3)
    mpz_add_ui(c,c,744)
    mpfr_set_z(t,c)
    mpfr_sub(t,t,qh)
    string qhs = mpfr_get_fixed(qh,32),
           cs = mpz_get_str(c),
           ts = mpfr_get_fixed(t,32)
    printf(1,"%3d: %51s ~= %18s (diff: %s)\n", {h0, qhs, cs, ts})
end for


from mpmath import mp
heegner = [19,43,67,163]
mp.dps = 50
x = mp.exp(mp.pi*mp.sqrt(163))
print("calculated Ramanujan's constant: {}".format(x))
print("Heegner numbers yielding 'almost' integers:")
for i in heegner:
    print(" for {}: {} ~ {} error: {}".format(str(i),mp.exp(mp.pi*mp.sqrt(i)),round(mp.exp(mp.pi*mp.sqrt(i))),(mp.pi*mp.sqrt(i)) - round(mp.pi*mp.sqrt(i))))


object Range {
   def spanRange(ls:List[Int])={
     var last=ls.head
     ls span {x => val b=x<=last+1; last=x; b}
   }

   def toRangeList(ls:List[Int]):List[List[Int]]=ls match {
      case Nil => List()
      case _ => spanRange(ls) match {
         case (range, Nil) => List(range)
         case (range, rest) => range :: toRangeList(rest)
      }
   }

   def toRangeString(ls:List[List[Int]])=ls map {r=>
      if(r.size<3) r mkString ","
      else r.head + "-" + r.last
   } mkString ","

   def main(args: Array[String]): Unit = {
      var l=List(0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
                 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39)
      println(toRangeString(toRangeList(l)))
   }
}


for i range 1000
  a[] &= 1 + 0.5 * sqrt (-2 * logn randomf) * cos (360 * randomf)
.
print a[]


class
	APPLICATION

inherit
	ARGUMENTS

create
	make

feature {NONE} -- Initialization

	l_time: TIME
	l_seed: INTEGER
	math:DOUBLE_MATH
	rnd:RANDOM
	Size:INTEGER
		once
			Result:= 1000
		end

	make
			-- Run application.
		local
			ergebnis:ARRAY[DOUBLE]
			tavg: DOUBLE
			x: INTEGER
			tmp: DOUBLE
			text : STRING

		do
			-- initialize random generator
			create l_time.make_now
     		        l_seed := l_time.hour
      		        l_seed := l_seed * 60 + l_time.minute
      		        l_seed := l_seed * 60 + l_time.second
      		        l_seed := l_seed * 1000 + l_time.milli_second
      		        create rnd.set_seed (l_seed)

			-- initialize random number container and math
			create ergebnis.make_filled (0.0, 1, size)
			tavg := 0;
			create math

			from
				x := 1
			until
				x > ergebnis.count
			loop
				tmp := randomNormal / 2 + 1
				tavg := tavg + tmp
				ergebnis.enter (tmp , x)
				x := x + 1
			end

			tavg := tavg / ergebnis.count
			text := "Average: "
			text.append_double (tavg)
			text.append ("%N")
			print(text)

			tmp := 0
			from
				x:= 1
			until
				x > ergebnis.count
			loop
				tmp := tmp + (ergebnis.item (x) - tavg)^2
				x := x + 1
			end

			tmp := math.sqrt (tmp / ergebnis.count)
			text := "Standard Deviation: "
			text.append_double (tmp)
			text.append ("%N")
			print(text)

		end

	randomNormal:DOUBLE

		local

      		        first: DOUBLE
      		        second: DOUBLE

		do
                        rnd.forth
                        first := rnd.double_item
                        rnd.forth
                        second := rnd.double_item

                        Result := math.cosine (2 * math.pi * first) * math.sqrt (-2 * math.log (second))

		end
end


from __future__ import print_function
from shapely.geometry import LineString

if __name__=="__main__":
	line = LineString([(0,0),(1,0.1),(2,-0.1),(3,5),(4,6),(5,7),(6,8.1),(7,9),(8,9),(9,9)])
	print (line.simplify(1.0, preserve_topology=False))


#lang racket
(require math/flonum)
;; points are lists of x y (maybe extensible to z)
;; x+y gets both parts as values
(define (x+y p) (values (first p) (second p)))

;; https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
(define (⊥-distance P1 P2)
  (let*-values
      ([(x1 y1) (x+y P1)]
       [(x2 y2) (x+y P2)]
       [(dx dy) (values (- x2 x1) (- y2 y1))]
       [(h) (sqrt (+ (sqr dy) (sqr dx)))])
    (λ (P0)
      (let-values (((x0 y0) (x+y P0)))
        (/ (abs (+ (* dy x0) (* -1 dx y0) (* x2 y1) (* -1 y2 x1))) h)))))

(define (douglas-peucker points-in ϵ)
  (let recur ((ps points-in))
    ;; curried distance function which will be applicable to all points
    (let*-values
        ([(p0) (first ps)]
         [(pz) (last ps)]
         [(p-d) (⊥-distance p0 pz)]
         ;; Find the point with the maximum distance
         [(dmax index)
          (for/fold ((dmax 0) (index 0))
                    ((i (in-range 1 (sub1 (length ps))))) ; skips the first, stops before the last
            (define d (p-d (list-ref ps i)))
            (if (> d dmax) (values d i) (values dmax index)))])
      ;; If max distance is greater than epsilon, recursively simplify
      (if (> dmax ϵ)
          ;; recursive call
          (let-values ([(l r) (split-at ps index)])
            (append (drop-right (recur l) 1) (recur r)))
          (list p0 pz))))) ;; else we can return this simplification

(module+ main
  (douglas-peucker
   '((0 0) (1 0.1) (2 -0.1) (3 5) (4 6) (5 7) (6 8.1) (7 9) (8 9) (9 9))
   1.0))

(module+ test
  (require rackunit)
  (check-= ((⊥-distance '(0 0) '(0 1)) '(1 0)) 1 epsilon.0))


sub norm (*@list) { @list»².sum.sqrt }

sub perpendicular-distance (@start, @end where @end !eqv @start, @point) {
    return 0 if @point eqv any(@start, @end);
    my ( $Δx, $Δy ) =   @end «-» @start;
    my ($Δpx, $Δpy) = @point «-» @start;
    ($Δx, $Δy) «/=» norm $Δx, $Δy;
    norm ($Δpx, $Δpy) «-» ($Δx, $Δy) «*» ($Δx*$Δpx + $Δy*$Δpy);
}

sub Ramer-Douglas-Peucker(@points where * > 1, \ε = 1) {
    return @points if @points == 2;
    my @d = (^@points).map: { perpendicular-distance |@points[0, *-1, $_] };
    my ($index, $dmax) = @d.first: @d.max, :kv;
    return flat
      Ramer-Douglas-Peucker( @points[0..$index], ε )[^(*-1)],
      Ramer-Douglas-Peucker( @points[$index..*], ε )
      if $dmax > ε;
    @points[0, *-1];
}

# TESTING
say Ramer-Douglas-Peucker(
   [(0,0),(1,0.1),(2,-0.1),(3,5),(4,6),(5,7),(6,8.1),(7,9),(8,9),(9,9)]
);


use Rat::Precise;

# set the degree of precision for calculations
constant D = 54;
constant d = 15;

# two versions of exponentiation where base and exponent are both FatRat
multi infix:<**> (FatRat $base, FatRat $exp where * >= 1 --> FatRat) {
    2 R** $base**($exp/2);
}

multi infix:<**> (FatRat $base, FatRat $exp where * <  1 --> FatRat) {
    constant ε = 10**-D;
    my $low  = 0.FatRat;
    my $high = 1.FatRat;
    my $mid  = $high / 2;
    my $acc  = my $sqr = sqrt($base);

    while (abs($mid - $exp) > ε) {
      $sqr = sqrt($sqr);
      if ($mid <= $exp) { $low  = $mid; $acc *=   $sqr }
      else              { $high = $mid; $acc *= 1/$sqr }
      $mid = ($low + $high) / 2;
    }
    $acc.substr(0, D).FatRat;
}

# calculation of π
sub π (--> FatRat) {
    my ($a, $n) = 1, 1;
    my $g = sqrt 1/2.FatRat;
    my $z = .25;
    my $pi;

    for ^d {
        given [ ($a + $g)/2, sqrt $a * $g ] {
            $z -= (.[0] - $a)**2 * $n;
            $n += $n;
            ($a, $g) = @$_;
            $pi = ($a ** 2 / $z).substr: 0, 2 + D;
        }
    }
    $pi.FatRat;
}

multi sqrt(FatRat $r --> FatRat) {
    FatRat.new: sqrt($r.nude[0] * 10**(D*2) div $r.nude[1]), 10**D;
}

# integer roots
multi sqrt(Int $n) {
    my $guess = 10**($n.chars div 2);
    my $iterator = { ( $^x + $n div ($^x) ) div 2 };
    my $endpoint = { $^x == $^y|$^z };
    min ($guess, $iterator … $endpoint)[*-1, *-2];
}

# 'cosmetic' cover to upgrade input to FatRat sqrt
sub prefix:<√> (Int $n) { sqrt($n.FatRat) }

# calculation of 𝑒
sub postfix:<!> (Int $n) { (constant f = 1, |[\*] 1..*)[$n] }
sub 𝑒 (--> FatRat) { sum map { FatRat.new(1,.!) }, ^D }

# inputs, and their difference, formatted decimal-aligned
sub format ($a,$b) {
    sub pad ($s) { ' ' x ((34 - d - 1) - ($s.split(/\./)[0]).chars) }
    my $c = $b.precise(d, :z);
    my $d = ($a-$b).precise(d, :z);
    join "\n",
        (sprintf "%11s {pad($a)}%s\n", 'Int', $a) ~
        (sprintf "%11s {pad($c)}%s\n", 'Heegner', $c) ~
        (sprintf "%11s {pad($d)}%s\n", 'Difference', $d)
}

# override built-in definitions
constant π = &π();
constant 𝑒 = &𝑒();

my $Ramanujan = 𝑒**(π*√163);
say "Ramanujan's constant to 32 decimal places:\nActual:     " ~
    "262537412640768743.99999999999925007259719818568888\n" ~
    "Calculated: ", $Ramanujan.precise(32, :z), "\n";

say "Heegner numbers yielding 'almost' integers";
for 19, 96, 43, 960, 67, 5280, 163, 640320 -> $heegner, $x {
    my $almost = 𝑒**(π*√$heegner);
    my $exact  = $x³ + 744;
    say format($exact, $almost);
}


(define (make-range start end)
  (cond ((= start end)
         `("," ,start))
        ((= end (+ start 1))
         `("," ,start "," ,end))
        (else
         `("," ,start "-" ,end))))

(define (range-extract-0 start end a)
  (cond ((null? a)
         (make-range start end))
        ((= (+ 1 end) (car a))
         (range-extract-0 start (car a) (cdr a)))
        (else
         (append (make-range start end)
                 (range-extract-0 (car a) (car a) (cdr a))))))

(define (range-extract a)
  (apply string-append (map (lambda (x)
                              (if (number? x)
                                  (number->string x)
                                  x))
                            (cdr (range-extract-0 (car a) (car a) (cdr a))))))

(range-extract '( 0  1  2  4  6  7  8 11 12 14
                 15 16 17 18 19 20 21 22 23 24
                 25 27 28 29 30 31 32 33 35 36
                 37 38 39))


import extensions;
import extensions'math;

randomNormal()
{
    ^ cos(2 * Pi_value * randomGenerator.nextReal())
                      * sqrt(-2 * ln(randomGenerator.nextReal()))
}

public program()
{
    real[] a := new real[](1000);

    real tAvg := 0;
    for (int x := 0, x < a.Length, x += 1)
    {
        a[x] := (randomNormal()) / 2 + 1;
        tAvg += a[x]
    };

    tAvg /= a.Length;
    console.printLine("Average: ", tAvg);

    real s := 0;
    for (int x := 0, x < a.Length, x += 1)
    {
        s += power(a[x] - tAvg, 2)
    };

    s := sqrt(s / 1000);

    console.printLine("Standard Deviation: ", s);

    console.readChar()
}


defmodule Random do
  def normal(mean, sd) do
    {a, b} = {:rand.uniform, :rand.uniform}
    mean + sd * (:math.sqrt(-2 * :math.log(a)) * :math.cos(2 * :math.pi * b))
  end
end

std_dev = fn (list) ->
            mean = Enum.sum(list) / length(list)
            sd = Enum.reduce(list, 0, fn x,acc -> acc + (x-mean)*(x-mean) end) / length(list)
                 |> :math.sqrt
            IO.puts "Mean: #{mean},\tStdDev: #{sd}"
          end

xs = for _ <- 1..1000, do: Random.normal(1.0, 0.5)
std_dev.(xs)


mean(Values) ->
    mean(tl(Values), hd(Values), 1).

mean([], Acc, Length) ->
    Acc / Length;
mean(Values, Acc, Length) ->
    mean(tl(Values), hd(Values)+Acc, Length+1).

variance(Values) ->
    Mean = mean(Values),
    variance(Values, Mean, 0) / length(Values).

variance([], _, Acc) ->
    Acc;
variance(Values, Mean, Acc) ->
    Diff = hd(Values) - Mean,
    DiffSqr = Diff * Diff,
    variance(tl(Values), Mean, Acc + DiffSqr).

stddev(Values) ->
    math:sqrt(variance(Values)).

normal(Mean, StdDev) ->
    U = random:uniform(),
    V = random:uniform(),
    Mean + StdDev * ( math:sqrt(-2 * math:log(U)) * math:cos(2 * math:pi() * V) ).  % Erlang's math:log is the natural logarithm.

main(_) ->
    X = [ normal(1.0, 0.5) || _ <- lists:seq(1, 1000) ],
    io:format("mean = ~w\n", [mean(X)]),
    io:format("stddev = ~w\n", [stddev(X)]).


/*REXX program uses the  Ramer─Douglas─Peucker (RDP)  line simplification algorithm  for*/
/*───────────────────────────── reducing the number of points used to define its shape. */
parse arg epsilon pts                            /*obtain optional arguments from the CL*/
if epsilon='' | epsilon=","   then epsilon= 1    /*Not specified?  Then use the default.*/
if pts=''  then pts= '(0,0) (1,0.1) (2,-0.1) (3,5) (4,6) (5,7) (6,8.1) (7,9) (8,9) (9,9)'
pts= space(pts)                                  /*elide all superfluous blanks.        */
            say '  error threshold: '   epsilon  /*echo the error threshold to the term.*/
            say ' points specified: '   pts      /*  "   "    shape points   "  "    "  */
$= RDP(pts)                                      /*invoke Ramer─Douglas─Peucker function*/
            say 'points simplified: '   rez($)   /*display points with () ───► terminal.*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
bld: parse arg _; #= words(_); dMax=-#; idx=1; do j=1  for #; @.j= word(_, j); end; return
px:  parse arg _;          return word( translate(_, , ','),  1)   /*obtain the X coörd.*/
py:  parse arg _;          return word( translate(_, , ','),  2)   /*   "    "  Y   "   */
reb: parse arg a,b,,_;                  do k=a  to b;  _= _ @.k;    end;   return strip(_)
rez: parse arg z,_;   do k=1  for words(z); _= _ '('word(z, k)") "; end;   return strip(_)
/*──────────────────────────────────────────────────────────────────────────────────────*/
RDP: procedure expose epsilon;    call bld  space( translate(arg(1), , ')(][}{') )
     L= px(@.#) - px(@.1)
     H= py(@.#) - py(@.1)                        /* [↓] find point IDX with max distance*/
                         do i=2  to #-1
                         d= abs(H*px(@.i) - L*py(@.i) + px(@.#)*py(@.1) - py(@.#)*px(@.1))
                         if d>dMax  then do;   idx= i;   dMax= d
                                         end
                         end   /*i*/             /* [↑]  D is the perpendicular distance*/

     if dMax>epsilon  then do;   r= RDP( reb(1, idx) )
                                 return subword(r, 1, words(r) - 1)     RDP( reb(idx, #) )
                           end
     return @.1  @.#


/*REXX pgm displays Ramanujan's constant to at least  100  decimal digits of precision. */
d= min( length(pi()), length(e()) )  - length(.) /*calculate max #decimal digs supported*/
parse arg digs sDigs . 1 . . $                   /*obtain optional arguments from the CL*/
if  digs=='' |  digs==","  then  digs= d         /*Not specified?  Then use the default.*/
if sDigs=='' | sDigs==","  then sDigs= d % 2     /* "      "         "   "   "      "   */
if     $=''  |     $=","   then $= 19 43 67 163  /* "      "         "   "   "      "   */
 digs= min( digs, d)                             /*the minimum decimal digs for calc.   */
sDigs= min(sDigs, d)                             /* "     "       "      "      display.*/
numeric digits digs                              /*inform REXX how many dec digs to use.*/
say "The value of Ramanujan's constant calculated with " d ' decimal digits of precision.'
say "shown with "    sDigs    ' decimal digits past the decimal point:'
say
       do  j=1  for words($);   #= word($, j)    /*process each of the Heegner numbers. */
       say 'When using the Heegner number: '  #  /*display which Heegner # is being used*/
       z= exp(pi * sqrt(#) )                     /*perform some heavy lifting here.     */
       say format(z, 25, sDigs);           say   /*display a limited amount of dec digs.*/
       end   /*j*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
pi:    pi= 3.1415926535897932384626433832795028841971693993751058209749445923078164062862,
           || 089986280348253421170679821480865132823066470938446095505822317253594081284,
           || 8111745028410270193852110555964462294895493038196;     return pi
/*──────────────────────────────────────────────────────────────────────────────────────*/
e:     e = 2.7182818284590452353602874713526624977572470936999595749669676277240766303535,
           || 475945713821785251664274274663919320030599218174135966290435729003342952605,
           || 9563073813232862794349076323382988075319525101901;     return  e
/*──────────────────────────────────────────────────────────────────────────────────────*/
exp:   procedure; parse arg x;  ix= x%1;  if abs(x-ix)>.5  then ix= ix + sign(x);  x= x-ix
       z=1;  _=1;   w=z;     do j=1; _= _*x/j;  z=(z+_)/1; if z==w  then leave;  w=z;  end
       if z\==0  then z= z * e() ** ix;                                         return z/1
/*──────────────────────────────────────────────────────────────────────────────────────*/
sqrt:  procedure; parse arg x;  if x=0  then return 0;  d=digits();  h=d+6; numeric digits
       numeric form; m.=9; parse value format(x,2,1,,0) 'E0' with g 'E' _ .;  g=g*.5'e'_%2
         do j=0  while h>9;      m.j=h;               h=h % 2  +  1;   end /*j*/
         do k=j+5  to 0  by -1;  numeric digits m.k;  g=(g+x/g) * .5;  end /*k*/; return g


require "bigdecimal/math"
include BigMath

e, pi = E(200), PI(200)
[19, 43, 67, 163].each do |x|
  puts "#{x}: #{(e ** (pi * BigMath.sqrt(BigDecimal(x), 200))).round(100).to_s("F")}"
end


$ include "seed7_05.s7i";

const func string: rangeExtraction (in array integer: numbers) is func
  result
    var string: rangeStri is "";
  local
    var integer: index is 1;
    var integer: index2 is 1;
  begin
    while index <= length(numbers) do
      while index2 <= pred(length(numbers)) and numbers[succ(index2)] = succ(numbers[index2]) do
        incr(index2);
      end while;
      if succ(index) < index2 then
        rangeStri &:= "," <& numbers[index] <& "-" <& numbers[index2];
      else
        while index <= index2 do
          rangeStri &:= "," <& numbers[index];
          incr(index);
	end while;
      end if;
      incr(index2);
      index := index2;
    end while;
    rangeStri := rangeStri[2 ..];
  end func;

const proc: main is func
  begin
    writeln(rangeExtraction([] (0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19,
        20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39)));
  end func;


PROGRAM DISTRIBUTION

!
! for rosettacode.org
!

! formulas taken from TI-59 Master Library manual

CONST NUM_ITEM=1000

!VAR SUMX#,SUMX2#,R1#,R2#,Z#,I%

DIM A#[1000]

BEGIN
! seeds random number generator with system time
   RANDOMIZE(TIMER)

   PRINT(CHR$(12);)  !CLS
   SUMX#=0  SUMX2#=0

   FOR I%=1 TO NUM_ITEM DO
      R1#=RND(1)  R2#=RND(1)
      Z#=SQR(-2*LOG(R1#))*COS(2*π*R2#)
      A#[I%]=Z#/2+1   ! I want a normal distribution with
                      !      mean=1 and std.dev=0.5
      SUMX#+=A#[I%]  SUMX2#+=A#[I%]*A#[I%]
   END FOR

   Z#=SUMX#/NUM_ITEM

   PRINT("Average is";Z#)
   PRINT("Standard dev. is";SQR(SUMX2#/NUM_ITEM-Z#*Z#))

END PROGRAM


include misc.e

function RandomNormal()
    atom x1, x2
    x1 = rand(999999) / 1000000
    x2 = rand(999999) / 1000000
    return sqrt(-2*log(x1)) * cos(2*PI*x2)
end function

constant n = 1000
sequence s
s = repeat(0,n)
for i = 1 to n do
    s[i] = 1 + 0.5 * RandomNormal()
end for


#[derive(Copy, Clone)]
struct Point {
    x: f64,
    y: f64,
}

use std::fmt;

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

// Returns the distance from point p to the line between p1 and p2
fn perpendicular_distance(p: &Point, p1: &Point, p2: &Point) -> f64 {
    let dx = p2.x - p1.x;
    let dy = p2.y - p1.y;
    (p.x * dy - p.y * dx + p2.x * p1.y - p2.y * p1.x).abs() / dx.hypot(dy)
}

fn rdp(points: &[Point], epsilon: f64, result: &mut Vec<Point>) {
    let n = points.len();
    if n < 2 {
        return;
    }
    let mut max_dist = 0.0;
    let mut index = 0;
    for i in 1..n - 1 {
        let dist = perpendicular_distance(&points[i], &points[0], &points[n - 1]);
        if dist > max_dist {
            max_dist = dist;
            index = i;
        }
    }
    if max_dist > epsilon {
        rdp(&points[0..=index], epsilon, result);
        rdp(&points[index..n], epsilon, result);
    } else {
        result.push(points[n - 1]);
    }
}

fn ramer_douglas_peucker(points: &[Point], epsilon: f64) -> Vec<Point> {
    let mut result = Vec::new();
    if points.len() > 0 && epsilon >= 0.0 {
        result.push(points[0]);
        rdp(points, epsilon, &mut result);
    }
    result
}

fn main() {
    let points = vec![
        Point { x: 0.0, y: 0.0 },
        Point { x: 1.0, y: 0.1 },
        Point { x: 2.0, y: -0.1 },
        Point { x: 3.0, y: 5.0 },
        Point { x: 4.0, y: 6.0 },
        Point { x: 5.0, y: 7.0 },
        Point { x: 6.0, y: 8.1 },
        Point { x: 7.0, y: 9.0 },
        Point { x: 8.0, y: 9.0 },
        Point { x: 9.0, y: 9.0 },
    ];
    for p in ramer_douglas_peucker(&points, 1.0) {
        println!("{}", p);
    }
}


func perpendicular_distance(Arr start, Arr end, Arr point) {
    ((point == start) || (point == end)) && return 0
    var (Δx,  Δy ) = (  end »-« start)...
    var (Δpx, Δpy) = (point »-« start)...
    var h = hypot(Δx, Δy)
    [\Δx, \Δy].map { *_ /= h }
    (([Δpx, Δpy] »-« ([Δx, Δy] »*» (Δx*Δpx + Δy*Δpy))) »**» 2).sum.sqrt
}

func Ramer_Douglas_Peucker(Arr points { .all { .len > 1 } }, ε = 1) {
    points.len == 2 && return points

    var d = (^points -> map {
        perpendicular_distance(points[0], points[-1], points[_])
    })

    if (d.max > ε) {
        var i = d.index(d.max)
        return [Ramer_Douglas_Peucker(points.ft(0, i), ε).ft(0, -2)...,
                Ramer_Douglas_Peucker(points.ft(i),    ε)...]
    }

    return [points[0,-1]]
}

say Ramer_Douglas_Peucker(
    [[0,0],[1,0.1],[2,-0.1],[3,5],[4,6],[5,7],[6,8.1],[7,9],[8,9],[9,9]]
)


struct Point: CustomStringConvertible {
    let x: Double, y: Double

    var description: String {
        return "(\(x), \(y))"
    }
}

// Returns the distance from point p to the line between p1 and p2
func perpendicularDistance(p: Point, p1: Point, p2: Point) -> Double {
    let dx = p2.x - p1.x
    let dy = p2.y - p1.y
    let d = (p.x * dy - p.y * dx + p2.x * p1.y - p2.y * p1.x)
    return abs(d)/(dx * dx + dy * dy).squareRoot()
}

func ramerDouglasPeucker(points: [Point], epsilon: Double) -> [Point] {
    var result : [Point] = []
    func rdp(begin: Int, end: Int) {
        guard end > begin else {
            return
        }
        var maxDist = 0.0
        var index = 0
        for i in begin+1..<end {
            let dist = perpendicularDistance(p: points[i], p1: points[begin],
                                             p2: points[end])
            if dist > maxDist {
                maxDist = dist
                index = i
            }
        }
        if maxDist > epsilon {
            rdp(begin: begin, end: index)
            rdp(begin: index, end: end)
        } else {
            result.append(points[end])
        }
    }
    if points.count > 0 && epsilon >= 0.0 {
        result.append(points[0])
        rdp(begin: 0, end: points.count - 1)
    }
    return result
}

let points = [
    Point(x: 0.0, y: 0.0),
    Point(x: 1.0, y: 0.1),
    Point(x: 2.0, y: -0.1),
    Point(x: 3.0, y: 5.0),
    Point(x: 4.0, y: 6.0),
    Point(x: 5.0, y: 7.0),
    Point(x: 6.0, y: 8.1),
    Point(x: 7.0, y: 9.0),
    Point(x: 8.0, y: 9.0),
    Point(x: 9.0, y: 9.0)
]
print("\(ramerDouglasPeucker(points: points, epsilon: 1.0))")


func ramanujan_const(x, decimals=32) {
    local Num!PREC = *"#{4*round((Num.pi*√x)/log(10) + decimals + 1)}"
    exp(Num.pi * √x) -> round(-decimals).to_s
}

var decimals = 100
printf("Ramanujan's constant to #{decimals} decimals:\n%s\n\n",
     ramanujan_const(163, decimals))

say "Heegner numbers yielding 'almost' integers:"
[19, 96, 43, 960, 67, 5280, 163, 640320].each_slice(2, {|h,x|
    var c = ramanujan_const(h, 32)
    var n = (x**3 + 744)
    printf("%3s: %51s ≈ %18s (diff: %s)\n", h, c, n, n-Num(c))
})


import "/big" for BigRat
import "/fmt" for Fmt

var pi = "3.1415926535897932384626433832795028841971693993751058209749445923078164"
var bigPi = BigRat.fromDecimal(pi)

var exp = Fn.new { |x, p|
    var sum = x + 1
    var prevTerm = x
    var k = 2
    var eps = BigRat.fromDecimal("0.5e-%(p)")
    while (true) {
        var nextTerm = prevTerm * x / k
        sum = sum + nextTerm
        if (nextTerm < eps) break
        // speed up calculations by limiting precision to 'p' places
        prevTerm = BigRat.fromDecimal(nextTerm.toDecimal(p))
        k = k + 1
    }
    return sum
}

var ramanujan = Fn.new { |n, dp|
    var e = bigPi * BigRat.new(n, 1).sqrt(70)
    return exp.call(e, 70)
}

System.print("Ramanujan's constant to 32 decimal places is:")
System.print(ramanujan.call(163, 32).toDecimal(32))
var heegner = [19, 43, 67, 163]
System.print("\nHeegner numbers yielding almost integers:")
for (h in heegner) {
    var r = ramanujan.call(h, 32)
    var rc = r.ceil
    var diff = (rc - r).toDecimal(32)
    r = r.toDecimal(32)
    rc = rc.toDecimal(32)
    Fmt.print("$3d: $51s ≈ $18s (diff: $s)", h, r, rc, diff)
}


import Darwin

func ranges(from ints:[Int]) -> [(Int, Int)] {

	var range : (Int, Int)?
	var ranges = [(Int, Int)]()
	for this in ints {
		if let (start, end) = range {
			if this == end + 1 {
				range = (start, this)
			}
			else {
				ranges.append(range!)
				range = (this, this)
			}
		}
		else { range = (this, this) }
	}
	ranges.append(range!)

	return ranges
}

func description(from ranges:[(Int, Int)]) -> String {
	var desc = ""
	for (start, end) in ranges {
		desc += desc.isEmpty ? "" : ","
		if start == end {
			desc += "\(start)"
		}
		else if end == start + 1 {
			desc += "\(start),\(end)"
		}
		else {
			desc += "\(start)-\(end)"
		}
	}
	return desc
}

let ex = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
let longer = [0,  1,  2,  4,  6,  7,  8, 11, 12, 14,
	15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
	25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
	37, 38, 39]

print(description(from: ranges(from: ex)))
print(description(from: ranges(from: longer)))


let n = MathNet.Numerics.Distributions.Normal(1.0,0.5)
List.init 1000 (fun _->n.Sample())


USING: random ;
1000 [ 1.0 0.5 normal-random-float ] replicate


a = []
for i in [0:1000] : a+= norm_rand_num()

function norm_rand_num()
   pi = 2*acos(0)
   return 1 + (cos(2 * pi * random()) * pow(-2 * log(random()) ,1/2)) /2
end


import "/dynamic" for Tuple

var Point = Tuple.create("Point", ["x", "y"])

var rdp // recursive
rdp = Fn.new { |l, eps|
    var x = 0
    var dMax = -1
    var p1 = l[0]
    var p2 = l[-1]
    var x21 = p2.x - p1.x
    var y21 = p2.y - p1.y
    var i = 0
    for (p in l[1..-1]) {
        var d = (y21*p.x - x21*p.y + p2.x*p1.y - p2.y*p1.x).abs
        if (d > dMax) {
            x = i + 1
            dMax = d
        }
        i = i + 1
    }
    if (dMax > eps) {
        return rdp.call(l[0..x], eps) + rdp.call(l[x..-1], eps)[1..-1]
    }
    return [l[0], l[-1]]
}

var points = [
    Point.new(0, 0), Point.new(1, 0.1), Point.new(2, -0.1), Point.new(3, 5), Point.new(4, 6),
    Point.new(5, 7), Point.new(6, 8.1), Point.new(7, 9), Point.new(8, 9), Point.new(9, 9)
]
System.print(rdp.call(points, 1))


sub perpendicularDistance(tabla(), i, ini, fin)
    local dx, cy, mag, pvx, pvy, pvdot, dsx, dsy, ax, ay

    dx = tabla(fin, 1) - tabla(ini, 1)
    dy = tabla(fin, 2) - tabla(ini, 2)

    //Normalise
    mag = (dx^2 + dy^2)^0.5
    if mag > 0 dx = dx / mag : dy = dy / mag

    pvx = tabla(i, 1) - tabla(ini, 1)
    pvy = tabla(i, 2) - tabla(ini, 2)

    //Get dot product (project pv onto normalized direction)
    pvdot = dx * pvx + dy * pvy

    //Scale line direction vector
    dsx = pvdot * dx
    dsy = pvdot * dy

    //Subtract this from pv
    ax = pvx - dsx
    ay = pvy - dsy

    return (ax^2 + ay^2)^0.5
end sub

sub DouglasPeucker(PointList(), ini, fin, epsilon)
    local dmax, index, i, d
    // Find the point with the maximum distance

    for i = ini + 1 to fin
        d = perpendicularDistance(PointList(), i, ini, fin)
        if d > dmax index = i : dmax = d
    next

    // If max distance is greater than epsilon, recursively simplify
    if dmax > epsilon then
        PointList(index, 3) = true
        // Recursive call
        DouglasPeucker(PointList(), ini, index, epsilon)
        DouglasPeucker(PointList(), index, fin, epsilon)
    end if
end sub

data 0,0, 1,0.1,  2,-0.1,  3,5,  4,6,  5,7,  6,8.1,  7,9,  8,9,  9,9

dim matriz(10, 3)

for i = 1 to 10
    read matriz(i, 1), matriz(i, 2)
next

DouglasPeucker(matriz(), 1, 10, 1)

matriz(1, 3) = true : matriz(10, 3) = true
for i = 1 to 10
    if matriz(i, 3) print matriz(i, 1), matriz(i, 2)
next


proc rangeExtract list {
    set result [lindex $list 0]
    set first [set last [lindex $list 0]]
    foreach term [lrange $list 1 end] {
	if {$term == $last+1} {
	    set last $term
	    continue
	}
	if {$last > $first} {
	    append result [expr {$last == $first+1 ? "," : "-"}] $last
	}
	append result "," $term
	set first [set last $term]
    }
    if {$last == $first+1} {
	append result "," $last
    } elseif {$last > $first} {
	append result "-" $last
    }
    return $result
}

# Commas already removed so it is a natural Tcl list
puts [rangeExtract {
    0 1 2 4 6 7 8 11 12 14
    15 16 17 18 19 20 21 22 23 24
    25 27 28 29 30 31 32 33 35 36
    37 38 39
}]


class Main
{
  static const Float PI := 0.0f.acos * 2  // we need to precompute PI

  static Float randomNormal ()
  {
    return (Float.random * PI * 2).cos * (Float.random.log * -2).sqrt
  }

  public static Void main ()
  {
    mean := 1.0f
    sd := 0.5f
    Float[] values := [,] // this is the collection to fill with random numbers
    1000.times { values.add (randomNormal * sd + mean) }
  }
}


require random.fs
here to seed

-1. 1 rshift 2constant MAX-D	\ or s" MAX-D" ENVIRONMENT? drop

: frnd ( -- f )			\ uniform distribution 0..1
  rnd rnd dabs d>f MAX-D d>f f/ ;

: frnd-normal ( -- f )		\ centered on 0, std dev 1
  frnd pi f* 2e f* fcos
  frnd fln -2e f* fsqrt f* ;

: ,normals ( n -- )		\ store many, centered on 1, std dev 0.5
  0 do frnd-normal 0.5e f* 1e f+ f, loop ;

create rnd-array 1000 ,normals


PROGRAM Random

  INTEGER, PARAMETER :: n = 1000
  INTEGER :: i
  REAL :: array(n), pi, temp, mean = 1.0, sd = 0.5

  pi = 4.0*ATAN(1.0)
  CALL RANDOM_NUMBER(array) ! Uniform distribution

! Now convert to normal distribution
  DO i = 1, n-1, 2
    temp = sd * SQRT(-2.0*LOG(array(i))) * COS(2*pi*array(i+1)) + mean
    array(i+1) = sd * SQRT(-2.0*LOG(array(i))) * SIN(2*pi*array(i+1)) + mean
    array(i) = temp
  END DO

! Check mean and standard deviation
  mean = SUM(array)/n
  sd = SQRT(SUM((array - mean)**2)/n)

  WRITE(*, "(A,F8.6)") "Mean = ", mean
  WRITE(*, "(A,F8.6)") "Standard Deviation = ", sd

END PROGRAM Random


fcn perpendicularDistance(start,end, point){  // all are tuples: (x,y) -->|d|
   dx,dy   := end  .zipWith('-,start);	// deltas
   dpx,dpy := point.zipWith('-,start);
   mag     := (dx*dx + dy*dy).sqrt();
   if(mag>0.0){ dx/=mag; dy/=mag; }
   p,dsx,dsy := dx*dpx + dy*dpy, p*dx, p*dy;
   ((dpx - dsx).pow(2) + (dpy - dsy).pow(2)).sqrt()
}

fcn RamerDouglasPeucker(points,epsilon=1.0){  // list of tuples --> same
   if(points.len()==2) return(points);  // but we'll do one point
   d:=points.pump(List,  // first result/element is always zero
      fcn(p, s,e){ perpendicularDistance(s,e,p) }.fp1(points[0],points[-1]));
   index,dmax := (0.0).minMaxNs(d)[1], d[index]; // minMaxNs-->index of min & max
   if(dmax>epsilon){
       return(RamerDouglasPeucker(points[0,index],epsilon)[0,-1].extend(
              RamerDouglasPeucker(points[index,*],epsilon)))
   } else return(points[0],points[-1]);
}


$$ MODE TUSCRIPT,{}
MODE DATA
$$ numbers=*
0,  1,  2,  4,  6,  7,  8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39
$$ MODE TUSCRIPT
numbers=EXCHANGE   (numbers,":,{0-00} :':")
unrangednrs=JOIN   (numbers,"")
rangednrs=COMBINE  (unrangednrs,"")
rangednrs=EXCHANGE (rangednrs,":':,:")
PRINT rangednrs


(defun range-extract (numbers)
  `@{(mapcar [iff [callf > length (ret 2)]
                  (ret `@[@1 0][email protected][@1 -1]`)
                  (ret `@{@1 ","}`)]
             (mapcar (op mapcar car)
                     (split [window-map 1 :reflect
                                        (op list @2 (- @2 @1))
                                        (sort (uniq numbers))]
                            (op where [chain second (op < 1)])))) ","}`)


function randg(mean,stddev: float): float;