ชุมชนคนรักภาษาเบสิค - Visual Basic Community

 ลืมรหัสผ่าน
 ลงทะเบียน
ค้นหา
ดู: 2620|ตอบกลับ: 0

[VB.NET/C#] การคิดวิเคราะห์โจทย์เพื่อแก้ปัญหา การแสดงผลพื้นที่รูปสี่เหลี่ยมขนมเปียกปูน

[คัดลอกลิงก์]

252

กระทู้

367

โพสต์

3064

เครดิต

ผู้ดูแลระบบ

Rank: 9Rank: 9Rank: 9

เครดิต
3064


  1. __X
  2. _XXX
  3. XXXXX
  4. _XXX
  5. __X
คัดลอกไปที่คลิปบอร์ด
โจทย์ข้อนี้ต้องการให้พิมพ์ X เป็นรูปพื้นที่สี่เหลี่ยมขนมเปียกปูน (Rhombus Area) โดยการรับค่าตัวเลขชนิดจำนวนเต็มแบบเลขคี่เข้ามา แล้วทำการพิมพ์ดังภาพตัวอย่าง ...

โจทย์ลักษณะแบบนี้ หากมองดูเผินๆค่อนข้างไร้สาระ เพราะนำไปใช้งานจริงไม่ได้ แต่ทว่าสำหรับแอดมินกลับมองเห็นเป็นความคลาสสิค คลาสสิคยังไงล่ะ??? ก็เพราะว่าคนส่วนใหญ่มักตีโจทย์โดยการคิดหาคำตอบแบบเดินหน้า (Forward Algorithm) คือพิมพ์คำตอบทีละบรรทัดน่ะซิ แต่หากคิดอีกแบบคือ การคิดย้อนกลับ (Backward Algorithm) ด้วยการมองไปที่คำตอบแบบรวมเอาไว้ทั้งหมด จากนั้นแยกวิเคราะห์เพื่อหาคำตอบกลับคืนไปทีละส่วนๆ เหมือนดั่งที่แอดมินจะนำมาอธิบายเอาไว้ในบทความชิ้นนี้ครับผม และความคลาสสิคอีกอย่างคือ เรานำหลักการวิธีคิดการมองภาพรวมเพื่อไปแก้ปัญหาโจทย์กับงานจริงๆได้แน่นอนครับ ... (อย่าลืมลองคิดหาวิธีอื่นๆด้วยล่ะ) ... หรืออ่านเสริมเรื่อง
Working Backward Algorithm

ใช้ภาพประกอบจากทางด้านบน ... สิ่งแรกที่ต้องพิจารณา คือ จะรู้ได้อย่างไรว่าจำนวนตัวเลข (คี่) นั้นๆ มันอยู่ในลำดับที่เท่าไร??? และเพื่ออะไร??? ...

ลำดับที่ของเลขจำนวนเต็ม (คี่) = (ค่าอินพุท หารตัดเศษด้วย 2) + (ค่าอินพุท หารเอาเศษด้วย 2)
เช่น เลข 13 จะถูกจัดเรียงดังนี้ 1, 3, 5, 7, 9, 11, 13
ดังนั้นลำดับที่ของเลข 13 ...
= (13 \ 2) + (13 Mod 2)

= 6 + 1
= 7 --> นี่คือคำตอบ ซึ่งจะเป็นเงื่อนไขในการวนรอบ

เอ้า!!! แล้วคำตอบส่วนด้านล่างนั่นล่ะ มันหายไปไหน??? ... มันไม่ได้หายไปไหน แต่มันเป็นเงาของคำตอบที่อยู่ซีกด้านบน เพราะในเมื่อเราพิมพ์ส่วนด้านบนได้แล้ว ก็เอามันมาเป็นคำตอบในซีกด้านล่างซ่ะซิครับ จะไปคิดคำนวณหาให้เมื่อยก้นไปทำไมล่ะ จริงหรือเปล่า ... 5555+

FIRST ANALYSIS ...
  1.         Dim S As String = ""
  2.         Dim sArr(100) As String '// เก็บค่าคำตอบเงา
  3.         For i As Integer = 1 To orderNum
  4.             '// (1) คำตอบในการแสดงผล
  5.             S = S + "X"
  6.             '// เก็บค่าคำตอบเงา โดยเริ่มจาก Index = 0
  7.             sArr(i - 1) = S
  8.             '// แสดงผลคำตอบ พร้อมกับขึ้นบรรทัดใหม่
  9.             Console.Write(S & vbCrLf)
  10.             '// เพิ่ม "X" ไว้รออีก 1 ตัว เพราะค่าที่จะพิมพ์มันเป็นเลขคี่ เมื่อวนกลับไปที่ (1)
  11.             S = S + "X"
  12.         Next
คัดลอกไปที่คลิปบอร์ด
สมมุติว่าค่าอินพุทที่รับเข้ามา คือ 5 ดังนั้น 1, 3, 5 ลำดับที่ของเลข 5 หรือ orderNum = 3
- รอบที่ 1 ... ค่า S เริ่มต้นจะว่างเปล่า จากนั้นเอา S = S & "X" คือการพิมพ์ X ออกไป 1 ตัว แต่ก่อนที่มันจะวนรอบกลับขึ้นไปก็เพิ่ม X เข้าไปต่อท้ายเป็น XX

- รอบที่ 2 ... ค่า S = "XX" จากนั้น S = S & "X" เมื่อนำไปต่อท้ายกับของเดิมคือ XX ก็จะกลายเป็นพิมพ์ XXX แต่ก่อนที่มันจะวนรอบกลับขึ้นไปก็เพิ่ม X เข้าไปต่อท้ายเป็น XXXX

- รอบที่ 3 ... ค่า S = "XXXX" จากนั้น S = S & "X" เมื่อนำไปต่อท้ายกับของเดิมคือ XXXX ก็จะกลายเป็นพิมพ์ XXXXX แต่ก่อนที่มันจะวนรอบกลับขึ้นไปก็เพิ่ม X เข้าไปต่อท้ายเป็น XXXXXX ...
  1. X
  2. XXX
  3. XXXXX
คัดลอกไปที่คลิปบอร์ด
เนื่องจากค่าสูงสุดในการวนลูปคือ 3 รอบ (orderNum = 3) ก็เป็นการสิ้นสุดการพิมพ์ในชุดแรก ... จากบรรทัดคำสั่ง sArr(i - 1) = S คือการเก็บค่าที่พิมพ์ออกไปทั้ง 3 ชุดเอาไว้ ก็นำมันกลับมาพิมพ์ใหม่อีกรอบ แต่เป็นการพิมพ์คำตอบแบบเรียงกลับด้านกัน
  1.         For i = orderNum - 1 To 1 Step -1
  2.             Console.Write(sArr(i - 1) & vbCrLf)
  3.         Next
  4. XXX
  5. X
คัดลอกไปที่คลิปบอร์ด
เราจะเริ่มต้นพิมพ์แบบกลับด้านกัน โดยเริ่มจากค่า Upper Bound หรือค่าสูงสุดของ Array แล้วลดค่าลงทีละ 1 (Step -1) แต่ตัดส่วนคำตอบแรกทิ้งไป i = orderNum - 1 เพื่อไม่ต้องพิมพ์ซ้ำ

SECOND ANALYSIS ...
ส่วนแรกแม้ว่าเราจะยังไม่ได้คำตอบตามที่โจทย์ต้องการ แต่มันคือจุดเริ่มต้นของการคิด วิเคราะห์ปัญหา แบบมีลำดับขั้นตอน ...
  1. __X
  2. _XXX
  3. XXXXX
  4. _XXX
  5. __X
คัดลอกไปที่คลิปบอร์ด
ให้ดู X แถวแรกบนสุดมันอยู่ตำแหน่งที่เท่าไร??? คำตอบคือ อยู่จุดกึ่งกลางของแถวที่ 3 ที่มีค่าสูงสุด และเนื่องจากว่ามันเป็นเลขคี่ เราลองกระจายลำดับเลขเล่นๆไป เช่น 1 2 3 4 5 เราจะสังเกตเห็นว่า จุดกึ่งกลางของเลขชุดนี้คือ 3 จะมีจำนวนตัวเลขที่อยู่ทางซ้ายและทางขวาเท่ากัน ... ตามนิยามกฏการสมมาตรอะไรประมาณนี้แหละครับ 5555+

ดังนั้นหากเราอยากรู้จุดกึ่งกลางของเลข 5 ก็คือการเอา (5 มาหารตัดเศษด้วย 2) + (5 หารเอาเศษด้วย 2) ก็คือ (5 \ 2) + (5 Mod 2) = 3 ... แต่โจทย์ต้องการให้เราพิมพ์ช่องว่าง (ASCII Code = 32 ฐาน 10) นำหน้า X เราจึงคิดเฉพาะส่วนแรกคือ 5 หารตัดเศษด้วย 2 ก็พอ
  1.         For i As Integer = 1 To orderNum
  2.             '// หาค่า Space นำหน้า ด้วยการหารตัดเศษ (โดยที่ค่า N จะลดค่าลงทีละ 2 เพราะมันเป็นเลขคี่ ... อยู่ด้านล่างใกล้ Next)
  3.             For sP = 1 To (N \ 2)
  4.                 S = Chr(32) & S
  5.             Next
  6.             '// (1) เอา Space นำหน้าตามด้วยคำตอบ
  7.             S = S + "X"
  8.             '// เก็บค่าคำตอบเงา โดยเริ่มจาก Index = 0
  9.             sArr(i - 1) = S
  10.             '// แสดงผลคำตอบ พร้อมกับขึ้นบรรทัดใหม่
  11.             Console.Write(S & vbCrLf)
  12.             '// เพิ่ม "X" ไว้รออีก 1 ตัว เพราะค่าที่จะพิมพ์มันเป็นเลขคี่ เมื่อวนกลับไปที่ (1)
  13.             '// ตัดค่าช่องว่างออกไป เพราะจะวนไปรับค่า Space หรือ Chr(32) ใหม่
  14.             S = Trim(S & "X")
  15.             '// ลดค่าอินพุทลงไปทีละ 2 เพราะเป็นเลขคี่ เช่นจาก 5 ก็จะเหลือ 3 และเหลือ 1 เพื่อสิ้นสุด
  16.             N = N - 2
  17.         Next
คัดลอกไปที่คลิปบอร์ด
ดังนั้นเราเพิ่มโค้ดใส่ช่องว่างนำหน้าเข้าไปก่อนการพิมพ์ โดยจำนวนช่องว่างที่ต้องพิมพ์ sP = 1 To (N \ 2)
- รอบที่ 1 ... sP = 1 To (5 \ 2) = 2 คือพิมพ์ Chr(32) หรือช่องว่างนำหน้าไป 2 ตัว เมื่อพิมพ์เสร็จลดค่ามันลงไป 2 ก็จะเป็น N = 5 - 2 = 3

- รอบที่ 2 ... sP = 1 TO (3 \ 2) = 1 คือพิมพ์ Chr(32) หรือช่องว่างนำหน้าไป 1 ตัว เมื่อพิมพ์เสร็จลดค่ามันลงไป 2 ก็จะเป็น N = 3 - 2 = 1

- รอบที่ 3 ... sP = 1 TO (1 \ 2) = 0 คือไม่มีการพิมพ์ Chr(32) หรือช่องว่างใดๆออกมา ... และมันเป็นจังหวะเดียวกับที่ orderNum = 3 จะเป็นการวนรอบในครั้งสุดท้ายพอดี ... ก็จบบริบูรณ์

มาดูโค้ดฉบับเต็ม VB.NET ...
  1. ' / --------------------------------------------------------------------------------
  2. ' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
  3. ' / eMail : [email protected]
  4. ' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
  5. ' / Facebook: https://www.facebook.com/g2gnet (For Thailand)
  6. ' / Facebook: https://www.facebook.com/commonindy (Worldwide)
  7. ' / Purpose: How to solve problems in programming.
  8. ' / Microsoft Visual Basic .NET (2010)
  9. ' /
  10. ' / This is open source code under @CopyLeft by Thongkorn Tubtimkrob.
  11. ' / You can modify and/or distribute without to inform the developer.
  12. ' / --------------------------------------------------------------------------------
  13. Module Module1

  14.     Sub Main()
  15.         Console.Clear()
  16.         Dim orderNum As Integer
  17.         Console.Write("Enter number: ")
  18.         Dim N As Integer = Console.ReadLine()
  19.         '// หาลำดับที่ของตัวเลข ด้วยการ (จำนวนหารตัดเศษด้วย 2)+(จำนวนหารเอาเศษด้วย 2) ... จะเป็นค่าสูงสุดในการวนรอบ
  20.         orderNum = (N \ 2) + (N Mod 2)
  21.         Console.WriteLine("The order is {0}", orderNum)
  22.         Call FirstMethod(N, orderNum)
  23.         Call SecondMethod(N, orderNum)
  24.     End Sub

  25.     Sub FirstMethod(ByVal N As Integer, orderNum As Integer)
  26.         Dim S As String = ""
  27.         Dim sArr(100) As String '// เก็บค่าคำตอบเงา
  28.         For i As Integer = 1 To orderNum
  29.             '// (1) คำตอบในการแสดงผล
  30.             S = S + "X"
  31.             '// เก็บค่าคำตอบเงา โดยเริ่มจาก Index = 0
  32.             sArr(i - 1) = S
  33.             '// แสดงผลคำตอบ พร้อมกับขึ้นบรรทัดใหม่
  34.             Console.Write(S & vbCrLf)
  35.             '// เพิ่ม "X" ไว้รออีก 1 ตัว เพราะค่าที่จะพิมพ์มันเป็นเลขคี่ เมื่อวนกลับไปที่ (1)
  36.             S = S + "X"
  37.         Next
  38.         For i = orderNum - 1 To 1 Step -1
  39.             Console.Write(sArr(i - 1) & vbCrLf)
  40.         Next
  41.         Console.ReadLine()
  42.     End Sub

  43.     Sub SecondMethod(ByVal N As Integer, orderNum As Integer)
  44.         Dim S As String = ""
  45.         Dim sP As Integer = orderNum - 1
  46.         Dim sArr(100) As String
  47.         For i As Integer = 1 To orderNum
  48.             '// หาค่า Space นำหน้า ด้วยการหารตัดเศษ (โดยที่ค่า N จะลดค่าลงทีละ 2 เพราะมันเป็นเลขคี่ ... อยู่ด้านล่างใกล้ Next)
  49.             For sP = 1 To (N \ 2)
  50.                 S = Chr(32) & S
  51.             Next
  52.             '// (1) เอา Space นำหน้าตามด้วยคำตอบ
  53.             S = S + "X"
  54.             '// เก็บค่าคำตอบเงา โดยเริ่มจาก Index = 0
  55.             sArr(i - 1) = S
  56.             '// แสดงผลคำตอบ พร้อมกับขึ้นบรรทัดใหม่
  57.             Console.Write(S & vbCrLf)
  58.             '// เพิ่ม "X" ไว้รออีก 1 ตัว เพราะค่าที่จะพิมพ์มันเป็นเลขคี่ เมื่อวนกลับไปที่ (1)
  59.             '// ตัดค่าช่องว่างออกไป เพราะจะวนไปรับค่า Space หรือ Chr(32) ใหม่
  60.             S = Trim(S & "X")
  61.             '// ลดค่าอินพุทลงไปทีละ 2 เพราะเป็นเลขคี่ เช่นจาก 5 ก็จะเหลือ 3 และเหลือ 1 เพื่อสิ้นสุด
  62.             N = N - 2
  63.         Next
  64.         '// แสดงผลส่วนเงา
  65.         For i = orderNum - 1 To 1 Step -1
  66.             Console.Write(sArr(i - 1) + vbCrLf)
  67.         Next
  68.         Console.ReadLine()
  69.     End Sub
คัดลอกไปที่คลิปบอร์ด

มาดูโค้ดฉบับเต็ม C# ...
ขอให้สังเกตการวนรอบเพื่อพิมพ์ช่องว่าง คราวนี้แอดมินเปลี่ยนใหม่เป็น การใช้ค่าลำดับตัวเลขของอินพุทเป็นเงื่อนไขแทน หากเราพิจารณาจากรูปประกอบทางด้านบนจะเห็นได้ว่า จำนวนช่องว่างจะเริ่มต้นจากค่าลำดับตัวเลข - 1 จากนั้น มันก็จะถูกลดค่าลงหนึ่งเสมอทุกๆครั้งที่วนรอบกลับมา ... อั้ยย่ะ!!!
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;

  5. namespace BasicThinkingCSharp
  6. {
  7.     class Program
  8.     {
  9.         static void Main(string[] args)
  10.         {
  11.             int orderNum = 0;
  12.             Console.Write("Enter number: ");
  13.             string n = Console.ReadLine();
  14.             orderNum = (Int32.Parse(n) / 2) + (Int32.Parse(n) % 2);
  15.             Console.WriteLine("The order is {0}", orderNum);
  16.             firstmethod(Int32.Parse(n), orderNum);
  17. }

  18.         static void firstmethod(int m, int order) {
  19.             string s = "";
  20.             int sp = order-1;
  21.             string[] sArr = new string[100];
  22.             for (int i = 1; i <= order; i++) {
  23.                 for (int j = 1; j <= sp; j++) s = " " + s;
  24.                 s = s + "X";
  25.                 sArr[i] = s;
  26.                 Console.Write(s + "\n");
  27.                 s = s.Replace(" ", "");
  28.                 s = s + "X";
  29.                 sp--;
  30.             }
  31.             for (int i = order-1; i >= 0; i--) Console.Write(sArr[i] + "\n");
  32.             Console.ReadLine();
  33.         }

  34. }
  35. }
คัดลอกไปที่คลิปบอร์ด


วิธีคิดหาคำตอบแบบเดินหน้า (VB.NET)
ก็คือการพิมพ์แบบทีละบรรทัด โดยเริ่มจากบรรทัดแรกบนสุด ซึ่งจะมีช่องว่างเริ่มต้นจาก (ลำดับที่ตัวเลข - 1) ... แอดมินคิดว่าในเรื่องนี้คงไม่ต้องอธิบายมากมาย เพราะเชื่อว่าหลายๆคนคงต้องคิดแบบลักษณะนี้กันอยู่แล้วแหละข่ะรับกระผม
  1.     Sub ThirdMethod(ByVal N As Integer, orderNum As Integer)
  2.         Dim S As String = ""
  3.         Dim sP As Integer = orderNum - 1
  4.         Dim L As Integer = 1
  5.         For i As Integer = 1 To orderNum
  6.             For k As Integer = 1 To sP
  7.                 '// จำนวนช่องว่าง
  8.                 S = S & " "
  9.             Next
  10.             For j As Integer = 1 To L
  11.                 S = S & "X"
  12.             Next
  13.             Console.WriteLine(S)
  14.             L += 2 : sP -= 1 : S = ""
  15.         Next
  16.         '// ทำกลับด้าน
  17.         sP = 1
  18.         L = N - 2
  19.         For i As Integer = orderNum - 1 To 1 Step -1
  20.             For k As Integer = 1 To sP
  21.                 '// จำนวนช่องว่าง
  22.                 S = S & " "
  23.             Next
  24.             For j As Integer = 1 To L
  25.                 S = S & "X"
  26.             Next
  27.             Console.WriteLine(S)
  28.             L -= 2 : sP += 1 : S = ""
  29.         Next
  30.         Console.ReadLine()
  31.     End Sub
คัดลอกไปที่คลิปบอร์ด

วิธีคิดหาคำตอบแบบเดินหน้า (C#)
  1.         // การคิดแบบเดินหน้าหาคำตอบ (Forward Algorithm)
  2.         static void secondmethod(int m, int order) {
  3.             string s = "";
  4.             int sp = order - 1;
  5.             int x = 1;
  6.             for (int i = 1; i <= order; i++) {
  7.                 for (int j = 1; j <= sp; j++)  s = s + " ";
  8.                 for (int k = 1; k <= x; k++)  s = s + "X";
  9.                 Console.WriteLine(s);
  10.                 x += 2; sp -= 1; s = "";
  11.             }
  12.             sp = 1;
  13.             x = m - 2;
  14.             for (int i = order-1; i >= 1; i--) {
  15.                 for (int j = 1; j <= sp; j++) s = s + " ";
  16.                 for (int k = 1; k <= x; k++) s = s + "X";
  17.                 Console.WriteLine(s);
  18.                 x -= 2; sp += 1; s = "";
  19.             }
  20.             Console.ReadLine();
  21.         }
คัดลอกไปที่คลิปบอร์ด
Conclusion: จะเห็นได้เลยว่าการแก้ปัญหาโจทย์ข้อนี้ไม่ได้ใช้กฏสมการ หรือการคำนวณอะไรที่ซับซ้อนใดๆเลย ใช้เพียงแต่คำว่า "พื้นฐาน" เท่านั้นเอง ... สวัสดี
สิ่งที่ดีกว่าการให้ คือการให้แบบไม่มีที่สิ้นสุด
ขออภัย! คุณไม่ได้รับสิทธิ์ในการดำเนินการในส่วนนี้ กรุณาเลือกอย่างใดอย่างหนึ่ง ลงชื่อเข้าใช้ | ลงทะเบียน

รายละเอียดเครดิต

ข้อความล้วน|อุปกรณ์พกพา|ประวัติการแบน|G2GNet.com  

GMT+7, 2020-9-19 15:51 , Processed in 0.230993 second(s), 4 queries , File On.

Powered by Discuz! X3.3 R20170401, Rev.54

© 2001-2017 Comsenz Inc.

ตอบกระทู้ ขึ้นไปด้านบน ไปที่หน้ารายการกระทู้