1000 PUBLIC NUMERIC x,y
1010 LET x=1
1020 LET y=2
1030 !
1040 DEF isLeft2(L(,),p()) = -SGN(  (L(1,x)-L(2,x))*(p(y)-L(2,y)) - (p(x)-L(2,x))*(L(1,y)-L(2,y)))
1050 !
1060 FUNCTION inpolygon(p1(,),p2())
1070    LET k=UBOUND(p1,1)+1
1080    DIM send (1 TO 2,2)
1090    LET wn=0
1100    FOR n=1 TO UBOUND(p1,1)
1110       LET index=MOD(n, k)
1120       LET nextindex=MOD(n+1, k)
1130       IF nextindex=0 THEN LET nextindex=1
1140       LET send(1,x)=p1(index,x)
1150       LET send(2,x)=p1(nextindex,x)
1160       LET send(1,y)=p1(index,y)
1170       LET send(2,y)=p1(nextindex,y)
1180       IF p1(index,y)<=p2(y) THEN
1190          IF p1(nextindex,y)>p2(y) THEN
1200             IF isleft2(send,p2)>=0 THEN !'=
1210                LET wn=wn+1
1220             END IF
1230          END IF
1240       ELSE
1250          IF p1(nextindex,y)<=p2(y) THEN
1260             IF isleft2(send,p2)<=0 THEN !'=
1270                LET wn=wn-1
1280             END IF
1290          END IF
1300       END IF
1310    NEXT n
1320    LET inpolygon = wn
1330 END FUNCTION
1340 !
1350 DIM type(1 TO 2)
1360 !
1370 DIM square(4,2)
1380 MAT READ square
1390 DATA 0,0,10,0,10,10,0,10
1400 !
1410 DIM hole(4,2)
1420 MAT READ hole
1430 DATA 2.5,2.5,7.5,2.5,7.5,7.5,2.5,7.5
1440 !
1450 DIM strange(8,2)
1460 MAT READ strange
1470 DATA 0,0,2.5,2.5,0,10,2.5,7.5,7.5,7.5,10,10,10,0,2.5,2.5
1480 !
1490 DIM exagon(6,2)
1500 MAT READ exagon
1510 DATA 3,0,7,0,10,5,7,10,3,10,0,5
1520 !
1530 ! printouts
1540 FOR z=1 TO 4
1550    SELECT CASE z
1560    CASE 1
1570       PRINT "squared"
1580       PRINT "(5,5)  ";TAB(12);
1590       MAT READ type
1600       DATA 5,5
1610       IF inpolygon(square,type) <> 0 THEN PRINT "in" ELSE PRINT "out"
1620       MAT READ type
1630       DATA 5,8
1640       PRINT "(5,8)  ";TAB(12);
1650       IF inpolygon(square,type) <> 0 THEN PRINT "in" ELSE PRINT "out"
1660       PRINT "(-10,5)  ";TAB(12);
1670       MAT READ type
1680       DATA -10,5
1690       IF inpolygon(square,type) <> 0 THEN PRINT "in" ELSE PRINT "out"
1700       Print "(0,5)  ";Tab(12);
1710       MAT READ type
1720       DATA 0,5
1730       IF inpolygon(square,type) <> 0 THEN PRINT "in" ELSE PRINT "out"
1740       Print "(10,5)  ";Tab(12);
1750       MAT READ type
1760       DATA 10,5
1770       IF inpolygon(square,type) <> 0 THEN PRINT "in" ELSE PRINT "out"
1780       PRINT "(8,5)  ";TAB(12);
1790       MAT READ type
1800       DATA 8,5
1810       IF inpolygon(square,Type) <> 0 THEN PRINT "in" ELSE PRINT "out"
1820       PRINT "(10,10)  ";TAB(12);
1830       MAT READ type
1840       DATA 10,10
1850       IF inpolygon(square,Type) <> 0 THEN PRINT "in" ELSE PRINT "out"
1860       PRINT
1870    CASE 2
1880       PRINT "squared hole"
1890       PRINT "(5,5)  ";TAB(12);
1900       MAT READ type
1910       DATA 5,5
1920       IF NOT inpolygon(hole,Type)<>0 AND inpolygon(square,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
1930       Print "(5,8)  ";Tab(12);
1940       MAT READ type
1950       DATA 5,8
1960       IF NOT inpolygon(hole,Type)<>0 AND inpolygon(square,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
1970       PRINT "(-10,5)  ";TAB(12);
1980       MAT READ type
1990       DATA -10,5
2000       IF NOT inpolygon(hole,Type)<>0 AND inpolygon(square,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2010       PRINT "(0,5)  ";TAB(12);
2020       MAT READ type
2030       DATA 0,5
2040       IF NOT inpolygon(hole,Type)<>0 AND inpolygon(square,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2050       PRINT "(10,5)  ";TAB(12);
2060       MAT READ type
2070       DATA 10,5
2080       IF NOT inpolygon(hole,Type)<>0 AND inpolygon(square,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2090       PRINT "(8,5)  ";TAB(12);
2100       MAT READ type
2110       DATA 8,5
2120       IF NOT inpolygon(hole,Type)<>0 AND inpolygon(square,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2130       PRINT "(10,10)  ";TAB(12);
2140       MAT READ type
2150       DATA 10,10
2160       IF NOT inpolygon(hole,Type)<>0 AND inpolygon(square,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2170       PRINT
2180    CASE 3
2190       PRINT "strange"
2200       PRINT "(5,5)  ";TAB(12);
2210       MAT READ type
2220       DATA 5,5
2230       IF inpolygon(strange,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2240       PRINT "(5,8)  ";TAB(12);
2250       MAT READ type
2260       DATA 5,8
2270       IF inpolygon(strange,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2280       PRINT "(-10,5)  ";TAB(12);
2290       MAT READ type
2300       DATA -10,5
2310       IF inpolygon(strange,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2320       PRINT "(0,5)  ";TAB(12);
2330       MAT READ type
2340       DATA 0,5
2350       IF inpolygon(strange,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2360       PRINT "(10,5)  ";TAB(12);
2370       MAT READ type
2380       DATA 10,5
2390       IF inpolygon(strange,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2400       PRINT "(8,5)  ";TAB(12);
2410       MAT READ type
2420       DATA 8,5
2430       IF inpolygon(strange,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2440       PRINT "(10,10)  ";TAB(12);
2450       MAT READ type
2460       DATA 10,10
2470       IF inpolygon(strange,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2480       PRINT
2490    CASE 4
2500       PRINT "exagon"
2510       PRINT "(5,5)  ";TAB(12);
2520       MAT READ type
2530       DATA 5,5
2540       IF inpolygon(exagon,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2550       PRINT "(5,8)  ";TAB(12);
2560       MAT READ type
2570       DATA 5,8
2580       IF inpolygon(exagon,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2590       PRINT "(-10,5)  ";TAB(12);
2600       MAT READ type
2610       DATA -10,5
2620       IF inpolygon(exagon,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2630       PRINT "(0,5)  ";TAB(12);
2640       MAT READ type
2650       DATA 0,5
2660       IF inpolygon(exagon,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2670       PRINT "(10,5)  ";TAB(12);
2680       MAT READ type
2690       DATA 10,5
2700       IF inpolygon(exagon,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2710       PRINT "(8,5)  ";TAB(12);
2720       MAT READ type
2730       DATA 8,5
2740       IF inpolygon(exagon,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2750       PRINT "(10,10)  ";TAB(12);
2760       MAT READ type
2770       DATA 10,10
2780       IF inpolygon(exagon,Type)<>0 THEN PRINT "in" ELSE PRINT "out"
2790       PRINT
2800    END SELECT
2810 NEXT z
2820 END


USING: formatting io kernel math math.parser sequences
splitting.monotonic ;
IN: rosetta-code.range-extraction

: make-range ( seq -- str )
    [ first ] [ last ] bi "%d-%d" sprintf ;

: make-atomic ( seq -- str ) [ number>string ] map "," join ;

: extract-range ( seq -- str )
    [ - -1 = ] monotonic-split
    [ dup length 2 > [ make-range ] [ make-atomic ] if ] map
    "," join ;

{
    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
} extract-range print


create values
here
    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 ,
here swap - 1 cells / constant /values

: clip 1- swap cell+ swap ;            \ reduce array
: .range2 0 .r ." -" 0 .r ;            \ difference two or more
: .range1 0 .r ." , " 0 .r ;           \ difference one
: .range0 drop 0 .r ;                  \ no difference
                                       \ select printing routine
create .range ' .range0 , ' .range1 , ' .range2 ,
  does> >r over over - 2 min cells r> + @ execute ;

: .ranges                              ( a n --)
  over @ dup >r >r                     \ setup first value
  begin
    clip dup                           \ check length array
  while
    over @ dup [email protected] 1+ =                 \ check if range breaks
    if r> drop >r else r> r> .range ." , " dup >r >r then
  repeat 2drop r> r> .range cr         \ print last range
;

values /values .ranges


      SUBROUTINE IRANGE(TEXT)	!Identifies integer ranges in a list of integers.
Could make this a function, but then a maximum text length returned would have to be specified.
       CHARACTER*(*) TEXT	!The list on input, the list with ranges on output.
       INTEGER LOTS		!Once again, how long is a piece of string?
       PARAMETER (LOTS = 666)	!This should do, at least for demonstrations.
       INTEGER VAL(LOTS)	!The integers of the list.
       INTEGER N		!Count of numbers.
       INTEGER I,I1		!Steppers.
        N = 1		!Presume there to be one number.
        DO I = 1,LEN(TEXT)	!Then by noticing commas,
          IF (TEXT(I:I).EQ.",") N = N + 1	!Determine how many more there are.
        END DO			!Step alonmg the text.
        IF (N.LE.2) RETURN	!One comma = two values. Boring.
        IF (N.GT.LOTS) STOP "Too many values!"
        READ (TEXT,*) VAL(1:N)	!Get the numbers, with free-format flexibility.
        TEXT = ""		!Scrub the parameter!
        L = 0			!No text has been placed.
        I1 = 1			!Start the scan.
   10   IF (L.GT.0) CALL EMIT(",")	!A comma if there is prior text.
        CALL SPLOT(VAL(I1))		!The first number always appears.
        DO I = I1 + 1,N			!Now probe ahead
          IF (VAL(I - 1) + 1 .NE. VAL(I)) EXIT	!While values are consecutive.
        END DO				!Up to the end of the remaining list.
        IF (I - I1 .GT. 2) THEN		!More than two consecutive values seen?
          CALL EMIT("-")		!Yes!
          CALL SPLOT(VAL(I - 1))	!The ending number of a range.
          I1 = I			!Finger the first beyond the run.
         ELSE			!But if too few to be worth a span,
          I1 = I1 + 1			!Just finger the next number.
        END IF			!So much for that starter.
        IF (I.LE.N) GO TO 10	!Any more?
       CONTAINS		!Some assistants to save on repetition.
        SUBROUTINE EMIT(C)	!Rolls forth one character.
         CHARACTER*1 C		!The character.
          L = L + 1		!Advance the finger.
          IF (L.GT.LEN(TEXT)) STOP "Ran out of text!"	!Maybe not.
          TEXT(L:L) = C		!And place the character.
        END SUBROUTINE EMIT	!That was simple.
        SUBROUTINE SPLOT(N)	!Rolls forth a signed number.
         INTEGER N		!The number.
         CHARACTER*12 FIELD	!Sufficient for 32-bit integers.
         INTEGER I		!A stepper.
          WRITE (FIELD,"(I0)") N!Roll the number, with trailing spaces.
          DO I = 1,12		!Now transfer the text of the number.
            IF (FIELD(I:I).LE." ") EXIT	!Up to the first space.
            CALL EMIT(FIELD(I:I))	!One by one.
          END DO		!On to the end.
        END SUBROUTINE SPLOT	!Not so difficult either.
      END	!So much for IRANGE.

      PROGRAM POKE
      CHARACTER*(200) SOME
      SOME = "  0,  1,  2,  4,  6,  7,  8, 11, 12, 14,  "
     1      //"  15, 16, 17, 18, 19, 20, 21, 22, 23, 24,"
     2      //"25, 27, 28, 29, 30, 31, 32, 33, 35, 36,  "
     3      //"37, 38, 39                               "
      CALL IRANGE(SOME)
      WRITE (6,*) SOME
      END


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

typedef struct { double x, y; } vec;
typedef struct { int n; vec* v; } polygon_t, *polygon;

#define BIN_V(op, xx, yy) vec v##op(vec a,vec b){vec c;c.x=xx;c.y=yy;return c;}
#define BIN_S(op, r) double v##op(vec a, vec b){ return r; }
BIN_V(sub, a.x - b.x, a.y - b.y);
BIN_V(add, a.x + b.x, a.y + b.y);
BIN_S(dot, a.x * b.x + a.y * b.y);
BIN_S(cross, a.x * b.y - a.y * b.x);

/* return a + s * b */
vec vmadd(vec a, double s, vec b)
{
	vec c;
	c.x = a.x + s * b.x;
	c.y = a.y + s * b.y;
	return c;
}

/* check if x0->x1 edge crosses y0->y1 edge. dx = x1 - x0, dy = y1 - y0, then
   solve  x0 + a * dx == y0 + b * dy with a, b in real
   cross both sides with dx, then: (remember, cross product is a scalar)
	x0 X dx = y0 X dx + b * (dy X dx)
   similarly,
	x0 X dy + a * (dx X dy) == y0 X dy
   there is an intersection iff 0 <= a <= 1 and 0 <= b <= 1

   returns: 1 for intersect, -1 for not, 0 for hard to say (if the intersect
   point is too close to y0 or y1)
*/
int intersect(vec x0, vec x1, vec y0, vec y1, double tol, vec *sect)
{
	vec dx = vsub(x1, x0), dy = vsub(y1, y0);
	double d = vcross(dy, dx), a;
	if (!d) return 0; /* edges are parallel */

	a = (vcross(x0, dx) - vcross(y0, dx)) / d;
	if (sect)
		*sect = vmadd(y0, a, dy);

	if (a < -tol || a > 1 + tol) return -1;
	if (a < tol || a > 1 - tol) return 0;

	a = (vcross(x0, dy) - vcross(y0, dy)) / d;
	if (a < 0 || a > 1) return -1;

	return 1;
}

/* distance between x and nearest point on y0->y1 segment.  if the point
   lies outside the segment, returns infinity */
double dist(vec x, vec y0, vec y1, double tol)
{
	vec dy = vsub(y1, y0);
	vec x1, s;
	int r;

	x1.x = x.x + dy.y; x1.y = x.y - dy.x;
	r = intersect(x, x1, y0, y1, tol, &s);
	if (r == -1) return HUGE_VAL;
	s = vsub(s, x);
	return sqrt(vdot(s, s));
}

#define for_v(i, z, p) for(i = 0, z = p->v; i < p->n; i++, z++)
/* returns 1 for inside, -1 for outside, 0 for on edge */
int inside(vec v, polygon p, double tol)
{
	/* should assert p->n > 1 */
	int i, k, crosses, intersectResult;
	vec *pv;
	double min_x, max_x, min_y, max_y;

	for (i = 0; i < p->n; i++) {
		k = (i + 1) % p->n;
		min_x = dist(v, p->v[i], p->v[k], tol);
		if (min_x < tol) return 0;
	}

	min_x = max_x = p->v[0].x;
	min_y = max_y = p->v[1].y;

	/* calculate extent of polygon */
	for_v(i, pv, p) {
		if (pv->x > max_x) max_x = pv->x;
		if (pv->x < min_x) min_x = pv->x;
		if (pv->y > max_y) max_y = pv->y;
		if (pv->y < min_y) min_y = pv->y;
	}
	if (v.x < min_x || v.x > max_x || v.y < min_y || v.y > max_y)
		return -1;

	max_x -= min_x; max_x *= 2;
	max_y -= min_y; max_y *= 2;
	max_x += max_y;

	vec e;
	while (1) {
		crosses = 0;
		/* pick a rand point far enough to be outside polygon */
		e.x = v.x + (1 + rand() / (RAND_MAX + 1.)) * max_x;
		e.y = v.y + (1 + rand() / (RAND_MAX + 1.)) * max_x;

		for (i = 0; i < p->n; i++) {
			k = (i + 1) % p->n;
			intersectResult = intersect(v, e, p->v[i], p->v[k], tol, 0);

			/* picked a bad point, ray got too close to vertex.
			   re-pick */
			if (!intersectResult) break;

			if (intersectResult == 1) crosses++;
		}
		if (i == p->n) break;
	}
	return (crosses & 1) ? 1 : -1;
}

int main()
{
	vec vsq[] = {	{0,0}, {10,0}, {10,10}, {0,10},
			{2.5,2.5}, {7.5,0.1}, {7.5,7.5}, {2.5,7.5}};

	polygon_t sq = { 4, vsq }, /* outer square */
		sq_hole = { 8, vsq }; /* outer and inner square, ie hole */

	vec c = { 10, 5 }; /* on edge */
	vec d = { 5, 5 };

	printf("%d\n", inside(c, &sq, 1e-10));
	printf("%d\n", inside(c, &sq_hole, 1e-10));

	printf("%d\n", inside(d, &sq, 1e-10));	/* in */
	printf("%d\n", inside(d, &sq_hole, 1e-10));  /* out (in the hole) */

	return 0;
}


' FB 1.05.0 Win64

Function formatRange (a() As Integer) As String
  Dim lb As Integer = LBound(a)
  Dim ub As Integer = UBound(a)
  If ub = - 1 Then Return ""
  If lb = ub Then Return Str(a(lb))
  Dim rangeCount As Integer = 1
  Dim range As String = Str(a(lb))
  For i As Integer = lb + 1 To ub
    If a(i) = a(i - 1) + 1 Then
      rangeCount += 1
    ElseIf rangeCount = 1 Then
      range += "," + Str(a(i))
    ElseIf rangeCount = 2 Then
      rangeCount = 1
      range += "," + Str(a(i-1)) + "," + Str(a(i))
    Else
      rangeCount = 1
      range += "-" + Str(a(i-1)) + "," + Str(a(i))
    End If
  Next
  If rangeCount = 2 Then
    range += "," + Str(a(ub))
  ElseIf rangeCount > 2 Then
    range += "-" + Str(a(ub))
  End If
  Return range
End Function

Dim a(1 To 20) As Integer = {-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20}
Print formatRange(a())
Print

Dim b(1 To 33) As Integer => _
{ _
   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 formatRange(b())
Print
Print "Press any key to continue"
Sleep


#include <algorithm>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <limits>

using namespace std;

const double epsilon = numeric_limits<float>().epsilon();
const numeric_limits<double> DOUBLE;
const double MIN = DOUBLE.min();
const double MAX = DOUBLE.max();

struct Point { const double x, y; };

struct Edge {
    const Point a, b;

    bool operator()(const Point& p) const
    {
        if (a.y > b.y) return Edge{ b, a }(p);
        if (p.y == a.y || p.y == b.y) return operator()({ p.x, p.y + epsilon });
        if (p.y > b.y || p.y < a.y || p.x > max(a.x, b.x)) return false;
        if (p.x < min(a.x, b.x)) return true;
        auto blue = abs(a.x - p.x) > MIN ? (p.y - a.y) / (p.x - a.x) : MAX;
        auto red = abs(a.x - b.x) > MIN ? (b.y - a.y) / (b.x - a.x) : MAX;
        return blue >= red;
    }
};

struct Figure {
    const string  name;
    const initializer_list<Edge> edges;

    bool contains(const Point& p) const
    {
        auto c = 0;
        for (auto e : edges) if (e(p)) c++;
        return c % 2 != 0;
    }

    template<unsigned char W = 3>
    void check(const initializer_list<Point>& points, ostream& os) const
    {
        os << "Is point inside figure " << name <<  '?' << endl;
        for (auto p : points)
            os << "  (" << setw(W) << p.x << ',' << setw(W) << p.y << "): " << boolalpha << contains(p) << endl;
        os << endl;
    }
};

int main()
{
    const initializer_list<Point> points =  { { 5.0, 5.0}, {5.0, 8.0}, {-10.0, 5.0}, {0.0, 5.0}, {10.0, 5.0}, {8.0, 5.0}, {10.0, 10.0} };
    const Figure square = { "Square",
        {  {{0.0, 0.0}, {10.0, 0.0}}, {{10.0, 0.0}, {10.0, 10.0}}, {{10.0, 10.0}, {0.0, 10.0}}, {{0.0, 10.0}, {0.0, 0.0}} }
    };

    const Figure square_hole = { "Square hole",
        {  {{0.0, 0.0}, {10.0, 0.0}}, {{10.0, 0.0}, {10.0, 10.0}}, {{10.0, 10.0}, {0.0, 10.0}}, {{0.0, 10.0}, {0.0, 0.0}},
           {{2.5, 2.5}, {7.5, 2.5}}, {{7.5, 2.5}, {7.5, 7.5}}, {{7.5, 7.5}, {2.5, 7.5}}, {{2.5, 7.5}, {2.5, 2.5}}
        }
    };

    const Figure strange = { "Strange",
        {  {{0.0, 0.0}, {2.5, 2.5}}, {{2.5, 2.5}, {0.0, 10.0}}, {{0.0, 10.0}, {2.5, 7.5}}, {{2.5, 7.5}, {7.5, 7.5}},
           {{7.5, 7.5}, {10.0, 10.0}}, {{10.0, 10.0}, {10.0, 0.0}}, {{10.0, 0}, {2.5, 2.5}}
        }
    };

    const Figure exagon = { "Exagon",
        {  {{3.0, 0.0}, {7.0, 0.0}}, {{7.0, 0.0}, {10.0, 5.0}}, {{10.0, 5.0}, {7.0, 10.0}}, {{7.0, 10.0}, {3.0, 10.0}},
           {{3.0, 10.0}, {0.0, 5.0}}, {{0.0, 5.0}, {3.0, 0.0}}
        }
    };

    for(auto f : {square, square_hole, strange, exagon})
        f.check(points, cout);

    return EXIT_SUCCESS;
}


siInput As New Short[]
siInput1 As Short[] = [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]
siInput2 As Short[] = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
sOutput As New String[]
siCount As Short
siNum As Short
'__________________
Public Sub Main()
Dim siLoop As Short

For siLoop = 0 To 1
  If siLoop = 0 Then siInput = siInput1.Copy() Else siInput = siInput2.Copy()
  siCount = 0
  siNum = 0
    Repeat
      If siInput[siCount + 1] = siInput[siCount] + 1 Then
        Inc siCount
      Else
        GetOutput
      Endif
    Until siCount = siInput.Max

  GetOutput
  Print sOutput.join(", ")
  sOutput.clear
Next

End
'__________________
Public Sub GetOutput()

If siNum = siCount Then
  sOutput.add(siInput[siNum])
  Inc siCount
  siNum = siCount
End If

If siNum <> siCount Then
  If siNum = siCount - 1 Then
    sOutput.add(siInput[siNum])
    sOutput.add(siInput[siNum + 1])
    siCount += 2
    siNum += 2
    Return
  End If
  sOutput.Add(siInput[siNum] & "-" & siInput[siCount])
  Inc siCount
  siNum = siCount
End If

End


  Point = (@x,@y) ->

  pointInPoly = (point,poly) ->
    segments = for pointA, index in poly
                 pointB = poly[(index + 1) % poly.length]
                 [pointA,pointB]
    intesected = (segment for segment in segments when rayIntesectsSegment(point,segment))
    intesected.length % 2 != 0

  rayIntesectsSegment = (p,segment) ->
    [p1,p2] = segment
    [a,b] = if p1.y < p2.y
              [p1,p2]
            else
              [p2,p1]
    if p.y == b.y || p.y == a.y
      p.y += Number.MIN_VALUE

    if p.y > b.y || p.y < a.y
      false
    else if p.x > a.x && p.x > b.x
      false
    else if p.x < a.x && p.x < b.x
      true
    else
      mAB = (b.y - a.y) / (b.x - a.x)
      mAP = (p.y - a.y) / (p.x - a.x)
      mAP > mAB


package main

import (
    "errors"
    "fmt"
    "strconv"
    "strings"
)

func main() {
    rf, err := rangeFormat([]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,
    })
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println("range format:", rf)
}

func rangeFormat(a []int) (string, error) {
    if len(a) == 0 {
        return "", nil
    }
    var parts []string
    for n1 := 0; ; {
        n2 := n1 + 1
        for n2 < len(a) && a[n2] == a[n2-1]+1 {
            n2++
        }
        s := strconv.Itoa(a[n1])
        if n2 == n1+2 {
            s += "," + strconv.Itoa(a[n2-1])
        } else if n2 > n1+2 {
            s += "-" + strconv.Itoa(a[n2-1])
        }
        parts = append(parts, s)
        if n2 == len(a) {
            break
        }
        if a[n2] == a[n2-1] {
            return "", errors.New(fmt.Sprintf(
                "sequence repeats value %d", a[n2]))
        }
        if a[n2] < a[n2-1] {
            return "", errors.New(fmt.Sprintf(
                "sequence not ordered: %d < %d", a[n2], a[n2-1]))
        }
        n1 = n2
    }
    return strings.Join(parts, ","), nil
}


(defun point-in-polygon (point polygon)
  (do ((in-p nil)) ((endp polygon) in-p)
    (when (ray-intersects-segment point (pop polygon))
      (setf in-p (not in-p)))))

(defun ray-intersects-segment (point segment &optional (epsilon .001))
  (destructuring-bind (px . py) point
    (destructuring-bind ((ax . ay) . (bx . by)) segment
      (when (< ay by)
        (rotatef ay by)
        (rotatef ax bx))
      (when (or (= py ay) (= py by))
        (incf py epsilon))
      (cond
       ;; point is above, below, or to the right of the rectangle
       ;; determined by segment; ray does not intesect the segment.
       ((or (> px (max ax bx)) (> py (max ay by)) (< py (min ay by)))
        nil)
       ;; point is to left of the rectangle; ray intersects segment
       ((< px (min ax bx))
        t)
       ;; point is within the rectangle...
       (t (let ((m-red (if (= ax bx) nil
                         (/ (- by ay) (- bx ax))))
                (m-blue (if (= px ax) nil
                          (/ (- py ay) (- px ax)))))
            (cond
             ((null m-blue) t)
             ((null m-red) nil)
             (t (>= m-blue m-red)))))))))


def range = { s, e -> s == e ? "${s}," : s == e - 1 ? "${s},${e}," : "${s}-${e}," }

def compressList = { list ->
    def sb, start, end
    (sb, start, end) = [''<<'', list[0], list[0]]
    for (i in list[1..-1]) {
        (sb, start, end) = i == end + 1 ? [sb, start, i] : [sb << range(start, end), i, i]
    }
    (sb << range(start, end))[0..-2].toString()
}

def compressRanges = { expanded -> compressList(Eval.me('[' + expanded + ']')) }


import Data.List (intercalate)

extractRange :: [Int] -> String
extractRange = intercalate "," . f
  where f :: [Int] -> [String]
        f (x1 : x2 : x3 : xs) | x1 + 1 == x2 && x2 + 1 == x3
             = (show x1 ++ '-' : show xn) : f xs'
          where (xn, xs') = g (x3 + 1) xs
                g a (n : ns) | a == n    = g (a + 1) ns
                             | otherwise = (a - 1, n : ns)
                g a []                   = (a - 1, [])
        f (x : xs)            = show x : f xs
        f []                  = []


procedure main()

   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 ]

   write("Input list      := ",list2string(R))
   write("Extracted sting := ",s := range_extract(R)  | "FAILED")
end

procedure range_extract(R)         #: return string/range representation of a list of unique integers
local s,sep,low,high,x

   every if integer(x:= !R) ~= x then fail                  # ensure all are integers,
   R := sort(set(R))                                        # unique, and sorted

   s := sep := ""
   while s ||:= sep || ( low := high := get(R) ) do {       # lower bound of range
      sep := ","
      while high := ( R[1] = high + 1 ) do get(R)           # find the end of range
      if high > low+1 then s ||:= "-" || high               # - record range of 3+
      else if high = low+1 then push(R,high)                # - range of 2, high becomes new low
      }
   return s
end

procedure list2string(L)          #: helper to convert list to string
local s

   every (s := "[ ") ||:= !L || " "
   return s || "]"
end


USING: kernel prettyprint sequences arrays math math.vectors ;
IN: raycasting

: between ( a b x -- ? ) [ last ] [email protected] [ < ] curry [email protected] xor ;

: lincomb ( a b x -- w )
  3dup [ last ] [email protected]
  [ - ] curry [email protected]
  [ drop ] 2dip
  neg 2dup + [ / ] curry [email protected]
  [ [ v*n ] curry ] [email protected] bi*  v+ ;
: leftof ( a b x -- ? ) dup [ lincomb ] dip [ first ] [email protected] > ;

: ray ( a b x -- ? ) [ between ] [ leftof ] 3bi and ;

: raycast ( poly x -- ? )
  [ dup first suffix [ rest-slice ] [ but-last-slice ] bi ] dip
  [ ray ] curry 2map
  f [ xor ] reduce ;


module Polygons
  use Points_Module
  implicit none

  type polygon
     type(point), dimension(:), allocatable :: points
     integer, dimension(:), allocatable :: vertices
  end type polygon

contains

  function create_polygon(pts, vt)
    type(polygon) :: create_polygon
    type(point), dimension(:), intent(in) :: pts
    integer, dimension(:), intent(in) :: vt

    integer :: np, nv

    np = size(pts,1)
    nv = size(vt,1)

    allocate(create_polygon%points(np), create_polygon%vertices(nv))
    create_polygon%points = pts
    create_polygon%vertices = vt

  end function create_polygon

  subroutine free_polygon(pol)
    type(polygon), intent(inout) :: pol

    deallocate(pol%points, pol%vertices)

  end subroutine free_polygon

end module Polygons


public class RangeExtraction {

    public static void main(String[] args) {
        int[] arr = {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 len = arr.length;
        int idx = 0, idx2 = 0;
        while (idx < len) {
            while (++idx2 < len && arr[idx2] - arr[idx2 - 1] == 1);
            if (idx2 - idx > 2) {
                System.out.printf("%s-%s,", arr[idx], arr[idx2 - 1]);
                idx = idx2;
            } else {
                for (; idx < idx2; idx++)
                    System.out.printf("%s,", arr[idx]);
            }
        }
    }
}


Type Point
  As Single x,y
End Type

Function inpolygon(p1() As Point,p2 As Point) As Integer
  #Macro isleft2(L,p)
    -Sgn(  (L(1).x-L(2).x)*(p.y-L(2).y) - (p.x-L(2).x)*(L(1).y-L(2).y))
  #EndMacro
  Dim As Integer index,nextindex
  Dim k As Integer=UBound(p1)+1
  Dim send (1 To 2) As Point
  Dim wn As Integer=0
  For n As Integer=1 To UBound(p1)
    index=n Mod k:nextindex=(n+1) Mod k
    If nextindex=0 Then nextindex=1
    send(1).x=p1(index).x:send(2).x=p1(nextindex).x
    send(1).y=p1(index).y:send(2).y=p1(nextindex).y
    If p1(index).y<=p2.y Then
      If p1(nextindex).y>p2.y Then
        If isleft2(send,p2)>=0 Then '=
          wn=wn+1
        End If
      End If
    Else
      If p1(nextindex).y<=p2.y Then
        If isleft2(send,p2)<=0 Then'=
          wn=wn-1
        End If
      End If
    End If
  Next n
  Return wn
End Function

Dim As Point square(1 To 4)  ={(0,0),(10,0),(10,10),(0,10)}

Dim As Point hole(1 To 4)    ={(2.5,2.5),(7.5,2.5),(7.5,7.5),(2.5,7.5)}

Dim As Point strange(1 To 8) ={(0,0),(2.5,2.5),(0,10),(2.5,7.5),_
                              (7.5,7.5),(10,10),(10,0),(2.5,2.5)}

Dim As Point exagon(1 To 6)  ={(3,0),(7,0),(10,5),(7,10),(3,10),(0,5)}

'printouts
For z As Integer=1 To 4
  Select Case z
    Case 1: Print "squared"
      Print "(5,5)  " ;Tab(12);
      If inpolygon(square(),Type<Point>(5,5)) Then Print "in" Else Print "out"
      Print "(5,8)  " ;Tab(12);
      If inpolygon(square(),Type<Point>(5,8)) Then Print "in" Else Print "out"
      Print "(-10,5)  " ;Tab(12);
      If inpolygon(square(),Type<Point>(-10,5)) Then Print "in" Else Print "out"
      Print "(0,5)  " ;Tab(12);
      If inpolygon(square(),Type<Point>(0,5)) Then Print "in" Else Print "out"
      Print "(10,5)  " ;Tab(12);
      If inpolygon(square(),Type<Point>(10,5)) Then Print "in" Else Print "out"
      Print "(8,5)  " ;Tab(12);
      If inpolygon(square(),Type<Point>(8,5)) Then Print "in" Else Print "out"
      Print "(10,10)  " ;Tab(12);
      If inpolygon(square(),Type<Point>(10,10)) Then Print "in" Else Print "out"
      Print
    Case 2:Print "squared hole"
      Print "(5,5)  " ;Tab(12);
      If Not inpolygon(hole(),Type<Point>(5,5)) And inpolygon(square(),Type<Point>(5,5)) Then Print "in" Else Print "out"
      Print "(5,8)  " ;Tab(12);
      If Not inpolygon(hole(),Type<Point>(5,8)) And inpolygon(square(),Type<Point>(5,8))Then Print "in" Else Print "out"
      Print "(-10,5)  " ;Tab(12);
      If Not inpolygon(hole(),Type<Point>(-10,5))And inpolygon(square(),Type<Point>(-10,5)) Then Print "in" Else Print "out"
      Print "(0,5)  " ;Tab(12);
      If Not inpolygon(hole(),Type<Point>(0,5))And inpolygon(square(),Type<Point>(0,5)) Then Print "in" Else Print "out"
      Print "(10,5)  " ;Tab(12);
      If Not inpolygon(hole(),Type<Point>(10,5))And inpolygon(square(),Type<Point>(10,5)) Then Print "in" Else Print "out"
      Print "(8,5)  " ;Tab(12);
      If Not inpolygon(hole(),Type<Point>(8,5))And inpolygon(square(),Type<Point>(8,5)) Then Print "in" Else Print "out"
      Print "(10,10)  " ;Tab(12);
      If Not inpolygon(hole(),Type<Point>(10,10))And inpolygon(square(),Type<Point>(10,10)) Then Print "in" Else Print "out"
      Print
    Case 3:Print "strange"
      Print "(5,5)  " ;Tab(12);
      If inpolygon(strange(),Type<Point>(5,5)) Then Print "in" Else Print "out"
      Print "(5,8)  " ;Tab(12);
      If inpolygon(strange(),Type<Point>(5,8)) Then Print "in" Else Print "out"
      Print "(-10,5)  " ;Tab(12);
      If inpolygon(strange(),Type<Point>(-10,5)) Then Print "in" Else Print "out"
      Print "(0,5)  " ;Tab(12);
      If inpolygon(strange(),Type<Point>(0,5)) Then Print "in" Else Print "out"
      Print "(10,5)  " ;Tab(12);
      If inpolygon(strange(),Type<Point>(10,5)) Then Print "in" Else Print "out"
      Print "(8,5)  " ;Tab(12);
      If inpolygon(strange(),Type<Point>(8,5)) Then Print "in" Else Print "out"
      Print "(10,10)  " ;Tab(12);
      If inpolygon(strange(),Type<Point>(10,10)) Then Print "in" Else Print "out"
      Print
    Case 4:Print "exagon"
      Print "(5,5)  " ;Tab(12);
      If inpolygon(exagon(),Type<Point>(5,5)) Then Print "in" Else Print "out"
      Print "(5,8)  " ;Tab(12);
      If inpolygon(exagon(),Type<Point>(5,8)) Then Print "in" Else Print "out"
      Print "(-10,5)  " ;Tab(12);
      If inpolygon(exagon(),Type<Point>(-10,5)) Then Print "in" Else Print "out"
      Print "(0,5)  " ;Tab(12);
      If inpolygon(exagon(),Type<Point>(0,5)) Then Print "in" Else Print "out"
      Print "(10,5)  " ;Tab(12);
      If inpolygon(exagon(),Type<Point>(10,5)) Then Print "in" Else Print "out"
      Print "(8,5)  " ;Tab(12);
      If inpolygon(exagon(),Type<Point>(8,5)) Then Print "in" Else Print "out"
      Print "(10,10)  " ;Tab(12);
      If inpolygon(exagon(),Type<Point>(10,10)) Then Print "in" Else Print "out"
      Print
  End Select
Next z
Sleep


function rangeExtraction(list) {
  var len = list.length;
  var out = [];
  var i, j;

  for (i = 0; i < len; i = j + 1) {
    // beginning of range or single
    out.push(list[i]);

    // find end of range
    for (var j = i + 1; j < len && list[j] == list[j-1] + 1; j++);
    j--;

    if (i == j) {
      // single number
      out.push(",");
    } else if (i + 1 == j) {
      // two numbers
      out.push(",", list[j], ",");
    } else {
      // range
      out.push("-", list[j], ",");
    }
  }
  out.pop(); // remove trailing comma
  return out.join("");
}

// using print function as supplied by Rhino standalone
print(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
]));


package main

import (
    "fmt"
    "math"
)

type xy struct {
    x, y float64
}

type seg struct {
    p1, p2 xy
}

type poly struct {
    name  string
    sides []seg
}

func inside(pt xy, pg poly) (i bool) {
    for _, side := range pg.sides {
        if rayIntersectsSegment(pt, side) {
            i = !i
        }
    }
    return
}

func rayIntersectsSegment(p xy, s seg) bool {
    var a, b xy
    if s.p1.y < s.p2.y {
        a, b = s.p1, s.p2
    } else {
        a, b = s.p2, s.p1
    }
    for p.y == a.y || p.y == b.y {
        p.y = math.Nextafter(p.y, math.Inf(1))
    }
    if p.y < a.y || p.y > b.y {
        return false
    }
    if a.x > b.x {
        if p.x > a.x {
            return false
        }
        if p.x < b.x {
            return true
        }
    } else {
        if p.x > b.x {
            return false
        }
        if p.x < a.x {
            return true
        }
    }
    return (p.y-a.y)/(p.x-a.x) >= (b.y-a.y)/(b.x-a.x)
}

var (
    p1  = xy{0, 0}
    p2  = xy{10, 0}
    p3  = xy{10, 10}
    p4  = xy{0, 10}
    p5  = xy{2.5, 2.5}
    p6  = xy{7.5, 2.5}
    p7  = xy{7.5, 7.5}
    p8  = xy{2.5, 7.5}
    p9  = xy{0, 5}
    p10 = xy{10, 5}
    p11 = xy{3, 0}
    p12 = xy{7, 0}
    p13 = xy{7, 10}
    p14 = xy{3, 10}
)

var tpg = []poly{
    {"square", []seg{{p1, p2}, {p2, p3}, {p3, p4}, {p4, p1}}},
    {"square hole", []seg{{p1, p2}, {p2, p3}, {p3, p4}, {p4, p1},
        {p5, p6}, {p6, p7}, {p7, p8}, {p8, p5}}},
    {"strange", []seg{{p1, p5},
        {p5, p4}, {p4, p8}, {p8, p7}, {p7, p3}, {p3, p2}, {p2, p5}}},
    {"exagon", []seg{{p11, p12}, {p12, p10}, {p10, p13},
        {p13, p14}, {p14, p9}, {p9, p11}}},
}

var tpt = []xy{
    // test points common in other solutions on this page
    {5, 5}, {5, 8}, {-10, 5}, {0, 5}, {10, 5}, {8, 5}, {10, 10},
    // test points that show the problem with "strange"
    {1, 2}, {2, 1},
}

func main() {
    for _, pg := range tpg {
        fmt.Printf("%s:\n", pg.name)
        for _, pt := range tpt {
            fmt.Println(pt, inside(pt, pg))
        }
    }
}


# Input should be an array
def extract:
  reduce .[] as $i
    # state is an array with integers or [start, end] ranges
    ([];
     if length == 0 then [ $i ]
     else ( .[-1]) as $last
            | if ($last|type) == "array" then
                if ($last[1] + 1) == $i then setpath([-1,1]; $i)
                else . + [ $i ]
                end
              elif ($last + 1) == $i then setpath([-1]; [$last, $i])
              else . + [ $i ]
              end
     end)
     | map( if type == "number" then tostring
       elif .[0] == .[1] -1
         then  "\(.[0]),\(.[1])"  # satisfy special requirement
       else "\(.[0])-\(.[1])" end )
     | join(",") ;


/* Range Extraction, in Jsish */
function rangeExtraction(list) {
  var len = list.length;
  var out = [];
  var i, j;

  for (i = 0; i < len; i = j + 1) {
    // beginning of range or single
    out.push(list[i]);

    // find end of range
    for (j = i + 1; j < len && list[j] == list[j-1] + 1; j++);
    j--;

    if (i == j) {
      // single number
      out.push(",");
    } else if (i + 1 == j) {
      // two numbers
      out.push(",", list[j], ",");
    } else {
      // range
      out.push("-", list[j], ",");
    }
  }
  out.pop(); // remove trailing comma
  return out.join("");
}

var arr = [ 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 ];

puts(arr);
puts(rangeExtraction(arr));


import Data.Ratio

type Point = (Rational, Rational)
type Polygon = [Point]
data Line = Sloped {lineSlope, lineYIntercept :: Rational} |
            Vert {lineXIntercept :: Rational}

polygonSides :: Polygon -> [(Point, Point)]
polygonSides poly@(p1 : ps) = zip poly $ ps ++ [p1]

intersects :: Point -> Line -> Bool
{- @intersects (px, py) [email protected] is true if the ray {(x, py) | x ≥ px}
intersects l. -}
intersects (px, _)  (Vert xint)  = px <= xint
intersects (px, py) (Sloped m b) | m < 0     = py <= m * px + b
                                 | otherwise = py >= m * px + b

onLine :: Point -> Line -> Bool
{- Is the point on the line? -}
onLine (px, _)  (Vert xint)  = px == xint
onLine (px, py) (Sloped m b) = py == m * px + b

carrier :: (Point, Point) -> Line
{- Finds the line containing the given line segment. -}
carrier ((ax, ay), (bx, by)) | ax == bx  = Vert ax
                             | otherwise = Sloped slope yint
  where slope = (ay - by) / (ax - bx)
        yint = ay - slope * ax

between :: Ord a => a -> a -> a -> Bool
between x a b | a > b     = b <= x && x <= a
              | otherwise = a <= x && x <= b

inPolygon :: Point -> Polygon -> Bool
inPolygon p@(px, py) = f 0 . polygonSides
  where f n []                             = odd n
        f n (side : sides) | far           = f n       sides
                           | onSegment     = True
                           | rayIntersects = f (n + 1) sides
                           | otherwise     = f n       sides
          where far = not $ between py ay by
                onSegment | ay == by  = between px ax bx
                          | otherwise = p `onLine` line
                rayIntersects =
                    intersects p line &&
                    (py /= ay || by < py) &&
                    (py /= by || ay < py)
                ((ax, ay), (bx, by)) = side
                line = carrier side


function sprintfrange{T<:Integer}(a::Array{T,1})
    len = length(a)
    0 < len || return ""
    dropme = falses(len)
    dropme[2:end-1] = Bool[a[i-1]==a[i]-1 && a[i+1]==a[i]+1 for i in 2:(len-1)]
    s = [string(i) for i in a]
    s[dropme] = "X"
    s = join(s, ",")
    replace(s, r",[,X]+,", "-")
end

testa = [ 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("Testing range-style formatting.")
println("   ", testa, "\n       =>\n   ", sprintfrange(testa))


NB.*crossPnP v point in closed polygon, crossing number
NB.  bool=. points crossPnP polygon
crossPnP=: 4 : 0"2
  'X Y'=. |:x
  'x0 y0 x1 y1'=. |:2 ,/\^:(2={:@[email protected]]) y
  p1=. ((y0<:/Y)*. y1>/Y) +. (y0>/Y)*. y1<:/Y
  p2=. (x0-/X) < (x0-x1) * (y0-/Y) % (y0 - y1)
  2|+/ p1*.p2
)


import static java.lang.Math.*;

public class RayCasting {

    static boolean intersects(int[] A, int[] B, double[] P) {
        if (A[1] > B[1])
            return intersects(B, A, P);

        if (P[1] == A[1] || P[1] == B[1])
            P[1] += 0.0001;

        if (P[1] > B[1] || P[1] < A[1] || P[0] >= max(A[0], B[0]))
            return false;

        if (P[0] < min(A[0], B[0]))
            return true;

        double red = (P[1] - A[1]) / (double) (P[0] - A[0]);
        double blue = (B[1] - A[1]) / (double) (B[0] - A[0]);
        return red >= blue;
    }

    static boolean contains(int[][] shape, double[] pnt) {
        boolean inside = false;
        int len = shape.length;
        for (int i = 0; i < len; i++) {
            if (intersects(shape[i], shape[(i + 1) % len], pnt))
                inside = !inside;
        }
        return inside;
    }

    public static void main(String[] a) {
        double[][] testPoints = {{10, 10}, {10, 16}, {-20, 10}, {0, 10},
        {20, 10}, {16, 10}, {20, 20}};

        for (int[][] shape : shapes) {
            for (double[] pnt : testPoints)
                System.out.printf("%7s ", contains(shape, pnt));
            System.out.println();
        }
    }

    final static int[][] square = {{0, 0}, {20, 0}, {20, 20}, {0, 20}};

    final static int[][] squareHole = {{0, 0}, {20, 0}, {20, 20}, {0, 20},
    {5, 5}, {15, 5}, {15, 15}, {5, 15}};

    final static int[][] strange = {{0, 0}, {5, 5}, {0, 20}, {5, 15}, {15, 15},
    {20, 20}, {20, 0}};

    final static int[][] hexagon = {{6, 0}, {14, 0}, {20, 10}, {14, 20},
    {6, 20}, {0, 10}};

    final static int[][][] shapes = {square, squareHole, strange, hexagon};
}


// version 1.0.6

fun extractRange(list: List<Int>): String {
    if (list.isEmpty()) return ""
    val sb = StringBuilder()
    var first = list[0]
    var prev  = first

    fun append(index: Int) {
        if (first == prev) sb.append(prev)
        else if (first == prev - 1) sb.append(first, ",", prev)
        else sb.append(first, "-", prev)
        if (index < list.size - 1) sb.append(",")
    }

    for (i in 1 until list.size) {
        if (list[i] == prev + 1) prev++
        else {
            append(i)
            first = list[i]
            prev  = first
        }
    }
    append(list.size - 1)
    return sb.toString()
}

fun main(args: Array<String>) {
    val list1 = listOf(-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20)
    println(extractRange(list1))
    println()
    val list2 = listOf(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(extractRange(list2))
}


/**
 * @return {boolean} true if (lng, lat) is in bounds
 */
function contains(bounds, lat, lng) {
    //https://rosettacode.org/wiki/Ray-casting_algorithm
    var count = 0;
    for (var b = 0; b < bounds.length; b++) {
        var vertex1 = bounds[b];
        var vertex2 = bounds[(b + 1) % bounds.length];
        if (west(vertex1, vertex2, lng, lat))
            ++count;
    }
    return count % 2;

    /**
     * @return {boolean} true if (x,y) is west of the line segment connecting A and B
     */
    function west(A, B, x, y) {
        if (A.y <= B.y) {
            if (y <= A.y || y > B.y ||
                x >= A.x && x >= B.x) {
                return false;
            } else if (x < A.x && x < B.x) {
                return true;
            } else {
                return (y - A.y) / (x - A.x) > (B.y - A.y) / (B.x - A.x);
            }
        } else {
            return west(B, A, x, y);
        }
    }
}

var square = {name: 'square', bounds: [{x: 0, y: 0}, {x: 20, y: 0}, {x: 20, y: 20}, {x: 0, y: 20}]};
var squareHole = {
    name: 'squareHole',
    bounds: [{x: 0, y: 0}, {x: 20, y: 0}, {x: 20, y: 20}, {x: 0, y: 20}, {x: 5, y: 5}, {x: 15, y: 5}, {x: 15, y: 15}, {x: 5, y: 15}]
};
var strange = {
    name: 'strange',
    bounds: [{x: 0, y: 0}, {x: 5, y: 5}, {x: 0, y: 20}, {x: 5, y: 15}, {x: 15, y: 15}, {x: 20, y: 20}, {x: 20, y: 0}]
};
var hexagon = {
    name: 'hexagon',
    bounds: [{x: 6, y: 0}, {x: 14, y: 0}, {x: 20, y: 10}, {x: 14, y: 20}, {x: 6, y: 20}, {x: 0, y: 10}]
};

var shapes = [square, squareHole, strange, hexagon];
var testPoints = [{lng: 10, lat: 10}, {lng: 10, lat: 16}, {lng: -20, lat: 10},
    {lng: 0, lat: 10}, {lng: 20, lat: 10}, {lng: 16, lat: 10}, {lng: 20, lat: 20}];

for (var s = 0; s < shapes.length; s++) {
    var shape = shapes[s];
    for (var tp = 0; tp < testPoints.length; tp++) {
        var testPoint = testPoints[tp];
        console.log(JSON.stringify(testPoint) + '\tin ' + shape.name + '\t' + contains(shape.bounds, testPoint.lat, testPoint.lng));
    }
}


s$ = "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 ExtractRange$( s$)
end

function ExtractRange$( range$)
    n = 1
    count = ItemCount( range$, ",")
    while n <= count
        startValue = val( word$( range$, n, ","))
        m = n + 1
        while m <= count
            nextValue = val( word$( range$, m, ","))
            if nextValue - startValue <> m - n then exit while
            m = m + 1
        wend
        if m - n > 2 then
            ExtractRange$ = ExtractRange$ + str$( startValue) + "-" + str$( startValue + m - n - 1) + ","
        else
            for i = n to m - 1
                ExtractRange$ = ExtractRange$ + str$( startValue + i - n) + ","
            next i
        end if
        n = m
    wend
    ExtractRange$ = left$( ExtractRange$, len( ExtractRange$) - 1)
end function

function ItemCount( list$, separator$)
    while word$( list$, ItemCount + 1, separator$) <> ""
        ItemCount = ItemCount + 1
    wend
end function


module RayCastings

export Point

struct Point{T}
    x::T
    y::T
end
Base.show(io::IO, p::Point) = print(io, "($(p.x), $(p.y))")

const Edge = Tuple{Point{T}, Point{T}} where T
Base.show(io::IO, e::Edge) = print(io, "$(e[1]) ∘-∘ $(e[2])")

function rayintersectseg(p::Point{T}, edge::Edge{T}) where T
    a, b = edge
    if a.y > b.y
        a, b = b, a
    end
    if p.y ∈ (a.y, b.y)
        p = Point(p.x, p.y + eps(p.y))
    end

    rst = false
    if (p.y > b.y || p.y < a.y) || (p.x > max(a.x, b.x))
        return false
    end

    if p.x < min(a.x, b.x)
        rst = true
    else
        mred = (b.y - a.y) / (b.x - a.x)
        mblu = (p.y - a.y) / (p.x - a.x)
        rst = mblu ≥ mred
    end

    return rst
end

isinside(poly::Vector{Tuple{Point{T}, Point{T}}}, p::Point{T}) where T =
    isodd(count(edge -> rayintersectseg(p, edge), poly))

connect(a::Point{T}, b::Point{T}...) where T =
    [(a, b) for (a, b) in zip(vcat(a, b...), vcat(b..., a))]

end  # module RayCastings


import java.lang.Double.MAX_VALUE
import java.lang.Double.MIN_VALUE
import java.lang.Math.abs

data class Point(val x: Double, val y: Double)

data class Edge(val s: Point, val e: Point) {
    operator fun invoke(p: Point) : Boolean = when {
        s.y > e.y -> Edge(e, s).invoke(p)
        p.y == s.y || p.y == e.y -> invoke(Point(p.x, p.y + epsilon))
        p.y > e.y || p.y < s.y || p.x > Math.max(s.x, e.x) -> false
        p.x < Math.min(s.x, e.x) -> true
        else -> {
            val blue = if (abs(s.x - p.x) > MIN_VALUE) (p.y - s.y) / (p.x - s.x) else MAX_VALUE
            val red = if (abs(s.x - e.x) > MIN_VALUE) (e.y - s.y) / (e.x - s.x) else MAX_VALUE
            blue >= red
        }
    }

    val epsilon = 0.00001
}

class Figure(val name: String, val edges: Array<Edge>) {
    operator fun contains(p: Point) = edges.count({ it(p) }) % 2 != 0
}

object Ray_casting {
    fun check(figures : Array<Figure>, points : List<Point>) {
        println("points: " + points)
        figures.forEach { f ->
            println("figure: " + f.name)
            f.edges.forEach { println("        " + it) }
            println("result: " + (points.map { it in f }))
        }
    }
}


function rangeExtract nums
    local prevNum, znums, rangedNums
    set itemDelimiter to ", "
    put the first item of nums into prevNum
    repeat for each item n in nums
        if n is (prevNum + 1) then
            put n into prevNum
            put "#" & n after znums
        else
            put n into prevNum
            put return & n after znums
        end if
    end repeat
    set itemDelimiter to "#"
    repeat for each line z in znums
        if z is empty then next repeat
        switch the number of items of z
            case 1
                put z & "," after rangedNums
                break
            case 2
                put item 1 of z & "," & item -1 of z & "," after rangedNums
                break
            default
                put item 1 of z & "-" & item -1 of z & "," after rangedNums
        end switch
    end repeat
    return char 1 to -2 of rangedNums  --strip off trailing comma
end rangeExtract


function extractRange (rList)
    local rExpr, startVal = ""
    for k, v in pairs(rList) do
        if rList[k + 1] == v + 1 then
            if not startVal then startVal = v end
        else
            if startVal then
                if v == startVal + 1 then
                    rExpr = rExpr .. startVal .. "," .. v .. ","
                else
                    rExpr = rExpr .. startVal .. "-" .. v .. ","
                end
                startVal = nil
            else
                rExpr = rExpr .. v .. ","
            end
        end
    end
    return rExpr:sub(1, -2)
end

local intList = {
    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(extractRange(intList))


NoMainWin
Global sw, sh, verts

sw = 640 :   sh = 480
WindowWidth  = sw+8 : WindowHeight = sh+31
UpperLeftX = (DisplayWidth -sw)/2
UpperLeftY = (DisplayHeight-sh)/2
Open"Ray Casting Algorithm" For Graphics_nf_nsb As #g
#g "Down; TrapClose [halt]"
h$ = "#g"

Dim xp(15),yp(15)
#g "when leftButtonDown [halt];when mouseMove checkPoint"
#g "when rightButtonDown [Repeat]"

[Repeat]
    #g "Cls;Fill 32 160 255; Color white;BackColor 32 160 255"
    #g "Place 5 460;\L-click to exit"
    #g "Place 485 460;\R-click for new polygon"

    'generate polygon from random points
    numPoints =  rand(4,15)
    verts = numPoints
    For i = 0 To numPoints-1
        xp(i) = rand(20,620)
        yp(i) = rand(40,420)
    Next
    Call drawPoly h$, verts, "white"
    #g "Flush"
    Wait

[halt]
Close #g
End

'Point In Polygon Function
Function pnp(x, y, numSides)
    j= numSides-1: oddNodes = 0
    For i = 0 To numSides-1
        If ((yp(i)<y) And (yp(j)>=y)) Or ((yp(j)<y) And (yp(i)>=y)) Then
            f1 = y - yp(i):f2 = yp(j) - yp(i): f3 = xp(j) - xp(i)
            If (xp(i) + f1 / f2 * f3) < x Then oddNodes = 1 - oddNodes
        End If
        j = i
    Next
    pnp = oddNodes
End Function

'draw the polygon
Sub drawPoly h$, verts, colour$
    #h$, "Color ";colour$
    j = verts-1
    For i = 0 To verts-1
        #h$ "Line ";xp(j);" ";yp(j);" ";xp(i);" ";yp(i)
        j = i
    Next
End Sub

'change message and color of polygon
Sub checkPoint h$, x, y
    If pnp(x,y,verts) Then
        #h$ "Color 32 160 255;BackColor 32 160 255"
        #h$ "Place 5 0;BoxFilled 150 20;Color white"
        #h$ "Place 7 15;\Mouse In Polygon"
        Call drawPoly h$, verts, "red"
    Else
        #h$ "Color 32 160 255;BackColor 32 160 255"
        #h$ "Place 5 0;BoxFilled 150 20;Color white"
        #h$ "Place 7 15;\Mouse Not In Polygon"
        Call drawPoly h$, verts, "white"
    End If
End Sub

Function rand(loNum,hiNum)
    rand = Int(Rnd(0)*(hiNum-loNum+1)+loNum)
End Function


function Point(x,y) return {x=x, y=y} end

function Polygon(name, points)
  local function contains(self, p)
    local odd, eps = false, 1e-9
    local function rayseg(p, a, b)
      if a.y > b.y then a, b = b, a end
      if p.y == a.y or p.y == b.y then p.y = p.y + eps end
      if p.y < a.y or p.y > b.y or p.x > math.max(a.x, b.x) then return false end
      if p.x < math.min(a.x, b.x) then return true end
      local red = a.x == b.x and math.huge or (b.y-a.y)/(b.x-a.x)
      local blu = a.x == p.x and math.huge or (p.y-a.y)/(p.x-a.x)
      return blu >= red
     end
    for i, a in ipairs(self.points) do
      local b = self.points[i%#self.points+1]
      if rayseg(p, a, b) then odd = not odd end
    end
    return odd
  end
  return {name=name, points=points, contains=contains}
end

polygons = {
  Polygon("square", { Point(0,0), Point(10,0), Point(10,10), Point(0,10) }),
  Polygon("squarehole", { Point(0,0), Point(10,0), Point(10,10), Point(0,10), Point(2.5,2.5), Point(7.5,2.5), Point(7.5,7.5), Point(2.5,7.5) }),
  Polygon("strange", { Point(0,0), Point(2.5,2.5),  Point(0, 10), Point(2.5,7.5), Point(7.5,7.5), Point(10,10), Point(10,0), Point(2.5,2.5) }),
  Polygon("hexagon", { Point(3,0), Point(7,0), Point(10,5), Point(7,10), Point(3,10), Point(0,5) })
}
points = { Point(5,5), Point(5,8), Point(-10,5), Point(0,5), Point(10,5), Point(8,5), Point(10,10) }

for _,poly in ipairs(polygons) do
  print("Does '"..poly.name.."' contain the point..")
  for _,pt in ipairs(points) do
    print(string.format("  (%3.f, %2.f)?  %s", pt.x, pt.y, tostring(poly:contains(pt))))
  end
  print()
end


:- module range_extraction.
:- interface.

:- import_module io.

:- pred main(io::di, io::uo) is det.

:- implementation.

:- import_module int, list, ranges, string.

main(!IO) :-
    print_ranges(numbers, !IO).

:- pred print_ranges(list(int)::in, io::di, io::uo) is det.

print_ranges(Nums, !IO) :-
    Ranges = ranges.from_list(Nums),
    ranges.range_foldr(add_range_string, Ranges, [], RangeStrs),
    io.write_list(RangeStrs, ",", io.write_string, !IO).

:- pred add_range_string(int::in, int::in,
     list(string)::in, list(string)::out) is det.

add_range_string(L, H, !Strs) :-
   ( if L = H then
      !:Strs = [int_to_string(L) | !.Strs]
   else if L + 1 = H then
      !:Strs = [int_to_string(L), int_to_string(H) | !.Strs]
   else
      !:Strs = [string.format("%d-%d", [i(L), i(H)]) | !.Strs]
   ).

:- func numbers = list(int).

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].


type point = { x:float; y:float }

type polygon = {
  vertices: point array;
  edges: (int * int) list;
}

let p x y = { x=x; y=y }

let square_v = [|
  (p 0. 0.); (p 10. 0.); (p 10. 10.); (p 0. 10.);
  (p 2.5 2.5); (p 7.5 0.1); (p 7.5 7.5); (p 2.5 7.5)
|]

let esa_v = [|
  (p 3. 0.); (p 7. 0.); (p 10. 5.); (p 7. 10.); (p 3. 10.); (p 0. 5.)
|]

let esa = {
  vertices = esa_v;
  edges = [ (0,1); (1,2); (2,3); (3,4); (4,5); (5,0) ]
}

let square = {
  vertices = square_v;
  edges = [ (0,1); (1,2); (2,3); (3,0) ]
}

let squarehole = {
  vertices = square_v;
  edges = [ (0,1); (1,2); (2,3); (3,0); (4,5); (5,6); (6,7); (7,4) ]
}

let strange = {
  vertices = square_v;
  edges = [ (0,4); (4,3); (3,7); (7,6); (6,2); (2,1); (1,5); (5,0) ]
}

let min_y ~a ~b = if a.y > b.y then (b) else (a)

let coeff_ang ~pa ~pb = (pb.y -. pa.y) /. (pb.x -. pa.x)

let huge_val = infinity

let hseg_intersect_seg ~s ~a ~b =
  let _eps =
    if s.y = (max a.y b.y) ||
       s.y = (min a.y b.y) then 0.00001 else 0.0
  in
  if  (s.y +. _eps) > (max a.y b.y) ||
      (s.y +. _eps) < (min a.y b.y) ||
       s.x > (max a.x b.x) then (false)
  else if s.x <= (min a.x b.x) then (true)
  else
    let ca = if a.x <> b.x then (coeff_ang a b) else (huge_val) in
    let my = min_y ~a ~b in
    let cp = if (s.x -. my.x) <> 0.0 then (coeff_ang my s) else (huge_val) in
    (cp >= ca)
;;

let point_is_inside ~poly ~pt =
  let cross = ref 0 in
  List.iter (fun (a,b) ->
    if hseg_intersect_seg pt
             poly.vertices.(a)
             poly.vertices.(b)
    then incr cross
  ) poly.edges;
  ( (!cross mod 2) <> 0)
;;

let make_test p label s =
  Printf.printf "point (%.5f,%.5f) is " p.x p.y;
  print_string (if point_is_inside s p
                then "INSIDE "
                else "OUTSIDE ");
  print_endline label;
;;

let () =
  let test_points = [
    (p 5. 5.); (p 5. 8.); (p 2. 2.); (p 0. 0.);
    (p 10. 10.); (p 2.5 2.5); (p 0.01 5.);
    (p 2.2 7.4); (p 0. 5.); (p 10. 5.); (p (-4.) 10.) ] in

  List.iter (fun p ->
    make_test p "square"     square;
    make_test p "squarehole" squarehole;
    make_test p "strange"    strange;
    make_test p "esa"        esa;
    print_newline()
  ) test_points;
;;


extractRange = function(ints)
    result = []
    idx = 0
    while idx < ints.len
        runLen = 1
        while idx+runLen < ints.len and ints[idx+runLen] == ints[idx] + runLen
            runLen = runLen + 1
        end while
        if runLen > 2 then
            result.push ints[idx] + "-" + ints[idx+runLen-1]
            idx = idx + runLen
        else
            result.push ints[idx]
            idx = idx + 1
        end if
    end while
    return join(result, ",")
end function

test = [ 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 extractRange(test)


RANGCONT(X) ;Integer range contraction
 NEW Y,I,CONT,NOTFIRST,CURR,PREV,NEXT,SEQ SET Y="",SEQ=0,PREV="",CONT=0
 FOR I=1:1:$LENGTH(X,",") DO
 .SET NOTFIRST=$LENGTH(Y),CURR=$PIECE(X,",",I),NEXT=$PIECE(X,",",I+1)
 .FOR  Q:$EXTRACT(CURR)'=" "  S CURR=$EXTRACT(CURR,2,$LENGTH(CURR))  ;clean up leading spaces
 .S SEQ=((CURR-1)=PREV)&((CURR+1)=NEXT)
 .IF 'NOTFIRST SET Y=CURR
 .IF NOTFIRST DO
 ..;Order matters due to flags
 ..IF CONT&SEQ ;Do nothing
 ..IF 'CONT&'SEQ SET Y=Y_","_CURR
 ..IF CONT&'SEQ SET Y=Y_CURR,CONT=0
 ..IF 'CONT&SEQ SET Y=Y_"-",CONT=1
 .SET PREV=CURR
 IF CONT SET Y=Y_PREV
 K I,CONT,NOTFIRST,CURR,PREV,NEXT,SEQ
 QUIT Y


/*NetRexx program to test range extraction. ***************************
* 07.08.2012 Walter Pachl derived from my Rexx Version
* Changes: line continuation in aaa assignment changed
*          1e99 -> 999999999
*          Do -> Loop
*          words(aaa) -> aaa.words()
*          word(aaa,i) -> aaa.word(i)
**********************************************************************/
Say 'NetRexx program derived from Rexx'
aaa='0 1 2 4 6 7 8 11 12 14 15 16 17 18 19 20 21 22 23 24 25 27 28 29'
aaa=aaa' 30 31 32 33 35 36 37 38 39'
say 'old='aaa;
aaa=aaa 999999999                   /* artificial number at the end  */
i=0                                 /* initialize index              */
ol=''                               /* initialize output string      */
comma=''                            /* will become a ',' lateron     */
inrange=0
Loop While i<=aaa.words             /* loop for all numbers          */
  i=i+1                             /* index of next number          */
  n=aaa.word(i)                     /* the now current number        */
  If n=999999999 Then Leave         /* we are at the end             */
  If inrange Then Do                /* range was opened              */
    If aaa.word(i+1)<>n+1 Then Do   /* following word not in range   */
      ol=ol||n                      /* so this number is the end     */
      inrange=0                     /* and the range is over         */
      End                           /* else ignore current number    */
    End
  Else Do                           /* not in a range                */
    ol=ol||comma||n                 /* add number (with comma)       */
    comma=','                       /* to the output string          */
    If aaa.word(i+2)=n+2 Then Do    /* if the nr after the next fits */
      inrange=1                     /* open a range                  */
      ol=ol'-'                      /* append the range connector    */
      End
    End
  End
Say 'new='ol


import parseutils, re, strutils, sequtils

proc extractRange(input: string): string =
  var list = input.replace(re"\s+").split(',').map(parseInt)
  var ranges: seq[string]
  var i = 0
  while i < list.len:
    var first = list[i] # first element in the current range
    var offset = i
    while True: # skip ahead to the end of the current range
      if i + 1 >= list.len:
        # reached end of the list
        break
      if list[i + 1] - (i + 1) != first - offset:
        # next element isn't in the current range
        break
      i.inc
    var last = list[i] # last element in the current range
    case last - first
      of 0: ranges.add($first)
      of 1: ranges.add("$1,$2".format(first, last))
      else: ranges.add("$1-$2".format(first, last))
    i.inc
  return ranges.join(",")

echo("""
    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""".extractRange)


constant inf = 1e300*1e300

function rayIntersectsSegment(sequence point, sequence segment)
    sequence {a, b} = segment
    atom {pX,pY} = point,
         {aX,aY} = a,
         {bX,bY} = b,
         m_red,m_blue
    -- ensure {aX,aY} is the segment end-point with the smallest y coordinate
    if aY>bY then
        {bX,bY} = a
        {aX,aY} = b
    end if
    if pY=aY or pY=bY then
        --
        -- Consider a ray passing through the top or left corner of a diamond:
        --          /
        --  --- or  -
        --   ^      \
        -- In both cases it touches both edges, but ends up outside in the
        --  top case, whereas it ends up inside in the left case. Just move
        --  the y co-ordinate down a smidge and it'll work properly, by
        --  missing one line in the left/right cases and hitting both/none
        --  in the top/bottom cases.
        --
        pY += 0.000001
    end if
    if pY<aY or pY>bY then return false end if
    if pX>max(aX,bX) then return false end if
    if pX<min(aX,bX) then return true end if
    if aX!=bX then
        m_red = (bY-aY)/(bX-aX)
    else
        m_red = inf
    end if
    if aX!=pX then
        m_blue = (pY-aY)/(pX-aX)
    else
        m_blue = inf
    end if
    return m_blue >= m_red
end function

function inside(sequence point, sequence poly)
    bool res = false
    for i=1 to length(poly) do
        if rayIntersectsSegment(point,poly[i]) then
            res = not res
        end if
    end for
    return res
end function

function instr(integer flag, integer expected)
    string res = {"in", "out"}[2-flag]
    if flag!=expected then
        res &= "*** ERROR ***"
    end if
    return res
end function

function instar(integer flag)
    return "* "[2-flag]
end function

constant test_points = {{5,5},{5,8},{-10,5},{0,5},{10,5},{8,5},{10,10}}

--constant NAME = 1, POLY = 2, EXPECTED = 3
constant test_polygons = {
        {"square",      {{{0,0},{10,0}},{{10,0},{10,10}},{{10,10},{0,10}},{{0,10},{0,0}}},
                        {true,true,false,false,true,true,false}},
        {"square hole", {{{0,0},{10,0}},{{10,0},{10,10}},{{10,10},{0,10}},{{0,10},{0,0}},
                         {{2.5,2.5},{7.5,2.5}},{{7.5,2.5},{7.5,7.5}},{{7.5,7.5},{2.5,7.5}},{{2.5,7.5},{2.5,2.5}}},
                        {false,true,false,false,true,true,false}},
        {"strange",     {{{0,5},{2.5,2.5}},{{2.5,2.5},{0,10}},{{0,10},{2.5,7.5}},{{2.5,7.5},{7.5,7.5}},
                         {{7.5,7.5},{10,10}},{{10,10},{10,0}},{{10,0},{2.5,2.5}}},
                        {true,false,false,false,true,true,false}},
        {"exagon",      {{{3,0},{7,0}},{{7,0},{10,5}},{{10,5},{7,10}},{{7,10},{3,10}},{{3,10},{0,5}},{{0,5},{3,0}}},
                        {true,true,false,false,true,true,false}}
}

sequence name, poly, expected, tp

for i=1 to length(test_polygons) do
    {name,poly,expected} = test_polygons[i]
    printf(1,"\n%12s:",{name})
    for j=1 to length(test_points) do
        tp = test_points[j]
        printf(1," %s, %-4s",{sprint(tp),instr(inside(tp,poly),expected[j])})
    end for
end for

puts(1,"\n\n\n")

for i=0 to 10 do
    for j=1 to length(test_polygons) do
        puts(1,"     ")
        poly = test_polygons[j][2]
        for k=0 to 10 do
            puts(1,instar(inside({k+0.5,10.5-i},poly)))
        end for
    end for
    puts(1,"\n")
end for


class IdentityMatrix {
  function : Main(args : String[]) ~ Nil {
    Compress2Range("-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20")->PrintLine();

    Compress2Range("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")->PrintLine();
  }

  function : Compress2Range(expanded : String) ~ String {
    result := "";
    nums := expanded->ReplaceAll(" ", "")->Split(",");
    firstNum := nums[0]->ToInt();
    rangeSize := 0;
    for(i:= 1; i < nums->Size(); i += 1;) {
      thisNum := nums[i]->ToInt();
            if(thisNum - firstNum - rangeSize = 1) {
                rangeSize += 1;
            }
      else{
        if(rangeSize <> 0){
          result->Append(firstNum);
          result->Append((rangeSize = 1) ? ",": "-");
          result->Append(firstNum+rangeSize);
          result->Append(",");
                    rangeSize := 0;
                }
        else {
          result->Append(firstNum);
          result->Append(",");
        };
        firstNum := thisNum;
      };
    };

    if(rangeSize <> 0){
      result->Append(firstNum);
      result->Append((rangeSize = 1) ? "," : "-");
      result->Append(firstNum + rangeSize);
      rangeSize := 0;
    }
    else {
      result->Append(firstNum);
    };

    return result;
  }
}


(scl 4)

(de intersects (Px Py Ax Ay Bx By)
   (when (> Ay By)
      (xchg 'Ax 'Bx)
      (xchg 'Ay 'By) )
   (when (or (= Py Ay) (= Py By))
      (inc 'Py) )
   (and
      (>= Py Ay)
      (>= By Py)
      (>= (max Ax Bx) Px)
      (or
         (> (min Ax Bx) Px)
         (= Ax Px)
         (and
            (<> Ax Bx)
            (>=
               (*/ (- Py Ay) 1.0 (- Px Ax))            # Blue
               (*/ (- By Ay) 1.0 (- Bx Ax)) ) ) ) ) )  # Red

(de inside (Pt Poly)
   (let Res NIL
      (for Edge Poly
         (when (apply intersects Edge (car Pt) (cdr Pt))
            (onOff Res) ) )
      Res ) )


Structure point_f
  x.f
  y.f
EndStructure
Procedure inpoly(*p.point_f, List poly.point_f())
  Protected.point_f new, old, lp, rp
  Protected inside
  If ListSize(poly()) < 3: ProcedureReturn 0: EndIf
  LastElement(poly()): old = poly()
  ForEach poly()
    ;find leftmost endpoint 'lp' and the rightmost endpoint 'rp' based on x value
    If poly()\x > old\x
      lp = old
      rp = poly()
    Else
      lp = poly()
      rp = old
    EndIf
    If lp\x < *p\x And *p\x <= rp\x And (*p\y - lp\y) * (rp\x - lp\x) < (rp\y - lp\y) * (*p\x - lp\x)
      inside = ~inside
    EndIf
    old = poly()
  Next
  ProcedureReturn inside & 1
EndProcedure

If InitSprite()
  If InitKeyboard() And InitMouse()
    OpenWindow(0, 0, 0, 800, 600, "Press [Esc] to close, [Left mouse button] Add Point, [Right mouse button] Clear All Points.", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
    OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 1, 0, 0)
    SetFrameRate(60)
  EndIf
Else
  MessageRequester("", "Unable to initsprite"): End
EndIf

NewList v.point_f()
Define.point_f pvp, mp
Define Col, EventID, mode.b, modetxt.s
Repeat
  Delay(1)
  EventID = WindowEvent()
  ExamineKeyboard()
  ExamineMouse()
  ClearScreen(Col)

  mp\x = MouseX()
  mp\y = MouseY()
  If MouseButton(#PB_MouseButton_Left)
    AddElement(v())
    v()\x = mp\x
    v()\y = mp\y
    Delay(100)
  EndIf

  If MouseButton(#PB_MouseButton_Right)
    ClearList(v())
    Delay(100)
  EndIf

  StartDrawing(ScreenOutput())
    If LastElement(v())
      pvp = v()
      ForEach v()
        LineXY(pvp\x, pvp\y, v()\x, v()\y, RGB(0, $FF, 0)) ;Green
        Circle(pvp\x, pvp\y, 5, RGB($FF, 0, 0)) ;Red
        pvp = v()
      Next
    EndIf
    Circle(MouseX(), MouseY(), 5, RGB($C0, $C0, $FF)) ;LightBlue

    If inpoly(mp, v())
      modetxt = "You are in the polygon."
      Col = RGB(0, 0, 0)
    Else
      modetxt = "You are not in the polygon."
      Col = RGB($50, $50, $50)
    EndIf
    DrawText((800 - TextWidth(modetxt)) / 2, 0, modetxt)
  StopDrawing()

  FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape) Or EventID = #PB_Event_CloseWindow


#import <Foundation/Foundation.h>

NSString *extractRanges(NSArray *nums) {
  NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];
  for (NSNumber *n in nums) {
    if ([n integerValue] < 0)
      @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"negative number not supported" userInfo:nil];
    [indexSet addIndex:[n unsignedIntegerValue]];
  }
  NSMutableString *s = [[NSMutableString alloc] init];
  [indexSet enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) {
    if (s.length)
      [s appendString:@","];
    if (range.length == 1)
      [s appendFormat:@"%lu", range.location];
    else if (range.length == 2)
      [s appendFormat:@"%lu,%lu", range.location, range.location+1];
    else
      [s appendFormat:@"%lu-%lu", range.location, range.location+range.length-1];
  }];
  return s;
}

int main() {
  @autoreleasepool {

    NSLog(@"%@", extractRanges(@[@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]));

  }
  return 0;
}


from collections import namedtuple
from pprint import pprint as pp
import sys

Pt = namedtuple('Pt', 'x, y')               # Point
Edge = namedtuple('Edge', 'a, b')           # Polygon edge from a to b
Poly = namedtuple('Poly', 'name, edges')    # Polygon

_eps = 0.00001
_huge = sys.float_info.max
_tiny = sys.float_info.min

def rayintersectseg(p, edge):
    ''' takes a point p=Pt() and an edge of two endpoints a,b=Pt() of a line segment returns boolean
    '''
    a,b = edge
    if a.y > b.y:
        a,b = b,a
    if p.y == a.y or p.y == b.y:
        p = Pt(p.x, p.y + _eps)

    intersect = False

    if (p.y > b.y or p.y < a.y) or (
        p.x > max(a.x, b.x)):
        return False

    if p.x < min(a.x, b.x):
        intersect = True
    else:
        if abs(a.x - b.x) > _tiny:
            m_red = (b.y - a.y) / float(b.x - a.x)
        else:
            m_red = _huge
        if abs(a.x - p.x) > _tiny:
            m_blue = (p.y - a.y) / float(p.x - a.x)
        else:
            m_blue = _huge
        intersect = m_blue >= m_red
    return intersect

def _odd(x): return x%2 == 1

def ispointinside(p, poly):
    ln = len(poly)
    return _odd(sum(rayintersectseg(p, edge)
                    for edge in poly.edges ))

def polypp(poly):
    print ("\n  Polygon(name='%s', edges=(" % poly.name)
    print ('   ', ',\n    '.join(str(e) for e in poly.edges) + '\n    ))')

if __name__ == '__main__':
    polys = [
      Poly(name='square', edges=(
        Edge(a=Pt(x=0, y=0), b=Pt(x=10, y=0)),
        Edge(a=Pt(x=10, y=0), b=Pt(x=10, y=10)),
        Edge(a=Pt(x=10, y=10), b=Pt(x=0, y=10)),
        Edge(a=Pt(x=0, y=10), b=Pt(x=0, y=0))
        )),
      Poly(name='square_hole', edges=(
        Edge(a=Pt(x=0, y=0), b=Pt(x=10, y=0)),
        Edge(a=Pt(x=10, y=0), b=Pt(x=10, y=10)),
        Edge(a=Pt(x=10, y=10), b=Pt(x=0, y=10)),
        Edge(a=Pt(x=0, y=10), b=Pt(x=0, y=0)),
        Edge(a=Pt(x=2.5, y=2.5), b=Pt(x=7.5, y=2.5)),
        Edge(a=Pt(x=7.5, y=2.5), b=Pt(x=7.5, y=7.5)),
        Edge(a=Pt(x=7.5, y=7.5), b=Pt(x=2.5, y=7.5)),
        Edge(a=Pt(x=2.5, y=7.5), b=Pt(x=2.5, y=2.5))
        )),
      Poly(name='strange', edges=(
        Edge(a=Pt(x=0, y=0), b=Pt(x=2.5, y=2.5)),
        Edge(a=Pt(x=2.5, y=2.5), b=Pt(x=0, y=10)),
        Edge(a=Pt(x=0, y=10), b=Pt(x=2.5, y=7.5)),
        Edge(a=Pt(x=2.5, y=7.5), b=Pt(x=7.5, y=7.5)),
        Edge(a=Pt(x=7.5, y=7.5), b=Pt(x=10, y=10)),
        Edge(a=Pt(x=10, y=10), b=Pt(x=10, y=0)),
        Edge(a=Pt(x=10, y=0), b=Pt(x=2.5, y=2.5))
        )),
      Poly(name='exagon', edges=(
        Edge(a=Pt(x=3, y=0), b=Pt(x=7, y=0)),
        Edge(a=Pt(x=7, y=0), b=Pt(x=10, y=5)),
        Edge(a=Pt(x=10, y=5), b=Pt(x=7, y=10)),
        Edge(a=Pt(x=7, y=10), b=Pt(x=3, y=10)),
        Edge(a=Pt(x=3, y=10), b=Pt(x=0, y=5)),
        Edge(a=Pt(x=0, y=5), b=Pt(x=3, y=0))
        )),
      ]
    testpoints = (Pt(x=5, y=5), Pt(x=5, y=8),
                  Pt(x=-10, y=5), Pt(x=0, y=5),
                  Pt(x=10, y=5), Pt(x=8, y=5),
                  Pt(x=10, y=10))

    print ("\n TESTING WHETHER POINTS ARE WITHIN POLYGONS")
    for poly in polys:
        polypp(poly)
        print ('   ', '\t'.join("%s: %s" % (p, ispointinside(p, poly))
                               for p in testpoints[:3]))
        print ('   ', '\t'.join("%s: %s" % (p, ispointinside(p, poly))
                               for p in testpoints[3:6]))
        print ('   ', '\t'.join("%s: %s" % (p, ispointinside(p, poly))
                               for p in testpoints[6:]))


let range_extract = function
  | [] -> []
  | x::xs ->
    let f (i,j,ret) k =
      if k = succ j then (i,k,ret) else (k,k,(i,j)::ret) in
    let (m,n,ret) = List.fold_left f (x,x,[]) xs in
    List.rev ((m,n)::ret)

let string_of_range rng =
  let str (a,b) =
    if a = b then string_of_int a
    else Printf.sprintf "%d%c%d" a (if b = succ a then ',' else '-') b in
  String.concat "," (List.map str rng)

let () =
  let li =
    [ 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 ]
  in
  let rng = range_extract li in
  print_endline(string_of_range rng)


point_in_polygon <- function(polygon, p) {
  count <- 0
  for(side in polygon) {
    if ( ray_intersect_segment(p, side) ) {
      count <- count + 1
    }
  }
  if ( count %% 2 == 1 )
    "INSIDE"
  else
    "OUTSIDE"
}

ray_intersect_segment <- function(p, side) {
  eps <- 0.0001
  a <- side$A
  b <- side$B
  if ( a$y > b$y ) {
    a <- side$B
    b <- side$A
  }
  if ( (p$y == a$y) || (p$y == b$y) ) {
    p$y <- p$y + eps
  }
  if ( (p$y < a$y) || (p$y > b$y) )
    return(FALSE)
  else if ( p$x > max(a$x, b$x) )
    return(FALSE)
  else {
    if ( p$x < min(a$x, b$x) )
      return(TRUE)
    else {
      if ( a$x != b$x )
        m_red <- (b$y - a$y) / (b$x - a$x)
      else
        m_red <- Inf
      if ( a$x != p$x )
        m_blue <- (p$y - a$y) / (p$x - a$x)
      else
        m_blue <- Inf
      return( m_blue >= m_red )
    }
  }
}


#lang racket

(module pip racket
  (require racket/contract)

  (provide point)
  (provide seg)
  (provide (contract-out [point-in-polygon? (->
                                             point?
                                             list?
                                             boolean?)]))

  (struct point (x y) #:transparent)
  (struct seg (Ax Ay Bx By) #:transparent)
  (define ε 0.000001)
  (define (neq? x y) (not (eq? x y)))

  (define (ray-cross-seg? r s)
    (let* ([Ax (seg-Ax s)] [Ay (seg-Ay s)]
           [Bx (seg-Bx s)] [By (seg-By s)]
           [Px (point-x r)] [Pyo (point-y r)]
           [Py (+ Pyo (if (or (eq? Pyo Ay)
                              (eq? Pyo By))
                          ε 0))])

      (define Ax2 (if (< Ay By) Ax Bx))
      (define Ay2 (if (< Ay By) Ay By))
      (define Bx2 (if (< Ay By) Bx Ax))
      (define By2 (if (< Ay By) By Ay))

      (cond [(or (> Py (max Ay By)) (< Py (min Ay By))) #f]
            [(> Px (max Ax Bx)) #f]
            [else (cond
                [(< Px (min Ax Bx)) #t]
                [else
                 (let ([red (if (neq? Ax2 Bx2)
                               (/ (- By2 Ay2) (- Bx2 Ax2))
                               +inf.0)]
                      [blue (if (neq? Ax2 Px)
                                (/ (- Py Ay2) (- Px Ax2))
                                 +inf.0)])
                   (if (>= blue red) #t #f))])])))

  (define (point-in-polygon? point polygon)
    (odd?
     (for/fold ([c 0]) ([seg polygon])
       (+ c (if (ray-cross-seg? point seg) 1 0))))))

(require 'pip)

(define test-point-list
  (list
   (point 5.0    5.0)
   (point 5.0    8.0)
   (point -10.0  5.0)
   (point  0.0   5.0)
   (point 10.0   5.0)
   (point  8.0   5.0)
   (point 10.0  10.0)))

(define square
  (list (seg 0.0   0.0  10.0   0.0)
        (seg 10.0  0.0  10.0  10.0)
        (seg 10.0  10.0  0.0  10.0)
        (seg 0.0   0.0  0.0   10.0)))

(define exagon
  (list (seg  3.0   0.0   7.0   0.0)
        (seg  7.0   0.0  10.0   5.0)
        (seg 10.0   5.0   7.0  10.0)
        (seg  7.0  10.0   3.0  10.0)
        (seg  0.0   5.0   3.0   10.0)
        (seg  3.0   0.0 0.0   5.0)))

(define (test-figure fig name)
  (printf "\ntesting ~a: \n" name)
  (for ([p test-point-list])
    (printf "testing ~v: ~a\n"  p (point-in-polygon? p fig))))

(test-figure square "square")
(test-figure exagon "exagon")


(define (extract ll)
   (let loop ((head (car ll)) (tail (cdr ll)) (out #null))
      (if (null? tail)
         (reverse (cons head out))
      else
         (cond
            ((eq? head (- (car tail) 1))
               (loop (list (car tail) head) (cdr tail) out))
            ((and (pair? head) (eq? (car head) (- (car tail) 1)))
               (loop (cons (car tail) head) (cdr tail) out))
            (else
               (loop (car tail) (cdr tail) (cons head out)))))))

(define (range->string range)
   (fold (lambda (f v)
            (string-append (if f (string-append f ",") "")
               (if (pair? v)
                  (string-append (string-append (number->string (last v #f)) "-")(number->string (car v)))
                  (number->string v))))
      #false
      range))

; let's test
(define data '(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))
(define range (extract data))

(print "extracted ranges: " range)
(print "string representation: " (range->string range))


// Twin Ramanujan primes. Nigel Galloway: September 9th., 2021
printfn $"There are %d{rP 1000000|>Seq.pairwise|>Seq.filter(fun(n,g)->n=g-2)|>Seq.length} twins in the first million Ramanujan primes"


package main

import (
    "fmt"
    "math"
    "rcu"
    "time"
)

var count []int

func primeCounter(limit int) {
    count = make([]int, limit)
    for i := 0; i < limit; i++ {
        count[i] = 1
    }
    if limit > 0 {
        count[0] = 0
    }
    if limit > 1 {
        count[1] = 0
    }
    for i := 4; i < limit; i += 2 {
        count[i] = 0
    }
    for p, sq := 3, 9; sq < limit; p += 2 {
        if count[p] != 0 {
            for q := sq; q < limit; q += p << 1 {
                count[q] = 0
            }
        }
        sq += (p + 1) << 2
    }
    sum := 0
    for i := 0; i < limit; i++ {
        sum += count[i]
        count[i] = sum
    }
}

func primeCount(n int) int {
    if n < 1 {
        return 0
    }
    return count[n]
}

func ramanujanMax(n int) int {
    fn := float64(n)
    return int(math.Ceil(4 * fn * math.Log(4*fn)))
}

func ramanujanPrime(n int) int {
    if n == 1 {
        return 2
    }
    for i := ramanujanMax(n); i >= 2*n; i-- {
        if i%2 == 1 {
            continue
        }
        if primeCount(i)-primeCount(i/2) < n {
            return i + 1
        }
    }
    return 0
}

func rpc(p int) int { return primeCount(p) - primeCount(p/2) }

func main() {
    for _, limit := range []int{1e5, 1e6} {
        start := time.Now()
        primeCounter(1 + ramanujanMax(limit))
        rplim := ramanujanPrime(limit)
        climit := rcu.Commatize(limit)
        fmt.Printf("The %sth Ramanujan prime is %s\n", climit, rcu.Commatize(rplim))
        r := rcu.Primes(rplim)
        c := make([]int, len(r))
        for i := 0; i < len(c); i++ {
            c[i] = rpc(r[i])
        }
        ok := c[len(c)-1]
        for i := len(c) - 2; i >= 0; i-- {
            if c[i] < ok {
                ok = c[i]
            } else {
                c[i] = 0
            }
        }
        var fr []int
        for i, r := range r {
            if c[i] != 0 {
                fr = append(fr, r)
            }
        }
        twins := 0
        for i := 0; i < len(fr)-1; i++ {
            if fr[i]+2 == fr[i+1] {
                twins++
            }
        }
        fmt.Printf("There are %s twins in the first %s Ramanujan primes.\n", rcu.Commatize(twins), climit)
        fmt.Println("Took", time.Since(start))
        fmt.Println()
    }
}


/* Rexx */

parse arg userInput
call runSample userInput
return
exit

-- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-- Compact a list of numbers by reducing ranges
compact:
procedure
--trace ?r;nop
  parse arg expanded
  nums = expanded~changestr(',', ' ')~space -- remove possible commas & clean up the string
  rezult = ''

  RANGE = 0
  FIRST = nums~word(1) -- set starting value
  loop i_ = 2 to nums~words -- each word in the string is a number to examine
    LOCAL = nums~word(i_)
    if LOCAL - FIRST - RANGE == 1 then do
      -- inside a range
      RANGE += 1
      end
    else do
      -- not inside a range
      if RANGE \= 0 then do
        -- we have a range of numbers so collect this and reset
        rezult = rezult || FIRST || delim(RANGE) || FIRST + RANGE || ','
        RANGE = 0
        end
      else do
        -- just collect this number
        rezult = rezult || FIRST || ','
        end
      FIRST = LOCAL -- bump new starting value
      end
    end i_
  if RANGE \= 0 then do
    -- collect terminating value (a range)
    rezult = rezult || FIRST || delim(RANGE) || FIRST + RANGE
    end
  else do
    -- collect terminating value (a single number)
    rezult = rezult || FIRST
    end

  return rezult~space(1, ',') -- format and return result string

-- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-- determine if the range delimiter should be a comma or dash
delim:
procedure
  parse arg range .
  if range == 1 then dlm = ','
  else               dlm = '-'
  return dlm

-- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-- sample driver
runSample:
procedure
parse arg userInput
td. = 0
if userInput~words > 0 then do
  td.0 += 1; r_ = td.0; td.r_ = userInput
  end
else do
  td.0 += 1; r_ = td.0; td.r_ = '-6 -3 -2 -1 0 1 3 4 5 7 8 9 10 11 14 15 17 18 19 20'
  td.0 += 1; r_ = td.0; td.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'
  td.0 += 1; r_ = td.0; td.r_ = '-4, -3, -2, 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

loop r_ = 1 to td.0
  say 'Original: ' td.r_~changestr(',', ' ')~space(1, ',')
  say 'Compacted:' compact(td.r_)
  say
  end r_
return


using Primes

function rajpairs(N, verbose, interval = 2)
    maxpossramanujan(n) = Int(ceil(4n * log(4n) / log(2)))
    prm = primes(maxpossramanujan(N))
    pivec = accumulate(+, primesmask(maxpossramanujan(N)))
    halfrpc = [pivec[p] - pivec[p ÷ 2] for p in prm]
    lastrpc = last(halfrpc) + 1
    for i in length(halfrpc):-1:1
        if halfrpc[i] < lastrpc
            lastrpc = halfrpc[i]
        else
            halfrpc[i] = 0
        end
    end
    rajvec = [prm[i] for i in eachindex(prm) if halfrpc[i] > 0]
    nrajtwins = count(rajvec[i] + interval == rajvec[i + 1] for i in 1:N-1)
    verbose && println("There are $nrajtwins twins in the first $N Ramanujan primes.")
    return nrajtwins
end

rajpairs(100000, false)
@time rajpairs(1000000, true)


$HistoryLength = 1;
l = PrimePi[Range[35 10^6]] - PrimePi[Range[35 10^6]/2];
ramanujanprimes = GatherBy[Transpose[{Range[2, Length[l] + 1], l}], Last][[All, -1, 1]];
ramanujanprimes = Take[[email protected], 10^6];
Count[Differences[ramanujanprimes], 2]


import math, sequtils, strutils, sugar, times

let t0 = now()

type PrimeCounter = seq[int32]

proc initPrimeCounter(limit: Positive): PrimeCounter {.noInit.} =
  doAssert limit > 1
  result = repeat(1i32, limit)
  result[0] = 0
  result[1] = 0
  for i in countup(4, limit - 1, 2): result[i] = 0
  var p = 3
  var p2 = 9
  while p2 < limit:
    if result[p] != 0:
      for q in countup(p2, limit - 1, p + p):
        result[q] = 0
    inc p, 2
    p2 = p * p
  # Compute partial sums in place.
  var sum = 0i32
  for item in result.mitems:
    sum += item
    item = sum

func ramanujanMax(n: int): int {.inline.} = int(ceil(4 * n.toFloat * ln(4 * n.toFloat)))

func ramanujanPrime(pi: PrimeCounter; n: int): int =
  if n == 1: return 2
  var max = ramanujanMax(n)
  if (max and 1) == 1: dec max
  for i in countdown(max, 2, 2):
    if pi[i] - pi[i div 2] < n:
      return i + 1

func primesLe(limit: Positive): seq[int] =
  var composite = newSeq[bool](limit + 1)
  var n = 3
  var n2 = 9
  while n2 <= limit:
    if not composite[n]:
      for k in countup(n2, limit, 2 * n):
        composite[k] = true
    n2 += (n + 1) shl 2
    n += 2
  result = @[2]
  for n in countup(3, limit, 2):
    if not composite[n]: result.add n

proc main() =
  const Lim = 1_000_000
  let pi = initPrimeCounter(1 + ramanujanMax(Lim))
  let rpLim = ramanujanPrime(pi, Lim)
  echo "The 1_000_000th Ramanujan prime is $#.".format(($rpLim).insertSep())
  let r = primesLe(rpLim)
  var c = r.mapIt(pi[it] - pi[it div 2])
  var ok = c[^1]
  for i in countdown(c.len - 2, 0):
    if c[i] < ok:
      ok = c[i]
    else:
      c[i] = 0
  let fr = collect(newSeq, for i, p in r: (if c[i] != 0: p))
  var twins = 0
  var prev = -1
  for p in fr:
    if p == prev + 2: inc twins
    prev = p
  echo "There are $1 twins in the first $2 Ramanujan primes.".format(($twins).insertSep(), ($Lim).insertSep)

main()
echo "\nElapsed time: ", (now() - t0).inMilliseconds, " ms"


use strict;
use warnings;
use ntheory <ramanujan_primes nth_ramanujan_prime>;

sub comma { reverse ((reverse shift) =~ s/(.{3})/$1,/gr) =~ s/^,//r }

my $rp = ramanujan_primes nth_ramanujan_prime 1_000_000;
for my $limit (1e5, 1e6) {
    printf "The %sth Ramanujan prime is %s\n", comma($limit), comma $rp->[$limit-1];
    printf  "There are %s twins in the first %s Ramanujan primes.\n\n",
        comma( scalar grep { $rp->[$_+1] == $rp->[$_]+2 } 0 .. $limit-2 ), comma $limit;
}


with javascript_semantics
sequence pi = {}

procedure primeCounter(integer limit)
    pi = repeat(1,limit)
    if limit > 1 then
        pi[1] = 0
        for i=4 to limit by 2 do
            pi[i] = 0
        end for
        integer p = 3, sq = 9
        while sq<=limit do
            if pi[p]!=0 then
                for q=sq to limit by p*2 do
                    pi[q] = 0
                end for
            end if
            sq += (p + 1)*4
            p += 2
        end while
        atom total = 0
        for i=2 to limit do
            total += pi[i]
            pi[i] = total
        end for
    end if
end procedure

function ramanujanMax(integer n)
    return floor(4*n*log(4*n))
end function

function ramanujanPrime(integer n)
    if n=1 then return 2 end if
    integer maxposs = ramanujanMax(n)
    for i=maxposs-odd(maxposs) to 1 by -2 do
        if pi[i]-pi[floor(i/2)] < n then
            return i + 1
        end if
    end for
    return 0
end function

constant lim = 1e5      -- 0.6s
--constant lim = 1e6    -- 4.7s -- (not pwa/p2js)
atom t0 = time()
primeCounter(ramanujanMax(lim))
integer rplim = ramanujanPrime(lim)
printf(1,"The %,dth Ramanujan prime is %,d\n", {lim,rplim})
function rpc(integer p) return pi[p]-pi[floor(p/2)] end function
sequence r = get_primes_le(rplim),
         c = apply(r,rpc)
integer ok = c[$]
for i=length(c)-1 to 1 by -1 do
    if c[i]<ok then
        ok = c[i]
    else
        c[i] = 0
    end if
end for
function nzc(integer p, idx) return c[idx]!=0 end function
r = filter(r,nzc)
integer twins = 0
for i=1 to length(r)-1 do
    if r[i]+2 = r[i+1] then twins += 1 end if
end for
printf(1,"There are %,d twins in the first %,d Ramanujan primes\n", {twins,length(r)})
?elapsed(time()-t0)


/*REXX program verifies if a   horizontal ray   from   point P   intersects  a polygon. */
call points 5 5,       5 8,       -10  5,       0  5,       10  5,       8  5,       10 10
   A= 2.5;     B= 7.5                      /* ◄───── used for shorter arguments (below).*/
call poly 0 0, 10 0,  10 10,  0 10                             ;   call test 'square'
call poly 0 0, 10 0,  10 10,  0 10,  A  A,   B  A,   B  B, A B ;   call test 'square hole'
call poly 0 0,  A A,   0 10,  A  B,  B  B,  10 10,  10  0      ;   call test 'irregular'
call poly 3 0,  7 0,  10  5,  7 10,  3 10,   0  5              ;   call test 'hexagon'
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
in$out: procedure expose point. poly.;     parse arg p;              #= 0
                     do side=1  to poly.0  by 2;  #= # +intersect(p, side);   end /*side*/
        return # // 2                            /*ODD  is inside.     EVEN  is outside.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
intersect: procedure expose point. poly.;         parse arg ?,s;                 sp= s + 1
           epsilon= '1e'  ||  (-digits() % 2)
           Px= point.?.x;     Ax= poly.s.x;       Bx= poly.sp.x
           Py= point.?.y;     Ay= poly.s.y;       By= poly.sp.y  /* [↓]  do vertex swap.*/
           if Ay>By           then parse  value   Ax Ay Bx By    with    Bx By Ax Ay
           if Py=Ay | Py=By   then Py= Py + epsilon
           if Py<Ay | Py>By | Px>max(Ax, Bx)  then  return 0
           if                 Px<min(Ax, Bx)  then  return 1
           if Ax\=Bx          then red = (By-Ay) / (Bx-Ax)
                              else red = i"1e"  ||  (digits() *2)      /* ◄─── infinity.*/
           if Ax\=Px          then return  (Py-Ay) / (Px-Ax)  >=  red
                              else return  1
/*──────────────────────────────────────────────────────────────────────────────────────*/
points: wx= 0;  wy= 0;   do j=1  for arg();         parse value  arg(j)    with   xx  yy
                         wx= max(wx, length(xx) );  call  value  'POINT.'j".X",   xx
                         wy= max(wy, length(yy) );  call  value  'POINT.'j".Y",       yy
                         end   /*j*/
        call value point.0,  j-1                         /*define the number of points. */
        return                                           /* [↑]  adjust J  (for DO loop)*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
poly:   @= 'POLY.';      parse arg Fx Fy                 /* [↓]  process the X,Y points.*/
        n= 0
                 do j=1  for arg();      n= n + 1;  parse value arg(j)   with   xx yy
                 call value @ || n'.X',  xx ;       call value  @ || n".Y", yy
                 if n//2  then iterate;  n= n + 1        /*Inside? Then skip this point.*/
                 call value @ || n'.X',  xx ;       call value  @ || n".Y", yy
                 end   /*j*/
        n= n + 1                                         /*POLY.0  is # segments(sides).*/
        call value @ || n'.X', Fx;       call value @ || n".Y", Fy;     call value @'0', n
        return
/*──────────────────────────────────────────────────────────────────────────────────────*/
test:   say;     do k=1  for point.0;    w= wx + wy + 2  /*W, WX, WY ≡are various widths*/
                 say right('  ['arg(1)"]  point:",  30),
                     right( right(point.k.x, wx)', 'right(point.k.y, wy), w)     "  is  ",
                     right( word('outside inside',  in$out(k) + 1),  7)
                 end   /*k*/
        return                                           /* [↑] format the output nicely*/


declare
  fun {Extract Xs}
     {CommaSeparated
      {Map {ExtractRanges Xs} RangeToString}}
  end

  fun {ExtractRanges Xs}
     fun {Loop Ys Start End}
        case Ys
        of Y|Yr andthen Y == End+1 then {Loop Yr Start Y}
        [] Y|Yr                    then Start#End|{Loop Yr Y Y}
        [] nil                     then [Start#End]
        end
     end
  in
     case Xs
     of X|Xr then {Loop Xr X X}
     [] nil then nil
     end
  end

  fun {RangeToString S#E}
     if E-S >= 2 then
        {VirtualString.toString S#"-"#E}
     else
        {CommaSeparated
         {Map {List.number S E 1} Int.toString}}
     end
  end

  fun {CommaSeparated Xs}
     {Flatten {Intersperse "," Xs}}
  end

  fun {Intersperse Sep Xs}
     case Xs of X|Y|Xr then
        X|Sep|{Intersperse Sep Y|Xr}
     else
        Xs
     end
  end
in
  {System.showInfo
   {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 ]}}


use ntheory:from<Perl5> <ramanujan_primes nth_ramanujan_prime>;
use Lingua::EN::Numbers;

my @rp = ramanujan_primes nth_ramanujan_prime 1_000_000;

for (1e5, 1e6)».Int -> $limit {
    say "\nThe {comma $limit}th Ramanujan prime is { comma @rp[$limit-1]}";
    say "There are { comma +(^($limit-1)).race.grep: { @rp[$_+1] == @rp[$_]+2 } } twins in the first {comma $limit} Ramanujan primes.";
}

say (now - INIT now).fmt('%.3f') ~ ' seconds';


import "/trait" for Stepped, Indexed
import "/math" for Int, Math
import "/fmt" for Fmt

var count

var primeCounter = Fn.new { |limit|
    count = List.filled(limit, 1)
    if (limit > 0) count[0] = 0
    if (limit > 1) count[1] = 0
    for (i in Stepped.new(4...limit, 2)) count[i] = 0
    var p = 3
    var sq = 9
    while (sq < limit) {
        if (count[p] != 0) {
            var q = sq
            while (q < limit) {
                count[q] = 0
                q = q + p * 2
            }
        }
        sq = sq + (p + 1) * 4
        p = p + 2
    }
    var sum = 0
    for (i in 0...limit) {
        sum = sum + count[i]
        count[i] = sum
    }
}

var primeCount = Fn.new { |n| (n < 1) ? 0 : count[n] }

var ramanujanMax = Fn.new { |n| (4 * n * (4*n).log).ceil }

var ramanujanPrime = Fn.new { |n|
    if (n == 1) return 2
    for (i in ramanujanMax.call(n)..2) {
        if (i % 2 == 1) continue
        if (primeCount.call(i) - primeCount.call((i/2).floor) < n) return i + 1
    }
    return 0
}

var rpc = Fn.new { |p| primeCount.call(p) - primeCount.call((p/2).floor) }

for (limit in [1e5, 1e6]) {
    var start = System.clock
    primeCounter.call(1 + ramanujanMax.call(limit))
    var rplim = ramanujanPrime.call(limit)
    Fmt.print("The $,dth Ramanujan prime is $,d", limit, rplim)
    var r = Int.primeSieve(rplim)
    var c = r.map { |p| rpc.call(p) }.toList
    var ok = c[-1]
    for (i in c.count - 2..0) {
        if (c[i] < ok) {
            ok = c[i]
        } else {
            c[i] = 0
        }
    }
    var ir = Indexed.new(r).where { |se| c[se.index] != 0 }.toList
    var twins = 0
    for (i in 0...ir.count-1) {
        if (ir[i].value + 2 == ir[i+1].value) twins = twins + 1
    }
    Fmt.print("There are $,d twins in the first $,d Ramanujan primes.", twins, limit)
    System.print("Took %(Math.toPlaces(System.clock -start, 2, 0)) seconds.\n")
}


use std::f64;

const _EPS: f64 = 0.00001;
const _MIN: f64 = f64::MIN_POSITIVE;
const _MAX: f64 = f64::MAX;

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

#[derive(Clone)]
struct Edge {
    pt1: Point,
    pt2: Point,
}

impl Edge {
    fn new(pt1: (f64, f64), pt2: (f64, f64)) -> Edge {
        Edge {
            pt1: Point { x: pt1.0, y: pt1.1 },
            pt2: Point { x: pt2.0, y: pt2.1 },
        }
    }
}

struct Polygon {
    edges: Vec<Edge>, // Polygon has to be created with counter-clockwise coordinates
}

fn pt_in_polygon(pt: &Point, poly: &Polygon) -> bool {
    let count = poly.edges
        .iter()
        .filter(|edge| ray_intersect_seg(pt, edge))
        .count();

    count % 2 == 1
}

fn ray_intersect_seg(p: &Point, edge: &Edge) -> bool {
    let mut pt = p.clone();
    let (mut a, mut b): (&Point, &Point) = (&edge.pt1, &edge.pt2);
    if a.y > b.y {
        std::mem::swap(&mut a, &mut b);
    }
    if pt.y == a.y || pt.y == b.y {
        pt.y += _EPS;
    }

    if (pt.y > b.y || pt.y < a.y) || pt.x > a.x.max(b.x) {
        false
    } else if pt.x < a.x.min(b.x) {
        true
    } else {
        let m_red = if (a.x - b.x).abs() > _MIN {
            (b.y - a.y) / (b.x - a.x)
        } else {
            _MAX
        };
        let m_blue = if (a.x - pt.x).abs() > _MIN {
            (pt.y - a.y) / (pt.x - a.x)
        } else {
            _MAX
        };
        m_blue >= m_red
    }
}

fn main() {
    let p = |x, y| Point { x, y };
    let testpoints = [p(5.0, 5.0), p(5.0, 8.0), p(-10.0, 5.0), p(0.0, 5.0), p(10.0, 5.0), p(8.0, 5.0), p(10.0, 10.0)];
    let poly_square = Polygon {
        edges: vec![
            Edge::new((0.0, 0.0), (10.0, 0.0)),
            Edge::new((10.0, 0.0), (10.0, 10.0)),
            Edge::new((10.0, 10.0), (0.0, 10.0)),
            Edge::new((0.0, 10.0), (0.0, 0.0)),
        ],
    };
    let poly_square_hole = Polygon {
        edges: vec![
            Edge::new((0.0, 0.0), (10.0, 0.0)),
            Edge::new((10.0, 0.0), (10.0, 10.0)),
            Edge::new((10.0, 10.0), (0.0, 10.0)),
            Edge::new((0.0, 10.0), (0.0, 0.0)),
            Edge::new((2.5, 2.5), (7.5, 2.5)),
            Edge::new((7.5, 2.5), (7.5, 7.5)),
            Edge::new((7.5, 7.5), (2.5, 7.5)),
            Edge::new((2.5, 7.5), (2.5, 2.5)),
        ],
    };
    let poly_strange = Polygon {
        edges: vec![
            Edge::new((0.0, 0.0), (2.5, 2.5)),
            Edge::new((2.5, 2.5), (0.0, 10.0)),
            Edge::new((0.0, 10.0), (2.5, 7.5)),
            Edge::new((2.5, 7.5), (7.5, 7.5)),
            Edge::new((7.5, 7.5), (10.0, 10.0)),
            Edge::new((10.0, 10.0), (10.0, 0.0)),
            Edge::new((10.0, 0.0), (2.5, 2.5)),
        ],
    };
    let poly_hexagon = Polygon {
        edges: vec![
            Edge::new((3.0, 0.0), (7.0, 0.0)),
            Edge::new((7.0, 0.0), (10.0, 5.0)),
            Edge::new((10.0, 5.0), (7.0, 10.0)),
            Edge::new((7.0, 10.0), (3.0, 10.0)),
            Edge::new((3.0, 10.0), (0.0, 5.0)),
            Edge::new((0.0, 5.0), (3.0, 0.0)),
        ],
    };
    print!("\nSquare :");
    for pt in &testpoints {
        print!(" {:?}", pt_in_polygon(pt, &poly_square));
    }
    print!("\nSquare with hole:");
    for pt in &testpoints {
        print!(" {:?}", pt_in_polygon(pt, &poly_square_hole));
    }
    print!("\nStrange polygon :");
    for pt in &testpoints {
        print!(" {:?}", pt_in_polygon(pt, &poly_strange));
    }
    print!("\nHexagon :");
    for pt in &testpoints {
        print!(" {:?}", pt_in_polygon(pt, &poly_hexagon));
    }
    println!();
}


program RangeExtractionApp;

{$IFDEF FPC}
  {$mode objfpc}{$H+}
{$ENDIF}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  SysUtils;

function RangeExtraction(const Seq: array of integer): String;
const
  SubSeqLen = 3; // minimal length of the range, can be changed.
var
  i, j: Integer;
  Separator: string;
begin
  Separator:= '';
  Result := '';
  i := Low(Seq);
  while i <= High(Seq) do
  begin
    j := i;
    // All subsequent values, starting from i, up to High(Seq) possibly
    while ((j < High(Seq)) and ((Seq[j+1]-Seq[j]) = 1)) do
      Inc(j);
    // is it a range ?
    if ((j-i) >= (SubSeqLen-1)) then
    begin
      Result := Result + Format(Separator+'%d-%d',[Seq[i],Seq[j]]);
      i := j+1; // Next value to be processed
      Separator := ',';
    end
    else
    begin
      // Loop, to process the case SubSeqLen > 3
      while i<=j do
      begin
        Result := Result + Format(Separator+'%d',[Seq[i]]);
        Inc(i); // Next value to be processed
        Separator := ',';
      end;
    end;
  end;
End;

procedure DisplayRange(const Seq: array of integer);
var
  i: Integer;
begin
  Write(Format('[%d', [Seq[Low(Seq)]]));
  for i := Low(Seq) + 1 to High(Seq) do
    Write(Format(',%d', [Seq[i]]));
  WriteLn('] => ' + RangeExtraction(Seq));
  WriteLn;
End;

begin
  DisplayRange([0]);
  DisplayRange([0,1]);
  DisplayRange([0,2]);
  DisplayRange([0,1,2]);
  DisplayRange([0,1,2,3]);
  DisplayRange([0,1,2,3,4,5,6,7]);
  DisplayRange([0,2,3,4,5,6,7,9]);
  DisplayRange([0,2,4,6,8,10]);
  DisplayRange([0,1,2,3,4,5,6,7,9]);
  DisplayRange([0,1,2,3,4,6,9,10,11,12]);

  DisplayRange([
      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]);
  {$IFNDEF UNIX}readln;{$ENDIF}
end.