Sunday, November 30, 2008

301 Moved Permanently

Visit my new weblog at http://w1.tonkla.com : )

Saturday, November 29, 2008

Ruby 1.9 vs. Python 2.5.2 Benchmark

Credit: http://antoniocangiano.com/2007/11/28/holy-shmoly-ruby-19-smokes-python-away/

วันนี้เกิดความอยากรู้ว่าประสิทธิภาพ Ruby 1.9 กับ Python 2.6 ใครจะดีกว่ากัน เท่าที่หาดูไม่พบ Python 2.6 มีแต่ 2.5.1 ซึ่งก็พอแทนกันได้ ในเว็บนี้เขาทำการทดสอบด้วย recursive Fibonacci ดังนี้

Ruby:
def fib(n)
if n == 0 || n == 1
n
else
fib(n-1) + fib(n-2)
end
end

36.times do |i|
puts "n=#{i} => #{fib(i)}"
end

Python:
def fib(n):
if n == 0 or n == 1:
return n
else:
return fib(n-1) + fib(n-2)

for i in range(36):
print "n=%d => %d" % (i, fib(i))

Result:
Ruby 1.8.6:       158.869s
Python 2.5.1: 31.507s
Ruby 1.9.0: 11.934s


อ่า Ruby 1.9 แม่งเจ๋งว่ะ เร็วขึ้นจาก 1.8 เป็นกอง .. แต่ช้าก่อน !! บล็อกที่เขียนเกี่ยวกับการทำ programming language benchmark นี่ของดีอยู่ที่คอมเม้นต์ครับ เพราะเรื่องนี้มันเป็นเหมือนศาสนาที่ไม่มีใครยอมใคร ลองได้ผลลัพธ์ว่า Python ช้ากว่านะ เดี๋ยวมึงโดนเทพ Python มาตบแน่ ซึ่งก็เป็นไปตามคาด

คนแรกมาบอกว่าสำหรับ Python ต้องใช้ Psyco ช่วย จะทำให้ประสิทธิภาพดีขึ้น ซึ่งผมลองแล้วก็ได้ผลว่าเร็วกว่า Ruby 1.9 (Python with Psyco -> 2.403s, Ruby 1.9 -> 17.858s)

แต่ดูเหมือนไม่ยุติธรรม เพราะ Python ใช้ตัวช่วย .. จึงลองอ่านคอมเม้นต์ต่อ ปรากฏว่าเจอเทพ

def fib(n):
return fib_r(0, 1, n)

def fib_r(cur, next, rem):
if rem == 0:
return cur
else:
return fib_r(next, cur + next, rem - 1)

for i in range(36):
print "n=%d => %d" % (i, fib(i))


(โค้ดง่ายๆ แต่ลองไล่ดูแล้วปรากฏว่าไม่ไหว แค่ 3 รอบ เมมโมรี่ในหัวก็ตายแล้ว :-P)

อย่าว่าแต่ตำแหน่งที่ 36 เลย ผมลองที่ 360 ก็ยังใช้เวลาไปแค่ 0.246s (ไม่ใช้ Psyco)

พี่แกบอกว่า "So I guess you can create slow programs with Python too, didn’t know that.." เจ็บบบบ

การจะวิจารณ์สิ่งใดได้นั้น ต้องแน่ใจก่อนว่าเรารู้จักสิ่งนั้นอย่างถ่องแท้แล้ว หาไม่จะโดนของจริง ... ภาษาไหนก็เจ๋งหมดแหละหากรู้จักใช้ให้เป็น

แถมๆ Performance Comparison - C++ / Java / Python / Ruby/ Jython / JRuby / Groovy

เรื่องนี้ก็เช่นกัน ของดีอยู่ที่คอมเม้นต์ อ่านคอมเม้นต์แล้วได้เปิดหูเปิดตาเยอะเลย แต่ปัญหาคือมันเยอะมาก .. Languages War เหอๆ

Saturday, November 08, 2008

Text file processing with Python II

คราวนี้มีงานต้องจัดการกับอีเมลและ text file อีกแล้ว เจ้าหน้าที่คณะต้องการให้ invite นักศึกษาที่ตกสำรวจรอบแรกเข้า mailing list โดยให้รายการอีเมลของนักศึกษามาจำนวนหนึ่ง ซึ่งไม่ได้คัดอีเมลที่อยู่ใน mailing list แล้วออก

อันดับแรกเราต้อง export อีเมลปัจจุบันออกจาก mailing list มาเก็บไว้ในไฟล์ก่อน โชคดีที่ใช้ google groups จึงทำได้ง่ายๆ แค่ 3 คลิก

ต่อมาก็เขียนโปรแกรมให้อ่านอีเมลจากไฟล์มาเก็บไว้ใน set แล้วเอา set ทั้งสองมาหาความแตกต่างเพื่อคัดเอารายการอีเมลใหม่

ขั้นตอนสุดท้ายก็รวม set ทั้งสองเข้าด้วยกัน ซึ่งจะได้ set รายการอีเมลของนักศึกษาทั้งหมด

#! /usr/bin/env python

fi1 = open('mi_cur.txt', 'r')
fi2 = open('mi_new.txt', 'r')
fo1 = open('mo_dff.txt', 'w')
fo2 = open('mo_all.txt', 'w')

def parse(fi):
tmp = set() # using Set for prevent entry duplication
for line in fi:
tmp.add(line.rstrip('\n').lower())
return tmp

def write(fo, mails):
for m in mails:
fo.write(m + ',\n')

try:
mi_cur = parse(fi1) # Set object
mi_new = parse(fi2)

mo_dff = list(mi_new.difference(mi_cur)) # find new e-mails, then convert Set to List (unordered to ordered)
mo_dff.sort() # sort by alphabetic. can't chain in one line, e.g. list.sort()

mo_all = list(mi_cur.union(mi_new)) # merge both
mo_all.sort()

write(fo1, mo_dff) # write to new file
write(fo2, mo_all)
finally:
fi1.close()
fi2.close()
fo1.close()
fo2.close()

Wednesday, November 05, 2008

Hello Intrepid Ibex

ตั้งใจว่าจะใช้ 8.04 ไปนานๆ กว่านี้หน่อย แต่เห็นชาวบ้านใช้ 8.10 แล้วอิจฉา จึงตัดสินใจอัพเกรดทันทีโดยไม่คิดว่าจะเกิดปัญหาอะไรขึ้น เพราะ Thinkpad T43 ของผมลง Ubuntu เทคเดียวผ่านตั้งแต่ 6.04 โน่นแล้ว เรียกได้ว่าเป็น "Laptop for Linux" ยี่ห้อหนึ่งเลยก็ว่าได้

สิ่งแรกที่ประทับใจภายหลังอัพเกรด คือไม่ต้องแก้ /etc/X11/xorg.conf และไม่ต้องสั่ง xrandr เพื่อแสดง 2 จออีกต่อไป สามารถจัดการจากเมนู Preferences ได้เลย ... GNOME 2.24 ก็แหล่ม กราฟิกก็ดูดีขึ้น ทุกอย่างดีหมด ยกเว้นว่าติดต่อ DHCP ไม่ได้ ลองแก้แบบโง่ๆ อยู่พักหนึ่ง เมื่อไม่มีอะไรดีขึ้นจึงตัดสินใจว่าจะติดตั้งใหม่ เพราะบางทีการอัพเกรดอาจจะไม่สมบูรณ์ แต่ใจยังนึกเสียดาย เพราะใช้มา 6 เดือน ลง package และ configuration ต่างๆ ไว้เยอะทีเดียว ... ติดตั้งใหม่เสร็จ แต่ก็ยังติดต่อ DHCP ไม่ได้ ลองเปลี่ยน kernel ก็แล้ว ลองใช้ static IP ก็แล้ว อาการก็ยังเหมือนเดิม ... lspci ก็เจอฮาร์ดแวร์นะ ทุกอย่าง work fine หมด แล้วเป็นเพราะอะไรล่ะ?

วันต่อมาจึงลองเอาไปต่อที่ทำงาน ปรากฏว่าแม่งต่อได้ ทั้ง wired และ wireless โดยลองต่อเข้ากับเน็ตเวิร์ค 2 วงก็ไม่มีปัญหาใดๆ ... ค่อนข้างมั่นใจมากว่าเป็นที่ตัว router ของหอพักแน่ๆ แต่ไม่รู้ว่าเป็นอะไร ... ใจคิดไปไกลถึงว่า ถึงที่สุดแล้วจะลงทุนซื้อ wireless router มาใช้ กวางจริงๆ เลยกรู ... แต่เราไม่ยอมแพ้ครับ ถามพี่กูสักพักก็ได้คำตอบ ว่าเป็นเพราะ router ที่หอมันเก่าแล้ว ไม่มีฟีเจอร์สำหรับจัดการค่า MTU (Maximum Transmission Unit) วิธีแก้ก็แค่ไปลบค่า 'interface-mtu' ออกจากไฟล์ '/etc/dhcp3/dhclient.conf' ... อืมมม ง่ายๆ แบบนี้เลยเหรอ

ต่อมาจัดการเปลี่ยน font mapping ซึ่งปกติมันจะประกบ Sans, Sans-Serif เข้ากับฟอนต์ของแต่ละภาษาที่ Sans ไม่สามารถแสดงผลได้ โดยภาษาไทยรุ่นก่อน 8.04 ประกบเข้ากับ Loma รุ่น 8.04 ประกบกับ Waree รุ่น 8.10 ประกบกับ Norasi ซึ่งผมไม่ชอบ ผมชอบ Waree มากกว่า ... วิธีแก้คือสั่ง :%s/Norasi/Waree/g (search and replace) ในไฟล์ /etc/fonts/conf.avail/65-nonlatin.conf

ต่อมาปรับ speed / sensitive ของ Trackpoint ให้พริ้วๆ พร้อมทั้งกำหนดให้สามารถใช้ scroll ได้ ซึ่งไฟล์ config ใน 8.10 ได้เปลี่ยนจาก /etc/X11/xorg.conf ไปเป็นอะไรก็ไม่รู้ ... ขอบคุณฝรั่งใจดี ที่สอนวิทยายุทธิ์

นำไปใส่ไว้ในไฟล์ /etc/rc.local เพื่อให้มันสั่งทุกๆ ครั้งที่เปิดเครื่อง
echo -n 120 > /sys/devices/platform/i8042/serio1/speed
echo -n 255 > /sys/devices/platform/i8042/serio1/sensitivity

ต่อมาติดตั้งฟอนต์ Monaco ฟอนต์ที่เกิดมาเพื่อใช้เขียนโปรแกรมโดยเฉพาะ โดยนำไปใส่ไว้ใน /usr/share/fonts/truetype/ แล้วสั่ง
$ sudo fc-cache -sf
สร้าง cache เพื่อให้สามารถเรียกใช้ฟอนต์ใหม่ได้เลย โดยไม่ต้องรอบูตเครื่อง
หากอยากได้ฟอนต์บน Windows เช่น Tahoma, Verdana ก็สั่งติดตั้ง
$ sudo aptitude install msttcorefonts

เครื่องผมแบ่งพาร์ทิชันสำหรับเก็บของไว้อันหนึ่ง ปกติ Ubuntu จะไม่ mount ให้อัตโนมัติ จะทำก็ต่อเมื่อเราเรียกใช้ แต่ผมต้องการให้มัน mount ทุกครั้ง วิธีการคือไปเพิ่มคำสั่งไว้ใน /etc/fstab
# /dev/sda8
UUID=9dfa0c26-af71-4974-807d-0b3ec1bb3493 /media/sda8 ext3 defaults 0 0
UUID เป็นหมายเลขพาร์ทิชัน หาได้จากคำสั่ง
$ sudo vol_id /dev/sda8
0 ตัวหลังสุดบอกมันว่าไม่ต้องทำการ check disk แต่ถ้าเปลี่ยนเป็น 1 มันจะ check ทุกๆ การ mount 25 ครั้ง (ถ้าจำไม่ผิด)

รายละเอียดการปรับแต่งยังมีอีกเยอะ ซึ่งไม่ได้จำเพาะกับ 8.10 ถ้าจะโอกาสจะทยอยเขียนแนะนำ ... สรุปแล้ว 8.10 ค่อนข้างสมบูรณ์แบบ อะไรๆ ก็ง่ายสะดวกสบายไปเสียหมด : )

Wednesday, October 22, 2008

Generate a Random Password with Ruby and Python

Today, I want a random password for doing some tasks. I try to write a program with my interesting languages such as Ruby and Python.

gen_passwd.rb (http://snippets.dzone.com/posts/show/491)
#!/usr/bin/env ruby

def gen_passwd(size=8)
chars = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
return Array.new(size) { chars[rand(chars.size)] }.join
#passwd = ''
#1.upto(size) { passwd << chars[rand(chars.size - 1)] }
#return passwd
end

size = ($*[0].to_i == 0) ? 8 : ARGV[0].to_i
puts gen_passwd(size)

gen_passwd.rb gives two ways returning result, one is disabled by comments.

gen_passwd.py (http://code.activestate.com/recipes/59873/)
#!/usr/bin/env python

from random import choice
import string
import sys

def gen_passwd(size=8):
chars = string.letters + string.digits + string.punctuation
return ''.join([choice(chars) for i in range(size)])

args = sys.argv[1:]
print gen_passwd(int(args[0]))