Fly Swatter ข้อนี้สนุกมาก สมมติว่าเราเป็นนักเทนนิส ซึ่งจะใช้ไม้เทนนิสของเราตบแมลงวัน โจทย์จะให้ขนาดของแมลงวัน (f) ขนาดของไม้ (R) ความหนาของไม้ (t) ความหนาของเส้นเอ็น (r) และความห่างของเส้นเอ็น (g) ![]() โจทย์ให้หาว่า โอกาสที่ไม้เทนนิสจะตบโดนแมลงวันเป็นเท่าไหร่? อ่านต่อ ที่นี่ โจทย์ข้อนี้ ใครมานั่งหาสูตรคำนวนพื้นที่ก็อ้วกครับ มานั่งคำนวนเส้นตัดวงกลมทีละช่อง โหดแท้ เนื่องจากโจทย์ไม่ได้ให้คำนวนละเอียดมาก ทศนิยมหกหลัก เราสามารถใช้วิธี divide and conquer ได้ หลักการคือ แบ่งไม้เป็นสี่ส่วน แล้วก็พิจารณาดูว่าในส่วนนึง มีทั้งเส้นเอ็นและขอบเทนนิสหรือเปล่า ถ้ามี เราก็แบ่งเป็นสี่ส่วนอีก แบ่งเฉพาะช่องที่มีขอบเทนนิสไปเรื่อยๆ จนทศนิยมไม่เกินหกหลักเราก็หยุด เริ่มเลยละกัน let solve f R t r g = วิธีที่จะทำให้คิดง่ายขึ้นคือ เอาขนาดของแมลงวันมาขยายขนาดไม้ แล้วแมลงวันจะเหลือแค่จุดเดียว Rin คือขนาดไม้ด้านใน (หักขนาดของแมลงวันแล้ว) start สมมติว่า 0 คือกลางไม้ start คือจุดซ้ายล่างของเส้นเอ็นกลางไม้ r คือ ขนาดของเส้นเอ็น (รวมขนาดของแมลงวันแล้ว) g คือ ช่องว่างระหว่างเส้นเอ็น (หักขนาดของแมลงวันแล้ว) rg คือ ความห่างระหว่างจุดศูนย์กลางของเส้นเอ็น let calculateGap p len = อันนี้คือสูตรหาความยาวของช่องว่าง p คือจุดเริ่มต้น len คือความยาวของเส้น concept ในการหาจะมี head, body, tail head คือ gap ระหว่างขอบจุดเริ่มต้น ไปแต่ขอบเอ็นเส้นแรก body คือ ขนาดของ gap ระหว่างเส้นเอ็น ภายในเส้นตรง tail คือ gap ระหว่างขอบเอ็นเส้นสุดท้าย กับจุดสิ้นสุดของเส้นตรง let touchString (x1,y1) (x2,y2) = function นี้ใช้คู่กับ function calculateGap คือหาพื้นที่ของ gap หารด้วยพื้นที่ของสี่เหลี่ยม ผลลัพธ์คือ โอกาสที่แมลงวันจะหลุดไปใน gap let rinMixRate = (r / rg) * 0.5 + 0.5 ถัดมาคือการคำนวน ที่รวมขอบไม้ rinMixRate คือ โอกาสคร่าวๆ ที่แมลงวันจะรอดระหว่างขอบไม้กับเส้นเอ็นได้ p1 p2 คือจุดของสี่เหลี่ยม โดย p1 คือจุดซ้ายล่าง p2 คือ ขวาบน a กับ b คือ ระยะระหว่าง จุดศูนย์กลางถึง p1 และ p2 operator (<->) คือการหาระยะ อ่านของเก่าดูครับ function นี้ return โอกาสที่ตีโดนแมลงวัน โอกาสที่อยู่ในไม้ และ สามารถแบ่งออกได้อีกหรือไม่ logic คือ ถ้าทั้ง p1 และ p2 อยู่นอกขอบไม้ โอกาสตีโดนคือ 0 โอกาสอยู่ในไม้คือ 0 และไม่ต้องแบ่งอีกแล้ว ถ้า p2 อยู่นอกไม้ แต่ p1 อยู่ในไม้ โอกาสตีโดนคือ 1 โอกาสอยู่ในไม้คือ 0.5 และสามารถแบ่งเพื่อคำนวนให้ละเอียดขึ้นได้ ถ้าใน p1 และ p2 อยู่ระหว่างขอบไม้ด้านในกับด้านนอก ก็คือตีโดนแน่นอน แต่ถ้า p2 อยู่ระหว่างขอบไม้ แต่ p1 อยู่ในวงกลม โอกาสคือ rinMixRate แต่สามารถแบ่งเพื่อคำนวนละเอียดขึ้นได้ สุดท้ายถ้า p1 และ p2 อยู่ในวงกลม ก็ใช้สูตรคำนวน touchString let epsilon = 0.00000025 * R function สุดท้ายละ epsilon คือ ขนาดที่เล็กที่สุดที่เราจะไม่คำนวนต่อ divide คือ แบ่งสี่เหลี่ยมเป็นพื้นที่สี่ส่วนย่อย แล้วก็ conquer ส่วน conquer คือ คำนวนหา hitRate ถ้าสามารถคำนวนละเอียดขึ้นได้ ก็ divide ไปเรื่อยๆ ด้านบนมีใช้ keyword "and" ใน f# คือ mutually recursive function ครับ แล้วก็ print ผลลัพธ์ let pop,_ = if g <= 0.0 จบ |