Curve stitching is the process of "stitching" together multiple straight lines in order to create a curve, like so:


For an explanation of curve stitching, visit this website.

We will be drawing our curve in the top left of the screen, as shown in the image above.

Given an integer n (via STDIN or a function parameter), being the number of lines to draw, and an integer p pixels, being the interval between the starting points, draw a straight line curve.

Horizontal/vertical lines are necessary, and should be part of the line count.

Example Outputs:

n = 25, p = 15


n = 20, p = 20


This is a challenge, so shortest code wins.

  • \$\begingroup\$ Oh yeah! D'oh... \$\endgroup\$ Commented Sep 12, 2014 at 15:37
  • \$\begingroup\$ The curve is in fact a parabola. I can't remember where I read that thoughl. If I was a pedant I would point out that it's not a "straight line curve" but an approximation of a curve built up from straight lines :-) \$\endgroup\$ Commented Sep 12, 2014 at 16:07
  • \$\begingroup\$ @Martin Yup, pixels. \$\endgroup\$ Commented Sep 12, 2014 at 16:15
  • \$\begingroup\$ @Martin The horizontal line shouldn't be necessary, because the border of the window will make up the lines. \$\endgroup\$ Commented Sep 12, 2014 at 16:41
  • 3
    \$\begingroup\$ Oh dayum I used to do this for fun when bored in class ... didn't know other people had done the exact same thing! \$\endgroup\$
    – Claudiu
    Commented Sep 12, 2014 at 20:32

10 Answers 10


Python - 74

Since the question doesn't specify units, axes scaling etc. I'm coming up with the following minimum solution:

import pylab
for i in range(n):pylab.plot([0,i*p],[(i-n)*p,0])

enter image description here

  • \$\begingroup\$ Disregarding units and axis scaling, the minimum solution saves four characters by omitting *p ;). also, are you sure you're not adding a horizontal and/or vertical line? those are not in the example outputs. finally, I noticed in mine, that it's shorter to offset the first coordinate horizontally instead of the second one (because you can save the - and the parentheses) \$\endgroup\$ Commented Sep 12, 2014 at 16:14
  • 2
    \$\begingroup\$ (The question does specify units as pixels now, btw.) \$\endgroup\$ Commented Sep 12, 2014 at 19:32

Mathematica, 55 51 50 47 64 68 bytes


Defines a function which yields the image as specified when called like



enter image description here

Edit: Had to add some characters to make sure that the second parameter was actually interpreted as pixels.

Edit: four more bytes to plot the horizontal lines.


Bash+Imagemagick+xview, 124 bytes

s+=" -draw 'line $[i*$2],0 0,$[($1-i++)*$2]'"
eval convert -size $[$1*$2]x$[$1*$2] xc:$s png:-|xview stdin

Output for ./curvestitch.sh 25 15:

enter image description here

  • \$\begingroup\$ Yay for overflowing the maximum command line length if you're not careful. Nice one \$\endgroup\$
    – tomsmeding
    Commented Sep 13, 2014 at 22:11

Basic 7.0, Commodore 128, 60 58 bytes


Watch a video of it running:

C128 video

Unfortunately, INPUT command hasn't an abbreviation :(


APL (dzaima/APL), 26 bytes

{P5.G.ln↓⍉↑⍵×⍺∘-@3⍳¨⍺1 1⍺}

-2 bytes from Adam using magic

Requires ⎕IO←0. (0-indexing)


{P5.G.ln↓⍉↑⍵×⍺∘-@3⍳¨⍺1 1⍺}
 P5.G.ln                   Create lines using the following sets of four points:
                    ⍺1 1⍺  Array [n,1,1,n]
                  ⍳¨       generate range 0..n for each
                @3         to the third element,
             ⍺∘-           subtract it from n.(reversing the last range)
           ⍵×              scale all items by p
          ↑                mix , creating columns of coordinates.
        ↓⍉                 transpose, and convert to lists of two points

APL (dzaima/APL), 28 bytes


Anonymous function which takes n and p as left and right arguments, and displays the pattern, given an adequately sized canvas.

Full Program here.

Made with a lot of advice and golfing from dzaima.

Test Cases

25, 15

enter image description here

20, 20

enter image description here


enter image description here

Java + Processing, 62 bytes

The original function I made for this question.

void c(int n,int p){for(int i=1;i<n;)line(p*i,0,0,p*(n-i++));}
  • \$\begingroup\$ Does {P5.G.ln↓⍉↑⍵×⍺-@3⍳¨⍺1 1⍺} work? \$\endgroup\$
    – Adám
    Commented Oct 21, 2020 at 5:04
  • \$\begingroup\$ @Adám IncorrectArgsError: @ can't be called dyadically \$\endgroup\$
    – Razetime
    Commented Oct 21, 2020 at 5:24
  • \$\begingroup\$ OK, but then you have the choice between {P5.G.ln↓⍉↑⍵×⍺∘-@3⍳¨⍺1 1⍺} and {P5.G.ln↓⍉↑⍵×(⍳⍺)⍬⍬(⍺-⍳⍺)} \$\endgroup\$
    – Adám
    Commented Oct 21, 2020 at 5:27
  • \$\begingroup\$ @Adám Added an explanation, hope it's correct. \$\endgroup\$
    – Razetime
    Commented Oct 21, 2020 at 6:03
  • 1
    \$\begingroup\$ Almost: ⍵× is a scaling applied to everything, not just item 3. \$\endgroup\$
    – Adám
    Commented Oct 21, 2020 at 6:05

Perl, 121 130 bytes

The input is via STDIN. The values are comma separated.

EDIT: We have new rules. I'm not sure why, but the first two pixels are invisible and I had to add an offset...

use Tk;<>=~/,/;$c=tkinit->Canvas(-width=>$w=$`*$'-$',-height=>$w)->pack;$c->createLine(2,2+$_*$',2+$w-$_*$',2)for 0..~-$`;MainLoop

Here are some tests:






BBC Basic, 58 ascii characters, tokenised filesize 49


Download emulator at http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

p*=2 is needed because in the default mode BBC Basic maps a logical square of 2x2 to a single physical pixel.

BBC Basic has the origin at the bottom left corner of the screen, with y coorinates going up. On my machine the default window has an upper y coordinate of 974 (yours may be different.) 7 characters could be saved if it was permitted to plot in the bottom left corner of the screen. Adding MODE16 after the first : will resize the window so that the upper y coordinate is guaranteed to be 799.

enter image description here

  • \$\begingroup\$ This is fast becoming a dangerous golfing language. CJam who? \$\endgroup\$ Commented Sep 13, 2014 at 2:29

Java 8, 143 bytes

import java.awt.*;n->p->new Frame(){{add(new Panel(){public void paint(Graphics g){for(int m=0;m<n;)g.drawLine(0,m*p,n*p-++m*p,0);}});show();}}

Output for \$n=25, p=15\$:

enter image description here

Output for \$n=5, p=50\$:

enter image description here


import java.awt.*;            // Required import for almost everything
n->p->                        // Method with two integer parameters & Frame return-type
  new Frame(){                //  Create the Frame
   {                          //   In an inner code-block:
     add(new Panel(){         //    Add a Panel we can draw on:
       public void paint(Graphics g){
                              //     Overwrite its paint method:
         for(int m=0;m<n;)    //      Loop `m` in the range [0,n):
           g.drawLine(        //       Draw a line:
             0,m*p,           //        Starting at x=0, y=m*p
             n*p-++m*p,0);}});//        to x=n*p-(m+1)*p, y=0
     show();}};               //    And afterwards show the Frame
  • 1
    \$\begingroup\$ I think it specifies that vertical and horizontal lines are necessary where it says "Horizontal/vertical lines are necessary, and should be part of the line count." (or am I misunderstanding you?) \$\endgroup\$ Commented Sep 4, 2020 at 11:48
  • \$\begingroup\$ @thedefault. Fixed. And it turned out even 2 bytes shorter. :) Thanks again for noticing. \$\endgroup\$ Commented Sep 4, 2020 at 13:26
  • \$\begingroup\$ I don't know java, but where in the code do you specify the output pixels? When I look at your 2 examples, they seem to be 305 & 176 pixels across, which is less than 25*15 & 5*50. Or is this just a side-effect of the up-/downloading? \$\endgroup\$ Commented Sep 4, 2020 at 14:07
  • \$\begingroup\$ @DominicvanEssen The width/height is actually \$(n-1)\times p\$, so 360 for the first test case and 200 for the second. But if the pictures shows something different it's probably an issue of automatic cropping when making a screenshot, uploading it to imgur, or showing it at stackexchange. I don't see it mentioning pixels in particular in the drawLine method (it uses Graphics coordinate system, but no idea what it uses by default). Tbh, I have no idea why my screenshots appear smaller than some other answers for the \$n=25,p=15\$ test case, but the calculations are correct with n & p.. \$\endgroup\$ Commented Sep 4, 2020 at 14:53
  • \$\begingroup\$ Ah, I kind-of assumed that the screenshot/upload/imgur/SE chain was to blame! So if your graphs are the correct sizes on your computer, I take it that the 'graphics' coordinates are defined as 1 coordinate = 1 pixel, which is quite convenient here! \$\endgroup\$ Commented Sep 4, 2020 at 14:59

Html + JavaScript 155 157 183

Edit: learnig what stuff I can cut without functionality loss
Edit 2: as suggested by @Optimizer

<canvas id='c'/><script>

Fiddle First input number of lines, second input pixel interval

Ungolfed Fiddle

  • \$\begingroup\$ l=p(s=p(t=c.getContext("2d"))) \$\endgroup\$
    – Optimizer
    Commented Sep 13, 2014 at 10:56
  • \$\begingroup\$ @Optimizer I think I need to set width and height before getting the context \$\endgroup\$
    – edc65
    Commented Sep 13, 2014 at 13:08
  • 1
    \$\begingroup\$ Nope, this works : jsfiddle.net/6ke43m7c/10 \$\endgroup\$
    – Optimizer
    Commented Sep 13, 2014 at 13:11

R, 100 bytes


Saves output to bitmap file 'Rplot001.bmp'.
There are some 'wasted' pixels at the top & on the left (so the curve is in the top left corner but not touching the edge). This seems to be within the spec, but could be removed for +13 bytes.

Commented code:

function(n,p,                   # n = number of lines, p = pixels between starting points
 P=p*n*1.08){                   # P = pixel dimensions of final plot.  
                                # (R expands axes by 4% at each end by default, so to 
                                # ensure that the curve itself is p*n pixels, we need 
                                # to expand the output by +8%
 bmp(,P,P)                      # open bitmap output to default filename, with dimensions PxP
 par(mar=!1:4)                  # remove margins by setting all to zero
 plot.new()                     # define new plot (default data range from 0 to 1)
 segments((1:n-1)/n,1,0,1:n/n)  # plot lines within range from 0 to 1
 dev.off()                      # close bitmap output to save file

Sample output:


enter image description here


enter image description here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.