[JAVA] Inception Watch step by step
วันนี้เราจะมาทำโจทย์ Inception Watch แบบ step by step
โจทย์ Inception Watch สามารถดาวโหลดได้ที่ลิงค์ http://goo.gl/48Zvudจากบทความเดิมที่ผมเคยเขียนไว้ ACM InceptionWatchQ JAVA วิธีทำ คือ ให้คำนวณกลับจากชั้นสุดท้ายมายังชั้นแรก ในชั้นสุดท้าย (level n) จะคำนวณเวลาของ Tsk ที่ชั้นนั้นได้โดยตรง ส่วนชั้น n-1 ต้องเอาเวลาทั้งหมด(elapsed time) ของชั้น n หารด้วย 12 แล้วบวกกับ Tnext ของชั้นนั้น ก็จะได้ Tsk ของชั้น n-1
อ่านแล้วคงรู้งงๆมาลองคำนวน เพื่อจะช่วยให้เห็นภาพมากขึ้น ซึ่งมองภาพการเขียนโปรแกรมของเราได้ชัดเจนมากยิ่งขึ้นด้วย
1.การวิเคราะห์โจทย์และลองคำนวณผลลัพธ์ด้วยมือก่อนเขียนโปรแกรม
1.1 แปลงเวลาทั้งหมดให้เป็นหน่วยวินาทีทั้งหมดของทุกๆชั้น
โดยอ้างอิงจากโจทย์ตัวอย่างต่อไปนี้
1 48 m
2 6 h
3 2 d
4 24 d
-1
หน่วยเวลาทีควรรู้นะครับ
1 นาที(m) = 60 วินาที
1 ชั่วโมง(h) = 3600 วินาที ->ได้จาก 60*60
1 วัน(d) = 86400 วินาที ->ได้จาก 24*60*60
1 ปี(y) = 31536000 วินาที ->ได้จาก 365*24*60*60
ผลจากการแปลงให้อยู่ในหน่วย วินาที ก็จะได้ตัวเลขดังนี้
0 0
1 2880
2 21600
3 172800
4 2073600
1.2 การคำนวน inception watch โดยใช้สูตร
sum = sum / 12 +incept[i - 1].getNumSecond();
โดยกำหนดให้
sum คือ ตัวแปรสำหรับเก็บผลลัพธ์
Incept[i - 1].getNum() คือ จำนวนเวลาในหน่วยวินาที ในชั้นรองจากชั้นปัจจุบันที่เราอยู่
i คือ ชั้นปัจจุบันที่เราอยู่
getNumSecond () คือ เป็นฟังก์ชันก์สำหรับการดึงจำนวนเวลาในหน่วยวินาทีของชั้น i -1
Incept คือ เป็น object ที่เก็บลำดับชั้นจำนวนเวลาในวินาที
วิธีทำ
เริ่มจากชั้นที่ 5ค่า ณ ปัจจุบัน sum = 0 , Incept[i - 1].getNum() = 2073600, i = 5
แทนค่า sum = 0/ 12 + 2073600
sum = 2073600;
ชั้นที่ 4
ค่า ณ ปัจจุบัน sum = 2073600 , Incept[i - 1].getNum() = 172800 , i = 4
แทนค่า sum = 2073600 / 12 + 172800
sum = 345600
ชั้นที่ 3
ค่า ณ ปัจจุบัน sum = 345600 , Incept[i - 1].getNum() = 21600 , i = 3
แทนค่า sum = 345600 / 12 + 21600
sum = 50400
ชั้นที่ 2
ค่า ณ ปัจจุบัน sum = 50400 , Incept[i - 1].getNum() = 2880 , i = 2
แทนค่า sum = 50400 / 12 + 2880
sum = 7080
ชั้นที่ 1
ค่า ณ ปัจจุบัน sum = 7080 , Incept[i - 1].getNum() = 0 , i = 1
แทนค่า sum = 7080 / 12 + 0
sum = 590
เป็นอันเสร็จการคำนวน แล้วเราจะมาแสดงค่ายังไงล่ะ เราก็เรียงจากด้านล่างไปด้านหน้าก็จบ
590
7080
50400
345600
2073600
ส่วนการทำให้ได้ตัวเลขแสดง 10 หลักอ่านลงไปด้านล่างของบทความก็จะเจอครับ
2.การออกแบบการเขียนโปรแกรมที่เราได้วิเคราะห์มา
หลังที่เราวิเคราะห์โจทย์แล้ว เราวิเคราะห์ในส่วนของโปรแกรมที่เราจะเขียน โดยเราจะใช้หลักการ OOP เข้ามาเป็นหลักเกณฑ์ในการคิด คือ class InceptinWatch ควรจะมีคุณสมบัติอะไรบ้าง (attribute หรือจะเรียกว่า ตัวแปรก็ได้นะ) มีการกระทำอะไรบ้าง(Method) หรือ จะเรียกว่า ฟังก์ชั่นการทำงาน
class InceptinWatch ควรจะมีคุณสมบัติดังนี้ คือ
attribute
int level = 0; //เอาไว้เก็บ level หรือลำดับชั้น
int numSecond= 0; //เอาไว้เก็บผลการแปลงเวลาในหน่วยวินาทีของ object
Method
convertToSecondUnit(int numc,char c) //Method สำหรับแปลงเวลาให้อยู่ในหน่วยวินาที
position9(String s) //Method สำหรับ ทำตำแหน่งตัวเแลข 9 ตำแหน่ง
main(String[] args) //เอาไว้ทำงานในส่วน main ของโปรแกรม
ตามความคิดผมว่า...ที่สำคัญๆ หลักๆของโปรแกรมเราควรจะมีแค่นี้ล่ะครับซึ่งเวลาเราเขียนจริงๆ ก็จะเกิดไอเดียร์ใหม่ๆ ทำให้สามารถเพิ่มหรือลดความยาวของบรรทัดของโปรแกรมได้ครับ
ตามความคิดผมว่า...ที่สำคัญๆ หลักๆของโปรแกรมเราควรจะมีแค่นี้ล่ะครับซึ่งเวลาเราเขียนจริงๆ ก็จะเกิดไอเดียร์ใหม่ๆ ทำให้สามารถเพิ่มหรือลดความยาวของบรรทัดของโปรแกรมได้ครับ
3. เริ่มเขียนโปรแกรม
จากที่ได้วิเคราะห์และคำนวนจนได้ผลลัพท์เรียบร้อยแล้ว ต่อไปเรามาเริ่มเขียนโปรแกรมกันแล้วนะครับ ขั้นแรกก็ New Project
รูปการ New Project ใหม่ |
รูป การตั้งชื่อโปรเจก |
ให้เราทำการ คลิกขวาที่ default package แล้วก็ new > Java Class
พอได้แล้วก็ ตั้งชื่อให้เหมือนกันกับชื้อโปรเจก ดังรูป แล้วก็กด finish
พอกดเสร็จ มันก็จะเจนค่าให้ดังรูป
ทีนี้ก็ได้ Class InceptionWatch มาแล้ว ซึ่งตอนนี้ยังไม่สามารถ run โปรเจกได้เนืองจากยังไม่มี Mathode main ให้เราพิมพ์
public static void main (String [] args){
}
ให้พิมพ์ ภายใต้ class InceptionWatch นะครับ ดังรูปด้านล่าง
ก่อนที่จะเริ่มเขียนโปรแกรมผมจะเช็คดูก่อนว่า โปรแกรมมีการรับค่าแสดงผลอย่างไร ซึ่งในโจทย์นี้มันจะเป็นการวนรับค่าไปเรื่อยๆ จนกว่า input ที่เข้ามาเป็น "-1" ค่อยแสดงผลลัพธ์ออกมา เรามาลองทำตามเงื่อนไขนี้ดู ซึ่งมันจะช่วยให้เรากำหนดรูปแบบโปรแกรมที่จะเขียนได้
สิ่งที่เราต้องการ
- จะมีการรับค่ามาจากคีย์บอร์ด
- วนรับค่าเรื่อยๆจนกว่า input เป็น " -1" ค่อยออกจากลูป
- จะมีการเก็บค่าระหว่างที่รอให้ input เป็น "-1"
- แสดงค่า ที่เก็บไว้เมื่อ input เป็น "-1"
จากรูป
- รับค่าเราใช้ Scanner ในการรับข้อมูลจากคีย์บอร์ด
- การวนลูป รับค่าเรื่อยๆ เราใช้ while (true)
- การเก็บมูลระหว่างที่รอให้ input เป็น "-1" เราใช้ ArrayList<String> เป็น Array ชนิด String
พอเราเข่าใจ input / output ของโปรแกรมแล้ว เราก็มาเขียนโปรแกรมตามที่เราวิเคราะห์ไว้ครับ
มาเขียนที่ล่ะ step ตามที่ผมทำ
step 1 แปลงหน่วย m , h , d ให้อยู่ในหน่วย s แล้วก็เก็บค่า level กับ numSecond ใส่ในออปเจกให้ครบตาม input ที่เข้ามา แล้วก็แสดงค่าค่าทั้งหมดเมื่อ input = "-1"
import java.util.Scanner; public class InceptionWatchQ { //attribute private int level; //เก็บ level private int numSecond; //เก็บ ผลการแปลงเวลาในหน่วยวินาที ของ opject //methode สำหรับดึง ค่า level private int getlevel(){ return level; } //สำหรับดึง ค่า numSecond private int getNumSecond(){ return numSecond; } //แปลงเวลาให้อยู่ในหน่วยวินาที public int convertToSecondUnit(int numc,char c){ switch(c){ case 's': return numc *= 1; // 1 วินาที case 'm': return numc *= 60; //1 นาที = 60 วินาที case 'h': return numc *= 3600; //1 ชั่วโมง = 3600 วินาที = 60*60 case 'd': return numc *= 86400; //1 วัน = 86400 วินาที = 24*60*60 case 'y': return numc *= 31536000;//1 ปี = 31536000 วินาที = 365*24*60*60 default : return numc = 0; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); String input; //เอาไว้เก็บ input String [] textIn = new String[3]; //เอาไว้เก็บ level , num , unit InceptionWatchQ[] incept = new InceptionWatchQ[10]; //เพราะว่า โจทย์กำหนด level 0-9 int sum =0; //เก็บผลลัพธ์ ในการคำนวน int levels = 0; //นับจำนวนชั้น while (true) { //วนรับค่าเรื่อยๆ input = sc.nextLine(); //รับค่ามาจากคีย์บอร์ด if (!input.equals("-1")) { // input ไม่เป็น " -1" textIn = input.split(" ");//แยก level , num , unit incept[levels] = new InceptionWatchQ(Integer.parseInt(textIn[0]),Integer.parseInt(textIn[1]),textIn[2].charAt(0)); levels++; //ก็ให้เก็บมูลลงให้ list } else { // input เป็น " -1" ก็ให้แสดง list ทั้งหมด //print รายการทีเก็บไว้ for(int i = 0 ; i< levels ; i++){ System.out.println(incept[i].getlevel()+ " " + incept[i].getNumSecond()); } } } } }หมายเหตุ
- InceptionWatchQ[] incept = new InceptionWatchQ[10]; เป็นการสร้าง Opject แบบ Array โดยประกาศจอง array 10 ช่อง
- incept[levels] = new InceptionWatchQ(Integer.parseInt(textIn[0]),Integer.parseInt(textIn[1]),textIn[2].charAt(0)); เป็นการเก็บค่า level ,num,unit ใส่ในออปเจก incept[levels]
ผลการรันโปรแกรม step 1
ผลการรัน step 1 |
/* * แก้ปัญหาโจทย์ Inception Watch * @author http://javaagkasit.blogspot.com */ import java.util.ArrayList; import java.util.Scanner; public class InceptionWatchQ { //attribute private int level;//เก็บ level private int numSecond;//เก็บ ผลการแปลงเวลาในหน่วยวินาที ของ opject //คอนทรักเจอร์ public InceptionWatchQ(int _level,int _numSecond,char unit){ this.level = _level; this.numSecond = convertToSecondUnit(_numSecond,unit); } //คอนทรักเจอร์ โอเว่อโลดดิ่ง public InceptionWatchQ(int _level,int _numSecond){ this.level = _level; this.numSecond = _numSecond; } //สำหรับดึง ค่า level private int getlevel(){ return level; } //สำหรับดึง ค่า numSecond private int getNumSecond(){ return numSecond; } //แปลงเวลาให้อยู่ในหน่วยวินาที public int convertToSecondUnit(int numc,char c){ switch(c){ case 's': return numc *= 1; // 1 วินาที case 'm': return numc *= 60; //1 นาที = 60 วินาที case 'h': return numc *= 3600; //1 ชั่วโมง = 3600 วินาที = 60*60 case 'd': return numc *= 86400; //1 วัน = 86400 วินาที = 24*60*60 case 'y': return numc *= 31536000; //1 ปี = 31536000 วินาที = 365*24*60*60 default : return 0; } } //method main public static void main(String[] args) { Scanner sc = new Scanner(System.in); String input; //เอาไว้เก็บ input String [] textIn = new String[3]; //เอาไว้เก็บ level , num , unit InceptionWatchQ[] incept = new InceptionWatchQ[10];//เพราะว่า โจทย์กำหนด level 0-9 int sum =0; //เก็บผลลัพธ์ ในการคำนวน int levels = 0;//นับจำนวนชั้น ArrayListจาก code ด้านบน ตัวหนังสือสีแดงคือ คำสั่งที่เพิ่มขึ้นจาก step 1lists; //ประกาศตัวเเปร list ไว้เก็บผลลัพท์ while (true) { //วนรับค่าเรื่อยๆ input = sc.nextLine(); //รับค่ามาจากคีย์บอร์ด if (!input.equals("-1")) { // input ไม่เป็น " -1" textIn = input.split(" "); //แยก level , num , unit incept[levels] = new InceptionWatchQ(Integer.parseInt(textIn[0]),Integer.parseInt(textIn[1]),textIn[2].charAt(0)); levels++; //ก็ให้เก็บมูลลงให้ list } else { // input เป็น " -1" ก็ให้แสดง list ทั้งหมด lists = new ArrayList (); for(int i = levels; i > 0 ; i--){ sum = sum / 12 + incept[i - 1].getNumSecond(); //คำนวน lists.add(new InceptionWatchQ(incept[i-1].level,sum)); //เก็บผลลัพธ์ } //print รายการทีเก็บไว้ for(int i = lists.size()-1 ; i >= 0 ; i--){ System.out.println(lists.get(i).level +" "+lists.get(i).numSecond); } //เคียร์ข้อมูลทั้งหมด lists.clear(); // เคลีย์ lists levels = 0; //เคลีย์ levels = 0 sum =0; // เคลีย์ sum =0 } } } }
หมายเหตุ
ArrayList<InceptionWatchQ> lists; //เป็นการเก็บข้อมูล ชนิดที่เป็น object
ผลการรันโปรแกรม step 2
step 3 จากนั้นก็เหลือแค่ ทำให้ตัวให้เป็น 10 วิธี ทำโดยการเอาตัวเลข lists.get(i).numSecond มาให้ให้เป็น 9 หลัก แล้วเอา 9 หลักที่ได้มารวมกันกับ lists.get(i).level ก็จะได้ตัวเลข 10 หลัก
//ทำตำแหน่งตัวเแลข 9 ตำแหน่ง public static String position9(String s){ char c = 0 ; for(int i = 0 ; i < 10;i++){ if(i > s.length()){ s = "0"+s; } } return s; }หลักการคือ ถ้าค่า i มากว่า ความยาวของ s.length() ก็ให้เพิ่มเข้าไปหน้าของ ตัวเลข
ส่วนการใช้งาน methode position9() ก็ง่ายๆ
//print รายการทีเก็บไว้ for(int i = lists.size()-1 ; i >= 0 ; i--){ System.out.println(lists.get(i).level +""+position9(lists.get(i).numSecond+"")); }
ผลการรันโปรแกรม step 3
เป็นอันเสร็จสิ้นการ เขียนโปรแกรม Inception Watch แบบ step by step จะเห็นได้ว่าทุกสิ่งอย่างที่เขียนไป มันขึ้นกับตัวผู้เขียนโปรแกรมเองว่ามีความเข้าใจโจทย์อย่างแท้จริงหรอยัง ถ้าคิดไม่ออกก็ถามพี่ google และที่สำคัญเราจะเขียนโปรแกรมได้สักโปรแกรมสิ่งแรกคือ จินตนาการ ใครที่ยังไม่เข้าก็ ดาวโหลดโปรเจกไปลองไล่ดูครับตามลิงค์นี้เลย http://www.mediafire.com/?qkp99h84kk9h5hq ผมก็จบเพียงแค่นี้ครับเจอกันใหม่บทความหน้า....
อาจอธิบายได้ไม่ละเอียดพอ ศึกษาเพิ่มได้ที่
- การใช้ for http://javaagkasit.blogspot.com/2012/08/for.html- การใช้ switch casehttp://javaagkasit.blogspot.com/2012/08/switch-case.html
- การใช้ if else http://javaagkasit.blogspot.com/2012/08/if-else.html
- การใช้ while loop http://javaagkasit.blogspot.com/2012/09/while-loop.html
- Class และ object คืออะไร http://javaagkasit.blogspot.com/2012/09/class-object.html
- เข้าใจ Java method main
- ArrayList คืออะไร
- this คืออะไร
- Constructor คืออะไรhttp://javaagkasit.blogspot.com/2012/09/constructor.html
- Encapsulation คืออะไร
- การสร้างโปรเจกใน NetBeans IDEhttp://javaagkasit.blogspot.com/2012/09/netbeans-ide.html