Estoy tratando de escribir un programa que calcule la distancia entre dos puntos desde la entrada estándar. Pero los dos puntos deben leerse desde la misma línea. Por ejemplo (25,2) (26,15). Estoy atascado en una parte donde no pude poner esas entradas en una línea. Tengo esto hasta ahora:

/*
This Distance Program calculates the distance between two points
 */
package distance;

/**
 *
 * @author
 */
import java.util.Scanner;

public class Distance {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);
        System.out.println("X1");

        try {

            double x1 = input.nextDouble();

            double y1 = input.nextDouble();

            double x2 = input.nextDouble();

            double y2 = input.nextDouble();

            double dist = Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
            System.out.println("Distance between two points is: " + dist);
        } catch (Exception E) {
            System.out.println(E);
        }

    }

}
2
UsNepal Platform 28 dic. 2016 a las 10:12

3 respuestas

La mejor respuesta

Como señaló @GhostCat, puede usar regex para verificar el formato de entrada del usuario. Implementé una posible solución.

  1. Solicite la entrada del usuario en formato (x1, y1) (x2, y2).
  2. Compruebe si la entrada del usuario es correcta (imprima el mensaje de error si no lo es).
  3. Si el formato es correcto, usted hace los cálculos: calcule la distancia usando los grupos matcher para obtener la subsecuencia capturada.

Regex sin procesar:

^ ((-? \ d +), (-? \ d +)) \ s ((-? \ d +), (-? \ d +)) $

La expresión regular coincidirá entre paréntesis, comas y espacios literalmente, y capturará en grupos los cuatro números. es decir

Regex example

Clase de distancia:

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Distance {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);
        System.out.println("Insert two point to calculate the distance. Format: (x1,y1) (x2,y2) : ");

        Pattern pattern = Pattern.compile("^\\((-?\\d+),(-?\\d+)\\)\\s\\((-?\\d+),(-?\\d+)\\)$");
        Matcher matcher = pattern.matcher( input.nextLine ( ) );

        if ( matcher.matches ( ) )
        {
            System.out.println ( "Good" );
            double dist = Math.sqrt( Math.pow ( Long.parseLong ( matcher.group(3) ) - Long.parseLong ( matcher.group(1) ) , 2 ) + 
                    Math.pow ( Long.parseLong ( matcher.group(4) ) - Long.parseLong ( matcher.group(2) ) , 2 ) );
            System.out.println ( "Distance: " + dist );
        }

        else
        {
            System.out.println ( "Wrong input format" );
        }

    }

}

Nota: ya que está utilizando el Matemáticas Clase que recomiendo usar pow en lugar de multiplicación cruda.

Nota2: en Java, un carácter precedido por una barra invertida (\) es una secuencia de escape y tiene un significado especial para el compilador. Es por eso que en el código debe agregar uno adicional.

Ejemplos de E / S:

Insert two point to calculate the distance. Format: (x1,y1) (x2,y2) : 
2 3 4 5
Wrong input format

Insert two point to calculate the distance. Format: (x1,y1) (x2,y2) : 
(-2,-3) (-4,4)
Good
Distance: 7.280109889280518

Extra:

También puede verificar el rango de puntos. Está más claro si crea un método estático como este.

public static boolean rangeInclusive(int x, int y, int min, int max)
    {
        return x>=min && x<=max && y>=min && y<=max;    
    }

Esto devolverá verdadero si x e y están en el rango min-max inclusive. Falso de lo contrario.

Dijo que haces los cálculos solo si los puntos están en el rango, así:

if ( matcher.matches ( ) )
        {
            if( rangeInclusive ( Integer.parseInt ( matcher.group(1) ) , Integer.parseInt ( matcher.group(2) ), -50 , 50 ) &&
                    rangeInclusive ( Integer.parseInt ( matcher.group(3) ) , Integer.parseInt ( matcher.group(4) ), -50 , 50 ))
            {
                double dist = Math.sqrt( Math.pow ( Long.parseLong ( matcher.group(3) ) - Long.parseLong ( matcher.group(1) ) , 2 ) + 
                        Math.pow ( Long.parseLong ( matcher.group(4) ) - Long.parseLong ( matcher.group(2) ) , 2 ) );
                System.out.println ( "Distance: " + dist );
            }
            else
            {
                System.out.println ( "Wrong range" );
            }

        }
1
Rcordoval 28 dic. 2016 a las 21:36

La clave aquí es: debe ser específico sobre el formato exacto que su usuario debe proporcionar. Sí, ingresar una sola cadena y analizar ese contenido es una buena idea, pero ... presenta este ejemplo (25,2) (26,15) en tu pregunta. Y esa cadena no funcionará con la solución de Itamars.

Entonces, el punto es: antes de comenzar a pensar "cómo analizo la entrada del usuario", debe aclarar para usted mismo cómo espera / desea que el usuario ingrese esas dos coordenadas.

Significado: si su usuario le da "n1 n2 n3 n4" (entonces 4 números); puedes dividir usando \ s +. Si su usuario le da "n1, n2, n3, n4)", entonces debe dividir en "," por ejemplo.

Y para permitir su formato dado "(x1, y1) (x2, y2)" probablemente primero se dividiría en \ s + (dándole dos cadenas; que luego se dividirá nuevamente usando ",". O aprenderá sobre expresiones regulares, porque hacen que tal análisis sea mucho más fácil de escribir.

En pocas palabras: no trabaje con requisitos poco claros .

Finalmente: también sea preciso sobre los tipos utilizados. Estás utilizando doble en tu código; pero, ¿es eso realmente lo que necesitas? Como ejemplo de entrada ... está usando solo números enteros. Por supuesto, el doble siempre funcionará; pero cuando quieras que tu usuario use números enteros, ¡deberías usar int o long en su lugar!

2
GhostCat 28 dic. 2016 a las 07:40

Si el formato de la entrada es ##.## ##.## ##.## ##.## (cada ##.## es un doble, y no necesita tener un lugar decimal, por ejemplo, puede ser un número entero, como 5), lo que significa los números están separados por espacios, entonces esto funcionará:

String line = input.nextLine();
String[] points = line.split("\\s+");

if(points.length() == 4){
    double x1 = Double.parseDouble(points[0]);
    double y1 = Double.parseDouble(points[1]);
    double x2 = Double.parseDouble(points[2]);
    double y2 = Double.parseDouble(points[3]);
    //and the rest is the same
}

Lo que esto hace es leer un String de la entrada. Luego divide las cadenas por los espacios entre ellas (\\s+ divide la cadena en cadenas que tienen uno o más espacios entre ellas). El conjunto de cadenas son en realidad dobles, por lo que las convertimos en dobles.

NOTA: Si la entrada es algo que no es doble, obtendrá un error.

3
ItamarG3 28 dic. 2016 a las 07:46