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 code-golf so all usual golfing rules apply, and the shortest code (in bytes) wins.
14 Answers 14
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.
-
\$\begingroup\$ How does this guarantee the minimum 400x400 canvas? \$\endgroup\$David Mulder– David Mulder2017年11月02日 10:45:48 +00:00Commented Nov 2, 2017 at 10:45
-
1\$\begingroup\$ @DavidMulder FMSLogo by default (without additional command line) start with canvas 1000×1000. \$\endgroup\$user202729– user2027292017年11月02日 10:58:52 +00:00Commented Nov 2, 2017 at 10:58
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.
-
\$\begingroup\$ @Jenny_mathy Mathematica version maybe? I tested this on 11.1. \$\endgroup\$Martin Ender– Martin Ender2017年11月01日 15:02:42 +00:00Commented Nov 1, 2017 at 15:02
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. (削除ここまで)
-
\$\begingroup\$ I think
truecould be0<1. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年11月01日 13:44:47 +00:00Commented Nov 1, 2017 at 13:44 -
\$\begingroup\$ Also, can
main(String args[])not bemain(String[]Z)? \$\endgroup\$Jonathan Frech– Jonathan Frech2017年11月01日 13:47:40 +00:00Commented Nov 1, 2017 at 13:47 -
\$\begingroup\$ I think
{F f=new F();}can be{new F();}. \$\endgroup\$Jonathan Frech– Jonathan Frech2017年11月01日 13:49:22 +00:00Commented Nov 1, 2017 at 13:49 -
\$\begingroup\$
setVisible(0<1);can be removed, and you can add.show()to the Frame;printlncan beprint. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年11月01日 14:04:22 +00:00Commented Nov 1, 2017 at 14:04 -
1\$\begingroup\$ @KevinCruijssen I don't know how OP wants the output for multiple results \$\endgroup\$Roberto Graham– Roberto Graham2017年11月01日 14:05:29 +00:00Commented Nov 1, 2017 at 14:05
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.println(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
TI-Basic (TI-84 Plus CE), 49 bytes (45 tokens) (possibly non-competing)
0→Xmin
0→Ymin
83→Xmax
Ans→Ymax
While 1
Input
{X,Y
Input
Ans-{X,Y
Disp √(sum(Ans2
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
83→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(Ans2 # 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
-
1\$\begingroup\$ Since the size only has to be at least 400, you can golf that constant to something like
8³which is greater than 400 but one byte less. \$\endgroup\$kamoroso94– kamoroso942017年11月01日 18:29:13 +00:00Commented Nov 1, 2017 at 18:29 -
1\$\begingroup\$ Also you can reduce the
Displine by two bytes with{X-A,Y-B:Disp √(sum(Ans²(colon or newline works obviously). \$\endgroup\$kamoroso94– kamoroso942017年11月01日 18:34:14 +00:00Commented 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\$KarelPeeters– KarelPeeters2017年11月01日 21:13:00 +00:00Commented Nov 1, 2017 at 21:13 -
\$\begingroup\$ @ToddSewell no,
8^2(8 squared) is 64 and less than 400. I said8³(8 cubed) which is greater than 400 and uses two tokens, one byte each:8and³. \$\endgroup\$kamoroso94– kamoroso942017年11月01日 21:15:25 +00:00Commented Nov 1, 2017 at 21:15 -
1\$\begingroup\$ @ToddSewell: There sure is (MATH→3). \$\endgroup\$Nick Matteo– Nick Matteo2017年11月02日 16:20:45 +00:00Commented Nov 2, 2017 at 16:20
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
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.
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);}
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()
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
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.
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.
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.
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}
ntimes,n-1instead offloor(n/2)numbers are printed) Is that allowed? \$\endgroup\$