March 26, 2012

Python: เรียงลำดับข้อมูล

การเรียงลำดับข้อมูลใน Python นั้น มีเครื่องมือที่ช่วยอำนวยความสะดวกคือ sorted และ list.sort

ความแตกต่างของสองตัวนี้ คือ sorted จะมองแบบ functional ได้ของใหม่ออกมา (โดยที่ของเก่าไม่เปลี่ยนค่า) ส่วน list.sort จะมองแบบ OOP คือเข้าไปเปลี่ยนแปลงการเรียงลำดับในตัว list object

หรือถ้าจะเรียงจากมากไปน้อย

สิ่งที่ต้องระวังคือ สมาชิกแต่ละตัวใน list ต้องอยู่ในรูปแบบของข้อมูลที่สามารถนำมาเปรียบเทียบมากกว่า-น้อยกว่าได้ (อย่าง [1, 2, 'a'] หมดสิทธิ์)



ตัวเลือกอีกตัวคือ key ที่ใช้ในการเปรียบเทียบ ซึ่งทำได้โดยส่งผ่านฟังก์ชันที่รับค่า 1 ตัวแปรเข้าไปเป็น key



ข้อมูลทางเทคนิคคือการเรียงลำดับจะใช้อัลกอริทึม Timsort ซึ่งมีประสิทธิภาพที่ O(n log n) และเป็นแบบ stable (สมาชิกหลังการจัดเรียงแล้วยังคงลำดับเดิมอยู่) ครับ

March 24, 2012

PHP: วัน และเวลา

ฟังชั่นที่แสดงวัน และเวลาออกมาใน PHP จะใช้ date()
string date ( string $format[, int $timestamp = time() ] )
$format เป็นตัวกำหนดให้แสดงวัน และ/หรือเวลาออกมาในรูปแบบต่าง ๆ สามารถรายละเอียดของตัวอักษรที่ใช้แสดงผลได้จาก function.date นอกจากจะเขียนรูปแบบเองแล้ว PHP ยังเตรียมรูปแบบที่ใช้บ่อย (ในงานเบื้องหลัง) ไว้ให้บางส่วน
  • DATE_RSS: รูปแบบที่ใช้สำหรับ RSS (Sat, 24 Mar 2012 12:23:34 +0700)
  • DATE_COOKIE: รูปแบบที่ใช้สำหรับ cookie (Saturday, 24-Mar-12 12:23:34 ICT)
  • DATE_W3C: รูปแบบตาม W3C (2012-03-24T12:23:34+07:00)
ส่วนที่เหลือดูจาก class.datetime $timestamp ใช้สร้างวันเวลาขึ้นมาแสดงผล ผ่านฟังชั่น mktime() และ strtotime()
int mktime (
     [  int $hour = date("H")
     [, int $minute = date("i")
     [, int $second = date("s")
     [, int $month = date("n")
     [, int $day = date("j")
     [, int $year = date("Y") ]]]]]] )

int strtotime ( string $time [, int $now = time() ] )
ผลของทั้ง 2 ฟังชั่นเหมือนกันคือได้ unix timestamp เหมือนกัน แต่ mktime() จะรับค่าเป็นตัวเลขระบุเจาะจง ส่วน strtotime() จะรับค่าเป็นข้อความได้

สำหรับ $now ใน strtotime() คือ เวลาที่เริ่มต้นคำนวณ หากระบุค่าของ $time เป็นข้อความสัมพันธ์กับการเพิ่มลดเวลา แม้ว่า strtotime() จะสามารถพิมพ์เป็นภาษาที่มนุษย์เข้าใจได้ทันที แต่ว่าให้ระวังเรื่อง วัน-เดือน-ปี ที่เป็นตัวเลขจำนวนน้อย ๆ เช่น 10-11-12 เพราะบอกยากว่าแท้ที่จริงแล้วเป็นวันที่เท่าไหร่กันแน่ ทาง PHP จะทึกทักเอาเองว่า ถ้าคั่นด้วย / จะเป็นแบบอเมริกัน (m/d/y) แต่ถ้าคั่นด้วย - หรือ . จะเป็นแบบยุโรป (d-m-y) ทางออกที่ดีคือใช้มาตรฐาน ISO 8601 (YYYY-MM-DD) แทน

ฟังชั่นอื่น ๆ ที่เกี่ยวกับ วัน และเวลา ยังมีอีกมากสามารถอ่านเพิ่มได้จาก ref.datetime

March 21, 2012

PHP: รับข้อมูลจาก form

ในครั้งก่อน ๆ จะเป็นการทำงานเฉพาะส่วนของ PHP ไม่มีการรับค่าจากผู้ใช้ ส่วนอันนี้จะพูดถึงการรับค่าจากผู้ใช้ผ่าน <form> ของ HTML กันบ้าง

การส่งค่าจาก <form> จะส่งมายังเซิฟเวอร์ได้ 2 แบบคือ
  • get: ข้อมูลจะถูกส่งผ่าน URL ทำให้มองเห็นได้ทุกคน และจำกัดปริมาณการส่ง
  • post: ข้อมูลที่ส่งจะมองไม่เห็น (ง่าย ๆ) และ (เกือบ) ไม่จำกัดปริมาณการส่ง (ขึ้นอยู่กับค่า post_max_size ในไฟล์ php.ini)
จะส่งค่าแบบใดนั้น ขึ้นอยู่กับข้อมูลที่จะส่ง ถ้าไม่เป็นความลับ หรือต้องการให้มีการคัดลอก URL แล้วเอาไปใช้ได้โดยไม่จำเป็นต้องกรอกข้อมูลอีกก็ใช้ get ไป แต่ถ้าข้อมูลนั้นเป็นความลับ หรือมีปริมาณมาก ๆ ก็ส่งผ่าน post โดยกำหนดค่า method ส่วน action คือไฟล์ .php ที่จะให้ประมวลผลข้อมูลจาก <form> อันนี้ ส่วนการนำค่ามาใช้งานนั้นจะใช้ผ่าน $_GET สำหรับ get และใช้ $_POST สำหรับ post ซึ่งเป็น associative array มี key เป็น name ของ <input> อันนั้น ๆ

ทั้ง $_GET และ $_POST ถือเป็นตัวแปรแบบ superglobal ที่เรียกใช้ได้ทุกที่ตลอดเวลา แตกต่างจากตัวแปรแบบ global ตรงที่ไม่ต้องใส่ global นำก่อนจะใช้งาน นอกจากนี้ยังมี $_REQUEST ที่เก็บค่าทั้งของ $_POST, $_GET และ $_COOKIE ไว้ด้วยกัน แต่เสี่ยงที่จะถูกโจมตี จึงไม่แนะนำให้ใช้

และสิ่งสำคัญอีกอย่างคือ ควรจะตรวจสอบความถูกต้อง (validation) ของค่าที่ได้จากผู้ใช้ และ/หรือแปลงค่า (cast) ให้ถูกต้องก่อนจะนำมาใช้งานเสมอ จะเต็มรูปแบบหรือคร่าว ๆ ก็แล้วแต่ความเหมาะสม และหากใช้ค่าที่รับมากับฐานข้อมูล หรือส่งต่อให้ระบบอื่น ๆ ควรจะเรียกใช้ฟังชั่น string escape ที่เกี่ยวข้องเสียก่อนทุกครั้ง ซึ่งจะป้องกันการโจมตีได้ระดับหนึ่ง

March 16, 2012

Python: ใช้ทศนิยมแบบ decimal และ fractions

การจัดการเลขทศนิยมในคอมพิวเตอร์ส่วนมาก จะใช้ floating point แบบ IEEE 754 ทำให้ความแม่นยำในหลักท้ายๆ หายไปเสมอ เช่น



ทางแก้นอกจากจะปัดเศษตามข้างต้นแล้ว ยังมี decimal เมื่อต้องการค่าที่แม่นยำครับ

ค่าปริยายของตำแหน่งทศนิยมอยู่ที่ 28 หลัก คือ

จะเห็นว่าเมื่อนำมาคำนวณ ความแม่นยำจะถอยกลับมาที่ 28 ตำแหน่ง ถ้าต้องการความละเอียดมากกว่านั้น

และการเปลี่ยนวิธีการปัดค่าตัวท้าย



ส่วน fractions เป็นการเก็บเศษส่วนที่เขียนได้ในรูปของจำนวนเต็มหารกัน (จำนวนตรรกยะ) วิธีใช้คือ

แม้ว่า fractions จะไม่สูญเสียความแม่นยำเลย แต่มันก็ไม่สามารถเก็บจำนวนอตรรกยะ (อย่างเช่น sqrt(2)) ก็เลือกใช้เครื่องมือเหล่านี้ให้ถูกงานนะครับ

March 14, 2012

PHP: Function

ฟังชั่น (function) จะแบ่งเป็น 2 ประเภทคือ
  • ฟังชั่นที่มากับตัวภาษา (built-in function) เช่น abs(), max(), min()
  • ฟังชั่นที่สร้างขึ้นเอง
ในที่นี้จะพูดถึงการสร้างฟังชั่นขึ้นมาใช้เอง ส่วน built-in function ดูได้จาก W3School (แต่อาจจะนำมาเขียนถึงในบางฟังชั่น)

การสร้างฟังชั่น จะมีรูปแบบประมาณนี้ ตัวอย่างการสั่งพิมพ์ข้อความโดยไม่มีการส่งค่า และคืนค่า สำหรับการส่งค่าไปยังฟังชั่น สามารถสั่งได้ 2 แบบคือ
  • By Value เป็นส่งค่าของตัวแปรไปให้ ซึ่งค่าที่ถูกแก้ไขในฟังชั่นจะไม่ทำให้ค่าของตัวแปรที่ส่งเปลี่ยนแปลงไป
  • By Reference เป็นส่งตำแหน่งอ้างอิงของตัวแปรไปให้ ซึ่งทำให้ค่าของตัวแปรที่ส่งเปลี่ยนแปลงไป การส่งค่าแบบ by reference จะใช้ & นำหน้าชื่อตัวแปร
นอกจากนี้ยังกำหนดค่าโดยปริยาย (default) ให้กับพารามิเตอร์ของฟังชั่นได้โดยใช้ = ส่วนมากมักจะใส่ตัวแปรที่มีค่าโดยปริยายไว้หลังสุด การคืนค่าจากฟังชั่น ใช้ return return จะถือว่าเป็นการจบการทำงานของฟังชั่นนั้น เมื่อเจอ return โค้ดที่อยู่หลัง return จะไม่ถูกเรียกใช้งาน จึงสามารถนำไปประยุกต์ให้หยุดการทำงานของฟังชั่นเมื่อพบข้อผิดพลาดได้ ใช้ฟังชั่นเมื่อไหร่? ใช้เมื่อรู้สึกว่า จะต้องเขียนชุดคำสั่งเดิม ๆ มากกว่า 1 ครั้ง จำไว้ว่า โปรแกรมเมอร์นั้นขี้เกียจ เราจะไม่เขียนชุดคำสั่งเดิม ๆ ซ้ำเป็นครั้งที่ 2 (ที่จริง เพื่อให้แก้ไขจัดการง่าย ถ้าหากโค้ดมีบั๊ก แก้ที่เดียวจบ)

March 12, 2012

Python: โครงสร้างข้อมูลชุดแบบอื่นๆ จาก collections

นอกจาก list, dictionary, tuple และ set แล้ว ยังมีโครงสร้างข้อมูลชุดแบบอื่นๆ เช่น

deque ที่ทำความเร็วได้ดีกว่าการใช้ list.append(elem) และ list.pop(0) สร้างคิวเอง

อีกประเด็ตที่น่าสนใจคือ deque สามารถจำกัดขนาดได้ครับ

ระวังไว้หน่อยตอนที่เพิ่มค่าเข้าไปจนล้น มันไม่ได้คืนตัวที่โดนปัดทิ้งให้นะ



defaultdict ที่จะสร้างค่าเริ่มต้นให้เสมอเมื่อเรียกใช้ index ตัวที่ยังไม่มีใน dict

และจะเห็นความง่ายของมันเมื่อสร้าง dict ที่เก็บ list ของ key ที่ซ้ำกันได้



namedtuple สำหรับสร้าง tuple ที่มีชื่อสำหรับเรียกแทนตัวแปรต่างๆ (หรืออาจมองว่ามันเป็น struct ที่สามารถเรียกตำแหน่งได้จากทั้งตำแหน่งและชื่อก็ได้)

สังเกตความสะดวกในการประกาศตัวแปรชุด xyz นะครับ

March 9, 2012

Python: วัดประสิทธิภาพ code ด้วย timeit

ก่อนที่จะวัดความเร็ว มี 2 ฟังก์ชันที่ควรรู้จักคือ eval และ exec ซึ่งจะทำการรับ code ที่เก็บเป็น string มารัน

ความแตกต่างคือ eval จะสามารถใช้ได้กับ expression เท่านั้น ไม่สามารถใช้กับ statement ได้ (คือไม่สามารถกำหนดค่าให้กับตัวแปรได้นั่นเอง)



การวัดความเร็วสามารถทำได้โดยฟังก์ชัน timeit จากโมดูล timeit โดยส่งผ่าน code เข้าไปเช่นนี้

ตัวเลือกหนึ่งที่น่าสนใจคือ number ซึ่งหมายถึงรอบที่ใช้ทดลองเพื่อหาเวลารวม (ค่าปริยายคือหนึ่งล้าน) ถ้ารู้สึกว่าใช้เวลาทดลองนานเกินไปก็ลดรอบได้

ส่วนการจะทดสอบ function ที่เขียนไว้ล่วงหน้าแล้ว ก็ทำได้ผ่านการ setup เช่นนี้



หรือถ้าหากต้องการทดสอบจาก shell ก็สามารถสั่งแบบนี้ได้

สังเกตว่ารูปแบบการพิมพ์ผลลัพท์ที่ได้จะต่างออกไปเล็กน้อยนะครับ

March 8, 2012

Visual Basic: ฟังก์ชันและการทำงานย่อย

การทำงานย่อยใน Visual Basic สามารถแบ่งได้เป็น 2 อย่างคือ Function และ Sub

ความแตกต่างคือ Function เป็นการทำงานย่อยที่ (ควรจะ) ส่งค่าแบบ ByVal (ส่งค่าของตัวแปรเข้าไป ถ้ามีการเปลี่ยนค่าระหว่างทำงาน ตัวแปรต้นทางจะไม่เปลี่ยน) และเมื่อทำงานเสร็จเรียบร้อยก็ (ควรจะ) ส่งค่าคืนกลับมา เช่น

หรือถ้าจะแหกฎนั้น

สังเกตว่าต้องมีการคืนค่าเสมอนะครับ (แม้จะเขียนโดยที่ไม่ให้คืนค่าก็ตาม)



ส่วนการใช้ Sub จะถูกมองคล้ายๆ การแยกส่วนของ code ออกเป็นหลายๆ ส่วน ตัวแปรส่วนใหญ่ส่งเข้าไปแบบ ByRef (เมื่อเปลี่ยนค่าตัวแปร ตัวแปรที่ต้นทางจะเปลี่ยนด้วย) และเมื่อทำงานเสร็จจะไม่มีการคืนค่าครับ

ความแตกต่างอีกอย่างคือการที่ Sub สามารถ Handles เหตุการณ์ต่างๆ เช่นการคลิกเมาส์ได้ โดยเปลี่ยนไปส่งผ่านตัวแปรที่เกี่ยวกับ event 2 ตัวแทน (ซึ่งจะเหมือนกับการดับเบิลคลิกเข้าไปเขียน code) ดังนี้

(อันที่จริงแล้ว Function ก็ Handles ได้ แต่มักไม่ทำกัน เพราะผิด concept)

สรุปคือตัดสินใจจากสถานการณ์นั้นๆ ว่าจะใช้ Function (มีการคืนค่า) หรือจะใช้ Sub (จัดระเบียบ code, อิงกับ event ภายนอก) ให้เหมาะกับงานด้วยนะครับ

March 7, 2012

PHP: วนรอบ

การวนรอบ (loop) ใน PHP มี 4 แบบ คือ
  • while ตรวจสอบ แล้วค่อยวนรอบ
  • do...while ทำก่อน 1 ครั้งแล้วค่อยตรวจสอบ
  • for วนรอบตามจำนวนที่กำหนด
  • foreach วนรอบตามจำนวน element ใน array


while

while จะตรวจสอบค่าก่อน หากเป็นจริง จึงวนทำตามคำสั่งภายใน หากเป็นเท็จก็จะไม่วนรอบนั้น ๆ มักใช้ในกรณีที่ไม่รู้จำนวนรอบที่แน่นอน หรือไม่ต้องการหาจำนวนรอบก่อนที่จะวน เช่น วนรอบแสดงข้อมูลจากไฟล์ หรือฐานข้อมูลเป็นต้น while สามารถเขียนได้ 2 แบบ เช่นเดียวกับ switch


do...while

do...while จะทำตามคำสั่งใน do ก่อน 1 ครั้งแล้วค่อยตรวจสอบ หากยังเป็นจริงก็ทำใน do อีก โดยทั่วไปแล้วแทบไม่ต่างจาก while เลย แต่การใช้ do...while เพื่อให้มั่นใจว่า คำสั่งใน loop จะถูกสั่งแน่ ๆ อย่างน้อย 1 ครั้ง

for

for จะวนตามจำนวนที่ระบุเอาไว้จนครบแล้วออกจากการวนรอบ มักใช้ในการวนรอบที่มีจำนวนแน่นอนซึ่งต่างจาก while และ do...while ที่มักใช้กับจำนวนรอบที่ไม่แน่นอน forสามารถเขียนได้ 2 แบบเหมือนกับ while

foreach

foreach ใช้ในการวนดูข้อมูลใน array เป็นหลัก เขียนได้ 2 แบบเช่นกัน

break และ continue

break จะเป็นการออกจากการวนรอบก่อนที่จะครบตามที่กำหนดไว้ continue จะข้ามรอบนั้น ๆ ไป แต่ยังวนรอบอยู่เหมือนเดิม

สรุปเรื่องคำสั่งทางเลือก

จากบทความเรื่อง if...else และ switch กับเรื่องการวนรอบ จะเห็นว่า ใน PHP จะมีคำสั่ง หรือ syntax ทางเลือกอยู่หลายแบบ สรุปรวมเท่าที่เขียนมาทั้งหมดจะมี
  • if...else ที่ใช้ if (): (ร่วมกับ else: และ/หรือ elseif ():) และปิดด้วย endif;
  • switch ที่ใช้ switch (): และปิดด้วย endswitch;
  • while ที่ใช้ while (): และปิดด้วย endwhile;
  • for ที่ใช้ for (): และปิดด้วย endfor;
  • foreach ที่ใช้ foreach (): และปิดด้วย endforeach;

Visual Basic: ตัวแปรชุดแบบอาเรย์

แนวคิด array ใน Visual Basic อาจมองได้ว่ามันเป็น object ที่เรียกใช้ attribute เป็นตัวเลขก็ได้

สังเกตว่า การประกาศขนาด array จะบอกเป็นขนาดลบด้วยหนึ่ง ถ้ากลัวงง จะไม่ประกาศขนาด array ก็สามารถทำเช่นนี้ได้

และ attribute ประจำ array ที่ควรรู้ก็คือ



สำหรับ array ในหลายมิติ ก็ใช้เครื่องหมาย , คั่นแต่ละมิติออกจากกัน

แต่คราวนี้ การใช้ตรวจสอบขนาดโดยใช้ Length จะให้ผลลัพท์ที่ประหลาดแล้ว ถ้าต้องการขนาดของ array ในมิติย่อยๆ ให้ใช้ GetLength แทน

March 3, 2012

ร้อยไลค์

นับตั้งแต่วันที่ปัดฝุ่นเว็บ ขอจดไว้ว่า เราบรรลุ milestone แรกที่ 100 like แล้วครับ!

สถิติเล็กน้อยๆ
  • ใช้เวลาเก็บ achievement นี้ไป 129 วัน
  • รวมได้ 9,142 visits และ 13,755 pageviews
  • new/return visitor อยู่ที่ 55% ต่อ 45%
  • ใช้ Chrome เข้ากันถึง 57% เลย! ส่วน Firefox ก็ 27%
  • Windows 78%, Mac 10%, Linux 7%
  • traffic 92% มาจาก Blognone (ขอขอบคุณมา ณ ที่นี้ด้วย)

let's code: ย่อโปรแกรมให้สั้นที่ 140byt.es

140byt.es เป็นเว็บที่เกิดจากกลุ่มผู้ใช้งานทวิตเตอร์ เล่นสนุกกันโดยการเขียน code สั้นๆ แล้วทวีต (เพราะทวิตเตอร์อนุญาตให้ใช้ได้แค่ 140 ตัวอักษรต่อทวีต) ดังนั้นหลายๆ อันก็ต้องลงมือเขียนแบบ obfuscate กันเลยทีเดียว นับได้ว่าเป็นการฝึกพลังลมปราณอย่างหนึ่งนะครับ ;D

ความแตกต่างที่น่าสนใจจากที่อื่นๆ คือ ไม่มีโจทย์ตายตัวว่าจะต้องเขียนโปรแกรมอะไร ย่อให้ได้สั้นเท่าไหร่ แต่ขึ้นอยู่กับเราเลยว่าคิดอะไรออก แล้วก็ย่อให้อยู่ในขนาด 140 ตัวอักษรก็พอ (เกินก็ได้ - แล้วค่อยๆ แก้กันไปเรื่อยๆ) หรือว่าถ้ายังไม่แก่กล้าพอก็ไปศึกษา/ให้ความเห็น code ของคนอื่นๆ ก่อนก็ได้ ด้านประเภทของโปรแกรมก็มีอยู่หลากหลายมาก ตั้งแต่คำนวณทางคณิตศาสตร์ธรรมดาๆ ไปจนกระทั่งเขียนเกมกันเลยทีเดียว

ภาษาที่ใช้ได้
JavaScript

รูปแบบการตรวจคำตอบ
ส่ง source code ให้ชุมชนช่วยกันตรวจสอบ

ตัวอย่างโปรแกรม
  • Fibonacci (41b): มือใหม่เริ่มที่ตรงนี้เลยครับ กับการหาเลขฟีโบนัชชีแบบง่ายๆ โดยการ recursive
  • RGB to HEX (68b): แปลงค่าสีจากตัวเลขของ RGB ไปเป็น code สีตัวอักษร เทคนิคคือ shift bit
  • Konami Code (105b): ปลดล็อกสูตร 30 ตัว จากการตวจสอบ regular expression
  • Minesweeper (125b): เกมกู้ระเบิดนั่นเองครับ (เริ่มแกะ code ไม่รู้เรื่องแล้ว 555+)
  • Vigenère Cypher (138b): รหัสลับวิจเญอแนร์ (เลื่อนอักษรตามขนาดอักษรแต่ละตัวในกุญแจ)
  • Sudoku (141b): แก้ซูโดกุ เกินมาแค่ตัวเดียวเองนะ :'D (ใครสนใจไปช่วยลดขนาดมันบ้าง)