กรอกคะแนน

July 9th, 2010

ผมรู้สึกว่าการกรอกคะแนนนักศึกษาเป็นเรื่องยุ่งยาก โดยเฉพาะคะแนนการบ้านกับควิซ ที่เก็บมาแบบไม่ได้เรียงตามลำดับรหัสนักศึกษา ไม่รู้ว่าอาจารย์คนอื่นเขาทำกันยังไง (โดยเฉพาะวิชาที่สอนกัน 200-300 คน) เดิมผมมักจะเอากระดาษมาเรียงตามรหัสนักศึกษา แล้วค่อยไล่กรอกลง spreadsheet แต่มันก็ยุ่งยาก ขี้เกียจอีก

ความขี้เกียจนี้ส่งผลให้ผมไม่ค่อยได้คืนควิชหรือการบ้านกลับให้นักศึกษา แล้วก็จะมาหัวหมุนเอาตอนปลายเทอม เพราะต้องกรอกทุกอย่างให้เสร็จก่อนจะตัดเกรด

วันก่อนก็เลยเขียนโปรแกรมเล็กๆ เอาไว้กรอกคะแนนควิซโดยเฉพาะ ฟีเจอร์หลักๆ ที่ต้องการก็คือ อยากใส่แค่รหัสนักศึกษาบางส่วน (3-4 ตัวก็พอ) ถ้าไม่ซ้ำก็กรอกคะแนนไปได้เลย ถ้าซ้ำก็แสดงตัวเลือกให้หน่อย แล้วค่อยกรอกคะแนน ตอนแรกก็อยากจะทำเป็น GUI สวยงาม มี textbox ให้กรอกรหัส แล้วจะแสดงตัวเลือกเหมือนพวก autocomplete อะไรทำนองนั้น แต่ก็ดูยุ่งยาก ขี้เกียจอีก (จะเห็นว่าขี้เกียจกันทุกขั้นตอน) แต่สุดท้ายเลยได้โปรแกรม python แบบ command-line มาอันหนึ่ง รับข้อมูลเป็น text file มีแต่รหัสนักศึกษา ใช้ regular expression สำหรับเทียบรหัสกรอกเข้ามา แล้วก็ให้เลือกได้ ถ้ามีรหัสตรงหลายอัน จากนั้นก็กรอกคะแนนลงไปได้ เรียบร้อย ใช้ได้ดี ตามข้างล่างนี้ (แต่ไม่รับประกันความผิดพลาดถ้าจะเอาไปใช้ เพราะขี้เกียจเช็ค input error บางกรณีอีก) โปรดลองใช้กันได้ตามอัตภาพ :D
Read the rest of this entry »

ดอกไม้ที่บ้าน

April 20th, 2010

ช่วงนี้ชอบถ่ายรูปดอกไม้ต่างๆ ที่บ้านเก็บเอาไว้ด้วย iPhone เลยเอามารวบรวมลงเว็บไว้หน่อย
Read the rest of this entry »

แกงส้มดอกแคกับถั่วฝักยาว

April 19th, 2010

เนื่องจากระยะหลังบ้านผมมักจะซื้อกับข้าวถุงมากิน หรือไม่ก็ออกไปกินข้าวเย็นข้างนอก เนื่องด้วยความยุ่งยากวุ่นวายในการทำอาหาร แต่การไปกินข้างนอกบางครั้งก็ไม่อร่อยถูกใจ วันก่อนอยู่กันพร้อมหน้า คุณน้องสาวก็เลยเสนอให้พ่อแม่ทำแกงส้มดอกแค เลยเอาวิธีการปรุงมาเขียนไว้แก้ขัด

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

ตำน้ำพริก 1
ตำน้ำพริก 2

Read the rest of this entry »

Stylish และ Twitter

February 6th, 2010

หลังจากที่ twitter ออกฟีเจอร์ใหม่ให้แจ้ง tweet เพิ่มเติมอัตโนมัติ ผมก็มักจะใช้ Firefox เล่น twitter ตรงๆ ผ่านเว็บ แต่ก็พบปัญหาหนึ่งคือเว็บของ twitter จะแสดงภาษาไทยไม่ถูกต้อง สระบนถูกตัดแสดงไม่ครบ ลองใช้ Firebug ตรวจดูพบว่าเกิดจากปัญหาของ CSS ที่กำหนดความสูงของบรรทัดไว้เป็นค่าคงที่ ซึ่งจะใช้ได้ดีกับภาษาอังกฤษ แต่ก่อปัญหาให้กับภาษาไทย

ผมแก้ไข CSS โดยใช้ add-on ของ Firefox ที่ชื่อ Stylish ซึ่งจะทำให้เราสามารถปรับเปลี่ยนรูปแบบการแสดงผลของเว็บที่กำหนดโดย URL ได้ เมื่อติดตั้งเสร็จ ก็แค่เปิดเว็บ twitter แล้วก็เลือกที่ icon ของ Stylish ที่อยู่มุมล่างขวาของ Firefox จากนั้นก็เลือก “Write new style” > “For twitter.com” จากนั้นก็เพิ่ม CSS ตามข้างล่างนี้ เพื่อกำหนดให้ใช้ line-height เป็นแบบปกติ เท่านี้ก็เสร็จเรียบร้อย

.entry-content {
line-height: normal !important;
}
textarea#status {
line-height: normal !important;
}

ลองเล่น Go

November 22nd, 2009

ไม่ได้เขียนอะไรใหม่ๆ ที่นี่มาเกือบครึ่งปี เพราะงานยุ่ง แล้วก็ยังเสพติด twitter และ facebook งอมแงมอีกต่างหาก วันนี้มีเวลาว่าง (จริงๆ ก็ไม่ว่างหรอก แต่ขี้เกียจทำงานที่ควรจะทำ) เลยเอา Go Programming Language ที่พัฒนาโดย Google มาลองเล่นดู เนื่องจากผมใช้ Mac OS X ซึ่งเป็นแพลตฟอร์มที่สนับสนุนอยู่แล้ว ก็เลยติดตั้งไม่ยาก แค่มี XCode อยู่ แล้วลง mercurial เพิ่ม ก็สามารถโหลดซอร์สโค้ดคอมไพเลอร์ของ Go มาคอมไพล์เองได้เลย ใช้เวลาคอมไพล์ตัวคอมไพเลอร์สั้นมาก แป๊บเดียวเสร็จ ประทับใจพอสมควร

จากนั้นก็เลยลองเขียนโปรแกรมแบบมั่วๆ (เพราะยังงงกับ syntax อยู่) เพื่อแก้ปัญหา N-Queens แบบง่ายๆ (ใช้ backtracking search ด้วย recursive ดื้อๆ เอานี่แหละ) โดยใช้ Go:

package main
 
import "fmt"
 
var N int = 10
 
func nqueens(board []int, filled int) int {
	var attack bool = false;
	if filled == N-1 {
		for i:=0; i<N; i++ {
			fmt.Printf("%d\t", board[i])
		}
		fmt.Printf("\n");
		return 1
	}
	filled += 1;
	for i:=0; i<N; i++ {
		board[filled] = i;
		attack = false;
		for j:=0; j<filled; j++ {
			dy := board[j]-board[filled];
			dx := j - filled;
			if (board[j] == board[filled]) || 
			(dy/dx == 1 || dy/dx == -1) && (dy%dx == 0) {
				attack = true;
				break
			}
		}		
		if !attack {
			nqueens(board, filled)
		}	
	}
	return 0
}
 
func main() {
	var board []int = make([]int, N);
	nqueens(board, -1);
}

ด้วยความอยากรู้ ก็เลยลองเอาโปรแกรมนี้เอามาแปลงเป็นภาษา C แบบตรงๆ บรรทัดต่อบรรทัด

#include<stdio.h>
#include<stdlib.h>
 
const int N=10;
 
int nqueens(int *board, int filled) {
	int i,j,attack,dy,dx;
	if (filled == N-1) {
		for(i=0; i<N; i++)
			printf("%d\t", board[i]);
		printf("\n");
		return 1;
	}
	filled++;
	for(i=0; i<N; i++) {
		board[filled] = i;
		attack = 0;
		for(j=0; j<filled; j++) {
			dy = board[j]-board[filled];
			dx = j - filled;
			if ((board[j] == board[filled]) ||
			((dy/dx == 1 || dy/dx == -1) && (dy%dx == 0))){
				attack = 1;
				break;
			}
		}
		if (!attack)
			nqueens(board, filled);
	}
	return 0;
}
 
main() {
	int *board = (int *)malloc(sizeof(int)*N);
	nqueens(board, -1);
}

เสร็จแล้วก็ลองเขียน Python อีกโปรแกรมหนึ่ง

def nqueens(board, filled):
	global N
	if filled == N-1:
		for i in board:
			print "%d\t" % board[i],
		print
		return True
	filled+=1
	for i in xrange(0, N):
		board[filled] = i
		attack = False
		for j in xrange(0, filled):
			dy = board[j]-board[filled]
			dx = j - filled
			if board[j] == board[filled] or ((dy/dx == 1 or dy/dx == -1) and dy%dx==0):
				attack = True
				break
		if not attack:
			nqueens(board, filled)
	return 0
N=10
board = [0]*N
nqueens(board, -1)

ทดลองรัน (ด้วย N=10) แล้วจับเวลาง่ายๆ ด้วย time ก็จะได้ผลเป็น

Go C Python
real 0m0.165s 0m0.041s 0m1.048s
user 0m0.116s 0m0.029s 0m1.028s
sys 0m0.040s 0m0.002s 0m0.015s

ประสิทธิภาพแบบคร่าวๆ ก็ถือว่าใช้ได้ทีเดียว ไม่ได้แย่กว่า C นัก แต่ไม่รู้ว่าผมชินกับภาษา C มากเกินไปหรือเปล่า ทำให้ผมรู้สึกแปลกๆ งงๆ กับ syntax ของ Go มันดูไม่ค่อยสวยงามยังไงไม่รู้ บอกไม่ถูก เหมือนแค่เอา C มาตัดบางส่วนออก เพราะกลัวจะพิมพ์เยอะเกินไป มันเลยดูขัดๆ อีกอย่าง Go ก็ไม่ได้เขียนสั้นๆ ง่ายๆ ได้เหมือน Python ผมว่าโครงสร้าง syntax ของ C กับ Python สวยงามกว่าเยอะ แต่ผมก็ยังไม่ลอง concurrent programming ที่เป็นจุดขายของ Go เหมือนกัน เอาไว้หนีงานมาลองใหม่คราวหน้าละกัน