<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.3.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>Kata learns to code</title>
	<link>http://katatunix.freeweb7.com/weblog</link>
	<description>Data Structures + Algorithms = Programs</description>
	<pubDate>Tue, 22 Jan 2008 07:17:35 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.2</generator>
	<language>en</language>
			<item>
		<title>Isis - In Fiction</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=16</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=16#comments</comments>
		<pubDate>Tue, 22 Jan 2008 05:28:38 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[post-rock]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=16</guid>
		<description><![CDATA[Nghe ISIS có cảm giác thật mông lung&#8230;


Through fiction we saw The Birth
Of Futures Yet to come
Yet in Fiction lay the Bones
Ugly in their nakedness
Yet under this Mortal Sun
We cannot hide Ourselves
]]></description>
			<content:encoded><![CDATA[<p>Nghe ISIS có cảm giác thật mông lung&#8230;</p>
<p><embed src="http://www.youtube.com/v/wWTAkBRe6aI&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" allowscriptaccess="none" height="355" width="425"></embed></p>
<p></p>
<p>Through fiction we saw The Birth<br />
Of Futures Yet to come<br />
Yet in Fiction lay the Bones<br />
Ugly in their nakedness<br />
Yet under this Mortal Sun<br />
We cannot hide Ourselves</p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=16</wfw:commentRss>
		</item>
		<item>
		<title>Sai lầm thường gặp khi dùng Quy Hoạch Động</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=14</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=14#comments</comments>
		<pubDate>Mon, 21 Jan 2008 15:26:49 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[algorithms]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=14</guid>
		<description><![CDATA[Quy Hoạch Động (QHD) là 1 phương pháp rất mạnh mẽ trong Tin học. Nếu phân tích kĩ các bạn sẽ thấy những thuật toán nổi tiếng như Ford-Bellman, Dijkstra, hay Floyd đều có bản chất là QHD. Nhưng không phải bài toán nào cũng giải bằng QHD được, nếu quá áp đặt, cố sức [...]]]></description>
			<content:encoded><![CDATA[<p class="postcolor" id="post-46074">Quy Hoạch Động (QHD) là 1 phương pháp rất mạnh mẽ trong Tin học. Nếu phân tích kĩ các bạn sẽ thấy những thuật toán nổi tiếng như Ford-Bellman, Dijkstra, hay Floyd đều có bản chất là QHD. Nhưng không phải bài toán nào cũng giải bằng QHD được, nếu quá áp đặt, cố sức giải nó như vậy bạn sẽ dễ dàng mắc phải 1 sai lầm gọi là Phụ thuộc tiền sử.</p>
<p>Để tìm hiểu sai lầm này chúng ta nhắc lại về nguyên lí QHD do Bellman phát minh ra: &#8220;Một dãy là tối ưu thì các dãy con của nó cũng là tối ưu&#8221;. Nghe có vẻ khó hiểu nhưng đại loại là ta có 1 cái bảng rồi lần lượt điền các số vào bảng đó, các số điền vào đầu tiên thường đơn giản, các số sau<br />
đó dựa vào các số trước mà điền, cho đến khi điền kín bảng. Kết quả bài toán là số mà ta điền cuối cùng. Như vậy nguyên lí &#8220;chia để trị&#8221; đã được đẩy tới cao độ ở đây.</p>
<p>Khâu quan trọng nhất là làm thế nào điền được số sau dựa trên các số trước, hay nói cách khác là ta đang tìm 1 hệ thức truy hồi.</p>
<p>Gọi f(i) là hàm QHD tại i, ta xây dựng công thức truy hồi tính f(i) dựa vào các f(j) với j = i - 1, i - 2, &#8230; Công thức truy hồi này chỉ được phụ thuộc vào các f(j) cùng các đại lượng cố định của các j (cho trong đề bài) tuyệt đối không được phụ thuộc vào tiền sử, cách thức tạo nên f(j). Đây là chính là sai lầm mà tôi muốn nói đến!</p>
<p>Để dễ hiểu chúng ta xét 1 ví dụ rất thú vị sau:</p>
<p>Bài toán: ngày xửa ngày xưa, có 1 chàng Hoàng tử bị 1 mụ Phù thủy hóa phép biến thành 1 con ếch, còn Công chúa thì bị mụ ta nhốt trong 1 tòa lâu đài nằm trên 1 hòn đảo giữa hồ. Bây giờ ếch đang đứng ở bờ hồ, trên đoạn thẳng từ chỗ đó đến tòa lâu đài có các lá sen nổi trên mặt nước ở những vị trí, khoảng cách khác nhau, ếch phải nhảy qua các lá sen để vào tòa lâu đài cứu Công chúa. Bước nhảy kề sau không được dài hơn bước nhảy kề trước A mét cho trước.<br />
Ếch có 1 túi rất nhiều muỗi thần, ăn K con muỗi, ếch có thể nhảy tối đa trong 1 bước là K mét. Mỗi bước nhảy (dù dài hay ngắn) đều tốn 1 giây. Cho trước thời gian giới hạn là T giây, hãy tính số muỗi ít nhất mà ếch cần ăn để có thể nhảy đến tòa lâu đài!</p>
<p>Dữ liệu vào cho trong file ECHOP.INP có cấu trúc:<br />
Dòng đầu là 3 số nguyên N A T<br />
Dòng 2 là N số nguyên dương tăng dần thể hiện tọa độ các lá sen.<br />
Các số trên cùng 1 dòng cách nhau bởi ít nhất 1 dấu cách.<br />
Dữ liệu ra file ECHOP.OUT gồm 1 số duy nhất là số muỗi tối thiểu, nếu không có phương án giải<br />
cứu Công chúa in ra số -1</p>
<p>Rồi, đọc xong là biết phải dùng QHD, đây là cách sai:<br />
Gọi d[t, i] là số muỗi ít nhất cần ăn khi phải nhảy đến lá sen thứ i và thời gian giới hạn là t. Để tính d[t, i] ta chỉ cần xét các d[j, t - 1] với j = i - 1, i - 2, &#8230; kiểm tra xem khoảng cách từ lá sen j đến lá sen i là bao nhiêu (là P), xem tiền sử của d[j, t - 1] xem lá sen kề trước j là lá nào (lá thứ z), tính khoảng cách giữa lá sen z và j là Q, kiểm tra Q + A &gt;= P được thỏa mãn rồi đặt x = max(d[t, j], P), trong các x như thế chọn ra cái nhỏ nhất và đó chính là d[t, i]</p>
<p>Cách đúng: gọi d[t, i, j] là số muỗi ít nhất khi trong thời gian t, cần nhảy đến lá sen j nhưng lá kề trước j phải là i. Lúc này hệ thức truy hồi tương tự như trên nhưng không còn phụ thuộc tiền sử nữa.</p>
<p>Bạn cũng dễ mắc sai lầm này khi đi tìm cách giải hoàn hảo cho các bài toán &#8220;bất trị&#8221;, cho đến nay loài người vẫn chưa giải được như bài toán Người du lịch, bài toán Tìm đường đi dài nhất không lặp lại đỉnh trên đồ thị trọng số dương, bài toán Tập thống trị nhỏ nhất&#8230;<!--IBF.ATTACHMENT_46074--></p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=14</wfw:commentRss>
		</item>
		<item>
		<title>Öröm</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=12</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=12#comments</comments>
		<pubDate>Mon, 21 Jan 2008 06:13:38 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[doom]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=12</guid>
		<description><![CDATA[Cuối cùng cũng xong sự kiện mà suốt thời gian qua được rùm beng: Unite 08 với MCR. Thực ra tôi đi là cho có đi, gọi là không bị chê lạc hậu. Đến khá sớm và có được chỗ đứng ngon: phía trước, ngay sát rào chắn, nhưng không hiểu sao lúc UnlimiteD sắp [...]]]></description>
			<content:encoded><![CDATA[<p>Cuối cùng cũng xong sự kiện mà suốt thời gian qua được rùm beng: Unite 08 với MCR. Thực ra tôi đi là cho có đi, gọi là không bị chê lạc hậu. Đến khá sớm và có được chỗ đứng ngon: phía trước, ngay sát rào chắn, nhưng không hiểu sao lúc UnlimiteD sắp đánh, tôi lại nổi cơn hâm: chen xuống dưới cùng, sát khán đài để xem. Trên đường &#8220;tháo lui&#8221;, nghe có vài tiếng nói con gái dễ thương đại loại: &#8220;Ăn ơi, sao lại xuống dzzzzzzzzở?&#8221;, &#8220;Rồiiiiiiiii, cám ơn ăn!&#8221;</p>
<p>Về đến nhà mệt bã người, xong xuôi đâu đấy, theo thói quen trước khi đi ngủ, tôi bật máy lên nghe nhạc. Đã hết thời hạn làm crazy fan &#8220;tạm thời&#8221; của MCR, &#8220;I don&#8217;t love you&#8221;, uh, đúng đấy, &#8220;I don&#8217;t hate you&#8221;, cũng đúng luôn, tôi không thích mà cũng chẳng ghét MCR. Tôi định đêm nay tìm hiểu 1 band mới. Trong list các album download về để đó, ít hoặc chưa nghe, tôi ngẫu nhiên chọn Dolmen (Demo) của Öröm (country: Hungary, genres: Doom/Dark/Folk). OK, để xem thế nào.</p>
<p style="text-align: center"><img src="http://www.arsnautilus.com/orom/Photos_files/Media/orom011_1/orom011_1.jpg" width="522" /></p>
<p> Mở đầu album là tiếng mưa rơi tầm tã, 1 kiểu khá quen thuộc. Nhưng kiểu Doom của Öröm thì chả quen thuộc, không có gào thét thảm thiết, không có những đoạn riff xé lòng hay thê lương, không có cao trào hay điệp khúc gì cả. Tất cả cứ chầm chậm, đều đều, từ từ, vocal thì thầm, thở dài ngao ngán, khô khan. Bài nào cũng như bài nào, nhưng bài nào cũng hay.</p>
<p style="text-align: center"><img src="http://www.arsnautilus.com/orom/Photos_files/Media/orom007/orom007.jpg" width="522" /></p>
<p> Nhạc của Öröm gợi lên trước mắt người nghe những cảnh tượng của rừng già xám xịt, ảm đạm, bi ai, khói sương mù mịt, của nỗi nhớ, kỷ niệm buồn xa xăm.</p>
<p>Öröm cũng mới chỉ có 1 full length duy nhất ra năm 2006, tên là &#8220;8&#8243;, chỉ phát hành đúng 8 bản, nhưng album lại có 9 bài.</p>
<p>Chưa thể nói có thể làm fan của Öröm hay không, đợi nghe xong &#8220;8&#8243; đã. Tuy nhiên, sống giữa cái thành phố ồn ào, bụi bặm và tắc đường này, đêm nay nghe Öröm, vâng, cho nói phét tí, như được sống giữa rừng thiêng nước độc, thiên nhiên hoang vắng, nỗi buồn và sự cô đơn mới đẹp làm sao!</p>
<p><center><strong>Orom - Egyszer</strong></p>
<p><embed src="http://www.youtube.com/v/DBL2wPABqh8&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" allowscriptaccess="none" height="355" width="425"></embed></p>
<p></p>
<p><strong>Orom - Csondben</strong></p>
<p><embed src="http://www.youtube.com/v/XdtJ_BTmDVM&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" allowscriptaccess="none" height="355" width="425"></embed></p>
<p></center></p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=12</wfw:commentRss>
		</item>
		<item>
		<title>Hôn nhân bền vững</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=11</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=11#comments</comments>
		<pubDate>Sun, 20 Jan 2008 04:08:37 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[algorithms]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=11</guid>
		<description><![CDATA[Những ai đam mê lập trình và thuật toán hẳn có nhiều lúc ngây ngất trước vẻ đẹp của các thuật toán cũng như sự tinh tế trong cách cài đặt chúng! Có nhiều bài toán nghĩ ra thuật toán rất khó nhưng nghĩ ra rồi thì cài đặt lại rất dễ. Lại có những [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://katatunix.freeweb7.com/stock/images/married.jpg" align="left" />Những ai đam mê lập trình và thuật toán hẳn có nhiều lúc ngây ngất trước vẻ đẹp của các thuật toán cũng như sự tinh tế trong cách cài đặt chúng! Có nhiều bài toán nghĩ ra thuật toán rất khó nhưng nghĩ ra rồi thì cài đặt lại rất dễ. Lại có những bài ngược lại, thuật toán thì thấy ngay nhưng để biểu diễn cho máy nó hiểu thì khó vô cùng. Lại cũng có những bài &#8220;quái chiêu&#8221; cả thuật toán lẫn cài đặt đều khó nhăn răng và 1 trong số đó là bài toán kinh điển Hôn Nhân Bền Vững tôi muốn giới thiệu cùng các bạn.</p>
<p><strong>Phát biểu bài toán nghe khá hấp dẫn:</strong> có N chàng trai và N cô gái, mỗi chàng trai phát biểu cảm nghĩ về N cô gái kia (rằng là cô này anh ta thích nhất, cô này thích nhì, ba, &#8230; cho đến cô thích thứ N) tương tự các cô gái cũng phát biểu như vậy về các chàng trai. Hãy ghép đôi họ với nhau sao cho các cuộc hôn nhân này là bền vững nghĩa là không được tồn tại 2 cặp mà người chồng bên cặp này lại thích người vợ bên cặp kia hơn vợ mình, đồng thời người vợ bên cặp kia lại cũng thích người chồng bên cặp này hơn chồng mình, khi đó 2 người này sẽ tìm đến với nhau và thế là ngoại tình.</p>
<p>Bây giờ chúng ta sẽ nghiên cứu 1 thuật toán xây dựng các cặp bền vững dựa trên ý tưởng giống như đời thực của bài toán. Mỗi chàng trai X sẽ chọn cho mình 1 cô dâu, hiển nhiên là anh ta sẽ chọn cô gái đầu tiên trong danh sách của mình. Nếu cô này đã hứa hôn (đã được chọn trước đó) với chàng trai khác mà cô ta thích hơn thì anh chàng X phải chọn người phụ nữ kế tiếp trong danh sách của anh ta, quá trình này tiếp tục cho đến khi X tìm được một cô Y chưa được hứa hôn hoặc thích anh ta hơn anh chàng đã hứa hôn trước đó. Nếu Y chưa được hứa hôn thì cô ta sẽ được gả cho X và chúng ta tiếp tục cho người đàn ông kế tiếp. Còn nếu Y đã hứa hôn thì sẽ hủy bỏ cuộc đính hôn và gả cô ta cho X (vì cô ta thích X hơn), và chúng ta lại tiếp tục với anh chàng vừa bị từ hôn.</p>
<p>Phương pháp này có lẽ được mô phỏng từ 1 câu chuyện trong các tiểu thuyết của thế kỉ 19. Rất đơn giản phải không? Nhưng còn cài đặt thì sao? Trong các tài liệu thường thấy ở VN thì họ dùng foward bởi phải xây dựng 2 hàm mà trong thân hàm này gọi tới hàm kia, rất rối rắm phức tạp, khó sửa lỗi và code cũng dài dòng. Còn trong cuốn Cẩm Nang Thuật Toán (sách dịch nước ngoài) tập 2, tác giả đã có 1 cách cài đặt vô cùng đỉnh cao, gọn nhẹ và xúc tích, (điều thường thấy trong bộ sách này) chẳng phải pho goắc pho ghiếc gì hết.</p>
<p>Bởi vì tất cả các danh sách sở thích đều co chung độ dài, cài đặt đơn giản nhất là dùng mảng 2 chiều. Ví dụ prefer[m, w] là cô gái thứ w trong danh sách sở thích của chàng trai thứ m. Hơn nữa chúng ta cần theo dõi xem mỗi chàng trai đã xử lí đến đâu trong danh sách anh ta. Điều nay có thể được thực hiện bằng 1 mảng 1 chiều next, mảng này khởi tạo đến 0 và next[m] + 1 là chỉ số của cô gái kế tiếp trong danh sách của chàng trai thứ m, chỉ danh của cô tra sẽ là prefer[m, next[m] + 1]. Với mỗi cô gái ta cần theo dõi vị hôn phu hiện thời là ai (fiancee[w] sẽ là chàng trai đã hứa hôn với cô gái w) và chúng ta cần trả lời câu hỏi &#8221; người đàn ông thứ s có được thích hơn so với người đàn ông fiancee[w] hay không?&#8221;. Câu trả lời này có thể được giải đáp bằng cách tìm kiếm tuần tự cho tới khi s hoặc fiancee[w] được tìm thấy, nhưng cách này không hiệu quả nếu 2 người nằm ở cuối danh sách. Thay vì vậy, chúng ta dùng 1 danh sách ngược: rank[w, s] là chỉ số của chàng trai thứ s trong danh sách sở thích của cô w. Sự phù hợp của vị hôn phu s có thể xác định rất nhanh chóng bằng cách kiểm tra xem rank[w, s] có nhỏ hơn rank[w, fiancee[w]] hay không. Các mảng này được xây dựng dễ dàng và trực tiếp từ danh sách các sở thích. Để khởi đầu, chúng ta dùng 1 lính canh là chàng trai 0 để khởi tạo cho vị hôn phu và đặt anh ta ở cuối tất cả các danh sách sở thích của các cô gái.</p>
<p>Với cấu trúc dữ liệu được khởi tạo bằng phương pháp này, việc cài đặt có thể thực hiện dễ dàng như sau:</p>
<p>Language: Pascal<br />
Author: Katatunix</p>
<p>
<pre style="background-color:#669966;color:#000000;padding:10px;overflow:auto"><code style="font-size:14px">for m := 1 to N do
begin
    s := m;
    repeat
        next[s] := next[s] + 1;
        w := prefer[s, next[s]];
        if rank[w, s] &lt; rank[w, fiancee[w]] then
        begin
            t := fiancee[w]; fiancee[w] := s; s := t;
        end;
    until s = 0;
end;</code></pre>
</p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=11</wfw:commentRss>
		</item>
		<item>
		<title>Metalwolf (JavaScript version)</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=10</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=10#comments</comments>
		<pubDate>Sun, 20 Jan 2008 03:55:29 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=10</guid>
		<description><![CDATA[Browser: Firefox, IE
 Play here
]]></description>
			<content:encoded><![CDATA[<p>Browser: Firefox, IE<br />
<a href="http://katatunix.freeweb7.com/stock/metalwolfjs/metalwolf.html" title="Play Metalwolf game in new tab" target="_blank"> Play here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=10</wfw:commentRss>
		</item>
		<item>
		<title>Calculate an Expression</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=9</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=9#comments</comments>
		<pubDate>Sun, 20 Jan 2008 03:49:36 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[algorithms]]></category>

		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=9</guid>
		<description><![CDATA[1 + 1 = ?
12*(16-(6-40/20)-7)  +  5*(23-3*(7-2)) = ?
sqrt[pow[12*(16-(6-40/20)-7)  +  5*(23-3*(7-2)),3]] = ?  

package calexp;

public class CalculateExpression {

    private static final String MSG = &#34;Invalid Expression&#34;;

    private static final String[] FUNCTION_LIST = {
        &#34;abs&#34;, &#34;sqrt&#34;, &#34;sin&#34;, &#34;cos&#34;, [...]]]></description>
			<content:encoded><![CDATA[<p>1 + 1 = ?<br />
12*(16-(6-40/20)-7)  +  5*(23-3*(7-2)) = ?<br />
sqrt[pow[12*(16-(6-40/20)-7)  +  5*(23-3*(7-2)),3]] = ?  </p>
<p>
<pre style="background-color:#669966;color:#000000;padding:10px;overflow:auto;height:400px"><code style="font-size:14px">package calexp;

public class CalculateExpression {

    private static final String MSG = &quot;Invalid Expression&quot;;

    private static final String[] FUNCTION_LIST = {
        &quot;abs&quot;, &quot;sqrt&quot;, &quot;sin&quot;, &quot;cos&quot;, &quot;tan&quot;, &quot;cotan&quot;, &quot;log&quot;, &quot;exp&quot;, &quot;pow&quot;
    };

    private static final int[] PARAMETER_NUMBER = {
            1,      1,     1,     1,     1,       1,     1,     1,     2
    };

    public static double calculate(String exp) throws Exception {
        int sepa = findSeparator(exp);

        if (sepa == -1)
            return calcuSingleExp(exp);

        if (sepa == 0)
            switch (exp.charAt(0)) {
                case '+':
                    return calculate(exp.substring(1));
                case '-':
                    return -calculate(exp.substring(1));
                default:
                    throw new Exception(MSG);
            }

        double part1 = calculate(exp.substring(0, sepa));
        double part2 = calculate(exp.substring(sepa + 1));

        switch (exp.charAt(sepa)) {
            case '+':
                return part1 + part2;
            case '-':
                return part1 - part2;
            case '*':
                return part1 * part2;
            default:
                return part1 / part2;
        }
    }

    private static double calcuSingleExp(String exp) throws Exception {
        exp = exp.trim();
        if (exp.isEmpty()) throw new Exception(MSG);

        int len = exp.length();
        if (exp.charAt(len - 1) == ')') {
            if (len &lt; 3 || findOpen(exp, len - 1) != 0)
                throw new Exception(MSG);
            return calculate(exp.substring(1, len - 1));
        }

        try {
            return Double.valueOf(exp);
        } catch (NumberFormatException e) {
            if (exp.charAt(len - 1) != ']') throw new Exception(MSG);
            int open = findOpen(exp, len - 1);
            String func = exp.substring(0, open).trim();

            exp = exp.substring(open + 1, len - 1);
            String[] sub = splitFay(exp);

            int funcIndex = findFuncIndexOf(func);
            if (funcIndex == -1) throw new Exception(MSG);
            if (sub.length &gt; PARAMETER_NUMBER[funcIndex]) throw new Exception(MSG);

            double res = calculate(sub[0]);

            switch (funcIndex) {
                case 0: return Math.abs(res);
                case 1: return Math.sqrt(res);
                case 2: return Math.sin(res);
                case 3: return Math.cos(res);
                case 4: return Math.tan(res);
                case 5: return 1.0 / Math.tan(res);
                case 6: return Math.log(res);
                case 7: return Math.exp(res);
                default: return Math.pow(res, calculate(sub[1]));
            }
        }
    }

    private static int findFuncIndexOf(String func) {
        for (int i = 0; i &lt; FUNCTION_LIST.length; i++)
            if (FUNCTION_LIST[i].equalsIgnoreCase(func))
                return i;
        return -1;
    }

    private static String[] splitFay(String listExp) throws Exception {
        java.util.ArrayList&lt;String&gt; listSub = new java.util.ArrayList&lt;String&gt;();
        char ch;
        int j = 0;
        for (int i = listExp.length() - 1; i &gt;= 0; i--) {
            ch = listExp.charAt(i);
            if (ch == ')' || ch == ']')
                i = findOpen(listExp, i);
            else if (ch == ',') {
                listSub.add(listExp.substring(j, i));
                j = i + 1;
            }
        }
        listSub.add(listExp.substring(j, listExp.length()));
        String[] s = new String[listSub.size()];
        for (j = 0; j &lt; s.length; j++)
            s[j] = listSub.get(j);
        return s;
    }

    private static int findSeparator(String exp) throws Exception {
        int len = exp.length();
        if (isOperator(exp.charAt(len - 1)))
            throw new Exception(MSG);

        int i, j = -1;
        char ch;
        for (i = len - 1; i &gt;= 0; i--) {
            ch = exp.charAt(i);
            if (ch == ')' || ch == ']') {
                i = findOpen(exp, i);
                if (i == -1)
                    throw new Exception(MSG);
            } else if (ch == '+' || ch == '-') {
                return i;
            } else if (ch == '*' || ch == '/') {
                j = i;
            }
        }
        return j;
    }

    private static boolean isOperator(char ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }

    private static int findOpen(String exp, int off) throws Exception {
        int count = 0;
        char close = exp.charAt(off);
        char open = close == ')' ? '(' : '[';
        while (off &gt;= 0) {
            if (exp.charAt(off) == close) {
                count++;
            } else if (exp.charAt(off) == open) {
                count--;
                if (count == 0) return off;
            }
            off--;
        }
        throw new Exception(MSG);
    }

    public static void main(String[] args) {
        try {
            String s = &quot;12*(16-(6-40/20)-7)  +  5*(23-3*(7-2))&quot;;
            System.out.println(calculate(s));

            s = &quot;sqrt[pow[12*(16-(6-40/20)-7)  +  5*(23-3*(7-2)),3]]&quot;;
            System.out.println(calculate(s));

            s = &quot;abs[cotan[sin[(5*(13-7)- (5*6-9)*2)+pow[2,3]*(sqrt[9*pow[9.13,2.2]]-8+12*cos[23])]-log[4]]]&quot;;
            System.out.println(calculate(s));

            s = &quot;(1 * (4 + 50)) / 69&quot;;
            System.out.println(calculate(s));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}</code></pre>
</p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=9</wfw:commentRss>
		</item>
		<item>
		<title>Light on Mobile</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=8</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=8#comments</comments>
		<pubDate>Sun, 20 Jan 2008 03:46:58 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=8</guid>
		<description><![CDATA[Một số loại điện thoại (như Motorola) thường có sẵn chức năng đèn lồng, tức là đèn điện thoại sáng liên tục trên 1 nền trắng, hoặc đèn flash (chớp sáng rồi tắt luân phiên). Điện thoại Nokia ít có hơn, thực ra việc code ứng dụng Java như vậy ko khó.
Sử dụng phương thức [...]]]></description>
			<content:encoded><![CDATA[<p>Một số loại điện thoại (như Motorola) thường có sẵn chức năng đèn lồng, tức là đèn điện thoại sáng liên tục trên 1 nền trắng, hoặc đèn flash (chớp sáng rồi tắt luân phiên). Điện thoại Nokia ít có hơn, thực ra việc code ứng dụng Java như vậy ko khó.</p>
<p>Sử dụng phương thức tĩnh setLights(num, level) của lớp DeviceControl trong gói com.nokia.mid.ui để điều khiển đèn điện thoại. Trong đó num = 0, level là mức độ sáng (0-100).</p>
<p>Để làm được màn hình trắng trơn, ta cần viết 1 Canvas có màu nền là White, đặt nó ở chế độ toàn màn hình bằng lệnh setFullScreenMode(true).</p>
<p>Code khá đơn giản:</p>
<p>
<pre style="background-color:#669966;color:#000000;padding:10px;overflow:auto;height:350px"><code style="font-size:14px">// TestLight.java

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import com.nokia.mid.ui.*;

public class TestLight extends MIDlet
    implements CommandListener, Runnable {

    private Display display;
    private Form form;
    private Command exitCommand;
    private Command setCommand;
    private MyCanvas cv;

    public TestLight() {
        this.display = Display.getDisplay(this);
        this.form = new Form(&quot;Katatonia&quot;);
        this.exitCommand = new Command(&quot;Exit&quot;, Command.EXIT, 1);
        this.setCommand = new Command(&quot;Fuck it!&quot;, Command.OK, 1);
        this.form.addCommand(this.exitCommand);
        this.form.addCommand(this.setCommand);
        this.form.setCommandListener(this);
        this.form.append(&quot;Last fair deal gone down&quot;);

        this.cv = new MyCanvas();
    }

    protected void destroyApp(boolean unc) {
    }

    protected void pauseApp() {
    }

    protected void startApp() throws MIDletStateChangeException {
        this.display.setCurrent(this.form);
    }

    public void commandAction(Command c, Displayable d) {
        if (c == this.exitCommand) {
            this.destroyApp(false);
            this.notifyDestroyed();
        } else if (c == this.setCommand) {
            new Thread(this).start();
        }
    }

    public void run() {
        this.display.setCurrent(this.cv);
        for (int i = 0; i &lt; 20; i++) {
            if (i % 2 == 0) DeviceControl.setLights(0, 0);
            else DeviceControl.setLights(0, 100);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.display.setCurrent(this.form);
    }

}

// MyCanvas.java

import javax.microedition.lcdui.*;

public class MyCanvas extends Canvas {

    public MyCanvas() {
        this.setFullScreenMode(true);
    }

    protected void paint(Graphics g) {
        g.setColor(255, 255, 255);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
    }

}</code></pre>
</p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=8</wfw:commentRss>
		</item>
		<item>
		<title>Preloading Image</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=7</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=7#comments</comments>
		<pubDate>Sun, 20 Jan 2008 03:44:08 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=7</guid>
		<description><![CDATA[Nếu một trang web có nhiều hình ảnh, chúng sẽ được trình duyệt tải về từ từ, tải được đến đâu hiển thị đến đó. Ok, nhưng nếu chúng ta ko muốn người dùng tương tác với hình ảnh trước khi chúng được tải về đầy đủ thì sao? Cách giải quyết là đầu tiên [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://katatunix.freeweb7.com/stock/images/loading-card.gif" width="245" height="175" align="left" />Nếu một trang web có nhiều hình ảnh, chúng sẽ được trình duyệt tải về từ từ, tải được đến đâu hiển thị đến đó. Ok, nhưng nếu chúng ta ko muốn người dùng tương tác với hình ảnh trước khi chúng được tải về đầy đủ thì sao? Cách giải quyết là đầu tiên chỉ hiện lên màn hình &quot;Loading&#8230;&quot;, đồng thời tiến hành tải ảnh vào bộ đệm của trình duyệt, sau khi tải xong thì mới cho hiện lên trang web đầy đủ.</p>
<p>Và chúng ta phải dùng JavaScript (xin đừng nhầm với Java, chúng hoàn toàn khác nhau). Một trong những thế mạnh to bự của JavaScript là nó có thể chọc ngoáy vào mã HTML vốn là tĩnh. Trang web ban đầu chỉ là mã HTML tĩnh để hiện &quot;Loading&#8230;&quot;, khi tải xong, dùng Node.removeChild() để xóa chữ &quot;Loading&#8230;&quot;, kế tiếp dùng Node.appendChild() để đưa vào nội dung chính.</p>
<p>Một sai lầm phổ biến tôi thường thấy là code đơn giản như sau:</p>
<p>
<pre style="background-color:#669966;color:#000000;padding:10px;overflow:auto"><code style="font-size:14px">var oImg = new Image;
oImg.src = &quot;abc.jpg&quot;;</code></pre>
</p>
<p></p>
<p>Câu lệnh thứ 2 sẽ mở ra một Thread mới, Thread này âm thầm tải ảnh &quot;abc.jpg&quot; vào bộ đệm, đồng thời, ko cần biết đã tải xong hay chưa, ngay tắp lự chạy dòng lệnh tiếp theo. Thế là hỏng việc!</p>
<p>Vậy thì vấn đề là ta phải túm được thời điểm tất cả các ảnh đã tải xong hết!</p>
<p>Bây giờ ta sẽ tạo 1 lớp tên là ImagePreloader, trong contructor của lớp này nhận vào 2 tham số là mảng URL của các tấm hình và tên gọi của hàm sẽ được thực thi sau khi tải xong hết các tấm hình ấy:</p>
<p>
<pre style="background-color:#669966;color:#000000;padding:10px;overflow:auto"><code style="font-size:14px">function ImagePreloader(images, call-back) {
    // store the call-back
    this.call-back = call-back;
    // initialize internal state
    this.nLoaded = 0;
    this.nProcessed = 0;
    this.aImages = new Array;
    // record the number of images
    this.nImages = images.length;
    // for each image, call preload()
    for (var i = 0; i &lt; images.length; i++)
        this.preload(images[i]);
}</code></pre>
</p>
<p></p>
<p>Hàm call-back được lưu lại để sử dụng sau này, các URL được truyền vào hàm preload:
</p>
<p>
<pre style="background-color:#669966;color:#000000;padding:10px;overflow:auto"><code style="font-size:14px">ImagePreloader.prototype.preload = function(image) {
    // create new Image object and add to array
    var oImage = new Image;
    this.aImages.push(oImage);
    // set up event handlers for the Image object
    oImage.onload = ImagePreloader.prototype.onload;
    oImage.onerror = ImagePreloader.prototype.onerror;
    oImage.onabort = ImagePreloader.prototype.onabort;
    // assign pointer back to this
    oImage.oImagePreloader = this;
    oImage.bLoaded = false;
    // assign the .src property of the Image object
    oImage.src = image;
}</code></pre>
</p>
<p></p>
<p>Hàm preload tạo ra 1 đối tượng Image mới, cho nó đăng kí 3 sự kiện: onload, onerror, onabort. onload được gọi khi tải thành công, onerror khi có lỗi và onabort khi user ngưng tải bằng cách nhấn nút Stop trên Toolbar của trình duyệt. Các câu lệnh tiếp theo đều dễ hiểu.</p>
<p>Cuối cùng, ta cài đặt sự kiện:</p>
<p>
<pre style="background-color:#669966;color:#000000;padding:10px;overflow:auto"><code style="font-size:14px">ImagePreloader.prototype.onComplete = function() {
    this.nProcessed++;
    if ( this.nProcessed == this.nImages ) {
        this.call-back(this.aImages, this.nLoaded);
    }
}

ImagePreloader.prototype.onload = function() {
    this.bLoaded = true;
    this.oImagePreloader.nLoaded++;
    this.oImagePreloader.onComplete();
}

ImagePreloader.prototype.onerror = function() {
    this.bError = true;
    this.oImagePreloader.onComplete();
}

ImagePreloader.prototype.onabort = function() {
    this.bAbort = true;
    this.oImagePreloader.onComplete();
}</code></pre>
</p>
<p></p>
<p>Chú ý từ khóa this, theo lẽ thường, this sẽ trỏ vào lớp ImagePreloader, tuy nhiên ở trong ngữ cảnh này, this lại trỏ vào đối tượng Image xin đăng kí sự kiện.</p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=7</wfw:commentRss>
		</item>
		<item>
		<title>Kẹo lạc</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=6</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=6#comments</comments>
		<pubDate>Sun, 20 Jan 2008 03:33:48 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[emotion]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=6</guid>
		<description><![CDATA[Mặc dù vài tuần nữa là về nhà nhưng tôi ko khỏi vui mừng khi mama lại gửi đồ ăn.
Đương nhiên thứ mà lần nào cũng có là ruốc do chính tay mama làm (trong này gọi là chà bông, hừm, hồi đầu nghe tường xà bông, quái, người ta ăn được xà bông sao). [...]]]></description>
			<content:encoded><![CDATA[<p>Mặc dù vài tuần nữa là về nhà nhưng tôi ko khỏi vui mừng khi mama lại gửi đồ ăn.</p>
<p>Đương nhiên thứ mà lần nào cũng có là ruốc do chính tay mama làm (trong này gọi là chà bông, hừm, hồi đầu nghe tường xà bông, quái, người ta ăn được xà bông sao). Thứ này để được lâu, xếp vào loại lương khô. Tôi không ăn nổi ruốc miền Nam, ngọt quá! Mua mấy cái bánh mì không, cho ruốc vào, ngồi nhâm nhi đọc Teppi, nghe mấy bản nhạc ưa thích, chà chà&#8230;</p>
<p><img src="http://katatunix.freeweb7.com/stock/images/BanhMi.jpg" height="150" width="200" /></p>
<p>Và&#8230; kẹo lạc! Cái thứ kẹo quê mùa. Các bạn trẻ xì tin ngày nay mấy ai thích ăn kẹo lạc? Hehe, tôi thì thích, nếu có trà xanh để nhắm nữa thì cứ gọi là hết cả gói to.</p>
<p><img src="http://katatunix.freeweb7.com/stock/images/KeoLac.jpg" height="150" width="200" /> <img src="http://katatunix.freeweb7.com/stock/images/KeoLac2.jpg" height="150" width="200" /></p>
<p>Nhắc đến kẹo lạc, có ai còn nhớ bài đồng dao ngày xưa này ko:</p>
<blockquote><p>Anh lớp trưởng lấy chị quản ca<br />
Tối hôm qua đi ra Bờ Hồ<br />
Ăn kẹo lạc, hút thuốc lá<br />
Một hai ba chúng ta&#8230; tụt quần</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=6</wfw:commentRss>
		</item>
		<item>
		<title>Algorithms of Metalwolf</title>
		<link>http://katatunix.freeweb7.com/weblog/?p=4</link>
		<comments>http://katatunix.freeweb7.com/weblog/?p=4#comments</comments>
		<pubDate>Sun, 20 Jan 2008 03:05:28 +0000</pubDate>
		<dc:creator>Kata</dc:creator>
		
		<category><![CDATA[algorithms]]></category>

		<guid isPermaLink="false">http://katatunix.freeweb7.com/weblog/?p=4</guid>
		<description><![CDATA[Trò chơi Trúc Xanh (Kawai Chen Program Study) khá phổ biến, đặc biệt đối với chị em phụ nữ. Luật chơi là tìm ra 2 quân giống nhau và có đường đi giữa chúng không rẽ quá 2 lần. Đường đi là 1 dãy liên tiếp các ô trống kề cạnh nhau. Dưới góc độ [...]]]></description>
			<content:encoded><![CDATA[<p>Trò chơi Trúc Xanh (Kawai Chen Program Study) khá phổ biến, đặc biệt đối với chị em phụ nữ. Luật chơi là tìm ra 2 quân giống nhau và có đường đi giữa chúng không rẽ quá 2 lần. Đường đi là 1 dãy liên tiếp các ô trống kề cạnh nhau. Dưới góc độ lập trình, tôi tự hỏi khi người chơi click vào 2 quân giống nhau làm thế nào để kiểm tra xem giữa chúng có tồn tại đường đi thỏa mãn hay không? Bảng Pokemon được biểu diễn bởi ma trận a[0..17, 0..10], ở đây để cho khớp với hệ tọa độ khi lập trình GUI tôi cho chỉ số cột của a đứng trước chỉ số hàng, điều này cũng không có gì quan trọng lắm. Bảng thực sự chỉ có các cột 1..16 và các hàng 1..9 các ô đường viền dùng làm lính canh (trong luật chơi cho phép đi ra ngoài bảng) các ô này đương nhiên đều là ô trống. Ma trận a quy ước như sau:</p>
<ul>
<li>a[i, j] = 0 nếu ô (i, j) trống</li>
<li>a[i, j] = k &gt; 0 nếu ô (i, j) chứa quân thứ k</li>
</ul>
<p>Giả sử có 2 ô có quân Pokemon giống nhau cho trước (i1, j1) và (i2, j2) làm thế nào để kiểm tra đường đi thỏa mãn giữa chúng? Vì số lần rẽ chỉ giới hạn là 2 nên bạn có thể liệt kê, xét hết tất cả các trường hợp cùng với 1 đống if else lồng nhau loạn xạ, cách này không hay cho lắm. Ta hãy xét 1 cách khác hay hơn, chuyển bài toán về dạng đồ thị như sau:</p>
<ul>
<li>2 ô (i1, j1) và (i2, j2) cho trở thành ô trống</li>
<li>tập đỉnh của đồ thị là tập các ô trống</li>
<li>2 đỉnh có cạnh nối với nhau nếu 2 ô tương ứng với chúng là (u1, v1) và (u2, v2) cùng nằm trên 1 cột hay 1 hàng và nằm giữa 2 ô này toàn là ô trống</li>
<li>trọng số tất cả các cạnh đều = 1</li>
</ul>
<p>Bài toán chuyển về tìm đường đi ngắn nhất từ đỉnh ứng với ô (i1, j1) đến đỉnh ứng với ô (i2, j2). Nên dùng Tìm kiếm theo chiều rộng vì trọng số các cạnh chỉ là 1. Nếu đường đi này có độ dài không vượt quá 3 thì kết luận có đường đi thỏa mãn, ngược lại thì không có.</p>
<p>Các bạn thấy sao? Có ai có thuật toán nào nhanh hơn thì vào bàn bạc nhé!</p>
]]></content:encoded>
			<wfw:commentRss>http://katatunix.freeweb7.com/weblog/?feed=rss2&amp;p=4</wfw:commentRss>
		</item>
	</channel>
</rss>
