四辺形を分類する| 数学の試験で私を助けてください!


20

助けて!私の数学の試験はすぐに来て、私は勉強しませんでした!1試験の一部は、頂点座標を指定して四角形を分類することです。残念ながら、その方法はわかりません。2

だから、あなたの挑戦は私のためにこれを行うプログラムを書くことです。そうすれば私は失敗しません!

チャレンジ

3つの頂点が同一直線上にない4つの頂点が与えられた場合、それらの4つの頂点によって形成される四辺形の最も具体的な分類を決定します。

「最も具体的な分類」とは、すべての正方形が長方形であっても、形状が正方形である場合、長方形であることを示すのではなく、正方形であることを示す必要があるということです。

入力

入力は4つの(x、y)座標として与えられます。これらは、長さ2のリスト/タプルの長さ4のリストとして取得できます。また、入力をx座標のリストおよびそれぞれのy座標のリストとして取得することもできます。

私の形状がポイントで頂点を持っている場合たとえば、(0, 0)(5, 0)(6, 1)、そして(1, 1)、あなたは以下の形式または類似のもののいずれかの入力を取ることを選択することがあります。

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

四辺形は自己交差しておらず、ポイントは正しい順序で与えられていると想定できます(つまり、入力内の連続する2つのポイントは、四辺形の線分で接続されます)。

出力

次の四辺形のクラスごとに一意の出力が必要になります。

  • 平方
  • 矩形
  • ひし形
  • 平行四辺形
  • 台形/台形
  • カイト
  • 四辺形

これは、正確な名前そのもの、文字、整数などです。

ルール

  • 標準的な抜け穴が適用されます
  • プログラミング言語にこの正確なタスクを実行するビルトインがある場合、そのビルトインは許可されません。
  • 2点間の距離を見つけるためのビルトインが許可されています。
  • 2本の線の間の角度を見つけるためのビルトインが許可されています。

この時点で、すべての用語を知っていれば、プログラミングを開始できます。(テストケースは最後にあります)

用語

このセクションは、さまざまな形状の定義を明確にする必要がある人を対象としています。

平方

四辺形は、その4辺すべての長さが等しく、隣接する辺のすべてのペアが垂直である(つまり、長方形と菱形の両方である)場合にのみ、正方形です。

矩形

四辺形は、隣接する辺のすべてのペアが垂直である場合にのみ、長方形です。

ひし形

四辺形は、その4つの辺すべてが等しい場合にのみ菱形になります。

平行四辺形

四辺形は、対向する辺の各ペアが平行で、対向する角度の各ペアが等しい場合にのみ平行四辺形です。これらの条件は両方とも相互に関係しているため、どちらか一方のみをチェックする必要があります。

台形/台形

四辺形は、少なくとも1組の平行な辺がある場合にのみ、台形/台形です。

カイト

四辺形は、隣接する2つの対の長さが等しい場合、カイトです。つまり、隣接する2つの側面は等しく、他の2つの側面も等しくなります。

テストケース

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

リンク(Desmos Graphing Calculator)

以下に、各テストケースの視覚化へのリンクを示します。

正方形の
長方形の
菱形の
平行四辺形の
台形/台形の
iteの
四辺形

受賞基準

私は明らかに試験にコンピュータを持ち込むことはできませんので、覚えられるようにできるだけ短いコードを書く必要があります。プログラムをできるだけ小さくする必要があるマージンに収まるように、マージンに書き込み、TryItOffline TMを使用して実行する必要があります!

1もちろん私は実際にやった:P
2もちろん私は実際にやった:P


1
マージンの問題xkcd.com/1381
Rohan Jhunjhunwala

@RohanJhunjhunwala私は新しいフェルマーです(私はそれが正しい人だと思いますか?)。しかし、素敵なXKCD ref:P
HyperNeutrino

CSVは入力を許可されていますか?
tuskiomi

特異性の半順序とは何ですか?
ピーターテイラー

回答:


6

APL(Dyalog)104 89 80 82 81 79 78バイト

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

オンラインでお試しください!


入出力

入力として4×2の座標行列を取ります

出力

  • 1 1 1 スクエア用
  • 1 1 0 ひし形用
  • 1 0 1 長方形用
  • 1 0 0 平行四辺形
  • 1 0 カイト用
  • 0 1 トラペジウム用
  • 0 0 四辺形用

アルゴリズム

最初に、四辺形の4つの辺の長さと角度をすべて見つけます

反対の角度のペアが両方とも等しい場合(OA)、形状はある種の平行四辺形になります。すべての辺の長さが等しいか(AS、隣接する辺)、すべての角度が等しいか(AA)を決定します。

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

そうでない場合OA

  • 等しい隣接する辺のペアが正確に2組あるかどうか、およびそれらが(aabbではなくaaab)分離されているかどうかを判別します。その場合、形状はkitです。

  • 正確に1対の平行な反対側があるかどうかを判断します。その場合、形状は台形です。

  • それ以外の場合、形状は四角形です。


コード

⍙←{⍵⍺⍺1⌽⍵}新しい演算子を定義します。APLでは、演算子は高階関数を意味します。この演算子は1つの関数引数(⍺⍺)を取り、次の単項関数を返します。

  1. 1⌽引数を回転(
  2. ⍺⍺それの間に適用し、

これは、スカラー関数のほとんどが配列引数間で暗黙的にマップされ、ラップアラウンドで隣接する要素のペア間でそれらを適用できるため、特に便利です。たとえば、+⍙1 2 3 41 2 3 4 + 2 3 4 1に評価され3 5 7 5ます。


x←-⍙⎕+.×1 0J1 入力座標行列を、形状の4辺のベクトルを表す複素数の配列に変換します。

  • 、参照されると、入力を受け取って返します

  • 1 0J1ベクトル[1、i](数学的な意味での「ベクトル」、-1の平方根としての「i」)を表します。APLでは、複素数a+biが書かれていますaJb

  • +.×行列の乗算。数学的には、結果は4×1マトリックスになります。ただし、+.×APLでは「内積」と呼ばれ、行列乗算とベクトル内積を一般化し、3次元配列を2次元配列と「乗算」するような処理も可能にします。この場合、4×2行列と2要素ベクトルを乗算し、4要素ベクトル(4つの与えられた頂点の複素数表現)を生成します。

  • -⍙上記のラップアラウンドを使用したペアワイズ減算です。これにより、形状の4辺のベクトルが(複素数として)与えられます。これらのベクトルは「逆」方向を指しますが、それは問題ではありません。

  • x← それを変数に保存します x


2|1+-⍙(12○x)÷○1 形状の4つの頂点で外角(の表現)を見つけます。

  • 12○x4つのサイドベクトルのそれぞれの主引数(ラジアン単位)を見つけます。

  • ÷○1πで除算するので、角度が扱いやすくなります。したがって、すべての角度は直線角度の倍数として表されます。

  • -⍙上記のラップアラウンドによるペアワイズ減算。これにより、4つの外部角度が与えられます。

  • 2|1+ 主引数は上限(-1,1]で、ペアワイズ減算は範囲(-2,2)になります。同じ角度には2つの異なる表現があるため、これは良くありません。 (0,2]で上限が設定されています。すべての角度は本来の角度より1大きくなっていますが、これを念頭に置いておくと問題ありません。


|x4つのサイドベクトルのそれぞれの大きさを見つける


{⍵≡2⌽⍵:≡⍙¨0⍺⍵⋄2 4=+/1=2|+⍙↑⍵(=⍙⍺)}は、4つの外角の配列を右引数として、4つの辺の長さの配列を右引数として関数を定義および適用します

  • 関数には保護された式があります。この場合、⍵≡2⌽⍵ガードです。
  • ガードが評価される1と、次の式≡⍙¨0⍺⍵が実行され、その値が返されます。
  • ガードの評価がの場合0、その式はスキップ2 4=...=⍙⍺)され、代わりにその式が実行されます。

⍵≡2⌽⍵ 反対の角度の両方のペアが等しいかどうかをチェックします。

  • 2⌽⍵ 角度配列を2箇所回転します。
  • ⍵≡それがそれ自体と同じかどうかをチェックします

≡⍙¨0⍺⍵ 各平行四辺形の形状に固有の値を返します。

  • 0⍺⍵は、スカラー0、辺の長さの配列、角度の配列の3要素配列です
  • ≡⍙¨≡⍙これらの各要素に対して実行されます。
  • ≡⍙配列のすべての値が等しいかどうかを、1回転すると同じ配列になるかどうかをチェックします。スカラーは回転しないため、を≡⍙0返します1。上記のように、≡⍙⍺菱形を≡⍙⍵チェックし、長方形をチェックします。

2 4=+/1=2|+⍙↑⍵(=⍙⍺)各非平行四辺形タイプの形状に対して一意の値を返します。これは、カイトと台形のチェックを組み合わせることで達成されます。


2=+/1=2|+⍙⍵ 台形をチェックします。

  • +⍙⍵隣接する角度の合計を示します。平行線の内角は合計して直線角になり、したがって、四辺形の平行辺の外角も直線になります。そのため、平行な辺の各ペアは、2つ1または-1隣接する角度の合計になるはずです。

  • 1=2|ただし、の角度は本来あるべき角度より1大きいため、実際の角度は1またはになり3ます。これは「mod 2 equals 1」で確認できます。

  • +/配列を合計します。これにより、1またはである隣接する角度の合計がカウントされます3

  • 2= それが2に等しいかどうかを確認します(つまり、平行な側面のペアがちょうど1つある場合)


4=+/1=2|+⍙(=⍙⍺) カイトをチェックします。

  • (=⍙⍺)どの隣接辺が等しいかを示す配列を提供します。とは異なり=要素ごとに動作します。したがって、これは、1その辺の長さが「次の」辺の長さと等しいsを持つ4要素配列です。

  • +⍙ ラップアラウンドのペアワイズ合計。

  • 1=2|(=⍙⍺)ブール配列(0sと1s のみを持つもの)を提供するため、ペアワイズ和の唯一の可能な値は012です。だから1=2|ちょうどと同じ1=です。

  • +/配列を合計します。これにより、ペアワイズ合計のカウントが得られ1ます。

  • 4=それがどうなる唯一の方法はある4.等しいかどうかをチェック(=⍙⍺)です1 0 1 00 1 0 1。上記のように、これは形状がkitであることを意味します。


2 4=+/1=2|+⍙↑⍵(=⍙⍺) 上記のチェックを組み合わせます。

  • ⍵(=⍙⍺)配列と配列の2要素のネストされた配列(=⍙⍺)

  • ネストされた配列を適​​切なマトリックスにプロモートします。以来、⍵(=⍙⍺)4素子アレイの2素子アレイであり、結果は2×4の行列です。

  • +⍙以来(拡張により、および)最後の(水平)軸を回転させ、+⍙マトリックスに適用することと同じである+⍙個々の行に。

  • 1=2|剰余/ mod(|)とequals(=)は両方とも、マトリックスに対しても要素ごとに機能します。

  • +/デフォルトでは、reduce(/)は最後の(水平)軸に沿って機能します。したがって+/、行に沿って合計し、2×4行列を2要素の単純な配列に変換します。

  • 2 4==要素ごとに機能するため、これはカイトと台形の状態を同時にチェックします。


3

Mathematica、195バイト

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

空白あり:

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

出力1正方形のため、2菱形のため、3長方形のために、4平行四辺形のため、5凧のために、6台形のため、そして7何かのために。TIOリンクを投稿しますが、これはMathicsでは機能しないようです。

フォーポイントである場合PQR、及びS、その後{##,#}れる{P,Q,R,S,P}ので、sサイドベクトルのリストであり{Q-P,R-Q,S-R,P-S}lこれらのベクトルの長さであり、そしてr間の角度という条件であるQ-PR-Q同様との間の角度R-QS-Rの両方である90度。

したがって、すべての辺の長さが等しい場合、四辺形は菱形になります。r保持する場合、実際には正方形であり、そうでない場合は単なる菱形です。

反対側の長さの両方のペアが等しい場合、菱形を除外すると、四辺形はまだ平行四辺形です。r保持する場合、それは実際には長方形であり、そうでない場合、単なる平行四辺形です。

平行四辺形を除外すると、辺の長さのリストはlの形式{a,b,b,a}または{a,a,b,b}一部のでaありb、四辺形はkitです。さらに台形にすることはできないか、実際には菱形になることに注意してください。

四辺形に一対の平行な側面がある場合、平行四辺形とkitを除外すると、台形になります。これを確認Normalizeするには、サイドベクトルを入力し、反対のベクトルのペアがに追加されるかどうかを確認し{0,0}ます。

上記のすべてを除外する場合、1 > 0(もしそうであれば)四辺形は単なる古い四辺形です。


1

パイソン2463の 410 408 397バイト

リストにインデックスを付ける代わりに、6行目のタプルを使用して53バイトを節約しました。

各形状の最初の文字の代わりに出力整数1〜7にシフトすることで11バイトを節約しました。整数は次のように対応します。

  1. 平方
  2. 矩形
  3. ひし形
  4. 平行四辺形
  5. 台形
  6. カイト
  7. 四辺形
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

オンラインでお試しください!

ロジックを表示するためにゴルフをしていません

関数として表示され、異なるテスト入力の出力を表示します。注: "Rectangle"テストの例は、元々質問で提供されていたもので、長方形ではありませんでした。

このロジックは、四辺形の辺によって形成されるベクトルのノルム(長さ)とドット積に基づいて、辺の長さが等しいか、反対側が平行か、隣接する辺が垂直かを評価します。

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

オンラインでお試しください!


1
[(0, 0), (2, 2), (4, 0), (0,-2)]カイトとして誤分類
ツイナイト

これは機能しますか?repl.it/JRzE
ザカリー

@TwiNightありがとう。この可能性を見ませんでした。問題は、最初のアルゴリズムでは、一致する長さの辺が1組あるかどうかだけを確認することです。あなたの例が示すように、それは十分ではありません。一致する辺の1つのペアを確認し、反対のペアの長さも似ているかどうかを確認する必要があります。それを実装するには忙しすぎました。
-CCB60

0

バッチ、287バイト

@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%)

バイナリ出力:1=カイト、10=四辺形、11=台形、100=平行四辺形、101=菱形、110=長方形、111=正方形。説明:g, h, i, j辺の長さの二乗です。pは、同じ長さの反対側のペアの数でありq、反対のペアが実際に等しいかどうかを確認することによって平行四辺形/長方形とrhobmi / squaresをr区別しkます。隣接する等しい辺のペアを探してカイトしt、平行な2つの辺のチェックを介して台形をチェックします。



@TwiNight Bah、カイトの確認は本当に厄介です。
ニール

うん、私はそれを行うためのコンパクトな方法を見つけることができてラッキーだった
-TwiNight

@TwiNight私はあなたの言葉を受け取ります。APLは私にはまったく読めません。
ニール

カイトをチェックする部分は2=|-.=⍙⍺です。計算する作業(4辺の長さ)と定義する行全体を無視すると、確かにコンパクトに見えます
-TwiNight
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.