Clasificar cuadriláteros | ¡Ayúdame con mi examen de matemáticas!


20

¡Ayuda! ¡Mi examen de matemáticas llegará pronto y no estudié! 1 Parte del examen es clasificar un cuadrilátero debido a sus coordenadas de vértice, que desafortunadamente no sé cómo hacer. 2

¡Entonces, su desafío es escribir un programa para hacer esto por mí para que no falle!

Desafío

Dados cuatro vértices de modo que no tres de ellos sean colineales, determine la clasificación más específica del cuadrilátero formado por esos cuatro vértices.

Lo que quiero decir con "clasificación más específica" es que, aunque todos los cuadrados son rectángulos, si la forma es un cuadrado, debe indicar que es un cuadrado y no indicar que es un rectángulo.

Entrada

La entrada se dará como cuatro coordenadas (x, y). Puede tomarlos como una lista de longitud 4 de listas / tuplas de longitud 2. Alternativamente, puede tomar la entrada como una lista de las coordenadas xy una lista de las coordenadas y respectivas.

Por ejemplo, si mi forma tiene vértices en los puntos (0, 0), (5, 0), (6, 1), y (1, 1), se puede optar por tomar de entrada en cualquiera de los siguientes formatos o algo similar:

[(0, 0), (5, 0), (6, 1), (1, 1)]
([0, 5, 6, 1], [0, 0, 1, 1])

Puede suponer que el cuadrilátero no se auto intersecta y que los puntos se dan en el orden correcto (es decir, dos puntos consecutivos en la entrada estarán conectados por un segmento de línea en el cuadrilátero).

Salida

Necesitará una salida única para cada una de las siguientes clases de cuadriláteros:

  • Cuadrado
  • Rectángulo
  • Rombo
  • Paralelogramo
  • Trapecio / Trapecio
  • Cometa
  • Cuadrilátero

Este podría ser el nombre exacto en sí, un personaje, un número entero, etc.

Reglas

  • Se aplican lagunas estándar
  • Si su lenguaje de programación tiene una función incorporada que realizará esta tarea exacta, esa función no está permitida.
  • Se permiten los elementos integrados para encontrar la distancia entre dos puntos.
  • Se permiten los elementos integrados para encontrar el ángulo entre dos líneas.

En este punto, si conoce todos los términos, ¡está listo para comenzar a programar! (Los casos de prueba están al final)

Terminología

Esta sección es para cualquier persona que necesite aclaraciones sobre las definiciones de las diferentes formas.

Cuadrado

Un cuadrilátero es un cuadrado si y solo si sus 4 lados tienen la misma longitud y cada par de lados adyacentes es perpendicular (es decir, es un rectángulo y un rombo).

Rectángulo

Un cuadrilátero es un rectángulo si y solo si cada par de lados adyacentes es perpendicular.

Rombo

Un cuadrilátero es un rombo si y solo si sus 4 lados son iguales.

Paralelogramo

Un cuadrilátero es un paralelogramo si y solo si cada par de lados opuestos es paralelo y cada par de ángulos opuestos es igual. Ambas condiciones implican una a la otra, por lo que solo necesita verificar una de ellas.

Trapecio / Trapecio

Un cuadrilátero es un trapecio / trapecio si y solo si tiene al menos un par de lados paralelos.

Cometa

Un cuadrilátero es una cometa si dos pares opuestos de lados adyacentes tienen la misma longitud; es decir, dos de sus lados adyacentes son iguales y los otros dos también son iguales.

Casos de prueba

input as (x, y) * 4 -> full name
[(0, 0), (1, 0), (1, 1), (0, 1)] -> square
[(0, 0), (1, 1), (-1, 3), (-2, 2)] -> rectangle
[(0, 0), (5, 0), (8, 4), (3, 4)] -> rhombus
[(0, 0), (5, 0), (6, 1), (1, 1)] -> parallelogram
[(0, 0), (4, 0), (3, 1), (1, 1)] -> trapezoid/trapezium
[(0, 0), (1, 1), (0, 3), (-1, 1)] -> kite  
[(0, 0), (2, 0), (4, 4), (0, 1)] -> quadrilateral

Enlaces (calculadora gráfica Desmos)

Aquí hay enlaces a visualizaciones de cada uno de los casos de prueba.

Cuadrado
Rectángulo
Rombo
Paralelograma
Trapecio / Trapecio
Cometa
Cuadrilátero

Criterios ganadores

Obviamente, no puedo traer una computadora al examen, así que necesito que escribas el código más corto posible para poder memorizarlo. ¡Necesito escribirlo en los márgenes y ejecutarlo usando TryItOffline TM para que quepa en los márgenes, su programa debe ser lo más pequeño posible!

1 Por supuesto que sí: P
2 Por supuesto que sí: P


1
Podría ayudarlo con su problema de margen xkcd.com/1381
Rohan Jhunjhunwala

@RohanJhunjhunwala Soy el nuevo Fermat (¿creo que es la persona adecuada?). Pero agradable ref XKCD: P
HyperNeutrino

¿Se permite la entrada CSV?
tuskiomi

¿Cuál es el orden parcial de especificidad?
Peter Taylor

Respuestas:


6

APL (Dyalog) , 104 89 80 82 81 79 78 bytes

⍙←{⍵⍺⍺1⌽⍵}
⎕←(|x){⍵≡2⌽⍵:≡⍙¨0⍺⍵⋄2 4=+/1=2|+⍙↑⍵(=⍙⍺)}2|1+-⍙(12x←-⍙⎕+.×1 0J1)÷○1

Pruébalo en línea!


De entrada y salida

Toma una matriz de coordenadas 4 × 2 como entrada

Salidas

  • 1 1 1 para la plaza
  • 1 1 0 para rombo
  • 1 0 1 para rectángulo
  • 1 0 0 para paralelogramo
  • 1 0 para la cometa
  • 0 1 para trapecio
  • 0 0 para cuadrilátero

Algoritmo

Primero, encuentre las 4 longitudes y ángulos laterales del cuadrilátero

Si ambos pares de ángulos opuestos son iguales ( OA), entonces la forma es algún tipo de paralelogramo. Determine si todas las longitudes de los lados son iguales ( AS, lados adyacentes) y si todos los ángulos son iguales ( AA).

+--------+----------------+----------------+
|        |       AA       |      ~AA       |
+--------+----------------+----------------+
|   AS   |     Square     |    Rhombus     |
|--------+----------------+----------------+
|  ~AS   |    Rectangle   |  Parallelogram |
+--------+----------------+----------------+

Si no OA, entonces:

  • Determine si hay exactamente 2 pares de lados adyacentes iguales y si están separados (en aabblugar de aaab). Si es así, la forma es una cometa.

  • Determine si hay exactamente 1 par de lados opuestos paralelos. Si es así, la forma es un trapecio.

  • De lo contrario, la forma es un cuadrilátero.


Código

⍙←{⍵⍺⍺1⌽⍵}define un nuevo operador. En APL, un operador significa una función de orden superior . Este operador toma 1 argumento funcional ( ⍺⍺) y devuelve una función monádica que:

  1. Rota ( 1⌽) el argumento ( )
  2. Aplicar ⍺⍺entre él y

Esto es especialmente útil para las funciones escalares, ya que la mayoría de ellas se mapean implícitamente en los argumentos de la matriz, lo que permite aplicarlas entre cada par de elementos adyacentes con ajuste. Por ejemplo, +⍙1 2 3 4es el 1 2 3 4 + 2 3 4 1que evalúa 3 5 7 5.


x←-⍙⎕+.×1 0J1 convierte la matriz de coordenadas de entrada en una matriz de números complejos que representan los vectores de los 4 lados de la forma.

  • , cuando se hace referencia, toma y devuelve la entrada

  • 1 0J1representa el vector [1, i] ("vector" en el sentido matemático e "i" como la raíz cuadrada de -1). En APL, a+bise escribe un número complejoaJb

  • +.×multiplicación de matrices Matemáticamente, el resultado sería una matriz 4 × 1. Sin embargo, +.×se llama "producto interno" en APL que generaliza la multiplicación de matrices y el producto interno de vectores y le permite hacer incluso cosas como "multiplicar" una matriz tridimensional con una bidimensional. En este caso, estamos multiplicando una matriz de 4 × 2 y un vector de 2 elementos, lo que resulta en un vector de 4 elementos (de las representaciones de números complejos de los 4 vértices dados).

  • -⍙es una resta por pares con envoltura como se indicó anteriormente. Esto proporciona los vectores de los 4 lados de la forma (como números complejos). Estos vectores apuntan en la dirección "inversa" pero eso no importa.

  • x← almacena eso en la variable x


2|1+-⍙(12○x)÷○1 encuentra (una representación de) los ángulos exteriores en los 4 vértices de la forma.

  • 12○xencuentra el argumento principal , en radianes, de cada uno de los 4 vectores laterales.

  • ÷○1se divide por π para que los ángulos sean más fáciles de trabajar. Por lo tanto, todos los ángulos se expresan como un múltiplo de un ángulo recto.

  • -⍙Sustracción por pares con envoltura como se indicó anteriormente. Esto le da a los 4 ángulos exteriores.

  • 2|1+ El argumento principal está limitado (-1,1] y la resta por pares hace el rango (-2,2]. Esto es malo ya que el mismo ángulo tiene 2 representaciones diferentes. Al hacer "sumar 1 mod 2", el ángulo es re limitado a (0,2]. Aunque todos los ángulos son 1 más de lo que debería ser, está bien si lo tenemos en cuenta.


|xencuentra la magnitud de cada uno de los 4 vectores laterales


{⍵≡2⌽⍵:≡⍙¨0⍺⍵⋄2 4=+/1=2|+⍙↑⍵(=⍙⍺)}define y aplica una función con la matriz de 4 ángulos exteriores como argumento correcto y la matriz de 4 longitudes laterales como argumento correcto .

  • La función tiene una expresión protegida. En este caso, ⍵≡2⌽⍵es el guardia.
  • Si el guardia evalúa, se ejecuta 1la siguiente expresión ≡⍙¨0⍺⍵y se devuelve su valor.
  • Si el guardia evalúa 0, esa expresión se omite y la siguiente 2 4=...=⍙⍺)se ejecuta en su lugar.

⍵≡2⌽⍵ comprueba si ambos pares de ángulos opuestos son iguales.

  • 2⌽⍵ Rota la matriz de ángulos en 2 lugares.
  • ⍵≡comprueba si que es el mismo que en sí

≡⍙¨0⍺⍵ devuelve un valor único para cada forma de tipo paralelogramo.

  • 0⍺⍵es la matriz de 3 elementos del escalar 0, la matriz de longitudes laterales y la matriz de ángulos .
  • ≡⍙¨se ejecuta ≡⍙para cada uno de esos elementos.
  • ≡⍙comprueba si todos los valores de una matriz son iguales comprobando si al girarla en 1 se obtiene la misma matriz. Los escalares no giran, por lo que ≡⍙0regresa 1. Como se señaló anteriormente, ≡⍙⍺busca un rombo y ≡⍙⍵busca un rectángulo.

2 4=+/1=2|+⍙↑⍵(=⍙⍺)devuelve un valor único para cada forma de tipo no paralelogramo. Esto se logra entrelazando los controles para la cometa y el trapecio.


2=+/1=2|+⍙⍵ busca un trapecio.

  • +⍙⍵da las sumas de ángulos adyacentes. Los ángulos interiores de las líneas paralelas suman un ángulo recto, por lo que también lo hacen los ángulos exteriores de los lados paralelos de un cuadrilátero. Entonces, cada par de lados paralelos debe conducir a dos 1o -1en las sumas de los ángulos adyacentes.

  • 1=2|Sin embargo, los ángulos en son 1 más de lo que deberían ser, por lo que los ángulos en realidad suman 1o 3. Esto se puede verificar con "mod 2 es igual a 1".

  • +/suma la matriz. Esto da un recuento de sumas de ángulos adyacentes que es 1o 3.

  • 2= compruebe si eso es igual a 2. (es decir, si hay exactamente un par de lados paralelos)


4=+/1=2|+⍙(=⍙⍺) busca una cometa.

  • (=⍙⍺)da una matriz que indica qué lados adyacentes son iguales. A diferencia , el =trabajo en cuanto a elementos. Por lo tanto, esta es una matriz de 4 elementos con 1s donde la longitud de ese lado es igual a la del lado "siguiente".

  • +⍙ Suma por pares con envoltura.

  • 1=2|Dado que (=⍙⍺)da una matriz booleana (una con solo 0sy 1s), los únicos valores posibles de suma por pares son 0, 1y 2. Entonces 1=2|es lo mismo que justo 1=.

  • +/suma la matriz. Esto da un recuento de sumas por pares que es 1.

  • 4=compruebe si eso es igual a 4. La única forma en que sucede es si (=⍙⍺)es 1 0 1 0o 0 1 0 1. Como se señaló anteriormente, esto significa que la forma es una cometa.


2 4=+/1=2|+⍙↑⍵(=⍙⍺) entrelaza los controles anteriores.

  • ⍵(=⍙⍺)es la matriz anidada de 2 elementos de la matriz y la matriz(=⍙⍺)

  • promueve la matriz anidada a una matriz adecuada. Dado que ⍵(=⍙⍺)es una matriz de 2 elementos de matrices de 4 elementos, el resultado es una matriz de 2 × 4.

  • +⍙Dado que (y, por extensión, ) gira el último eje (horizontal), +⍙a una matriz es lo mismo que aplicar +⍙a cada fila individualmente.

  • 1=2|tanto residual / mod ( |) como equals ( =) funcionan por elemento, incluso para matrices.

  • +/Por defecto, reduce ( /) funciona a lo largo del último eje (horizontal). Entonces, +/suma a lo largo de filas y convierte una matriz de 2 × 4 en una matriz simple de 2 elementos.

  • 2 4=Como =funciona por elemento, esto verifica las condiciones de cometa y trapecio simultáneamente.


3

Mathematica, 195 bytes

Which[s=Differences@{##,#};l=Norm/@s;r=#.#2==#2.#3==0&@@s;Equal@@l,If[r,1,2],#==#3&&#2==#4&@@l,If[r,3,4],MatchQ[l,{a_,b_,b_,a_}|{a_,a_,b_,b_}],5,#+#3=={0,0}||#2+#4=={0,0}&@@Normalize/@s,6,1>0,7]&

Con espacios en blanco:

Which[
    s = Differences @ {##,#};
    l = Norm /@ s;
    r = #.#2 == #2.#3 == 0& @@ s;

    Equal @@ l, If[r, 1, 2],
    # == #3 && #2 == #4& @@ l, If[r, 3, 4],
    MatchQ[l, {a_,b_,b_,a_}|{a_,a_,b_,b_}], 5,
    #+#3 == {0,0} || #2+#4 == {0,0}& @@ Normalize /@ s, 6,
    1 > 0, 7
]&

Salidas 1para cuadrados, 2rombos, 3rectángulos, 4paralelogramos, 5cometas, 6trapecios y 7cualquier otra cosa. Publicaría un enlace TIO, pero aparentemente esto no funciona en matemáticas.

Si los cuatro puntos son P, Q, R, y S, a continuación, {##,#}se {P,Q,R,S,P}, por lo que ses la lista de vectores secundarios {Q-P,R-Q,S-R,P-S}, les las longitudes de los vectores, y res la condición de que el ángulo entre Q-Py R-Qasí como el ángulo entre R-Qy S-Rson ambos 90grados.

Por lo tanto, si todas las longitudes de los lados son iguales, entonces el cuadrilátero es un rombo. Si se rmantiene, de hecho es un cuadrado, de lo contrario es solo un rombo simple.

Descartando los rombos, si ambos pares de lados opuestos son iguales, entonces el cuadrilátero sigue siendo paralelogramo. Si se rmantiene, de hecho es un rectángulo, de lo contrario, es solo un paralelogramo simple.

Al descartar paralelogramos, la lista de longitudes de los lados les de la forma {a,b,b,a}o {a,a,b,b}para algunos ay b, luego, el cuadrilátero es una cometa. Tenga en cuenta que, además, no puede ser un trapecio o, de hecho, sería un rombo.

Descartando paralelogramos y cometas, si el cuadrilátero tiene un par de lados paralelos, entonces es un trapecio. Verificamos esto mediante Normalizelos vectores laterales y verificando si se suma un par de vectores opuestos {0,0}.

Descartando todo lo anterior, si 1 > 0(es mejor que sea), entonces el cuadrilátero es simplemente un viejo cuadrilátero.


1

Python 2 , 463 410 408 397 bytes

Ahorró 53 bytes usando una tupla en la sexta línea en lugar de indexar en una lista.

Ahorró 11 bytes al cambiar a los enteros de salida 1 a 7 en lugar de la primera letra de cada forma. Los enteros corresponden de la siguiente manera:

  1. Cuadrado
  2. Rectángulo
  3. Rombo
  4. Paralelogramo
  5. Trapecio
  6. Cometa
  7. Cuadrilátero
from numpy import *;D=dot
from numpy.linalg import *;N=norm
def P(a,b):x=D(a,b);y=N(a)*N(b);return x==y or x==-y
def Q(a,b):return int(N(a)==N(b))
L=input()
a,b,c,d=tuple([(L[i][0]-L[(i+1)%4][0],L[i][1]-L[(i+1)%4][1]) for i in range(4)])
g=7
e=Q(a,c)+Q(b,d)
if e==2:
 g=(1if D(a,b)==0 else 3) if Q(a,b) else 2 if D(a,b)==0 else 4
elif P(a,c) or P(b,d):
 g = 5
elif Q(a,b) or Q(b,c):
 g = 6
print g

Pruébalo en línea!

Sin ánimo de mostrar la lógica

Se muestra como una función para mostrar la salida de las diferentes entradas de prueba. tenga en cuenta que cambié el ejemplo de prueba "Rectángulo" del que se proporcionó originalmente en la pregunta, que no era un rectángulo.

La lógica se basa en productos de punto y la norma (longitud) de los vectores formados por los lados del cuadrilátero para evaluar si los lados son iguales en longitud, paralelos en lados opuestos o perpendiculares a lados adyacentes.

def S(va, vb):
    return (va[0]-vb[0], va[1]-vb[1])
def dot(sa,sb):      # Eventually replaced with numpy.dot
    return(sa[0]*sb[0]+sa[1]*sb[1])
def norm(s):         # Eventually replaced by numpy.linalg.norm
    return (s[0]**2+s[1]**2)**.5
def isperp(a,b):     # Test if lines/vectors are perpendicular
    return dot(a,b)==0
def ispar(a,b):      # Test if lines/vectors are parallel
    x = dot(a,b)
    y = norm(a)*norm(b)
    return x == y or x == -y
def iseq(a,b):       # Test if lines/vectors are equal in length
    return norm(a)==norm(b)
   
def f(L):
    #Define the four sides
    s = []
    for i in range(4):
        s.append(S(L[i],L[(i+1)%4]))  # I refer often so shorter names may eventually

    guess = 'Q'
    eqsides = 0           # These 6 lines eventually golfed using integer arithmetic by returning an int from iseq()
    if iseq(s[0], s[2]):
        eqsides += 1
    if iseq(s[1],s[3]):
        eqsides += 1
    if eqsides == 2:
    # Opposite sides are equal, so square, rhombus, rectangle or parallelogram
        if iseq(s[0],s[1]):       #Equal adjacent sides, so square or rhombus
            guess='S' if isperp(s[0], s[1]) else 'H'
        else:                     # rectangle or Parallelogram
            guess='R' if isperp(s[0], s[1]) else 'P'
    elif ispar(s[0],s[2]) or ispar(s[1],s[3]):
        guess = 'T'
    elif iseq(s[0],s[1]) or iseq(s[1],s[2]):
        guess = 'K'
    return guess
    

#test suite:
print f([(0, 0), (1, 0), (1, 1), (0, 1)]) # -> square
print f([(0, 0), (1, 1), (-1, 3), (-2, 2)]) # -> rectangle
print f([(0, 0), (5, 0), (8, 4), (3, 4)]) #  -> rhombus
print f([(0, 0), (5, 0), (6, 1), (1, 1)]) #  -> parallelogram
print f([(0, 0), (4, 0), (3, 1), (1, 1)]) # -> trapezoid/trapezium
print f([(0, 0), (1, 1), (0, 3), (-1, 1)]) #-> kite  
print f([(0, 0), (2, 0), (4, 4), (0, 1)]) #-> quadrilateral

Pruébalo en línea!


1
[(0, 0), (2, 2), (4, 0), (0,-2)]
Clasificado

¿Funcionaría esto? repl.it/JRzE
Zacharý

@TwiNight Gracias. No vi esta posibilidad. El problema es que mi algoritmo inicial solo verifica si hay UN par de lados de longitud coincidente. Como muestra su ejemplo, eso no es suficiente. Necesitaría verificar un par de lados coincidentes y luego verificar si el par opuesto también tiene una longitud similar. He estado demasiado ocupado para implementar eso.
CCB60

0

Lote, 287 bytes

@set/aa=%3-%1,b=%4-%2,c=%5-%1,d=%6-%2,e=%7-%1,f=%8-%2,g=a*a+b*b,h=(h=c-a)*h+(h=d-b)*h,i=(i=c-e)*i+(i=d-f)*i,j=e*e+f*f,p=!(i-g)+!(j-h),q=!(h-g),r=!(a*e+b*f),k=q+!(j-i)^|!(j-g)+!(h-i),t=!(a*(f-d)-b*(e-c))+!((c-a)*f-(d-b)*e)
@if %p%==2 (echo 1%r%%q%)else if %k%==2 (echo 1)else (echo 1%t%)

Salidas en binario: 1= Cometa, 10= Cuadrilátero, 11= Trapecio, 100= Paralelogramo, 101= Rombo, 110= Rectángulo, 111= Cuadrado. Explicación: g, h, i, json los cuadrados de las longitudes de los lados. pes el número de pares de lados opuestos con la misma longitud, qdistingue entre paralelogramos / rectángulos y rhobmi / cuadrados al verificar si los pares opuestos son de hecho iguales, rdistingue entre paralelogramos / rombos y rectángulos / cuadrados a través de una verificación de perpendicularidad, kverifica si hay un cometa buscando pares de lados adyacentes iguales y tcomprueba un trapecio a través de un par de controles laterales paralelos.



@TwiNight Bah, buscar una cometa es realmente incómodo.
Neil

Sí, tuve la suerte de encontrar una forma compacta de hacerlo
TwiNight

@TwiNight tomaré tu palabra por ello; APL es completamente ilegible para mí.
Neil

La parte donde verifico si hay cometa es 2=|-.=⍙⍺. Sin duda se ve compacto si se ignora el puesto de trabajo en el cálculo (las longitudes de los lados 4) y toda una línea para definir
TwiNight
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.