Gift Wrapping Algorithm

Gift wrapping is the act of enclosing a gift in some sort of material. An option to gift wrapping is use a gift box or bag. Although the Hall brothers Rollie and Joyce Hall, founders of Hallmark card, make not invent gift wrapping, their innovations led to the development of modern gift wrapping. They helped to popularize the idea of decorative gift wrapping in the 20th century, and according to Joyce Hall," the decorative gift-wrapping business was birth the day Rollie put those French envelope linings on top of that showcase."The purpose of wrapping paper is first documented in ancient China, where paper was invented in 2nd century BC.
/*
 * Copyright (c) 2017 Kotlin Algorithm Club
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.algorithmexamples.geometry.convexhull

import com.algorithmexamples.datastructures.Stack
import com.algorithmexamples.geometry.Point

class GiftWrapping: ConvexHullAlgorithm {
    override fun convexHull(points: Array<Point>): Collection<Point> {
        if (points.size < 3) throw IllegalArgumentException("there must be at least 3 points")

        val hull = Stack<Point>()

        // Find the leftmost point
        var l = 0
        points.indices
                .asSequence()
                .filter { points[it].x < points[l].x }
                .forEach { l = it }

        // Start from leftmost point, keep moving counterclockwise
        // until reach the start point again.  This loop runs O(h)
        // times where h is number of points in result or output.
        var p = l
        var q: Int
        do {
            // Add current point to result
            hull.push(points[p])

            // Search for a point 'q' such that orientation(p, x,
            // q) is counterclockwise for all points 'x'. The idea
            // is to keep track of last visited most counterclock-
            // wise point in q. If any point 'i' is more counterclock-
            // wise than q, then update q.
            q = ( p+ 1) % points.size
            points.indices
                    .asSequence()
                    .filter { Point.orientation(points[p], points[it], points[q]) < 0 }
                    .forEach { q = it }

            // Now q is the most counterclockwise with respect to p
            // Set p as q for next iteration, so that q is added to
            // result 'hull'
            p = q

        } while (p != l)  // While we don't come to first point

        return hull
    }
}

LANGUAGE:

DARK MODE: