ดูแล้วน่ารักดีครับ ลองหาคร่าวๆ เจอเท่านี้ ใครเจออะไรอีกสะกิดบอกกันได้ :D









Politics is for the present, but an equation is something for eternity.
-- Albert Einstein
E = mc2
ที่เปรียบได้ดั่งกุญแจไขความลับจักรวาลว่าสสารและพลังงานนั้นแท้จริงแล้วรากฐานเป็นสิ่งเดียวกัน อย่าลืมว่าผลลัพธ์จากสมการนี้ทำให้เกิดอาวุธที่น่ากลัวที่สุดที่มนุษย์เคยสร้างมาself.c
การสั่งคำสั่ง diff
ครั้งสุดท้ายในโค้ดต่อไปนี้ต้องให้ค่าคืนมาเป็นว่า 2 ไฟล์มีเนื้อหาเหมือนกัน$ gcc self.c $ ./a.out > other.c $ diff self.c other.cเนื่องจากคุ้นว่าจะเคยเห็นคำถามแนวนี้ใน Ruby มาก่อนแล้ว ตอนแรกก็ไม่ได้คิดว่าจะลองทำหรอก แต่เท่าที่สังเกตแล้วจุดที่น่าจะเป็นปัญหาน่าจะมาจากเรื่อง escape string ซึ่งใน Python มันคงไม่ยุ่งยากเท่าไหร่ เพราะมี raw string และฟังก์ชั่น
repr
ไว้คอยจัดการปัญหา escape string อยู่แล้วvoid main() { int i = 0, j = 0; char* x = "void main() {\n\tint i = 0, j = 0;\n\tchar* x = \"%s\";\n\twhile (x[i]) {\n\t\tif (x[i++] == '%%' && x[i++] == 's') {\n\t\t\twhile (x[j]) {\n\t\t\t\tswitch (x[j++]) {\n\t\t\t\t\tcase '\\n': putchar('\\\\'); putchar('n'); break;\n\t\t\t\t\tcase '\\t': putchar('\\\\'); putchar('t'); break;\n\t\t\t\t\tcase '\\\"': putchar('\\\\'); putchar('\"'); break;\n\t\t\t\t\tcase '\\\\': putchar('\\\\'); putchar('\\\\'); break;\n\t\t\t\t\tdefault: putchar(x[j-1]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tputchar(x[i-1]);\n\t\t}\n\t}\n}\n"; while (x[i]) { if (x[i++] == '%' && x[i++] == 's') { while (x[j]) { switch (x[j++]) { case '\n': putchar('\\'); putchar('n'); break; case '\t': putchar('\\'); putchar('t'); break; case '\"': putchar('\\'); putchar('"'); break; case '\\': putchar('\\'); putchar('\\'); break; default: putchar(x[j-1]); } } } else { putchar(x[i-1]); } } }ไม่ได้จับ C มาหลายปี หมดพลังไปเยอะกว่าคิดออก 555+
พอดีเดือนก่อนปิดเทอมกลับบ้านนานครับ เลยยกเลิกเน็ตหอไป พอกลับมาแล้วยังไม่ครบรอบ เลยไม่ได้กลับมาต่อเน็ตไวไฟ ใช้แต่บนมือถืออย่างเดียว
ก็เป็นประสบการณ์ที่แปลกดีนะ วันแรกๆ รู้สึกจดจ่อกับงานได้ดีขึ้นเยอะมาก ไม่มีสิ่งกวนใจเลย
แต่พอทำไปทำมาแล้วเจอปัญหาใหญ่ครับ เพราะต้องพึ่ง Google, StackOverflow บ่อยๆ ครั้นจะหาในมือถือจอเล็กๆ แล้วพิมพ์ code ซ้ำในคอมก็ลำบากไปหน่อย กลายเป็นว่าวันหลังๆ นี่งานเดินช้ากว่าช่วงที่มีเน็ตไวไฟซะอีก
เดี๋ยวว่าจะกลับไปติดเน็ตคืนละครับ แล้วค่อยหาวิธีคุมสิ่งกวนใจด้วยวิธีอื่นแทน งานนี้ถือว่า trade-off ไม่คุ้มซะเท่าไหร่ :s
list = [2, 4, 6, 8] sum = 0 for num in list: sum = sum + num print("The sum is:", sum)เรียบง่ายและงดงาม...
list
กับ sum
ซึ่งทั้ง 2 ชื่อนี้ เป็นชื่อของฟังก์ชันมาตฐาน ถึงแม้ว่าจะไม่มีข้อห้ามให้ประกาศชื่อซ้ำได้เหมือนกับพวก reserved keyword แต่การทำเช่นนี้ก็บาปมากเพราะ 2 ฟังก์ชันนี้จะไม่สารมารถถูกเรียกใช้ได้โดยง่ายอย่างที่ตัวภาษาออกแบบไว้sum
สำหรับหาผลรวมของชุดตัวเลขให้ใช้งาน นอกจากจะเขียนได้ง่ายและทำงานเร็วกว่าแล้ว มันยังสร้างสุขลักษณะที่ดีต่อการเขียนโปรแกรมสำหรับใช้งานในโลกจริงด้วยnumbers = [2, 4, 6, 8] product = 1 for number in numbers: product = product * number print("The product is:", product)เพราะการสร้างตัวอย่างที่ดีไม่ใช่เรื่องง่ายๆ
counter = 0 for file in glob('*.cpp'): if '//' in file.read(): counter += 1 print(counter)โค้ดนี้ทำงานได้ดีเลยแหละ ติดตรงที่ไฟล์ที่นำมาวิเคราะห์บางไฟล์ก็ใช้ encoding แปลกๆ แล้วเปิดอ่านไม่ได้ (ยังงงอยู่ว่า Python ไม่เช็คว่าเป็น ASCII หรือ UTF-8 ให้อัติโนมัติ?) ก็แก้ๆ โค้ดด้านบนนี้โดยใช้โมดูล
codecs
เข้าช่วย ไม่มีปัญหาอะไรcounter=0 for file in *.cpp do grep -q '//' "$file" && : $((counter++)) done echo $counterผลลัพท์ออกมาไม่ต่างกับ Python ด้านบน แต่ว่า Bash ทำงานช้ามากกกกก (ก.ไก่ 140 ตัว) ตอนแรกก็คิดว่า Bash มันน่าจะทำลูปไม่เก่งมั้ง เพราะเท่าที่อ่านโค้ดของโครงการ Linux ก็ไม่ค่อยเห็นเขียนลูปกันเท่าไหร่ แต่พอลองเขียนลูปเปล่าแสนรอบใน Bash มันก็ไม่เห็นจะช้า เลยคิดว่าน่าจะเป็นที่
grep
มั้ง? แต่ก็ไม่อยากจะเชื่ออยู่ดีเพราะเคยอ่านงานของ Russ Cox ก็ไม่เห็นว่า grep
มันจะช้าซักเท่าไหร่time
จับเวลาดู โอ้ว user กับ sys ใช้เวลาพอๆ กันเลยแฮะgrep
แต่ละครั้งเป็น process ใหม่เลย ต้องรอให้ system จองทรัพยากรเสร็จก่อนจึงจะใช้งานได้ แถมพอจบงานก็ทำลาย process นี้ทิ้งซะอีก ไม่ได้จัดสรรทรัพยากรอะไรกันระหว่างลูปเลย ... เทียบง่ายๆ คงเหมือนกับการที่มีเตารีดแสนอัน เสียบปลั๊กเตารีดตัวแรกรอร้อนแล้วจึงรีดผ้าหนึ่งชิ้น พอผ้าชิ้นนี้เรียบเนี๊ยบจนพอใจก็ถอดปลั๊กเตารีดซะงั้น แล้วไปเสียบปลั๊กเตารีดอีกตัวมารีดผ้าอีกชิ้นนั่นเองgrep -l '//' *.cpp | wc -lคราวนี้เร็วส์เสียยิ่งกว่า Python อีก :P
:
(colon ตัวเดียว) ซึ่งเป็นคำสั่งที่ไม่ทำอะไรเลย> # ตั้งตัวแปรไว้ใช้ดีกว่า > foo="hahaha" > # ทำงานอื่นไปเรื่อยๆๆๆๆ > # เอ๊ะ ตัวแปร $foo โดนเปลี่ยนค่า (?) ไปเป็นอะไรแล้วนะ? > $foo hahaha: command not foundด้านบนนี้เป็น user error เอง อยากดูค่าก็อย่าลืม
echo
สิ :P> i=0 > for f in * > do > [ -s "$f" ] && i=$((i+1)) > done > echo $iโค้ดด้านบนนี้จะถามว่าไฟล์ในแฟ้มปัจจุบัน มีกี่ไฟล์ที่มีเนื้อหา (ขนาดไม่เป็น 0 byte) ซึ่ง counter จะเพิ่มขึ้นตรงหลังเครื่องหมาย && นั่นเอง
> i=0 > for ... > do > # ทำอะไรซักอย่าง > i=$((i+1)) > doneเขียนไปเขียนมาจะพบว่า
i=$((i+1))
มันตลกสิ้นดี ยิ่งเมื่อรู้ว่า Shell เขียน i++
ได้! แต่อย่าลืมว่าถ้าเปลี่ยนไปเขียนตรงๆ ก็จะเจอปัญหาเดิม> $((i++)) 0: command not foundทั่วไปแล้ว การเขียนในแนวนี้จะเป็นการสร้างตัวนับเพื่อบอกว่า process นี้ทำงานไปถึงไหนแล้ว ซึ่งมันสามารถเอาไปแทรกไว้กับคำสั่ง
echo
ได้> echo "now doing item number: $((++i))"แต่ถ้าไม่ต้องการให้มัน
echo
อะไรระหว่างทางหละ? นี่แหละคือจุดยืนของคำสั่ง :
> : $((i++))ป.ล. Shell รุ่นเก่าๆ ไม่มีคำสั่ง
true
เลยต้องใช้คำสั่ง :
แทนdef foo(answer_1, matrix_1, answer_2, matrix_2): candidate_1 = matrix_1[answer_1-1] candidate_2 = matrix_2[answer_2-1] final = set(candidate_1) & set(candidate_2) if len(final) == 0: return 'Volunteer cheated!' elif len(final) > 1: return 'Bad magician!' else: return final.pop() for case in range(int(input())): answer_1 = int(input()) matrix_1 = [[int(n) for n in input().split()] for _ in range(4)] answer_2 = int(input()) matrix_2 = [[int(n) for n in input().split()] for _ in range(4)] answer = foo(answer_1, matrix_1, answer_2, matrix_2) print('Case #{}: {}'.format(case+1, answer))
def optimal_cookie(new_farm_cost, prodct_cookie, finale_cookie): income_cookie = 2.0 optimal_spent = 0 while True: new_farm_time = new_farm_cost / income_cookie expect_cookie = prodct_cookie + income_cookie wait_win_time = finale_cookie / income_cookie upgd_win_time = finale_cookie / expect_cookie + new_farm_time if wait_win_time > upgd_win_time: income_cookie = expect_cookie optimal_spent += new_farm_time else: optimal_spent += wait_win_time break return optimal_spent for case in range(int(input())): answer = optimal_cookie(*[float(n) for n in input().split()]) print('Case #{}: {:.7f}'.format(case+1, answer))
from collections import deque def normal_war(ns, ks): c = 0 while ns: n = ns.pop() if ks[-1] < n: ks.pop(0) c += 1 else: i = 0 while n > ks[i]: i += 1 ks.pop(i) return c def deceitful_war(ns, ks): while any(n < k for n, k in zip(ns, ks)): ns.popleft() and ks.pop() return len(ns) for case in range(int(input())): _ = input() ns = sorted(float(n) for n in input().split()) ks = sorted(float(n) for n in input().split()) dw_answer = deceitful_war(deque(ns), deque(ks)) nw_answer = normal_war(ns[:], ks[:]) print('Case #{}: {} {}'.format(case+1, dw_answer, nw_answer))
Case #0: Case #1: Case #2: Case #3: c... c... c... c... .... .... .... .... .... .... .... ...* .... ...* ..** ..** Case #4: Case #5: Case #6: Case #7: c..* c..* c..* c..* ...* ...* ...* ...* ...* ...* ..** ...* ...* ..** ..** **** Case #8: Case #9: Case #10: Case #11: c.** Impossible c.** Impossible ..** ..** ..** ..** ..** **** Case #12: Case #13: Case #14: Case #15: c.** Impossible Impossible c*** ..** **** **** **** **** ****ส่วน code ก็หน้าตาประมาณ
def transpose(matrix): return [list(line) for line in zip(*matrix)] def fill_line(r, c, left): width, length = sorted([r, c]) matrix = [['*' for _ in range(length)] for _ in range(width)] for i in range(width): matrix[i][:left//width] = ['.' for _ in range(left//width)] matrix[0][0] = 'c' return matrix if r == len(matrix) else transpose(matrix) def fill_rect(r, c, left): width, length = sorted([r, c]) sq_length = int(left**0.5) matrix = [['*' for _ in range(width)] for _ in range(length)] if sq_length > width: i = 0 while left - width > 0: matrix[i] = ['.' for _ in range(width)] left -= width i += 1 if left == 1: matrix[i-1][-1:] = ['*'] matrix[i][:2] = ['.' for _ in range(2)] else: matrix[i][:left] = ['.' for _ in range(left)] else: i = 0 while i < sq_length: matrix[i][:sq_length] = ['.' for _ in range(sq_length)] left -= sq_length i += 1 if left > sq_length: if left == sq_length + 1: matrix[i][:sq_length-1] = ['.' for _ in range(sq_length-1)] left = 2 else: matrix[i][:sq_length] = ['.' for _ in range(sq_length)] left -= sq_length if i == len(matrix)-1: matrix = transpose(matrix) else: i += 1 matrix[i][:left] = ['.' for _ in range(left)] elif left > 0: if left == 1: matrix[i-1][sq_length-1:sq_length] = ['*'] left = 2 matrix[i][:left] = ['.' for _ in range(left)] matrix[0][0] = 'c' return matrix if r == len(matrix) else transpose(matrix) def mine_fill(r, c, m): width = min(r, c) left = r * c - m if width == 1: if left == 0: return None return fill_line(r, c, left) if width == 2: if left in [0, 2] or left % 2 == 1 and left != 1: return None return fill_line(r, c, left) else: if left in [0, 2, 3, 5, 7]: return None return fill_rect(r, c, left) for case in range(int(input())): r, c, m = [int(n) for n in input().split()] answer = mine_fill(r, c, m) print('Case #{}:'.format(case+1)) if answer is None: print('Impossible') else: for line in answer: print(''.join(line))ข้อนี้เสียดายมากที่หา bug ไม่เจอ มาเจออีกทีตอนแข่งจบไปแล้ว ไม่งั้นรอบนี้คงได้ทำคะแนนเต็มให้เป็นเกียรติเป็นศรี \(TwT)/
read_only = 42 def f(x): return read_only + x print(f(10)) # 52หรือกระทั่ง
ls = [4, 8, 15, 16, 23, 42] def g(x): ls.append(x) g(99) print(ls) # [4, 8, 15, 16, 23, 42, 99]ความประหลาดและน่ารำคาญใน PHP คือเราไม่สามารถเขียนแค่นี้เพื่อทำ closure ง่ายๆ ตามข้างบนได้ เพราะเมื่อเราสร้างฟังก์ชันขึ้นมาแล้ว ฟังก์ชันนั้นจะไม่รู้จักตัวแปรใดๆ เลย (ยกเว้นพวก superglobals อย่าง
$_GET
) เราต้องเพิ่ม keyword global
เข้าไปอีก เช่น$ls = array(4, 8, 15, 16, 23, 42); function g($x) { global $ls; $ls[] = $x; }ซึ่งท่านี้ก็ยังมีปัญหาอีกว่าถ้าตัวแปรที่ต้องการไม่อยู่ใน global scope (เช่นไปอยู่ใน local scope ของฟังก์ชันที่สร้างฟังก์ชันนี้อีกที) PHP ก็จะหาตัวแปรนั้นไม่เจอ
use
เช่นนี้$ls = array(4, 8, 15, 16, 23, 42); $g = function($x) use($ls) { $ls[] = $x; return $ls; };แน่นอนว่าเมื่อทำแบบ functional แล้ว ตัวแปร
$ls
เก่าจะไม่เปลี่ยนค่า เพราะเมื่อมันถูกเรียกผ่าน use
นั่นหมายถึงการคัดลอกค่าตัวแปรมาทั้งหมด แล้วตั้งชื่อตัวแปรให้เหมือนกันใน scope ต่างกัน แต่ถ้าอยากให้ตัวแปรเดิมเปลี่ยนค่าก็ยังสามารถใช้เทคนิคเดิมได้คือfunction($x) use(&$ls) { ... }อย่างไรก็ตาม ท่านี้ยังมีปัญหาตรงที่การประกาศฟังก์ชันต้องทำแบบ anonymous (แล้วค่อยเอาตัวแปรไปรับ) แถมถ้าเราจะอ้างค่าใน scope อื่นเป็นจำนวนมาก ที่หัวฟังก์ชันจะเขียนได้รุงรังอย่าบอกใคร
global
หรือ use
สำหรับเรียกตัวแปรนอก scope คือ PHP อนุญาตให้ไม่ต้อง init ตัวแปรก็ได้ (ถ้าไม่มีการ init มาก่อน มันจะถือว่าเป็นค่าว่างตามการใช้งานนั้นๆ) ทำให้เราสามารถเขียนอะไรเช่นนี้ได้function query_to_array() { $res = mysql_query('SELECT * FROM blah_blah_blah'); foreach ($res as $row) { $ls[] = $row['foo_blah']; } return $ls; }เราอาจมองว่าท่านี้สวยตรงที่ไม่ต้อง init ตัวแปร
$ls
ที่รู้ๆ กันอยู่แล้วว่าต้องเป็น array ว่างแน่ๆ แต่ถ้าเกิดว่า query ข้างบนให้ผลลัพท์เป็นเซ็ตว่าง ตอน return เอาไปใช้ต่อจะเกิด bug เพราะ PHP ไม่สามารถบอก type ของ $ls
ได้ สุดท้ายก็ต้องกลับไปประกาศตัวแปรไว้ที่จุดเริ่มต้นฟังก์ชันอยู่ดี หรือไม่งั้นก็เปลี่ยน return เป็นreturn $ls ?: array();
$db = new PDO('mysql: ...'); $res = $db->prepare('SELECT * FROM blah_blah_blah WHERE answer = ?'); $res->execute(array(42));ในความจริงแล้ว ขั้นตอน prepare/execute มักถูกเขียนในส่วนอื่นๆ ไม่เอาไว้ติดกันเช่นนี้ ยิ่งไปกว่านั้นมันมักโดน refactor ไว้ในฟังก์ชันเพื่อจัดระเบียบให้อ่านง่ายด้วย ในเมื่อตัวแปร
$db
ที่ควรเป็น global ดันไม่สามารถเรียกใช้ได้ง่ายๆ ใครมันจะอยากเขียนแบบ OOP กันหละ?$db
เข้าไป ก็คือเราสามารถเข้าถึง database ได้โดย $this->db
ซึ่งท่านี้ก็ยังรุงรังเหมือนเดิม แถมตอนเรียกใช้ก็ยังต้องพิมพ์ยาวขึ้นอีกด้วย$res = DB::select('SELECT * FROM blah_blah_blah WHERE answer = ?', array(42));เพราะว่า class และฟังก์ชันใน PHP สามารถเรียกใช้จาก scope ไหนๆ ก็ได้ครับ
ควรมี flash game ถีบเนยสดได้แล้ว คือจับเวลา 1 นาที ให้เราพิมพ์คำว่าถีบเนยสดให้ได้มากที่สุด แล้วแมวเนยสดก็หน้าน่วมๆไปด้วยไรงี้ เก็บสถิติด้วย
— แม็คคลี่ (@McKiEz) December 14, 2013
position: absolute
สิครัชในตอนเด็กเรามักคิดว่าเมื่อเป็นผู้ใหญ่แล้ว จะทำอะไรก็ได้ แต่พอโตขึ้นมาแล้ว ถึงรู้ว่าตอนเป็นเด็กต่างหาก ที่จะทำอะไรก็ได้
— ไอ้เชี้ยอ้วน (@BestzFail) February 2, 2014
Power tends to corrupt, and absolute power corrupts absolutely. Great men are almost always bad men.
-- Lord Acton
!
) และสิ่งที่น่าตกใจยิ่งกว่าคือคำตอบที่ว่า 0!=1
เมื่อถามต่อว่าทำไมก็จะได้รับคำตอบว่ามันเป็นนิยาม ซึ่งจริงๆ ก็ถูกต้องแล้วแหละ แต่หลายคนคงอยากให้มันมีความหมายที่ลึกซึ้งกว่านั้นn!
นั้นคือการหาผลคูณจาก 1
ขึ้นไปเรื่อยๆ จนถึง n
การหา 1!
ได้จึงไม่แปลก เพราะมันคือผลคูณจาก 1
ไปจนถึง 1
(ซึ่งก็คือไม่ต้องคูณเลยซักตัว) แต่ถ้าคิดตามนิยามนี้ 0!
ก็ไม่มีตัวตนเพราะว่า 1
มีค่ามากกว่า 0
(แล้วเราจะคูณขึ้นไปเรื่อยๆ ได้ยังไง!?) ตอนนี้ถ้าเราอยากให้ 0!
มีค่าก็ต้องหาวิธีคำนวณ/นิยายามที่มีเหตุผลขึ้นมาเพื่อให้คนอื่นยอมรับค่านั้นๆ ... ซึ่งแน่นอนว่ามันไม่ใช่การเปลี่ยนนิยามข้างต้นเป็น n!
คือผลคูณจาก 0
ขึ้นไปเรื่อยๆ จนถึง n
แน่ :Pn!=n(n-1)!
จะเห็นว่าสูตรนี้เป็น recursive การจะหาผลลัพท์ได้นั้น ต้องมองย้อนกลับไป 1 ขั้นเสมอ ในทำนองเดียวกัน ถ้าเรารู้ผลลัพท์ของขั้นตอนปัจจุบัน เราอาจจะสามารถย้อนกลับไปคำนวณผลลัพท์สำหรับขั้นตอนก่อนหน้าได้ ดังนั้น5! = 120 = 5 * 4! 4! = 24 = 4 * 3! 3! = 6 = 3 * 2! 2! = 2 = 2 * 1! 1! = 1 = 1 * 0!เลขตัวเดียวที่คูณหนึ่งแล้วยังได้หนึ่งก็คือหนึ่ง ดังนั้น
0!=1
อย่างไม่ต้องสงสัย...0! = 1 = 0 * (-1)!แน่นอนว่าสมการนี้หาคำตอบไม่ได้ (เลขใดๆ คูณศูนย์ย่อมได้ศูนย์) แม้ว่าสมการข้างต้นจะทำงานได้ดีไม่มีผิดถ้าหาก
n
เป็นเลขจำนวนเต็มบวก แต่ก็ทำให้เกิดข้อสงสัยว่า ในเมื่อ 0!
ไม่สามารถคำนวนมาได้จากฝั่ง 0!=0*(-1)!
แล้วเราจะแน่ใจได้หรือ ว่าสมการข้างต้นนี้สามารถใช้ได้ตั้งแต่ n=1
จริงๆ (เพราะตอนนี้เรามั่นใจแค่ว่ามันใช้ได้ตั้งแต่ n=2
)0!=1
และ factorial ของจำนวนเต็มลบใดๆ หาค่าไม่ได้ ซึ่งไม่ขัดแย้งกับความพยายามก่อนหน้า0!=1
ครับ0!=1
มันเป็นนิยามนั่นแหละ(x+y)^n = sigma C(n,k) x^(n-k)y^k for k from 0 to nซึ่งถ้าไม่ได้นิยาม factorial ตามข้างต้น ก็ต้องเปลี่ยนสูตรนี้ใหม่เป็น
(x+y)^n = x^k + (sigma C(n,k) x^(n-k)y^k for k from 1 to n-1) + y^k
C(n,0)
(เลือกของ 0 ชิ้นจากของ n ชิ้นได้กี่วิธี) ซึ่งก็ยังเข้าใจได้เพราะการไม่เลือกของซักชิ้นเลยอาจเป็นข้อถกเถียงC(n,n)
(เลือกของ n ชิ้นจากของ n ชิ้นได้กี่วิธี) อันนี้เริ่มแปลกๆ แล้ว ทำไมเลือกของทุกชิ้นต้องมีข้อยกเว้นด้วยหละ?e = sigma 1/k! for k from 0 to infinityก็จะกลายเป็นสมการหน้าเกลียดๆ ที่ไม่สามารถอธิบายได้ว่าเลข
1
ตัวแรกนั้นโผล่มาจากไหน/โผล่มาทำไม เช่นนี้e = 1 + (sigma 1/k! for k from 1 to infinity)
ppa:neizod/ppa
ทำขำๆ ไม่รู้จะได้กลับไปดูแลหรือเปล่า :\