Skip to Content
CoursesCSC102การพิมพ์ข้อความในรูปแบบซิกแซก

การพิมพ์ข้อความในรูปแบบซิกแซก

โจทย์

กำหนดสตริงและจำนวนเต็มหนึ่งค่า เขียนโปรแกรมที่จะแปลงสตริงนั้นให้อยู่ในรูปแบบซิกแซกตามจำนวนแถวที่กำหนด สตริงจะถูกอ่านทีละแถวเพื่อสร้างสตริงที่แปลงแล้ว โปรแกรมควรรับสตริงและจำนวนเต็มเป็นอินพุต สตริงควรถูกจัดเรียงให้อยู่ในรูปแบบซิกแซกข้ามแถวตามจำนวนแถวที่กำหนด เช่น หากกำหนดสตริงเป็น “PAYPALISHIRING” และ numRows = 3

InputOutput
PAYPALISHIRING
3
PAHNAPLSIIGYIR

โค้ด

import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String text = scanner.nextLine(); int rows = scanner.nextInt(); if (rows == 1) { System.out.println(text); } else { for (int i = 0; i < rows; i++) { int spacer = rows - i; int n = 0; int extractIndex = i; while (extractIndex < text.length()) { char c = text.charAt(extractIndex); System.out.print(c); n++; extractIndex = (i == 0 || i == rows - 1) ? extractIndex + rows + 1 : spacer * n + 1; } } } } }

คำอธิบาย

ขั้นตอนที่ 1: การเริ่มต้นโปรแกรม

import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in);
  • โค้ดเริ่มต้นด้วยการ import คลาส Scanner ซึ่งเป็นเครื่องมือที่ช่วยให้เราสามารถรับข้อมูลจากผู้ใช้ได้
  • เราสร้างคลาสชื่อ Main และกำหนดเมธอด main ซึ่งเป็นจุดเริ่มต้นของโปรแกรม
  • เราสร้างตัวแปร scanner เพื่อใช้รับข้อมูลจากผู้ใช้

ขั้นตอนที่ 2: การรับข้อมูลจากผู้ใช้

String text = scanner.nextLine(); int rows = scanner.nextInt();
  • เราใช้ scanner.nextLine() เพื่อรับข้อความจากผู้ใช้ และเก็บไว้ในตัวแปร text
  • เราใช้ scanner.nextInt() เพื่อรับจำนวนแถวจากผู้ใช้ และเก็บไว้ในตัวแปร rows

ขั้นตอนที่ 3: การตรวจสอบกรณีพิเศษ

if (rows == 1) { System.out.println(text); } else { // โค้ดสำหรับกรณีที่มีมากกว่า 1 แถว }
  • ถ้าจำนวนแถวเป็น 1 เราแค่แสดงข้อความเดิมออกมา เพราะไม่ต้องจัดรูปแบบใหม่
  • ถ้าไม่ใช่ เราจะดำเนินการจัดรูปแบบซิกแซก

ขั้นตอนที่ 4: การจัดรูปแบบซิกแซก

for (int i = 0; i < rows; i++) { int spacer = rows - i; int n = 0; int extractIndex = i; while (extractIndex < text.length()) { char c = text.charAt(extractIndex); System.out.print(c); n++; extractIndex = (i == 0 || i == rows - 1) ? extractIndex + rows + 1 : spacer * n + 1; } }

นี่คือส่วนหลักของโปรแกรม ที่ทำการจัดรูปแบบซิกแซก:

  1. เราวนลูปตามจำนวนแถว (rows)
  2. สำหรับแต่ละแถว:
    • เราคำนวณ spacer ซึ่งเป็นระยะห่างระหว่างตัวอักษรในแถวนั้นๆ
    • เราใช้ extractIndex เพื่อเก็บตำแหน่งของตัวอักษรที่จะดึงออกมา
    • เราวนลูปภายในเพื่อดึงตัวอักษรจากข้อความเดิม:
      • ดึงตัวอักษรและแสดงผล
      • คำนวณตำแหน่งถัดไปที่จะดึงตัวอักษร:
        • สำหรับแถวแรกและแถวสุดท้าย: ข้ามไป rows + 1 ตำแหน่ง
        • สำหรับแถวอื่นๆ: ใช้สูตร spacer * n + 1

ทำไมต้องใช้ extractIndex?

extractIndex เป็นตัวแปรสำคัญในการแปลงข้อความเป็นรูปแบบซิกแซก มันทำหน้าที่เป็น “ตัวชี้” ที่บอกว่าเราควรดึงตัวอักษรจากตำแหน่งใดในข้อความต้นฉบับ การใช้ extractIndex ช่วยให้เราสามารถ:

  1. เลือกตัวอักษรที่ถูกต้องสำหรับแต่ละตำแหน่งในรูปแบบซิกแซก
  2. ข้ามตัวอักษรที่ไม่ควรอยู่ในแถวปัจจุบัน
  3. สร้างรูปแบบซิกแซกโดยไม่ต้องสร้างตารางจริงๆ ซึ่งประหยัดหน่วยความจำ

วิธีการทำงานของ extractIndex

extractIndex = (i == 0 || i == rows - 1) ? extractIndex + rows + 1 : spacer * n + 1;

นี่คือส่วนสำคัญที่คำนวณ extractIndex ถัดไป มาดูวิธีการทำงานกัน:

กรณีที่ 1: แถวแรกและแถวสุดท้าย (i == 0 หรือ i == rows - 1)

สำหรับแถวแรกและแถวสุดท้าย เราใช้:

extractIndex = extractIndex + rows + 1
  • ทำไม? เพราะในแถวแรกและแถวสุดท้าย ตัวอักษรจะห่างกันเท่าๆ กันเสมอ
  • ระยะห่างนี้เท่ากับ rows + 1 เพราะ:
  • rows คือจำนวนแถวทั้งหมด
  • +1 เพราะเราต้องนับรวมตัวอักษรในแถวปัจจุบันด้วย

ตัวอย่าง: ถ้า rows = 3 ตัวอักษรในแถวแรกจะห่างกัน 4 ตำแหน่ง (3 + 1)

กรณีที่ 2: แถวกลาง (i ไม่ใช่ 0 และไม่ใช่ rows - 1)

สำหรับแถวกลาง เราใช้:

extractIndex = spacer * n + 1
  • spacer = rows - i คือระยะห่างระหว่างตัวอักษรในแถวนั้นๆ
  • n เป็นตัวนับว่าเรากำลังหาตัวอักษรตัวที่เท่าไหร่ในแถวนั้น
  • +1 เพื่อปรับให้ตรงกับตำแหน่งจริงในข้อความ (เพราะข้อความเริ่มที่ตำแหน่ง 0)

ทำไมต้องใช้สูตรนี้? เพราะในแถวกลาง ตัวอักษรจะสลับระหว่าง “ลงมา” และ “ขึ้นไป” ในรูปแบบซิกแซก

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

สมมติว่าเรามีข้อความ “PAYPALISHIRING” และ rows = 3

  1. แถวที่ 1 (i = 0):
  • ตัวอักษร: P _ _ A _ _ H _ _ N
  • extractIndex: 0, 4, 8, 12 (ห่างกัน 4 ตำแหน่ง)
  1. แถวที่ 2 (i = 1):
  • ตัวอักษร: A _ P _ L _ S _ I _ G
  • extractIndex: 1, 3, 5, 7, 9, 11, 13 (สลับระหว่างห่าง 2 และ 4 ตำแหน่ง)
  1. แถวที่ 3 (i = 2):
  • ตัวอักษร: Y _ _ I _ _ R
  • extractIndex: 2, 6, 10 (ห่างกัน 4 ตำแหน่ง)

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

ปรับปรุงล่าสุด