[KubeOps Academy] Palindrome with Rust ทำยังไงนะ!?
Tags: rust, algorithms
Published: 2022-01-17 13:02:57

อยากให้ทุกคนลองเขียนชื่อตัวเองจาก หลังไปหน้า แล้วอ่านดู... อ่านรู้เรื่องกันมั้ยครับ? แล้วเคยสงสัยมั้ย ว่าทำไมชื่อคนบางคนไม่ว่าจะอ่านจากหลังไป

## อะไรคือ palindrome?
Palindrome คือ ประโยคหรือคำ ทั้งในเชิงอักษร (ABC, abc) ตัวเลข (123321) และตัวอักขระ ที่เรียงต่อกันแล้วสามารถอ่านแล้วได้ความหมายเดิม ทั้งจากหลังไปหน้า และหน้าไปหลัง

ในทางคอมพิวเตอร์ ได้มีการทำ Palindrome มาใช้สำหรับการบีบอัด (Compression) DNA อีกด้วย [อ่านต่อ](https://www.researchgate.net/publication/343284206_A_Compression_Algorithm_for_DNA_Palindrome_Compression_Technique)
Why rust?

## เราจะแก้โจทย์ Palindrome ได้อย่างไร?
การแก้ Palindrome นั้นมีวิธีคิดได้หลากหลายในทางกระบวนการวิธี เช่น ตัดครึ่งคำ จากนั้นนำฝั่งซ้าย - ขวา มาทาบกัน โดยบทความนี้จะนำวิธีการ ไล่คำจากด้านหลังและด้านหน้าทีละตัวอักษรพร้อมๆ กัน เพื่อเปรียบเทียบว่าเป็น Palindrome หรือป่าว

## แนวคิด

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ga1ja6gupiwm2j5zh2m8.png)

จากภาพด้านบน ให้ลองคิดว่า ให้

1. เรานำปากกา 2 ด้านมาวางไว้ที่ปลายสุดของทั้งสองฝั่ง
2. จากนั้นให้เปรียบเทียบตัวอักษรที่ปลายของปากกาทั้งสอง 
3. เมื่อเปรียบเทียบแล้ว ให้ขยับปากกาเข้าหากัน 
4. เปรียบเทียบ ทำเช่นนี้ไปเรื่อยๆ
5.1 หากรอบใดที่ปลายตัวอักษรปลายปากกาไม่เท่ากัน สรุปได้ว่าคำนั้น **ไม่ใช่** Palindrome
5.2 หากว่าเปรียบเทียบหมดแล้ว ตัวอักษรทุกตัวเท่านั้น สรุปได้ว่า **คำนั้นคือ Palindrome**

## ลงมือเขียน Code กัน!!
โดยเราจะใช้ ภาษา Rust ซึ่งเป็นภาษา System Programming หนึ่งที่ค่อนข้างฝึกให้เราคิดถึง process เบื้องหลังการทำงานของ Computer 

Import การจัดการ input/output ของภาษา Rust

```use std::io::stdin;```

ภายใน Function main ซึ่งถือเป็น function หลักของโปรแกรม เราจะแสดงข้อความออกทาง terminal ให้ผู้ใช้งานเข้าใจการทำงานคร่าวๆ และถ้าพร้อมให้ผู้ใช้พิมพ์คำที่อยากเช็ค Palindrome ลงมา
```
println!("Palindrome.");
    println!("If you want to exit. please type ==> :q\n");
    loop {
        let mut pre_string = String::new();
        println!("Please input your thing ==>");
        stdin().read_line(&mut pre_string).expect("Please put correct string.");
        
        let string: &str = &pre_string.trim().replace(" ", "");
        if string.to_uppercase() == END_GAME {
            println!("==========");
            println!("THANK YOU.");
            println!("==========");
            break;
        }
        if string == "" {
            println!("Please put correct string!\n");
            continue;
        }

        let is_palindrome: bool = check_palindrom(string);

        println!("is {} Palindrome? : {}\n", string, match is_palindrome { true => "YES", false => "NO" });
    }
```

โดยจะทำการ loop วนจนกว่าผู้ใช้งานพิมพ์คำว่า "END" จึงจะหยุดการทำงาน

โดยขออธิบายการทำงานของ check_palindrome function สำหรับเช็ค palindrome ตามด้านล่าง

```
fn check_palindrom(string: &str) -> bool {
    let mut is_palindrome: bool = true;
    for (c1, c2) in string.chars().zip(string.chars().rev()) {
        if c1 != c2 {
            is_palindrome = false;
        }
    }
    return is_palindrome;
}
```

วิธีการทำงานจะเหมือนแนวคิดด้านบน นั้นคือสร้าง loop ทั้งคำ จากนั้นให้มี c1 และ c2 โดยที่ c1 ชี้ที่ด้านซ้ายสุด และ c2 ชี้ด้านขวาสุด โดยใน ภาษา rust นั้นการทำ indexing ใน string จะมีความท้าทาย ทางผู้เขียนจึงใช้วิธีสร้าง string ขึ้นมา 2 ตัว โดย ชุดแรกเป็นคำเดิม แต่ ชุดที่สอง จะเป็นคำที่กลับด้าน จากนั้นให้ c1 loop ผ่านชุดแรก และ c2 loop ผ่านชุดที่สอง

และหากว่าทุกคำเท่ากัน จะถือว่าคำนั้นเป็น palindrome ด้วยการ return true ถือเป็นการจบกระบวนการเช็ค Palindrome

## สรุปและต่อยอด
โดยจริงแล้ว Palindrome จะเหมาะกับการแก้ปัญหาสิ่งที่เป็น sequence ต่อกันและสามารถ map เข้าหากันได้จากด้านหน้าและด้านหลัง ซึ่งวิธีการเช็ค Palindrome ในบทความนี้ต้องการนำเสนอ แนวคิดการเช็คแบบไล่ หัว-ท้าย โดยไม่ต้องตัดคำตรงกลางทิ้ง ทุกคนคิดเห็นอย่างไรมาแบ่งปันกันได้นะครับ

------------------------------------

> KubeOps Academy คือ Long-Term Program ที่อยากสร้าง Cloud Native จาก Zero to Workforce. หากสนใจกิจกรรมอื่นๆ ที่น่าสนใจ ของ Community สามารถติดตามต่อได้ที่ [KubeOps Skills](https://www.facebook.com/kubeOpsSkills) ครับ