title: Computer Generated Cracked Soil

text:
# Question
Title: Computer Generated Cracked Soil
Write a program that takes in an integer from 0 to 65535 (216-1) and generates a *unique* 500×500 pixel image that looks as similar as possible to these 6 real life images of cracked soil:

**These are thumbnails, click them to see the full-size 500×500 images.**

The goal here is to **make your computer generated images as photorealistic as possible**. So ideally, if any of the images output by your program were mixed in with the 6 images above, someone seeing the images for the first time would not be able to tell the computer generated ones apart from the real ones.

Perfect photorealism is tricky however, so just do the best you can. This is a so the answers that have more realistic outputs will be upvoted more and be more likely to win.

## Rules

* You may use image processing functions or libraries.
* You may base your algorithm on information gathered from the 6 sample images, but your 65536 (216) possible output images should be visually distinct from each other *and* the sample images, especially with regard to the arrangement of the cracks. You must truly generate your images, don't just rotate and translate a selection from a preexisting photo.
* You should not otherwise hardcode your outputs. A generic algorithm should be used and numbers larger than 65535 should theoretically produce valid outputs. (I've restricted it merely to accommodate small-maximum integer types.)
* The input integer can be thought of as a seed that results in a random cracked soil output image. It should be deterministic though, so the same input should always result in the same output.
* The output images must be exactly 500×500 pixels.
* The output images may be saved in any common image file format, or simply displayed.
* Be sure to include a few example output images in your answer, and their corresponding input numbers.
* **The answer with the most votes wins.** Voters should of course upvote answers that attempt to produce images similar to the 6 samples, and downvote answers that break rules or give inconsistent results.

The 6 sample images were taken from texturelib.com. 1000×1000 pixel area selections were taken from two larger images of cracked soil and then resized to 500×500. You may use analysis from these larger images in your program but the output should specifically imitate the 6 chosen sample images.

# Answer
# Mathematica

A Voronoi diagram looks like this drawing, from Wikipedia, showing 19 cells, each containing a single seed point. A cell consists of the subregion of points which the respective generating point is closer to than any of the other seed points.

The code below generates a diagram from 80 random points (in the square region bound by (-1,-1) and (1,1)).

It uses the polygon primitives (in 2D) in the diagram to build polyhedra (in 3D). Imagine that each polygon has, just under it, a translation (-.08 in z) of itself. Think of the two polygons as the upper and lower face of a polyhedron. "Side faces" are then added to complete the polyhedron.

Each polyhedron is then translated outwards, from the center of the image, on the xy plane; it moves away from the middle. The magnitude of the translation varies directly with the distance between the polyhedron's original generating random point and the center of the screen. This "spreading out" of the polyhedra in the xy plane results in crevices.

```
crackedMud[1]

```

##

```
crackedMud[65535]

```

##

## Code

```
ClearAll[polyhedronFromPolygon, voronoiPolygons, generatingPointFromPolygon, crackedMud]

(* polyhedronFromPolygon returns a single polyhedron from a polygon *)

polyhedronFromPolygon[polygon_] :=
 Module[{twoPolygons, verticesOfUpperPolygonCell, nVertices, n = 1},
 verticesOfUpperPolygonCell = Join @@ (polygon[[1]] /. {x_, y_} :> {{x, y, 0}, {x, y, -.08}});
 (* number of vertices in a single *Voronoi* cell *)
 nVertices = Length[verticesOfUpperPolygonCell]/2;

(*vertex indices of the upper and lower polygon faces *)
twoPolygons = Select[Range@(2*nVertices), #] & /@ {OddQ, EvenQ};

(*vertex indices of a rectangular face of the polyhedron *)
While[n < nVertices + 1, AppendTo[twoPolygons,
    {twoPolygons[[1, n]], twoPolygons[[2, n]],
     twoPolygons[[2, If[n + 1 < nVertices + 1, n + 1, 1]]],
     twoPolygons[[1, If[n + 1 < nVertices + 1, n + 1, 1]]]}]; n++];
(*the graphics complex returned is a polyhedron, even though it says Polygon *)
 GraphicsComplex[verticesOfUpperPolygonCell, Polygon[twoPolygons]] ]

(* takes two dimensional coordinates and returns all of the cells of a Voronoi diagram *)

voronoiPolygons[pts_] :=
Module[{voronoiRegion, data},
  voronoiRegion = VoronoiMesh[pts, ImageSize -> Medium,
  PlotTheme -> "Lines", Axes -> True, AxesOrigin -> {0, 0}];
  data = Join @@ (MeshPrimitives[voronoiRegion, 2][[All, 1]] /. {x_, y_} :> {{x, y, 0}, {x, y, .04}});
 (* the mesh primitives are the polygons *)
  MeshPrimitives[voronoiRegion, 2]]

(* Returns, in 3D, the point which was used to generate the nth Voronoi cell. *)
generatingPointFromPolygon[n_, points_, pgons_] :=
 FirstCase[points, {x_, y_} /; RegionMember[pgons[[n]], {x, y}] :> {x,y,0}]

crackedMud[seedNumber_] :-
 Module[{pts, pts3D, geometricImage, nPts, polygons, polyhedra, centerPtinImage},
  SeedRandom[seedNumber];
  nPts = 80;
  pts = RandomReal[{-1, 1}, {nPts, 2}];
  pts3D = pts /. {x_, y_} :> {x, y, .0};
  polygons = voronoiPolygons[pts];
  polyhedra = polyhedronFromPolygon /@ polygons;
  centerPtinImage =   (Mean /@ (PlotRange /.
        AbsoluteOptions[
         Graphics3D[{polyhedra, Blue, Point@pts3D}, Axes -> False,
         Boxed -> False]])) /. {x_Real, y_, _} :> {x, y, 0};
  geometricImage =
  Graphics3D[{RGBColor[0.75, 0.75, 0.8], EdgeForm[Darker@Gray],
        (* # is the nth polygon which yields the nth polyhedron *)
        (* generatingPointFromPolygon returns the point the generated the #th polygon *)

     GeometricTransformation[{polyhedronFromPolygon[polygons[[#]]]},
        TranslationTransform[(generatingPointFromPolygon[#, pts, polygons] - centerPtinImage)/5]] & /@ Range@nPts},
         Axes -> False,  Boxed -> False, ViewPoint -> {0., -1, 1.5},
         Background -> Black, ImageSize -> 1200];

     (*ImageTrim returns a 500 by 500 pixel clip from the center of the image *)
     ImageTrim[
        (*ImageEffect speckles the image *)
        ImageEffect[Rasterize[geometricImage], {"Noise", 1/5}],
     {{250, 250}, {750, 750}}]
  ]

```
> 31 votes

# Answer
# Java

I used an approach based on recursive Voronoi diagrams. The outputs doesn't look very realistic, but I guess they're okay.

Here are some example images (resized to 250x250 so that it doesn't fill the entire screen):

0:

1:

## More details about the algorithm:

All images in this section are using the same seed.

The algorithm starts by generating a Voronoi diagram with 5 points:

If we look at the original images in the challenge, we can see that the lines aren't all straight like that, so we weigh the distance by a random value, based on the angle to the point, also, closer angles gives closer values:

Now, we recursively draw these kinds of Voronoi diagrams inside of each region, with thinner and more transparent line, and remove the background, with a maximum recursion depth of 3, and we get:

Now, we just add the pale brown background, and we're done!

## Code:

The code consists of three classes, `Main.java`, `VoronoiPoint.java` and `Vector.java`:

`Main.java`:

```
import java.awt.Desktop;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Random;

import javax.imageio.ImageIO;

public class Main {
    public static int WIDTH = 500;
    public static int HEIGHT = 500;
    public static int RECURSION_LEVELS = 3;
    public static int AMOUNT_OF_POINTS = 5;
    public static int ROTATION_RESOLUTION = 600;
    public static int ROTATION_SMOOTHNESS = 10;
    public static int BACKGROUND = 0xFFE0CBAD;

    public static Random RAND;

    public static void main(String[] args) {

        int seed = new Random().nextInt(65536);
        if (args.length == 1) {
            System.out.println(Arrays.toString(args));
            seed = Integer.parseInt(args[0]);
        } else {
            System.out.println("Generated seed: " + seed);
        }
        RAND = new Random(seed);

        ArrayList<Vector> points = new ArrayList<Vector>();
        for (int x = 0; x < WIDTH; x++) {
            for (int y = 0; y < HEIGHT; y++) {
                points.add(new Vector(x, y));
            }
        }
        BufferedImage soil = generateSoil(WIDTH, HEIGHT, seed, points, AMOUNT_OF_POINTS, RECURSION_LEVELS);

        BufferedImage background = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        for (int x = 0; x < background.getWidth(); x++) {
            for (int y = 0; y < background.getHeight(); y++) {
                background.setRGB(x, y, BACKGROUND ^ (RAND.nextInt(10) * 0x010101));
            }
        }

        Graphics g = background.getGraphics();
        g.drawImage(soil, 0, 0, null);
        g.dispose();

        String fileName = "soil";
        File output = new File(fileName + ".png");
        for (int i = 0; output.exists(); i++) {
            output = new File(fileName + i + ".png");
        }
        try {
            ImageIO.write(background, "png", output);
            Desktop.getDesktop().open(output);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Done. Saved as " + output);
    }

    private static BufferedImage generateSoil(int width, int height, int seed, ArrayList<Vector> drawPoints,
            int amountOfPoints, int recursionLevel) {

        BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        ArrayList<VoronoiPoint> points = new ArrayList<VoronoiPoint>();
        for (int i = 0; i < amountOfPoints; i++) {
            points.add(new VoronoiPoint(drawPoints.get(RAND.nextInt(drawPoints.size()))));
        }

        HashMap<Integer, ArrayList<Vector>> pointMaps = new HashMap<Integer, ArrayList<Vector>>();
        for (VoronoiPoint point : points) {
            pointMaps.put(point.hashCode(), new ArrayList<Vector>());
        }
        System.out.println(pointMaps);

        System.out.println(points);

        for (Vector v : drawPoints) {
            VoronoiPoint closest = null;
            VoronoiPoint secondClosest = null;

            for (VoronoiPoint point : points) {
                double distance = point.getMultiplicativeDistanceTo(v);
                if (closest == null || distance < closest.getMultiplicativeDistanceTo(v)) {
                    secondClosest = closest;
                    closest = point;
                } else if (secondClosest == null || distance < secondClosest.getMultiplicativeDistanceTo(v)) {
                    secondClosest = point;
                }
            }

            int col = 0;
            if (Math.abs(closest.getMultiplicativeDistanceTo(v)
                    - secondClosest.getMultiplicativeDistanceTo(v)) < (recursionLevel * 5 / RECURSION_LEVELS)) {
                col = 0x01000000 * (recursionLevel * 255 / RECURSION_LEVELS);
            } else {
                pointMaps.get(closest.hashCode()).add(v);
            }
            result.setRGB((int) v.getX(), (int) v.getY(), col);
        }
        Graphics g = result.getGraphics();
        if (recursionLevel > 0) {
            for (ArrayList<Vector> pixels : pointMaps.values()) {
                if (pixels.size() > 10) {
                    BufferedImage img = generateSoil(width, height, seed, pixels, amountOfPoints,
                            recursionLevel - 1);
                    g.drawImage(img, 0, 0, null);
                }
            }
        }
        g.dispose();

        return result;
    }

    public static int modInts(int a, int b) {
        return (int) mod(a, b);
    }

    public static double mod(double a, double b) {
        a = a % b;
        while (a < 0)
            a += b;
        return a;
    }
}

```

`VoronoiPoint.java`:

```
public class VoronoiPoint {

    private Vector pos;
    private double[] distances;

    public VoronoiPoint(Vector pos) {
        this.pos = pos;
        distances = new double[Main.ROTATION_RESOLUTION];
        for (int i = 0; i < distances.length; i++)
            distances[i] = Main.RAND.nextFloat() / 2 + 0.51;

        for (int iter = 0; iter < Main.ROTATION_SMOOTHNESS; iter++) {
            for (int i = 0; i < distances.length; i++) {
                distances[i] = (distances[Main.modInts(i - Main.RAND.nextInt(4) - 2, distances.length)] + distances[i]
                        + distances[Main.modInts(i + Main.RAND.nextInt(4) - 2, distances.length)]) / 3;
            }
        }
    }

    public Vector getPos() {
        return pos;
    }

    public double getRotationFromAngle(double radians) {
        return distances[(int) (Main.mod(Math.toDegrees(radians) / 360, 1) * distances.length)];
    }

    public double getRotationFromVector(Vector vec) {
        return getRotationFromAngle(Math.atan2(pos.getY() - vec.getY(), -(pos.getX() - vec.getX())));
    }

    public double getMultiplicativeDistanceTo(Vector other) {
        return pos.getLengthTo(other) * getRotationFromVector(other);
    }

    public String toString() {
        return "VoronoiPoint(pos=[" + pos.getX() + ", " + pos.getY() + "])";
    }

    public int hashCode() {
        return distances.hashCode() ^ pos.hashCode();
    }
}

```

`Vector.java`: (This class is copied from one of my other projects, so it contains some unnecessary code)

```
package com.loovjo.soil;

import java.util.ArrayList;
import java.util.Random;

public class Vector {
    private static final float SMALL = 1f / Float.MAX_EXPONENT * 100;
    private float x, y;

    public Vector(float x, float y) {
        this.setX(x);
        this.setY(y);
    }

    public Vector(int x, int y) {
        this.setX(x);
        this.setY(y);
    }

    public Vector(double x, double y) {
        this.setX((float) x);
        this.setY((float) y);
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    /*
     * Gets the length ^ 2 This is faster than getting the length.
     */
    public float getLengthToSqrd(float x, float y) {
        return (float) ((this.x - x) * (this.x - x) + (this.y - y) * (this.y - y));
    }

    public float getLengthToSqrd(Vector v) {
        return getLengthToSqrd(v.x, v.y);
    }

    public float getLengthSqrd() {
        return getLengthToSqrd(0, 0);
    }

    public float getLengthTo(float x, float y) {
        return (float) Math.sqrt(getLengthToSqrd(x, y));
    }

    public float getLengthTo(Vector v) {
        return getLengthTo(v.x, v.y);
    }

    public float getLength() {
        return getLengthTo(0, 0);
    }

    public Vector setLength(float setLength) {
        float length = getLength();
        x *= setLength / length;
        y *= setLength / length;
        return this;
    }

    public float getFastLengthTo(float x, float y) {
        return getFastLengthTo(new Vector(x, y));
    }

    public float getFastLengthTo(Vector v) {
        float taxiLength = getTaxiCabLengthTo(v);
        float chebyDist = getChebyshevDistanceTo(v);
        return Float.min(taxiLength * 0.7f, chebyDist);
    }

    public float getFastLength() {
        return getLengthTo(0, 0);
    }

    public Vector setFastLength(float setLength) {
        float length = getFastLength();
        x *= setLength / length;
        y *= setLength / length;
        return this;
    }

    public float getTaxiCabLengthTo(float x, float y) {
        return Math.abs(this.x - x) + Math.abs(this.y - y);
    }

    public float getTaxiCabLengthTo(Vector v) {
        return getTaxiCabLengthTo(v.x, v.y);
    }

    public float getTaxiCabLength() {
        return getTaxiCabLengthTo(0, 0);
    }

    public Vector setTaxiCabLength(float setLength) {
        float length = getTaxiCabLength();
        x *= setLength / length;
        y *= setLength / length;
        return this;
    }

    public Vector absIfBoth() {
        if (x < 0 && y < 0)
            return new Vector(-x, -y);
        return this;
    }

    public Vector abs() {
        return new Vector(x < 0 ? -x : x, y < 0 ? -y : y);
    }

    public float getChebyshevDistanceTo(float x, float y) {
        return Math.max(Math.abs(this.x - x), Math.abs(this.y - y));
    }

    public float getChebyshevDistanceTo(Vector v) {
        return getChebyshevDistanceTo(v.x, v.y);
    }

    public float getChebyshevDistance() {
        return getChebyshevDistanceTo(0, 0);
    }

    public Vector setChebyshevLength(float setLength) {
        float length = getChebyshevDistance();
        x *= setLength / length;
        y *= setLength / length;
        return this;
    }

    public Vector sub(Vector v) {
        return new Vector(this.x - v.getX(), this.y - v.getY());
    }

    public Vector add(Vector v) {
        return new Vector(this.x + v.getX(), this.y + v.getY());
    }

    public Vector mul(Vector v) {
        return new Vector(this.x * v.getX(), this.y * v.getY());
    }

    public Vector mul(float f) {
        return mul(new Vector(f, f));
    }

    public Vector div(Vector v) {
        return new Vector(this.x / v.getX(), this.y / v.getY());
    }

    public Vector div(float f) {
        return div(new Vector(f, f));
    }

    public Vector mod(Vector v) {
        return new Vector(this.x % v.getX(), this.y % v.getY());
    }

    public Vector mod(int a, int b) {
        return mod(new Vector(a, b));
    }

    public Vector mod(int a) {
        return mod(a, a);
    }

    public String toString() {
        return "Vector(" + getX() + ", " + getY() + ")";
    }

    /*
     * Returns a list with vectors, starting with this, ending with to, and each
     * one having length between them
     */
    public ArrayList<Vector> loop(Vector to, float length) {
        Vector delta = this.sub(to);
        float l = delta.getLength();
        ArrayList<Vector> loops = new ArrayList<Vector>();
        for (float i = length; i < l; i += length) {
            delta.setLength(i);
            loops.add(delta.add(to));
        }
        loops.add(this);

        return loops;
    }

    public boolean intersects(Vector pos, Vector size) {
        pos.sub(this);
        if (pos.getX() < getX())
            return false;
        if (pos.getY() < getY())
            return false;
        return true;
    }

    public Vector copy() {
        return new Vector(x, y);
    }

    public void distort(float d) {
        x += Math.random() * d - d / 2;
        y += Math.random() * d - d / 2;
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof Vector) {
            Vector v = (Vector) o;
            return getLengthToSquared(v) < SMALL * SMALL;
        }
        return false;
    }

    private float getLengthToSquared(Vector v) {
        return sub(v).getLengthSquared();
    }

    private float getLengthSquared() {
        return x * x + y * y;
    }

    public boolean kindaEquals(Vector o, int i) {
        if (o.x + i < x)
            return false;
        if (o.x - i > x)
            return false;
        if (o.y + i < y)
            return false;
        if (o.y - i > y)
            return false;
        return true;
    }
    /*
     * Gets the direction, from 0 to 8.
     */
    public int getDirection() {
        return (getDirectionInDegrees()) / (360 / 8);
    }
    /*
     * Gets the direction in degrees.
     */
    public int getDirectionInDegrees() {
        return (int) positize((float) Math.toDegrees(Math.atan2(x, -y)), 360f);
    }

    private float positize(float f, float base) {
        while (f < 0)
            f += base;
        return f;
    }
    // 0 = north,
            // 1 = northeast,
            // 2 = east,
            // 3 = southeast,
            // 4 = south,
            // 5 = southwest,
            // 6 = west,
            // 7 = northwest
    public Vector moveInDir(int d) {
        d = d % 8;
        d = (int) positize(d, 8);

        if (d == 0)
            return this.add(new Vector(0, -1));
        if (d == 1)
            return this.add(new Vector(1, -1));
        if (d == 2)
            return this.add(new Vector(1, 0));
        if (d == 3)
            return this.add(new Vector(1, 1));
        if (d == 4)
            return this.add(new Vector(0, 1));
        if (d == 5)
            return this.add(new Vector(-1, 1));
        if (d == 6)
            return this.add(new Vector(-1, 0));
        if (d == 7)
            return this.add(new Vector(-1, -1));
        return this;
    }
    /*
     * Gets the angle in degrees to o.
     */
    public float getRotationTo(Vector o) {
        float d = (float) Math.toDegrees((Math.atan2(y - o.y, -(x - o.x))));
        while (d < 0)
            d += 360;
        while (d > 360)
            d -= 360;
        return d;
    }
    public float getRotation() {
        return getRotationTo(new Vector(0, 0));
    }
    /*
     * In degrees
     */
    public Vector rotate(double n) {
        n = Math.toRadians(n);
        float rx = (float) ((this.x * Math.cos(n)) - (this.y * Math.sin(n)));
        float ry = (float) ((this.x * Math.sin(n)) + (this.y * Math.cos(n)));
        return new Vector(rx, ry);
    }

    public int hashCode() {
        int xx = (int) x ^ (int)(x * Integer.MAX_VALUE);
        int yy = (int) y ^ (int)(y * Integer.MAX_VALUE);
        return new Random(12665 * xx).nextInt() ^ new Random(5349 * yy).nextInt() + new Random((30513 * xx) ^ (19972 * yy)).nextInt();
    }

    public boolean isPositive() {
        return x >= 0 && y >= 0;
    }

    public Vector clone() {
        return new Vector(x, y);
    }
}

```

## But I don't want to compile a bunch of Java classes!

Here is a JAR file which you can run to generate these images yourself. Run as `java -jar Soil.jar number`, where `number` is the seed (can be anything up to 231-1), or run as `java -jar Soil.jar`, and it chooses a seed by itself. There will be some debug output.
> 26 votes

# Answer
# Python 3 (using Kivy library and GLSL)

First generated image

**Python code:**

```
import os
os.environ['KIVY_NO_ARGS'] = '1'

from kivy.config import Config
Config.set('input','mouse','mouse,disable_multitouch')
Config.set('graphics', 'width', '500')
Config.set('graphics', 'height', '500')
Config.set('graphics', 'resizable', '0')
Config.set('graphics', 'borderless', '1')
Config.set('graphics', 'fbo', 'force-hardware')

from kivy.app import App
from kivy.graphics import RenderContext, Fbo, Color, Rectangle
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
from kivy.factory import Factory
from kivy.core.window import Window

class ShaderSurface(FloatLayout):
    seed = 0.

    def __init__(self, **kwargs):
        self.canvas = RenderContext(use_parent_projection=True, use_parent_modelview=True)
        with self.canvas:
            self.fbo = Fbo(size=Window.size, use_parent_projection=True)

        with self.fbo:
            Color(0,0,0)
            Rectangle(size=Window.size)

        self.texture = self.fbo.texture

        super(ShaderSurface, self).__init__(**kwargs)
        self.keyboard = Window.request_keyboard(self.keyboard_closed, self)
        self.keyboard.bind(on_key_down=self.on_key_down)
        Clock.schedule_once(self.update_shader,-1)

    def keyboard_closed(self):
        self.keyboard.unbind(on_key_down=self.on_key_down)
        self.keyboard = None

    def update_shader(self, dt=0.):
        self.canvas['resolution'] = list(map(float, self.size))
        self.canvas['seed'] = self.seed
        self.canvas.ask_update()

    def on_key_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 'spacebar':
            self.seed += 1.
            self.update_shader()
            Window.screenshot()

Factory.register('ShaderSurface', cls=ShaderSurface)

class RendererApp(App):
    def build(self):
        self.root.canvas.shader.source = 'cracks_sub.glsl'

if __name__ == '__main__':
    RendererApp().run()

```

**KV file:**

```
#:kivy 1.9

ShaderSurface:
    canvas:
        Color:
            rgb: 1, 1, 1
        Rectangle:
            size: self.size
            pos: self.pos
            texture: root.fbo.texture

```

**GLSL code:**

```
---VERTEX---
uniform vec2        resolution;
in vec2             vPosition;

void main()
{
    gl_Position = vec4(vPosition.xy-resolution/2., 0, 1);
}
---FRAGMENT---
#version 330
precision highp float;

out vec4 frag_color;

uniform vec2 resolution;
uniform float seed;

vec2 tr(vec2 p)
{
    p /= resolution.xy;
    p = -1.0+2.0*p;
    p.y *= resolution.y/resolution.x;
    return p;
}

float hash( float n ){
    return fract(sin(n)*43758.5453);
}

float noise( vec2 uv ){
    vec3 x = vec3(uv, 0);

    vec3 p = floor(x);
    vec3 f = fract(x);

    f       = f*f*(3.0-2.0*f);
    float n = p.x + p.y*57.0 + 113.0*p.z;

    return mix(mix(mix( hash(n+0.0), hash(n+1.0),f.x),
                   mix( hash(n+57.0), hash(n+58.0),f.x),f.y),
               mix(mix( hash(n+113.0), hash(n+114.0),f.x),
                   mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}

mat2 m = mat2(0.8,0.6,-0.6,0.8);

float fbm(vec2 p)
{
    float f = 0.0;
    f += 0.5000*noise( p ); p*=m*2.02;
    f += 0.2500*noise( p ); p*=m*2.03;
    f += 0.1250*noise( p ); p*=m*2.01;
    f += 0.0625*noise( p );
    f /= 0.9375;
    return f;
}

vec2 hash2( vec2 p )
{
    return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}

float voronoi(vec2 x, out vec2 rt)
{
    vec2 p = floor(x);
    vec2 f = fract(x);

    vec2 mb, mr;

    float res = 8.0;
    for( int j=-1; j<=1; j++)
    for( int i=-1; i<=1; i++)
    {
        vec2 b = vec2(float(i),float(j));
        vec2 r = b+hash2(p+b)-f;
        float d = dot(r,r);

        if( d<res )
        {
            res = d;
            mr = r;
            mb = b;
            rt=r;
        }
    }

    res = 8.0;
    for( int j=-2; j<=2; j++ )
    for( int i=-2; i<=2; i++ )
    {
        vec2 b = mb + vec2(float(i),float(j));
        vec2 r = b + hash2(p+b)-f;
        float d = dot((res*res)*(mr+r),normalize(r-mr));

        res = min(res,d);
    }

    return res;
}

float crack(vec2 p)
{
    float g = mod(seed,65536./4.);
    p.x+=g;
    p.y-=seed-g;
    p.y*=1.3;
    p.x+=noise(p*4.)*.08;
    float k = 0.;
    vec2 rb = vec2(.0);
    k=voronoi(p*2.,rb);
    k=smoothstep(.0,.3,k*.05);
    float v = 0.;
    v=voronoi(rb*4.,rb);
    v=smoothstep(.0,.5,v*.05);
    k*=v;
    k-=fbm(p*128.)*.3;
    return k;
}

void main( void )
{
    vec2 fc = gl_FragCoord.xy;
    vec2 p = tr(fc);
    vec3 col = vec3(.39,.37,.25);

    vec3 abb = vec3(.14,.12,.10)/5.;

    p*=(1.+length(p)*.1);

    col.r*=crack(vec2(p.x+abb.x,p.y));
    col.g*=crack(vec2(p.x+abb.y,p.y));
    col.b*=crack(vec2(p.x+abb.z,p.y));

    col*=smoothstep(4.,1.2,dot(p,p));
    col*=exp(.66);

    //col=vec3(crack(p));
    frag_color = vec4(col,1.);
}

```

The voronoi function in the GLSL code is from Íñigo Quílez. Every voronoi related calculation happens in the fragment shader entirely with some procedural noise functions to create speckles and to disturb the lines of the voronoi pattern a bit.

By pressing space the seed will be increased by 1 and a new image will be generated and saved as a `.png` file.

**Update:** Added lense distortion, vignetting and chromatic aberration to make it more photo-realistic. Added sub-voronoi pattern.
> 12 votes

# Answer
# Java

```
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.Scanner;

import javax.imageio.ImageIO;

public class CrackedSoil {
    static BufferedImage b;
    static Random rand;
    public static int distance(int col1,int col2){
        Color a=new Color(col1);
        Color b=new Color(col2);
        return (int)(Math.pow(a.getRed()-b.getRed(), 2)+Math.pow(a.getGreen()-b.getGreen(), 2)+Math.pow(a.getBlue()-b.getBlue(), 2));
    }
    public static void edge(){
        boolean[][] edges=new boolean[500][500];
        int threshold=125+rand.nextInt(55);
        for(int x=1;x<499;x++){
            for(int y=1;y<499;y++){
                int rgb=b.getRGB(x, y);
                int del=0;
                for(int i=-1;i<=1;i++){
                    for(int j=-1;i<=j;i++){
                        del+=distance(rgb,b.getRGB(x+i, y+j));
                    }
                }
                edges[x][y]=del>threshold;
            }
        }
        for(int x=0;x<500;x++){
            for(int y=0;y<500;y++){
                if(edges[x][y])b.setRGB(x, y,new Color(4+rand.nextInt(4),4+rand.nextInt(4),4+rand.nextInt(4)).getRGB());
            }
        }
    }
    public static void main(String[]arg) throws IOException{
        b=new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);
        Scanner scanner=new Scanner(System.in);
        rand=new Random(scanner.nextInt());
        int numPoints=10+rand.nextInt(15);
        Color[]c=new Color[numPoints];
        int[][]ints=new int[numPoints][2];
        int[]weights=new int[numPoints];
        for(int i=0;i<numPoints;i++){
            switch(i%4){
            case 0:ints[i]=new int[]{251+rand.nextInt(240),7+rand.nextInt(240)};break;
            case 1:ints[i]=new int[]{7+rand.nextInt(240),7+rand.nextInt(240)};break;
            case 2:ints[i]=new int[]{7+rand.nextInt(240),251+rand.nextInt(240)};break;
            case 3:ints[i]=new int[]{251+rand.nextInt(240),251+rand.nextInt(240)};break;
            }

            c[i]=new Color(40+rand.nextInt(200),40+rand.nextInt(200),40+rand.nextInt(200));
            weights[i]=50+rand.nextInt(15);
        }
        for(int x=0;x<500;x++){
            for(int y=0;y<500;y++){
                double d=999999;
                Color col=Color.BLACK;
                for(int i=0;i<numPoints;i++){
                    double d2=weights[i]*Math.sqrt((x-ints[i][0])*(x-ints[i][0])+(y-ints[i][1])*(y-ints[i][1]));
                    if(d2<d){
                        d=d2;
                        col=c[i];
                    }
                }
                b.setRGB(x, y,col.getRGB());
            }
        }
        //ImageIO.write(b,"png",new File("voronoi1.png"));
        for(int i=0;i<numPoints/3;i++){
            ints[i]=new int[]{7+rand.nextInt(490),7+rand.nextInt(490)};
            c[i]=new Color(40+rand.nextInt(200),40+rand.nextInt(200),40+rand.nextInt(200));
            weights[i]=50+rand.nextInt(5);
        }
        for(int x=0;x<500;x++){
            for(int y=0;y<500;y++){
                double d=999999;
                Color col=Color.BLACK;
                for(int i=0;i<numPoints/3;i++){
                    double d2=weights[i]*Math.sqrt((x-ints[i][0])*(x-ints[i][0])+(y-ints[i][1])*(y-ints[i][1]));
                    if(d2<d){
                        d=d2;
                        col=c[i];
                    }
                }
                Color col3=new Color(b.getRGB(x, y));
                b.setRGB(x, y,new Color((col3.getRed()+col.getRed()*3)/4,(col3.getGreen()+col.getGreen()*3)/4,(col3.getBlue()+col.getBlue()*3)/4).getRGB());
            }
        }
        //ImageIO.write(b,"png",new File("voronoi2.png"));
        for(int i=2+rand.nextInt(3);i>0;i--)edge();
        //ImageIO.write(b,"png",new File("voronoi_edge.png"));
        for(int x=0;x<500;x++){
            for(int y=0;y<500;y++){
                Color col=new Color(b.getRGB(x, y));
                if(col.getRed()+col.getBlue()+col.getGreen()>50){
                    if(rand.nextDouble()<0.95){
                        b.setRGB(x, y,new Color(150+rand.nextInt(9),145+rand.nextInt(9),135+rand.nextInt(9)).getRGB());
                    }else{
                        b.setRGB(x, y,new Color(120+col.getRed()/7+rand.nextInt(12),115+col.getGreen()/7+rand.nextInt(12),105+col.getBlue()/7+rand.nextInt(12)).getRGB());
                    }
                }
            }
        }
        ImageIO.write(b,"png",new File("soil.png"));
    }
}

```

Creates a composite of two random diagrams which is then run through a simple edge detection and finally converted to the final result.

**Some outputs:**

**Some of the intermediate steps for that last one:**

(The first voronoi diagram)

(The composite of the two voronoi diagrams)

(After the edge detection step but before the final recoloring)
> 1 votes

---
Tags: number, popularity-contest, graphical-output, image-processing, fractal
---


title: Find the Intersections

text:
# Question
Title: Find the Intersections
Let us consider a regular n-sided polygon where all of the sides are equal in length with n being a natural number larger than or equal to three. All of the vertices lie on the unit circle (circle of radius one centered at the origin) and one of the vertices is always at the coordinate (x,y)=(1,0). Now let's draw all possible diagonals (including the edges) which connect all n vertices to one another. Here is an example for n=11.

This results in n-choose-2 (which is just n(n-1)/2) lines (diagonals and edges) which in this case is 55. The total number of line intersections, counting the interior intersection points as well as the n vertices, will be denoted I and I=341 in this case.

## The Goal

Your goal is to write a full program or a function which takes in an integer n larger than or equal to three and outputs a list of (x,y) coordinates of all of the intersections of all of the diagonals and edges, that are contained within the regular n-sided polygon with one of its vertices being at (1,0). This includes the n vertices themselves which lie on the unit circle. The length of this list must be I. There is an OEIS sequence for I, which is A007569 and here is a paper which talks about it.

## Rules and Specifications

1. Standard loopholes are forbidden.
2. Each coordinate has to be an ordered 2-tuple, giving the (x,y) coordinates in the Cartesian system.
3. The list of coordinates can be in any order. It doesn't have to be sorted or in any particular order.
4. All of the coordinates provided must be accurate to at least six significant figures. I am not specifying a rounding method. You are free to choose any rounding method or to simply chop off a number. Also for n large enough, it will be the case that two distinct intersections (in exact arithmetic) will be equal to each other to six significant figures in both coordinates (in floating point arithmetic). In this case you are free to treat them as the "same" and remove the "duplicates" from your list. The length of your list will be less than I, but oh well!
5. The coordinates can be in decimal or scientific notation. For small enough n, decimal notation is fine and decimal notation will make it easier to check so it is preferred. But I am not mandating one over the other.
6. Outputting I, which should be the length of your coordinate list, is not a requirement for this task. You don't have to output it.

You can assume whatever input/output form that is appropriate for your language. You can also assume that the input will always be a positive integer greater than or equal to three. In case of any other input, your program is free to do whatever it wants. You can also assume that the input and output will always be in the numerical range of your language/environment. Trailing newlines are okay in the output.

## Some Test Cases

I am showing more significant digits here than I need to. You are only required to show six. Remember, you don't have to print I.

```
n => 3

I => 3
(1.000000000,0)
(-0.5000000000,0.8660254038)
(-0.5000000000,-0.8660254038)

n => 4

I => 5
(1.000000000,0)
(0,1.000000000)
(-1.000000000,0)
(0,0)
(0,-1.000000000)

n => 5

I => 10
(1.000000000,0)
(0.3090169944,0.9510565163)
(-0.8090169944,0.5877852523)
(-0.1180339887,0.3632712640)
(0.3090169944,0.2245139883)
(-0.8090169944,-0.5877852523)
(0.3090169944,-0.2245139883)
(-0.1180339887,-0.3632712640)
(0.3090169944,-0.9510565163)
(-0.3819660113,0)

n => 6

I => 19
(1.000000000,0)
(0.5000000000,0.8660254038)
(-0.5000000000,0.8660254038)
(0,0.5773502692)
(0.2500000000,0.4330127019)
(0.5000000000,0.2886751346)
(-1.000000000,0)
(0,0)
(0.5000000000,0)
(-0.5000000000,0)
(-0.5000000000,-0.8660254038)
(0.5000000000,-0.2886751346)
(0.2500000000,-0.4330127019)
(0,-0.5773502692)
(0.5000000000,-0.8660254038)
(-0.5000000000,0.2886751346)
(-0.2500000000,0.4330127019)
(-0.2500000000,-0.4330127019)
(-0.5000000000,-0.2886751346)

n => 7

I => 42
(1.000000000,0)
(0.6234898019,0.7818314825)
(-0.2225209340,0.9749279122)
(0.1539892642,0.6746710485)
(0.3215520661,0.5410441731)
(0.4559270000,0.4338837391)
(0.6234898019,0.3002568637)
(-0.9009688679,0.4338837391)
(-0.05495813209,0.2407873094)
(0.3215520661,0.1548513136)
(0.6234898019,0.08593599577)
(-0.5244586698,0.3479477434)
(-0.2225209340,0.2790324255)
(0.1539892642,0.1930964297)
(-0.9009688679,-0.4338837391)
(0.1539892642,-0.1930964297)
(0.6234898019,-0.08593599577)
(-0.2225209340,-0.2790324255)
(0.3215520661,-0.1548513136)
(-0.5244586698,-0.3479477434)
(-0.05495813209,-0.2407873094)
(-0.2225209340,-0.9749279122)
(0.6234898019,-0.3002568637)
(0.4559270000,-0.4338837391)
(0.3215520661,-0.5410441731)
(0.1539892642,-0.6746710485)
(0.6234898019,-0.7818314825)
(-0.4314683302,0.5410441731)
(-0.2225209340,0.5887350528)
(-0.05495813209,0.6269801688)
(-0.2225209340,0.1071604339)
(0.07941680185,0.3479477434)
(-0.5990311321,-0.1930964297)
(-0.3568958679,0)
(0.2469796037,0)
(0.07941680185,-0.3479477434)
(-0.05495813209,-0.6269801688)
(-0.6920214716,0)
(-0.5990311321,0.1930964297)
(-0.2225209340,-0.1071604339)
(-0.2225209340,-0.5887350528)
(-0.4314683302,-0.5410441731)

```

I can provide more test cases but they will take up a lot of space and I am not sure how to provide them here. Let me know if you guys need more cases and what is the best way for me to provide them.

## Scoring

This is code-golf. The answer with the smallest byte-count will win. In case of a tie, I will pick the answer that was posted earlier as the winner.

Please post your answer in the standard format with all compiler/interpreter options/flags.

# Answer
> 2 votes
# Python 3, 211 204 bytes

```
from itertools import*
C=combinations
lambda n:{(round(z.real,6),round(z.imag,6))
          for z in[(a*b*c+a*b*d-a*c*d-b*c*d)/(a*b-c*d)
          for(a,b),(c,d)in C(C([23.140693**(2j*k/n)for k in range(n)],2),2)]
          if abs(z)<=1}

```

For readability I've added superfluous newlines in my answer that aren't included in the bytecount.

If we have a line crossing through points *a* and *b*, and another line crossing through points *c* and *d*, where *a, b, c, d* are complex numbers, then the intersection between those lines (not segments!) is

But for a point *u* on the unit circle, the conjugate of *u* is *1/u*. Then the formula simplifies to:

Now, if the intersection of the two lines also lies within the unit circle, that's a proper intersection of the diagonals.

# Answer
> 2 votes
# Mathematica ~~165 143~~  112 bytes

53 bytes saved by Misha Lavrov! 22 thanks to his suggestion to use `Cases` instead of `Select`. 31 additional bytes saved thanks to his suggestion to use `CirclePoints`.

```
(s=Subsets;Union@Cases[RegionIntersection@@@s[Line/@s[N[{1,Pi/2}~CirclePoints~#,8]&@#,{2}],{2}],Point@{x_}:>x])&

```

---

`Table[{Cos[Pi/2+(2k Pi)/# ],Sin[Pi/2+(2k Pi)/# ]},{k,0,#-1}]` generates the coordinates of the vertices of a regular polygon (inscribed in the unit circle) with one vertex at `(0,1)`.

Line segments are then defined for each subsets of possible pairs of those coordinates.

`RegionIntersection` finds a point of intersection for each pair of these line segments (iff such intersection exists).
`Cases[... Point@{x_} :> x]` returns the coordinates. Cases in which two segments do not intersect are ignored.

`Union` eliminates possible duplicates.

---

**Example** (n=7)

```
(s = Subsets;
Union@Cases[
 RegionIntersection @@@s[Line /@s[N[{1, Pi/2}~CirclePoints~#&@#, {2}], {2}],
Point@{x_} :> x]) &[7]

```

{{-0.974928, -0.222521}, {-0.781831, 0.62349}, {-0.674671, 0.153989}, {-0.62698, -0.0549581}, {-0.588735, -0.222521}, \ {-0.541044, -0.431468}, {-0.541044, 0.321552}, {-0.433884, -0.900969}, {-0.433884, 0.455927}, {-0.347948, -0.524459}, {-0.347948, 0.0794168}, {-0.300257, 0.62349}, {-0.279032, -0.222521}, {-0.240787, -0.0549581}, \ {-0.193096, -0.599031}, {-0.193096, 0.153989}, {-0.154851, 0.321552}, {-0.10716, -0.222521}, {-0.085936, 0.62349}, {0., -0.692021}, {0., -0.356896}, {0., 0.24698}, {0., 1.}, {0.085936, 0.62349}, {0.10716, -0.222521}, {0.154851, 0.321552}, {0.193096, -0.599031}, {0.193096, 0.153989}, {0.240787, -0.0549581}, {0.279032, -0.222521}, {0.300257, 0.62349}, {0.347948, -0.524459}, {0.347948, 0.0794168}, {0.433884, -0.900969}, {0.433884, 0.455927}, {0.541044, -0.431468}, {0.541044, 0.321552}, {0.588735, -0.222521}, {0.62698, -0.0549581}, {0.674671, 0.153989}, {0.781831, 0.62349}, {0.974928, -0.222521}}

```
Graphics[{PointSize[Large], Blue, Point@%}, Axes -> True]

```

---
Tags: code-golf, geometry
---


# Question
Title: Sprocket Science: Animating a Chain Drive System
The goal of this challenge is to produce an animation of a **chain drive** system, comprised of a set of **sprocket gears** connected together by a **chain**.

**General Requirements**

Your program will be given a **list of sprockets**, specified as `(x, y, radius)` triplets. The **resulting chain drive system** is comprised of these sprockets, connected together by a **closed taut chain** passing over each of them, **in order**. Your goal is to produce an **infinitely looping animation**, showing the system in motion. For example, given the input

```
(0, 0, 16),  (100, 0, 16),  (100, 100, 12),  (50, 50, 24),  (0, 100, 12)

```

, the output should look something like

.

The **coordinate system** should be such that the x-axis points right, and the y-axis points up. You may assume that the **radii are even numbers** greater than or equal to 8 (we'll see why this matters later.) You may also assume that there are **at least two sprockets**, and that the **sprockets don't intersect** one another. The **units** of the input are not too critical. All the examples and test cases in this post use pixels as the input units (so, for example, the radius of the middle sprocket in the previous figure is 24 pixels;) try not to deviate too much from these units. In the rest of the challenge, spatial quantities are understood to be given in the same units as the input—make sure to keep the proportions right! The **dimensions of the output** should be slightly bigger than the bounding box of all the sprockets, big enough so that the entire system is visible. In particular, the absolute positions of the sprockets should not affect the output; only their relative positions should (so, for example, if we shifted all the sprockets in the above example by the same amount, the output would remain the same.)

The chain should be **tangent** to the sprockets it passes over at all points of contact, and **straight** everywhere else. The chain should pass over the sprockets such that **adjacent chain segments** (that is, parts of the chain between two sprockets, that meet at the same sprocket) **don't intersect** each other.

.

For example, while the left system above is valid, the middle one is not, since the two adjacent chain segments that pass over the bottom left sprocket intersect. However, note that the right system *is* valid, since the two intersecting chain segments are not adjacent (this system is produced by a different input than the other two, though.)

To keep things simple(r), you may assume that **no sprocket intersects the convex hull** of its two neighboring sprockets, or the convex hulls of each of its neighbors and their other neighbor. In other words, the top sprocket in the diagram below may not intersect any of the shaded regions.

Chain segments may intersect sprockets other than the ones they pass over (such as in the last test case). In this case, the chain should always appear in front of the sprockets.

**Visual Requirements**

The chain should consist of a series of **links** of alternating widths. The width of the **narrow link** should be about 2, and the width of the **wide link** should be about 5. The **length** of both types of links should be about equal. The **period** of the chain, that is, the total length of a wide/narrow pair of links, should be the closest number to 4π that fits an integer number of times in the length of the chain. For example, if the length of the chain is 1,000, then its period should be 12.5, which is the closest number to 4π (12.566...) that fits an integer number of times (80) in 1,000. It's important for the period to fit an integer number of times in the chain's length, so that there are no artifacts at the point where the chain wraps around.

A sprocket of radius ***R*** should consist of three concentric parts: a central **axle**, which should be a circle of radius about 3; the **sprocket's body**, around the axle, which should be a circle of radius about *R* \- 4.5; and the **sprocket's rim**, around the body, which should be a circle of radius about
*R* \- 1.5. The rim should also contain the **sprocket's teeth**, which should have a width of about 4; the teeth's size and spacing should match the the sizes of the chain links, so that they enmesh neatly.

The period of the sprocket's teeth, that is, the distance between two consecutive teeth along the circumference of the sprocket, should match the period of the chain. Since the period is about 4π, and since the radius of the sprocket is guaranteed to be even, the period should fit in the sprocket's circumference an almost-integer number of times, so that there shouldn't be any noticeable artifacts at the point where the sprocket's teeth wrap around.

You may use **any combination of colors** for the chain, the different parts of the sprocket, and the background, as long as they are **easily distinguishable**. The background may be transparent. The examples in this post use `#202020` for the chain, `#868481` for the sprocket's axle and rim, and `#646361` for the sprocket's body.

**Animation Requirements**

The **first sprocket** in the input list should rotate **clockwise**; the rest of the sprockets should rotate accordingly. The chain should move at a **speed** of about 16π (about 50) units per second; the frame rate is up to you, but the animation should look smooth enough.

The animation should **loop seamlessly**.

**Conformance**

Some of the visual attributes and proportions are intentionally specified only roughly—you don't have to match them *exactly*. Your program's output doesn't have to be a pixel-to-pixel replica of the examples given here, but it should look similar. In particular, the exact proportions of the chain and the sprockets, and the exact shape of the chain's links and sprocket's teeth, are flexible.

The most important points to follow are these:

* The chain should pass over the sprockets, in input order, from the correct direction.
* The chain should be tangent to the sprockets at all points of contact.
* The links of the chain and the teeth of the sprockets should enmesh neatly, at least up to correct spacing and phase.
* The spacing between the links of the chain, and the teeth of the sprockets, should be such that there are no noticeable artifacts at the point where they wrap around.
* The sprockets should rotate in the correct direction.
* The animation should loop seamlessly.

As a final note, while, technically, the goal of this challenge is to write the shortest code, if you feel like getting creative and producing a more elaborate output, by all means, go for it!

## Challenge

Write a **program** or a **function**, taking a list of sprockets, and producing a corresponding chain drive system animation, as described above.

## Input and Output

You may take the **input** through the **command line**, through **STDIN**, as **function arguments**, or using an **equivalent method**. You may use **any convenient format** for the input, but make sure to specify it in your post.

As **output**, you may **display the animation directly**, produce an **animation file** (e.g., an animated GIF), or produce a **sequence of frame files** (however, there's a small penalty in this case; see below.) If you use file output, make sure the **number of frames is reasonable** (the examples in this post use very few frames;) the number of frames doesn't have to be minimal, but you shouldn't produce too many superfluous frames. If you output a sequence of frames, make sure to **specify the frame rate** in your post.

## Score

This is **code-golf**. The **shortest answer**, in bytes, wins.

**+10% Penalty** If your program produces a sequence of frames as output, instead of displaying the animation directly or producing a single animation file, add 10% to your score.

## Test Cases

**Test 1**

```
(0, 0, 26),  (120, 0, 26)

```

**Test 2**

```
(100, 100, 60),  (220, 100, 14)

```

**Test 3**

```
(100, 100, 16),  (100, 0, 24),  (0, 100, 24),  (0, 0, 16)

```

**Test 4**

```
(0, 0, 60),  (44, 140, 16),  (-204, 140, 16),  (-160, 0, 60),  (-112, 188, 12),
(-190, 300, 30),  (30, 300, 30),  (-48, 188, 12)

```

**Test 5**

```
(0, 128, 14),  (46.17, 63.55, 10),  (121.74, 39.55, 14),  (74.71, -24.28, 10),
(75.24, -103.55, 14),  (0, -78.56, 10),  (-75.24, -103.55, 14),  (-74.71, -24.28, 10),
(-121.74, 39.55, 14),  (-46.17, 63.55, 10)

```

**Test 6**

```
(367, 151, 12),  (210, 75, 36),  (57, 286, 38),  (14, 181, 32),  (91, 124, 18),
(298, 366, 38),  (141, 3, 52),  (80, 179, 26),  (313, 32, 26),  (146, 280, 10),
(126, 253, 8),  (220, 184, 24),  (135, 332, 8),  (365, 296, 50),  (248, 217, 8),
(218, 392, 30)

```

---

# Answer
> 45 votes
# JavaScript (ES6), ~~2557~~ ~~1915~~ ~~1897~~ 1681 bytes

This isn't super-duper *golfed* really; it's minified - partly by hand - but that's nothing special. It could no doubt be shorter if I'd golfed it more before minifying, but I've spent (more than) enough time on this already.

*Edit: Ok, so I spent more time on it and golfed the code more before minifying (very manually this time). The code's still using the same approach and overall structure, but even so I still ended up saving 642 bytes. Not too shabby, if I do say so myself. Probably missed some byte-saving opportunities, but at this point even I'm not sure how it works anymore. The only thing that's different in terms of output, is that it now uses slightly different colors that could be written more tersely.*

*Edit 2 (much later): Saved 18 bytes. Thanks to ConorO'Brien in the comments for pointing out the blindingly obvious that I'd totally missed.*

*Edit 3: So, I figured I'd reverse engineer my own code, because, frankly, I couldn't remember how I'd done it, and I lost the ungolfed versions. So I went through, and lo and behold found another 316 bytes to save by restructuring and doing some micro-golfing.*

```
R=g=>{with(Math){V=(x,y,o)=>o={x,y,l:sqrt(x*x+y*y),a:v=>V(x+v.x,y+v.y),s:v=>o.a(v.m(-1)),m:f=>V(x*f,y*f),t:r=>V(x*cos(r)-y*sin(r),x*sin(r)+y*cos(r)),c:v=>x*v.y-y*v.x,toString:_=>x+','+y};a='appendChild',b='setAttribute';S=(e,a)=>Object.keys(a).map(n=>e[b](n,a[n]))&&e;T=(t,a)=>S(k.createElementNS('http://www.w3.org/2000/svg',t),a);C=(e,a)=>S(e.cloneNode(),a);P=a=>T('path',(a.fill='none',a));w=h=-(x=y=1/0);G=g.map((a,g)=>(g=V(...a))&&(u=(g.r=a[2])+5,x=min(x,g.x-u),y=min(y,g.y-u),w=max(w,g.x+u),h=max(h,g.y+u))&&g);k=document;I=k[a].bind(k.body[a](T('svg',{width:w-x,height:h-y}))[a](T('g',{transform:`translate(${-x},${h})scale(1,-1)`})));L=(c)=>(h=G.length)&&G.map((g,i)=>c(G[i],G[i?i-1:h-1],G[(i+1)%h]))&&L;l='';L((g,p,n)=>g.f=p.s(g).c(n.s(g))>0)((g,a,n)=>{d=g.s(n),y=x=1/d.l;g.f!=n.f?(a=asin((g.r+n.r)*x),g.f?(x=-x,a=-a):(y=-y)):(a=asin((g.r-n.r)*x),g.f&&(x=y=-x,a=-a));t=d.t(a+PI/2);g.o=t.m(x*g.r).a(g);n.i=t.m(y*n.r).a(n)})((g,p,n)=>{z='#888';d=(l,s,e)=>`A${g.r},${g.r} 0 ${1*l},${1*s} ${e}`;e=(f,r)=>T('circle',{cx:g.x,cy:g.y,r,fill:f});g.k=p.o.s(n.i).l<g.i.s(g.o).l;w=d(g.k,!g.f,g.o);g.j=`${w}L${n.i}`;l+=g.j;I(e(z,g.r-1.5));g.g=I(P({d:`M${g.i}${w}${d(!g.k,!g.f,g.i)}`,stroke:z,'stroke-width':5}));g.h=I(C(g.g,{d:`M${g.i}${g.j}`,stroke:'#222'}));I(e('#666',g.r-4.5));I(e(z,3))});t=e=>e.getTotalLength(),u='stroke-dasharray',v='stroke-dashoffset',f=G[0];l=I(C(f.h,{d:'M'+f.i+l,'stroke-width':2}));s=f.w=t(l)/round(t(l)/(4*PI))/2;X=8*s;Y=f.v=0;L((g,p)=>{g.g[b](u,s);g.h[b](u,s);g==f||(g.w=p.w+t(p.h),g.v=p.v+t(p.h));g.g[b](v,g.w);g.h[b](v,g.v);g.h[a](C(g.g[a](T('animate',{attributeName:v,from:g.w+X,to:g.w+Y,repeatCount:'indefinite',dur:'1s'})),{from:g.v+X,to:g.v+Y}))})}}

```

The function above appends an SVG element (including animations) to the document. E.g. to display the 2nd test case:

```
R([[100, 100, 60],  [220, 100, 14]]);

```

Seems to work a treat - at least here in Chrome.

Try it in the snippet below (clicking the buttons will draw each of OP's test cases).

```
R=g=>{with(Math){V=(x,y,o)=>o={x,y,l:sqrt(x*x+y*y),a:v=>V(x+v.x,y+v.y),s:v=>o.a(v.m(-1)),m:f=>V(x*f,y*f),t:r=>V(x*cos(r)-y*sin(r),x*sin(r)+y*cos(r)),c:v=>x*v.y-y*v.x,toString:_=>x+','+y};a='appendChild',b='setAttribute';S=(e,a)=>Object.keys(a).map(n=>e[b](n,a[n]))&&e;T=(t,a)=>S(k.createElementNS('http://www.w3.org/2000/svg',t),a);C=(e,a)=>S(e.cloneNode(),a);P=a=>T('path',(a.fill='none',a));w=h=-(x=y=1/0);G=g.map((a,g)=>(g=V(...a))&&(u=(g.r=a[2])+5,x=min(x,g.x-u),y=min(y,g.y-u),w=max(w,g.x+u),h=max(h,g.y+u))&&g);k=document;I=k[a].bind(k.body[a](T('svg',{width:w-x,height:h-y}))[a](T('g',{transform:`translate(${-x},${h})scale(1,-1)`})));L=(c)=>(h=G.length)&&G.map((g,i)=>c(G[i],G[i?i-1:h-1],G[(i+1)%h]))&&L;l='';L((g,p,n)=>g.f=p.s(g).c(n.s(g))>0)((g,a,n)=>{d=g.s(n),y=x=1/d.l;g.f!=n.f?(a=asin((g.r+n.r)*x),g.f?(x=-x,a=-a):(y=-y)):(a=asin((g.r-n.r)*x),g.f&&(x=y=-x,a=-a));t=d.t(a+PI/2);g.o=t.m(x*g.r).a(g);n.i=t.m(y*n.r).a(n)})((g,p,n)=>{z='#888';d=(l,s,e)=>`A${g.r},${g.r} 0 ${1*l},${1*s} ${e}`;e=(f,r)=>T('circle',{cx:g.x,cy:g.y,r,fill:f});g.k=p.o.s(n.i).l<g.i.s(g.o).l;w=d(g.k,!g.f,g.o);g.j=`${w}L${n.i}`;l+=g.j;I(e(z,g.r-1.5));g.g=I(P({d:`M${g.i}${w}${d(!g.k,!g.f,g.i)}`,stroke:z,'stroke-width':5}));g.h=I(C(g.g,{d:`M${g.i}${g.j}`,stroke:'#222'}));I(e('#666',g.r-4.5));I(e(z,3))});t=e=>e.getTotalLength(),u='stroke-dasharray',v='stroke-dashoffset',f=G[0];l=I(C(f.h,{d:'M'+f.i+l,'stroke-width':2}));s=f.w=t(l)/round(t(l)/(4*PI))/2;X=8*s;Y=f.v=0;L((g,p)=>{g.g[b](u,s);g.h[b](u,s);g==f||(g.w=p.w+t(p.h),g.v=p.v+t(p.h));g.g[b](v,g.w);g.h[b](v,g.v);g.h[a](C(g.g[a](T('animate',{attributeName:v,from:g.w+X,to:g.w+Y,repeatCount:'indefinite',dur:'1s'})),{from:g.v+X,to:g.v+Y}))})}}

// ========================
// Test code

var testCases = [
  [[0, 0, 16],  [100, 0, 16],  [100, 100, 12],  [50, 50, 24],  [0, 100, 12]],
  [[0, 0, 26],  [120, 0, 26]],
  [[100, 100, 60],  [220, 100, 14]],
  [[100, 100, 16],  [100, 0, 24],  [0, 100, 24],  [0, 0, 16]],
  [[0, 0, 60],  [44, 140, 16],  [-204, 140, 16],  [-160, 0, 60],  [-112, 188, 12], [-190, 300, 30],  [30, 300, 30],  [-48, 188, 12]],
  [[0, 128, 14],  [46.17, 63.55, 10],  [121.74, 39.55, 14],  [74.71, -24.28, 10], [75.24, -103.55, 14],  [0, -78.56, 10],  [-75.24, -103.55, 14],  [-74.71, -24.28, 10], [-121.74, 39.55, 14],  [-46.17, 63.55, 10]],
  [[367, 151, 12],  [210, 75, 36],  [57, 286, 38],  [14, 181, 32],  [91, 124, 18], [298, 366, 38],  [141, 3, 52],  [80, 179, 26],  [313, 32, 26],  [146, 280, 10], [126, 253, 8],  [220, 184, 24],  [135, 332, 8],  [365, 296, 50],  [248, 217, 8], [218, 392, 30]]
];

function clear() {
  var buttons = document.createElement('div');
  document.body.innerHTML = "";
  document.body.appendChild(buttons);
  testCases.forEach(function (data, i) {
    var button = document.createElement('button');
    button.innerHTML = String(i);
    button.onclick = function () {
      clear();
      R(data);
      return false;
    };
    buttons.appendChild(button);
  });
}

clear();
```

The code draws the chain and gear teeth as a dashed strokes. It then uses `animate` elements to animate the `stroke-dashoffset` attribute. The resulting SVG element is self-contained; there's no JS-driven animation or CSS styling.

To make things line up nicely, each gear's ring of teeth is actually drawn as a path consisting of two arcs, so the path can start right at the tangent point where the chain touches. This makes it a lot simpler to line it up.

Furthermore, it seems there's a lot of rounding errors when using SVG's dashed strokes. At least, that's what I saw; the longer the chain, the worse it'd mesh with each successive gear. So to minimize the issue, the chain is actually made up of several paths. Each path consists of an arcing segment around one gear and a straight line to the next gear. Their dash-offsets are calculated to match. The thin "inner" part of the chain, however, is just a single looping path, since it isn't animated.

# Answer
> 41 votes
# C# 3566 bytes

~~Not golfed at all, but~~ works (I think)

Ungolfed in edit history.

Uses Magick.NET to render gif.

```
class S{public float x,y,r;public bool c;public double i,o,a=0,l=0;public S(float X,float Y,float R){x=X;y=Y;r=R;}}class P{List<S>q=new List<S>();float x=float.MaxValue,X=float.MinValue,y=float.MaxValue,Y=float.MinValue,z=0,Z=0,N;int w=0,h=0;Color c=Color.FromArgb(32,32,32);Pen p,o;Brush b,n,m;List<PointF>C;double l;void F(float[][]s){p=new Pen(c,2);o=new Pen(c,5);b=new SolidBrush(c);n=new SolidBrush(Color.FromArgb(134,132,129));m=new SolidBrush(Color.FromArgb(100,99,97));for(int i=0;i<s.Length;i++){float[]S=s[i];q.Add(new S(S[0],S[1],S[2]));if(S[0]-S[2]<x)x=S[0]-S[2];if(S[1]-S[2]<y)y=S[1]-S[2];if(S[0]+S[2]>X)X=S[0]+S[2];if(S[1]+S[2]>Y)Y=S[1]+S[2];}q[0].c=true;z=-x+16;Z=-y+16;w=(int)(X-x+32);h=(int)(Y-y+32);for(int i=0;i<=q.Count;i++)H(q[i%q.Count],q[(i+1)%q.Count],q[(i+2)%q.Count]);C=new List<PointF>();for(int i=0;i<q.Count;i++){S g=q[i],k=q[(i+1)%q.Count];if(g.c)for(double a=g.i;a<g.i+D(g.o,g.i);a+=Math.PI/(2*g.r)){C.Add(new PointF((float)(g.x+z+g.r*Math.Cos(a)),(float)(g.y+Z+g.r*Math.Sin(a))));}else
for(double a=g.o+D(g.i,g.o);a>g.o;a-=Math.PI/(2*g.r)){C.Add(new PointF((float)(g.x+z+g.r*Math.Cos(a)),(float)(g.y+Z+g.r*Math.Sin(a))));}C.Add(new PointF((float)(g.x+z+g.r*Math.Cos(g.o)),(float)(g.y+Z+g.r*Math.Sin(g.o))));C.Add(new PointF((float)(k.x+z+k.r*Math.Cos(k.i)),(float)(k.y+Z+k.r*Math.Sin(k.i))));k.l=E(C);}l=E(C);N=(float)(K(l)/10.0);o.DashPattern=new float[]{N,N};double u=q[0].i;for(int i=0;i<q.Count;i++){S g=q[i];double L=g.l/(N*5);g.a=g.i+((1-(L%2))/g.r*Math.PI*2)*(g.c?1:-1);}List<MagickImage>I=new List<MagickImage>();for(int i=0;i<t;i++){using(Bitmap B=new Bitmap(w,h)){using(Graphics g=Graphics.FromImage(B)){g.Clear(Color.White);g.SmoothingMode=System.Drawing.Drawing2D.SmoothingMode.AntiAlias;foreach(S U in q){float R=U.x+z,L=U.y+Z,d=7+2*U.r;PointF[]f=new PointF[4];for(double a=(i*(4.0/t));a<2*U.r;a+=4){double v=U.a+((U.c?-a:a)/U.r*Math.PI),j=Math.PI/U.r*(U.c?1:-1),V=v+j,W=V+j,r=U.r+3.5;f[0]=new PointF(R,L);f[1]=new PointF(R+(float)(r*Math.Cos(v)),L+(float)(r*Math.Sin(v)));f[2]=new PointF(R+(float)(r*Math.Cos(V)),L+(float)(r*Math.Sin(V)));f[3]=new PointF(R+(float)(r*Math.Cos(W)),L+(float)(r*Math.Sin(W)));g.FillPolygon(n,f);}d=2*(U.r-1.5f);g.FillEllipse(n,R-d/2,L-d/2,d,d);d=2*(U.r-4.5f);g.FillEllipse(m,R-d/2,L-d/2,d,d);d=6;g.FillEllipse(n,R-d/2,L-d/2,d,d);}g.DrawLines(p,C.ToArray());o.DashOffset=(N*2.0f/t)*i;g.DrawLines(o,C.ToArray());B.RotateFlip(RotateFlipType.RotateNoneFlipY);B.Save(i+".png",ImageFormat.Png);I.Add(new MagickImage(B));}}}using(MagickImageCollection collection=new MagickImageCollection()){foreach(MagickImage i in I){i.AnimationDelay=5;collection.Add(i);}QuantizeSettings Q=new QuantizeSettings();Q.Colors=256;collection.Quantize(Q);collection.Optimize();collection.Write("1.gif");}}int t=5;double D(double a,double b){double P=Math.PI,r=a-b;while(r<0)r+=2*P;return r%(2*P);}double E(List<PointF> c){double u=0;for(int i=0;i<c.Count-1;i++){PointF s=c[i];PointF t=c[i+1];double x=s.X-t.X,y=s.Y-t.Y;u+=Math.Sqrt(x*x+y*y);}return u;}double K(double L){double P=4*Math.PI;int i=(int)(L/P);float a=(float)L/i,b=(float)L/(i+1);if(Math.Abs(P-a)<Math.Abs(P-b))return a;return b;}void H(S a,S b,S c){double A=0,r=0,d=b.x-a.x,e=b.y-a.y,f=Math.Atan2(e,d)+Math.PI/2,g=Math.Atan2(e,d)-Math.PI/2,h=Math.Atan2(-e,-d)-Math.PI/2,i=Math.Atan2(-e,-d)+Math.PI/2;double k=c.x-b.x,n=c.y-b.y,l=Math.Sqrt(d*d+e*e);A=D(Math.Atan2(n,k),Math.Atan2(-e,-d));bool x=A>Math.PI!=a.c;b.c=x!=a.c;if(a.r!=b.r)r=a.r+(x?b.r:-b.r);f-=Math.Asin(r/l);g+=Math.Asin(r/l);h+=Math.Asin(r/l);i-=Math.Asin(r/l);b.i=x==a.c?h:i;a.o=a.c?g:f;}}

```

Class P has a function F; Example:

```
static void Main(string[]a){
P p=new P();
float[][]s=new float[][]{
new float[]{10,200,20},
new float[]{240,200,20},
new float[]{190,170,10},
new float[]{190,150,10},
new float[]{210,120,20},
new float[]{190,90,10},
new float[]{160,0,20},
new float[]{130,170,10},
new float[]{110,170,10},
new float[]{80,0,20},
new float[]{50,170,10}
};
p.F(s);}

```

# Answer
> 3 votes
## JavaScript (ES6) 1626 bytes

This solution is the result of reverse engineering of @Flambino's solution, I post it with his accord.

```
R=g=>{with(Math){v='stroke';j=v+'-dasharray';q=v+'-dashoffset';m='appendChild';n='getTotalLength';b='setAttribute';z='#888';k=document;V=(x,y,r,o)=>o={x,y,r,l:sqrt(x*x+y*y),a:v=>V(x+v.x,y+v.y),s:v=>o.a(v.m(-1)),m:f=>V(x*f,y*f),t:r=>V(x*cos(r)-y*sin(r),x*sin(r)+y*cos(r)),c:v=>x*v.y-y*v.x,toString:_=>x+','+y};S=(e,a)=>Object.keys(a).map(n=>e[b](n,a[n]))&&e;T=(t,a)=>S(k.createElementNS('http://www.w3.org/2000/svg',t),a);C=(e,a)=>S(e.cloneNode(),a);w=h=-(x=y=1/0);G=g.map((a,g)=>(g=V(...a))&&(u=(g.r=a[2])+5,x=min(x,g.x-u),y=min(y,g.y-u),w=max(w,g.x+u),h=max(h,g.y+u))&&g);f=G[0];w-=x;h-=y;s=T('svg',{width:w,height:h,viewBox:x+' '+y+' '+w+' '+h,transform:'scale(1,-1)'});c='';L=(c)=>(h=G.length)&&G.map((g,i)=>c(G[i],G[(h+i-1)%h],G[(i+1)%h]))&&L;L((g,p,n)=>g.w=(p.s(g).c(n.s(g))>0))((g,p,n)=>{d=g.s(n),y=x=1/d.l;g.w!=n.w?(p=asin((g.r+n.r)*x),g.w?(x=-x,p=-p):(y=-y)):(p=asin((g.r-n.r)*x),g.w&&(x=y=-x,p=-p));t=d.t(p+PI/2);g.o=t.m(x*g.r).a(g);n.i=t.m(y*n.r).a(n)})((g,p,n)=>{l=(p.o.s(n.i).l<g.i.s(g.o).l);d=(l,e)=>`A${g.r} ${g.r} 0 ${+l} ${+!g.w} ${e}`;a=d(l,g.o);e=(f,r)=>T('circle',{cx:g.x,cy:g.y,r,fill:f});c+=a+'L'+n.i;s[m](e(z,g.r-1.5));s[m](e('#666',g.r-4.5));s[m](e(z,3));g.p=s[m](C(g.e=s[m](T('path',{d:'M'+g.i+a+d(!l,g.i),fill:'none',[v]:z,[v+'-width']:5})),{d:'M'+g.i+a+'L'+n.i,[v]:'#222'}))});c=C(f.p,{d:'M'+f.i+c,[v+'-width']:2});g=c[n]();y=8*(x=g/round(g/(4*PI))/2);f.g=x;f.h=0;L((g,p)=>{g!=f&&(g.g=p.g+p.p[n](),g.h=p.h+p.p[n]());S(g.p,{[j]:x,[q]:g.h})[m](C(S(g.e,{[j]:x,[q]:g.g})[m](T('animate',{attributeName:[q],from:g.g+y,to:g.g,repeatCount:'indefinite',dur:'1s'})),{from:g.h+y,to:g.h}))});k.body[m](s)[m](c)}}

```

The ungolfed version:

```
class Vector {

    constructor(x, y) {
        this.x = x;
        this.y = y;
        this.length = Math.sqrt(x * x + y * y);
    }

    add(vector) {

        return new Vector(this.x + vector.x, this.y + vector.y);
    }

    subtract(vector) {

        return new Vector(this.x - vector.x, this.y - vector.y);
    }

    multiply(scalar) {

        return new Vector(this.x * scalar, this.y * scalar);
    }

    rotate(radians) {

        const cos = Math.cos(radians);
        const sin = Math.sin(radians);

        return new Vector(this.x * cos - this.y * sin, this.x * sin + this.y * cos);
    }

    cross(vector) {

        return this.x * vector.y - this.y * vector.x;
    }

    toString() {

        return `${this.x},${this.y}`;
    }
}

class Gear {

    constructor(x, y, radius) {
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    getVector() {

        return new Vector(this.x, this.y);
    }
}

const setAttributes = (element, attributes) => {

    Object.keys(attributes).forEach((attribute) => {
        element.setAttribute(attribute, attributes[attribute]);
    });
};

const createElement = (tagName, attributes) => {

    const element = document.createElementNS('http://www.w3.org/2000/svg', tagName);

    setAttributes(element, attributes);

    return element;
};

const cloneElement = (element, attributes) => {

    const clone = element.cloneNode();

    setAttributes(clone, attributes);

    return clone;
};

const createPath = (attributes) => {

    return createElement('path', {
        ...attributes,
        fill: 'none'
    });
};

const createCircle = (cx, cy, r, fill) => {

    return createElement('circle', {
        cx,
        cy,
        r,
        fill
    });
};

const loopGears = (gears, callback) => {

    const length = gears.length;

    gears.forEach((gear, index) => {

        const prevGear = gears[(length + index - 1) % length];
        const nextGear = gears[(index + 1) % length];

        callback(gear, prevGear, nextGear);
    });
};

const arcDescription = (radius, largeArcFlag, sweepFlag, endVector) => {

    return `A${radius} ${radius} 0 ${+largeArcFlag} ${+sweepFlag} ${endVector}`;
};

const renderGears = (data) => {

    let x = Infinity;
    let y = Infinity;
    let w = -Infinity;
    let h = -Infinity;

    const gears = data.map((params) => {

        const gear = new Gear(...params);
        const unit = params[2] + 5;

        x = Math.min(x, gear.x - unit);
        y = Math.min(y, gear.y - unit);
        w = Math.max(w, gear.x + unit);
        h = Math.max(h, gear.y + unit);

        return gear;
    });

    const firstGear = gears[0];

    w -= x;
    h -= y;

    const svg = createElement('svg', {
        width: w,
        height: h,
        viewBox: `${x} ${y} ${w} ${h}`,
        transform: `scale(1,-1)`
    });

    let chainPath = '';

    loopGears(gears, (gear, prevGear, nextGear) => {

        const gearVector = gear.getVector();
        const prevGearVector = prevGear.getVector().subtract(gearVector);
        const nextGearVector = nextGear.getVector().subtract(gearVector);

        gear.sweep = (prevGearVector.cross(nextGearVector) > 0);
    });

    loopGears(gears, (gear, prevGear, nextGear) => {

        const diffVector = gear.getVector().subtract(nextGear.getVector());

        let angle = 0;
        let x = 1 / diffVector.length;
        let y = x;

        if (gear.sweep === nextGear.sweep) {

            angle = Math.asin((gear.radius - nextGear.radius) * x);

            if (gear.sweep) {
                x = -x;
                y = -y;
                angle = -angle;
            }
        } else {

            angle = Math.asin((gear.radius + nextGear.radius) * x);

            if (gear.sweep) {
                x = -x;
                angle = -angle;
            } else {
                y = -y;
            }
        }

        const perpendicularVector = diffVector.rotate(angle + Math.PI / 2);

        gear.out = perpendicularVector.multiply(x * gear.radius).add(gear.getVector());
        nextGear.in = perpendicularVector.multiply(y * nextGear.radius).add(nextGear.getVector());
    });

    loopGears(gears, (gear, prevGear, nextGear) => {

        const largeArcFlag = (prevGear.out.subtract(nextGear.in).length < gear.in.subtract(gear.out).length);
        const arcPath = arcDescription(gear.radius, largeArcFlag, !gear.sweep, gear.out);

        const gearExterior = createCircle(gear.x, gear.y, gear.radius - 1.5, '#888');
        const gearInterior = createCircle(gear.x, gear.y, gear.radius - 4.5, '#666');
        const gearCenter = createCircle(gear.x, gear.y, 3, '#888');

        const gearTeeth = createPath({
            d: `M${gear.in}${arcPath}${arcDescription(gear.radius, !largeArcFlag, !gear.sweep, gear.in)}`,
            stroke: '#888',
            'stroke-width': 5
        });

        const chainParts = cloneElement(gearTeeth, {
            d: `M${gear.in}${arcPath}L${nextGear.in}`,
            stroke: '#222'
        });

        gear.teeth = gearTeeth;
        gear.chainParts = chainParts;

        chainPath += `${arcPath}L${nextGear.in}`;

        svg.appendChild(gearExterior);
        svg.appendChild(gearInterior);
        svg.appendChild(gearCenter);
        svg.appendChild(gearTeeth);
        svg.appendChild(chainParts);
    });

    const chain = cloneElement(firstGear.chainParts, {
        d: 'M' + firstGear.in + chainPath,
        'stroke-width': 2
    });

    const chainLength = chain.getTotalLength();
    const chainUnit = chainLength / Math.round(chainLength / (4 * Math.PI)) / 2;
    const animationOffset = 8 * chainUnit;

    loopGears(gears, (gear, prevGear) => {

        if (gear === firstGear) {
            gear.teethOffset = chainUnit;
            gear.chainOffset = 0;
        } else {
            gear.teethOffset = prevGear.teethOffset + prevGear.chainParts.getTotalLength();
            gear.chainOffset = prevGear.chainOffset + prevGear.chainParts.getTotalLength();
        }

        setAttributes(gear.teeth, {
            'stroke-dasharray': chainUnit,
            'stroke-dashoffset': gear.teethOffset
        });

        setAttributes(gear.chainParts, {
            'stroke-dasharray': chainUnit,
            'stroke-dashoffset': gear.chainOffset
        });

        const animate = createElement('animate', {
            attributeName: 'stroke-dashoffset',
            from: gear.teethOffset + animationOffset,
            to: gear.teethOffset,
            repeatCount: 'indefinite',
            dur: '1s'
        });

        const cloneAnimate = cloneElement(animate, {
            from: gear.chainOffset + animationOffset,
            to: gear.chainOffset
        });

        gear.teeth.appendChild(animate);
        gear.chainParts.appendChild(cloneAnimate);
    });

    svg.appendChild(chain);
    document.body.appendChild(svg);
};

var testCases = [
    [[0, 0, 16],  [100, 0, 16],  [100, 100, 12],  [50, 50, 24],  [0, 100, 12]],
    [[0, 0, 26],  [120, 0, 26]],
    [[100, 100, 60],  [220, 100, 14]],
    [[100, 100, 16],  [100, 0, 24],  [0, 100, 24],  [0, 0, 16]],
    [[0, 0, 60],  [44, 140, 16],  [-204, 140, 16],  [-160, 0, 60],  [-112, 188, 12], [-190, 300, 30],  [30, 300, 30],  [-48, 188, 12]],
    [[0, 128, 14],  [46.17, 63.55, 10],  [121.74, 39.55, 14],  [74.71, -24.28, 10], [75.24, -103.55, 14],  [0, -78.56, 10],  [-75.24, -103.55, 14],  [-74.71, -24.28, 10], [-121.74, 39.55, 14],  [-46.17, 63.55, 10]],
    [[367, 151, 12],  [210, 75, 36],  [57, 286, 38],  [14, 181, 32],  [91, 124, 18], [298, 366, 38],  [141, 3, 52],  [80, 179, 26],  [313, 32, 26],  [146, 280, 10], [126, 253, 8],  [220, 184, 24],  [135, 332, 8],  [365, 296, 50],  [248, 217, 8], [218, 392, 30]]
];

function clear() {
    var buttons = document.createElement('div');
    document.body.innerHTML = "";
    document.body.appendChild(buttons);
    testCases.forEach(function (data, i) {
        var button = document.createElement('button');
        button.innerHTML = String(i);
        button.onclick = function () {
            clear();
            renderGears(data);
            return false;
        };
        buttons.appendChild(button);
    });
}

clear();
```

---
Tags: code-golf, graphical-output, geometry, animation
---


title: Build a checkerboard

text:
# Question
Title: Build a checkerboard
For this challenge you will print the coordinates and color of each piece at the start of a game of checkers.

Enter the x and y (comma seperated) for every square (indexed 0-7) on a checkerboard, followed by a "r" or "b" (for red or black) where the top of the board (closer to y=0) is red and the bottom is black. newlines between pieces are required and no spaces are necessary.

This is so answers are scored in bytes with fewer bytes being better.

Trailing newlines are allowed but not necessary and the order must be exactly of that below.

Desired output:

```
0,0r
0,2r
0,4r
0,6r
1,1r
1,3r
1,5r
1,7r
2,0r
2,2r
2,4r
2,6r
5,1b
5,3b
5,5b
5,7b
6,0b
6,2b
6,4b
6,6b
7,1b
7,3b
7,5b
7,7b

```

# Answer
# 05AB1E, 26 bytes

```
2ÝD5+«v4Fy',N·yÉ+„bry3‹èJ,

```

Try it online!

**Explanation**

```
2Ý                           # push [0,1,2]
  D5+                        # duplicate and add 5: [5,6,7]
     «                       # concatenate
      v                      # for each y in [0,1,2,5,6,7] do:
       4F                    # for each N in [0 ... 3] do:
         y                   # push y
          ',                 # push ","
            N·yÉ+            # push N*2+isOdd(y)
                 „br         # push "br"
                    y3‹è     # index into the string with y<3
                        J,   # join everything to a string and print

```
> 8 votes

# Answer
# C (gcc), ~~83~~ ~~81~~ ~~79~~ 78 bytes

* Saved two bytes thanks to Tahg; golfing `x/4+2*(x/12)` to `x/4+x/12*2`.
* Saved two bytes thanks to Kevin Cruijssen; golfing `x%8*2%8` to `x*2%8`.
* Saved a byte thanks to ceilingcat.

```
x;main(){for(;x<24;)printf("%d,%d%c\n",x/4+x++/12*2,x*2%8+x/4%2,114-x/12*16);}

```

Try it online!
> 7 votes

# Answer
# JavaScript (ES6), 66 bytes

Includes a trailing newline.

```
f=(n=24)=>n--?f(n)+[2*(x=n>11)+(y=n>>2),n%4*2+y%2+'rb'[+x]]+`
`:''

```

### Demo

```
f=(n=24)=>n--?f(n)+[2*(x=n>11)+(y=n>>2),n%4*2+y%2+'rb'[+x]]+`
`:''

console.log(f())
```
> 7 votes

# Answer
# Perl 5, 53 bytes

```
//&map{say"$',",$_+$'%2,$'<4?r:b}0,2,4,6for 0..2,5..7

```

Try it online!
> 7 votes

# Answer
# Python 2, ~~74~~ ~~73~~ 67 bytes

```
for i in 0,1,2,5,6,7:j=i%2;exec"print`i`+','+`j`+'rb'[i>4];j+=2;"*4

```

Try it online!
> 6 votes

# Answer
# Java 8, ~~102~~ ~~96~~ ~~95~~ ~~93~~ 91 bytes

```
v->{for(int i=0;i<24;System.out.printf("%d,%d%c%n",i/4+i/12*2,i*2%8+i/4%2,i++<12?114:98));}

```

Port from *@JonathanFrech*'s C answer, after which I golfed 5 bytes myself.

Try it here.

**Explanation:**

```
v->{                    // Method without empty unused parameter and no return-type
  for(int i=0;i<24;     //  Loop from 0 to 24 (exclusive)
    System.out.printf("%d,%d%c%n",
                        //   Print with format:
                        //   (%d=digit; %c=character; %n=new-line)
      i/4+i/12*2,       //    Print first coordinate
      i*2%8+i/4%2,      //    Print second coordinate
      i++<12?114:98)    //    Print either 'r' or 'b'
  );                    //  End of loop
}                       // End of method

```
> 4 votes

# Answer
# Bash, 59 bytes

Not the shortest, but a fun one:

```
printf %s\\n {{0,2,6}\,{0,2,4,6}r,{1,5,7}\,{1,3,5,7}b}|sort

```

Try it online!
> 4 votes

# Answer
# APL (Dyalog Classic), 38 bytes

```
(⍕⍪4/3 4~⍨⍳8),',',(⍕⍪24⍴⍋8⍴⍳2),12/'rb'

```

Try it online!
> 4 votes

# Answer
# Jelly, 35 bytes

```
8Ḷḟ3ḟ4µḂr7m2ṭ€µ€Ẏµḣ1<3Ḣị⁾rbṭj”,$µ€Y

```

Try it online!

Full program taking no arguments

# Explanation

```
8Ḷḟ3ḟ4µḂr7m2ṭ€µ€Ẏµḣ1<3Ḣị⁾rbṭj”,$µ€Y  Main link; no arguments
8                                    8
 Ḷ                                   Push 0 .. 8 - 1
  ḟ                                  Remove all instances of
   3                                 3
    ḟ                                Remove all instances of
     4                               4
                €                    For each in [0, 1, 2, 5, 6, 7]
       µḂr7m2ṭ€µ                     Generate all of the piece coordinates across that row
        Ḃ                            row number % 2
         r                           inclusive range up to
          7                          7
           m                         modular; take every   elements
            2                                            2
              €                      For each column coordinate
             ṭ                       Tack the row coordinate (reverse append)
                 Ẏ                   Tighten; flatten once
                                 €   For each piece coordinate (in the right order now)
                 µḣ1<3Ḣị⁾rbṭj”,$µ    Convert to its final output
                  ḣ                  Head; take the first   element(s)
                   1                                      1
                    <                Less Than; compare each element to
                     3               3
                      Ḣ              Head; take the comparison out of the list
                       ị             Index (1-indexed) into
                        ⁾rb          "rb"
                           ṭ         Tack the color character behind
                            j”,$     The coordinates joined by a comma
                            j        Join with separator
                             ”,      ","
                                  Y  Separate by newlines

```
> 3 votes

# Answer
# Java 8, 97 bytes

```
o->{int i=0,g;for(;i<8;i+=i==2?3:1)for(g=i%2;g<8;g+=2)System.out.println(i+","+g+(i<5?"r":"b"));}

```
> 3 votes

# Answer
# APL (Dyalog), ~~45~~ 44 bytes\*

-1 thanks to ngn.

Niladic function which assumes 0-based indexing (`⎕IO←0`) which is default on many systems. Prints to STDOUT.

```
↑' '⎕R','⊃,/(8 ¯8↑¨⊂⍕¨⍸∘.=⍨2|⍳8),¨¨'rb'

```

Try it online!

`(``),¨¨'rb'` append "r" to each of the first group of items and "b" to each of the second:

`⍳8` zero through eight

`2|` division remainder when halved

`∘.+⍨` plus table with itself on along both axes

indices of true values

`⍕¨` format each (converts to strings with the pattern `d d` where each `d` is a digit)

enclose (so we can reuse it for each…)

`8 ¯8↑¨` take the first nine and the last nine

now we have two lists of `d d` strings

`,/` catenation reduction (combine the two lists)

disclose (because the reduction reduced the rank from 1 to 0)

`' '⎕R','` PCRE **R**eplace spaces with commas

mix (the all the lists into a single matrix)

---

<sup>* In Dyalog Classic, counting  as `⎕U2378`.</sup>
> 3 votes

# Answer
# JavaScript (ES6), 64 bytes

This seems sufficiently different from @Arnauld's to warrant posting:

```
f=(n=0,y=n>>3,c=y>2)=>y<6?[y+c*2,n%8+y%2+'rb'[+c]]+`
`+f(n+2):''

```

**Explanation:**

```
f=(n = 0,            //the numbered square on checkerboard
   y = n >> 3,       //current row (n / 8 rounded)
   c = y > 2         //false if red pieces, true if black
  ) =>
  y < 6 ?            //if y less than 6
    [                //  using an array automatically adds the comma
     y + c * 2,      //  0 - 2 if red pieces, 5 - 7 if black
     n%8 + y%2 +     //  n%8 returns 0, 2, 4, or 6.
                     //  y%2 returns 0 or 1.
                     //  added, they return the appropriate position (0 - 7)
     'rb'[+c]        //  'r' if red, 'b' if black.  Plus sign coerces boolean to number.
    ]+`              //  new line
    `+
    f(n+2) :         //  recurse on n+2
    ''               //else return an empty string

```

**Snippet:**

```
f=(n=0,y=n>>3,c=y>2)=>y<6?[y+c*2,n%8+y%2+'rb'[+c]]+`
`+f(n+2):''

console.log(f());
```
> 3 votes

# Answer
# Python 2, 63 bytes

```
x=0;exec"print`x/8+x/24*2`+','+`x%8+x/8%2`+'rb'[x/24];x+=2;"*24

```

Try it online!
> 3 votes

# Answer
# Bubblegum, 59 bytes

```
00000000: 15ca b101 0030 0400 c1de 2c0a 2462 1f23  .....0....,.$b.#
00000010: d8bf 886f ae3a 531b 310d b8f0 465c 1d0e  ...o.:S.1...F\..
00000020: 24d4 48ec 5b02 2eec 4bf5 5e0e 2454 cb53  $.H.[...K.^.$T.S
00000030: 8380 0baf a5d4 e140 42f5 07              .......@B..

```

Try it online!
> 2 votes

# Answer
# Pyth, ~~37~~ ~~36~~ 35 bytes

isaacg wouldn't be proud

```
V+U3}5 7FG4p++N\,+yG?!%N2Z1?<N5\r\b

```

Explanation:

```
V+U3}5 7            For in the array [0, 1, 2, 5, 6, 7] as N
 FG4                 For in the array [0, 1, 2, 3] as G
  p                   Print without newline:
   ++N\,+yG?!%N2Z1     N, (2 * G) + 1 if N is even, else 0
  ?<N5\r\b            Output with newline "r" if N < 5 else "b"

```

This uses a simple pattern I cut down a bit. As follows:

If the `X` coord is even, use the even numbers `0, 2, 4, 6`. Else, `1, 3, 5, 7` for `Y`.

If the `X` coord is less than 5, the color (`r` or `b`) is `r`. Else, it is `b`.

Try it online!

**edit**: overnight got +40 rep on 3 different answers w00t
> 2 votes

# Answer
# Javascript (89 bytes):

```
for(x=y=0,r="r";x<7|y<8;console.log(x+","+y+r),y+=2){if(y>7)y=++x%2;if(x==3){x+=2;r="b"}}

```

Readable:

```
for(var x = y = 0, red = true; x < 7 || y < 8; y += 2) {
    if(y > 7) { //new row
        x++;
        y = x % 2;
    }
    if(x == 3) { //new color
        x += 2;
        red = false;
    }
    console.log(x + "," + y + (red ? "r" : "b") );
}

```

Try it online!
> 1 votes

# Answer
# SOGL V0.12, 31 bytes

```
⁰¹²⁵⁶⁷’{A4∫«Ha2\⌡HaOļ,pƧbra4>Wo

```

Try it Here!
> 1 votes

# Answer
# Jelly, 27 bytes

```
8Ḷµḟ3,4pµSḂ$Ðḟj€”,ż⁾rbx12¤Y

```

A full program which prints the required output.

**Try it online!**

### How

```
8Ḷµḟ3,4p⁸SḂ$Ðḟj€”,ż⁾rbx12¤Y - Link: no arguments
8                           - literal eight
 Ḷ                          - lowered range = [0,1,2,3,4,5,6,7]
  µ                         - new monadic chain
    3,4                     - literal list = [3,4]
   ḟ                        - filter discard = [0,1,2,5,6,7]
        ⁸                   - chain's left argument = [0,1,2,3,4,5,6,7]
       p                    - Cartesian product = [[0,0],[0,1],...,[2,7],[5,0],...,[7,6],[7,7]]
            Ðḟ              - filter discard if:
           $                -   last two links as a monad:
         S                  -     sum
          Ḃ                 -     modulo by 2
                ”,          - literal comma character
              j€            - join €ach pair with a comma = [0,',',0],[0,',',2],...,[2,',',6],[5,',',1],...,[7,',',5],[7,',',7]]
                         ¤  - nilad followed by links as a nilad:
                   ⁾rb      - literal list = ['r','b']
                       12   - literal twelve
                      x     - repeat = ['r','r','r','r','r','r','r','r','r','r','r','r','b','b','b','b','b','b','b','b','b','b','b','b']
                  ż         - zip together = [[[0,',',0],'r'],[[0,',',2],'r'],...,[[2,',',6],'r'],[[5,',',1],'b'],...,[[7,',',5],'b'],[[7,',',7],'b']]
                          Y - join with newlines = [[0,',',0],'r','\n',[0,',',2],'r','\n',...,'\n',[2,',',6],'r','\n',[5,',',1],'b','\n',...,'\n',[7,',',5],'b','\n',[7,',',7],'b']
                            - implicit print (smashes the list of lists and characters
                            -                 together and prints the digits)

```
> 1 votes

# Answer
# Ruby, ~~63~~ 60 bytes

```
[*0..11,*20..31].map{|x|puts [x/4,2*x%8+x[2]]*?,+"rb"[x[4]]}

```

Bitmask magic saves the byte.

Try it online!
> 1 votes

# Answer
# PowerShell, 63 bytes

```
0..2+5..7|%{$i=$_;0,2,4,6|%{"$i,$($_+$i%2)"+('r','b')[$i-ge5]}}

```

Try it online!

Loops over `0,1,2,5,6,7` and each iteration sets `$i` to the current number. Then loops over `0,2,4,6`. Each inner loop, we construct a string starting with `$i,` then concatenated with our inner loop's current number plus whether `$i` is even or odd (which gets us `0,2,4,6` one time and `1,3,5,7` the other time), then concatenated with either `r`ed or `b`lack based on whether `$i` is `-g`reater-than-or-`e`qual to `5`. Those strings are all left on the pipeline and the implicit `Write-Output` at program completion gives us newlines for free.
> 1 votes

# Answer
# , ~~48 44 40 37~~ 31 bytes

```
(}:"1":$.|:8$#:162 69),.12#'rb'

```

Try it online!

### How it works

```
           8$#:162 69    first 2 columns in binary, take 8 of them
         |:              transpose
       $.                format as a sparse array, kind of looks like the goal
     ":                 "to text"
 }:"1                    delete the last column
       ,.12#'rb'         append 12 rs followed by 12 bs as the last column

```
> 1 votes

# Answer
# C# (.NET Core), 96 bytes

```
()=>{for(int i=0;i<24;)System.Console.Write($"{i/4+i/12*2},{i*2%8+i/4%2}{(i++>11?"b":"r")}\n");}

```

Try it online!

Essentially just a port to C# of @JonathanFrech's answer. I couldn't come up with any better way of doing the math.
> 1 votes

---
Tags: code-golf, kolmogorov-complexity, board-game
---


title: Digital Calendar

text:
# Question
Title: Digital Calendar
Given a date, output the X and Y position of the current day of the date on a digital calendar. The digital calendar is sort of the calendar that gets shown when you click on your computers clock (at least on windows), and it looks something like this:

If we assume that the given date is 25.09.2017, the result would be `(2,5)`, because the 25th day of the 9th month of this year is in the second column and fifth row.

Note that if the date would be something like 29.08.2017, we couldn't use the calendar from above, but a new one for August. The gray-ish numbers are simply there to fill the gaps until the day that the month actually starts.

## Input

A date, in any reasonable format.

## Output

The point or coordinates that the day of the given date lies at, in its respective calendar. These should be 1-indexed.

## Rules

* This is , the shortest code in any language wins.
* Standard loopholes are forbidden.

## Additional Notes

The first column of the calendar will always be **Sunday**.

Here are the digital calendars from January and September 2017:

## Test Cases

Input: `06.02.2018 (DD.MM.YYYY)` or `2018.02.06 (YYYY.MM.DD)`
Output: `(3,2)`

Input: `12.11.1982 (DD.MM.YYYY)` or `1982.11.12 (YYYY.MM.DD)`
Output: `(6,2)`

Input: `01.01.2030 (DD.MM.YYYY)` or `2030.01.01 (YYYY.MM.DD)`
Output: `(3,1)`

Input: `13.06.3017 (DD.MM.YYYY)` or `3017.06.13 (YYYY.MM.DD)`
Output: `(6,3)`

# Answer
# Mathematica, 83 bytes

**New Rules**:Starting on **Sunday**

```
{s=Min@Position[(d=DayName)@{6,1,#}&/@Range@7,d@DateObject@{##}],⌈(#3-s)/7⌉+1}&

```

*-5 bytes from @Misha Lavrov*

**Input form**

> \[2030, 1, 1\]
> yyyy-mm-dd
> 3 votes

# Answer
## JavaScript (ES6), ~~64~~ 59 bytes

```
f=
(s,d=new Date(s),e=d.getDay())=>[1+e,(d.getDate()-e)/7+2|0]
```

```
<input oninput=o.textContent=f(this.value)><pre id=o>
```

Input is any string which JavaScript recognises as a date. Save 16 bytes if a JavaScript date object is acceptable input. Edit: Saved 5 bytes thanks to @GrzegorzOledzki.
> 3 votes

# Answer
# TI-Basic (84+), 27 bytes (50 characters)

```
:Prompt Y,M,D
:dayOfWk(Y,M,D
:{Ans,2+int(7⁻¹(D-Ans

```
> 2 votes

# Answer
# Python 2, ~~109~~ 98 bytes

The datetime module docs are 50,000 bytes, so I'm not using the datetime module yet.

```
def f(d,m,y):t=m<3;y-=t;Y=y%100;W=(d+(13*m+156*t-27)/5-y/100*2+y/400+Y+Y/4)%7+1;print W,(d+13-W)/7

```

Try it online!

My formula to compute day of week comes from https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html.

The formula is as follows (converted from image to text):

> W = (k + floor(2.6\*m-0.2) - 2\*C + Y + floor(Y/4) + floor(C/4)) mod 7
>
> where floor(k) denotes the integer floor function
>
> k is day (1 to 31)
>
> m is month (1 = March, ..., 10 = December, 11 = Jan, 12 = Feb) Treat Jan & Feb as months of the preceding year C is century (1987 has C = 19)
>
> Y is year (1987 has Y = 87 except Y = 86 for Jan & Feb)
>
> W is week day (0 = Sunday, ..., 6 = Saturday)
>
> Here the century and 400 year corrections are built into the formula. The floor(2.6\*m-0.2) term relates to the repetitive pattern that the 30-day months show when March is taken as the first month.

The row number can be calculated as one more than the number of Sundays in the month preceding the day.

*-7 bytes thanks to @GrzegorzOledzki*
> 2 votes

---
Tags: code-golf, date
---


title: Increasing, decreasing, none or all?

text:
# Question
Title: Increasing, decreasing, none or all?
Take two inputs, a non-empty vector/list containing digits `1` and `2` and a string (no, you may not take `0/1` instead). The string will be one of the following (in lowercase, exactly as written below:

```
increasing
decreasing
ones
twos
all
none

```

If the string is \____ then you shall return the indices \___:

* `increasing` ... where the list changes from `1` to `2` (every `2` that follows directly after a `1`)
* `decreasing` ... where the list changes from `2` to `1` (every `1` that follows directly after a `2`)
* `ones` ... of all digits that are `1`
* `twos` ... of all digits that are `2`
* `all` ... all the digits
* `none` ... none of the digits. `0` is fine if the list is 1-indexed. A negative number is fine if the list is 0-indexed. You may also output an empty list or string.

### Test cases:

These are 1-indexed. You may choose if you want 1-indexed or 0-indexed. The same vectors are used for different strings in the test cases.

```
--------------------------------
Vector:
1 1 2 2 2 1 2 2 1 1 2

String       - Output
increasing   - 3, 7, 11
decreasing   - 6, 9
ones         - 1, 2, 6, 9, 10
twos         - 3, 4, 5, 7, 8, 11
all          - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
none         - 0 / []

------------------------------------
Vector:
1

String:
ones         - 1
all          - 1
decreasing / increasing / twos / none  - 0 / []

```

# Scoring

As this is , the answer with the least bytes wins.

### Explanations are encouraged!

# Answer
## JavaScript (Firefox 30-57), ~~74~~ 73 bytes

```
(a,[s],i=0,p)=>[for(e of a)if({i:e>p,d:e<p,o:e<2,t:e>1,a:1}[p=e,i++,s])i]

```

Array comprehensions are a neat way of combining `map` and `filter` in one go. Edit: Saved 1 byte thanks to @edc65.
> 7 votes

# Answer
# Python 2, ~~136~~ ~~131~~ ~~119~~ ~~108~~ 97 bytes

* Saved five bytes; using a `lambda` function.
* Saved twelve bytes thanks to TFeld; golfing two conditions.
* Saved eleven bytes thanks to Mr. Xcoder; using `enumerate()` instead of `range(len())`.
* Saved eleven bytes by using a list instead of a dictionary and using `0`-indexing (as in TFeld's answer) and golfing `"adinot".find(m[0])` to `ord(m[0])/3-32`.

```
lambda l,m:[j for j,k in enumerate(l)if[1,j*k<j*l[~-j],0,j*k>j*l[~-j],0,k<2,k>1][ord(m[0])/3-32]]

```

Try it online!
> 3 votes

# Answer
# Python 2, ~~117~~ ~~111~~ ~~110~~ ~~99~~ ~~97~~ 92 bytes

```
lambda l,t:[i for i,v in enumerate(l)if[l[i+i/~i]<v,0,v<2,v>1,1,l[i+i/~i]>v][ord(t[0])/3%7]]

```

Try it online!

`0`-indexed

Switched to using Jonathan's indexing, and golfed `ord(m[0])/3-32` to `ord(t[0])/3%7`
> 3 votes

# Answer
# Haskell, ~~112~~ ~~83~~ 81 bytes

```
s%l=[i|(i,p,q)<-zip3[1..]l$l!!0:l,elem(s!!0,1<2)$zip"idota"[q<p,p<q,p<2,1<p,1<2]]

```

Try it online! Example usage: `"increasing"%[1,1,2,1,2]`. Results are 1-indexed.

Partly inspired by Lynn's Haskell answer.
> 3 votes

# Answer
# MATL, ~~32~~ ~~31~~ ~~30~~ 29 bytes

```
dQ~fQGqfOOGofGd1=fQGfO[]Xhjs)

```

Output is 1-based, or empty.

**Try it online!**

### Explanation

The code computes the six possible outputs for the array input, and then selects the appropriate output depending on the string input.

To select the output, the ASCII code points of all characters of the string input are added. The result modulo 9 gives `6`, `1`, `5`, `2`, `7`, `0` respectively for `'increasing'`, `'decreasing'`, `'ones'`, `'twos'`, `'all'`, `'none'`. Since all the resulting numbers are distinct this can be used as a selection criterion.

Instead of actually performing a modulo 9 operation on the sum, the list of possible inputs is extended to 9 entries (some of which are dummy), and so indexing into that list is automatically done modulo 9.

```
d     % Implicit input: numeric vector. Push vector of consecutive differences.
      % Contains -1, 0 or 1
Q~    % For each entry: add 1, negate. This turns -1 into 1, other values into 0
f     % Push indices of nonzeros
Q     % Add 1 to each entry (compensates the fact that computing consecutive
      % differences removes one entry). This the output for 'decreasing'
Gq    % Push input again. Subtract 1 from the code points
f     % Push indices of nonzeros. This is the output for 'twos'
OO    % Push two zeros. These are used as placeholders
Go    % Push input and compute parity of each entry
f     % Push indices of nonzeros. This is the output for 'ones'
Gd    % Push input and compute consecutive differences
1=    % Test each entry for equality with 1
f     % Push indices of nonzeros
Q     % Add 1. This is the output for 'increasing'
Gf    % Push indices for all input (nonzero) entries. This is the output for 'all'
O     % Push zeros. Used as placeholder
[]    % Push empty array. This is the output for 'none'
Xh    % Concatenate stack into a cell array
j     % Input a string
s     % Sum of code points
)     % Use as an index into the cell aray. Implicitly display

```
> 2 votes

# Answer
# Java (OpenJDK 8), ~~266~~ ~~217~~ ~~213~~ ~~205~~ ~~172~~ ~~171~~ ~~155~~ 131 bytes

```
s->a->{int i=0,l=0,c=s.charAt(0)-97;for(int e:a){if(++i>1&(c==8&e>l|c==3&e<l)|c==14&(l=e)<2|c>18&l>1|c<1)System.out.print(i+",");}}

```

Try it online!
> 1 votes

# Answer
# Jelly, 27 bytes

```
>2\0;
NÇ
Ị
=2

ḟ
⁹Ḣ“hɠ»iµĿT

```

Try it online!

-3 thanks to Jonathan Allan.
> 1 votes

# Answer
# J, 73 bytes

```
g=.[:I.[=0,2-/\]
(_1 g])`(1 g])`(1=])`(2=])`(i.@#@])`_1:@.('idotan'i.{.@[)

```

Would be curious to see how this can be significantly condensed -- I believe it can (10 chars just for all those agenda parens!)

* `g` \- helper verb for increasing and decreasing, which just amount to comparing the values of infix `\` runs of size 2
* The rest just grabs the first character from the "command" and executes the corresponding case using Agenda `@.`

Try it online!
> 1 votes

# Answer
# Python 2, 92 bytes

```
lambda a,s:[i for i,(x,y)in enumerate(zip([0]+a,a))if[0<x<y,0,y<2,y>1,1,x>y][ord(s[0])/3%7]]

```

Try it online!
> 1 votes

# Answer
# Haskell, 91 bytes

```
(c:_)!l=[i|(i,y,x)<-zip3[1..]l$l!!0:l,c/='i'||x<y,c>'d'||x>y,c/='o'||y<2,c<'t'||y>1,c/='n']

```

Try it online!

Laikoni saved a byte.
> 1 votes

# Answer
# Husk, 27 bytes

```
`fN!+mmëI=2ε¬moΘẊe><€¨Ÿȧö¨←

```

Try it online!

-9 thanks to H.PWiz.

I'm quite proud of this answer.
> 1 votes

# Answer
# Jq 1.5, 131 bytes

Based on xcali's approach since string matching is shorter then my array version.

```
def D(s):[.[1]|gsub(" ";"")|match(s;"g").offset+(s|length)];./"
"|{i:D("12"),d:D("21"),o:D("1"),t:D("12"),a:D("."),n:[]}[.[0][0:1]]

```

Assumes jq is invoked with `-Rs` options and input appears on two lines e.g.

```
decreasing
1 1 2 2 2 1 2 2 1 1 2

```

Expanded:

```
def D(s): [
      .[1]                              # find where s appears
    | gsub(" ";"")                      # in the input and add
    | match(s;"g").offset + (s|length)  # length to get ending index
  ]
;

  ./"\n"                                # split on newline
| {i:D("12"),                           # increasing
   d:D("21"),                           # decreasing
   o:D("1"),                            # ones
   t:D("2"),                            # twos
   a:D("."),                            # all
   n:[]                                 # none
  }[.[0][0:1]]

```

Try it online!
> 1 votes

# Answer
# Java 8, ~~233~~ ~~229~~ 216 bytes

```
l->s->{int i=s.charAt(0)-97,k=0,j=1;for(s=(l+"").replaceAll("[^12]","");s.length()*j>0;System.out.print(j++<0?"":(k+=j)+","),s=s.substring(j))j=i<1?0:s.indexOf(i<4?"21":i<9?"12":i<14?" ":i<15?"1":"2")+(i>2&i<9?1:0);}

```

This String approach ended up longer than I was expecting.. But even thought I'm hugely out-golfed by the other Java 8 answer, I decided to post it anyway.
It can definitely be golfed, even with this approach.. The "none" and "increase/decreasing" mainly caused some workaround that cost some bytes..

The result is 1-indexed.

**Explanation:**

Try it here.

```
l->s->{                          // Method with List and String parameters
  int i=s.charAt(0)-97,          //  First character of the String - 97
                                 //   (i=8; d=3; o=14; t=19; a=0; n=13)
      k=0,                       //  Total counter
      j=1;                       //  Index integer
  for(s=(l+"")                   //  toString of the List,
         .replaceAll("[^12]","");//   and leave only the 1s and 2s
      s.length()*j>0             //  Loop as long as `j` and the size of the String
                                 //  are both larger than 0
      ;                          //   After every iteration:
      System.out.print(          //    Print:
       j++<0?                    //     If `j` is -1:
        ""                       //      Print nothing
       :                         //     Else:
        (k+=j)+",")              //      Print the current index
      ,s=s.substring(j))         //    And then remove the part of the String we've checked
    j=i<1?                       //   If "all":
                                 //    Change `j` to 0
      :                          //   Else:
       s.indexOf(                //    Replace `j` with the next index of:
        i<1?                     //     If "all":
         s.charAt(0)+""          //      The next character
        :i<4?                    //     Else-if "decreasing":
         "21"                    //      Literal "21"
        :i<9?                    //     Else-if "increasing":
         "12"                    //      Literal "12"
        :i<14?                   //     Else-if "none":
         " "                     //      Literal space (any char that isn't present)
        :i<15?                   //     Else-if "one":
         "1"                     //      Literal "1"
        :                        //     Else(-if "two"):
         "2")                    //      Literal "2"
       +(i>2&i<9?1:0);           //     +1 if it's "increasing"/"decreasing"
                                 //  End of loop (implicit / single-line body)
}                                // End of method

```
> 0 votes

# Answer
# Perl 5, 71 + 2 (`-nl`) = 73 bytes

```
$p=/l/?'.':/t/?2:/^o/?1:/d/?21:/i/?12:0;$_=<>;s/ //g;say pos while/$p/g

```

Try it online!

Revised logic is effectively the same as the below explanation, but the pattern matches have been shortened.

*Previously:*

```
$p=/all/?'.':/^o/?1:/^t/?2:/^d/?21:/^i/?12:0;$_=<>;s/ //g;say pos while/$p/g

```

Try it online!

Outputs nothing if the criteria is not matched.

**Explained:**

```
$p=          # set the pattern to seach based on the input string
  /all/?'.'  # any character
 :/^o/?1     # starts with 'o', find ones
 :/^t/?2     # starts with 't', find twos
 :/^d/?21    # starts with 'd', find decreasing
 :/^i/?12    # starts with 'i', find increasing
 :0;         # anything else: create pattern that won't match
$_=<>;s/ //g;# read the digits and remove spaces
say pos while/$p/g # output position(s) of all matches

```
> 0 votes

---
Tags: code-golf, number, parsing
---