13
\$\begingroup\$

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

Imgur

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

Imgur

n = 20, p = 20

Imgur


This is a challenge, so shortest code wins.

\$\endgroup\$
16
  • \$\begingroup\$ Oh yeah! D'oh... \$\endgroup\$ 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\$ Sep 12, 2014 at 16:07
  • \$\begingroup\$ @Martin Yup, pixels. \$\endgroup\$ 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\$ 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
    Sep 12, 2014 at 20:32

10 Answers 10

6
\$\begingroup\$

Python - 74

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

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

enter image description here

\$\endgroup\$
2
  • \$\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\$ Sep 12, 2014 at 16:14
  • 2
    \$\begingroup\$ (The question does specify units as pixels now, btw.) \$\endgroup\$ Sep 12, 2014 at 19:32
6
\$\begingroup\$

Mathematica, 55 51 50 47 64 68 bytes

f=Graphics[Line@Table[#2{{i-1,#+1},{0,i+1}},{i,#}],ImageSize->#*#2]&

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

f[25,15]

Yielding

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.

\$\endgroup\$
0
4
\$\begingroup\$

Bash+Imagemagick+xview, 124 bytes

for((;i<$1;));{
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

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

Basic 7.0, Commodore 128, 60 58 bytes

0inputn,p:gR1:s=n*p:do:dR1,s,0to0,n:s=s-p:n=n+p:loOwHs>=0

Watch a video of it running:

C128 video

Unfortunately, INPUT command hasn't an abbreviation :(

\$\endgroup\$
4
+200
\$\begingroup\$

APL (dzaima/APL), 26 bytes

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

-2 bytes from Adam using magic

Requires ⎕IO←0. (0-indexing)

Explanation

{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
                           [0..n,0,0,0..n]
                @3         to the third element,
             ⍺∘-           subtract it from n.(reversing the last range)
                           [0..n,0,0,n..0]
           ⍵×              scale all items by p
          ↑                mix , creating columns of coordinates.
        ↓⍉                 transpose, and convert to lists of two points

APL (dzaima/APL), 28 bytes

{P5.G.ln↓⍉↑(⍵×⍳⍺)⍬⍬(⍵×⍺-⍳⍺)}

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

6,72

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++));}
\$\endgroup\$
5
  • \$\begingroup\$ Does {P5.G.ln↓⍉↑⍵×⍺-@3⍳¨⍺1 1⍺} work? \$\endgroup\$
    – Adám
    Oct 21, 2020 at 5:04
  • \$\begingroup\$ @Adám IncorrectArgsError: @ can't be called dyadically \$\endgroup\$
    – Razetime
    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
    Oct 21, 2020 at 5:27
  • \$\begingroup\$ @Adám Added an explanation, hope it's correct. \$\endgroup\$
    – Razetime
    Oct 21, 2020 at 6:03
  • 1
    \$\begingroup\$ Almost: ⍵× is a scaling applied to everything, not just item 3. \$\endgroup\$
    – Adám
    Oct 21, 2020 at 6:05
3
\$\begingroup\$

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:

25x15:

25x15

6x72:

6x72

\$\endgroup\$
3
\$\begingroup\$

BBC Basic, 58 ascii characters, tokenised filesize 49

INPUTn,p:p*=2FORi=1TOn:MOVEi*p-p,974DRAW0,974-(n-i)*p:NEXT

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

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

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

Explanation:

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
\$\endgroup\$
5
  • 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\$ Sep 4, 2020 at 11:48
  • \$\begingroup\$ @thedefault. Fixed. And it turned out even 2 bytes shorter. :) Thanks again for noticing. \$\endgroup\$ 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\$ 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\$ 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\$ Sep 4, 2020 at 14:59
1
\$\begingroup\$

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>
p=prompt,s=p(l=p(t=c.getContext("2d")));for(c.width=c.height=y=s*l,x=0;l--;x-=s)t.moveTo(0,y-=s),t.lineTo(-x,0);t.stroke()
</script>

Fiddle First input number of lines, second input pixel interval

Ungolfed Fiddle

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

R, 100 bytes

function(n,p,P=p*n*1.08){bmp(,P,P)
par(mar=!1:4)
plot.new()
segments((1:n-1)/n,1,0,1:n/n)
dev.off()}

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:

curve_stitch=
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:

curve_stitch(10,10)

enter image description here

curve_stitch(5,50)

enter image description here

\$\endgroup\$

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.