27
\$\begingroup\$

Code a program or function to construct an interactive canvas on the screen of at least 400 pixels x 400 pixels in size. The canvas can be any color you wish, bordered or borderless, with or without a title bar, etc., just some form of obvious canvas.

The user will click on two distinct areas of the canvas and the program must output the Euclidean distance (in pixels) between those two clicks in some fashion (STDOUT, displaying an alert, etc.). The two clicks can be only left clicks, only right clicks, a left click for the first and right click for the second, two double-left-clicks, etc., any combination is acceptable. Special Note: Clicking-and-dragging (e.g., using MOUSEUP as the second point) is specifically not allowed; they must be two distinct clicks.

The user must be able do this multiple times, and must get an output each time, until the program is closed/force-quit/killed/etc. You can choose the method of closure (clicking an X, ctrl-C, etc.), whatever is golfier for your code.

Rules

  • Either a full program or a function are acceptable. If a function, however, you must still display the output to the user somehow (simply returning the value is not acceptable).
  • Output can be to the console, displayed as an alert, populated onto the canvas, etc.
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
\$\endgroup\$
17
  • \$\begingroup\$ Can we output exact results (which may contain square roots) or does it have to be decimals? \$\endgroup\$ Nov 1, 2017 at 14:00
  • \$\begingroup\$ @MartinEnder Either/or. Output formatting isn't the interesting part of this challenge. \$\endgroup\$ Nov 1, 2017 at 14:13
  • 1
    \$\begingroup\$ The HTML/JS solution, from the second click, outputs the distance from that click to previous click. (so if the user click n times, n-1 instead of floor(n/2) numbers are printed) Is that allowed? \$\endgroup\$
    – DELETE_ME
    Nov 1, 2017 at 15:08
  • \$\begingroup\$ @user202729 It's a little outside of what I was envisioning, but I can see how it complies with the rules I have written above, so I'll allow it. \$\endgroup\$ Nov 1, 2017 at 15:11
  • 1
    \$\begingroup\$ Can we use a smaller canvas size if our language can't support a 400 x 400 canvas? \$\endgroup\$ Nov 1, 2017 at 16:14

14 Answers 14

8
\$\begingroup\$

LOGO (FMSLogo), 54 52 bytes

[mouseon[setpos mousepos]"[pr distance mousepos]"[]]

Unfortunately, I can't find any Logo interpreter online support mouse handling like FMSLogo.

This is a "explicit-slot template", which is similar to lambda in other programming languages. Click left mouse for first point and right mouse for second point (print distance).

Explanation: (Logo is a turtle graphics programming language)

mouseon                  Turn on mouse handling, with the following action:
[setpos mousepos]        Set the turtle to `mousepos` (the position of the mouse) on left mouse down
"                        Do nothing on left mouse up
[pr distance mousepos]   Print the distance from turtle position (`distance` is Logo builtin for that purpose) to `mousepos` on right mouse down
"                        Do nothing on right mouse up
[]                       Do nothing on mouse movement

The " is an empty word. Normally template is expected to be a list (where [], an empty list, does nothing), passing a word is acceptable (it is wrapped in a list), and in this case it saves 2 bytes.

Run:

apply [... <put the code here> ...] []

The apply is one way to run template in Logo, the [] is argument list, for which the template receive none.

\$\endgroup\$
2
  • \$\begingroup\$ How does this guarantee the minimum 400x400 canvas? \$\endgroup\$ Nov 2, 2017 at 10:45
  • 1
    \$\begingroup\$ @DavidMulder FMSLogo by default (without additional command line) start with canvas 1000×1000. \$\endgroup\$
    – DELETE_ME
    Nov 2, 2017 at 10:58
7
\$\begingroup\$

Mathematica, 94 bytes

e="MouseDown";m:=x=MousePosition[];1~RandomImage~400~EventHandler~{e:>m,{e,2}:>Echo@Norm[x-m]}

The canvas is a random grey-scale image, the first click should be a left-click and the second one a right-click. The exact behaviour is actually that right-click prints the distance to the last click (left or right), so if you use right-click repeatedly, you can also get consecutive distances.

The results are exact, so they might contain a square root.

If the resolution of your webcam is at least 400x400, you could use CurrentImage[] instead of 1~RandomImage~400 for your canvas, saving 3 bytes.

\$\endgroup\$
1
  • \$\begingroup\$ @Jenny_mathy Mathematica version maybe? I tested this on 11.1. \$\endgroup\$ Nov 1, 2017 at 15:02
6
\$\begingroup\$

Java 8, 469 389 388 385 380 357 348 325 bytes

import java.awt.event.*;interface F{static void main(String[]a){new java.awt.Frame(){{setSize(400,400);double[]a={-1,0};addMouseListener(new MouseAdapter(){public void mouseClicked(MouseEvent e){if(a[0]<0){a[0]=e.getX();a[1]=e.getY();}else{System.out.println(Math.hypot(e.getX()-a[0],e.getY()-a[1]));a[0]=-1;}}});}}.show();}}

import javafx.application.*;import javafx.scene.*;import javafx.scene.layout.*;import javafx.stage.*;public class E extends Application{double[]a={-1,0};public void start(Stage s)throws Exception{Pane p=new Pane();s.setScene(new Scene(p,400,400));s.show();p.setOnMouseClicked(e->{if(a[0]<0){a[0]=e.getX();a[1]=e.getY();}else {System.out.println(Math.sqrt(Math.pow(e.getX()-a[0],2)+Math.pow(e.getY()-a[1],2)));a[0]=-1;}});}public static void main(String[]a){launch(a);}}

Would be shorter with AWT, but I've never used it.

\$\endgroup\$
11
  • \$\begingroup\$ I think true could be 0<1. \$\endgroup\$ Nov 1, 2017 at 13:44
  • \$\begingroup\$ Also, can main(String args[]) not be main(String[]Z)? \$\endgroup\$ Nov 1, 2017 at 13:47
  • \$\begingroup\$ I think {F f=new F();} can be {new F();}. \$\endgroup\$ Nov 1, 2017 at 13:49
  • \$\begingroup\$ setVisible(0<1); can be removed, and you can add .show() to the Frame; println can be print. \$\endgroup\$ Nov 1, 2017 at 14:04
  • 1
    \$\begingroup\$ @KevinCruijssen I don't know how OP wants the output for multiple results \$\endgroup\$ Nov 1, 2017 at 14:05
5
\$\begingroup\$

Java (OpenJDK 8), 282 bytes

import java.awt.event.*;interface M{static void main(String[]a){new java.awt.Frame(){int k,x,y;{addMouseListener(new MouseAdapter(){public void mouseClicked(MouseEvent e){x=e.getX()-k*x;y=e.getY()-k*y;k^=1;if(k<1)System.out.prin‌​tln(Math.hypot(x,y))‌​;}});setSize(800,600‌​);show();}};}}

I cannot test this right now; if someone could tell me if there are any compiler errors that would be great.

AWT would probably be shorter but I need an actual IDE for that lol. I've never used AWT before but I could make it work if I had an IDE. I could use the docs but that's really hard lol

-10 bytes using AWT thanks to Kevin Cruijssen
-44 bytes using an initializer block; developed independently of Roberto Graham though I now see that they did the same thing, I think
-6 bytes combining a few declarations thanks to Kevin
-11 bytes using an interface thanks to Kevin
-35 bytes eliminating some unnecessary variables thanks to mellamokb
-9 bytes removing the unnecessary import and using a qualified name thanks to mellamokb
-44 bytes thanks to mellamokb and aditsu

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

TI-Basic (TI-84 Plus CE), 49 bytes (45 tokens) (possibly non-competing)

0→Xmin
0→Ymin
8³→Xmax
Ans→Ymax
While 1
Input 
{X,Y
Input 
Ans-{X,Y
Disp √(sum(Ans²
Pause
End

-7 bytes with suggestions from kamoroso94

The user doesn't 'click' per se, but moves around a cursor on the graph screen with the arrow keys and hits enter to select a point, and the smallest movement is ~1.5 for x and ~2.4 for y.

Explanation:

0→Xmin                # 5 bytes
0→Ymin                # 5 bytes
8³→Xmax               # 6 bytes, 
Ans→Ymax              # 5 bytes, Set up graph screen size (512x512)
While 1               # 3 bytes, Until interrupted with `on` button
Input                 # 2 bytes, Get user input as a point on the graph screen in X and Y
{X,Y                  # 5 bytes, store the list {X,Y} in Ans
Input                 # 2 bytes, Get second user input as a point on the graph screen in X and Y
Ans-{X,Y              # 7 bytes, store {X1-X2,Y1-Y2} in Ans
Disp √(sum(Ans²       # 6 bytes, Display the distance between the two points
Pause                 # 2 bytes, Let the user see it (press `enter` to continue)
End                   # 1 bytes, End while loop
\$\endgroup\$
6
  • 1
    \$\begingroup\$ Since the size only has to be at least 400, you can golf that constant to something like which is greater than 400 but one byte less. \$\endgroup\$
    – kamoroso94
    Nov 1, 2017 at 18:29
  • 1
    \$\begingroup\$ Also you can reduce the Disp line by two bytes with {X-A,Y-B:Disp √(sum(Ans² (colon or newline works obviously). \$\endgroup\$
    – kamoroso94
    Nov 1, 2017 at 18:34
  • \$\begingroup\$ @kamoroso94 My TI-BASIC is rusty but would't that be 8^2, the same number of bytes? \$\endgroup\$ Nov 1, 2017 at 21:13
  • \$\begingroup\$ @ToddSewell no, 8^2 (8 squared) is 64 and less than 400. I said (8 cubed) which is greater than 400 and uses two tokens, one byte each: 8 and ³. \$\endgroup\$
    – kamoroso94
    Nov 1, 2017 at 21:15
  • 1
    \$\begingroup\$ @ToddSewell: There sure is (MATH→3). \$\endgroup\$ Nov 2, 2017 at 16:20
4
\$\begingroup\$

JavaScript (ES6) + HTML, 58 bytes

The webpage itself serves as the "canvas" in question; I think it's quite safe to assume the browser window will be at least 400x400 pixels.

E=0,onclick=e=>(E&&alert(Math.hypot(E.x-e.x,E.y-e.y)),E=e)


JavaScript (ES6) + HTML, 51 bytes

We can save 7 bytes if we ignore the NaN output on the first click. (@Nate)

E=onclick=e=>alert(Math.hypot(E.x-e.x,E.y-e.y),E=e)


JavaScript (ES6) + HTML + CSS, 58 + 0 + 13 = 71 bytes

Edit: With an additional 13 bytes of CSS, we can ensure the scroll area will be sufficiently large enough to fit the 400x400 requirement.

E=0,onclick=e=>(E&&alert(Math.hypot(E.x-e.x,E.y-e.y)),E=e)
*{padding:9in

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

Processing/Java, 149 bytes

void setup(){size(400,400);}void draw(){}int a,b;void mousePressed(){if(mouseButton==LEFT){a=mouseX;b=mouseY;}else println(dist(a,b,mouseX,mouseY));}

Pretty straightforward, uses 2 global variables and 3 built-in functions to do everything.

  • Setup: just initializes the window to 400x400
  • Draw: empty, but must exist for Processing to be interactive for >1 frame
  • MousePressed: if left click, save the mouse coordinates into the integers a and b. If right click, measure the distance from point (a, b) to the current position, and print to the console.
\$\endgroup\$
2
\$\begingroup\$

Processing.org 126

float i,d,x,y;void setup(){fullScreen();}void draw(){}void mousePressed(){d=dist(x,y,x=mouseX,y=mouseY);print(i++%2<1?" ":d);}
\$\endgroup\$
1
\$\begingroup\$

Python 2, 144

Prints distance between last clicks (first one prints distance from 400,400).

import Tkinter as t,math
r=t.Tk()
p=[400]*2
r.minsize(*p)
def f(e):print math.hypot(p[0]-e.x,p[1]-e.y);p[:]=e.x,e.y
r.bind('<1>',f)
r.mainloop()
\$\endgroup\$
0
\$\begingroup\$

Autohotkey, 146 bytes

A=0
Gui,Add,Text,W400 H400 gC Border
Gui,Show
Return
C:
If A=0
MouseGetPos,A,B
Else{
MouseGetPos,C,D
Msgbox % Sqrt((A-C)**2+(B-D)**2)
A=0
}
Return

You'd think a language built specifically for capturing and simulating keyboard and mouse actions would be more efficient at this challenge...

This creates a window with a text box 400 x 400 pixels with a border to make it obvious. Without the border, there's a space around the edge that's in the window but outside the text box and you can't tell. Adding a border was the shortest way to differentiate them. The gC option make it run the subroutine C whenever you click on the text box. The command sequence is, therefore, Left Click followed by a different Left Click.

I found another solution that's 144 bytes but it allows clicks all over the screen instead of just in the "obvious canvas". It's also annoying to end because both left and right clicks are captured and it doesn't end when you close the GUI.

Gui,Add,Text,W400 H400 Border
Gui,Show
Return
LButton::
MouseGetPos,A,B
Return
RButton::
MouseGetPos,C,D
Msgbox % Sqrt((A-C)**2+(B-D)**2)
Return
\$\endgroup\$
0
\$\begingroup\$

Python 2 (TigerJython), 125 123 bytes

from gturtle import*
n=0
def c(x,y):
 global n
 if n:print distance(x,y)
 else:setPos(x,y)
 n^=1
makeTurtle(mousePressed=c)

TigerJython comes with a default size of (800x, 600y) sized canvas.

This spawns a temporary turtle image for every 'begin' point clicked, which disappears after the next 'begin' point is selected. This behaviour is approved by the OP.

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

SmileBASIC, 86 bytes

@L
TOUCH OUT F,X,Y
S=S-X
T=T-Y
IF!O*F*M THEN?SQR(S*S+T*T)
S=X
T=Y
M=M!=!O*F
O=F
GOTO@L

Uses touch screen for input.

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

Java 8, 228 bytes

interface A{static void main(String[]a){new java.awt.Frame(){{setSize(400,400);}int i,j,t;public boolean mouseDown(java.awt.Event e,int x,int y){if(t++%2==1)System.out.println(Math.hypot(x-i,y-j));i=x;j=y;return 1>0;}}.show();}}

Here's a Java solution that uses a deprecated AWT method mouseDown that you'd have to dig deep into the API to find. I only know of it because of the programming course I took as a high school sophomore, and one of the projects was to make a small paint program using that and similar methods. I never thought I'd have a good reason to use it until now.

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

Tcl/Tk, 94 104

wm ge . 400x400
bind . <1> {if [info ex x] {puts [expr hypot(%x-$x,%y-$y)]}
set x %x
set y %y}

enter image description here

\$\endgroup\$

Your Answer

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

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