<commit_before>module Geom ( Point (..)
            , Polygon
            , Segment
            , cross
            , lengthSquared
            , getArea
            , isCCW
            , sub
            , convexHull
            ) where

import Data.Ratio

data Point = Point { getX :: Rational
                   , getY :: Rational
                   } deriving (Eq, Show, Ord)

sub :: Point -> Point -> Point
sub (Point x1 y1) (Point x2 y2) = Point (x1 - x2) (y1 - y2)

cross :: Point -> Point -> Rational
cross (Point x1 y1) (Point x2 y2) = x1 * y2 - x2 * y1

lengthSquared :: Point -> Rational
lengthSquared (Point x y) = x * x + y * y

type Polygon = [Point]

type Segment = (Point, Point)

getArea :: Polygon -> Rational
getArea (origin:points) = sum $ zipWith area points (tail points)
    where area p1 p2 = cross (p1 `sub` origin) (p2 `sub` origin)

isCCW :: Polygon -> Bool
isCCW polygon = (getArea polygon) > 0


chooseNext :: Point -> [Point] -> Point
chooseNext o [] = o
chooseNext o (p1:ps)
  | p2 == o = p1
  | cr > 0 || (cr == 0 && len1 > len2) = p1
  | otherwise = p2
  where p2 = chooseNext o ps
        p1' = sub p1 o
        p2' = sub p2 o
        cr = cross p1' p2'
        len1 = lengthSquared p1'
        len2 = lengthSquared p2'

convexHullImpl :: Bool -> Point -> Point -> Polygon -> Polygon
convexHullImpl first o mp ps
  | o == mp && not first = []
  | otherwise = o:nps
  where nps = convexHullImpl False (chooseNext o ps) mp ps

convexHull :: Polygon -> Polygon
convexHull ps = convexHullImpl True mp mp ps
                where mp = minimum ps<commit_msg>Added an ordering for points.<commit_after>module Geom ( Point (..)
            , Polygon
            , Segment
            , cross
            , lengthSquared
            , getArea
            , isCCW
            , sub
            , convexHull
            ) where

import Data.Ratio
import Data.List

data Point = Point { getX :: Rational
                   , getY :: Rational
                   } deriving (Eq, Show, Ord)

sub :: Point -> Point -> Point
sub (Point x1 y1) (Point x2 y2) = Point (x1 - x2) (y1 - y2)

cross :: Point -> Point -> Rational
cross (Point x1 y1) (Point x2 y2) = x1 * y2 - x2 * y1

lengthSquared :: Point -> Rational
lengthSquared (Point x y) = x * x + y * y

type Polygon = [Point]

type Segment = (Point, Point)

getArea :: Polygon -> Rational
getArea (origin:points) = sum $ zipWith area points (tail points)
    where area p1 p2 = cross (p1 `sub` origin) (p2 `sub` origin)

isCCW :: Polygon -> Bool
isCCW polygon = (getArea polygon) > 0

ordPoints :: Point -> Point -> Point -> Ordering
ordPoints o p1 p2
  | c > 0 = LT
  | c < 0 = GT
  | c == 0 = compare l2 l1
  where p1' = p1 `sub` o
        p2' = p2 `sub` o 
        c = cross p1' p2'
        l1 = lengthSquared p1' 
        l2 = lengthSquared p2'

convexHullImpl :: Bool -> Point -> Point -> Polygon -> Polygon
convexHullImpl first o mp ps
  | o == mp && not first = []
  | otherwise = o:nps
  where nps = convexHullImpl False (minimumBy (ordPoints o) ps) mp ps  

convexHull :: Polygon -> Polygon
convexHull ps = convexHullImpl True mp mp ps
                where mp = minimum ps
{'fraction_non_alphanumeric': 0.11206349206349206, 'fraction_numerical': 0.02507936507936508, 'mean_word_length': 1.9980970504281637, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6218481', 'n_tokens_mistral': 1110, 'n_tokens_neox': 1051, 'n_words': 378}