(use posix)
(seconds->string (current-seconds))


$ include "seed7_05.s7i";
  include "time.s7i";

const proc: main is func
  begin
    writeln(time(NOW));
  end func;


$ Unix time
print(tod);

$ Human readable time and date
print(date);


# textual
say Time.local.ctime;        # => Thu Mar 19 15:10:41 2015

# epoch time
say Time.sec;                # => 1426770641

# epoch time with fractional seconds
say Time.micro_sec;          # => 1426770641.68409


hour,min,sec = #.now()
day,month,year = #.today()

#.output(#.str(hour,"00:"),#.str(min,"00:"),#.str(sec,"00.000"))
#.output(day,".",#.str(month,"00"),".",year)


SELECT CURRENT DATE, CURRENT TIME, CURRENT TIMESTAMP FROM SYSIBM.SYSDUMMY1;


print (Date.toString (Date.fromTimeLocal (Time.now ())) ^ "\n")


import Foundation

var ⌚ = NSDate()
println(⌚)


PRINT DATE$
! returns SYSTEM date in format: “YYYYMMDD”.
! Here YYYY IS the year, MM IS the month number, AND DD IS the day number.

PRINT TIME$
! returns SYSTEM time in format: “HH:MM:SS”.
END


date       # Thu Dec  3 15:38:06 PST 2009

date +%s   # 1259883518, seconds since the epoch, like C stdlib time(0)


# outputs time in milliseconds
import "time"
out (time.getcurrent) endl console


var now = new DateTime.now_local();
string now_string = now.to_string();


import time

fn main() {
    t := time.Now()
    println(t)                                    // default format YYYY-MM-DD HH:MM:SS
    println(t.custom_format("ddd MMM d HH:mm:ss YYYY")) // some custom format
}


import "os" for Process
import "/date" for Date

var args = Process.arguments
if (args.count != 1) Fiber.abort("Please pass the current time in hh:mm:ss format.")
var startTime = Date.parse(args[0], Date.isoTime)
for (i in 0..1e8) {} // do something which takes a bit of time
var now = startTime.addMillisecs((System.clock * 1000).round)
Date.default = Date.isoTime + "|.|ttt"
System.print("Time now is %(now)")


include c:\cxpl\codes;          \include intrinsic 'code' declarations

proc NumOut(N);                 \Output a 2-digit number, including leading zero
int  N;
[if N <= 9 then ChOut(0, ^0);
IntOut(0, N);
]; \NumOut

int Reg;
[Reg:= GetReg;                  \get address of array with copy of CPU registers
Reg(0):= $2C00;                 \call DOS function 2C (hex)
SoftInt($21);                   \DOS calls are interrupt 21 (hex)
NumOut(Reg(2) >> 8);            \the high byte of register CX contains the hours
ChOut(0, ^:);
NumOut(Reg(2) & $00FF);         \the low byte of CX contains the minutes
ChOut(0, ^:);
NumOut(Reg(3) >> 8);            \the high byte of DX contains the seconds
ChOut(0, ^.);
NumOut(Reg(3) & $00FF);         \the low byte of DX contains hundreths
CrLf(0);
]


Time.Clock.time //-->seconds since the epoch (C/OS defined)


F clip(subjectPolygon, clipPolygon)
   F inside(p, cp1, cp2)
      R (cp2.x - cp1.x) * (p.y - cp1.y) > (cp2.y - cp1.y) * (p.x - cp1.x)

   F computeIntersection(s, e, cp1, cp2)
      V dc = cp1 - cp2
      V dp = s - e
      V n1 = cp1.x * cp2.y - cp1.y * cp2.x
      V n2 = s.x * e.y - s.y * e.x
      V n3 = 1.0 / (dc.x * dp.y - dc.y * dp.x)
      R ((n1 * dp.x - n2 * dc.x) * n3, (n1 * dp.y - n2 * dc.y) * n3)

   V outputList = subjectPolygon
   V cp1 = clipPolygon.last

   L(clipVertex) clipPolygon
      V cp2 = clipVertex
      V inputList = outputList
      outputList.clear()
      V s = inputList.last

      L(subjectVertex) inputList
         V e = subjectVertex
         I inside(e, cp1, cp2)
            I !inside(s, cp1, cp2)
               outputList.append(computeIntersection(s, e, cp1, cp2))
            outputList.append(e)
         E I inside(s, cp1, cp2)
            outputList.append(computeIntersection(s, e, cp1, cp2))
         s = e
      cp1 = cp2
   R (outputList)

V subjectp = [(50.0, 150.0), (200.0, 50.0), (350.0, 150.0), (350.0, 300.0), (250.0, 300.0), (200.0, 250.0), (150.0, 350.0), (100.0, 250.0), (100.0, 200.0)]
V clipp = [(100.0, 100.0), (300.0, 100.0), (300.0, 300.0), (100.0, 300.0)]
print_elements(clip(subjectp, clipp), sep' "\n")


with Ada.Containers.Doubly_Linked_Lists;
with Ada.Text_IO;

procedure Main is
   package FIO is new Ada.Text_IO.Float_IO (Float);

   type Point is record
      X, Y : Float;
   end record;

   function "-" (Left, Right : Point) return Point is
   begin
      return (Left.X - Right.X, Left.Y - Right.Y);
   end "-";

   type Edge is array (1 .. 2) of Point;

   package Point_Lists is new Ada.Containers.Doubly_Linked_Lists
     (Element_Type => Point);
   use type Point_Lists.List;
   subtype Polygon is Point_Lists.List;

   function Inside (P : Point; E : Edge) return Boolean is
   begin
      return (E (2).X - E (1).X) * (P.Y - E (1).Y) >
             (E (2).Y - E (1).Y) * (P.X - E (1).X);
   end Inside;

   function Intersecton (P1, P2 : Point; E : Edge) return Point is
      DE : Point := E (1) - E (2);
      DP : Point := P1 - P2;
      N1 : Float := E (1).X * E (2).Y - E (1).Y * E (2).X;
      N2 : Float := P1.X * P2.Y - P1.Y * P2.X;
      N3 : Float := 1.0 / (DE.X * DP.Y - DE.Y * DP.X);
   begin
      return ((N1 * DP.X - N2 * DE.X) * N3, (N1 * DP.Y - N2 * DE.Y) * N3);
   end Intersecton;

   function Clip (P, C : Polygon) return Polygon is
      use Point_Lists;
      A, B, S, E : Cursor;
      Inputlist  : List;
      Outputlist : List := P;
      AB         : Edge;
   begin
      A := C.First;
      B := C.Last;
      while A /= No_Element loop
         AB        := (Element (B), Element (A));
         Inputlist := Outputlist;
         Outputlist.Clear;
         S := Inputlist.Last;
         E := Inputlist.First;
         while E /= No_Element loop
            if Inside (Element (E), AB) then
               if not Inside (Element (S), AB) then
                  Outputlist.Append
                    (Intersecton (Element (S), Element (E), AB));
               end if;
               Outputlist.Append (Element (E));
            elsif Inside (Element (S), AB) then
               Outputlist.Append
                 (Intersecton (Element (S), Element (E), AB));
            end if;
            S := E;
            E := Next (E);
         end loop;
         B := A;
         A := Next (A);
      end loop;
      return Outputlist;
   end Clip;

   procedure Print (P : Polygon) is
      use Point_Lists;
      C : Cursor := P.First;
   begin
      Ada.Text_IO.Put_Line ("{");
      while C /= No_Element loop
         Ada.Text_IO.Put (" (");
         FIO.Put (Element (C).X, Exp => 0);
         Ada.Text_IO.Put (',');
         FIO.Put (Element (C).Y, Exp => 0);
         Ada.Text_IO.Put (')');
         C := Next (C);
         if C /= No_Element then
            Ada.Text_IO.Put (',');
         end if;
         Ada.Text_IO.New_Line;
      end loop;
      Ada.Text_IO.Put_Line ("}");
   end Print;

   Source  : Polygon;
   Clipper : Polygon;
   Result  : Polygon;
begin
   Source.Append ((50.0, 150.0));
   Source.Append ((200.0, 50.0));
   Source.Append ((350.0, 150.0));
   Source.Append ((350.0, 300.0));
   Source.Append ((250.0, 300.0));
   Source.Append ((200.0, 250.0));
   Source.Append ((150.0, 350.0));
   Source.Append ((100.0, 250.0));
   Source.Append ((100.0, 200.0));
   Clipper.Append ((100.0, 100.0));
   Clipper.Append ((300.0, 100.0));
   Clipper.Append ((300.0, 300.0));
   Clipper.Append ((100.0, 300.0));
   Result := Clip (Source, Clipper);
   Print (Result);
end Main;


      VDU 23,22,200;200;8,16,16,128
      VDU 23,23,2;0;0;0;

      DIM SubjPoly{(8) x, y}
      DIM ClipPoly{(3) x, y}
      FOR v% = 0 TO 8 : READ SubjPoly{(v%)}.x, SubjPoly{(v%)}.y : NEXT
      DATA 50,150,200,50,350,150,350,300,250,300,200,250,150,350,100,250,100,200
      FOR v% = 0 TO 3 : READ ClipPoly{(v%)}.x, ClipPoly{(v%)}.y : NEXT
      DATA 100,100, 300,100, 300,300, 100,300

      GCOL 4 : PROCplotpoly(SubjPoly{()}, 9)
      GCOL 1 : PROCplotpoly(ClipPoly{()}, 4)
      nvert% = FNsutherland_hodgman(SubjPoly{()}, ClipPoly{()}, Clipped{()})
      GCOL 2 : PROCplotpoly(Clipped{()}, nvert%)
      END

      DEF FNsutherland_hodgman(subj{()}, clip{()}, RETURN out{()})
      LOCAL i%, j%, n%, o%, p1{}, p2{}, s{}, e{}, p{}, inp{()}
      DIM p1{x,y}, p2{x,y}, s{x,y}, e{x,y}, p{x,y}
      n% = DIM(subj{()},1) + DIM(clip{()},1)
      DIM inp{(n%) x, y}, out{(n%) x,y}
      FOR o% = 0 TO DIM(subj{()},1) : out{(o%)} = subj{(o%)} : NEXT
      p1{} = clip{(DIM(clip{()},1))}
      FOR i% = 0 TO DIM(clip{()},1)
        p2{} = clip{(i%)}
        FOR n% = 0 TO o% - 1 : inp{(n%)} = out{(n%)} : NEXT : o% = 0
        IF n% >= 2 THEN
          s{} = inp{(n% - 1)}
          FOR j% = 0 TO n% - 1
            e{} = inp{(j%)}
            IF FNside(e{}, p1{}, p2{}) THEN
              IF NOT FNside(s{}, p1{}, p2{}) THEN
                PROCintersection(p1{}, p2{}, s{}, e{}, p{})
                out{(o%)} = p{}
                o% += 1
              ENDIF
              out{(o%)} = e{}
              o% += 1
            ELSE
              IF FNside(s{}, p1{}, p2{}) THEN
                PROCintersection(p1{}, p2{}, s{}, e{}, p{})
                out{(o%)} = p{}
                o% += 1
              ENDIF
            ENDIF
            s{} = e{}
          NEXT
        ENDIF
        p1{} = p2{}
      NEXT i%
      = o%

      REM Which side of the line p1-p2 is the point p?
      DEF FNside(p{}, p1{}, p2{})
      =  (p2.x - p1.x) * (p.y - p1.y) > (p2.y - p1.y) * (p.x - p1.x)

      REM Find the intersection of two lines p1-p2 and p3-p4
      DEF PROCintersection(p1{}, p2{}, p3{}, p4{}, p{})
      LOCAL a{}, b{}, k, l, m : DIM a{x,y}, b{x,y}
      a.x = p1.x - p2.x : a.y = p1.y - p2.y
      b.x = p3.x - p4.x : b.y = p3.y - p4.y
      k = p1.x * p2.y - p1.y * p2.x
      l = p3.x * p4.y - p3.y * p4.x
      m = 1 / (a.x * b.y - a.y * b.x)
      p.x =  m * (k * b.x - l * a.x)
      p.y =  m * (k * b.y - l * a.y)
      ENDPROC

      REM plot a polygon
      DEF PROCplotpoly(poly{()}, n%)
      LOCAL i%
      MOVE poly{(0)}.x, poly{(0)}.y
      FOR i% = 1 TO n%-1
        DRAW poly{(i%)}.x, poly{(i%)}.y
      NEXT
      DRAW poly{(0)}.x, poly{(0)}.y
      ENDPROC


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

typedef struct { double x, y; } vec_t, *vec;

inline double dot(vec a, vec b)
{
	return a->x * b->x + a->y * b->y;
}

inline double cross(vec a, vec b)
{
	return a->x * b->y - a->y * b->x;
}

inline vec vsub(vec a, vec b, vec res)
{
	res->x = a->x - b->x;
	res->y = a->y - b->y;
	return res;
}

/* tells if vec c lies on the left side of directed edge a->b
 * 1 if left, -1 if right, 0 if colinear
 */
int left_of(vec a, vec b, vec c)
{
	vec_t tmp1, tmp2;
	double x;
	vsub(b, a, &tmp1);
	vsub(c, b, &tmp2);
	x = cross(&tmp1, &tmp2);
	return x < 0 ? -1 : x > 0;
}

int line_sect(vec x0, vec x1, vec y0, vec y1, vec res)
{
	vec_t dx, dy, d;
	vsub(x1, x0, &dx);
	vsub(y1, y0, &dy);
	vsub(x0, y0, &d);
	/* x0 + a dx = y0 + b dy ->
	   x0 X dx = y0 X dx + b dy X dx ->
	   b = (x0 - y0) X dx / (dy X dx) */
	double dyx = cross(&dy, &dx);
	if (!dyx) return 0;
	dyx = cross(&d, &dx) / dyx;
	if (dyx <= 0 || dyx >= 1) return 0;

	res->x = y0->x + dyx * dy.x;
	res->y = y0->y + dyx * dy.y;
	return 1;
}

/* === polygon stuff === */
typedef struct { int len, alloc; vec v; } poly_t, *poly;

poly poly_new()
{
	return (poly)calloc(1, sizeof(poly_t));
}

void poly_free(poly p)
{
	free(p->v);
	free(p);
}

void poly_append(poly p, vec v)
{
	if (p->len >= p->alloc) {
		p->alloc *= 2;
		if (!p->alloc) p->alloc = 4;
		p->v = (vec)realloc(p->v, sizeof(vec_t) * p->alloc);
	}
	p->v[p->len++] = *v;
}

/* this works only if all of the following are true:
 *   1. poly has no colinear edges;
 *   2. poly has no duplicate vertices;
 *   3. poly has at least three vertices;
 *   4. poly is convex (implying 3).
*/
int poly_winding(poly p)
{
	return left_of(p->v, p->v + 1, p->v + 2);
}

void poly_edge_clip(poly sub, vec x0, vec x1, int left, poly res)
{
	int i, side0, side1;
	vec_t tmp;
	vec v0 = sub->v + sub->len - 1, v1;
	res->len = 0;

	side0 = left_of(x0, x1, v0);
	if (side0 != -left) poly_append(res, v0);

	for (i = 0; i < sub->len; i++) {
		v1 = sub->v + i;
		side1 = left_of(x0, x1, v1);
		if (side0 + side1 == 0 && side0)
			/* last point and current straddle the edge */
			if (line_sect(x0, x1, v0, v1, &tmp))
				poly_append(res, &tmp);
		if (i == sub->len - 1) break;
		if (side1 != -left) poly_append(res, v1);
		v0 = v1;
		side0 = side1;
	}
}

poly poly_clip(poly sub, poly clip)
{
	int i;
	poly p1 = poly_new(), p2 = poly_new(), tmp;

	int dir = poly_winding(clip);
	poly_edge_clip(sub, clip->v + clip->len - 1, clip->v, dir, p2);
	for (i = 0; i < clip->len - 1; i++) {
		tmp = p2; p2 = p1; p1 = tmp;
		if(p1->len == 0) {
			p2->len = 0;
			break;
		}
		poly_edge_clip(p1, clip->v + i, clip->v + i + 1, dir, p2);
	}

	poly_free(p1);
	return p2;
}

int main()
{
	int i;
	vec_t c[] = {{100,100}, {300,100}, {300,300}, {100,300}};
	//vec_t c[] = {{100,300}, {300,300}, {300,100}, {100,100}};
	vec_t s[] = {	{50,150}, {200,50}, {350,150},
			{350,300},{250,300},{200,250},
			{150,350},{100,250},{100,200}};
#define clen (sizeof(c)/sizeof(vec_t))
#define slen (sizeof(s)/sizeof(vec_t))
	poly_t clipper = {clen, 0, c};
	poly_t subject = {slen, 0, s};

	poly res = poly_clip(&subject, &clipper);

	for (i = 0; i < res->len; i++)
		printf("%g %g\n", res->v[i].x, res->v[i].y);

	/* long and arduous EPS printout */
	FILE * eps = fopen("test.eps", "w");
	fprintf(eps, "%%!PS-Adobe-3.0\n%%%%BoundingBox: 40 40 360 360\n"
		"/l {lineto} def /m{moveto} def /s{setrgbcolor} def"
		"/c {closepath} def /gs {fill grestore stroke} def\n");
	fprintf(eps, "0 setlinewidth %g %g m ", c[0].x, c[0].y);
	for (i = 1; i < clen; i++)
		fprintf(eps, "%g %g l ", c[i].x, c[i].y);
	fprintf(eps, "c .5 0 0 s gsave 1 .7 .7 s gs\n");

	fprintf(eps, "%g %g m ", s[0].x, s[0].y);
	for (i = 1; i < slen; i++)
		fprintf(eps, "%g %g l ", s[i].x, s[i].y);
	fprintf(eps, "c 0 .2 .5 s gsave .4 .7 1 s gs\n");

	fprintf(eps, "2 setlinewidth [10 8] 0 setdash %g %g m ",
		res->v[0].x, res->v[0].y);
	for (i = 1; i < res->len; i++)
		fprintf(eps, "%g %g l ", res->v[i].x, res->v[i].y);
	fprintf(eps, "c .5 0 .5 s gsave .7 .3 .8 s gs\n");

	fprintf(eps, "%%%%EOF");
	fclose(eps);
	printf("test.eps written\n");

	return 0;
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace Sutherland
{
    public static class SutherlandHodgman
    {
        #region Class: Edge

        /// <summary>
        /// This represents a line segment
        /// </summary>
        private class Edge
        {
            public Edge(Point from, Point to)
            {
                this.From = from;
                this.To = to;
            }

            public readonly Point From;
            public readonly Point To;
        }

        #endregion

        /// <summary>
        /// This clips the subject polygon against the clip polygon (gets the intersection of the two polygons)
        /// </summary>
        /// <remarks>
        /// Based on the psuedocode from:
        /// http://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman
        /// </remarks>
        /// <param name="subjectPoly">Can be concave or convex</param>
        /// <param name="clipPoly">Must be convex</param>
        /// <returns>The intersection of the two polygons (or null)</returns>
        public static Point[] GetIntersectedPolygon(Point[] subjectPoly, Point[] clipPoly)
        {
            if (subjectPoly.Length < 3 || clipPoly.Length < 3)
            {
                throw new ArgumentException(string.Format("The polygons passed in must have at least 3 points: subject={0}, clip={1}", subjectPoly.Length.ToString(), clipPoly.Length.ToString()));
            }

            List<Point> outputList = subjectPoly.ToList();

            //	Make sure it's clockwise
            if (!IsClockwise(subjectPoly))
            {
                outputList.Reverse();
            }

            //	Walk around the clip polygon clockwise
            foreach (Edge clipEdge in IterateEdgesClockwise(clipPoly))
            {
                List<Point> inputList = outputList.ToList();		//	clone it
                outputList.Clear();

                if (inputList.Count == 0)
                {
                    //	Sometimes when the polygons don't intersect, this list goes to zero.  Jump out to avoid an index out of range exception
                    break;
                }

                Point S = inputList[inputList.Count - 1];

                foreach (Point E in inputList)
                {
                    if (IsInside(clipEdge, E))
                    {
                        if (!IsInside(clipEdge, S))
                        {
                            Point? point = GetIntersect(S, E, clipEdge.From, clipEdge.To);
                            if (point == null)
                            {
                                throw new ApplicationException("Line segments don't intersect");		//	may be colinear, or may be a bug
                            }
                            else
                            {
                                outputList.Add(point.Value);
                            }
                        }

                        outputList.Add(E);
                    }
                    else if (IsInside(clipEdge, S))
                    {
                        Point? point = GetIntersect(S, E, clipEdge.From, clipEdge.To);
                        if (point == null)
                        {
                            throw new ApplicationException("Line segments don't intersect");		//	may be colinear, or may be a bug
                        }
                        else
                        {
                            outputList.Add(point.Value);
                        }
                    }

                    S = E;
                }
            }

            //	Exit Function
            return outputList.ToArray();
        }

        #region Private Methods

        /// <summary>
        /// This iterates through the edges of the polygon, always clockwise
        /// </summary>
        private static IEnumerable<Edge> IterateEdgesClockwise(Point[] polygon)
        {
            if (IsClockwise(polygon))
            {
                #region Already clockwise

                for (int cntr = 0; cntr < polygon.Length - 1; cntr++)
                {
                    yield return new Edge(polygon[cntr], polygon[cntr + 1]);
                }

                yield return new Edge(polygon[polygon.Length - 1], polygon[0]);

                #endregion
            }
            else
            {
                #region Reverse

                for (int cntr = polygon.Length - 1; cntr > 0; cntr--)
                {
                    yield return new Edge(polygon[cntr], polygon[cntr - 1]);
                }

                yield return new Edge(polygon[0], polygon[polygon.Length - 1]);

                #endregion
            }
        }

        /// <summary>
        /// Returns the intersection of the two lines (line segments are passed in, but they are treated like infinite lines)
        /// </summary>
        /// <remarks>
        /// Got this here:
        /// http://stackoverflow.com/questions/14480124/how-do-i-detect-triangle-and-rectangle-intersection
        /// </remarks>
        private static Point? GetIntersect(Point line1From, Point line1To, Point line2From, Point line2To)
        {
            Vector direction1 = line1To - line1From;
            Vector direction2 = line2To - line2From;
            double dotPerp = (direction1.X * direction2.Y) - (direction1.Y * direction2.X);

            // If it's 0, it means the lines are parallel so have infinite intersection points
            if (IsNearZero(dotPerp))
            {
                return null;
            }

            Vector c = line2From - line1From;
            double t = (c.X * direction2.Y - c.Y * direction2.X) / dotPerp;
            //if (t < 0 || t > 1)
            //{
            //    return null;		//	lies outside the line segment
            //}

            //double u = (c.X * direction1.Y - c.Y * direction1.X) / dotPerp;
            //if (u < 0 || u > 1)
            //{
            //    return null;		//	lies outside the line segment
            //}

            //	Return the intersection point
            return line1From + (t * direction1);
        }

        private static bool IsInside(Edge edge, Point test)
        {
            bool? isLeft = IsLeftOf(edge, test);
            if (isLeft == null)
            {
                //	Colinear points should be considered inside
                return true;
            }

            return !isLeft.Value;
        }
        private static bool IsClockwise(Point[] polygon)
        {
            for (int cntr = 2; cntr < polygon.Length; cntr++)
            {
                bool? isLeft = IsLeftOf(new Edge(polygon[0], polygon[1]), polygon[cntr]);
                if (isLeft != null)		//	some of the points may be colinear.  That's ok as long as the overall is a polygon
                {
                    return !isLeft.Value;
                }
            }

            throw new ArgumentException("All the points in the polygon are colinear");
        }

        /// <summary>
        /// Tells if the test point lies on the left side of the edge line
        /// </summary>
        private static bool? IsLeftOf(Edge edge, Point test)
        {
            Vector tmp1 = edge.To - edge.From;
            Vector tmp2 = test - edge.To;

            double x = (tmp1.X * tmp2.Y) - (tmp1.Y * tmp2.X);		//	dot product of perpendicular?

            if (x < 0)
            {
                return false;
            }
            else if (x > 0)
            {
                return true;
            }
            else
            {
                //	Colinear points;
                return null;
            }
        }

        private static bool IsNearZero(double testValue)
        {
            return Math.Abs(testValue) <= .000000001d;
        }

        #endregion
    }
}


#include <iostream>

using namespace std;

struct point2D { float x, y; };

const int   N = 99; // clipped (new) polygon size

// check if a point is on the LEFT side of an edge
bool inside(point2D p, point2D p1, point2D p2)
{
    return (p2.y - p1.y) * p.x + (p1.x - p2.x) * p.y + (p2.x * p1.y - p1.x * p2.y) < 0;
}

// calculate intersection point
point2D intersection(point2D cp1, point2D cp2, point2D s, point2D e)
{
    point2D dc = { cp1.x - cp2.x, cp1.y - cp2.y };
    point2D dp = { s.x - e.x, s.y - e.y };

    float n1 = cp1.x * cp2.y - cp1.y * cp2.x;
    float n2 = s.x * e.y - s.y * e.x;
    float n3 = 1.0 / (dc.x * dp.y - dc.y * dp.x);

    return { (n1 * dp.x - n2 * dc.x) * n3, (n1 * dp.y - n2 * dc.y) * n3 };
}

// Sutherland-Hodgman clipping
void SutherlandHodgman(point2D *subjectPolygon, int &subjectPolygonSize, point2D *clipPolygon, int &clipPolygonSize, point2D (&newPolygon)[N], int &newPolygonSize)
{
    point2D cp1, cp2, s, e, inputPolygon[N];

    // copy subject polygon to new polygon and set its size
    for(int i = 0; i < subjectPolygonSize; i++)
        newPolygon[i] = subjectPolygon[i];

    newPolygonSize = subjectPolygonSize;

    for(int j = 0; j < clipPolygonSize; j++)
    {
        // copy new polygon to input polygon & set counter to 0
        for(int k = 0; k < newPolygonSize; k++){ inputPolygon[k] = newPolygon[k]; }
        int counter = 0;

        // get clipping polygon edge
        cp1 = clipPolygon[j];
        cp2 = clipPolygon[(j + 1) % clipPolygonSize];

        for(int i = 0; i < newPolygonSize; i++)
        {
            // get subject polygon edge
            s = inputPolygon[i];
            e = inputPolygon[(i + 1) % newPolygonSize];

            // Case 1: Both vertices are inside:
            // Only the second vertex is added to the output list
            if(inside(s, cp1, cp2) && inside(e, cp1, cp2))
                newPolygon[counter++] = e;

            // Case 2: First vertex is outside while second one is inside:
            // Both the point of intersection of the edge with the clip boundary
            // and the second vertex are added to the output list
            else if(!inside(s, cp1, cp2) && inside(e, cp1, cp2))
            {
                newPolygon[counter++] = intersection(cp1, cp2, s, e);
                newPolygon[counter++] = e;
            }

            // Case 3: First vertex is inside while second one is outside:
            // Only the point of intersection of the edge with the clip boundary
            // is added to the output list
            else if(inside(s, cp1, cp2) && !inside(e, cp1, cp2))
                newPolygon[counter++] = intersection(cp1, cp2, s, e);

            // Case 4: Both vertices are outside
            else if(!inside(s, cp1, cp2) && !inside(e, cp1, cp2))
            {
                // No vertices are added to the output list
            }
        }
        // set new polygon size
        newPolygonSize = counter;
    }
}

int main(int argc, char** argv)
{
    // subject polygon
    point2D subjectPolygon[] = {
	{50,150}, {200,50}, {350,150},
        {350,300},{250,300},{200,250},
        {150,350},{100,250},{100,200}
    };
    int subjectPolygonSize = sizeof(subjectPolygon) / sizeof(subjectPolygon[0]);

    // clipping polygon
    point2D clipPolygon[] = { {100,100}, {300,100}, {300,300}, {100,300} };
    int clipPolygonSize = sizeof(clipPolygon) / sizeof(clipPolygon[0]);

    // define the new clipped polygon (empty)
    int newPolygonSize = 0;
    point2D newPolygon[N] = { 0 };

    // apply clipping
    SutherlandHodgman(subjectPolygon, subjectPolygonSize, clipPolygon, clipPolygonSize, newPolygon, newPolygonSize);

    // print clipped polygon points
    cout << "Clipped polygon points:" << endl;
    for(int i = 0; i < newPolygonSize; i++)
        cout << "(" << newPolygon[i].x << ", " << newPolygon[i].y << ")" << endl;

    return 0;
}


import std.stdio, std.array, std.range, std.typecons, std.algorithm;

struct Vec2 { // To be replaced with Phobos code.
    double x, y;

    Vec2 opBinary(string op="-")(in Vec2 other)
    const pure nothrow @safe @nogc {
        return Vec2(this.x - other.x, this.y - other.y);
    }

    typeof(x) cross(in Vec2 other) const pure nothrow @safe @nogc {
        return this.x * other.y - this.y * other.x;
    }
}

immutable(Vec2)[] clip(in Vec2[] subjectPolygon, in Vec2[] clipPolygon)
pure /*nothrow*/ @safe in {
    assert(subjectPolygon.length > 1);
    assert(clipPolygon.length > 1);
    // Probably clipPolygon needs to be convex and probably
    // its vertices need to be listed in a direction.
} out(result) {
    assert(result.length > 1);
} body {
    alias Edge = Tuple!(Vec2,"p", Vec2,"q");

    static enum isInside = (in Vec2 p, in Edge cle)
    pure nothrow @safe @nogc =>
        (cle.q.x - cle.p.x) * (p.y - cle.p.y) >
        (cle.q.y - cle.p.y) * (p.x - cle.p.x);

    static Vec2 intersection(in Edge se, in Edge cle)
    pure nothrow @safe @nogc {
        immutable dc = cle.p - cle.q;
        immutable dp = se.p - se.q;
        immutable n1 = cle.p.cross(cle.q);
        immutable n2 = se.p.cross(se.q);
        immutable n3 = 1.0 / dc.cross(dp);
        return Vec2((n1 * dp.x - n2 * dc.x) * n3,
                    (n1 * dp.y - n2 * dc.y) * n3);
    }

    // How much slower is this compared to lower-level code?
    static enum edges = (in Vec2[] poly) pure nothrow @safe @nogc =>
        // poly[$ - 1 .. $].chain(poly).zip!Edge(poly);
        poly[$ - 1 .. $].chain(poly).zip(poly).map!Edge;

    immutable(Vec2)[] result = subjectPolygon.idup; // Not nothrow.

    foreach (immutable clipEdge; edges(clipPolygon)) {
        immutable inputList = result;
        result.destroy;
        foreach (immutable inEdge; edges(inputList)) {
            if (isInside(inEdge.q, clipEdge)) {
                if (!isInside(inEdge.p, clipEdge))
                    result ~= intersection(inEdge, clipEdge);
                result ~= inEdge.q;
            } else if (isInside(inEdge.p, clipEdge))
                result ~= intersection(inEdge, clipEdge);
        }
    }

    return result;
}

// Code adapted from the C version.
void saveEPSImage(in string fileName, in Vec2[] subjPoly,
                  in Vec2[] clipPoly, in Vec2[] clipped)
in {
    assert(!fileName.empty);
    assert(subjPoly.length > 1);
    assert(clipPoly.length > 1);
    assert(clipped.length > 1);
} body {
    auto eps = File(fileName, "w");

    // The image bounding box is hard-coded, not computed.
    eps.writeln(
"%%!PS-Adobe-3.0
%%%%BoundingBox: 40 40 360 360
/l {lineto} def
/m {moveto} def
/s {setrgbcolor} def
/c {closepath} def
/gs {fill grestore stroke} def
");

    eps.writef("0 setlinewidth %g %g m ", clipPoly[0].tupleof);
    foreach (immutable cl; clipPoly[1 .. $])
        eps.writef("%g %g l ", cl.tupleof);
    eps.writefln("c 0.5 0 0 s gsave 1 0.7 0.7 s gs");

    eps.writef("%g %g m ", subjPoly[0].tupleof);
    foreach (immutable s; subjPoly[1 .. $])
        eps.writef("%g %g l ", s.tupleof);
    eps.writefln("c 0 0.2 0.5 s gsave 0.4 0.7 1 s gs");

    eps.writef("2 setlinewidth [10 8] 0 setdash %g %g m ",
               clipped[0].tupleof);
    foreach (immutable c; clipped[1 .. $])
        eps.writef("%g %g l ", c.tupleof);
    eps.writefln("c 0.5 0 0.5 s gsave 0.7 0.3 0.8 s gs");

    eps.writefln("%%%%EOF");
    eps.close;
    writeln(fileName, " written.");
}

void main() {
    alias V = Vec2;
    immutable subjectPolygon = [V(50, 150), V(200, 50), V(350, 150),
                                V(350, 300), V(250, 300), V(200, 250),
                                V(150, 350), V(100, 250), V(100, 200)];
    immutable clippingPolygon = [V(100, 100), V(300, 100),
                                 V(300, 300), V(100, 300)];
    immutable clipped = subjectPolygon.clip(clippingPolygon);
    writefln("%(%s\n%)", clipped);
    saveEPSImage("sutherland_hodgman_clipping_out.eps",
                 subjectPolygon, clippingPolygon, clipped);
}


defmodule SutherlandHodgman do
  defp inside(cp1, cp2, p), do: (cp2.x-cp1.x)*(p.y-cp1.y) > (cp2.y-cp1.y)*(p.x-cp1.x)

  defp intersection(cp1, cp2, s, e) do
    {dcx, dcy} = {cp1.x-cp2.x, cp1.y-cp2.y}
    {dpx, dpy} = {s.x-e.x, s.y-e.y}
    n1 = cp1.x*cp2.y - cp1.y*cp2.x
    n2 = s.x*e.y - s.y*e.x
    n3 = 1.0 / (dcx*dpy - dcy*dpx)
    %{x: (n1*dpx - n2*dcx) * n3, y: (n1*dpy - n2*dcy) * n3}
  end

  def polygon_clipping(subjectPolygon, clipPolygon) do
    Enum.chunk([List.last(clipPolygon) | clipPolygon], 2, 1)
    |> Enum.reduce(subjectPolygon, fn [cp1,cp2],acc ->
         Enum.chunk([List.last(acc) | acc], 2, 1)
         |> Enum.reduce([], fn [s,e],outputList ->
              case {inside(cp1, cp2, e), inside(cp1, cp2, s)} do
                {true,  true} -> [e | outputList]
                {true, false} -> [e, intersection(cp1,cp2,s,e) | outputList]
                {false, true} -> [intersection(cp1,cp2,s,e) | outputList]
                _             -> outputList
              end
            end)
         |> Enum.reverse
       end)
  end
end

subjectPolygon = [[50, 150], [200, 50], [350, 150], [350, 300], [250, 300],
                  [200, 250], [150, 350], [100, 250], [100, 200]]
                 |> Enum.map(fn [x,y] -> %{x: x, y: y} end)

clipPolygon = [[100, 100], [300, 100], [300, 300], [100, 300]]
              |> Enum.map(fn [x,y] -> %{x: x, y: y} end)

SutherlandHodgman.polygon_clipping(subjectPolygon, clipPolygon)
|> Enum.each(&IO.inspect/1)


module SutherlandHodgmanUtil
  ! functions and type needed for Sutherland-Hodgman algorithm

  ! -------------------------------------------------------- !
  type polygon
    !type for polygons
    ! when you define a polygon, the first and the last vertices have to be the same
    integer :: n
    double precision, dimension(:,:), allocatable :: vertex
  end type polygon

  contains

  ! -------------------------------------------------------- !
  subroutine sutherlandHodgman( ref, clip, outputPolygon )
    ! Sutherland Hodgman algorithm for 2d polygons

    ! -- parameters of the subroutine --
    type(polygon) :: ref, clip, outputPolygon

    ! -- variables used is the subroutine
    type(polygon) :: workPolygon               ! polygon clipped step by step
    double precision, dimension(2) :: y1,y2    ! vertices of edge to clip workPolygon
    integer :: i

    ! allocate workPolygon with the maximal possible size
    !   the sum of the size of polygon ref and clip
    allocate(workPolygon%vertex( ref%n+clip%n , 2 ))

    !  initialise the work polygon with clip
    workPolygon%n = clip%n
    workPolygon%vertex(1:workPolygon%n,:) = clip%vertex(1:workPolygon%n,:)

    do i=1,ref%n-1 ! for each edge i of the polygon ref
      y1(:) = ref%vertex(i,:)   !  vertex 1 of edge i
      y2(:) = ref%vertex(i+1,:) !  vertex 2 of edge i

      ! clip the work polygon by edge i
      call edgeClipping( workPolygon, y1, y2, outputPolygon)
      ! workPolygon <= outputPolygon
      workPolygon%n = outputPolygon%n
      workPolygon%vertex(1:workPolygon%n,:) = outputPolygon%vertex(1:workPolygon%n,:)

    end do
    deallocate(workPolygon%vertex)
  end subroutine sutherlandHodgman

  ! -------------------------------------------------------- !
  subroutine edgeClipping( poly, y1, y2, outputPoly )
    ! make the clipping  of the polygon by the line (x1x2)

    type(polygon) :: poly, outputPoly
    double precision, dimension(2) :: y1, y2, x1, x2, intersecPoint
    integer ::  i, c

    c = 0 ! counter for the output polygon

    do i=1,poly%n-1 ! for each edge i of poly
      x1(:) = poly%vertex(i,:)   ! vertex 1 of edge i
      x2(:) = poly%vertex(i+1,:) ! vertex 2 of edge i

      if ( inside(x1, y1, y2) ) then ! if vertex 1 in inside clipping region
        if ( inside(x2, y1, y2) ) then ! if vertex 2 in inside clipping region
          ! add the vertex 2 to the output polygon
          c = c+1
          outputPoly%vertex(c,:) = x2(:)

        else ! vertex i+1 is outside
          intersecPoint = intersection(x1, x2, y1,y2)
          c = c+1
          outputPoly%vertex(c,:) = intersecPoint(:)
        end if
      else ! vertex i is outside
        if ( inside(x2, y1, y2) ) then
          intersecPoint = intersection(x1, x2, y1,y2)
          c = c+1
          outputPoly%vertex(c,:) = intersecPoint(:)

          c = c+1
          outputPoly%vertex(c,:) = x2(:)
        end if
      end if
    end do

    if (c .gt. 0) then
      ! if the last vertice is not equal to the first one
      if ( (outputPoly%vertex(1,1) .ne. outputPoly%vertex(c,1)) .or. &
           (outputPoly%vertex(1,2) .ne. outputPoly%vertex(c,2)))  then
        c=c+1
        outputPoly%vertex(c,:) = outputPoly%vertex(1,:)
      end if
    end if
    ! set the size of the outputPolygon
    outputPoly%n = c
  end subroutine edgeClipping

  ! -------------------------------------------------------- !
  function intersection( x1, x2, y1, y2)
    ! computes the intersection between segment [x1x2]
    ! and line the line (y1y2)

    ! -- parameters of the function --
    double precision, dimension(2) :: x1, x2, &  ! points of the segment
                                      y1, y2     ! points of the line

    double precision, dimension(2) :: intersection, vx, vy, x1y1
    double precision :: a

    vx(:) = x2(:) - x1(:)
    vy(:) = y2(:) - y1(:)

    ! if the vectors are colinear
    if ( crossProduct(vx,vy) .eq. 0.d0) then
      x1y1(:) = y1(:) - x1(:)
      ! if the the segment [x1x2] is included in the line (y1y2)
      if ( crossProduct(x1y1,vx) .eq. 0.d0) then
        ! the intersection is the last point of the segment
        intersection(:) = x2(:)
      end if
    else ! the vectors are not colinear
      ! we want to find the inersection between [x1x2]
      ! and (y1,y2).
      ! mathematically, we want to find a in [0;1] such
      ! that :
      !     x1 + a vx = y1 + b vy
      ! <=> a vx = x1y1 + b vy
      ! <=> a vx^vy = x1y1^vy      , ^ is cross product
      ! <=> a = x1y1^vy / vx^vy

      x1y1(:) = y1(:) - x1(:)
      ! we compute a
      a = crossProduct(x1y1,vy)/crossProduct(vx,vy)
      ! if a is not in [0;1]
      if ( (a .gt. 1.d0) .or. (a .lt. 0)) then
        ! no intersection
      else
        intersection(:) = x1(:) + a*vx(:)
      end if
    end if

  end function intersection

  ! -------------------------------------------------------- !
  function inside( p, y1, y2)
    ! function that tells is the point p is at left of the line (y1y2)

    double precision, dimension(2) :: p, y1, y2, v1, v2
    logical :: inside
    v1(:) = y2(:) -  y1(:)
    v2(:) = p(:)  -  y1(:)
    if ( crossProduct(v1,v2) .ge. 0.d0) then
      inside = .true.
    else
      inside = .false.
    end if

   contains
  end function inside

  ! -------------------------------------------------------- !
  function dotProduct( v1, v2)
    ! compute the dot product of vectors v1 and v2
    double precision, dimension(2) :: v1
    double precision, dimension(2) :: v2
    double precision :: dotProduct
    dotProduct = v1(1)*v2(1) + v1(2)*v2(2)
  end function dotProduct

  ! -------------------------------------------------------- !
  function crossProduct( v1, v2)
    ! compute the crossproduct of vectors v1 and v2
    double precision, dimension(2) :: v1
    double precision, dimension(2) :: v2
    double precision :: crossProduct
    crossProduct = v1(1)*v2(2) - v1(2)*v2(1)
  end function crossProduct

end module SutherlandHodgmanUtil

program main

  ! load the module for S-H algorithm
  use SutherlandHodgmanUtil, only : polygon, &
                                    sutherlandHodgman, &
                                    edgeClipping

  type(polygon) :: p1, p2, res
  integer :: c, n
  double precision, dimension(2) :: y1, y2

  ! when you define a polygon, the first and the last vertices have to be the same

  ! first polygon
  p1%n = 10
  allocate(p1%vertex(p1%n,2))
  p1%vertex(1,1)=50.d0
  p1%vertex(1,2)=150.d0

  p1%vertex(2,1)=200.d0
  p1%vertex(2,2)=50.d0

  p1%vertex(3,1)= 350.d0
  p1%vertex(3,2)= 150.d0

  p1%vertex(4,1)= 350.d0
  p1%vertex(4,2)= 300.d0

  p1%vertex(5,1)= 250.d0
  p1%vertex(5,2)= 300.d0

  p1%vertex(6,1)= 200.d0
  p1%vertex(6,2)= 250.d0

  p1%vertex(7,1)= 150.d0
  p1%vertex(7,2)= 350.d0

  p1%vertex(8,1)= 100.d0
  p1%vertex(8,2)= 250.d0

  p1%vertex(9,1)= 100.d0
  p1%vertex(9,2)= 200.d0

  p1%vertex(10,1)=  50.d0
  p1%vertex(10,2)= 150.d0

  y1 = (/ 100.d0, 300.d0 /)
  y2 = (/ 300.d0, 300.d0 /)

  ! second polygon
  p2%n = 5
  allocate(p2%vertex(p2%n,2))

  p2%vertex(1,1)= 100.d0
  p2%vertex(1,2)= 100.d0

  p2%vertex(2,1)= 300.d0
  p2%vertex(2,2)= 100.d0

  p2%vertex(3,1)= 300.d0
  p2%vertex(3,2)= 300.d0

  p2%vertex(4,1)= 100.d0
  p2%vertex(4,2)= 300.d0

  p2%vertex(5,1)= 100.d0
  p2%vertex(5,2)= 100.d0

  allocate(res%vertex(p1%n+p2%n,2))
  call sutherlandHodgman( p2, p1, res)
  write(*,*) "Suterland-Hodgman"
  do c=1, res%n
    write(*,*) res%vertex(c,1), res%vertex(c,2)
  end do
  deallocate(res%vertex)

end program main


Type Point
      As Double x,y
End Type

Type Line
      As Point s,f'start/finish
End Type

Function isleft(L As Line,p As Point) As Long
      Return  -Sgn((L.s.x-L.f.x)*(p.y-L.f.y)-(p.x-L.f.x)*(L.s.y-L.f.y))
End Function

Function segmentintersections(L1 As Line,L2 As Line) As Long
      If isleft(L2,L1.s) = isleft(L2,L1.f) Then Return 0
      If isleft(L1,L2.s) = isleft(L1,L2.f) Then Return 0
      Return 1
End Function

Function allintersections(l1 As Line,l2 As Line,_out As Point) As Long
      Const tolerance=.01
      Var p1=l1.s, p2=l1.f, p3=l2.s, p4=l2.f
      Var x12=p1.x-p2.x, x34=p3.x-p4.x, y12=p1.y-p2.y, y34=p3.y-p4.y
      Var c=x12*y34-y12*x34
      If Abs(c)<tolerance Then Return 0
      Var a=p1.x*p2.y-p1.y*p2.x, b=p3.x*p4.y-p3.y*p4.x
      _out.x = (a*x34-b*x12)/c
      _out.y = (a*y34-b*y12)/c
      Return 1
End Function

Dim As Point p1(...)={(50,150),(200,50),(350,150),(350,300),(250,300),(200,250), _
                     (150,350),(100,250),(100,200)}

Dim As Point p2(...)={(100,100),(300,100),(300,300),(100,300)}
'get the line segments around the polygons
Dim As Line L1(...)={(p1(0),p1(1)),(p1(1),p1(2)),(p1(2),p1(3)),(p1(3),p1(4)),(p1(4),p1(5)),_
                    (p1(5),p1(6)),(p1(6),p1(7)),(p1(7),p1(8)),(p1(8),p1(0))}

Dim As Line L2(...)={(p2(0),p2(1)),(p2(1),p2(2)),(p2(2),p2(3)),(p2(3),p2(0))}

'would normally draw these lines now, but not here.
Dim As Point x
For n1 As Long=Lbound(L1) To Ubound(L1)
      For n2 As Long=Lbound(L2) To Ubound(L2)
            If allintersections(L1(n1),L2(n2),x) And segmentintersections(L1(n1),L2(n2)) Then
                  Print x.x,x.y
            End If
      Next
Next

Sleep


package main

import "fmt"

type point struct {
    x, y float32
}

var subjectPolygon = []point{{50, 150}, {200, 50}, {350, 150}, {350, 300},
    {250, 300}, {200, 250}, {150, 350}, {100, 250}, {100, 200}}

var clipPolygon = []point{{100, 100}, {300, 100}, {300, 300}, {100, 300}}

func main() {
    var cp1, cp2, s, e point
    inside := func(p point) bool {
        return (cp2.x-cp1.x)*(p.y-cp1.y) > (cp2.y-cp1.y)*(p.x-cp1.x)
    }
    intersection := func() (p point) {
        dcx, dcy := cp1.x-cp2.x, cp1.y-cp2.y
        dpx, dpy := s.x-e.x, s.y-e.y
        n1 := cp1.x*cp2.y - cp1.y*cp2.x
        n2 := s.x*e.y - s.y*e.x
        n3 := 1 / (dcx*dpy - dcy*dpx)
        p.x = (n1*dpx - n2*dcx) * n3
        p.y = (n1*dpy - n2*dcy) * n3
        return
    }
    outputList := subjectPolygon
    cp1 = clipPolygon[len(clipPolygon)-1]
    for _, cp2 = range clipPolygon { // WP clipEdge is cp1,cp2 here
        inputList := outputList
        outputList = nil
        s = inputList[len(inputList)-1]
        for _, e = range inputList {
            if inside(e) {
                if !inside(s) {
                    outputList = append(outputList, intersection())
                }
                outputList = append(outputList, e)
            } else if inside(s) {
                outputList = append(outputList, intersection())
            }
            s = e
        }
        cp1 = cp2
    }
    fmt.Println(outputList)
}


module SuthHodgClip (clipTo) where

import Data.List

type   Pt a = (a, a)
type   Ln a = (Pt a, Pt a)
type Poly a = [Pt a]

-- Return a polygon from a list of points.
polyFrom ps = last ps : ps

-- Return a list of lines from a list of points.
linesFrom pps@(_:ps) = zip pps ps

-- Return true if the point (x,y) is on or to the left of the oriented line
-- defined by (px,py) and (qx,qy).
(.|) :: (Num a, Ord a) => Pt a -> Ln a -> Bool
(x,y) .| ((px,py),(qx,qy)) = (qx-px)*(y-py) >= (qy-py)*(x-px)

-- Return the intersection of two lines.
(><) :: Fractional a => Ln a -> Ln a -> Pt a
((x1,y1),(x2,y2)) >< ((x3,y3),(x4,y4)) =
    let (r,s) = (x1*y2-y1*x2, x3*y4-y3*x4)
        (t,u,v,w) = (x1-x2, y3-y4, y1-y2, x3-x4)
        d = t*u-v*w
    in ((r*w-t*s)/d, (r*u-v*s)/d)

-- Intersect the line segment (p0,p1) with the clipping line's left halfspace,
-- returning the point closest to p1.  In the special case where p0 lies outside
-- the halfspace and p1 lies inside we return both the intersection point and
-- p1.  This ensures we will have the necessary segment along the clipping line.
(-|) :: (Fractional a, Ord a) => Ln a -> Ln a -> [Pt a]
ln@(p0, p1) -| clipLn =
    case (p0 .| clipLn, p1 .| clipLn) of
      (False, False) -> []
      (False, True)  -> [isect, p1]
      (True,  False) -> [isect]
      (True,  True)  -> [p1]
    where isect = ln >< clipLn

-- Intersect the polygon with the clipping line's left halfspace.
(<|) :: (Fractional a, Ord a) => Poly a -> Ln a -> Poly a
poly <| clipLn = polyFrom $ concatMap (-| clipLn) (linesFrom poly)

-- Intersect a target polygon with a clipping polygon.  The latter is assumed to
-- be convex.
clipTo :: (Fractional a, Ord a) => [Pt a] -> [Pt a] -> [Pt a]
targPts `clipTo` clipPts =
    let targPoly = polyFrom targPts
        clipLines = linesFrom (polyFrom clipPts)
    in foldl' (<|) targPoly clipLines


NB. assumes counterclockwise orientation.
NB. determine whether point y is inside edge x.
isinside=:0< [:-/ .* {[email protected][ -~"1 {:@[,:]

NB. (p0,:p1) intersection (p2,:p3)
intersection=:|:@[ (+/ .* (,-.)) [:{. ,.&(-~/) %.~ -&{:

SutherlandHodgman=:4 :0 NB. clip S-H subject
  clip=.2 ]\ (,{.) x
  subject=.y
  for_edge. clip do.
    S=.{:input=.subject
    subject=.0 2$0
    for_E. input do.
      if. edge isinside E do.
        if. -.edge isinside S do.
          subject=.subject,edge intersection S,:E end.
        subject=.subject,E
      elseif. edge isinside S do.
        subject=.subject,edge intersection S,:E end.
      S=.E
    end.
  end.
  subject
)


import java.awt.*;
import java.awt.geom.Line2D;
import java.util.*;
import java.util.List;
import javax.swing.*;

public class SutherlandHodgman extends JFrame {

    SutherlandHodgmanPanel panel;

    public static void main(String[] args) {
        JFrame f = new SutherlandHodgman();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

    public SutherlandHodgman() {
        Container content = getContentPane();
        content.setLayout(new BorderLayout());
        panel = new SutherlandHodgmanPanel();
        content.add(panel, BorderLayout.CENTER);
        setTitle("SutherlandHodgman");
        pack();
        setLocationRelativeTo(null);
    }
}

class SutherlandHodgmanPanel extends JPanel {
    List<double[]> subject, clipper, result;

    public SutherlandHodgmanPanel() {
        setPreferredSize(new Dimension(600, 500));

        // these subject and clip points are assumed to be valid
        double[][] subjPoints = {{50, 150}, {200, 50}, {350, 150}, {350, 300},
        {250, 300}, {200, 250}, {150, 350}, {100, 250}, {100, 200}};

        double[][] clipPoints = {{100, 100}, {300, 100}, {300, 300}, {100, 300}};

        subject = new ArrayList<>(Arrays.asList(subjPoints));
        result  = new ArrayList<>(subject);
        clipper = new ArrayList<>(Arrays.asList(clipPoints));

        clipPolygon();
    }

    private void clipPolygon() {
        int len = clipper.size();
        for (int i = 0; i < len; i++) {

            int len2 = result.size();
            List<double[]> input = result;
            result = new ArrayList<>(len2);

            double[] A = clipper.get((i + len - 1) % len);
            double[] B = clipper.get(i);

            for (int j = 0; j < len2; j++) {

                double[] P = input.get((j + len2 - 1) % len2);
                double[] Q = input.get(j);

                if (isInside(A, B, Q)) {
                    if (!isInside(A, B, P))
                        result.add(intersection(A, B, P, Q));
                    result.add(Q);
                } else if (isInside(A, B, P))
                    result.add(intersection(A, B, P, Q));
            }
        }
    }

    private boolean isInside(double[] a, double[] b, double[] c) {
        return (a[0] - c[0]) * (b[1] - c[1]) > (a[1] - c[1]) * (b[0] - c[0]);
    }

    private double[] intersection(double[] a, double[] b, double[] p, double[] q) {
        double A1 = b[1] - a[1];
        double B1 = a[0] - b[0];
        double C1 = A1 * a[0] + B1 * a[1];

        double A2 = q[1] - p[1];
        double B2 = p[0] - q[0];
        double C2 = A2 * p[0] + B2 * p[1];

        double det = A1 * B2 - A2 * B1;
        double x = (B2 * C1 - B1 * C2) / det;
        double y = (A1 * C2 - A2 * C1) / det;

        return new double[]{x, y};
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.translate(80, 60);
        g2.setStroke(new BasicStroke(3));
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        drawPolygon(g2, subject, Color.blue);
        drawPolygon(g2, clipper, Color.red);
        drawPolygon(g2, result, Color.green);
    }

    private void drawPolygon(Graphics2D g2, List<double[]> points, Color color) {
        g2.setColor(color);
        int len = points.size();
        Line2D line = new Line2D.Double();
        for (int i = 0; i < len; i++) {
            double[] p1 = points.get(i);
            double[] p2 = points.get((i + 1) % len);
            line.setLine(p1[0], p1[1], p2[0], p2[1]);
            g2.draw(line);
        }
    }
}


<html>
    <head>
	<script>
        function clip (subjectPolygon, clipPolygon) {

            var cp1, cp2, s, e;
            var inside = function (p) {
                return (cp2[0]-cp1[0])*(p[1]-cp1[1]) > (cp2[1]-cp1[1])*(p[0]-cp1[0]);
            };
            var intersection = function () {
                var dc = [ cp1[0] - cp2[0], cp1[1] - cp2[1] ],
                    dp = [ s[0] - e[0], s[1] - e[1] ],
                    n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0],
                    n2 = s[0] * e[1] - s[1] * e[0],
                    n3 = 1.0 / (dc[0] * dp[1] - dc[1] * dp[0]);
                return [(n1*dp[0] - n2*dc[0]) * n3, (n1*dp[1] - n2*dc[1]) * n3];
            };
            var outputList = subjectPolygon;
            cp1 = clipPolygon[clipPolygon.length-1];
            for (var j in clipPolygon) {
                cp2 = clipPolygon[j];
                var inputList = outputList;
                outputList = [];
                s = inputList[inputList.length - 1]; //last on the input list
                for (var i in inputList) {
                    e = inputList[i];
                    if (inside(e)) {
                        if (!inside(s)) {
                            outputList.push(intersection());
                        }
                        outputList.push(e);
                    }
                    else if (inside(s)) {
                        outputList.push(intersection());
                    }
                    s = e;
                }
                cp1 = cp2;
            }
            return outputList
        }

        function drawPolygon(context, polygon, strokeStyle, fillStyle) {
            context.strokeStyle = strokeStyle;
            context.fillStyle = fillStyle;
            context.beginPath();
            context.moveTo(polygon[0][0],polygon[0][1]); //first vertex
            for (var i = 1; i < polygon.length ; i++)
                context.lineTo(polygon[i][0],polygon[i][1]);
            context.lineTo(polygon[0][0],polygon[0][1]); //back to start
            context.fill();
            context.stroke();
            context.closePath();
        }

        window.onload = function () {
	        var context = document.getElementById('canvas').getContext('2d');
	        var subjectPolygon = [[50, 150], [200, 50], [350, 150], [350, 300], [250, 300], [200, 250], [150, 350], [100, 250], [100, 200]],
	            clipPolygon = [[100, 100], [300, 100], [300, 300], [100, 300]];
	        var clippedPolygon = clip(subjectPolygon, clipPolygon);
	        drawPolygon(context, clipPolygon, '#888','#88f');
	        drawPolygon(context, subjectPolygon, '#888','#8f8');
	        drawPolygon(context, clippedPolygon, '#000','#0ff');
    	}
        </script>
    <body>
    	<canvas id='canvas' width='400' height='400'></canvas>
    </body>
</html>


using Luxor

isinside(p, a, b) = (b.x - a.x) * (p.y - a.y) > (b.y - a.y) * (p.x - a.x)

function intersection(a, b, s, f)
    dc = [a.x - b.x, a.y - b.y]
    dp = [s.x - f.x, s.y - f.y]
    n1 = a.x * b.y - a.y * b.x
    n2 = s.x * f.y - s.y * f.x
    n3 = 1.0 / (dc[1] * dp[2] - dc[2] * dp[1])
    Point((n1 * dp[1] - n2 * dc[1]) * n3, (n1 * dp[2] - n2 * dc[2]) * n3)
end

function clipSH(spoly, cpoly)
    outarr = spoly
    q = cpoly[end]
    for p in cpoly
        inarr = outarr
        outarr = Point[]
        s = inarr[end]
        for vtx in inarr
            if isinside(vtx, q, p)
                if !isinside(s, q, p)
                    push!(outarr, intersection(q, p, s, vtx))
                end
                push!(outarr, vtx)
            elseif isinside(s, q, p)
                push!(outarr, intersection(q, p, s, vtx))
            end
            s = vtx
        end
        q = p
    end
    outarr
end

subjectp = [Point(50, 150), Point(200, 50), Point(350, 150), Point(350, 300),
    Point(250, 300), Point(200, 250), Point(150, 350), Point(100, 250), Point(100, 200)]

clipp = [Point(100, 100), Point(300, 100), Point(300, 300), Point(100, 300)]

Drawing(400, 400, "intersecting-polygons.png")
background("white")
sethue("red")
poly(subjectp, :stroke, close=true)
sethue("blue")
poly(clipp, :stroke, close=true)
clipped = clipSH(subjectp, clipp)
sethue("gold")
poly(clipped, :fill, close=true)
finish()
preview()
println(clipped)


// version 1.1.2

import java.awt.*
import java.awt.geom.Line2D
import javax.swing.*

class SutherlandHodgman : JPanel() {
    private val subject = listOf(
        doubleArrayOf( 50.0, 150.0), doubleArrayOf(200.0,  50.0), doubleArrayOf(350.0, 150.0),
        doubleArrayOf(350.0, 300.0), doubleArrayOf(250.0, 300.0), doubleArrayOf(200.0, 250.0),
        doubleArrayOf(150.0, 350.0), doubleArrayOf(100.0, 250.0), doubleArrayOf(100.0, 200.0)
    )

    private val clipper = listOf(
        doubleArrayOf(100.0, 100.0), doubleArrayOf(300.0, 100.0),
        doubleArrayOf(300.0, 300.0), doubleArrayOf(100.0, 300.0)
    )

    private var result = subject.toMutableList()

    init {
        preferredSize = Dimension(600, 500)
        clipPolygon()
    }

    private fun clipPolygon() {
        val len = clipper.size
        for (i in 0 until len) {
            val len2 = result.size
            val input = result
            result = mutableListOf<DoubleArray>()
            val a = clipper[(i + len - 1) % len]
            val b = clipper[i]

            for (j in 0 until len2) {
                val p = input[(j + len2 - 1) % len2]
                val q = input[j]

                if (isInside(a, b, q)) {
                    if (!isInside(a, b, p)) result.add(intersection(a, b, p, q))
                    result.add(q)
                }
                else if (isInside(a, b, p)) result.add(intersection(a, b, p, q))
            }
        }
    }

    private fun isInside(a: DoubleArray, b: DoubleArray, c: DoubleArray) =
        (a[0] - c[0]) * (b[1] - c[1]) > (a[1] - c[1]) * (b[0] - c[0])

    private fun intersection(a: DoubleArray, b: DoubleArray,
                             p: DoubleArray, q: DoubleArray): DoubleArray {
        val a1 = b[1] - a[1]
        val b1 = a[0] - b[0]
        val c1 = a1 * a[0] + b1 * a[1]

        val a2 = q[1] - p[1]
        val b2 = p[0] - q[0]
        val c2 = a2 * p[0] + b2 * p[1]

        val d = a1 * b2 - a2 * b1
        val x = (b2 * c1 - b1 * c2) / d
        val y = (a1 * c2 - a2 * c1) / d

        return doubleArrayOf(x, y)
    }

    override fun paintComponent(g: Graphics) {
        super.paintComponent(g)
        val g2 = g as Graphics2D
        g2.translate(80, 60)
        g2.stroke = BasicStroke(3.0f)
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON)
        drawPolygon(g2, subject, Color.blue)
        drawPolygon(g2, clipper, Color.red)
        drawPolygon(g2, result, Color.green)
    }

    private fun drawPolygon(g2: Graphics2D, points: List<DoubleArray>, color: Color) {
        g2.color = color
        val len = points.size
        val line = Line2D.Double()
        for (i in 0 until len) {
            val p1 = points[i]
            val p2 = points[(i + 1) % len]
            line.setLine(p1[0], p1[1], p2[0], p2[1])
            g2.draw(line)
        }
    }
}

fun main(args: Array<String>) {
    SwingUtilities.invokeLater {
        val f = JFrame()
        with(f) {
            defaultCloseOperation = JFrame.EXIT_ON_CLOSE
            add(SutherlandHodgman(), BorderLayout.CENTER)
            title = "Sutherland-Hodgman"
            pack()
            setLocationRelativeTo(null)
            isVisible = true
        }
    }
}


[String] result
V longest = 0

F make_sequence(n) -> N
   DefaultDict[Char, Int] map
   L(c) n
      map[c]++

   V z = ‘’
   L(k) sorted(map.keys(), reverse' 1B)
      z ‘’= Char(code' map[k] + ‘0’.code)
      z ‘’= k

   I :longest <= z.len
      :longest = z.len
      I z !C :result
         :result [+]= z
         make_sequence(z)

L(test) [‘9900’, ‘9090’, ‘9009’]
   result.clear()
   longest = 0
   make_sequence(test)
   print(‘[#.] Iterations: #.’.format(test, result.len + 1))
   print(result.join("\n"))
   print("\n")


subjectPolygon = {
  {50, 150}, {200, 50}, {350, 150}, {350, 300},
  {250, 300}, {200, 250}, {150, 350}, {100, 250}, {100, 200}
}

clipPolygon = {{100, 100}, {300, 100}, {300, 300}, {100, 300}}

function inside(p, cp1, cp2)
  return (cp2.x-cp1.x)*(p.y-cp1.y) > (cp2.y-cp1.y)*(p.x-cp1.x)
end

function intersection(cp1, cp2, s, e)
  local dcx, dcy = cp1.x-cp2.x, cp1.y-cp2.y
  local dpx, dpy = s.x-e.x, s.y-e.y
  local n1 = cp1.x*cp2.y - cp1.y*cp2.x
  local n2 = s.x*e.y - s.y*e.x
  local n3 = 1 / (dcx*dpy - dcy*dpx)
  local x = (n1*dpx - n2*dcx) * n3
  local y = (n1*dpy - n2*dcy) * n3
  return {x=x, y=y}
end

function clip(subjectPolygon, clipPolygon)
  local outputList = subjectPolygon
  local cp1 = clipPolygon[#clipPolygon]
  for _, cp2 in ipairs(clipPolygon) do  -- WP clipEdge is cp1,cp2 here
    local inputList = outputList
    outputList = {}
    local s = inputList[#inputList]
    for _, e in ipairs(inputList) do
      if inside(e, cp1, cp2) then
        if not inside(s, cp1, cp2) then
          outputList[#outputList+1] = intersection(cp1, cp2, s, e)
        end
        outputList[#outputList+1] = e
      elseif inside(s, cp1, cp2) then
        outputList[#outputList+1] = intersection(cp1, cp2, s, e)
      end
      s = e
    end
    cp1 = cp2
  end
  return outputList
end

function main()
  local function mkpoints(t)
    for i, p in ipairs(t) do
      p.x, p.y = p[1], p[2]
    end
  end
  mkpoints(subjectPolygon)
  mkpoints(clipPolygon)

  local outputList = clip(subjectPolygon, clipPolygon)

  for _, p in ipairs(outputList) do
    print(('{%f, %f},'):format(p.x, p.y))
  end
end

main()


with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
procedure SelfRef is
   subtype Seed is Natural range 0 .. 1_000_000;
   subtype Num is Natural range 0 .. 10;
   type NumList is array (0 .. 10) of Num;
   package IO is new Ada.Text_IO.Integer_IO (Natural);
   package DVect is new Ada.Containers.Vectors (Positive, NumList);

   function Init (innum : Seed) return NumList is
      list : NumList := (others => 0);
      number : Seed := innum;  d : Num;
   begin
      loop
         d := Num (number mod 10);
         list (d) :=  list (d) + 1;
         number := number / 10; exit when number = 0;
      end loop; return list;
   end Init;

   procedure Next (inoutlist : in out NumList) is
      list : NumList := (others => 0);
   begin
      for i in list'Range loop
         if inoutlist (i) /= 0 then
            list (i) := list (i) + 1;
            list (inoutlist (i)) := list (inoutlist (i)) + 1;
         end if;
      end loop; inoutlist := list;
   end Next;

   procedure Show (list : NumList) is begin
      for i in reverse list'Range loop
         if list (i) > 0 then
            IO.Put (list (i), Width => 1); IO.Put (i, Width => 1);
         end if;
      end loop; New_Line;
   end Show;

   function Iterate (theseed : Seed; p : Boolean) return Natural is
      list : NumList := Init (theseed);
      vect : DVect.Vector;
   begin
      vect.Append (list);
      loop
         if p then Show (list); end if;
         Next (list); exit when vect.Contains (list); vect.Append (list);
      end loop;
      return Integer (DVect.Length (vect)) + 1;
   end Iterate;

   mseed : Seed;
   len, maxlen : Natural := 0;
begin
   for i in Seed'Range loop
      len := Iterate (i, False);
      if len > maxlen then mseed := i; maxlen := len; end if;
   end loop;
   IO.Put (maxlen, Width => 1); Put_Line (" Iterations:");
   IO.Put (mseed, Width => 1); New_Line;
   len := Iterate (mseed, True);
end SelfRef;


%The inputs are a table of x-y pairs for the verticies of the subject
%polygon and boundary polygon. (x values in column 1 and y values in column
%2) The output is a table of x-y pairs for the clipped version of the
%subject polygon.

function clippedPolygon = sutherlandHodgman(subjectPolygon,clipPolygon)

%% Helper Functions

    %computerIntersection() assumes the two lines intersect
    function intersection = computeIntersection(line1,line2)

        %this is an implementation of
        %http://en.wikipedia.org/wiki/Line-line_intersection

        intersection = zeros(1,2);

        detL1 = det(line1);
        detL2 = det(line2);

        detL1x = det([line1(:,1),[1;1]]);
        detL1y = det([line1(:,2),[1;1]]);

        detL2x = det([line2(:,1),[1;1]]);
        detL2y = det([line2(:,2),[1;1]]);

        denominator = det([detL1x detL1y;detL2x detL2y]);

        intersection(1) = det([detL1 detL1x;detL2 detL2x]) / denominator;
        intersection(2) = det([detL1 detL1y;detL2 detL2y]) / denominator;

    end %computeIntersection

    %inside() assumes the boundary is oriented counter-clockwise
    function in = inside(point,boundary)

        pointPositionVector = [diff([point;boundary(1,:)]) 0];
        boundaryVector = [diff(boundary) 0];
        crossVector = cross(pointPositionVector,boundaryVector);

        if ( crossVector(3) <= 0 )
            in = true;
        else
            in = false;
        end

    end %inside

%% Sutherland-Hodgman Algorithm

    clippedPolygon = subjectPolygon;
    numVerticies = size(clipPolygon,1);
    clipVertexPrevious = clipPolygon(end,:);

    for clipVertex = (1:numVerticies)

        clipBoundary = [clipPolygon(clipVertex,:) ; clipVertexPrevious];

        inputList = clippedPolygon;

        clippedPolygon = [];
        if ~isempty(inputList),
            previousVertex = inputList(end,:);
        end

        for subjectVertex = (1:size(inputList,1))

            if ( inside(inputList(subjectVertex,:),clipBoundary) )

                if( not(inside(previousVertex,clipBoundary)) )
                    subjectLineSegment = [previousVertex;inputList(subjectVertex,:)];
                    clippedPolygon(end+1,1:2) = computeIntersection(clipBoundary,subjectLineSegment);
                end

                clippedPolygon(end+1,1:2) = inputList(subjectVertex,:);

            elseif( inside(previousVertex,clipBoundary) )
                    subjectLineSegment = [previousVertex;inputList(subjectVertex,:)];
                    clippedPolygon(end+1,1:2) = computeIntersection(clipBoundary,subjectLineSegment);
            end

            previousVertex = inputList(subjectVertex,:);
            clipVertexPrevious = clipPolygon(clipVertex,:);

        end %for subject verticies
    end %for boundary verticies
end %sutherlandHodgman


text
next(text s)
{
    integer c, e, l;
    index v;
    data d;

    l = ~s;
    while (l) {
        v[-s[l -= 1]] += 1;
    }

    for (c, e in v) {
        b_form(d, "%d%c", e, -c);
    }

    return d;
}

integer
depth(text s, integer i, record r)
{
    integer d;

    d = 0;
    r_j_integer(d, r, s);
    if (d <= 0) {
        i += 1;
        d += d ? i : -i;
        r[s] = d;
        i = depth(next(s), i, r);
        d = r[s];
        if (d <= 0) {
            r[s] = d = i + 1;
        }
    }

    return d;
}

integer
main(void)
{
    integer d, e, i;
    record r;
    list l;

    d = 0;
    i = 1000000;
    while (i) {
        i -= 1;
        e = depth(itoa(i), 0, r);
        if (e == d) {
            lb_p_integer(l, i);
        } elif (d < e) {
            d = e;
            l_clear(l);
            lb_p_integer(l, i);
        }
    }

    o_("longest length is ", d, "\n");
    while (l_o_integer(i, l, 0)) {
        text s;

        o_("\n", i, "\n");
        e = d - 1;
        s = itoa(i);
        while (e) {
            o_(s = next(s), "\n");
            e -= 1;
        }
    }

    return 0;
}


; The following directives and commands speed up execution:
#NoEnv
SetBatchlines -1
ListLines Off
Process, Priority,, high

iterations := 0, seed := "Seeds: "

Loop 1000000
	If (newIterations := CountSubString(list := ListSequence(A_Index), "`n")) > iterations
		iterations := newiterations
		,final := "`nIterations: " iterations+1 "`nSequence:`n`n" A_Index "`n" list
		,seed := A_Index " "
	else if (newIterations = iterations)
		seed .= A_Index " "
MsgBox % "Seeds: " . seed . final
ListSequence(seed){
	While !InStr("`n" . out, "`n" (d:=Describe(seed)) "`n")
		out .= d "`n", seed := d
	return out
}

Describe(n){
	Loop 10
		If (t:=CountSubString(n, 10-A_Index))
			out .= t . (10-A_Index)
	return out
}

CountSubstring(fullstring, substring){
   StringReplace, junk, fullstring, %substring%, , UseErrorLevel
   return errorlevel
}


import sequtils, strformat

type
  Vec2 = tuple[x, y: float]
  Edge = tuple[p, q: Vec2]
  Polygon = seq[Vec2]

func `-`(a, b: Vec2): Vec2 = (a.x - b.x, a.y - b.y)

func cross(a, b: Vec2): float = a.x * b.y - a.y * b.x

func isInside(p: Vec2; edge: Edge): bool =
  (edge.q.x - edge.p.x) * (p.y - edge.p.y) > (edge.q.y - edge.p.y) * (p.x - edge.p.x)

func intersection(sEdge, cEdge: Edge): Vec2 =
  let
    dc = cEdge.p - cEdge.q
    dp = sEdge.p - sEdge.q
    n1 = cEdge.p.cross(cEdge.q)
    n2 = sEdge.p.cross(sEdge.q)
    n3 = 1 / dc.cross(dp)
  result = ((n1 * dp.x - n2 * dc.x) * n3, (n1 * dp.y - n2 * dc.y) * n3)

func edges(poly: Polygon): seq[Edge] =
  (poly[^1] & poly).zip(poly)

func clip(subjectPolygon, clipPolygon: Polygon): Polygon =
  assert subjectPolygon.len > 1
  assert clipPolygon.len > 1

  result = subjectPolygon
  for clipEdge in clipPolygon.edges:
    let inputList = move(result)
    result.reset()
    for inEdge in inputList.edges:
      if inEdge.q.isInside(clipEdge):
        if not inEdge.p.isInside(clipEdge):
          result.add intersection(inEdge, clipEdge)
        result.add inEdge.q
      elif inEdge.p.isInside(clipEdge):
        result.add intersection(inEdge, clipEdge)

proc saveEpsImage(filename: string; subject, clip, clipped: Polygon) =
  let eps = open(filename, fmWrite)
  eps.write "%%!PS-Adobe-3.0\n%%%%BoundingBox: 40 40 360 360\n/l {lineto} def\n/m {moveto} def\n",
            "/s {setrgbcolor} def\n/c {closepath} def\n/gs {fill grestore stroke} def\n"

  eps.write &"0 setlinewidth {clip[0].x} {clip[0].y} m "
  for i in 1..clip.high:
    eps.write &"{clip[i].x} {clip[i].y} l "
  eps.writeLine "c 0.5 0 0 s gsave 1 0.7 0.7 s gs"

  eps.write &"{subject[0].x} {subject[0].y} m "
  for i in 1..subject.high:
    eps.write &"{subject[i].x} {subject[i].y} l "
  eps.writeLine "c 0 0.2 0.5 s gsave 0.4 0.7 1 s gs"

  eps.write &"2 setlinewidth [10 8] 0 setdash {clipped[0].x} {clipped[0].y} m "
  for i in 1..clipped.high:
    eps.write &"{clipped[i].x} {clipped[i].y} l "
  eps.writeLine &"c 0.5 0 0.5 s gsave 0.7 0.3 0.8 s gs"

  eps.writeLine "%%%%EOF"
  eps.close()
  echo &"File “{filename}” written."

when isMainModule:

  let
    subjectPolygon = @[(50.0, 150.0), (200.0, 50.0), (350.0, 150.0),
                      (350.0, 300.0), (250.0, 300.0), (200.0, 250.0),
                      (150.0, 350.0), (100.0, 250.0), (100.0, 200.0)]
    clippingPolygon = @[(100.0, 100.0), (300.0, 100.0), (300.0, 300.0), (100.0, 300.0)]

    clipped = subjectPolygon.clip(clippingPolygon)

  for point in clipped:
    echo &"({point.x:.3f}, {point.y:.3f})"
  saveEpsImage("sutherland_hodgman_clipping_out.eps", subjectPolygon, clippingPolygon, clipped)


let is_inside (x,y) ((ax,ay), (bx,by)) =
  (bx -. ax) *. (y -. ay) > (by -. ay) *. (x -. ax)

let intersection (sx,sy) (ex,ey) ((ax,ay), (bx,by)) =
  let dc_x, dc_y = (ax -. bx, ay -. by) in
  let dp_x, dp_y = (sx -. ex, sy -. ey) in
  let n1 = ax *. by -. ay *. bx in
  let n2 = sx *. ey -. sy *. ex in
  let n3 = 1.0 /. (dc_x *. dp_y -. dc_y *. dp_x) in
  ((n1 *. dp_x -. n2 *. dc_x) *. n3,
   (n1 *. dp_y -. n2 *. dc_y) *. n3)

let last lst = List.hd (List.rev lst)

let polygon_iter_edges poly f init =
  if poly = [] then init else
    let p0 = List.hd poly in
    let rec aux acc = function
      | p1 :: p2 :: tl -> aux (f (p1, p2) acc) (p2 :: tl)
      | p :: [] -> f (p, p0) acc
      | [] -> acc
    in
    aux init poly

let poly_clip subject_polygon clip_polygon =
  polygon_iter_edges clip_polygon (fun clip_edge input_list ->
    fst (
      List.fold_left (fun (out, s) e ->

        match (is_inside e clip_edge), (is_inside s clip_edge) with
        | true, false -> (e :: (intersection s e clip_edge) :: out), e
        | true, true -> (e :: out), e
        | false, true -> ((intersection s e clip_edge) :: out), e
        | false, false -> (out, e)

      ) ([], last input_list) input_list)

  ) subject_polygon

let () =
  let subject_polygon =
    [ ( 50.0, 150.0); (200.0,  50.0); (350.0, 150.0);
      (350.0, 300.0); (250.0, 300.0); (200.0, 250.0);
      (150.0, 350.0); (100.0, 250.0); (100.0, 200.0); ] in

  let clip_polygon =
    [ (100.0, 100.0); (300.0, 100.0); (300.0, 300.0); (100.0, 300.0) ] in

  List.iter (fun (x,y) ->
      Printf.printf " (%g, %g)\n" x y;
    ) (poly_clip subject_polygon clip_polygon)


      *FLOAT64
      DIM list$(30)
      maxiter% = 0
      maxseed% = 0
      FOR seed% = 0 TO 999999
        list$(0) = STR$(seed%)
        iter% = 0
        REPEAT
          list$(iter%+1) = FNseq(list$(iter%))
          IF VALlist$(iter%+1) <= VALlist$(iter%) THEN
            FOR try% = iter% TO 0 STEP -1
              IF list$(iter%+1) = list$(try%) EXIT REPEAT
            NEXT
          ENDIF
          iter% += 1
        UNTIL FALSE
        IF iter% >= maxiter% THEN
          IF iter% > maxiter% CLS
          maxiter% = iter%
          maxseed% = seed%
          PRINT "Seed " ;seed% " has "; iter% " iterations"
        ENDIF
      NEXT
      PRINT '"Sequence:"
      number$ = STR$(maxseed%)
      FOR i% = 1 TO maxiter%
        PRINT number$
        number$ = FNseq(number$)
      NEXT
      END

      DEF FNseq(n$)
      LOCAL I%, o$, d%()
      DIM d%(9)
      FOR I% = 1 TO LEN(n$)
        d%(ASCMID$(n$,I%)-&30) += 1
      NEXT
      FOR I% = 9 TO 0 STEP -1
        IF d%(I%) o$ += STR$d%(I%) + STR$I%
      NEXT
      = o$


( ( self-referential
  =   seq N next
    .   ( next
        =   R S d f
          .   0:?S
            &   whl
              ' (@(!arg:%@?d ?arg)&(.!d)+!S:?S)
            & :?R
            &   whl
              ' ( !S:#?f*(.?d)+?S
                & !f !d !R:?R
                )
            & str$!R
        )
      & 1:?N
      & !arg:?seq
      &   whl
        ' ( next$!arg:?arg
          & ~(!seq:? !arg ?)
          & !arg !seq:?seq
          & 1+!N:?N
          )
      & (!seq.!N)
  )
& ( Perm
  =   permutations S p
    .   :?permutations
      & ( perm
        =   prefix List original A Z p
          .     !arg:(?prefix.)
              & str$!prefix:?p
              & (!S:?+(.!p)+?|(.!p)+!S:?S)
            | !arg:(0 ?.?)&
            |   !arg:(?prefix.?List:?original)
              &   whl
                ' ( @(!List:%?A ?Z)
                  & perm$(!prefix !A.!Z)
                  & str$(!Z !A):~!original:?List
                  )
        )
      & 0:?S
      & perm$(.!arg)
      & :?permutations
      &   whl
        ' ( !S:?*(.?p)+?S
          & !p !permutations:?permutations
          )
      & !permutations
  )
& -1:?i:?max
& :?seqs
&   whl
  ' ( 1+!i:<1000000:?i
    & ( @(!i:? %@?a >%@!a ?)
      |   self-referential$!i
        : ( ?seq
          .   ( >!max:?max&:?seqs
              | !max
              )
            &     ( "Seed Value(s):" Perm$!i
                  .   "Sequence: (same for all three seeds except for first element)
"
                      !seq
                  )
                  !seqs
              : ?seqs
          )
      |
      )
    )
& out$("Iterations:" !max !seqs)
);


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

typedef struct rec_t rec_t;
struct rec_t {
	int depth;
	rec_t * p[10];
};

rec_t root = {0, {0}};

#define USE_POOL_ALLOC
#ifdef USE_POOL_ALLOC /* not all that big a deal */
rec_t *tail = 0, *head = 0;
#define POOL_SIZE (1 << 20)
inline rec_t *new_rec()
{
	if (head == tail) {
		head = calloc(sizeof(rec_t), POOL_SIZE);
		tail = head + POOL_SIZE;
	}
	return head++;
}
#else
#define new_rec() calloc(sizeof(rec_t), 1)
#endif

rec_t *find_rec(char *s)
{
	int i;
	rec_t *r = &root;
	while (*s) {
		i = *s++ - '0';
		if (!r->p[i]) r->p[i] = new_rec();
		r = r->p[i];
	}
	return r;
}

/* speed up number to string conversion */
char number[100][4];
void init()
{
	int i;
	for (i = 0; i < 100; i++)
		sprintf(number[i], "%d", i);
}

void count(char *buf)
{
	int i, c[10] = {0};
	char *s;

	for (s = buf; *s; c[*s++ - '0']++);

	for (i = 9; i >= 0; i--) {
		if (!c[i]) continue;
		s = number[c[i]];

		*buf++ = s[0];
		if ((*buf = s[1])) buf++;

		*buf++ = i + '0';
	}

	*buf = '\0';
}

int depth(char *in, int d)
{
	rec_t *r = find_rec(in);

	if (r->depth > 0)
		return r->depth;

	d++;
	if (!r->depth)	r->depth = -d;
	else		r->depth += d;

	count(in);
	d = depth(in, d);

	if (r->depth <= 0) r->depth = d + 1;
	return r->depth;
}

int main(void)
{
	char a[100];
	int i, d, best_len = 0, n_best = 0;
	int best_ints[32];
	rec_t *r;

	init();

	for (i = 0; i < 1000000; i++) {
		sprintf(a, "%d", i);
		d = depth(a, 0);

		if (d < best_len) continue;
		if (d > best_len) {
			n_best = 0;
			best_len = d;
		}
		if (d == best_len)
			best_ints[n_best++] = i;
	}

	printf("longest length: %d\n", best_len);
	for (i = 0; i < n_best; i++) {
		printf("%d\n", best_ints[i]);
		sprintf(a, "%d", best_ints[i]);
		for (d = 0; d <= best_len; d++) {
			r = find_rec(a);
			printf("%3d: %s\n", r->depth, a);
			count(a);
		}
		putchar('\n');
	}

	return 0;
}


#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>

std::map<char, int> _map;
std::vector<std::string> _result;
size_t longest = 0;

void make_sequence( std::string n ) {
    _map.clear();
    for( std::string::iterator i = n.begin(); i != n.end(); i++ )
        _map.insert( std::make_pair( *i, _map[*i]++ ) );

    std::string z;
    for( std::map<char, int>::reverse_iterator i = _map.rbegin(); i != _map.rend(); i++ ) {
        char c = ( *i ).second + 48;
        z.append( 1, c );
        z.append( 1, i->first );
    }

    if( longest <= z.length() ) {
        longest = z.length();
        if( std::find( _result.begin(), _result.end(), z ) == _result.end() ) {
            _result.push_back( z );
            make_sequence( z );
        }
    }
}
int main( int argc, char* argv[] ) {
    std::vector<std::string> tests;
    tests.push_back( "9900" ); tests.push_back( "9090" ); tests.push_back( "9009" );
    for( std::vector<std::string>::iterator i = tests.begin(); i != tests.end(); i++ ) {
        make_sequence( *i );
        std::cout  << "[" << *i << "] Iterations: " << _result.size() + 1 << "\n";
        for( std::vector<std::string>::iterator j = _result.begin(); j != _result.end(); j++ ) {
            std::cout << *j << "\n";
        }
        std::cout << "\n\n";
    }
    return 0;
}


--
-- demo\rosetta\Sutherland_Hodgman_polygon_clipping.exw
-- ====================================================
--
with javascript_semantics
enum X,Y

function inside(sequence cp1, cp2, p)
    return (cp2[X]-cp1[X])*(p[Y]-cp1[Y])>(cp2[Y]-cp1[Y])*(p[X]-cp1[X])
end function

function intersect(sequence cp1, cp2, s, e)
    atom {dcx,dcy} = {cp1[X]-cp2[X],cp1[Y]-cp2[Y]},
         {dpx,dpy} = {s[X]-e[X],s[Y]-e[Y]},
         n1 = cp1[X]*cp2[Y]-cp1[Y]*cp2[X],
         n2 = s[X]*e[Y]-s[Y]*e[X],
         n3 = 1/(dcx*dpy-dcy*dpx)
    return {(n1*dpx-n2*dcx)*n3,(n1*dpy-n2*dcy)*n3}
end function

function sutherland_hodgman(sequence subjectPolygon, clipPolygon)
    sequence cp1 = clipPolygon[$],
      outputList = subjectPolygon
    for i=1 to length(clipPolygon) do
        sequence cp2 = clipPolygon[i],
           inputList = outputList,
                   s = inputList[$]
        outputList = {}
        for j=1 to length(inputList) do
            sequence e = inputList[j]
            if inside(cp1,cp2,e) then
                if not inside(cp1,cp2,s) then
                    outputList = append(outputList,intersect(cp1,cp2,s,e))
                end if
                outputList = append(outputList,e)
            elsif inside(cp1,cp2,s) then
                outputList = append(outputList,intersect(cp1,cp2,s,e))
            end if
            s = e
        end for
        cp1 = cp2
    end for
    return outputList
end function

constant subjectPolygon = {{50, 150}, {200, 50}, {350, 150}, {350, 300},
                           {250, 300}, {200, 250}, {150, 350}, {100, 250},
                           {100, 200}},
         clipPolygon = {{100, 100}, {300, 100}, {300, 300}, {100, 300}}

sequence clippedPolygon = sutherland_hodgman(subjectPolygon,clipPolygon)

include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

procedure draw_poly(sequence poly)
    cdCanvasBegin(cddbuffer,CD_FILL)
    for i=1 to length(poly) do
        atom {x,y} = poly[i]
        cdCanvasVertex(cddbuffer,x,y)
    end for
    cdCanvasEnd(cddbuffer)
end procedure

function redraw_cb(Ihandle /*ih*/)
    cdCanvasActivate(cddbuffer)
    cdCanvasClear(cddbuffer)
    cdCanvasSetForeground(cddbuffer, CD_CYAN)
    draw_poly(subjectPolygon)
    cdCanvasSetForeground(cddbuffer, CD_MAGENTA)
    draw_poly(clipPolygon)
    cdCanvasSetForeground(cddbuffer, CD_ORANGE)
    draw_poly(clippedPolygon)
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_WHITE)
    cdCanvasSetForeground(cddbuffer, CD_GRAY)
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()
    canvas = IupCanvas("RASTERSIZE=400x400")
    IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"),
                             "ACTION", Icallback("redraw_cb")})
    dlg = IupDialog(canvas, "RESIZE=NO")
    IupSetAttribute(dlg, "TITLE", "Sutherland-Hodgman polygon clipping")
    IupShow(dlg)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()


(defmacro reduce-with
  "simplifies form of reduce calls"
  [bindings & body]
  (assert (and (vector? bindings) (= 4 (count bindings))))
  (let [[acc init, item sequence] bindings]
    `(reduce (fn [~acc ~item] [email protected]) ~init ~sequence)))

(defn digits
  "maps e.g. 2345 => [2 3 4 5]"
  [n] (->> n str seq (map #(- (int %) (int \0))) vec))

(defn dcount
  "handles case (probably impossible in this range) of digit count > 9"
  [ds] (let [c (count ds)] (if (< c 10) c (digits c))))

(defn summarize-prev
  "produces the summary sequence for a digit sequence"
  [ds]
  (->> ds (sort >) (partition-by identity) (map (juxt dcount first)) flatten vec)

(defn convergent-sequence
  "iterates summarize-prev until a duplicate is found; returns summary step sequence"
  [ds]
  (reduce-with [cur-seq [], ds (iterate summarize-prev ds)]
    (if (some #{ds} cur-seq)
      (reduced cur-seq)
      (conj cur-seq ds))))

(defn candidate-seq
  "only try an already sorted digit sequence, so we only try equivalent seeds once;
   e.g. 23 => []; 32 => (convergent-sequence [3 2])"
  [n]
  (let [ds (digits n)]
    (if (apply >= ds) (convergent-sequence ds) [])))

(defn find-longest
  "the meat of the task; returns summary step sequence(s) of max length within the range"
  [limit]
  (reduce-with [max-seqs [[]], new-seq (map candidate-seq (range 1 limit))]
    (let [cmp (compare (-> max-seqs first count) (count new-seq))]
      (cond
        (pos? cmp) max-seqs
        (neg? cmp) [new-seq]
        (zero? cmp) (conj max-seqs new-seq)))))

(def results (find-longest 1000000))


summarize = proc (s: string) returns (string) signals (bad_format)
    digit_count: array[int] := array[int]$fill(0,10,0)
    for c: char in string$chars(s) do
        d: int := int$parse(string$c2s(c)) resignal bad_format
        digit_count[d] := digit_count[d] + 1
    end

    out: stream := stream$create_output()
    for d: int in int$from_to_by(9,0,-1) do
        if digit_count[d]>0 then
            stream$puts(out, int$unparse(digit_count[d]))
            stream$puts(out, int$unparse(d))
        end
    end

    return(stream$get_contents(out))
end summarize

converge = proc (s: string) returns (int) signals (bad_format)
    seen: array[string] := array[string]$[]
    steps: int := 0
    while true do
        for str: string in array[string]$elements(seen) do
            if str = s then return(steps) end
        end
        array[string]$addh(seen, s)
        s := summarize(s)
        steps := steps + 1
    end
end converge

start_up = proc ()
    po: stream := stream$primary_output()

    seeds: array[int]
    max: int := 0
    for i: int in int$from_to(1, 999999) do
        steps: int := converge(int$unparse(i))
        if steps > max then
            max := steps
            seeds := array[int]$[i]
        elseif steps = max then
            array[int]$addh(seeds,i)
        end
    end

    stream$puts(po, "Seed values: ")
    for i: int in array[int]$elements(seeds) do
        stream$puts(po, int$unparse(i) || " ")
    end

    stream$putl(po, "\nIterations: " || int$unparse(max))
    stream$putl(po, "\nSequence: ")

    s: string := int$unparse(array[int]$bottom(seeds))
    for i: int in int$from_to(1, max) do
        stream$putl(po, s)
        s := summarize(s)
    end
end start_up


sequence = (n) ->
  cnts = {}
  for c in n.toString()
    d = parseInt(c)
    incr cnts, d

  seq = []
  while true
    s = ''
    for i in [9..0]
      s += "#{cnts[i]}#{i}" if cnts[i]
    if s in seq
      break
    seq.push s

    new_cnts = {}
    for digit, cnt of cnts
      incr new_cnts, cnt
      incr new_cnts, digit
    cnts = new_cnts
  seq

incr = (h, k) ->
  h[k] ?= 0
  h[k] += 1

descending = (n) ->
  return true if n < 10
  tens = n / 10
  return false if n % 10 > tens % 10
  descending(tens)

max_len = 0
for i in [1..1000000]
  if descending(i)
    seq = sequence(i)
    if seq.length > max_len
      max_len = seq.length
      max_seq = seq
      max_i = i

console.log max_i, max_seq


Structure point_f
  x.f
  y.f
EndStructure

Procedure isInside(*p.point_f, *cp1.point_f, *cp2.point_f)
  If (*cp2\x - *cp1\x) * (*p\y - *cp1\y) > (*cp2\y - *cp1\y) * (*p\x - *cp1\x)
    ProcedureReturn 1
  EndIf
EndProcedure

Procedure intersection(*cp1.point_f, *cp2.point_f, *s.point_f, *e.point_f, *newPoint.point_f)
  Protected.point_f dc, dp
  Protected.f n1, n2, n3
  dc\x = *cp1\x - *cp2\x: dc\y = *cp1\y - *cp2\y
  dp\x = *s\x - *e\x: dp\y = *s\y - *e\y
  n1 = *cp1\x * *cp2\y - *cp1\y * *cp2\x
  n2 = *s\x * *e\y - *s\y * *e\x
  n3 = 1 / (dc\x * dp\y - dc\y * dp\x)
  *newPoint\x = (n1 * dp\x - n2 * dc\x) * n3: *newPoint\y = (n1 * dp\y - n2 * dc\y) * n3
EndProcedure

Procedure clip(List vPolygon.point_f(), List vClippedBy.point_f(), List vClippedPolygon.point_f())
  Protected.point_f cp1, cp2, s, e, newPoint
  CopyList(vPolygon(), vClippedPolygon())
  If LastElement(vClippedBy())
    cp1 = vClippedBy()

    NewList vPreClipped.point_f()
    ForEach vClippedBy()
      cp2 = vClippedBy()
      CopyList(vClippedPolygon(), vPreClipped())
      ClearList(vClippedPolygon())
      If LastElement(vPreClipped())
        s = vPreClipped()
        ForEach vPreClipped()
          e = vPreClipped()
          If isInside(e, cp1, cp2)
            If Not isInside(s, cp1, cp2)
              intersection(cp1, cp2, s, e, newPoint)
              AddElement(vClippedPolygon()): vClippedPolygon() = newPoint
            EndIf
            AddElement(vClippedPolygon()): vClippedPolygon() = e
          ElseIf isInside(s, cp1, cp2)
            intersection(cp1, cp2, s, e, newPoint)
            AddElement(vClippedPolygon()): vClippedPolygon() = newPoint
          EndIf
          s = e
        Next
      EndIf
      cp1 = cp2
    Next
  EndIf
EndProcedure

DataSection
  Data.f 50,150, 200,50, 350,150, 350,300, 250,300, 200,250, 150,350, 100,250, 100,200 ;subjectPolygon's vertices (x,y)
  Data.f 100,100, 300,100, 300,300, 100,300 ;clipPolygon's vertices (x,y)
EndDataSection

NewList subjectPolygon.point_f()
For i = 1 To 9
  AddElement(subjectPolygon())
  Read.f subjectPolygon()\x
  Read.f subjectPolygon()\y
Next

NewList clipPolygon.point_f()
For i = 1 To 4
  AddElement(clipPolygon())
  Read.f clipPolygon()\x
  Read.f clipPolygon()\y
Next

NewList newPolygon.point_f()
clip(subjectPolygon(), clipPolygon(), newPolygon())
If OpenConsole()
  ForEach newPolygon()
    PrintN("(" + StrF(newPolygon()\x, 2) + ", " + StrF(newPolygon()\y, 2) + ")")
  Next

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


(defun count-and-say (str)
   (let* ((s (sort (map 'list #'identity str) #'char>))
	  (out (list (first s) 0)))
     (loop for x in s do
	   (if (char= x (first out))
	     (incf (second out))
	     (setf out (nconc (list x 1) out))))
     (format nil "~{~a~^~}" (nreverse out))))

(defun ref-seq-len (n &optional doprint)
  (let ((s (format nil "~d" n)) hist)
    (loop (push s hist)
	  (if doprint (format t "~a~%" s))
	  (setf s (count-and-say s))
	  (loop for item in hist
		for i from 0 to 2 do
		(if (string= s item) (return-from ref-seq-len (length hist)))))))

(defun find-longest (top)
  (let (nums (len 0))
  (dotimes (x top)
    (let ((l (ref-seq-len x)))
      (if (> l len) (setf len l nums nil))
      (if (= l len) (push x nums))))
  (list nums len)))

(let ((r (find-longest 1000000)))
  (format t "Longest: ~a~%" r)
  (ref-seq-len (first (first r)) t))


def clip(subjectPolygon, clipPolygon):
   def inside(p):
      return(cp2[0]-cp1[0])*(p[1]-cp1[1]) > (cp2[1]-cp1[1])*(p[0]-cp1[0])

   def computeIntersection():
      dc = [ cp1[0] - cp2[0], cp1[1] - cp2[1] ]
      dp = [ s[0] - e[0], s[1] - e[1] ]
      n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0]
      n2 = s[0] * e[1] - s[1] * e[0]
      n3 = 1.0 / (dc[0] * dp[1] - dc[1] * dp[0])
      return [(n1*dp[0] - n2*dc[0]) * n3, (n1*dp[1] - n2*dc[1]) * n3]

   outputList = subjectPolygon
   cp1 = clipPolygon[-1]

   for clipVertex in clipPolygon:
      cp2 = clipVertex
      inputList = outputList
      outputList = []
      s = inputList[-1]

      for subjectVertex in inputList:
         e = subjectVertex
         if inside(e):
            if not inside(s):
               outputList.append(computeIntersection())
            outputList.append(e)
         elif inside(s):
            outputList.append(computeIntersection())
         s = e
      cp1 = cp2
   return(outputList)


import std.stdio, std.algorithm, std.conv;

string[] selfReferentialSeq(string n, string[] seen=[]) nothrow {
    __gshared static string[][string] cache;
    if (n in cache)
        return cache[n];
    if (seen.canFind(n))
        return [];

    int[10] digit_count;
    foreach (immutable d; n)
        digit_count[d - '0']++;
    string term;
    foreach_reverse (immutable d; 0 .. 10)
        if (digit_count[d] > 0)
            term ~= text(digit_count[d], d);
    return cache[n] = [n] ~ selfReferentialSeq(term, [n] ~ seen);
}

void main() {
    enum int limit = 1_000_000;
    int max_len;
    int[] max_vals;

    foreach (immutable n; 1 .. limit) {
        const seq = n.text().selfReferentialSeq();
        if (seq.length > max_len) {
            max_len = seq.length;
            max_vals = [n];
        } else if (seq.length == max_len)
            max_vals ~= n;
    }

    writeln("values: ", max_vals);
    writeln("iterations: ", max_len);
    writeln("sequence:");
    foreach (const idx, const val; max_vals[0].text.selfReferentialSeq)
        writefln("%2d %s", idx + 1, val);
}


#lang racket

(module sutherland-hodgman racket
  (provide clip-to)
  (provide make-edges)
  (provide (struct-out point))

  (struct point (x y) #:transparent)
  (struct edge (p1 p2) #:transparent)
  (struct polygon (points edges) #:transparent)

  (define (make-edges points)
    (let ([points-shifted
	   (match points
	     [(list a b ...) (append b (list a))])])
      (map edge points points-shifted)))

  (define (is-point-left? pt ln)
    (match-let ([(point x y) pt]
                [(edge (point px py) (point qx qy)) ln])
               (>= (* (- qx px) (- y py))
                   (* (- qy py) (- x px)))))

  ;; Return the intersection of two lines
  (define (isect-lines l1 l2)
    (match-let ([(edge (point x1 y1) (point x2 y2)) l1]
                [(edge (point x3 y3) (point x4 y4)) l2])
               (let* ([r (- (* x1 y2) (* y1 x2))] [s (- (* x3 y4) (* y3 x4))]
                      [t (- x1 x2)] [u (- y3 y4)] [v (- y1 y2)] [w (- x3 x4)]
                      [d (- (* t u) (* v w))])
                 (point (/ (- (* r w) (* t s)) d)
                        (/ (- (* r u) (* v s)) d)))))

  ;; Intersect the line segment (p0,p1) with the clipping line's left halfspace,
  ;; returning the point closest to p1.  In the special case where p0 lies outside
  ;; the halfspace and p1 lies inside we return both the intersection point and p1.
  ;; This ensures we will have the necessary segment along the clipping line.

  (define (intersect segment clip-line)
    (define (isect) (isect-lines segment clip-line))

    (match-let ([(edge p0 p1) segment])
               (match/values (values (is-point-left? p0 clip-line) (is-point-left? p1 clip-line))
                             [(#f #f) '()]
                             [(#f #t) (list (isect) p1)]
                             [(#t #f) (list (isect))]
                             [(#t #t) (list p1)])))

  ;; Intersect the polygon with the clipping line's left halfspace
  (define (isect-polygon poly-edges clip-line)
    (for/fold ([p '()]) ([e  poly-edges])
      (append p (intersect e clip-line))))

  ;; Intersect a subject polygon with a clipping polygon.  The latter is assumed to be convex.
  (define (clip-to sp-pts cp-edges)
    (for/fold ([out-poly sp-pts]) ([clip-line cp-edges])
      (isect-polygon (make-edges out-poly) clip-line))))


(lib 'hash)
(lib 'list) ;; permutations

(define H (make-hash))

;; G R A P H
;; generate 'normalized' starter vectors  D[i] = number of digits 'i' (0 <=i < 10)
;; reduce graph size : 9009, 9900 ..  will be generated once : vector #(2 0 0 0 0 0 0 0 0 2)

(define (generate D dstart ndigits (sd 0))
(when (> ndigits 0)
	(set! sd (vector-ref D dstart)) ;; save before recurse
	(for ((i (in-range 0 (1+ ndigits))))
		#:continue (and ( = i 0) (> dstart 0))
		(vector-set! D dstart i)
		(sequence D) ;; sequence length from D
		(for ((j (in-range (1+ dstart) 10)))
		(generate D j  (- ndigits i))))
	(vector-set! D dstart sd))) ;; restore

;; compute follower of D (at most 99 same digits)
(define (dnext D (dd 0))
	(define N (make-vector 10))
	(for ((d D) (i 10))
		#:continue (zero? d)
		(vector-set! N i (1+ (vector-ref N i)))
		(if (< d 10)
		(vector-set! N d (1+ (vector-ref N d))) ;; d < 9
		(begin
		(set! dd (modulo d 10))
		(vector-set! N dd (1+ (vector-ref N dd)))
		(set! dd (quotient d 10))
		(vector-set! N dd (1+ (vector-ref N dd))))))
		N)

;; update all nodes in same sequence
;; seq-length (next D) = 1 - seq-length(D)
(define (sequence D)
(define (dists D d)
	(unless (hash-ref H D)
		  (hash-set H  D d)
		  (dists (dnext D ) (1- d))))

		(unless  (hash-ref H D)
				 (dists D (sequence-length D))))

;; sequence length from D
;; stops on loop found (node N)
(define (sequence-length D )
(define (looper N looplg depth) ;; looper 2 : a b a
	(when ( > depth 0)
			(hash-set H N looplg)
			(looper (dnext N)  looplg (1- depth))))

		(define followers (make-hash))
		(define N (dnext D))
		(define seqlg 0)
		(define looplg 0)

		(hash-set followers D 0)

	(set! seqlg
		(for ((lg (in-naturals 1 )))
			 #:break (hash-ref H N) =>  (+ lg (hash-ref H N)) ;; already known
			 #:break (hash-ref followers N) => lg ;; loop found
			 (hash-set followers N lg)
			 (set! N (dnext N))))

;; update nodes in loop : same seq-length
		(when (hash-ref followers N) ;; loop found
			(set! looplg  ( - seqlg  (hash-ref followers N)))
			(looper N looplg looplg))

		seqlg )

;; O U T P U T
;; backwards from D - normalized vector - to numbers (as strings)
(define (starters D)
(define (not-leading-zero list) (!zero? (first list)))
	(map list->string
	(filter not-leading-zero (make-set (permutations (for/fold (acc null) ((d D) (i 10))
		#:continue (zero? d)
		(append acc   (for/list ((j d)) i))))))))

;; printing one node
(define (D-print D)
	 (set! D (reverse (vector->list D)))
	 (for/string ( (d D) (i (in-range 9 -1 -1)))
		#:continue (zero? d)
		(string-append d i)))

;; print graph contents
(define (print-sequence D)
		(writeln 1 (starters D))
		(writeln 2 (D-print D ))
		(for ((i (in-range 1 (hash-ref H D))))
			(writeln (+ i 2)  (D-print (setv! D (dnext D))))))

;; TA S K
(define (task (n 6)  (verbose #t))
	(generate (make-vector 10) 0 n)
	(define seqmax (apply max (hash-values H)))
	(when verbose (for ((kv H))
		#:continue (!= (rest kv ) seqmax)
		(print-sequence (first kv))))

	(writeln (expt 10 n) '--> 'max-sequence= (1+ seqmax)  'nodes= (length (hash-values H))))


sub intersection ($L11, $L12, $L21, $L22) {
    my ($Δ1x, $Δ1y) = $L11 »-« $L12;
    my ($Δ2x, $Δ2y) = $L21 »-« $L22;
    my $n1 = $L11[0] * $L12[1] - $L11[1] * $L12[0];
    my $n2 = $L21[0] * $L22[1] - $L21[1] * $L22[0];
    my $n3 = 1 / ($Δ1x * $Δ2y - $Δ2x * $Δ1y);
    (($n1 * $Δ2x - $n2 * $Δ1x) * $n3, ($n1 * $Δ2y - $n2 * $Δ1y) * $n3)
}

sub is-inside ($p1, $p2, $p3) {
    ($p2[0] - $p1[0]) * ($p3[1] - $p1[1]) > ($p2[1] - $p1[1]) * ($p3[0] - $p1[0])
}

sub sutherland-hodgman (@polygon, @clip) {
    my @output = @polygon;
    my $clip-point1 = @clip.tail;
    for @clip -> $clip-point2 {
        my @input = @output;
        @output = ();
        my $start = @input.tail;
        for @input -> $end {
            if is-inside($clip-point1, $clip-point2, $end) {
                @output.push: intersection($clip-point1, $clip-point2, $start, $end)
                  unless is-inside($clip-point1, $clip-point2, $start);
                @output.push: $end;
            } elsif is-inside($clip-point1, $clip-point2, $start) {
                @output.push: intersection($clip-point1, $clip-point2, $start, $end);
            }
            $start = $end;
        }
        $clip-point1 = $clip-point2;
    }
    @output
}

my @polygon = (50,  150), (200, 50),  (350, 150), (350, 300), (250, 300),
              (200, 250), (150, 350), (100, 250), (100, 200);

my @clip    = (100, 100), (300, 100), (300, 300), (100, 300);

my @clipped = sutherland-hodgman(@polygon, @clip);

say "Clipped polygon: ", @clipped;

# Output an SVG as well as it is easier to visualize
use SVG;
my $outfile = 'Sutherland-Hodgman-polygon-clipping-perl6.svg'.IO.open(:w);
$outfile.say: SVG.serialize(
    svg => [
        :400width, :400height,
        :rect[ :400width, :400height, :fill<white> ],
        :text[ :10x, :20y, "Polygon (blue)" ],
        :text[ :10x, :35y, "Clip port (green)" ],
        :text[ :10x, :50y, "Clipped polygon (red)" ],
        :polyline[ :points(@polygon.join: ','), :style<stroke:blue>,  :fill<blue>,  :opacity<.3> ],
        :polyline[ :points(   @clip.join: ','), :style<stroke:green>, :fill<green>, :opacity<.3> ],
        :polyline[ :points(@clipped.join: ','), :style<stroke:red>,   :fill<red>,   :opacity<.5> ],
    ],
);


class
	SELF_REFERENTIAL_SEQUENCE

create
	make

feature

	make
		local
			i: INTEGER
			length, max: INTEGER_64
		do
			create seed_value.make
			create sequence.make (25)
			create permuted_values.make
			from
				i := 1
			until
				i > 1000000
			loop
				length := check_length (i.out)
				if length > max then
					max := length
					seed_value.wipe_out
					seed_value.extend (i)
				elseif length = max then
					seed_value.extend (i)
				end
				sequence.wipe_out
				i := next_ascending (i).to_integer
			end
			io.put_string ("Maximal length: " + max.out)
			io.put_string ("%NSeed Value: %N")
			across
				seed_value as s
			loop
				permute (s.item.out, 1)
			end
			across
				permuted_values as p
			loop
				io.put_string (p.item + "%N")
			end
			io.put_string ("Sequence:%N")
			max := check_length (seed_value [1].out)
			across
				sequence as s
			loop
				io.put_string (s.item)
				io.new_line
			end
		end

	next_ascending (n: INTEGER_64): STRING
			-- Next number with ascending digits after 'n'.
			-- Numbers with trailing zeros are treated as ascending numbers.
		local
			st: STRING
			first, should_be, zero: STRING
			i: INTEGER
		do
			create Result.make_empty
			create zero.make_empty
			st := (n + 1).out
			from
			until
				st.count < 2
			loop
				first := st.at (1).out
				if st [2] ~ '0' then
					from
						i := 3
					until
						i > st.count
					loop
						zero.append ("0")
						i := i + 1
					end
					Result.append (first + first + zero)
					st := ""
				else
					should_be := st.at (2).out
					if first > should_be then
						should_be := first
					end
					st.remove_head (2)
					st.prepend (should_be)
					Result.append (first)
				end
			end
			if st.count > 0 then
				Result.append (st [st.count].out)
			end
		end

feature {NONE}

	seed_value: SORTED_TWO_WAY_LIST [INTEGER]

	permuted_values: SORTED_TWO_WAY_LIST [STRING]

	sequence: ARRAYED_LIST [STRING]

	permute (a: STRING; k: INTEGER)
			-- All permutations of 'a'.
		require
			count_positive: a.count > 0
			k_valid_index: k > 0
		local
			t: CHARACTER
			b: STRING
			found: BOOLEAN
		do
			across
				permuted_values as p
			loop
				if p.item ~ a then
					found := True
				end
			end
			if k = a.count and a [1] /= '0' and not found then
				create b.make_empty
				b.deep_copy (a)
				permuted_values.extend (b)
			else
				across
					k |..| a.count as c
				loop
					t := a [k]
					a [k] := a [c.item]
					a [c.item] := t
					permute (a, k + 1)
					t := a [k]
					a [k] := a [c.item]
					a [c.item] := t
				end
			end
		end

	check_length (i: STRING): INTEGER_64
			-- Length of the self referential sequence starting with 'i'.
		local
			found: BOOLEAN
			j: INTEGER
			s: STRING
		do
			create s.make_from_string (i)
			from
			until
				found
			loop
				sequence.extend (s)
				s := next (s)
				from
					j := sequence.count - 1
				until
					j < 1
				loop
					if sequence [j] ~ s then
						found := True
					end
					j := j - 1
				end
			end
			Result := sequence.count
		end

	next (n: STRING): STRING
			-- Next item after 'n' in a self referential sequence.
		local
			i, count: INTEGER
			counter: ARRAY [INTEGER]
		do
			create counter.make_filled (0, 0, 9)
			create Result.make_empty
			from
				i := 1
			until
				i > n.count
			loop
				count := n [i].out.to_integer
				counter [count] := counter [count] + 1
				i := i + 1
			end
			from
				i := 9
			until
				i < 0
			loop
				if counter [i] > 0 then
					Result.append (counter [i].out + i.out)
				end
				i := i - 1
			end
		end

end