Classificar quadriláteros | Ajude-me com o meu exame de matemática!

20

Socorro! Meu exame de matemática está chegando em breve e eu não estudei! 1 Parte do exame é classificar um quadrilátero, considerando suas coordenadas de vértice, que eu, infelizmente, não sei como fazer. 2

Então, seu desafio é escrever um programa para fazer isso por mim, para que eu não falhe!

Desafio

Dado quatro vértices de modo que nenhum deles seja colinear, determine a classificação mais específica do quadrilátero formado por esses quatro vértices.

O que quero dizer com "classificação mais específica" é que, embora todos os quadrados sejam retângulos, se a forma for um quadrado, você deve indicar que é um quadrado e não um retângulo.

Entrada

A entrada será dada como quatro (x, y) coordenadas. Você pode considerá-las como uma lista de comprimento 4 de listas / tuplas de comprimento 2. Como alternativa, você pode receber entradas como uma lista das coordenadas x e uma lista das respectivas coordenadas y.

Por exemplo, se a minha forma tem vértices em pontos (0, 0), (5, 0), (6, 1), e (1, 1), você pode optar por tirar a entrada em um dos seguintes formatos ou algo semelhante:

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

Você pode assumir que o quadrilátero não é auto-interceptado e que os pontos são dados na ordem correta (ou seja, dois pontos consecutivos na entrada serão conectados por um segmento de linha no quadrilátero).

Saída

Você precisará de uma saída exclusiva para cada uma das seguintes classes de quadriláteros:

  • Quadrado
  • Retângulo
  • Rhombus
  • Paralelogramo
  • Trapézio / Trapézio
  • Pipa
  • Quadrilátero

Pode ser o nome exato, um caractere, um número inteiro etc.

Regras

  • As brechas padrão se aplicam
  • Se a sua linguagem de programação possuir um built-in que executará essa tarefa exata, esse built-in não será permitido.
  • Built-ins para encontrar a distância entre dois pontos são permitidos.
  • São permitidos embutidos para encontrar o ângulo entre duas linhas.

Neste ponto, se você conhece todos os termos, está pronto para começar a programar! (Os casos de teste estão no final)

Terminologia

Esta seção é para quem precisa de esclarecimentos sobre as definições das diferentes formas.

Quadrado

Um quadrilátero é um quadrado se, e somente se, todos os quatro lados forem iguais em comprimento e cada par de lados adjacentes for perpendicular (ou seja, for um retângulo e um losango).

Retângulo

Um quadrilátero é um retângulo se, e somente se, cada par de lados adjacentes for perpendicular.

Rhombus

Um quadrilátero é um losango se e somente se todos os quatro lados forem iguais.

Paralelogramo

Um quadrilátero é um paralelogramo se, e somente se, cada par de lados opostos for paralelo e cada par de ângulos opostos for igual. Ambas as condições implicam uma à outra, portanto, você só precisa verificar uma delas.

Trapézio / Trapézio

Um quadrilátero é um trapézio / trapézio se e somente se tiver pelo menos um par de lados paralelos.

Pipa

Um quadrilátero é uma pipa se dois pares opostos de lados adjacentes são iguais em comprimento; isto é, dois dos seus lados adjacentes são iguais e os outros dois também são iguais.

Casos de teste

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

Links (calculadora gráfica Desmos)

Aqui estão os links para visualizações de cada um dos casos de teste.

Trapézio quadrado do paralelogramo do rombo do
retângulo / papagaio trapézio quadrilátero




Critérios Vencedores

Como não consigo trazer um computador para o exame, obviamente, preciso que você escreva o código mais curto possível para que eu possa memorizá-lo. Preciso gravá-lo nas margens e executá-lo usando o TryItOffline TM , para ajustá-lo às margens do seu programa precisa ser o menor possível!

1 Claro que sim: P
2 Claro que sim: P

HyperNeutrino
fonte
1
Talvez eu possa ajudá-lo com seu problema de margem xkcd.com/1381
Rohan Jhunjhunwala
@RohanJhunjhunwala Eu sou o novo Fermat (acho que é a pessoa certa?). Mas bom ref XKCD: P
HyperNeutrino 22/06
CSV é permitido?
tuskiomi
Qual é a ordem parcial de especificidade?
Peter Taylor
Related
Digital Trauma

Respostas:

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

Experimente online!


Entrada / Saída

Toma uma matriz 4 × 2 de coordenadas como entrada

Saídas

  • 1 1 1 para Square
  • 1 1 0 para Rhombus
  • 1 0 1 para retângulo
  • 1 0 0 para paralelogramo
  • 1 0 para Kite
  • 0 1 para trapézio
  • 0 0 para quadrilátero

Algoritmo

Primeiro, encontre todos os 4 comprimentos e ângulos laterais do quadrilátero

Se os dois pares de ângulos opostos são iguais ( OA), a forma é algum tipo de paralelogramo. Determine se todos os comprimentos laterais são iguais ( AS, lados adjacentes) e se todos os ângulos são iguais ( AA).

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

Caso contrário OA, então:

  • Determine se existem exatamente 2 pares de lados adjacentes iguais e se eles estão separados (em aabbvez de aaab). Nesse caso, a forma é uma pipa.

  • Determine se há exatamente 1 par de lados opostos paralelos. Nesse caso, a forma é um trapézio.

  • Caso contrário, a forma é quadrilateral.


Código

⍙←{⍵⍺⍺1⌽⍵}define um novo operador. No APL, um operador significa uma função de ordem superior . Este operador pega 1 argumento funcional ( ⍺⍺) e retorna uma função monádica que:

  1. Gira ( 1⌽) o argumento ( )
  2. Aplique ⍺⍺entre ele e

Isso é especialmente útil para funções escalares, pois a maioria delas mapeia implicitamente os argumentos da matriz, permitindo aplicar aqueles entre cada par adjacente de elementos ao redor. Por exemplo, +⍙1 2 3 4é o 1 2 3 4 + 2 3 4 1que avalia como 3 5 7 5.


x←-⍙⎕+.×1 0J1 converte a matriz de coordenadas de entrada em uma matriz de números complexos que representam os vetores dos 4 lados da forma.

  • , quando referenciado, recebe e retorna entrada

  • 1 0J1representa o vetor [1, i] ("vetor" no sentido matemático e "i" como a raiz quadrada de -1). Na APL, um número complexo a+bié gravadoaJb

  • +.×multiplicação da matriz. Matematicamente, o resultado seria uma matriz 4 × 1. No entanto, +.×é chamado de "produto interno" no APL, que generaliza a multiplicação de matrizes e o produto interno de vetor e permite que você faça coisas como "multiplicar" uma matriz tridimensional por uma matriz bidimensional. Nesse caso, estamos multiplicando uma matriz 4 × 2 e um vetor de 2 elementos, resultando em um vetor de 4 elementos (das representações numéricas complexas dos 4 vértices fornecidos).

  • -⍙é uma subtração pareada com enrolamento, como observado acima. Isso fornece os vetores dos quatro lados da forma (como números complexos). Esses vetores apontam na direção "reversa", mas isso não importa.

  • x← armazena isso na variável x


2|1+-⍙(12○x)÷○1 encontra (uma representação) os ângulos externos nos 4 vértices da forma.

  • 12○xencontra o argumento principal , em radianos, de cada um dos 4 vetores laterais.

  • ÷○1divide por π para facilitar o trabalho dos ângulos. Assim, todos os ângulos são expressos como múltiplos de um ângulo reto.

  • -⍙Subtração aos pares, envolva-a como indicado acima. Isso fornece os 4 ângulos externos.

  • 2|1+ O argumento principal é limitado (-1,1] e a subtração pareada faz o intervalo (-2,2]. Isso é ruim, pois o mesmo ângulo tem 2 representações diferentes. Ao fazer "add 1 mod 2", o ângulo é limitado a (0,2]. Embora todos os ângulos sejam 1 mais do que deveriam ser, tudo bem se mantivermos isso em mente.


|xencontra a magnitude de cada um dos 4 vetores laterais


{⍵≡2⌽⍵:≡⍙¨0⍺⍵⋄2 4=+/1=2|+⍙↑⍵(=⍙⍺)}define e aplica uma função com a matriz de 4 ângulos exteriores como argumento correto e a matriz com 4 comprimentos laterais como argumento correto .

  • A função tem uma expressão protegida. Nesse caso,⍵≡2⌽⍵ é o guarda.
  • Se o guarda avaliar se 1 então a próxima expressão≡⍙¨0⍺⍵ será executada e seu valor retornado.
  • Se o guarda avaliar 0, essa expressão será ignorada e a expressão seguinte 2 4=...=⍙⍺)será executada.

⍵≡2⌽⍵ verifica se os dois pares de ângulos opostos são iguais.

  • 2⌽⍵ gira a matriz de ângulos em 2 lugares.
  • ⍵≡verifica se é o mesmo que ele

≡⍙¨0⍺⍵ retorna um valor exclusivo para cada forma do tipo paralelogramo.

  • 0⍺⍵é a matriz de 3 elementos do escalar 0, a matriz de comprimentos laterais e a matriz de ângulos .
  • ≡⍙¨ executa ≡⍙ para cada um desses elementos.
  • ≡⍙verifica se todos os valores de uma matriz são iguais, verificando se girá-la 1 fornece a mesma matriz. Os escalares não giram, então ≡⍙0retornos 1. Como observado acima, ≡⍙⍺verifica um losango e ≡⍙⍵um retângulo.

2 4=+/1=2|+⍙↑⍵(=⍙⍺)retorna um valor exclusivo para cada forma do tipo não paralelogramo. Isso é obtido entrelaçando as verificações de pipa e trapézio.


2=+/1=2|+⍙⍵ verifica se há um trapézio.

  • +⍙⍵fornece as somas de ângulo adjacentes. Os ângulos internos das linhas paralelas somam um ângulo reto, assim como os ângulos externos dos lados paralelos de um quadrilátero. Portanto, cada par de lados paralelos deve levar a duas 1ou -1nas somas de ângulo adjacentes.

  • 1=2|No entanto, os ângulos em são 1 a mais do que deveriam, então os ângulos realmente somam a 1ou 3. Isso pode ser verificado por "mod 2 é igual a 1".

  • +/soma a matriz. Isso fornece uma contagem de somas de ângulo adjacentes que é 1ou 3.

  • 2= verifique se é igual a 2. (ou seja, se houver exatamente um par de lados paralelos)


4=+/1=2|+⍙(=⍙⍺) verifica se há uma pipa.

  • (=⍙⍺)fornece uma matriz indicando quais lados adjacentes são iguais. Ao contrário , =trabalhe em elementos. Portanto, essa é uma matriz de 4 elementos com 1s, em que o comprimento desse lado é igual ao do lado "próximo".

  • +⍙ Soma pareada com enrole.

  • 1=2|Uma vez que (=⍙⍺)proporciona uma matriz booleano (uma com apenas 0s e 1s), as únicas possíveis valores de soma de pares são 0, 1e 2. Então 1=2|é o mesmo que apenas 1=.

  • +/soma a matriz. Isso fornece uma contagem de somas aos pares, o que é 1.

  • 4=verifique se isso é igual a 4. A única maneira de isso acontecer é se (=⍙⍺)é 1 0 1 0ou 0 1 0 1. Como observado acima, isso significa que a forma é uma pipa.


2 4=+/1=2|+⍙↑⍵(=⍙⍺) entrelaça as verificações acima.

  • ⍵(=⍙⍺)é a matriz aninhada de 2 elementos da matriz e a matriz(=⍙⍺)

  • promove a matriz aninhada para uma matriz adequada. Como ⍵(=⍙⍺)é uma matriz de 2 elementos de matrizes de 4 elementos, o resultado é uma matriz 2 × 4.

  • +⍙Como (e, por extensão ) , gira o último eixo (horizontal), +⍙para uma matriz é o mesmo que aplicar +⍙a cada linha individualmente.

  • 1=2|resíduo / mod ( |) e equals ( =) funcionam em uma base por elemento, mesmo para matrizes.

  • +/Por padrão, reduzir ( /) funciona ao longo do último eixo (horizontal). Então, +/soma ao longo das linhas e transforma uma matriz 2 × 4 em uma matriz simples de 2 elementos.

  • 2 4=Como =funciona por elemento, isso verifica as condições da pipa e do trapézio simultaneamente.

TwiNight
fonte
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]&

Com espaço em branco:

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
]&

Saídas 1para quadrados, 2para losangos, 3retângulos,4 paralelogramos, 5pipas, 6trapézios e 7qualquer outra coisa. Eu postaria um link TIO, mas isso aparentemente não funciona em matemática.

Se os quatro pontos estão P, Q, R, e S, em seguida, {##,#}é {P,Q,R,S,P}, por isso, sé a lista de vectores secundários {Q-P,R-Q,S-R,P-S}, lsão os comprimentos desses vectores, e ré a condição de que o ângulo entre Q-PeR-Q bem como o ângulo entre R-Qe S-Restão ambos os 90graus.

Assim, se todos os comprimentos dos lados forem iguais, o quadrilátero é um losango. E ser válido, é de fato um quadrado, caso contrário, é apenas um losango simples.

Excluindo o losango, se os dois pares de comprimentos laterais opostos são iguais, o quadrilátero ainda é paralelogramo. E ser retido, é de fato um retângulo; caso contrário, é apenas um paralelogramo simples.

Excluindo paralelogramos, a lista de comprimentos laterais ltem a forma {a,b,b,a}ou, {a,a,b,b}para algunsa eb , então, o quadrilátero é uma pipa. Observe que ele não pode ser um trapézio ou seria um losango.

Excluindo paralelogramos e pipas, se o quadrilateral tem um par de lados paralelos, então é um trapézio. Verificamos isso através Normalizedos vetores laterais e verificando se um par de vetores opostos contribui para{0,0} .

Excluindo todos os itens acima, se 1 > 0(é melhor), então o quadrilátero é apenas um quadrilátero simples e antigo.

ngenisis
fonte
1

Python 2 , 463 410 408 397 bytes

53 bytes salvos usando uma tupla na sexta linha, em vez de indexar em uma lista.

Salva 11 bytes deslocando para a saída de números inteiros 1 a 7 em vez da primeira letra de cada forma. Os números inteiros correspondem da seguinte maneira:

  1. Quadrado
  2. Retângulo
  3. Rhombus
  4. Paralelogramo
  5. Trapézio
  6. Pipa
  7. Quadrilá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

Experimente online!

Ungolfed para mostrar a lógica

Mostrado como uma função, para mostrar a saída para as diferentes entradas de teste. note que eu mudei o exemplo de teste "Retângulo" do originalmente fornecido na pergunta, que não era um retângulo.

A lógica baseia-se em produtos de ponto e na norma (comprimento) dos vetores formados pelos lados do quadrilátero para avaliar se os lados são iguais em comprimento, paralelos em lados opostos ou perpendiculares aos lados adjacentes.

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

Experimente online!

CCB60
fonte
1
Classificado incorretamente [(0, 0), (2, 2), (4, 0), (0,-2)]como pipa
TwiNight
Isso funcionaria? repl.it/JRzE
Zachary
@TwiNight Thanks. Não via essa possibilidade. O problema é que meu algoritmo inicial apenas verifica se há UM par de lados de comprimento correspondente. Como o exemplo mostra, isso não é suficiente. Eu precisaria verificar se há um par de lados correspondentes e depois se o par oposto também tem comprimento semelhante. Estive muito ocupado para implementar isso.
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%)

Saídas em binário: 1= Papagaio, 10= Quadrilátero, 11= Trapézio, 100= Paralelogramo, 101= Losango, 110= Retângulo, 111= Quadrado. Explicação: g, h, i, jsão os quadrados dos comprimentos dos lados. pé o número de pares de lados opostos com o mesmo comprimento, qdistingue entre paralelogramos / retângulos e rhobmi / quadrados, verificando se os pares opostos são de fato iguais, rdistingue paralelogramos / losango e retângulos / quadrados por meio de uma verificação de perpendicularidade, kverifica pipa, procurando pares de lados adjacentes iguais e tverifica se há um trapézio através de duas verificações laterais paralelas.

Neil
fonte
Veja este comentário
TwiNight 27/17/17
@TwiNight Bah, procurar uma pipa é realmente estranho.
Neil
Sim, eu tive a sorte de encontrar uma maneira compacta para fazê-lo
TwiNight
@TwiNight, vou acreditar na sua palavra; APL é completamente ilegível para mim.
Neil
A parte em que eu procuro pipa é 2=|-.=⍙⍺. Certamente parece compacto se você ignorar a colocar o trabalho em cálculo (os 4 comprimentos laterais) e uma linha inteira para definir
TwiNight