ข้อต่อมา
TriangleTrilema ข้อนี้จะให้จุดมา 3 จุด แล้วให้เราบอกว่านี่เป็นสามเหลี่ยมประเภทไหน
โดยต้องบอกว่าเป็นสามเหลี่ยมด้านเท่า (Equilateral) สามเหลี่ยมหน้าจั่ว (Isosceles) หรือสามเหลี่ยมด้านไม่เท่า (Scalene)
และต้องบอกอีกว่า เป็นสามเหลี่ยมมุมป้าน (Obtuse) มุมฉาก (Right) หรือมุมแหลม (Acute)
และบางครั้งถ้าเป็นเส้นตรง หรือเป็นจุดเดียวก็ถือว่าไม่ใช่สามเหลี่ยม
อ่านเพิ่ม
ที่นี่ เริ่มจากการหา ประเภทด้านของสามเหลี่ยม อันนี้เราอาจจะแค่วัดความยาวของแต่ละด้าน
แต่ตรงนี้มีกับดักนิดนึง ถ้าวัดความยาวตัวเลขอาจเป็น float เวลาเปรียบเทียบค่าอาจจะคลาดเคลื่อน
ดังนั้นแทนที่เราจะวัดความยาว เรามาหาพื้นที่สี่เหลี่ยมจตุรัสของแต่ละด้าน
สูตรการหาพื้นที่คือ
let area (x1, y1) (x2, y2) =
let deltaX = x1 - x2
let deltaY = y1 - y2
(deltaX * deltaX) + (deltaY * deltaY)
ถัดมา มาหาประเภทด้านของสามเหลี่ยม
let typeSide areas =
let count = areas |> Seq.distinct
|> Seq.length
match count with
| 1 -> "equilateral"
| 2 -> "isosceles"
| 3 -> "scalene"
เราก็วัดขนาดพื้นที่ ถ้าเท่ากันหมด ก็ equilateral
ถ้าเท่ากัน 2 ด้านก็ isosceles
ถ้าไม่เท่ากันเลยก็ scalene
คราวนี้เรามาวัดมุม
let typeAngle areas =
let sorted = Array.sort areas
match compare (sorted.[0] + sorted.[1]) sorted.[2] with
| -1 -> "obtuse"
| 0 -> "right"
| 1 -> "acute"
ถ้าเป็นมุมฉากก็ง่ายมาก เรารู้ว่าพื้นที่ด้าน A + B = C เสมอ (right)
จริงๆ คิดต่อก็ไม่ยาก ถ้า A + B > C แปลว่า C มีพื้นที่แคบ จึงเป็นสามเหลี่ยมมุมแหลม (acute)
ถ้า A + B < C แปลว่า C มีพื้นที่กว้าง จึงเป็นสามเหลี่ยมมุมป้าน (obtuse)
ถัดมา เรามาหาว่าถ้าสามเหลี่ยมอยู่ระนาบเดียวกันหมด ก็ไม่ใช่สามเหลี่ยม
let (|Collinear|Triangle|) ((x1, y1), (x2, y2), (x3, y3)) =
if (x1 - x2) * (y1 - y3) = (x1 - x3) * (y1 - y2)
then Collinear
else Triangle
ด้านบนเป็น feature ของ f# ชื่อว่า
Active Patterns วิธีการหาก็ใช้สูตรหาความชัน ถ้าความชันเท่ากันก็ถือว่าเป็นระนาบเดียวกัน
ที่จริงสูตรหาความชันต้องเป็นหาร (x1 - x2) / (x1 - x3) = (y1 - y2) / (y1 - y3)
แต่เพียงแค่เอามาคูณสลับ เพื่อไม่อยากให้ type เป็น float
เรามาเริ่มคำนวนกันเลย
let solve p1 p2 p3 =
match p1, p2, p3 with
| Collinear -> "not a triangle"
| Triangle -> let areas = [| area p1 p2; area p2 p3; area p3 p1 |]
sprintf "%s %s triangle" (typeSide areas) (typeAngle areas)
โดย p1 = (x1, y1), p2 = (x2, y2), p3 = (x3, y3)
เข้าสูตรต่างๆ ด้านบนก็ได้ผลลัพธ์ออกมา
จบ