Category Archives: General

ทำครัวไม่เหมือนต่อเลโก้

น้ำท่วมพาเหตุการณ์สำคัญมาให้ผมอีกเรื่องนึง คือ ข้าวกล่องแดง 7-11 หมดเกลี้ยง หยุดผลิต!

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

พอมันหายไป ผมเลยต้องมองหาอย่างอื่นมาทดแทน ซึ่งก็ไม่ได้หายากอะไรเพราะนอกจาก 7-11 ใต้คอนโดยังมี Max-Value ที่เป็นซูเปอร์มาเปิดใหม่ไม่นาน มีอาหารปรุงเสร็จใส่กล่องขายด้วย

พวกข้าวกระเพราไก่ไข่ดาว ข้าวผัด blah blah มีหมด … เสียอย่างเดียวคือรสชาติมันพอๆกับข้าวที่ศูนย์ฝึก ร.ด. แค่นั้นเอง = =’’

อีกอย่างที่ขายคือพวกของสด เป็น ปลาแซลมอน ปลาดอรี หอยลาย พอร์คชอป กุ้งสด ใส่เป็นห่อๆขาย ที่ต้องทำคือเอามาทำให้สุกซักวิธี ที่ผมทำได้คือ microwave หรือไม่ก็ทอดกับเตาไฟฟ้า (ซึ่งยังไม่เคยใช้เลยเพราะปกติเวฟเอาตลอด)

ก็เลยลองทอดดู มันจะมีอะไรยาก เอามาทอดๆ ปรากฎว่าสนุกดีอะ ทำกินไปหลายอย่างเลย ทั้งแบบที่หน้าตามันดูกินได้ และดูกินไม่ได้ …

301089_10150346633527257_637427256_8542827_10672384_n  8f0498bc086d11e19896123138142014_7

พอเริ่มทอดคล่องแล้ว (หลายวัน) อยากลองของยากขึ้นฮะ แล้วไปเจอวิดิโอสอนทำคาโบนาราใน Youtube พอดีด้วยความบังเอิญ

http://www.youtube.com/watch?v=B47U6ff7SY8&feature=feedf_more

ไอ่คนในวีดิโอบอกว่าทำง่ายซะด้วย! เอาวะ ลองซะหน่อย ดูในวิดิโอก็ไม่เห็นจะยากตอนไหนเลย

ก็เลยไปหาของมาให้ครบๆ ดังต่อไปนี้

  1. เส้นสปาเกตตี (แน่นอน ต้องมี)
  2. หัวหอมใหญ่
  3. ไข่
  4. เบคอน
  5. พริกไทยดำ
  6. เกลือ
  7. พาเมซานชีส (แพง maxxx เกือบหาไม่ได้)
  8. วิปครีมเหลว (อันนี้ก็แพงเหมือนกัน)

วันแรกที่ทำยังไม่มี วิปครีมเหลว แต่ว่ามีซอสผัดอย่างอื่นที่น่าจะใช้แทนได้ เลยลองดันทุรังทำดูซักหน่อย ปรากฎว่าแง่งออกมาเป็นผัดหมี่ = =’’ แดมมม

 Photo Nov 08, 9 11 02 PM

วันที่สอง ไปแสวงหาอุปกรณ์มาจนครบละ “ผมชื่อแก๊น วันนี้ผมพร้อมมาก และหิวมาก” (เลียนแบบใครหว่า) เลยจัดหนักเอาเส้นมาซะเยอะเลย วิปครีมก็เยอะ ใช้ชีสเยอะ ทุกอย่างเยอะ แต่ก็ไม่คิดว่าพอลวกเส้นเสร็จมันจะออกมาเยอะขนาดนี้ = =’’ แดมมมม (2)

นอกจากเรื่องเส้นที่มากไปแล้ว ยังมีความผิดพลาดอื่นๆอีก (ที่เรียนรู้เองจากการลองทำ)

  • ใช้ไฟแรงเกินไป จนพวกเบคอนกับหอมสับห่อเหี่ยวหมด
  • พอไฟแรง ของในกระทะเริ่มแห้ง ก็ต้องเอาน้ำเปล่าเติม (ไม่มีน้ำซุป) ออกมาแฉะไปอีก
  • อัตราส่วนวิปครีมเทียบกับไข่ ใช้วิปครีมเยอะไป ตอนกินมีแต่รสวิปครีม เลี่ยนๆ
  • ใช้วิปครีมเยอะไปมากก จนท่วมเส้นได้ทั้งกระทะ กะผิด
  • ตั้งวิปครีมไว้บนเตาไฟแรงนานมากจนนมแยกออกจากน้ำมันชัดเจนเลยทีเดียว = =’

รูปข้างล่างมาจากวันที่สอง ออกมาเป็นไรไม่รู้ แต่ก็ฝืนๆกินจนทนไม่ไหว เลยเลิก – -‘

(เพิ่งเข้าใจประโยค Eat your own dog food จากการปฎิบัติจริง ก็วันนี้)

Photo Nov 12, 9 15 12 AM Photo Nov 12, 9 48 06 AM Photo Nov 12, 10 04 55 AM

ทำกินตอนเช้า ตอนบ่ายออกไปเที่ยวเล่นด้วยความพะอืดพะอม = = กะว่าจะเลิกทำคาโบไปอีกซักอาทิตย์

แต่วันนี้ตื่นมานึกไงไม่รู้ ทำอีกรอบ คราวนี้แก้ไขข้อผิดพลาดคราวที่แล้วคือ

  • ใช้เส้นน้อยลงมาก (คราวนี้นับเลยว่าใช้ 40 เส้น)
  • เพิ่มส่วนประกอบที่เป็นเบคอนทอดกรอบ (จะได้ดูดีขึ้นหน่อย + ดับความเลี่ยน)
  • ใช้วิปครีมน้อยลง ผสมไข่แล้วข้นๆเลย
  • ใช้ไฟอ่อนลงเยอะ
  • แยกหัวหอมออกมาส่วนนึงก่อน ไว้ค่อยใส่เข้าไปตอนหลัง จะได้กินหอมดิบๆบ้าง หวานๆดี
  • ตั้งวิปครีมบนกระทะแปร๊บเดียว แล้วเทลงจานเลย กลัวมันร้อนจนน้ำมันแยกตัวแบบคราวก่อน

ค่อนข้างพอใจกับผลที่ออกมาฮะ TvT พอรับประทานได้เลยทีเดียวเชียวล่ะ ..

Photo Nov 13, 12 08 31 PM

ที่น่าจะยากหลังจากนี้ คือ จะทำให้ได้ออกมาประมาณนี้แบบคงเส้นคงวายังไง แล้วถ้าต้อง scale (เช่นทำมาเสิร์ฟสองที่พร้อมกัน) จะ scale ได้มั้ย ..

เป็นอะไรเล็กๆน้อยๆที่มากับเรื่องน้ำท่วม 2554 ฮะ ผมจะจำไว้

ปล. ราคาต้นทุนน่าจะสูงกว่ากินตามร้านแล้ว แดมมม (3)

ลองใช้ LaTeX

วันก่อนไม่รู้นึกไงเอาไฟล์ The Not So Short Introduction to LaTeX ใส่ Kindle ไปอ่าน อ่านไปอ่านมา skim ไปจนจบ ต้องลองเล่นดูซะหน่อย

สมัยเรียนมหาลัยถ้าใครเคยอ่านเปเปอร์พวกที่เป็นงานวิจัยจะรู้สึกว่ามันมีอะไร “บางอย่าง” คล้ายๆกันอยู่ แต่ไม่รู้ว่ามันคืออะไร ..

จริงๆแล้วเอกสารเหล่านี้ส่วนใหญ่มากเลยล่ะ ผลิตมาด้วย LaTeX ทั้งนั้น

ดังนั้นถ้าให้เปรียบเทียบกับซอฟแวร์ที่เรารู้จักก็คงต้องเอา LaTeX ไปเปรียบเทียบกับ Microsoft Word เพราะทั้งสองโปรแกรมใช้ผลิตงานพิมพ์ได้เหมือนกัน

ในวงการการวิจัยและการศึกษาจะยอมรับเอกสารที่ผลิตมาจาก LaTeX มากกว่า ผมเชื่อว่าถ้าส่งไฟล์ .docx ไป conference คงโดนศาสตราจารย์มองด้วยหางตา + เพื่อนเนิ้ดไม่คุยด้วยเลยทีเดียว .. (ขี้เว่อร์ซะ)

จริงๆแล้วมีโจ๊กเกี่ยวกับ LaTeX ที่เคยโพสต์ไว้ด้วยใน วิธีอ่าน Resume ของ HR กับ Programmer

วิธีการเริ่มใช้งานจริงๆมันไม่ยากอะไร แต่ถ้าจะจัด format เอกสารให้ได้ดั่งใจจริงๆผมว่ายุ่งยาก

สำหรับ Windows

  1. ไปโหลด MikTeX มา โหลดแบบ portable ก็พอ เพราะเดี๋ยวก็ลบทิ้งแล้ว
  2. ติดตั้งให้เรียบร้อย
  3. เขียนไฟล์เอกสาร myfile.tex ง่ายๆหนึ่งไฟล์ ถ้าไม่มีลองเอาตัวอย่างจากท้ายบลอกนี้ไปเล่นดู
  4. รัน MikTeX portable, คลิกขวาที่ icon ตรง tray เลือก Command Prompt
  5. รัน pdflatex myfile.tex แล้วรับผลงานในรูปแบบ PDF file

ตัวอย่างเอกสาร

\documentclass[a4paper]{article}
\author{Natthawut K}
\title{Hello Old World! I’m on \LaTeX{} now!}
\begin{document}
\maketitle
\thispagestyle{empty}
\paragraph{About Me}
My name is Natthawut Kulnirundorn, and I think it’s a long name so you can just refer to my online identity “m3rLinEz.” I am from Thailand, Land of Tom-Yum-Goong and delicious foods :)\footnote{I don’t think we’re really “Land of Smiles” any more \ldots} I am interested in Object-Oriented Design, Software Architecture, Graphics, .NET, Java. I also have a technical blog\footnote{Visit my blog –
http://www.solidskill.net (in Thai)} and a Twitter account\footnote{Follow @m3rlinez!}.
\end{document}

เห็นมั้ยล่ะ อ่านไม่รู้เรื่องเลย 555+

เรื่องข้อดีข้อเสียหรือประวัติ LaTeX วิธีใช้งานเบื้องต้น ลองไปอ่านใน The Not So Short Introduction to LaTeX  ได้

บลอกนี้จดไว้กันลืม จะได้รู้ว่าเคยเล่นแล้ว

สร้างการเรียงสับเปลี่ยนด้วย Javascript

ไปเจอคำถามน่าสนใจใน Blognone forum ว่าจะเขียนโปรแกรมแก้ปัญหา Zebra Puzzle (ปัญหาที่มันบอกว่ามีคนหลายชาติ เลี้ยงสัตว์หลายแบบ บ้านหลายสี บ้านคนนั้นติดคนนี้ น่ะ) ยังไง? ตอนสมัยเรียนรู้สึกเหมือนเคยแก้ปัญหาอะไรทำนองนี้แต่ใช้ Prolog ทำ ถ้าจะเอาภาษา Imperative บ้านๆแบบ Python หรือ C# ทำจะได้มั้ย?

ผมเข้าใจว่า Prolog เองมันก็มีการทำ search หา solution ที่เป็นไปได้ แล้วมีการทำพวก branch & bound หรือ track back เวลา solution มันผิดอะไรแบบนี้เหมือน (ไม่รู้ใช้ศัพท์ถูกป่าว มันนานมาแล้ว – -‘a) ครั้งนี้กะว่าจะลองใช้ Javascript เขียน

วิธีที่อยากทำคือจะวนไปตามรูปแบบ solution ทั้งหมดที่เป็นไปได้แล้ว check กับ constraints ของโจทย์ทีละตัวเลย ปัญหาแรกที่เจอคือจะ generate solution ที่เป็นไปได้ออกมายังไง?? อันนี้ต้องใช้ Permutation

Permutation ทั้งหมดของ [1,2,3] มี 3! แบบ = 6 แบบ ได้แก่ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]

ถ้ามี list มาให้อันนึง จะวนหา Permutation ทั้งหมด Wikipedia แบบให้ทำแบบนี้

The following algorithm generates the next permutation lexicographically after a given permutation. It changes the given permutation in-place.

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l such that a[k] < a[l]. Since k + 1 is such an index, l is well defined and satisfies k < l.
  3. Swap a[k] with a[l].
  4. Reverse the sequence from a[k + 1] up to and including the final element a[n].

เขียนออกมาเป็น Javascript .. ผมทำไว้เป็น Module

/////////////////////////////////////////////
// Permutation Generator
// - generate all permutation of given string
// array
// - Natthawut Kulnirundorn <m3rlinez at email by google>
// http://www.solidskill.net 10 July 2011
/////////////////////////////////////////////

var PermutationGenerator = (function () {
var self = {};

// Get start sequence of given array
self.getStartSequence = function (list) {
return list.slice(0).sort();
};

// Get next sequence from given array
// Ref: http://en.wikipedia.org/wiki/Permutation#Systematic_generation_of_all_permutations
self.getNextSequence = function (list) {
// Make clone
var a = list.slice(0);

//The following algorithm generates the next permutation lexicographically after a given permutation. It changes the given permutation in-place.
// 1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
var k = -1;
for (var i = 0; i < a.length - 1; ++i) {
if (a[i] < a[i + 1]) { k = i; }
}
if (k == -1) return null; // means this is the last one

// 2. Find the largest index l such that a[k] < a[l]. Since k + 1 is such an index, l is well defined and satisfies k < l.
var l = -1;
for (var i = 0; i < a.length; ++i) {
if (a[k] < a[i]) { l = i };
}
if (l == -1) return null; // impossible

// 3. Swap a[k] with a[l].
var tmp = a[k]; a[k] = a[l]; a[l] = tmp;

// 4. Reverse the sequence from a[k + 1] up to and including the final element a[n].
var next = a.slice(0, k + 1).concat(a.slice(k + 1).reverse());

return next;
};

return self;
} ());

แถม test cases ให้เป็นวิธีใช้
/////////////////////////////////////////////
// Test Cases
/////////////////////////////////////////////

var PermutationGeneratorTest = (function () {
var self = {};

function getStartSequence_Test1() {
var a = ['red', 'white', 'green', 'yellow', 'blue'];
var res = PermutationGenerator.getStartSequence(a);
log('input = ' + a);
log('output = ' + res);
}

function generateSequence(list) {
var current = PermutationGenerator.getStartSequence(list);
var count = 1;
log('start = ' + current);
while (true) {
current = PermutationGenerator.getNextSequence(current);
if (current == null) { break; }
log('next' + (++count) + ' = ' + current);
}
}

function getNextSequence_TestNormal() {
generateSequence(['English', 'Spanish', 'Japanese']);
}

function getNextSequence_TestEmpty() {
generateSequence([]);
}

function getNextSequence_TestRepeat() {
generateSequence(['gant', 'gant', 'korkore', 'jan']);
}

self.runTests = function () {
log("=== getStartSequence 1 ===");
getStartSequence_Test1();
log("=== getNextSequence Normal ===");
getNextSequence_TestNormal();
log("=== getNextSequence Empty ===");
getNextSequence_TestEmpty();
log("=== getNextSequence Repeat ===");
getNextSequence_TestRepeat();
};

return self;
} ());

ตัวอย่างเต็มๆผมทิ้งไว้ที่ http://www.solidskill.net/ZebraPuzzle.htm

ส่วนอันนี้เป็นคำตอบที่ตอบใน forum .. เผื่อว่า Blognone ทำกระมุ้หายคงเสียดาย พิมพ์ตั้งนาน 😛

อาจารย์ให้โจทย์ได้น่าสนใจมากครับ ผมเห็นแล้วอยากทำไปด้วยเลย ลองทำดูเล่นๆเป็น Javascript ใช้เวลาไปมากพอสมควร

เวลาทำโจทย์แนวนี้โดยใช้ดินสอกระดาษ เราก็จะพยายามสร้างคำตอบที่เป็นไปได้โดยดูจาก constraints ที่โจทย์บอก ทำผิดก็ลบใหม่แล้วสลับโน่นเปลี่ยนนั่นเปลี่ยนนี่ไปเรื่อยๆให้สอดคล้องกับ constraints จนได้คำตอบ .. แต่สิ่งที่ยากคือจะเอาวิธีที่กล่าวมานี้เปลี่ยนมาเป็น code ได้ยังไง??

สิ่งแรกที่ต้องทำคือ กำหนดรูปแบบของคำตอบที่เราต้องการ ตัวอย่างอันนี้กำหนดให้อยู่ในรูป list ของ list เช่น

[[1,2,3,4,5], [yellow,blue,red,white,green], [Norwegian,Italian,English,Spanish,Japanese], [fox,horse,snails,dog,zebra], [water,tea,milk,orange juice,coffe], [diplomat,physician,photographer,violinist,painter]]

list ย่อยตัวแรกจะบอกตำแหน่งของบ้าน ตัวต่อมาบอกสีบ้าน ตัวต่อมาบอกสัญชาติ และอื่นๆ ตามลำดับ จากตัวอย่างจะบอกว่าบ้านหลังแรกสีเหลือง มีชาว Norwegian บ้านหลังที่ 3 มีชาว Italian เลี้ยงหอยทาก เป็นต้น จากรูปแบบคำตอบแบบนี้และข้อมูลที่โจทย์ให้มา เราจะต้องหาคำตอบที่ถูกต้องจากคำตอบที่เป็นไปได้ทั้งหมด (5!)^5 = 24,883,200,000 แบบ (ไม่ต้องยกกำลัง 6 เพราะจริงๆแล้ว list ย่อยตัวแรกคือตำแหน่งนั้น เรา fixed ไว้เลย)

ทำแบบตรงไปตรงมา .. เราก็ generate คำตอบที่เป็นไปได้ทั้งหมดออกมา แล้วเอามาตรวจสอบกับ constraints ว่าผ่านทุก constraints หรือไม่ หลังจากตรวจสอบแล้วก็จะเหลือแค่คำตอบที่สอดคล้องกับ constraints ทั้งหมด ถ้าลองทำกับโจทย์ข้อนี้จะพบว่ามันเหลือแค่คำตอบเดียว (จากทั้งหมด 25,000 ล้านแบบ) ถ้าลองเอา constraint ออกซักตัวจะเห็นได้ว่ามีตำตอบออกมาเพิ่มหลายคำตอบ

วิธี generate คำตอบทำได้ด้วยการหา permutation ทั้งหมดที่เป็นไปได้ ยกตัวอย่างเช่น [1,2,3] มี permutation 3! =6 แบบ คือ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] .. อัลกอริทึมสำหรับการทำดูได้ใน http://en.wikipedia.org/wiki/Permutation#Systematic_generation_of_all_permutations

แต่ถ้าเราจะ generate คำตอบที่เป็นได้ไปได้ออกมาทั้ง 25,000 ล้านแบบแล้ว ตรวจสอบทุกแบบอาจจะใช้เวลามาก จริงๆแล้วเราสามารถตัดคำตอบที่เป็นไปไม่ได้ออกได้ตั้งแต่ตอน generate เลย เช่นมี constraint ตัวนึงบอกว่าบ้านหลังสีเขียวอยู่ถัดจากบ้านหลังสีขาว ดังนั้นระหว่างเรา generate สีบ้าน เราก็ตัดเคสอื่นๆที่ไม่สอดคล้องกับ constraint ตัวนี้ออกไปซะ ก็จะลดเวลาที่ใช้ลงไปได้มาก (pruning)

ที่ผม implement เป็น Javascript ลองเข้าไปดู (view source) ได้ที่ http://www.solidskill.net/ZebraPuzzle.htm ถ้าเข้าใจหลักการแล้วจะ implement เป็น Python หรือภาษาอื่นก็ไม่น่าจะลำบาก

ผมเข้าใจว่าถ้าเป็นวิชา Discrete Mathematics อาจารย์คงอยากให้หัดทำ permutation แหละ คงไม่ได้ต้องการให้ใช้เทคนิคยากๆจาก AI หรืออย่างอื่น

วิธีคำนวณ ROA ในเว็บ SET

เพิ่งอ่านหนังสือเล่มแรกจบใน Kindle ไปได้ไม่นาน (The Little Book that beats the market) หนังสือมันสอนวิธีกรองหุ้นง่ายๆโดยใช้ reuturn on capital + earning yield แต่วิธีที่หนังสือมันใช้คำนวณสองค่านี่มันต้องใช้ค่าดิบๆบางอย่างจากงบการเงิน ซึ่งหามายากพอควร ( .. แปลว่า automate ไม่ได้ ..) ผมเลยลองมาดูๆค่าที่ใช้แทนได้ใกล้เคียงที่สุดแทนและมีบนเว็บ SET คือ ROA (return on assets – ผลกำไรต่อสินทรัพย์) และ ROE (return on equity – ผลกำไรต่อส่วนผู้ถือหุ้น)

 

ค่าสองตัวนี้ควรจะหาได้ง่ายๆ Wikipedia กล่าวว่า

ROA_FORM

แต่ทำไปทำมาปรากฎว่าคำนวณแล้วไม่เห็นจะตรงกับที่เขียนไว้ในเว็บเลยว่ะ ….’’ นั่งงงอยู่นาน

FS

จากรูป ถ้าจะหา ROA ปี 2009 (ปี 2010 ยังได้ข้อมูลไม่ครบ เด๋วจะงง) จะได้ 10190.22 / 115698.28 = 8.8076 %  … ไม่เห็นจะตรงกับ 13.33 % เลยอ้ะ

ถามอากู๋คนเดิมได้ความจากกระทู้ในพันทิบว่า SET มันใช้วิธีคำนวณคนละวิธี ใช้เป็น ROAA (return on average assets) แทน

ROAA = EBIT of nth year  / (0.5 * (NET assets n-1th year + NET assets nth year))

ตัวย่อแปลกๆในข้อความนี้อีกตัวคือ EBIT (Earnings before interest and taxes) ซึ่งเป็นกำไรแบบที่ยังไม่ได้คิดดอกเบี้ยเงินกู้กับภาษี ถ้าดูจากตารางข้างบนจะเห็น กำไร/ขาดทุน = 10,190.22 ล้านบาท แต่ถ้าไปเปิดงบกำไรขาดทุนละเอียดดูแล้วจะได้ EBIT = 14,878.46 ล้านบาท

INCOME

สุดท้ายเอาไปคำนวณ 14878.46 / ((115698.28 + 107510.00) / 2) ~ 13.3 % ตรงแล้ว

วันนี้แมงเม่าหนุ่มจึงอ่านงบการเงินเป็นมากขึ้นพอสมควรหลังจาก trade มานานเกือบปีแล้ว จดไว้นิดนึงเผื่อมีคนงงเหมือนกัน

หลักๆ หนังสือเล่มที่อ่านมันสอนให้ดูค่าพวกนี้เพื่อบอกว่าหุ้นตัวไหนน่าซื้อแบบ relative เค้าบอกว่าการทำนายอนาคตหรือราคาที่เหมาะสมนี่มันไม่ใช่เรื่องที่ใครๆก็จะทำได้ง่ายๆ แล้วหุ้นที่ undervalued แบบที่ Ben Graham เจ้าพ่อ VI ชอบซื้อปัจจุบันมันก็ไม่ได้เจอได้ง่ายขนาดนั้นอีกแล้ว ดังนั้นเรามาดูข้อมูลปีล่าสุดกันดีกว่า … ใครสนใจลองหาไปอ่านกันดู

หนังไม่สมจริง

ตอนเด็กๆ (ก็ไม่น่าจะเด็กมากประมาณ ม.3 ล่ะมั้ง) เวลาป๊าม๊าที่เป็นหมอนั่งดูละครชุดเรื่อง E.R. กันก็จะนั่งดูเหมือนจะบันเทิงแต่ก็จะจับผิดตลอดเวลาอย่างโน้นอย่างนี้ ไม่สมจริง ทำแบบนี้ไม่ได้ …. ตัวเองตอนนี้มาพอนั่งดูนั่งที่เกี่ยวกับคอมพิวเตอร์หลายๆเรื่องก็ไม่เห็นจะมีเรื่องไหนมันทำสมจริงๆมากๆเลยว่ะ (มีนะแต่น้อย) ส่วนใหญ่ GUI ของคอมพิวเตอร์ในหนังมันก็จะเว่อร์ๆอยู่แล้วเพื่อให้คนดูสนุก วันก่อนก็ได้คุยกับพี่ที่ทำงานอีกคนเค้าก็ติๆ Angel & Demon หน่อยว่าทำอะไรไม่อิงข้อมูลวิทยาศาสตร์ แล้วก็ชมเรื่อง Iron Man ให้ฟังว่าเรื่องนี้ทำอะไรปรึกษานักวิทยาศาสตร์ตลอด ไม่ได้ให้ข้อมูลผิดๆเหมือน Angel & Demon

พักหลังๆผมชอบไปอ่าน review หนัง หลายครั้งบทวิจารณ์หนังพวกนี้มันบอกว่าหนังเรื่องนึงไม่ดีด้วยเหตุผล “ไม่สมจริง” ยกตัวอย่างเช่นเรื่อง The Hurt Locker คนวิจารณ์เคยทำงานเกี่ยวกับทหารมาก่อน เค้าบอกว่าเค้าดูแล้วรู้สึกสะดุดมากตอนที่ตัวเอกตัดสินใจจัดกลุ่ม 3 คนไปกู้ระเบิด เค้าบอกว่าสถานการณ์จริงไม่มีทางมีเรื่องแบบนี้เกิดขึ้นเป็นอันขาด ทำให้เค้าเสียอารมณ์ = =’

มานั่งคิดๆดู สมมติว่าคนเขียนบทเค้าสามารถทำให้คนดู 95% ทั่วโลกบันเทิงไปกับหนังโดยไม่สะดุดเลยได้จนจบเรื่อง และไม่ต้องสนใจคน “วงใน” อีก 5% เลย ว่าจะคิดยังไง มันก็ดูคุ้มค่าที่จะทำนะ ไม่รู้จะเอาเงินไปจ้างที่ปรึกษาด้านวิทยาศาสตร์ การแพทย์ คณิตศาสตร์ โบราณคดี blah blah ไปทำให้คนอีก 5% พอใจไปทำไม

ผมมาจบที่ข้อสรุปว่า “ความไม่สมจริง” ไม่ใช่เหตุผลที่ทำให้หนังมันไม่ดีที่สามารถใช้เอามาบอกคนอื่นได้ (ยกเว้นชัวร์ว่าเป็น 5% ด้วยกัน) … หรือว่ายังไง ?

ถ้าจะให้ผมพูดในฐานะที่เป็นคนใน “5%” ของบางเรื่อง อย่างถ้าใครเคยดูเรื่อง Antitrust ไม่รู้จะมีคนสงสัยเหมือนผมรึเปล่าว่า บริษัทยักษ์ใหญ่จะแย่งตัวหนุ่มน้อยอัจฉริยะผู้เขียนโปรแกรมภาษา “Java” ได้ (ซึ่งมีคนเขียนเป็นอยู่ล้นตลาด) ไปทำงานทำไม =_=” อย่าลืมกดดูให้ถึงหน้าจอที่แสดงโค้ด Java สำหรับทำ Satellite Uplink .. หนังเรื่องนี้พยายาม feature ผลิตภัณฑ์ของ Sun ทั้งเรื่องเลย  …. ไม่อยาก spoil เพิ่มแต่ลองไปดูแล้วกันว่าคนพวกนี้พยายามกันขนาดไหนเพื่อจะ “ขโมย” โค้ด “Java” ของคนอื่น

แต่ก็ต้องยกให้ว่าเรื่องนี้ในด้าน GUI มันค่อนข้างจะสมจริงมาก จะมองมุมไหนคอมพิวเตอร์ก็น่าเกลียดเหมือนจริง +__+’

ถ้าหนังเรื่องไหนสามารถกำจัดความไม่สมจริงที่ถูกสั่งสมขึ้นมาโดยเรื่องอื่นๆได้นี่ ก็จะได้เป็น Hero ไปเลย :’) ยกตัวอย่าง Trinity ใช้ nmap ใน The Matrix (เคยลองๆใช้โปรแกรมนี้ตอนไปแข่ง Network Security Contest ด้วยนะ!) อันนี้ได้ใจคน 5% ไปชัวร์ๆ

หรือคุณว่ายังไง ??

จับโจรขโมยรูป

เมื่อเร็วๆนี้เห็นคนแอด facebook มา … รูป profile ดึงดูดเกินมาตรฐานเพื่อนไปมาก >_< … แต่ไม่รู้ว่าเป็นใคร …..’’

FacebookTheft

ปกติเวลามีคนไม่รู้จักแอดมา ถ้าไม่ได้ใช้รูป profile เป็นรูปคนผมจะดองไว้พักใหญ่ๆ (เผื่อตอนหลังเปลี่ยนรูปแล้วจำหน้าได้) แต่ถ้าเป็นหน้าคนแล้วไม่รู้จัก รอซักพักนึงไม่นานผมก็จะ Ignore ไป ครั้งนี้ก็เช่นเดียวกัน ผมดองไว้พักใหญ่ๆ จากเดิมที่ mutual friends ไม่มีเลย จนเริ่มเพิ่มจาก 3 …. 5 …. 8 …. 11 (จากการสังเกตพบว่าเกือบทั้งหมดเป็นผู้ชาย)

Mutual

Mutual friends ส่วนใหญ่เป็นคนที่จบ ม.ปลาย โรงเรียนเดียวกัน …. หรือว่าคนนี้มันจะคนดังโรงเรียนเราวะ …. อ่ะๆ ไหนๆก็ไหนๆ ขอเข้าไปเก็บข้อมูลเพิ่มหน่อยแล้วกัน ว่ะฮะๆๆ .. accept

ปรากฎว่า

  1. เข้าวอลล์อันดับแรก …. มันเป็นใครวะ ?!? ข้างในวอลล์ไม่มีอะไรเลย เขียนเพิ่มไม่ได้ แล้วก็มีเขียนบอกไว้ว่า ถ้าอยากติดต่อให้ message ไปหา ….. เฮ้ย!
  2. แน่นอน ดูรูป! มีอัลบั้มรูปเพิ่มอีกอันนึงเป็นรูปเหมือนถ่ายที่งานอะไรซักอย่าง แล้วเหมือนกำลังซ้อมอะไรอยู่ คนข้างหลังรูปมีอยู่คนนึง หน้าไม่ค่อยเหมือนคนไทย –_-‘ เริ่มเอะใจ แถมยังคอมเม็นต์รูปไม่ได้อีก ปกติถ้ารูปดีขนาดนี้จะมีพวกเข้ามาเม้นต์ว่า “น่ารักจังครับ ผม%sนะ อยากรู้จัก”

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

ยังโชคดีที่โลกเรามีสิ่งที่เรียกว่า Reverse Image Search!

Reverse

การใช้งานง่ายมาก แค่อัพโหลดรูปที่จะหาขึ้นไป ระบบจะหาให้ว่ามีรูปคล้ายๆกันอยู่ที่ไหนบ้าง จากการทดลอง ถ้ามี text มาโปะหน้ารูปนิดหน่อย / รูปโดน crop / รูปเอียง / เบี้ยว / distort นิดหน่อย มันก็หาเจอนะ!

ผลลัพธ์ …. tadaaaaa~!

Result

ปรากฎว่ารูปนี้เป็นของดาราจากประเทศขวัญใจเยาวชนไทยคนนึง ชื่อ Sandara Park (박산다라) ครับ

(หมั่นไส้ล่ะสิ เวลาเห็นคนเขียนชื่อแล้ววงเล็บชื่อเกาหลี – -‘ ก็เห็นเด็กๆเค้าชอบทำกันอยากทำบ้าง ไม่งั้นจะมี Unicode ไปทำไม)

dd2

สรุปสั้นๆของนิทานเรื่องนี้

  • Bandwagon effect มันมีผลมากกับการ add friend
  • มองโลกในแง่ร้าย คนที่กระทำการในลักษณะนี้จะสื่อสารกับเหยื่อที่หลงเข้ามาแบบ private เท่านั้น ไอ่การสื่อสารผ่านวอลล์ คอมเม็นต์ จะโดนปิดหมด ไม่ให้เหยื่อได้ข้อมูลเพิ่มจากเหยื่อคนอื่น พอการสื่อสารเป็นแบบ private แล้ว การล่อลวงก็จะทำได้ง่ายขึ้น
  • มองโลกในแง่ดี อาจจะมีเพื่อนโรงเรียนเก่าล่ะมั้ง ที่แค่ชอบดาราคนนี้ล่ะมั้ง เลยต้องเอารูปทั้ง profile ทั้งอัลบั้มอื่นเป็นคนนี้หมดเลยล่ะมั้ง ขี้อายก็เลยไม่อยากให้คนเขียนวอลล์แล้วให้เมสเสจไปคุยล่ะมั้ง ….
  • ผมจะไปลบ friend ที่เพิ่งแอดทิ้ง
  • ผมเข้าไปเสพย์รูป Sandara Park (박산다라) ต่อได้ถ้าต้องการ 😛

รีวิว The Art of the Start

TheArtOfTheStart

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

เนื้อหาประมาณ 200 หน้า ถือว่าไม่ยาว อ่านเพลินมากๆ ตอนอ่านก็คิดตามไปโดยเทียบกับประสบการณ์ที่เคยเจอมาในชีวิตด้วย แต่ยอมรับว่ามันก็มีบางเรื่องที่อ่านไม่ค่อยเข้าใจเท่าไหร่ อาจจะเป็นเพราะยังไม่มีประสบการณ์พอ – -‘a

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

  • เรื่อง 10/20/30 – ทำ slides 10 หน้าเท่านั้น และบรรยาย 20 นาที และใช้ฟอนต์ 30 pts (หรือขนาดเท่ากับอายุมากสุดของคนที่มาฟังหารสอง)
  • สร้าง mantra ไม่ใช่ mission statement
  • ทำสิ่งที่มีความหมาย ไม่ใช่ทำเพราะอยากได้เงิน แต่การทำสิ่งที่มีความหมายก็ต้องการเงิน ต้องการ business model ที่ทำให้อยู่ได้ ไม่งั้นก็อดตาย
  • กว่าจะทำ market research จนพิสูจน์ได้ว่าตลาดมันมีอยู่จริง คู่แข่งมันก็เต็มไปหมดแล้ว จะรอ proven market ก็รอกินฝุ่นได้เลย (อันนี้มีแอบกัด Gartner)
  • งานสำคัญอย่าง branding หรือเขียน business plan สำคัญเกินกว่าจะจ้าง consultant ข้างนอกทำ หรือจะจ้างก็เอาไว้ตรวจสอบก็พอ
  • หลายคนอยากทำ product หรือ service ของตัวเองแต่ทำไม่ได้เพราะเรื่องเงิน ต้องรับงานพวก consulting คือการทำตาม requirement ลูกค้าไปก่อนโดยพยายามเอา product ที่ทำไปเป็นส่วนประกอบ พอเงินพอ + ลูกค้าเยอะพอ ลุกค้าก็จะวิ่งเข้ามาหา product/service ของเราแทน (ไม่ต้องเข้าหาลูกค้าเหมือน consulting)
  • จ้างคนที่เสพย์ติด และเชื่อในความหมายที่เราจะสร้างไปด้วยกัน
  • เลือกเพื่อนร่วมงานที่หลากหลาย หาคนเห็นต่าง หาคนมีเน็ตเวิร์คเยอะ หาคนชอบ implement หาคนไอเดียบรรเจิด หา …. (มีลิสต์ในหนังสือ)
  • เทคนิคการพูด + การนำเสนอ … อันนี้รู้สึกเป็นประโยชน์กับตัวเองมากเพราะยังพูดไม่ค่อยเก่ง
  • การหาลูกค้าที่ชื่นชอบ product/service ของเราเพื่อขอความช่วยเหลือให้เป็นแนวร่วมในการเจาะตลาดเพิ่ม – สร้าง evangelist — evangelist ไม่ต้องการผลตอบแทนในรูปแบบเงิน แต่ถ้าได้เสื้อหรือแก้วน้ำ หรืออะไรที่ทำให้รู้สึกว่าเป็นลูกค้าคนพิเศษจะดีใจมาก
  • สร้าง exit ที่ง่ายให้กับลูกค้า — การสมัครสมาชิกที่ยกเลิกสมาชิกได้ง่ายๆ จะทำให้ลูกค้ารู้สึกดีกว่า
  • ไม่มีบริษัทที่สร้างมาให้ยิ่งใหญ่เหมือน Microsoft, Apple, Google (ตอนนี้) ตั้งแต่แรก ให้เริ่มจากตลาดที่ยักษ์ใหญ่จะเจาะไม่ถึง แต่ไม่คิดจะเจาะก่อน แล้วค่อยๆขยายไป .. แม้แต่ MS, Apple, Google ก็ทำแบบนี้เช่นกัน
  • การล้มเหลวไม่ใช่เรื่องใหญ่ ตราบใดก็ตามที่ยังลองใหม่ได้
  • …. อีกมากมายนับไม่ถ้วน

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

Correlation ในราคาหุ้น

ช่วงนี้สนใจเรื่องแนวๆ quantitative มากเป็นพิเศษ อ่านไปเรื่อยๆก็สนุกดี แต่บางทีก็อดรู้สึกไม่ได้ว่านี่เอาเวลามาทำอะไรอยู่ฟะเนี่ย -*- ยิ่งทำๆไปแล้วยังไม่เห็นผลลัพธ์ที่จับต้องได้นี่ มันจะเริ่มหงุดหงิดๆ 555+

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

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

ใน Excel มีฟังก์ชันสะดวกๆให้ใช้ชื่อ CORREL ส่วนใน Python เข้าใจว่าใน SciPy ก็มีเหมือนกัน แต่บางครั้งคนเราควร Reinvent the Wheel บ้าง เพื่อความบันเทิง 😛

Pearson

วิธีการตีความผลลัพธ์คือ

  • ถ้าได้ค่าใกล้ 1 มาก แปลว่ามันขึ้นลงพร้อมๆกันมากๆ (correlate)
  • ถ้าได้ค่าใกล้ 0 แปลว่ามันแทบจะไม่ correlate กันเลย
  • ถ้าได้ค่าใกล้ 1 มาก แปลว่ามันจะขึ้นลงกลับกันมากๆ (correlate)
def corr(series1, series2):
"""Calculate Pearson's product-moment coefficient

More info: http://en.wikipedia.org/wiki/Correlation_and_dependence#Pearson.27s_product-moment_coefficient

"
""
if len(series1) != len(series2):
raise Exception((series1, series2), 'Lengths of series are not equal')

n = len(series1)
sum_x = sum(series1)
sum_y = sum(series2)
sum_sqx = sum(a*a for a in series1)
sum_sqy = sum(a*a for a in series2)
sum_xy = sum(map(lambda s: s[0] * s[1], zip(series1, series2)))

import math
res = (n*sum_xy - sum_x*sum_y)/(math.sqrt(n*sum_sqx - sum_x*sum_x)*math.sqrt(n*sum_sqy - sum_y*sum_y))

return res

ตัวอย่างที่ค่อนข้าง obvious:

  • [1,2,3] กับ [3,4,5] ได้ 1.0
  • [1,2,3] กับ [-3,-4,-5] ได้ -1.0

ลองเอามาทดสอบกับราคาหุ้นดู ช่วงนี้ผมมีฐานข้อมูลราคาเป็นของตัวเองแล้ว (จากการไป pull ข้อมูลมาจากเว็บสาธารณะ) เก็บใส่ mongdb ไว้ ใช้คู่กับ Python สะดวกโยธินมาก (เอาเวลาตอนไหนไปทำวะเนี่ย)

ทดสอบกับ data 500 วันล่าสุด

  • CPF กับ CPALL = 0.96  — ขึ้นลงตามกันโคดๆๆ .. แน่ล่ะ
  • CPF กับ TUF = 0.94 — อาหารเหมือนกันมั้ง
  • BBL กับ KBANK = 0.94 — กลุ่มธนาคารเหมือนกัน
  • PS กับ QH = 0.89 — อันนี้อยู่ใน sector อสังหาเหมือนกัน
  • DTAC กับ ADVANC = 0.74 — ไม่เยอะอย่างที่คิด
  • CPN กับ CPF = 0.37 — ห้างเซ็นทรัล กับ อาหาร
  • CPF กับ CAWOW = –0.68 – ไก่ ลง ฟิตเนส ขึ้น ??
  • TRC กับ PS = -0.11 — ไม่ค่อยเกี่ยวกันเท่าไหร่ …
  • ..

พวก quant ตัวเทพเค้าบอกว่า จริงๆ correlation ไม่ค่อยมีประโยชน์กับการ trade เท่าไหร่ ที่มีประโยชน์คือ cointegration เป็นคุณสมบติอีกแบบที่บอกว่า series สองอันมันจะแตกต่างกันได้บ้างเป็นบางเวลา แต่สุดท้ายแล้วต้องกับมาขึ้นลงคู่กันอีกรอบ คุณสมบัตินี้ทำให้เอาไปใช้ทำ pair trading ได้

สรุปว่าถ้าลองทำกับทุกคู่ในตลาด (ประมาณ 500 ตัว) น่าจะพอเห็นอะไรบ้าง … ไว้เวลาเอื้ออำนวยอีกรอบละกัน 🙂

ช่วงนี้ความสนใจเยอะจัด สับสนมาก เลือกทำไม่ถูก – -‘ อย่างนึงที่ทำก็คือไล่อ่านบลอกของไอดอลคนใหม่อยู่ (Max Dama) ใครสนใจเรื่องพวก automated trading ต้องลองเข้าไปดู มีอะไรให้เก็บเกี่ยวเยอะแน่นอน

กูเกิ้ลโค้ดแยม : รอบคัดเลือก 2010

ครั้งนี้ตัดคำว่าเฉลยออกแล้ว ลดความมั่นใจลงหน่อยนึง – -‘a 

แต่ตั้งแต่ทำมา 3 ปี ปีนี้เป็นปีแรกที่ได้คะแนนเต็มรอบแรก T_T ดีใจ

ข้อแรก Snapper Chain

ถ้าเปลี่ยน ON เป็นเลข 1 แล้ว OFF เป็นเลขศูนย์ แล้วให้ปลั๊กไฟหลัก (Power) อยู่ซ้ายสุด

ถ้ามี Snapper สองอัน มันจะวิ่งตามลำดับนี้

00
10
01
11 <— Light on!
00
10 …

ถ้าเป็น 3 อัน ก็พอจะเดาได้ว่ามันก็เป็นแบบนี้

000
100
010
110
001
101
011
111 <— Light on!

สรุปว่ามันก็เหมือนกับนับเลขฐานสองกลับหลัง ดังนั้นถ้ามี snapper n อัน กรณีที่จะทำให้หลอดไฟติดได้ก็คงต้องเป็นการ snap เป็นจำนวน (c * 2^n) – 1 เท่านั้น (โดย c เป็นจำนวนเต็ม … บวก)

if __name__ == '__main__':
fin = 'A-large.in'
fon = 'A-large.out'

fi = open(fin, 'r')
fo = open(fon, 'w')

c = int(fi.readline())
for i in xrange(c):
n, k = [int(x) for x in fi.readline().split(' ')]
ans = (k % 2 ** n) == 2 ** n - 1
fo.write("Case #%d: %s\n" % (i + 1, 'ON' if ans else 'OFF'))

print "Done!"
fi.close()
fo.close()

ข้อสอง Fair Warning

ข้อนี้เข้าใจว่าเป็นเรื่องแนวๆ number theory

มีคนอ่านโจทย์แล้วงงเยอะมาก โจทย์มันถามว่า ต้องใช้เวลานานอย่างน้อยเท่าไหร่ ถึงจะทำให้ ตัวหารร่วมมากสุด (ห.ร.ม. – Greatest Common Divisor (GCD)) มีค่ามากที่สุด

ในโจทย์ตัวอย่างเป็น 26000 11000 6000 ดังนั้นถ้าเวลาผ่านไป 4000 sec (ซึ่งเป็นคำตอบที่ถูกต้อง) จะทำให้กลายเป็น 30000 15000 10000 และทำให้เลขชุดนี้มี GCD เป็น 5000 ซึ่งไม่ว่าจะเป็นเวลาก่อน 4000 sec หรือหลัง 4000 sec ไปอีกนานเท่าไหร่ก็ตาม GCD ที่หาได้ก็จะมีค่าไม่เกิน 5000 แน่นอน เช่นถ้าผ่านไปแค่ 2000 sec จะได้เลขชุดนี้เป็น 28000 13000 8000 ซึ่งมี GCD = 1000 (น้อยกว่า 5000)

ขอแทนเวลาที่ผ่านไปเรื่อยๆ ด้วยแถบยืดๆ x (ซึ่งยืดได้เท่าไหร่ก็ไม่รู้ แต่ต้องยืดเท่าๆกันสำหรับแต่ละ event)

<===== x ===…==><==  6000 ==>

<===== x ===…==><== 11000 ======>

<===== x ===…==><== 26000 ================>

หรือถ้าเรา define ให้ y = x + 6000 จะกลายเป็นรูปนี้ (เลือก 6000 เพราะเป็น MIN)

<===== y ===…=======>

<===== y ===…=======><== 5000 ======>

<===== y ===…=======><== 20000 ===========>

ทีนี้เราก็จะหา GCD ของ y, y+ 5000, และ y + 20000 .. ยกคุณสมบัติ GCD ที่จะใช้มาทวนก่อน

  • gcd(a, b) = gcd(b, a) …. สลับที่
  • gcd(a, gcd(b, c)) = gcd(gcd(a, b), c) …. เปลี่ยนกลุ่ม
  • gcd(a, b) = gcd(b, a – b) … กรณี a > b

จากรูปด้านบน ถ้าเราหา GCD ระหว่าง y กับบรรทัดอื่นๆ ทีละคู่ จะได้อะไรประมาณนี้ออกมา

<===== y ===…=======>

<== 5000 ======>

<== 20000 ===========>

กลายเป็น gcd(5000, 20000, y) ทำโน่นนี่ไปมาจะได้ GCD = gcd(gcd(5000, 20000), y)

เนื่องจากว่าเราให้ y เป็นอะไรก็ได้อยู่แล้ว ดังนั้น MAX GCD = gcd(5000, 20000) = 5000 แน่นอน!

ต่อมา เราต้องการทราบ x น้อยที่สุด (เวลาน้อยที่สุดที่จะทำให้ได้ MAX GCD) ซึ่ง y = x + 6000

พบว่าในเคสนี้ x น้อยสุดเป็น 4000 ซึ่งทำให้ y เป็น (+) ได้ และหาร MAX GCD = 5000 ลงตัว

ขอสารภาพว่า … ข้อนี้ตอนทำไม่ได้คิด math แบบข้างบนหรอก (อ้าววว) นั่งวาดรูปๆๆๆ เดาๆๆ แล้วลองมั่วๆกับ sample ดู ถูกเคสเล็กก็ลองเคสใหญ่เลย ไอ่ที่ทำ math เพราะพยายามหาข้อสนับสนุนวิธีที่ทำไป(แล้ว) = =’

ขอขอบคุณ Python ทำให้ไม่ต้องไปวุ่นวายเรื่อง BigInteger แล้วก็ยังแถม fractions.gcd มาให้อีก!

(แอบภูมิใจบรรทัด reduce TvT)

import fractions

if __name__ == '__main__':
fin = 'B-large.in'
fon = 'B-large.out'

fi = open(fin, 'r')
fo = open(fon, 'w')

c = int(fi.readline())
for i in xrange(c):
ts = [int(x) for x in fi.readline().split(' ')][1:]
m = min(ts)
tns = [x - m for x in ts]
unit = reduce(lambda x,y: fractions.gcd(x,y), tns)
r = m % unit
ans = unit - r if r else 0
fo.write("Case #%d: %d\n" % (i + 1, ans))

print "Done!"
fi.close()
fo.close()

ข้อสาม Theme Park

ข้อนี้ใช้วิธี pre-computed (หรือจะเรียกว่า cache ?) อะไรที่มันทำได้ไว้ก่อน ทำให้ตอนคำนวณจริงๆไม่ต้องทำอะไรซ้ำๆ แต่ถ้าทำแค่นี้มันจะยังไม่เร็วพอ (โดยเฉพาะถ้าเป็นโปรแกรม Python รันดิบๆ T_T’)

แนวคิดคือ ในการเล่นรอบใดๆที่มี group ที่อยู่หัวคิวเป็น group เดียวกัน (เช่นรอบ 3 กับรอบ 5 มี g1 เป็นหัวคิวเหมือนกัน) จะเก็บเงินได้เท่ากันเสมอ และหัว group ในรอบถัดไปก็จะเป็น group เดียวกันเสมอ …

ดังนั้นไอ่การคำนวณจำนวนคนนั่งในแต่ละรอบนี่ ทำครั้งเดียวก็พอ (สำหรับรอบที่ขึ้นต้นด้วยแต่ละ group) และก็ควรบันทึกไว้ด้วย ว่าหลังจาก group นี้เล่นในรอบนี้แล้ว รอบถัดไปจะเป็น group ไหน จากตัวอย่าง

grou: [1, 4, 2, 1]

hist: [5, 6, 4, 6]

next: [2, 3, 1, 2]

อันนี้บอกว่า ถ้าเริ่มที่ g0 เก็บเงินได้ 5 ในรอบนั้น, g1 เก็บได้ 6, ….

และถ้าเริ่มที่ g0 รอบถัดไปจะเริ่มที่ g2, เริ่ม g1 ถัดไปเริ่มที่ g3, เริ่ม g2 ถัดไปเริ่มที่ g1, …

โจทย์กำหนดมา r รอบ ก็แค่บวก hist แล้ววนตาม next ต่อไป r ครั้งก็น่าจะได้คำตอบแล้ว แต่อาจจะไม่ทัน …

ถ้าสังเกต next ดีๆ จะเห็นว่ามันวนซ้ำๆ

  • g0 –> g2 –> g3 –> g1 –> g2 –> g3 –> g1 –> g2 –> g3 –> g1 –> g2 –> ….
  • g0 –> (g2 –> g3 –> g1 –>)*  ….

จะเห็นว่ามี loop g2 –> g3 –> g1 วนซ้ำไปมา เราสามารถคิดเงินรวมได้เป็น hist[2] + hist[3] + hist[1] และการวนนี้ใช้เวลา 3 รอบ

ถ้าเรารู้ว่าในการเล่นเครื่องเล่น r รอบมันมีการวนแบบนี้เกิดขึ้นกี่ครั้ง ก็เอาจำนวนรอบมาคูณค่าเล่นรวมได้เลย จะลดการคำนวณไปได้มากเลยทีเดียว เพราะบางเคสมันเล่นตั้ง 10^8 รอบ

ข้อนี้โค้ดผมยาวและซับซ้อนผิด concept มาก – -‘ ปัญหาหลักเกิดจากการเลือกใช้ data structure ไม่ถูกต้อง ผมดันไปใช้เป็น linked structure แบบที่เห็นด้านบน ทำให้ทั้งการหา loop อะไรมันทำยากไปหมด ทั้งๆที่มันทำเป็น list ธรรมดาก็ได้แล้ว

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

ว่าด้วย Big Integer

ข้อสองดักคอคนเขียน C++ สุดๆ เพราะ input/output มันเกิน range ของ int, long ไปเยอะมากๆๆ (10^50)

หลังจากไปไล่อ่านโค้ดเพื่อนบ้านมาว่าแต่ละคนแก้ปัญหายังไง เพื่อนบ้านเขียนกันหลายภาษามาก Python, Ruby, C#, C++, Java, Scala, .. ได้ข้อสรุปว่า

  • Python – ไม่ต้องทำอะไร เด๋วมันเพิ่มขนาดให้เอง
  • C/C++ – ปกติใครๆในอินเทอร์เน็ตก็จะแนะนำให้ใช้ GNU MP (GMP – http://gmplib.org/) แต่เชื่อว่าหลายคนเห็นว่าเป็น GNU ก็คงไม่อยากยุ่งด้วยแล้ว ด้วยความชันของการเรียนรู้เพื่อใช้งาน (ผมคนนึงล่ะ) แล้วก็มีคนใช้ http://mattmccutchen.net/bigint/ ผมว่า lib มันดูใช้ง่ายน่าใช้มากเลยอ่ะ บางคนก็เคยเขียน big num ไว้ใช้เอง (จริงๆ)
  • Java BigInteger!
  • C# – เข้าใจว่า pre 4.0 ยังต้องหา lib ข้างนอกมาใช้เอง ส่วนถ้า 4.0+ (Visual Studio 2010) มี System.Numerics.BigInteger ให้ใช้ (พร้อมเมธอด GreatestCommonDivisor) เฉพาะเรื่องนี้ตามหลัง Java ไม่รู้กี่ปี 555+

ส่วนตัวรู้สึกสอบรอบนี้ โจทย์เน้นหนักไปทางคนที่ถนัดคิดแบบ verbally ซะเป็นส่วนใหญ่ (คือคนที่คิดเป็นข้อความ คำพูด พวกตรีโกณมิติ พีชคณิต ทฏษฏีจำนวน) คนที่ถนัดคิดแบบ visually จะเสียเปรียบ

Code Jam 2010 participants from Thailand http://www.go-hero.net/jam/10/regions/Thailand

ใครมีอะไรมาแชร์ คอมเม็นต์มาโลดด~

ว่าด้วย M79

Grenade_launcher_M79_1

ช่วงนี้ตูมตามกันใหญ่ เลยลองไปหาอ่านข้อมูลเพิ่มเติมเกี่ยวกับ M79 มาครับ เผื่อว่าจะมีประโยชน์ในการป้องกันตนเอง พอจะสรุปเป็นประเด็นได้ดังนี้

– M79 มันเป็นชื่อ ปืนยิงระเบิด ไม่ใช่ชื่อของระเบิดจริงๆ จริงๆแล้วมันยิงระเบิดได้หลายแบบมากสังแบบสังหารระยะใกล้ หรือยิงระเบิดระยะไกลแบบที่เจอในไทย

– ระเบิดที่เจอในไทยมีชื่อเรียกเฉพาะจริงๆว่า M406

– ตอนเริ่มยิง หัวระเบิด M406 จะวิ่งออกจากปากกระบอก M79 ด้วยความเร็วประมาณ 75 เมตร / วินาที หรือเท่ารถยนต์ความเร็ว 270 กม. / ชม. … โอ้ววว ที่ยกมาตรงนี้เพราะคิดว่าระหว่างหัวระเบิดวิ่งมันน่าจะมองเห็นทันด้วยตาเปล่าและมี action เช่นการหมอบลงพื้น ได้ทัน

– ตอนระเบิด หัวระเบิด M406 จะให้สะเก็ดระเบิดออกมาประมาณ 300 ชิ้นถ้วนออกมารอบทิศทาง (ถ้าใครไม่คุ้นกับคำว่าสะเก็ดระเบิด ให้คิดว่ามันเป็นกระสุนดีๆนี่เอง) ด้วยความเร็ว 1,524 เมตร / วินาที (อันนี้คงไม่ต้องเทียบกับรถยนต์ เพราะคงรู้นะว่ามันเร็วมาก – -‘’)

– เสียงเดินทางที่ความเร็ว 340 เมตร / วินาที ที่อากาศ 20 °C และความหนาแน่นอากาศระดับน้ำทะเล

– นั่นแปลว่า สะเก็ดระเบิดเดินทางเร็วกว่าเสียง และจังหวะที่เราได้ยินเสียงระเบิด คาดว่าสะเก็ดระเบิดคงฝังในตัวเรียบร้อยแล้ว o__o’ ฮะ!!?! ดังนั้นตอนที่ได้ยินเสียงระเบิด มันไม่มีโอกาสเลยที่จะทำ action เช่นการหมอบ … ยกเว้นจะทำเพื่อหลบระเบิดลูกถัดไป …

– ตัวลูกระเบิดมีระบบรักษาความปลอดภัย … ให้ผู้ยิง (เอ๊ะ!) ด้วยการการรันตีว่าจะไม่ระเบิดภายในระยะ 30 เมตรหลังจากที่มันโดนยิง ดังนั้นถ้าอยู่ใกล้คนยิง 30 เมตรก็จะปลอดภัย …. แต่ถ้าเห็นหน้าคนยิง ก็อาจจะโดนเก็บอยู่ดี =_=’’ โอ้ยย

– ยิงได้ไกลที่ประมาณ 350 – 400 เมตร  แต่ถ้าระเบิดตกใกล้ตัวในรัศมี 5 เมตร (เกือบเท่าตึก 2 ชั้น) การันตีว่าตาย  – -‘’

– ตอนเรียน นศท. (รด. นั่นแหละ) ทหารแตงโมรึเปล่าก็ไม่รู้ สอนว่าให้ “หมอบ” หลบระเบิด เพราะวิถีสะเก็ดระเบิดจะพุ่งออกมาเป็นตัว V แบบรูปด้านล่าง ดังนั้นการหมอบจะมีโอกาสหลบได้เยอะสุด อีกอย่างนึง (อันนี้ไม่แน่ใจ) ให้คว่ำหน้าเอาตาแนบกับมือเป็นการเก็บอวัยวะสำคัญ

Trajectory

– แต่ประเด็นคือระเบิดแบบที่ทหารบอก มัน assume ว่าระเบิดจากที่พื้น  แล้วถ้าระเบิดบนหลังคา BTS หรือต้นไม้ข้างๆ หรือกำแพงตึกล่ะ ??

Trajectory2

– ผมมานั่งคิดๆดูแล้ว คิดว่าสถานการณ์ส่วนใหญ่การหมอบ work สุดนะ เพราะโอกาสมันคงน้อยมากที่จะยิงแล้วไประเบิดบนเพดาน (ซึ่งเป็นกรณีแย่สุดของการหมอบ  – -‘ ) นอกนั้นก็โอเค

– ดังนั้น ผมคิดว่ากรณีทั่วๆไป ถ้าเราสามารถทำนายได้ว่าต่อไปจะมีเหตุระเบิดเกิดขึ้น หรือเห็นคนกำลังชู M79 กำลังจะยิงเลย ให้หมอบไว้น่าจะดีสุด (หวังว่าจะไม่มีใครทะลึ่งวิ่งเข้าไปหลบในระยะ 30 เมตรจากคนยิง +_+)

หวังว่าคงมีประโยชน์ ไม่ว่าฝ่ายไหนจะยิง ตัวเราต้องปลอดภัยไว้ก่อน