เตรียมสอบ FE ข้อสอบปี 2023 เมษายน AM

2023S_FE_AM_Answer.pdf (40.4 KB)
2023S_FE_AM_Questions.pdf (528.9 KB)
2023S_FE_AM_Questions_Thai.pdf (789.7 KB)

A = 1010
B = 1011
C = 1100
D = 1101

ABCD (hex) = 1010 1011 1100 1101 (16 บิต)

ขั้นที่ 2: ขยายให้เต็ม 32 บิต (เติม 0 ข้างหน้า)

0000 0000 0000 0000 1010 1011 1100 1101

ขั้นที่ 3: ทำ Logical Right Shift 2 บิต

Logical right shift = เลื่อนบิตไปทางขวา และเติม 0 ทางซ้าย

ก่อนเลื่อน: 0000 0000 0000 0000 1010 1011 1100 1101
                                                    ↓↓ (สองบิตนี้จะหลุดออกไป)

หลังเลื่อน: 00|00 0000 0000 0000 0010 1010 1111 0011
            ↑↑ (เติม 0 สองบิตเข้ามา)

ขั้นที่ 4: แปลงกลับเป็นเลขฐานสิบหก

0000 0000 0000 0000 0010 1010 1111 0011
  0    0    0    0    2    A    F    3

สูตรลัด

การ shift ขวา 2 บิต = หารด้วย 2² = หารด้วย 4

ABCD (hex) ÷ 4 = ?

ABCD = 43981 (decimal)
43981 ÷ 4 = 10995.25 → เอาเฉพาะจำนวนเต็ม = 10995
10995 (decimal) = 2AF3 (hex)

วิเคราะห์โจทย์

  • โยนเหรียญ 4 เหรียญ พร้อมกัน
  • หาความน่าจะเป็นที่จะได้ อย่างน้อย 3 เหรียญขึ้นหัว

ขั้นตอนการแก้

ขั้นที่ 1: หาจำนวนผลลัพธ์ทั้งหมด

เมื่อโยนเหรียญ 4 เหรียญ แต่ละเหรียญมี 2 ผลลัพธ์ (หัว/ก้อย)

จำนวนผลลัพธ์ทั้งหมด = 2⁴ = 16 วิธี

ขั้นที่ 2: หาจำนวนผลลัพธ์ที่ต้องการ

“อย่างน้อย 3 เหรียญขึ้นหัว” หมายถึง:

  • 3 เหรียญขึ้นหัว, 1 เหรียญขึ้นก้อย หรือ
  • 4 เหรียญขึ้นหัวทั้งหมด

กรณีที่ 1: 3 หัว, 1 ก้อย

จำนวนวิธี = C(4,3) = 4!/[3!(4-3)!] = 4 วิธี

ได้แก่:

  • H H H T
  • H H T H
  • H T H H
  • T H H H

กรณีที่ 2: 4 หัว, 0 ก้อย

จำนวนวิธี = C(4,4) = 1 วิธี

ได้แก่:

  • H H H H

ขั้นที่ 3: คำนวณความน่าจะเป็น

จำนวนผลลัพธ์ที่ต้องการ = 4 + 1 = 5 วิธี

ความน่าจะเป็น = จำนวนผลลัพธ์ที่ต้องการ / จำนวนผลลัพธ์ทั้งหมด

= 5/16

คำตอบ: b) 5/16 :white_check_mark:

วิเคราะห์โจทย์

  • Random(n) คืนค่าจำนวนเต็มตั้งแต่ 0 ถึง n-1 (รวม n ค่า) แบบ uniform probability
  • A = Random(10) → A มีค่าได้: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 (10 ค่า)
  • B = Random(10) → B มีค่าได้: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 (10 ค่า)
  • C = A - B
  • หา P(C = 0)
## ขั้นตอนการแก้

**ขั้นที่ 1:** หาเงื่อนไขที่ทำให้ C = 0


C = 0
A - B = 0
A = B


**ขั้นที่ 2:** หาจำนวนผลลัพธ์ทั้งหมด

เนื่องจาก A และ B เป็นตัวแปรสุ่มอิสระ:

จำนวนผลลัพธ์ทั้งหมด (A, B) = 10 × 10 = **100 คู่**

**ขั้นที่ 3:** หาจำนวนกรณีที่ A = B

กรณีที่ A = B:
- (0, 0)
- (1, 1)
- (2, 2)
- (3, 3)
- (4, 4)
- (5, 5)
- (6, 6)
- (7, 7)
- (8, 8)
- (9, 9)

มีทั้งหมด **10 คู่**

**ขั้นที่ 4:** คำนวณความน่าจะเป็น

P(C = 0) = P(A = B) = จำนวนกรณีที่ A = B / จำนวนผลลัพธ์ทั้งหมด

P(C = 0) = 10/100 = 1/10


## **คำตอบ: c) 1/10** ✅

### หมายเหตุ

ในการเขียนโปรแกรม ฟังก์ชัน Random(n) มักหมายถึง:

* **Python:** `random.randrange(n)` → คืนค่า 0 ถึง n-1
* **Java:** `Random.nextInt(n)` → คืนค่า 0 ถึง n-1
* **JavaScript:** `Math.floor(Math.random() * n)` → คืนค่า 0 ถึง n-1

image

คำตอบและวิธีทำ

วิเคราะห์ BNF Grammar

<number> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<letter> ::= A | B | C | D | E | F
<letter-and-number> ::= <letter> | <number> | _
<variable-name> ::= <letter> | <variable-name><letter-and-number>


## กฎสำคัญ

จากกฎที่ 4: `<variable-name> ::= <letter> | <variable-name><letter-and-number>`

**ความหมาย:**
- **ตัวแรกต้องเป็น `<letter>` เท่านั้น** (A, B, C, D, E, หรือ F)
- ตัวถัดไปสามารถเป็น `<letter-and-number>` ได้ (A-F, 0-9, หรือ _)

## ตรวจสอบแต่ละตัวเลือก

### a) _B39 ❌
- เริ่มต้นด้วย `_` (underscore)
- `_` **ไม่ใช่** `<letter>` 
- ละเมิดกฎ: ต้องเริ่มด้วยตัวอักษร
- **ไม่ถูกต้อง**

### b) 246 ❌
- เริ่มต้นด้วย `2` (ตัวเลข)
- `2` **ไม่ใช่** `<letter>`
- ละเมิดกฎ: ต้องเริ่มด้วยตัวอักษร
- **ไม่ถูกต้อง**

### c) 3E5 ❌
- เริ่มต้นด้วย `3` (ตัวเลข)
- `3` **ไม่ใช่** `<letter>`
- ละเมิดกฎ: ต้องเริ่มด้วยตัวอักษร
- **ไม่ถูกต้อง**

### d) F5_1 ✅
- ตัวที่ 1: `F` → เป็น `<letter>` ✓
- ตัวที่ 2: `5` → เป็น `<number>` ซึ่งอยู่ใน `<letter-and-number>` ✓
- ตัวที่ 3: `_` → อยู่ใน `<letter-and-number>` ✓
- ตัวที่ 4: `1` → เป็น `<number>` ซึ่งอยู่ใน `<letter-and-number>` ✓
- **ถูกต้องทุกข้อ**

## การ Derive (พิสูจน์)

<variable-name>
→ <variable-name><letter-and-number>           [F5_]
→ <variable-name><letter-and-number><letter-and-number>   [F5]
→ <letter><letter-and-number><letter-and-number><letter-and-number>
→ F · 5 · _ · 1

คำตอบ: d) F5_1 :white_check_mark:

สรุป

Variable name ที่ถูกต้องตาม BNF นี้:

  • ✓ ต้องเริ่มด้วยตัวอักษร A-F
  • ✓ ตามด้วยตัวอักษร, ตัวเลข, หรือ _ ได้
  • ✗ ห้ามเริ่มด้วยตัวเลขหรือ underscore

image

คำตอบและวิธีทำ

วิเคราะห์โจทย์

โจทย์อธิบายวิธีการตรวจจับข้อผิดพลาดที่มีลักษณะ:

  1. ข้อมูลที่ส่งมาพร้อมกับเศษที่เหลือจากการหาร ข้อมูลด้วยพหุนาม (Generator polynomial)
  2. ผู้รับจะตรวจสอบ โดยการหารข้อมูลด้วยพหุนามชุดเดียวกัน
  3. ใช้ชุดที่เหลือมาตรวจสอบความถูกต้อง

วิเคราะห์แต่ละตัวเลือก

a) CRC (Cyclic Redundancy Check) :white_check_mark:

หลักการทำงาน:

ฝั่งส่ง:
1. เอาข้อมูล (Data) หารด้วย Generator Polynomial
2. ได้เศษเหลือ (Remainder) = CRC
3. ส่ง: Data + CRC

ฝั่งรับ:
1. เอา (Data + CRC) ที่ได้รับ หารด้วย Generator Polynomial เดียวกัน
2. ถ้าเศษเหลือ = 0 → ข้อมูลถูกต้อง
3. ถ้าเศษเหลือ ≠ 0 → มี error

ตัวอย่าง:

  • Generator Polynomial: x³ + x + 1 → 1011 (binary)
  • Data: 1101
  • คำนวณ CRC แล้วแนบท้าย
  • ตรงกับคำอธิบายในโจทย์ทุกประการ

b) Hamming code :cross_mark:

  • เป็น Error Correcting Code (แก้ไข error ได้)
  • ใช้การคำนวณ parity bits หลายตัว
  • ไม่ได้ใช้ Generator Polynomial
  • ไม่ตรงกับโจทย์

c) Horizontal parity check :cross_mark:

  • ตรวจสอบความสมดุล (parity) ในแนวนอน
  • คำนวณ XOR ของบิตในแต่ละแถว
  • ไม่ได้ใช้ Generator Polynomial
  • ไม่ตรงกับโจทย์

d) Vertical parity check :cross_mark:

  • ตรวจสอบความสมดุล (parity) ในแนวตั้ง
  • คำนวณ XOR ของบิตในแต่ละคอลัมน์
  • ไม่ได้ใช้ Generator Polynomial
  • ไม่ตรงกับโจทย์

ตัวอย่าง CRC Calculation

ให้:

  • Data = 1101
  • Generator = 1011 (x³ + x + 1)

ขั้นตอน:

        1100  ← Quotient (ไม่สนใจ)
      -------
1011 | 1101000  ← Data + 3 bits (000)
       1011
       ----
        0100
        0000
        ----
         1000
         1011
         ----
          0110  ← Remainder (CRC)

ส่งข้อมูล: 1101 + 011 = 1101011

คำตอบ: a) CRC :white_check_mark:

สรุปจุดสำคัญ

CRC คือวิธีเดียวที่:

  • ใช้ Generator Polynomial ในการคำนวณ
  • ส่งข้อมูลพร้อมเศษที่เหลือ (remainder)
  • ผู้รับตรวจสอบโดยการหารด้วย polynomial เดียวกัน
  • ใช้กันอย่างแพร่หลายใน: Ethernet, WiFi, USB, Storage devices

คำตอบและวิธีทำ

หลักการ Pre-order Traversal

Pre-order traversal มีลำดับ: Root → Left → Right

กฎ:

  1. เยี่ยมชม โหนดปัจจุบัน ก่อน
  2. ไป subtree ซ้าย ทั้งหมด
  3. ไป subtree ขวา ทั้งหมด

โครงสร้างต้นไม้

        9 (root)
       / \
      3   10
     / \    \
    1   6   14
       / \   /
      4   7 13

ขั้นตอนการเดินผ่าน

ขั้นที่ 1: เริ่มที่ Root

  • เยี่ยม 9
  • ลำดับ: 9

ขั้นที่ 2: ไป Left subtree ของ 9 (คือ 3)

  • เยี่ยม 3
  • ลำดับ: 9, 3

ขั้นที่ 3: ไป Left subtree ของ 3 (คือ 1)

  • เยี่ยม 1 ✓ (ไม่มี children)
  • ลำดับ: 9, 3, 1

ขั้นที่ 4: ไป Right subtree ของ 3 (คือ 6)

  • เยี่ยม 6
  • ลำดับ: 9, 3, 1, 6

ขั้นที่ 5: ไป Left subtree ของ 6 (คือ 4)

  • เยี่ยม 4 ✓ (ไม่มี children)
  • ลำดับ: 9, 3, 1, 6, 4

ขั้นที่ 6: ไป Right subtree ของ 6 (คือ 7)

  • เยี่ยม 7 ✓ (ไม่มี children)
  • ลำดับ: 9, 3, 1, 6, 4, 7

ขั้นที่ 7: เสร็จ Left subtree ของ 9 แล้ว, ไป Right subtree (คือ 10)

  • เยี่ยม 10
  • ลำดับ: 9, 3, 1, 6, 4, 7, 10

ขั้นที่ 8: ไป Right subtree ของ 10 (คือ 14)

  • เยี่ยม 14
  • ลำดับ: 9, 3, 1, 6, 4, 7, 10, 14

ขั้นที่ 9: ไป Left subtree ของ 14 (คือ 13)

  • เยี่ยม 13 ✓ (ไม่มี children)
  • ลำดับ: 9, 3, 1, 6, 4, 7, 10, 14, 13

ผลลัพธ์

Pre-order traversal: 9, 3, 1, 6, 4, 7, 10, 14, 13

ตรวจสอบตัวเลือก

  • a) 1, 3, 4, 6, 7, 9, 10, 13, 14 :cross_mark: (นี่คือ In-order)
  • b) 1, 4, 7, 6, 3, 13, 14, 10, 9 :cross_mark: (นี่คือ Post-order)
  • c) 9, 3, 1, 6, 4, 7, 10, 14, 13 :white_check_mark: (Pre-order)
  • d) 9, 3, 10, 1, 6, 14, 4, 7, 13 :cross_mark: (ผิดลำดับ)

คำตอบ: c) 9, 3, 1, 6, 4, 7, 10, 14, 13 :white_check_mark:


เปรียบเทียบ 3 แบบการเดินผ่าน

แบบ ลำดับ ผลลัพธ์
Pre-order Root → Left → Right 9, 3, 1, 6, 4, 7, 10, 14, 13
In-order Left → Root → Right 1, 3, 4, 6, 7, 9, 10, 13, 14
Post-order Left → Right → Root 1, 4, 7, 6, 3, 13, 14, 10, 9

คำตอบและวิธีทำ

หลักการ Queue (คิว)

Queue เป็นโครงสร้างข้อมูลแบบ FIFO (First In First Out) = เข้าก่อนออกก่อน

  • ENQ n : เพิ่มข้อมูล n เข้าไปในคิว (Enqueue)
  • DEQ : นำข้อมูลออกจากคิว (Dequeue) - เอาตัวที่เข้าก่อนออกก่อน

ติดตามการดำเนินการทีละขั้นตอน

ลำดับ: ENQ 1, ENQ 2, ENQ 3, DEQ, ENQ 4, ENQ 5, DEQ, ENQ 6, DEQ, DEQ
ขั้นตอน คำสั่ง สถานะคิว หมายเหตุ
เริ่มต้น - คิวว่าง
1 ENQ 1 [1] เพิ่ม 1
2 ENQ 2 [1, 2] เพิ่ม 2
3 ENQ 3 [1, 2, 3] เพิ่ม 3
4 DEQ [2, 3] นำ 1 ออก
5 ENQ 4 [2, 3, 4] เพิ่ม 4
6 ENQ 5 [2, 3, 4, 5] เพิ่ม 5
7 DEQ [3, 4, 5] นำ 2 ออก
8 ENQ 6 [3, 4, 5, 6] เพิ่ม 6
9 DEQ [4, 5, 6] นำ 3 ออก
10 DEQ [5, 6] นำ 4 ออก

หลังดำเนินการครบทุกคำสั่งแล้ว

คิวมีข้อมูล: [5, 6]

  • ตัวหน้าสุด (Front): 5
  • ตัวท้ายสุด (Rear): 6

โจทย์ถามว่า

“ข้อใดคือค่าที่จะถูกนำออกมา” (หากทำ DEQ อีกครั้ง)

เมื่อทำ DEQ อีกครั้ง (ครั้งที่ 5):

  • จะนำตัวที่อยู่หน้าสุดออก
  • คือ 5

ภาพประกอบ

Front → [5, 6] ← Rear
         ↑
      DEQ ครั้งต่อไป
      จะนำ 5 ออก

คำตอบ: c) 5 :white_check_mark:


สรุปหลักการ

Queue:

  • เข้าจากด้านหลัง (Rear)
  • ออกจากด้านหน้า (Front)
  • FIFO: First In First Out

ในตัวอย่างนี้:

  • ตัวเลขที่เข้าคิวลำดับสุดท้าย: 5, 6
  • ตัวเลขที่จะออกก่อน: 5 (เข้าก่อน 6)

เทคนิคหาคำตอบแบบรวดเร็ว :high_voltage:

:bullseye: เทคนิค 1: นับจำนวน ENQ และ DEQ

หลักการ: Queue คงเหลือ = จำนวน ENQ - จำนวน DEQ

ลำดับ: ENQ 1, ENQ 2, ENQ 3, DEQ, ENQ 4, ENQ 5, DEQ, ENQ 6, DEQ, DEQ

✓ นับ ENQ: 1, 2, 3, 4, 5, 6 → 6 ครั้ง
✓ นับ DEQ: (4 ครั้ง)
✓ เหลือในคิว = 6 - 4 = 2 ตัว

สรุป:

  • เหลือ 2 ตัวสุดท้าย ที่ ENQ เข้าไป = 5 และ 6
  • ตัวที่จะออกก่อน = 5 (เข้าก่อน)

:stopwatch: ประหยัดเวลา: ~70%


:bullseye: เทคนิค 2: ติดตามเฉพาะจุดสำคัญ

หลักการ: ดูเฉพาะตำแหน่ง DEQ ว่าเอาอะไรออก

ENQ 1, ENQ 2, ENQ 3, ❌DEQ → นำ 1 ออก
                      มีอยู่: [2, 3]

ENQ 4, ENQ 5, ❌DEQ → นำ 2 ออก
              มีอยู่: [3, 4, 5]

ENQ 6, ❌DEQ, ❌DEQ → นำ 3 และ 4 ออก
                      เหลือ: [5, 6]

ตัวหน้าคิว (จะออกต่อไป): 5

:stopwatch: ประหยัดเวลา: ~60%


:bullseye: เทคนิค 3: วิเคราะห์ลำดับเข้า-ออก (เร็วสุด!)

ขั้นตอน:

:one: เขียนลำดับที่เข้าทั้งหมด

เข้า: 1 → 2 → 3 → 4 → 5 → 6

:two: นับว่า DEQ กี่ครั้ง

DEQ จำนวน: 4 ครั้ง

:three: ขีดเส้นตัดตัวแรก 4 ตัว

เข้า: 1̶ → 2̶ → 3̶ → 4̶ → 5 → 6
      ↑___ออกไปแล้ว___↑   ↑__เหลืออยู่__↑

:four: ตัวที่เหลือและตัวหน้าสุด

เหลือ: [5, 6]
หน้าสุด: 5 ← จะออกในครั้งต่อไป

:stopwatch: ประหยัดเวลา: ~80%


:bullseye: เทคนิค 4: สูตรคำนวณตำแหน่ง (สำหรับโจทย์ที่ซับซ้อน)

ตำแหน่งหน้าคิว = (จำนวน DEQ) + 1
                = 4 + 1
                = 5 ← ตัวเลขลำดับที่ 5 ที่เข้าคิว

จากลำดับที่เข้า: 1, 2, 3, 4, 5, 6

คำตอบ: 5 :white_check_mark:


:bar_chart: เปรียบเทียบเทคนิค

เทคนิค เวลา ความแม่นยำ เหมาะกับ
วิธีปกติ (ติดตามทุกขั้น) 100% 100% ผู้เริ่มต้น
เทคนิค 1: นับ ENQ/DEQ 30% 95% โจทย์ทั่วไป
เทคนิค 2: ดูจุดสำคัญ 40% 90% ควบคุมความผิดพลาด
เทคนิค 3: ขีดเส้นตัด 20% 100% แนะนำสำหรับสอบ :star:
เทคนิค 4: สูตร 10% 100% เร็วสุด! :high_voltage:

:light_bulb: เคล็ดลับการใช้งาน

:white_check_mark: ใช้เทคนิค 3 หรือ 4 เมื่อ:

  • โจทย์มี ENQ/DEQ เยอะมาก
  • ต้องการความเร็ว
  • มั่นใจในการนับ

:white_check_mark: ใช้เทคนิค 1 หรือ 2 เมื่อ:

  • ต้องการความแม่นยำสูง
  • โจทย์ซับซ้อน (มีเงื่อนไขพิเศษ)
  • ต้องการเช็คคำตอบ

:warning: ข้อควรระวัง:

  • ต้องนับจำนวน ENQ และ DEQ ให้ถูก
  • อย่าลืมว่า Queue เป็น FIFO
  • ตรวจสอบว่าโจทย์ถามตัวหน้าหรือตัวท้าย

:fire: ตัวอย่างใช้เทคนิค 4 แบบรวดเร็ว

โจทย์เดิม:

ENQ 1, ENQ 2, ENQ 3, DEQ, ENQ 4, ENQ 5, DEQ, ENQ 6, DEQ, DEQ

แก้แบบไว:

1. เขียนลำดับที่เข้า: 1, 2, 3, 4, 5, 6
2. นับ DEQ: 4 ครั้ง
3. ตำแหน่งหน้าคิว = 4 + 1 = 5
4. ลำดับที่ 5 = เลข 5

คำตอบ: 5 :white_check_mark:

เวลาใช้: ~10 วินาที :high_voltage:


:graduation_cap: สรุป

เมื่อไหร่ ใช้เทคนิคไหน
สอบจริง (เวลาน้อย) เทคนิค 3 หรือ 4
ฝึกทำโจทย์ เทคนิค 1 หรือ 2
เช็คคำตอบ วิธีปกติ (ติดตามทุกขั้น)

หัวใจสำคัญ:

  • Queue = FIFO (เข้าก่อนออกก่อน)
  • นับ DEQ แล้วบวก 1 = ตำแหน่งหน้าคิว
  • ขีดเส้นตัดตัวที่ออกไปแล้ว = เหลือตัวไหน

คำตอบข้อนี้: c) 5 :white_check_mark:

คำตอบและวิธีทำ

วิเคราะห์โจทย์

Hashing Function: mod(a₁+a₂+a₃+a₄+a₅, 13)

  • ข้อมูล: 54321
  • Hash Table Size: 13 ตำแหน่ง (0-12)
  • วิธีการ: บวกตัวเลขทุกหลักแล้วหาร mod 13

วิธีแก้แบบปกติ

ขั้นที่ 1: แยกตัวเลขแต่ละหลัก

54321 แยกเป็น:
a₁ = 5
a₂ = 4
a₃ = 3
a₄ = 2
a₅ = 1

ขั้นที่ 2: คำนวณผลรวม

a₁ + a₂ + a₃ + a₄ + a₅
= 5 + 4 + 3 + 2 + 1
= 15

ขั้นที่ 3: หา mod 13

mod(15, 13) = 15 % 13 = ?

15 ÷ 13 = 1 เศษ 2

ผลลัพธ์: 15 mod 13 = 2

ดังนั้น เก็บข้อมูลที่ตำแหน่ง 2


:bullseye: เทคนิคหาคำตอบแบบรวดเร็ว

เทคนิค 1: ใช้สูตรรวดเร็ว :high_voltage:

สำหรับเลขที่เรียงกัน (เช่น 54321, 12345):

ผลรวม = n × (first + last) / 2

โดยที่:
- n = จำนวนตัวเลข
- first = ตัวแรก
- last = ตัวสุดท้าย

ตัวอย่างนี้:

54321 → เลขเรียงจาก 5 ลงมา 1
n = 5 ตัว
first = 5, last = 1

ผลรวม = 5 × (5 + 1) / 2
       = 5 × 6 / 2
       = 30 / 2
       = 15

15 mod 13 = 2

:stopwatch: ประหยัดเวลา: ~40%


เทคนิค 2: จำหลัก mod ที่ใช้บ่อย :1234:

ตาราง mod 13 ที่ใช้บ่อย:

ผลรวม mod 13 ผลรวม mod 13
0 0 13 0
1 1 14 1
2 2 15 2
3 3 16 3
4 4 17 4
5 5 18 5
6 6 19 6
7 7 20 7
8 8 21 8
9 9 22 9
10 10 23 10
11 11 24 11
12 12 25 12

เทคนิคจำ:

  • ถ้าผลรวม < 13 → mod = ตัวเอง
  • ถ้าผลรวม ≥ 13 → ลบ 13 ไปเรื่อยๆ จนเหลือ < 13

ตัวอย่าง:

15 - 13 = 2

:stopwatch: ประหยัดเวลา: ~30%


เทคนิค 3: คำนวณในใจแบบเร็ว :high_voltage::high_voltage:

วิธีคิดในหัว:

5 + 4 = 9
9 + 3 = 12
12 + 2 = 14
14 + 1 = 15

15 เทียบกับ 13:
15 - 13 = 2

หรือแบบ “บวกเลื่อน”:

5+4=9, +3=12, +2=14, +1=15
15-13=2

:stopwatch: ประหยัดเวลา: ~50%


เทคนิค 4: ใช้สมบัติของ mod (สำหรับผู้เชี่ยวชาญ) :graduation_cap:

สูตร: (a + b) mod n = [(a mod n) + (b mod n)] mod n

(5+4+3+2+1) mod 13

= [(5 mod 13) + (4 mod 13) + (3 mod 13) + (2 mod 13) + (1 mod 13)] mod 13
= [5 + 4 + 3 + 2 + 1] mod 13
= 15 mod 13
= 2

หรือแบบทีละขั้น:

5 mod 13 = 5
(5 + 4) mod 13 = 9 mod 13 = 9
(9 + 3) mod 13 = 12 mod 13 = 12
(12 + 2) mod 13 = 14 mod 13 = 1  ← ลบ 13 ได้ 1
(1 + 1) mod 13 = 2 mod 13 = 2

:stopwatch: ประหยัดเวลา: ~20% (แต่ป้องกัน overflow ในเลขใหญ่)


:bar_chart: สรุปเปรียบเทียบเทคนิค

เทคนิค เวลา ความยาก เหมาะกับ
วิธีปกติ 100% :star: ผู้เริ่มต้น
สูตรรวดเร็ว 60% :star::star: เลขเรียงลำดับ :star:
จำตาราง mod 70% :star::star: สอบจริง
คิดในหัว 50% :star::star::star: ฝึกฝนแล้ว :star:
สมบัติ mod 80% :star::star::star::star: เลขใหญ่มาก

:light_bulb: เคล็ดลับการจำ mod

วิธีหา x mod 13 แบบเร็ว:

ถ้า x < 13   → mod = x
ถ้า x ≥ 13   → ลบ 13 ทีละครั้ง

ตัวอย่าง:
27 mod 13 = 27 - 13 = 14 - 13 = 1
40 mod 13 = 40 - 13 = 27 - 13 = 14 - 13 = 1

วิธีการคำนวณ mod แบบหาร:

x mod 13 = x - (13 × ⌊x/13⌋)

15 mod 13 = 15 - (13 × ⌊15/13⌋)
          = 15 - (13 × 1)
          = 15 - 13
          = 2

:bullseye: ตัวอย่างเพิ่มเติม

ถ้าเลขเป็น 98765:

วิธีเร็ว:

ผลรวม = 9+8+7+6+5 = 35
35 mod 13 = 35 - 13 = 22 - 13 = 9

ตำแหน่ง: 9

ถ้าเลขเป็น 11111:

วิธีเร็ว:

ผลรวม = 1+1+1+1+1 = 5
5 mod 13 = 5

ตำแหน่ง: 5

:warning: ข้อควรระวัง

  1. อย่าลืมว่า mod ให้ผลลัพธ์ 0 ถึง (n-1)

    • mod 13 ได้ 0-12 เท่านั้น
  2. ตรวจสอบว่าโจทย์ใช้ mod หรือ remainder

    • ส่วนใหญ่เหมือนกัน แต่อาจต่างในกรณีเลขลบ
  3. ระวังเลขใหญ่

    • ใช้เทคนิคสมบัติ mod ถ้าเลขใหญ่มาก

คำตอบ: b) 2 :white_check_mark:

แสดงในตาราง:

ตำแหน่ง     อาร์เรย์
   0          [    ]
   1          [    ]
   2          [54321] ← เก็บที่นี่
   3          [    ]
   :            :
  11          [    ]
  12          [    ]

สรุป: ใช้เทคนิคไหนก็ได้ตามความถนัด แต่แนะนำ “บวกแล้วลบ 13” สำหรับสอบจริง เพราะเร็วและแม่นยำ!

คำตอบและวิธีทำ

วิเคราะห์โจทย์

โจทย์ถามเทคโนโลยีที่:

  1. ประมวลผลแบบโต้ตอบ (Interactive processing)
  2. ทำงานอยู่เฉพาะบนเว็บเซิร์ฟเวอร์เท่านั้น (Server-side only)

วิเคราะห์แต่ละตัวเลือก

a) JavaScript :cross_mark:

ที่ทำงาน: Client-side (ในเบราว์เซอร์)

[เบราว์เซอร์] ← JavaScript ทำงานที่นี่
      ↕
[เว็บเซิร์ฟเวอร์]

คุณสมบัติ:

  • :white_check_mark: โต้ตอบกับผู้ใช้ได้
  • :cross_mark: ทำงานบน client-side ไม่ใช่เซิร์ฟเวอร์
  • ใช้สำหรับ: Animation, Form validation, DOM manipulation

สรุป: ไม่ใช่คำตอบ เพราะทำงานบน client


b) Java Applet :cross_mark:

ที่ทำงาน: Client-side (ดาวน์โหลดมารันในเบราว์เซอร์)

[เว็บเซิร์ฟเวอร์] → ส่ง Applet (.class)
      ↓
[เบราว์เซอร์] ← Applet ทำงานที่นี่ (ใน JVM)

คุณสมบัติ:

  • :white_check_mark: โต้ตอบกับผู้ใช้ได้
  • :cross_mark: ทำงานบน client-side ไม่ใช่เซิร์ฟเวอร์
  • ดาวน์โหลดจากเซิร์ฟเวอร์แล้วรันบนเครื่อง client
  • หมายเหตุ: เลิกใช้แล้วตั้งแต่ปี 2017

สรุป: ไม่ใช่คำตอบ เพราะทำงานบน client


c) Java Servlet :white_check_mark:

ที่ทำงาน: Server-side เท่านั้น

[เบราว์เซอร์] → ส่ง HTTP Request
      ↓
[เว็บเซิร์ฟเวอร์]
      ↓
[Servlet Container] ← Servlet ทำงานที่นี่
      ↓
[Database/Resources]

คุณสมบัติ:

  • :white_check_mark: โต้ตอบกับผู้ใช้ได้ (รับ request/ส่ง response)
  • :white_check_mark: ทำงานบน server-side เท่านั้น
  • ประมวลผลบนเซิร์ฟเวอร์
  • ส่งผลลัพธ์กลับไปที่ client

ตัวอย่างการทำงาน:

java

public class HelloServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) {
        // ประมวลผลบนเซิร์ฟเวอร์
        String name = request.getParameter("name");
        response.getWriter().println("Hello " + name);
    }
}

สรุป: นี่คือคำตอบ! :white_check_mark:


d) VBScript :cross_mark:

ที่ทำงาน: ส่วนใหญ่ Client-side (IE เท่านั้น)

[เบราว์เซอร์ IE] ← VBScript ทำงานที่นี่ (client-side)
      หรือ
[เซิร์ฟเวอร์ IIS] ← ASP + VBScript (server-side)

คุณสมบัติ:

  • :white_check_mark: โต้ตอบกับผู้ใช้ได้
  • :warning: ทำงานได้ทั้ง client-side และ server-side
  • ใช้ได้เฉพาะ Internet Explorer
  • เลิกใช้แล้ว (deprecated)

สรุป: ไม่ใช่คำตอบ เพราะไม่ได้ทำงานเฉพาะบนเซิร์ฟเวอร์เท่านั้น


:bar_chart: ตารางเปรียบเทียบ

เทคโนโลยี ทำงานที่ โต้ตอบได้ เฉพาะเซิร์ฟเวอร์ สถานะ
JavaScript Client :white_check_mark: :cross_mark: ใช้งานอยู่
Java Applet Client :white_check_mark: :cross_mark: เลิกใช้แล้ว
Java Servlet Server :white_check_mark: :white_check_mark: ใช้งานอยู่ :star:
VBScript Client/Server :white_check_mark: :cross_mark: เลิกใช้แล้ว

:bullseye: เทคนิคจำง่ายๆ

จำคำว่า “Servlet”

Servlet = Server + let (ขนาดเล็ก)
         = โปรแกรมเล็กๆ ที่ทำงานบน Server

จำความแตกต่าง

Client-side (รันในเบราว์เซอร์):
├─ JavaScript ⭐ (ใช้มาก)
├─ Java Applet (เลิกใช้)
└─ VBScript (เลิกใช้)

Server-side (รันบนเซิร์ฟเวอร์):
├─ Java Servlet ⭐ (คำตอบ)
├─ PHP
├─ Python (Django/Flask)
├─ Node.js
└─ ASP.NET

:light_bulb: ข้อมูลเพิ่มเติม

Java Servlet คืออะไร?

นิยาม:

  • คลาส Java ที่ทำงานบนเว็บเซิร์ฟเวอร์
  • ขยายความสามารถของเซิร์ฟเวอร์
  • จัดการ HTTP request/response

ข้อดี:

  • :white_check_mark: ประสิทธิภาพสูง (compile แล้ว)
  • :white_check_mark: ปลอดภัย (ทำงานบนเซิร์ฟเวอร์)
  • :white_check_mark: มีฟีเจอร์ครบ (session, cookie, etc.)
  • :white_check_mark: Platform independent

ใช้งานจริง:

  • Web applications
  • RESTful APIs
  • Backend processing
  • Database connectivity

:fire: เทคนิคจำแบบเร็ว

คำถาม: ทำงานบนเซิร์ฟเวอร์เท่านั้น?

❓ JavaScript?     → ❌ Client
❓ Applet?         → ❌ Client  
❓ Servlet?        → ✅ Server ← คำตอบ!
❓ VBScript?       → ❌ Client/Server

สูตรจำ:

"Let" = เล็ก
Servlet = Server + let = ตัวเล็กๆ ที่ทำงานบน Server
App + let = แอพเล็กๆ ที่ทำงานบน Client

คำตอบ: c) จาวาเซิร์ฟเล็ต (Java servlet) :white_check_mark:

เหตุผล:

  1. :white_check_mark: ทำงานเฉพาะบนเว็บเซิร์ฟเวอร์
  2. :white_check_mark: ประมวลผลแบบโต้ตอบกับ client ได้
  3. :white_check_mark: รับ request จาก client → ประมวลผล → ส่ง response กลับ
  4. :white_check_mark: ยังใช้งานอยู่ในปัจจุบัน

ตัวเลือกอื่นผิดเพราะ:

  • a) JavaScript → ทำงานบน client
  • b) Java Applet → ทำงานบน client
  • d) VBScript → ทำงานได้ทั้ง client และ server (ไม่ใช่เฉพาะเซิร์ฟเวอร์)

คำตอบและวิธีทำ

วิเคราะห์โจทย์

โจทย์ถามเกี่ยวกับ Special Register ที่ใช้ในการ:

  • Push (เพิ่มข้อมูลเข้า stack)
  • Pop (นำข้อมูลออกจาก stack)

วิเคราะห์แต่ละตัวเลือก

a) รีจิสเตอร์คำสั่ง (Instruction Register - IR) :cross_mark:

หน้าที่:

  • เก็บ คำสั่งปัจจุบัน ที่กำลังถูก execute
  • ใช้ในขั้นตอน Fetch-Decode-Execute
[Memory] → Fetch → [IR] → Decode → Execute

ตัวอย่าง:

IR = ADD R1, R2  ← เก็บคำสั่ง ADD

สรุป: ไม่เกี่ยวกับ Stack, Push, Pop


b) ตัวนับโปรแกรม (Program Counter - PC) :cross_mark:

หน้าที่:

  • เก็บ address ของคำสั่งถัดไป ที่จะ execute
  • เพิ่มค่าทีละ 1 (หรือมากกว่า) หลัง fetch คำสั่ง
PC = 1000  → Fetch instruction at 1000
PC = 1001  → Fetch instruction at 1001
PC = 1002  → ...

ตัวอย่าง:

Address | Instruction
--------|------------
1000    | MOV R1, #5
1001    | ADD R2, R1  ← PC ชี้ที่นี่
1002    | SUB R3, R2

สรุป: ไม่เกี่ยวกับ Stack, Push, Pop


c) ตัวชี้สแตก (Stack Pointer - SP) :white_check_mark:

หน้าที่:

  • ชี้ไปที่ top ของ stack (ตำแหน่งล่าสุด)
  • ใช้ใน PUSH operation
  • ใช้ใน POP operation
  • อัพเดทค่าอัตโนมัติ เมื่อมีการ push/pop

การทำงาน:

Stack (เติบโตลงล่าง):

High Address
    ↓
    [    ]
    [    ]
    [ 30 ] ← SP (ชี้ที่นี่)
    [ 20 ]
    [ 10 ]
Low Address

PUSH Operation:

PUSH 40

ขั้นตอน:
1. SP = SP - 1  (เลื่อน SP ลง)
2. Memory[SP] = 40  (เก็บข้อมูล)

ผลลัพธ์:
    [ 40 ] ← SP (ชี้ใหม่)
    [ 30 ]
    [ 20 ]
    [ 10 ]

POP Operation:

POP

ขั้นตอน:
1. Data = Memory[SP]  (อ่านข้อมูล)
2. SP = SP + 1  (เลื่อน SP ขึ้น)

ผลลัพธ์:
    [    ] 
    [ 30 ] ← SP (ชี้ใหม่)
    [ 20 ]
    [ 10 ]

สรุป: นี่คือคำตอบ! ใช้ในการ Push และ Pop :white_check_mark:


d) รีจิสเตอร์สถานะ (Status Register / Flags Register) :cross_mark:

หน้าที่:

  • เก็บ สถานะ หรือ flags ต่างๆ ของ CPU
  • แต่ละบิตมีความหมายต่างกัน

Flags ที่มีโดยทั่วไป:

Bit:  7  6  5  4  3  2  1  0
     [S][Z][--][AC][--][P][--][C]

C = Carry Flag
P = Parity Flag
AC = Auxiliary Carry Flag
Z = Zero Flag
S = Sign Flag

ตัวอย่างการใช้งาน:

SUB A, B

ถ้า A = B:
  Zero Flag (Z) = 1  ← ผลลัพธ์เป็น 0

ถ้า A < B:
  Carry Flag (C) = 1  ← เกิด borrow
  Sign Flag (S) = 1   ← ผลลัพธ์ติดลบ

สรุป: ไม่เกี่ยวกับ Stack, Push, Pop


:bar_chart: ตารางเปรียบเทียบ

Register หน้าที่หลัก ใช้กับ Stack? ใช้กับ Push/Pop?
Instruction Register (IR) เก็บคำสั่งปัจจุบัน :cross_mark: :cross_mark:
Program Counter (PC) ชี้คำสั่งถัดไป :cross_mark: :cross_mark:
Stack Pointer (SP) ชี้ top ของ stack :white_check_mark: :white_check_mark:
Status Register (SR) เก็บ flags สถานะ :cross_mark: :cross_mark:

:bullseye: ทำความเข้าใจ Stack Pointer

โครงสร้าง Stack

Stack มี 2 แบบ:

1. Full Descending (ใช้มาก):
   - SP ชี้ที่ occupied location
   - เติบโตจากบนลงล่าง
   - PUSH: SP--, then store
   - POP: load, then SP++

2. Empty Ascending:
   - SP ชี้ที่ empty location
   - เติบโตจากล่างขึ้นบน
   - PUSH: store, then SP++
   - POP: SP--, then load

ตัวอย่างโค้ด Assembly

assembly

; PUSH operation
PUSH AX          ; Push AX register to stack
; CPU ทำเบื้องหลัง:
; SP = SP - 2    (สมมุติ 16-bit)
; [SP] = AX

; POP operation
POP BX           ; Pop from stack to BX
; CPU ทำเบื้องหลัง:
; BX = [SP]
; SP = SP + 2

:light_bulb: เทคนิคจำง่ายๆ

จำคำว่า “Pointer”

Stack POINTER = ตัวชี้ Stack
              = ชี้ไปที่ตำแหน่งบน Stack
              = ใช้กับ Push/Pop

จำความสัมพันธ์

Stack ←→ Stack Pointer ←→ Push/Pop

เหมือน:
ถังน้ำ ←→ ไม้บรรทัดวัดระดับ ←→ เติม/ตัก

เปรียบเทียบกับของจริง

Stack of plates (จานซ้อน):

[จาน 3] ← SP ชี้ที่นี่ (จานบนสุด)
[จาน 2]
[จาน 1]
---------

PUSH จาน 4:
[จาน 4] ← SP เลื่อนมาชี้ที่นี่
[จาน 3]
[จาน 2]
[จาน 1]

POP:
         (เอาจาน 4 ออก)
[จาน 3] ← SP กลับมาชี้ที่นี่
[จาน 2]
[จาน 1]

:fire: เทคนิคจำแบบรวดเร็ว

คำถาม: ใช้กับ Push/Pop?

❓ IR (คำสั่ง)?        → ❌ เก็บคำสั่ง
❓ PC (นับโปรแกรม)?    → ❌ ชี้คำสั่งถัดไป
❓ SP (ชี้ Stack)?     → ✅ ใช้ Push/Pop ← คำตอบ!
❓ SR (สถานะ)?         → ❌ เก็บ flags

สูตรจำ:

Stack + Pointer = Stack Pointer
                = ใช้กับ Stack
                = ใช้กับ Push/Pop

คำตอบ: c) ตัวชี้สแตก (Stack pointer) :white_check_mark:

เหตุผล:

  1. :white_check_mark: Stack Pointer ชี้ไปที่ top ของ stack
  2. :white_check_mark: ใช้ใน PUSH operation (เพิ่มข้อมูลลง stack)
  3. :white_check_mark: ใช้ใน POP operation (เอาข้อมูลออกจาก stack)
  4. :white_check_mark: อัพเดทค่าอัตโนมัติ ทุกครั้งที่ push/pop

ตัวเลือกอื่นผิดเพราะ:

  • a) Instruction Register → เก็บคำสั่งที่กำลัง execute
  • b) Program Counter → ชี้ address ของคำสั่งถัดไป
  • d) Status Register → เก็บ flags สถานะต่างๆ

:memo: สรุปหลักการ

Stack Pointer คือ:

  • รีจิสเตอร์พิเศษที่จำเป็นสำหรับการทำงานของ Stack
  • ใช้ในการเรียก function (function call)
  • ใช้ในการเก็บ return address
  • ใช้ในการเก็บตัวแปร local
  • หัวใจสำคัญของ Push และ Pop operations!

คำตอบที่ถูกต้องคือ b) การขัดจังหวะที่เกิดจากการดำเนินการคำสั่งที่มีการหารด้วยศูนย์ (\text{divide-by-zero operation})

การวิเคราะห์และการจัดประเภท \text{Interrupt}

การขัดจังหวะ (\text{Interrupt}) แบ่งออกเป็น 2 ประเภทหลักๆ ตามแหล่งที่มา:

  1. \text{External Interrupt} (การขัดจังหวะภายนอก):

    • เกิดจากอุปกรณ์ภายนอก (\text{I/O device}) หรือสัญญาณจากภายนอก \text{CPU}
    • เช่น การกดแป้นพิมพ์, การขัดจังหวะเมื่อ \text{I/O} ทำงานเสร็จ, หรือไฟฟ้าดับ
  2. \text{Internal Interrupt} หรือ \text{Trap/Exception} (การขัดจังหวะภายใน):

    • เกิดจากความผิดพลาดขณะที่ \text{CPU} กำลังดำเนินการคำสั่ง (\text{executing an instruction})
    • เป็นสิ่งที่ผิดปกติที่เกิดขึ้นภายในตัวโปรแกรมเอง
    • เช่น การหารด้วยศูนย์, การเข้าถึงหน่วยความจำที่ผิดกฎหมาย (\text{illegal memory access}), หรือการใช้คำสั่งที่ไม่ถูกต้อง (\text{illegal instruction}
    • มักถูกเรียกว่า \text{Exception} หรือ \text{Trap}

การวิเคราะห์ตัวเลือก

ตัวเลือก เหตุการณ์ แหล่งที่มา/ประเภท เหตุผล
a) การจ่ายไฟผิดปกติ ไฟฟ้าดับไปชั่วขณะ \text{External} (เกิดจากแหล่งจ่ายไฟภายนอกระบบหลักของ \text{CPU})
b) การหารด้วยศูนย์ (\text{divide-by-zero}) เกิดจากการดำเนินการคำสั่งที่ผิดพลาด \text{Internal} (\text{Exception}/\text{Trap}) เป็นความผิดพลาดที่ \text{CPU} ตรวจพบขณะรันคำสั่งนั้นๆ
c) การเสร็จสิ้นการทำงานของ \text{Input/Output} \text{I/O device} ส่งสัญญาณเสร็จสิ้นมา \text{External} (เกิดจากอุปกรณ์ \text{I/O} ภายนอก \text{CPU})
d) ความผิดพลาดของพาริตีหน่วยความจำ (\text{memory parity error}) เกิดจากความผิดพลาดในการส่งข้อมูลของ \text{Memory} \text{External} (เกิดจาก \text{Memory} ซึ่งเป็นส่วนประกอบภายนอก \text{CPU})

ดังนั้น b) คือเหตุการณ์เดียวที่เกิดจากความผิดปกติใน การดำเนินการของคำสั่ง ซึ่งจัดเป็น \text{Internal Interrupt} หรือ \text{Exception}

คำตอบที่ถูกต้องคือ b) การเขียนทีหลัง (\text{Write back})

เทคนิคการจัดการการเขียนข้อมูล (\text{Cache Write Policies})

คำถามนี้เกี่ยวข้องกับ นโยบายการเขียนข้อมูล (\text{Write Policy}) ในหน่วยความจำแคช (\text{Cache Memory}) ซึ่งเป็นเทคนิคที่ใช้ในการจัดการว่าเมื่อ \text{CPU} มีการแก้ไขข้อมูลใน \text{Cache} จะต้องอัปเดตข้อมูลใน หน่วยความจำหลัก (\text{Main Memory}) เมื่อใด

นโยบายการเขียน คำอธิบาย จุดเด่น/จุดประสงค์
b) การเขียนทีหลัง (\text{Write back}) \text{CPU} จะทำการอัปเดตข้อมูล เฉพาะใน \text{Cache} เท่านั้น โดยจะทำเครื่องหมาย (\text{flag}) ว่า \text{Block} นั้นเป็นข้อมูลใหม่ (\text{Dirty}) และจะรออัปเดตข้อมูลไปยังหน่วยความจำหลัก ในภายหลัง (เมื่อ \text{Block} นั้นถูกนำออก/ถูกแทนที่จาก \text{Cache}) ลดจำนวนครั้ง ของการเขียนข้อมูลไปยังหน่วยความจำหลัก ซึ่งช่วยเพิ่มประสิทธิภาพความเร็วในการทำงานของ \text{CPU} ได้มากที่สุด
d) การเขียนทั้งหมด (\text{Write through}) \text{CPU} จะทำการอัปเดตข้อมูล ทั้งใน \text{Cache} และหน่วยความจำหลักพร้อมกัน ในทันทีที่เกิดการเขียน ข้อมูลใน \text{Cache} และ \text{Main Memory} จะมีความสอดคล้องกัน (\text{Consistency}) อยู่ตลอดเวลา แต่จะเกิดการ \text{Write} ไปยัง \text{Main Memory} บ่อยครั้ง ทำให้ช้าลง

สรุปเหตุผล

โจทย์ต้องการเทคนิคที่ “ลดจำนวนครั้งของกระบวนการเขียนข้อมูลที่กระทำต่อหน่วยความจำหลัก” โดยการอัปเดตเฉพาะใน \text{Cache} ก่อน แล้วจึงอัปเดตทีหลัง ซึ่งตรงกับหลักการของ การเขียนทีหลัง (\text{Write back}) โดยสมบูรณ์

  • a) \text{การซ้อนแทน} (\text{Overlay}) : เป็นเทคนิคการจัดการหน่วยความจำที่อนุญาตให้โปรแกรมขนาดใหญ่ทำงานในหน่วยความจำที่มีจำกัด (ไม่เกี่ยวกับ \text{Write Policy} ของ \text{Cache})
  • c) \text{การป้องกันการเขียน} (\text{Write protected}) : เป็นการตั้งค่าเพื่อไม่ให้สามารถแก้ไขข้อมูลได้ (ไม่ใช่นโยบายการเขียน)

คำตอบ: c) สร้างวัตถุสามมิติต่าง ๆ ขึ้นมาด้วยวิธีการต่าง ๆ เช่นการขึ้นรูปด้วยภาพลอมฟิลาเมนต์ :white_check_mark:

เหตุผล:

  1. :white_check_mark: อธิบายหน้าที่หลักของเครื่องพิมพ์ 3D ได้ถูกต้อง
  2. :white_check_mark: ยกตัวอย่าง FDM/FFF ซึ่งเป็นเทคโนโลยีที่ใช้กันมากที่สุด
  3. :white_check_mark: “การขึ้นรูปด้วยภาพลอมฟิลาเมนต์” = Fused Filament Fabrication
  4. :white_check_mark: สร้างวัตถุ 3D จริง จากไฟล์ดิจิทัล

ตัวเลือกอื่นผิดเพราะ:

  • a) 3D Scanning (input) ไม่ใช่ 3D Printing (output)
  • b) Thermal Printing 2D ไม่ใช่ 3D
  • d) Texture Mapping (CG) ไม่ใช่การสร้างวัตถุจริง

:memo: ความรู้เพิ่มเติม

ประเภทของ 3D Printing

เทคโนโลยี วัสดุ ข้อดี ใช้สำหรับ
FDM/FFF Filament ถูก ง่าย Prototype, Hobby
SLA Resin ละเอียดมาก Jewelry, Dental
SLS Powder แข็งแรง Functional parts
MJF Powder + Ink เร็ว แม่นยำ Mass production
DMLS Metal powder โลหะแท้ Aerospace, Medical

การใช้งานจริง

อุตสาหกรรม:

  • :airplane: Aerospace: ชิ้นส่วนเครื่องบิน
  • :hospital: Medical: Prosthetics, Implants
  • :building_construction: Construction: บ้านพิมพ์ 3D
  • :automobile: Automotive: Prototype ชิ้นส่วนรถ
  • :running_shoe: Fashion: รองเท้า เสื้อผ้า
  • :hamburger: Food: อาหารพิมพ์ 3D

หลักจำ: เครื่องพิมพ์ 3D สร้างวัตถุจริง จากไฟล์ดิจิทัล โดยการวางวัสดุทีละชั้น จนได้รูปทรงสามมิติสมบูรณ์!

คำตอบและวิธีทำ

วิเคราะห์โจทย์

โจทย์ถาม: การกำหนดค่า RAID ข้อใดตอบไม่ถูก ที่มีวัตถุประสงค์:

  1. ได้ความเร็วในการเข้าถึงดิสก์สูงสุด
  2. ยอมเสียคุณสมบัติด้านความเชื่อถือได้ไป

คำถามคือหา RAID ระดับไหนที่ไม่ตรงกับคำอธิบายนี้


วิเคราะห์ RAID แต่ละระดับ

a) RAID 0 (Striping) ✓

คุณสมบัติ:

Disk 1: [A1][B1][C1][D1]
Disk 2: [A2][B2][C2][D2]
Disk 3: [A3][B3][C3][D3]

Data A กระจายไป A1, A2, A3
อ่าน/เขียนพร้อมกัน 3 ดิสก์

ข้อดี:

  • :white_check_mark: ความเร็วสูงสุด (อ่าน/เขียนหลายดิสก์พร้อมกัน)
  • :white_check_mark: ใช้พื้นที่เต็ม 100%

ข้อเสีย:

  • :cross_mark: ไม่มี redundancy เลย
  • :cross_mark: ดิสก์เสีย 1 ตัว = ข้อมูลหายหมด
  • :cross_mark: ความเชื่อถือได้ต่ำสุด

สรุป: ตรงกับคำอธิบาย - เร็วสุด แต่เสียความเชื่อถือได้


b) RAID 1 (Mirroring) :cross_mark:

คุณสมบัติ:

Disk 1: [A][B][C][D] ← ข้อมูลต้นฉบับ
Disk 2: [A][B][C][D] ← Mirror (คัดลอก)

ข้อดี:

  • :white_check_mark: ความเชื่อถือได้สูง (มีสำรองเต็มชุด)
  • :white_check_mark: อ่านเร็วขึ้น (อ่านจากดิสก์ใดก็ได้)
  • :white_check_mark: ทนดิสก์เสีย 50% ได้

ข้อเสีย:

  • :cross_mark: เขียนช้ากว่า RAID 0 (ต้องเขียน 2 ที่)
  • :cross_mark: ใช้พื้นที่เพียง 50%
  • :cross_mark: ไม่ได้ความเร็วสูงสุด

สรุป: ไม่ตรงกับคำอธิบาย - เน้นความเชื่อถือได้ ไม่ใช่ความเร็ว


c) RAID 5 (Striping with Parity) :cross_mark:

คุณสมบัติ:

Disk 1: [A1][B1][C1][Dp]
Disk 2: [A2][B2][Cp][D2]
Disk 3: [A3][Bp][C3][D3]
         ↑
    p = parity (สำหรับ recovery)

ข้อดี:

  • :white_check_mark: มี redundancy (parity สำหรับกู้คืน)
  • :white_check_mark: ทนดิสก์เสีย 1 ตัวได้
  • :white_check_mark: ความเร็วดี (แต่ไม่เท่า RAID 0)
  • :white_check_mark: ใช้พื้นที่ประมาณ 67-90% (ขึ้นกับจำนวนดิสก์)

ข้อเสีย:

  • :cross_mark: เขียนช้ากว่า RAID 0 (ต้องคำนวณ parity)
  • :cross_mark: ไม่ได้ความเร็วสูงสุด

สรุป: ไม่ตรงกับคำอธิบาย - สมดุล ไม่ยอมเสียความเชื่อถือได้


d) RAID 6 (Striping with Double Parity) :cross_mark:

คุณสมบัติ:

Disk 1: [A1][B1][Cp][Dq]
Disk 2: [A2][Bp][C2][Dq]
Disk 3: [Ap][B2][C3][D3]
Disk 4: [Aq][Bq][Cq][D4]
         ↑   ↑
    p, q = parity 2 ชุด

ข้อดี:

  • :white_check_mark: ความเชื่อถือได้สูงสุด
  • :white_check_mark: ทนดิสก์เสีย 2 ตัวพร้อมกันได้
  • :white_check_mark: ปลอดภัยมาก

ข้อเสีย:

  • :cross_mark: เขียนช้าที่สุด (คำนวณ parity 2 ชุด)
  • :cross_mark: ใช้พื้นที่น้อยกว่า RAID 5
  • :cross_mark: ตรงข้ามกับคำอธิบายในโจทย์มากที่สุด

สรุป: ไม่ตรงกับคำอธิบาย - เน้นความเชื่อถือได้มากที่สุด ไม่ใช่ความเร็ว


:bar_chart: ตารางเปรียบเทียบ

RAID ความเร็ว ความเชื่อถือได้ Redundancy ตรงกับโจทย์?
RAID 0 :star::star::star::star::star: :cross_mark: :cross_mark: :white_check_mark: ตรง
RAID 1 :star::star::star: :star::star::star::star::star: :white_check_mark: :cross_mark: ไม่ตรง
RAID 5 :star::star::star::star: :star::star::star::star: :white_check_mark: :cross_mark: ไม่ตรง
RAID 6 :star::star::star: :star::star::star::star::star: :white_check_mark::white_check_mark: :cross_mark: ไม่ตรง

:bullseye: วิเคราะห์คำถาม

โจทย์ถาม: “ข้อใดตอบไม่ถูก

แปลว่า: ข้อไหนที่ไม่ตรงกับคำอธิบาย

คำอธิบายในโจทย์:

  • ✓ ความเร็วสูงสุด
  • ✓ ยอมเสียความเชื่อถือได้

ตัวเลือกที่ไม่ตรง:

b) RAID 1:

  • :cross_mark: ไม่ได้ความเร็วสูงสุด
  • :cross_mark: ไม่ยอมเสียความเชื่อถือได้ (กลับเน้นความเชื่อถือได้)

c) RAID 5:

  • :cross_mark: ไม่ได้ความเร็วสูงสุด
  • :cross_mark: ไม่ยอมเสียความเชื่อถือได้ (มี parity)

d) RAID 6:

  • :cross_mark: ไม่ได้ความเร็วสูงสุด (ช้าที่สุดในกลุ่มนี้)
  • :cross_mark: ไม่ยอมเสียความเชื่อถือได้ (เน้นความเชื่อถือได้มากที่สุด)
  • :cross_mark: ตรงข้ามกับโจทย์ทุกประการ

:light_bulb: เทคนิคจำ RAID

จำแบบง่าย

RAID 0: 
- 0 = Zero redundancy (ไม่มีสำรอง)
- เร็วสุด แต่เสี่ยงสุด

RAID 1:
- 1 = One mirror (กระจก 1 บาน)
- ปลอดภัย แต่ไม่เร็วสุด

RAID 5:
- 5 = ต้องมีดิสก์อย่างน้อย 3 ตัว
- สมดุล (ไม่เร็วสุด ไม่ปลอดภัยสุด)

RAID 6:
- 6 = RAID 5 + อีก 1 parity
- ปลอดภัยสุด แต่ช้ากว่า

ตารางสรุป

Feature RAID 0 RAID 1 RAID 5 RAID 6
Min disks 2 2 3 4
Speed :star::star::star::star::star: :star::star::star: :star::star::star::star: :star::star::star:
Safety :cross_mark: :star::star::star::star::star: :star::star::star::star: :star::star::star::star::star:
Capacity 100% 50% 67-90% 50-80%
Fault tolerance 0 1 disk 1 disk 2 disks

:fire: เทคนิคหาคำตอบแบบรวดเร็ว

ขั้นตอน:

1. อ่านโจทย์: เน้นความเร็ว + ยอมเสียความเชื่อถือได้

2. หา RAID ที่ตรง: RAID 0 เท่านั้น

3. หา RAID ที่ไม่ตรง: ทุกข้ออื่นไม่ตรง

4. หา RAID ที่ไม่ตรงมากที่สุด:

  • RAID 6 เน้นความเชื่อถือได้มากที่สุด
  • ช้าที่สุด (เพราะ double parity)
  • ตรงข้ามกับโจทย์ทุกประการ

คำตอบ: d) RAID 6 :white_check_mark:

เหตุผล:

RAID 6 ตรงข้ามกับคำอธิบายในโจทย์มากที่สุด เพราะ:

  1. :cross_mark: ไม่ได้ความเร็วสูงสุด - กลับช้าที่สุดในกลุ่มนี้
  2. :cross_mark: ไม่ยอมเสียความเชื่อถือได้ - กลับเน้นเพิ่มความเชื่อถือได้สูงสุด
  3. :cross_mark: มี double parity ทำให้เขียนช้า
  4. :cross_mark: ทนดิสก์เสีย 2 ตัวพร้อมกัน (ปลอดภัยสุด)

ตัวเลือกอื่น:

  • a) RAID 0ตรงกับโจทย์ - เร็วสุด ไม่มี redundancy
  • b) RAID 1 → ไม่ตรง - แต่ยังมีความเร็วอ่านที่ดี
  • c) RAID 5 → ไม่ตรง - แต่ยังสมดุลระหว่างเร็วและปลอดภัย

:memo: สรุปสำคัญ

ถ้าต้องการ:

ความเร็วสูงสุด (ยอมเสียความปลอดภัย):
RAID 0 :high_voltage:

ความปลอดภัยสูง (ยอมเสียความเร็ว):
RAID 1 หรือ RAID 6 :shield:

สมดุล:
RAID 5 :balance_scale:

หลักจำ: RAID 0 = เร็วแต่เสี่ยง, RAID 6 = ปลอดภัยแต่ช้า (ตรงข้ามกัน)!

คำตอบที่ถูกต้องคือ c) ระบบคู่ขนาน, ระบบโคลด์สแตนด์บาย, ระบบเครื่องเดียว

การเรียงลำดับสภาพพร้อมใช้งาน (\text{Availability}) จาก มากที่สุดไปน้อยที่สุด คือ \text{Dual System} \rightarrow \text{Cold Standby System} \rightarrow \text{Simplex System}

การวิเคราะห์สภาพพร้อมใช้งาน (\text{Availability})

สภาพพร้อมใช้งาน (\text{Availability}) คือ ความสามารถของระบบในการทำงานอย่างต่อเนื่องในช่วงเวลาที่กำหนด (\text{uptime}). ระบบที่มีความซ้ำซ้อน (\text{Redundancy}) สูงกว่าจะมี \text{Availability} สูงกว่า

1. ระบบคู่ขนาน (\text{Dual System}) - \text{สูงสุด}

  • ลักษณะ: มีคอมพิวเตอร์ทำงานพร้อมกัน 2 ชุด (\text{Active-Active} หรือ \text{Active-Standby} ที่สลับการทำงานได้เร็วมาก)
  • Availability: สูงที่สุด เพราะเมื่อเครื่องหนึ่งล้มเหลว อีกเครื่องหนึ่งสามารถ รับช่วงการทำงานต่อได้ทันที (\text{Immediate Failover}) ทำให้ผู้ใช้แทบไม่รู้สึกว่าระบบล้มเหลวเลย

2. ระบบโคลด์สแตนด์บาย (\text{Cold Standby System}) - \text{ปานกลาง}

  • ลักษณะ: มีคอมพิวเตอร์ชุดหลักทำงานอยู่ (\text{Active}) และมีคอมพิวเตอร์สำรองอีกชุดที่ ปิดอยู่ หรือ พร้อมทำงานแต่ไม่ได้รันแอปพลิเคชันหลัก (\text{Standby}).
  • Availability: ปานกลาง เพราะเมื่อเครื่องหลักล้มเหลว จะต้องใช้ เวลาในการเปิดเครื่องสำรอง, โหลดระบบปฏิบัติการ, และเริ่มต้นแอปพลิเคชันต่างๆ (\text{Recovery Time}) ซึ่งใช้เวลานานกว่าระบบคู่ขนาน

3. ระบบเครื่องเดียว (\text{Simplex System}) - \text{ต่ำที่สุด}

  • ลักษณะ: มีคอมพิวเตอร์ทำงานเพียง 1 ชุด เท่านั้น (\text{No Redundancy}).
  • Availability: ต่ำที่สุด เพราะเมื่อเครื่องล้มเหลว จะต้องใช้เวลาในการซ่อมแซมหรือเปลี่ยนเครื่องใหม่ทั้งหมด ก่อนที่ระบบจะกลับมาใช้งานได้อีกครั้ง

ดังนั้น การเรียงลำดับจาก \text{Availability} มากที่สุดไปน้อยที่สุดคือ: \text{Dual System} \rightarrow \text{Cold Standby System} \rightarrow \text{Simplex System}

คำตอบและวิธีทำ

วิเคราะห์โจทย์

ข้อมูลที่ให้:

  • เครื่องพิมพ์พิมพ์ได้ 400 ตัวอักษร/วินาที
  • ใช้ interrupt-driven I/O
  • Interrupt handler ใช้เวลา 50 ไมโครวินาที (μs) ต่อครั้ง
  • ถาม: % เวลาว่างที่ CPU ทำงานอื่นได้

วิธีแก้ทีละขั้นตอน

ขั้นที่ 1: คำนวณเวลาต่อ 1 ตัวอักษร

ความเร็วพิมพ์ = 400 ตัวอักษร/วินาที

เวลาต่อ 1 ตัวอักษร = 1/400 วินาที
                    = 0.0025 วินาที
                    = 2,500 ไมโครวินาที (μs)

ขั้นที่ 2: วิเคราะห์ Interrupt

ทุกๆ 1 ตัวอักษร:

  • ต้องมี interrupt 1 ครั้ง (เพื่อรับตัวอักษร)
  • Interrupt ใช้เวลา 50 μs
  • เวลารอบหนึ่ง = 2,500 μs
Timeline สำหรับ 1 ตัวอักษร:
[────────────── 2,500 μs ──────────────]
[Interrupt: 50 μs][CPU ว่าง: 2,450 μs]

ขั้นที่ 3: คำนวณ % เวลา interrupt

% เวลาที่ใช้กับ interrupt = (เวลา interrupt / เวลาทั้งหมด) × 100

= (50 / 2,500) × 100
= 0.02 × 100
= 2%

ขั้นที่ 4: คำนวณ % เวลาว่าง

% เวลาว่างสำหรับทำงานอื่น = 100% - 2%
                          = 98%

:bullseye: วิธีคำนวณแบบทางลัด

เทคนิค 1: คำนวณต่อวินาที

จำนวน interrupt/วินาที = 400 ครั้ง (ตัวอักษร 400 ตัว)

เวลา interrupt ทั้งหมด/วินาที:
= 400 × 50 μs
= 20,000 μs
= 0.02 วินาที

% interrupt overhead = (0.02/1) × 100 = 2%
% เวลาว่าง = 100 - 2 = 98%

เทคนิค 2: สูตรโดยตรง

% CPU Available = 100 × [1 - (Interrupt_frequency × Interrupt_time)]

= 100 × [1 - (400/sec × 50×10⁻⁶ sec)]
= 100 × [1 - 0.02]
= 100 × 0.98
= 98%

:bar_chart: ภาพประกอบ Timeline

ใน 1 วินาที:

วินาทีที่ 1:
├─[I]─[CPU ทำงานอื่น]─[I]─[CPU ทำงานอื่น]─[I]─...─[I]─┤
  ↑                    ↑
  50μs              2,450μs

I = Interrupt (50 μs)
มี 400 ครั้งใน 1 วินาที

เวลา interrupt รวม = 400 × 50 μs = 20,000 μs = 0.02 sec
เวลาว่าง = 1 - 0.02 = 0.98 sec = 98%

:light_bulb: เทคนิคจำแบบง่าย

สูตรสำคัญ

% CPU Overhead = (Interrupts/sec × Time/interrupt) × 100

% CPU Available = 100% - % Overhead

วิธีคิด 3 ขั้นตอน

1️⃣ หาว่ามี interrupt กี่ครั้งต่อวินาที
   = ความเร็ว I/O (ในที่นี้ = 400)

2️⃣ คูณด้วยเวลาต่อ interrupt
   = 400 × 50 μs = 20,000 μs = 0.02 sec

3️⃣ เอา 1 - ผลลัพธ์ แล้วคูณ 100
   = (1 - 0.02) × 100 = 98%

:fire: ตารางสรุป

รายการ ค่า หน่วย
ความเร็วพิมพ์ 400 ตัวอักษร/วินาที
เวลาต่อตัวอักษร 2,500 μs
เวลา interrupt 50 μs
% interrupt overhead 2 %
% CPU ว่าง 98 %

:white_check_mark: ตรวจสอบคำตอบ

วิธีตรวจสอบ 1: ใน 1 วินาที

เวลาทั้งหมด = 1,000,000 μs (1 วินาที)
เวลา interrupt = 400 × 50 = 20,000 μs
เวลาว่าง = 1,000,000 - 20,000 = 980,000 μs

% = (980,000 / 1,000,000) × 100 = 98% ✅

วิธีตรวจสอบ 2: ต่อรอบ

รอบหนึ่ง = 2,500 μs
ใช้ไป = 50 μs
เหลือ = 2,450 μs

% = (2,450 / 2,500) × 100 = 98% ✅

คำตอบ: a) 98 :white_check_mark:

สรุปการคำนวณ:

ขั้นตอนสั้น:

  1. จำนวน interrupt = 400 ครั้ง/วินาที
  2. เวลา interrupt รวม = 400 × 50 μs = 20,000 μs = 0.02 วินาที
  3. % interrupt = 2%
  4. % เวลาว่าง = 98%

ความหมาย:

  • CPU ใช้เวลา 2% ในการจัดการ interrupt
  • CPU มีเวลาว่าง 98% สำหรับทำงานอื่น
  • เครื่องพิมพ์ไม่ได้กิน CPU มากนัก เพราะ I/O ช้ากว่า CPU มาก

:memo: ข้อมูลเพิ่มเติม

ทำไม Interrupt-driven I/O ถึงมีประสิทธิภาพ?

เปรียบเทียบ:

1. Polling (ถามซ้ำๆ):

CPU: "เสร็จหรือยัง?" (ถามตลอด)
Printer: "ยัง..."
CPU: "เสร็จหรือยัง?"
Printer: "ยัง..."
→ เสีย CPU 100%!

2. Interrupt-driven:

CPU: ทำงานอื่น...
Printer: "เสร็จแล้ว!" (ส่ง interrupt)
CPU: จัดการ (50 μs) แล้วกลับไปทำงานอื่น
→ เสีย CPU เพียง 2%!

สูตรทั่วไป

% CPU Overhead = (I/O_rate × Interrupt_time) × 100

% CPU Available = 100 - % Overhead

ตัวอย่าง:
- Disk: 1000 interrupts/sec × 10 μs = 1% overhead
- Network: 10000 packets/sec × 5 μs = 5% overhead
- Keyboard: 10 keys/sec × 100 μs = 0.001% overhead

หลักจำ: I/O ยิ่งช้า (เช่น เครื่องพิมพ์) → interrupt น้อย → overhead ต่ำ → CPU ว่างมาก!

คำตอบและวิธีทำ

วิเคราะห์โจทย์

Algorithm: Preemptive Shortest Remaining Time First (SRTF)

  • เลือก process ที่มี remaining time น้อยที่สุด
  • สามารถ preempt (แย่งชิง) ได้

ข้อมูล:

Process Arrival Burst
P1 0 8
P2 2 3
P3 3 7
P4 5 4

ถาม: Average Waiting Time


วิธีแก้: จำลอง SRTF Scheduling

Timeline การทำงาน

Time 0-2:

Available: P1 (remaining: 8)
Run: P1
  • P1 ทำงาน 2 หน่วย
  • P1 remaining = 8 - 2 = 6

Time 2:

P2 arrives (burst: 3)
Available: P1(6), P2(3)
Compare: 6 vs 3
Run: P2 ← เลือก P2 (shortest)
  • Preempt P1 (แย่ง P1 ออก)

Time 2-3:

Run: P2 (3 หน่วย)
  • P2 ทำงาน 1 หน่วย
  • P2 remaining = 3 - 1 = 2

Time 3:

P3 arrives (burst: 7)
Available: P1(6), P2(2), P3(7)
Compare: 6 vs 2 vs 7
Run: P2 ← ยังเป็น P2 (shortest)

Time 3-5:

Run: P2
  • P2 ทำงานต่ออีก 2 หน่วย
  • P2 เสร็จที่ time 5

Time 5:

P4 arrives (burst: 4)
Available: P1(6), P3(7), P4(4)
Compare: 6 vs 7 vs 4
Run: P4 ← เลือก P4 (shortest)

Time 5-9:

Run: P4
  • P4 ทำงาน 4 หน่วย
  • P4 เสร็จที่ time 9

Time 9:

Available: P1(6), P3(7)
Compare: 6 vs 7
Run: P1 ← เลือก P1 (shortest)

Time 9-15:

Run: P1
  • P1 ทำงานต่ออีก 6 หน่วย
  • P1 เสร็จที่ time 15

Time 15-22:

Available: P3(7)
Run: P3
  • P3 ทำงาน 7 หน่วย
  • P3 เสร็จที่ time 22

Gantt Chart

0────2────5────9────15────22
│ P1 │ P2 │ P4 │ P1 │ P3  │

คำนวณ Waiting Time

สูตร:

Waiting Time = Turnaround Time - Burst Time
Turnaround Time = Completion Time - Arrival Time

P1:

Arrival: 0
Completion: 15
Turnaround: 15 - 0 = 15
Burst: 8
Waiting: 15 - 8 = 7

P2:

Arrival: 2
Completion: 5
Turnaround: 5 - 2 = 3
Burst: 3
Waiting: 3 - 3 = 0

P3:

Arrival: 3
Completion: 22
Turnaround: 22 - 3 = 19
Burst: 7
Waiting: 19 - 7 = 12

P4:

Arrival: 5
Completion: 9
Turnaround: 9 - 5 = 4
Burst: 4
Waiting: 4 - 4 = 0

ตารางสรุป

Process Arrival Burst Completion Turnaround Waiting
P1 0 8 15 15 7
P2 2 3 5 3 0
P3 3 7 22 19 12
P4 5 4 9 4 0

คำนวณค่าเฉลี่ย

Average Waiting Time = (7 + 0 + 12 + 0) / 4
                     = 19 / 4
                     = 4.75

คำตอบ: b) 4.75 :white_check_mark:


:light_bulb: เทคนิคทำโจทย์ SRTF

ขั้นตอนการทำ:

1. เรียงตาม Arrival Time

P1(0) → P2(2) → P3(3) → P4(5)

2. จำลอง Timeline:

  • ทุกครั้งที่มี process มาถึง → เปรียบเทียบ remaining time
  • เลือก process ที่ remaining time น้อยที่สุด
  • ถ้ามี process ใหม่ที่ remaining time น้อยกว่า → preempt

3. บันทึก Completion Time ของแต่ละ process

4. คำนวณ Waiting Time:

Waiting = (Completion - Arrival) - Burst

5. หาค่าเฉลี่ย


:bullseye: เทคนิคลัด: ใช้ตาราง

Time Event Available (Remaining) Selected Reason
0 P1 arrives P1(8) P1 Only one
2 P2 arrives P1(6), P2(3) P2 3 < 6
3 P3 arrives P1(6), P2(2), P3(7) P2 2 < 6 < 7
5 P2 done, P4 arrives P1(6), P3(7), P4(4) P4 4 < 6 < 7
9 P4 done P1(6), P3(7) P1 6 < 7
15 P1 done P3(7) P3 Only one
22 P3 done - - All done

:bar_chart: Timeline รายละเอียด

Time:  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22
CPU:   P1 P1 P2 P2 P2 P4 P4 P4 P4 P1 P1 P1 P1 P1 P1 P3 P3 P3 P3 P3 P3 P3
       └─┘       └────┘ └──────┘ └──────────┘ └─────────────────────┘
        2          3        4           6                  7

P1: 0-2 (work 2), idle 2-9, 9-15 (work 6) → waiting = 7
P2: arrive 2, 2-5 (work 3) → waiting = 0
P3: arrive 3, idle 3-15, 15-22 (work 7) → waiting = 12
P4: arrive 5, 5-9 (work 4) → waiting = 0

:white_check_mark: วิธีตรวจสอบคำตอบ

ตรวจสอบ waiting time ทีละตัว:

P1 waiting = 7?

ช่วงรอ: [2-9] = 7 หน่วย ✓
(รอเพราะถูก preempt โดย P2 และ P4)

P2 waiting = 0?

Arrive 2 → Run ทันที 2-5 → ไม่รอเลย ✓

P3 waiting = 12?

Arrive 3 → รอจนถึง 15 = 12 หน่วย ✓
(รอเพราะ P2, P4, P1 ทำก่อน)

P4 waiting = 0?

Arrive 5 → Run ทันที 5-9 → ไม่รอเลย ✓

Average:

(7 + 0 + 12 + 0) / 4 = 4.75 ✓

:memo: สรุปสำคัญ

SRTF คุณสมบัติ:

:white_check_mark: Optimal - Average waiting time ต่ำสุด (ในกลุ่ม preemptive)
:white_check_mark: Preemptive - สามารถแย่งชิงได้
:warning: Starvation - process ที่ burst ยาวอาจรอนาน
:warning: Overhead - ต้องคำนวณ remaining time บ่อย

เปรียบเทียบกับ SJF:

  • SJF (Non-preemptive): ไม่แย่งชิง
  • SRTF (Preemptive SJF): แย่งชิงได้ → Average WT ดีกว่า

หลักจำ: SRTF = เลือก remaining time น้อยสุด + สามารถ preempt ได้!


คำตอบที่ถูกต้องคือ b) 4.75

คำถามนี้ต้องการหา **เวลาคอยเฉลี่ย (\text{Average Waiting Time}) ** โดยใช้การจัดลำดับแบบ เวลาที่เหลือสั้นที่สุดแบบแทรกแซงได้ (\text{Preemptive Shortest Remaining Time First - PSRTF} หรือ \text{SRTF})

วิธีทำ: การคำนวณเวลาคอยเฉลี่ย (\text{Average Waiting Time})

การจัดลำดับแบบ \text{SRTF} คือการที่ \text{Scheduler} จะเลือกทำงานกับโปรเซสที่มีเวลา \text{CPU} ที่เหลือ (Remaining Time) น้อยที่สุด ณ ขณะนั้น และสามารถแทรกแซง (\text{Preempt}) โปรเซสที่กำลังทำงานอยู่ได้ เมื่อมีโปรเซสใหม่เข้ามาและมี \text{Remaining Time} น้อยกว่า

โปรเซส (\text{P}) เวลาที่มาถึง (\text{AT}) เวลาที่ต้องการใช้ \text{CPU} (\text{BT})
\text{P1} 0 8
\text{P2} 2 3
\text{P3} 3 7
\text{P4} 5 4

1. แผนผังแกนต์ (\text{Gantt Chart})

เวลา (ms) สถานะ โปรเซสที่ทำงาน \text{Remaining Time} หมายเหตุ
0 (\text{P1} มาถึง) \text{P1} (8) \text{P1: 8}
0-2 \text{P1} \text{P1: 6}
2 (\text{P2} มาถึง) \text{P2} (3) \text{P1: 6, P2: 3} \text{P2} สั้นกว่า \text{P1} จึง \text{Preempt} \text{P1}
2-3 \text{P2} \text{P1: 6, P2: 2}
3 (\text{P3} มาถึง) \text{P2} (2) \text{P1: 6, P2: 2, P3: 7} \text{P2} สั้นที่สุด
3-5 \text{P2} \text{P1: 6, P2: 0, P3: 7} \text{P2} เสร็จสิ้นที่ \text{t=5}
5 (\text{P4} มาถึง) \text{P4} (4) \text{P1: 6, P3: 7, P4: 4} \text{P4} สั้นที่สุด
5-9 \text{P4} \text{P1: 6, P3: 7, P4: 0} \text{P4} เสร็จสิ้นที่ \text{t=9}
9 \text{P1} (6) \text{P1: 6, P3: 7} \text{P1} สั้นกว่า \text{P3}
9-15 \text{P1} \text{P1: 0, P3: 7} \text{P1} เสร็จสิ้นที่ \text{t=15}
15-22 \text{P3} (7) \text{P3: 0} \text{P3} เสร็จสิ้นที่ \text{t=22}

สรุปแผนผังแกนต์:

\text{P1} \text{P2} \text{P2} \text{P4} \text{P1} \text{P3}
0-2 2-3 3-5 5-9 9-15 15-22

2. คำนวณเวลาที่ใช้ในการประมวลผลทั้งหมด (\text{Turnaround Time})

$$\text{Turnaround Time (TT)} = \text{เวลาสิ้นสุด} - \text{เวลาที่มาถึง}$$

  • \text{P1}: \text{TT1} = 15 - 0 = 15
  • \text{P2}: \text{TT2} = 5 - 2 = 3
  • \text{P3}: \text{TT3} = 22 - 3 = 19
  • \text{P4}: \text{TT4} = 9 - 5 = 4

3. คำนวณเวลาคอย (\text{Waiting Time})

$$\text{Waiting Time (WT)} = \text{Turnaround Time} - \text{เวลาที่ต้องการใช้ } \text{CPU}$$

  • \text{P1}: \text{WT1} = 15 - 8 = 7
  • \text{P2}: \text{WT2} = 3 - 3 = 0
  • \text{P3}: \text{WT3} = 19 - 7 = 12
  • \text{P4}: \text{WT4} = 4 - 4 = 0

รวมเวลาคอยทั้งหมด: \text{Total WT} = 7 + 0 + 12 + 0 = 19 ms

4. คำนวณเวลาคอยเฉลี่ย (\text{Average Waiting Time})

$$\text{Average Waiting Time} = \frac{\text{Total Waiting Time}}{\text{จำนวนโปรเซส}}$$

$$\text{Average Waiting Time} = \frac{19}{4} = 4.75 \text{ มิลลิวินาที}$$

คำตอบที่ถูกต้องคือ d) เฉพาะไฟล์ที่มีข้อมูลระบุว่ามีการแก้ไขไฟล์เท่านั้นที่จะถูกสำรอง และข้อมูลที่ระบุว่ามีการแก้ไขไฟล์นั้นจะถูกรีเซ็ต

การวิเคราะห์วิธีการสำรองข้อมูลแบบเพิ่มส่วน (\text{Incremental Backup})

\text{Incremental Backup} (การสำรองข้อมูลแบบเพิ่มส่วน) เป็นวิธีการสำรองข้อมูลที่มุ่งเน้นการเก็บเฉพาะการเปลี่ยนแปลงที่เกิดขึ้นหลังจากรอบการสำรองข้อมูลครั้งล่าสุดเท่านั้น เทคนิคนี้มีจุดประสงค์เพื่อประหยัดพื้นที่จัดเก็บและลดเวลาที่ใช้ในการสำรองข้อมูล

กลไกการทำงาน

  1. การสำรองข้อมูล: ระบบจะทำการสำรองข้อมูล เฉพาะไฟล์ที่ถูกแก้ไข นับตั้งแต่การสำรองข้อมูลแบบเต็ม (\text{Full Backup}) หรือการสำรองแบบเพิ่มส่วน (\text{Incremental Backup}) ครั้งล่าสุด โดยอ้างอิงจาก \text{Archive Bit} (บิตระบุการเก็บถาวร) ซึ่งเป็น \text{flag} สถานะของไฟล์
  2. การจัดการ \text{Archive Bit}:
    • เมื่อไฟล์ถูกสร้างหรือแก้ไข ระบบปฏิบัติการจะ ตั้งค่า \text{Archive Bit} เป็น \text{ON} (หรือ \text{Set}) เพื่อระบุว่าไฟล์นี้ต้องการการสำรองข้อมูล
    • เมื่อโปรแกรมสำรองข้อมูลทำการสำรองไฟล์นั้นเสร็จสิ้นแล้ว จะต้อง รีเซ็ต (\text{Clear}) \text{Archive Bit} เป็น \text{OFF} เพื่อระบุว่าไฟล์นี้ถูกสำรองไปแล้ว และพร้อมสำหรับการเปลี่ยนแปลงครั้งถัดไป

การวิเคราะห์ตัวเลือก

ตัวเลือก การสำรองข้อมูล การจัดการ \text{Archive Bit} สอดคล้องกับ \text{Incremental Backup}
a) \text{ไฟล์ทั้งหมด...} ผิด (ถ้าทั้งหมดจะกลายเป็น \text{Full Backup}) \text{คงไว้ดังเดิม} ผิด
b) \text{ไฟล์ทั้งหมด...} ผิด \text{ถูกรีเซ็ต} ผิด
c) \text{เฉพาะไฟล์ที่ถูกแก้ไขเท่านั้น} ถูกต้อง \text{คงไว้ดังเดิม} ผิด (ถ้าไม่รีเซ็ต จะสำรองไฟล์เดิมซ้ำในการสำรองครั้งถัดไป)
d) \text{เฉพาะไฟล์ที่ถูกแก้ไขเท่านั้น} ถูกต้อง \text{ถูกรีเซ็ต} ถูกต้อง (เป็นการเตรียมพร้อมสำหรับการเปลี่ยนแปลงครั้งต่อไป)

ดังนั้น \text{Incremental Backup} จะสำรอง เฉพาะไฟล์ที่มีการแก้ไข (ซึ่งดูจาก \text{Archive Bit} ที่ \text{Set}) และ รีเซ็ต \text{Archive Bit} นั้น เพื่อรอการแก้ไขใหม่