Beta

Connect the dots - how many laps?

Description:

Task

You are given a list of points (x,y pairs) representing a closed path. The path is obtained connecting all points in order, and last point to first point: path[0]->path[1]->path[2]->...->path[-1]->path[0].

x axis is horizontal and oriented to the right, y axis is vertical and oriented upwards.

The path can intersect and/or overlap itself.

The path can't reverse direction with a 180 degree about-face.

Your task is to determine direction of path (clockwise or counterclockwise) and count laps.

Turning 360 degrees in one direction counts as a lap (360° left -> one lap counterclockwise; 360° right -> one lap clockwise). The path can change turn direction at any point (sometime turns right, sometime turns left). Order of turns doesn't matter, only total counts. Turns in opposite directions compensate each other.

Examples

Simple polygons -> one lap

  • [(0,0), (1,0), (1,1), (0,1)] -> one lap counterclockwise
  • [(0,0), (0,1), (1,1), (1,0)] -> one lap clockwise

A simple polygon repeated twice -> two laps

  • [(0,0), (1,0), (1,1), (0,0), (1,0), (1,1)] -> two laps counterclockwise

Eight-shaped paths -> net total: zero laps (turns in opposite directions compensate each other)

  • [(0,0), (1,1), (1,0), (0,1)] -> zero laps

Step-by-step example: [(0,0), (1,1), (1,0), (2,1), (0,1)]

  • start at 0,0
  • at 1,1: turn 135° right
  • at 1,0: turn 135° left (compensate previos turn)
  • at 2,1: turn 135° left
  • at 0,1: turn 90° left
  • at 0,0: turn 135° left (path is closed)

Net total is 360° left -> one lap counterclockwise.

Input

  • path [list of tuples]: points; format is [(x0,y0), (x1,y1), ... (xn,yn)].

    x and y coordinates are floats and can assume any value between -1000.0 and 1000.0.

    Input is always valid and there are at least 3 points.

Output

  • [integer] number of laps; positive if countercloskwise, negative if clockwise.

Test cases

  • 17 basic tests: short paths (3-24 point) with some longer path up to 650 points;
  • 18 "circuit" tests: long paths up to 4,000 points (average ~1,000 points);
  • 65 "doodle" tests: medium paths up to 200 points.

Plotting paths

Plotting paths isn't needed to solve kata, but may be useful to ease debugging (or to satisfy curiosity).

You can plot paths on your comupter using turtle graphics and a function like this (turtle needs a display and does't work on codewars server):

import turtle
from math import atan2

def plot(path, auto=True, speed=None):
    if auto:
        width, height = turtle.screensize() # NOTE: on my PC screensize() != actual widow size
        xs, ys = zip(*path)
        minx, maxx = min(xs), max(xs)
        miny, maxy = min(ys), max(ys)
        center = (minx + maxx) / 2, (miny + maxy) / 2
        scale = min(width/(maxx-minx), height/(maxy-miny))
    else:
        center = 0, 0
        scale = 1
    def scaled(p):
        return (p[0]-center[0])*scale, (p[1]-center[1])*scale
    turtle.clearscreen()
    if speed: turtle.speed(speed)
    turtle.up()
    turtle.goto(scaled(path[0]))
    turtle.down()
    for point in path[1:]+path[:1]:
        turtle.goto(scaled(point))
    turtle.radians()
    turtle.setheading(atan2(path[1][1]-path[0][1], path[1][0]-path[0][0]))
Mathematics
Algorithms

Stats:

CreatedNov 28, 2020
PublishedNov 28, 2020
Warriors Trained132
Total Skips40
Total Code Submissions38
Total Times Completed9
Python Completions9
Total Stars3
% of votes with a positive feedback rating100% of 2
Total "Very Satisfied" Votes2
Total "Somewhat Satisfied" Votes0
Total "Not Satisfied" Votes0
Total Rank Assessments2
Average Assessed Rank
6 kyu
Highest Assessed Rank
6 kyu
Lowest Assessed Rank
6 kyu
Ad
Contributors
  • mauro-1 Avatar
Ad