Tôi đã học tin học như thế nào? Bắt đầu từ đâu
Trong bài
viết này mình sẽ cố gắng trả lời ngắn gọn và đơn
giản những câu hỏi mà mình nghĩ rằng sẽ có ích đối
với các bạn đặc biệt có đam mê đối với Tin học,
nhưng mới tiếp xúc và không biết phải bắt đầu từ
đâu. Trọng tâm của mình sẽ là việc học thuật toán
để tham gia các kì thi quốc gia, tuy nhiên mình cũng sẽ
cố gắng gợi mở thêm nhiều hướng khác trong phạm trù
kinh nghiệm của mình.
Lưu
ý:
Xuất xứ của mình là một người học Tin để thi quốc
gia, sau đó chuyển dần sang nghiên cứu khoa học về
Machine Learning. Vì thế, những gì được viết dưới đây
xuất phát từ kinh nghiệm của riêng bản thân mình, và
chỉ thể hiện góc nhìn từ con đường mình đã đi. Mình
khuyên các bạn nên chừa ra một khoảng trống trong tâm
hồn để thu nhặt các ý kiến từ các góc nhìn khác.
Sau đây là
các câu hỏi…
Tại
sao phải học Tin học?
Về
cơ duyên đến với Tin học của mình, bạn có thể tham
khảo bài
viết trước. Hy vọng các bạn sẽ tìm thấy điểm
chung nào đó. Một điều mình muốn nói thêm là Tin học
hiện nay giống như một môn Toán thứ hai vậy. Nếu sau
cuộc cách mạng công nghiệp, nhân loại bắt đầu gắn
động cơ vào bất cứ mọi thứ xung quanh, thì đến cuộc
cách mạng máy tính hiện tại, con người bắt đầu dùng
máy tính vào mọi việc có thể. Một công việc trong thế
giới hiện đại khó mà có thể vận hành hiệu quả mà
không cần dùng đến máy tính. Vì thế, một con người
trong thế giới hiện đại khó mà có thể thành công mà
không có kỹ năng sử dụng công cụ này. Bạn bè của
mình làm nhiều ngành khác nhau, từ toán học, hoá học,
vật lý, đến kiểm toán. Họ đều phải chí ít phải có
kỹ năng lập trình để phục vụ cho công việc của
mình.
Học
Tin học như thế nào cho đúng?
Rất
khó để đưa được một câu trả lời trọn vẹn. Thay
vì đó mình sẽ nói về một cách học mình cho là chưa
đúng. Đó là quan niệm học Tin học tức là học một
ngôn ngữ lập trình. Các cách nói dân gian như “học
Pascal” không thể hiện được hết tinh thần của việc
học Tin. Đối với phạm trù Tin học cấp 3, điều quan
trọng nhất bạn rút ra được sau 3 năm học phải một
tư duy thuật toán.
Bạn cần làm cho bộ não quen thuộc với lối suy nghĩ
theo các cấu trúc điều kiện, cấu trúc lặp lại, cách
chia chương trình ra thành các chương trình nhỏ hơn rồi
tập trung giải quyết từng phần một. Vì đa phần các
ngôn ngữ lập trình đều được xây dựng dựa trên các
yếu tố cơ bản trên, việc bạn thành thạo về tư duy
lập trình sẽ giúp bạn học một ngôn ngữ lập
trình rất nhanh. Hãy làm chủ ngôn ngữ lập trình chứ
đừng bị phụ thuộc vào chúng.
Mình không
phản đối việc thành thục một ngôn ngữ lập trình.
Thậm chí việc thành thạo một ngôn ngữ lập trình là
quan trọng sống còn sau này khi bạn muốn làm ra những
sản phẩm thực thụ. Nhưng hãy để việc đó sau khi bạn
đã có một nền tảng tư duy vững chắc.
Nhưng
vẫn phải chọn một ngôn ngữ để bắt đầu học chứ?
Chính xác.
Câu trả lời này mình xin chia ra dành cho hai đối
tượng:
1.
Các bạn luyện thi tin học quốc gia:
theo mình biết thì hai lựa chọn chính dành cho các bạn
là Pascal
và C++.
Việc đưa C++ vào danh sách là một thay đổi lớn vì 6
năm trước khi mình học Tin, Pascal là sự lựa chọn duy
nhất cho các vòng thi trong nước. Trong tương lai mình dự
đoán C++ sẽ thay thế hẳn cho Pascal. Mình không rành về
Pascal bằng C++ nên sẽ không so sánh tính năng của chúng
chi tiết. Tuy nhiên, C++ đưa ra ưu thế rõ rệt về tốc
độ, bao gồm cả tốc độ chạy của chương trình và
tốc độ lập trình ra chương trình đó. Nói đơn giản
là code C++ chạy nhanh và tương đối ngắn gọn (không quá
ngắn gọn đến mức khó hiểu). Đặc biệt, khi học C++
bạn có thể tham gia được rất nhiều kỳ thi lập trình
thuật toán trực tuyến trên mạng. Đây là mấu chốt
trong việc thành công trong kỳ thi quốc gia. Một lợi thế
khác khi học C++ là nó được sử dụng rộng rãi trong
công nghiệp. Vì sớm muộn gì bạn cũng phải học đến
nó chi bằng học sớm từ đầu.
2.
Các bạn học tin với mục đích chung khác:
ngoài C++ ra, theo mình ngôn ngữ Python
là một sự khởi đầu tuyệt vời. Cú pháp của Python
cực kỳ đơn giản, giống như là đang viết những phép
toán trong sách giáo khoa vậy. Dù đơn giản, Python lại
rất đa năng và được hỗ trợ mạnh mẽ từ cộng đồng
người sử dụng. Java
là một sự lựa chọn tốt cho những bạn muốn học về
lập trình hướng đối tượng một cách bài bản. Dù cả
Python và C++ đèu hỗ trợ lập trình hướng đối tượng,
Java theo mình là ngôn ngữ biểu hiện điều này rõ rệt
nhất. Bạn không thể viết một chương trình hoàn chỉnh
trong Java mà không đặt nó vào trong một đối tượng
(class), trong khi nếu sử dụng Python và C++ ta có thể quên
bẵng đi khái niệm này. Ngôn ngữ Java chặt chẽ và dạy
cho bạn những thói quen tốt về cách thiết kế chương
trình.
Học
ngôn ngữ lập trình như thế nào?
Mình
sẽ giả sử là các bạn muốn học C++. Theo mình thì việc
chạy ra nhà sách và mua ngay một cuốn sách giáo khoa dày
cộm về C++ không giúp ích gì mấy (vì mình đã từng làm
điều này). Hồi mình mới học C++, mình thường lên các
trang giải bài trực tuyến hoặc cách trang kỳ thi và xem
code
C++ của các cao thủ khác để học theo cách code của học.
Điều này có hai lợi ích. Thứ nhất, vì mình đã biết
trước lời giải, nên mình có thể đoán được từng
phần chương trình sẽ làm nhiệm vụ gì, sau đó đi sau
vào xem cụ thể nhiệm vụ đó được thực hiện thế
nào. Thứ hai, vì là cao thủ nên code của họ sẽ rất
tối ưu, có thể học được nhiều mẹo vặt mà sách
giáo khoa không dạy. Một cách khác là bạn có thể google
từ khoá “C++ interactive tutorial”
để tìm kiếm cách trang dạy ngôn ngữ lập trình một
cách tương tác. Các trang này thường sẽ đưa bạn đi
qua các khái niệm từ dễ đến khó. Bạn vừa học vừa
thực hành ngay nên sẽ bớt nhàm chám hơn là ngồi cày
sách. Tuy nhiên, về lâu về dài bạn vẫn phải đọc sách
hoặc tài liệu chính thống để hiểu biết các khái niệm
cốt lõi của một ngôn ngữ. Ví dụ như là trong C++ bạn
có thể truyền tham số bằng cả reference hoặc value,
trong khi đó Java chỉ cho phép truyền tham số bằng value
mà thôi. Những điều “behind-the-scenes” như vậy không
thể học được nếu chỉ nhìn vào code của người khác.
StackOverflow
– The definitive C++ book guide and list
Nên
dùng công cụ gì để lập trình?
Trên
Windows, Free Pascal là sự
lựa chọn tốt cho Pascal. Ngoài ra còn có một số công cụ
khác như Lazarus,
Codeblocks, Delphi,…
Đối C++ thì hồi trước mình hay dùng nhất là Dev-C++.
Tuy
nhiên, mình khuyên là các bạn nên từ bỏ Windows và
chuyển sang một hệ điều khác dựa trên nền tảng Unix
như là Ubuntu. Hiện tại
thì màn hình lập trình của mình trông giống như thế
này (bấm vào để phóng to):
Ở
cửa sổ trái mình sử dụng vim,
chỉ đơn thuần là một chương trình soạn thảo văn bản
(text editor) của Ubuntu. Ở cửa sổ phải mình sử dụng
terminal,
nói nôm na là nơi bạn có thể điều khiển máy tính bằng
các câu lệnh thay vì dùng chuột (giống như là MS-DOS thời
xa xưa). Lưu ý là hai công cụ này đều có sẵn trong
Ubuntu, bạn không cần phải cài đặt gì cả. Trong hình,
mình có cài thêm một số Plugins cho vim để thêm màu mè,
màn hình đen, hiển thị dòng cột (cảm ơn bạn mình là
RR!). Mình cũng cài thêm theme Macbook cho máy nên màn hình
trông giống MacOS mặc dù thật ra nó vẫn là Ubuntu.
Khi lập
trình, mình viết code vào vim rồi sử dụng câu lệnh này
để biên dịch (compile) chương trình.
1
|
g++ test.cpp -o a -O2
-Wall |
Lựa
chọn “-o a” sẽ biên dịch file test.cpp
thành một file excutable tương tự như file .exe của Windows
có tên là a
trong
cùng thư mục của file test.cpp.
Vì thế, muốn chạy chương trình, mình chỉ cần chạy
file a
bằng
câu lệnh sau:
1
|
./a |
Nếu
bạn không thích vim, có thể xài gedit hoặc là emacs hoặc
bất cứ trình soạn thảo văn bản nào khác đều được.
Bộ đôi (text editor + terminal) rất đa năng vì bạn có thể
sử dụng nó cho nhiều
ngôn ngữ
khác nhau. Hơn nữa, trong một sản phẩm lập trình thật
sự, bạn không phải compile một lúc một file nữa mà có
thể là cả ngàn files. Lúc đó, bạn sẽ cần đến các
công cụ chạy từ terminal. Cho nên, làm quen với terminal
sớm là một lợi thế. Ngoài ra, trong tương lai gần,
nếu thi tin học quốc tế (IOI), các bạn sẽ thi trên
hệ điều hành Ubuntu.
Tìm
thầy nơi đâu?
Muốn học
giỏi cần phải có thầy giỏi. Cho dù có tố chất đến
mấy mà không biết cách khai phá thì cũng sẽ không thể
đạt đỉnh cao. Nếu ai đó bảo bạn rằng chỉ có tự
học mới giỏi được, thì người đó nói đúng. Nhưng
nếu bạn chỉ ngồi trong giếng nhà tự mày mò tất cả
thì theo mình đó không phải là tự học, mà chỉ là học
một mình. Tự học bao gồm cả việc tự tìm thầy để
mà học.
Khi
mình đặt chân vào trường Phổ Thông Năng Khiếu, nơi có
đội tuyển tin thuộc hàng top của đất nước thời bấy
giờ, mình cứ ngỡ sẽ được dạy dỗ bởi những sư tổ
tu luyện lâu năm, là những giáo sư tiến sĩ đầu tóc
bạc phơ. Tuy nhiên, Năng Khiếu xây dựng cho mình một
hình tượng khác về người thầy. Người “thầy” của
mình ở Năng Khiếu ngoài thầy chủ nhiệm, còn là các
anh khóa trên đi trước và các bạn trong cùng đội tuyển.
Ngoài ra, mình cũng chủ động làm quen các anh học giỏi
trong cả nước thời ấy như Khúc Anh Tuấn hoặc Phạm
Quang Vũ để hỏi bài. Khi hỏi mình cũng thấy hơi ngại
nhưng mà thông qua đó mình học được cách suy nghĩ rất
hay của các anh. Có những bài tập đòi hỏi những kỹ
thuật mà mình thật sự không thể nào biết được nếu
chỉ ngồi học trong giếng nhà. Sau này, diễn đàn VNOI
được các đàn anh lập ra cũng vì mục đích để mọi
người tìm được những người thầy như vậy.
Tuy nhiên,
mình khuyến cáo các bạn không nên quá lạm dụng các
“thầy”, không nên coi các thầy như là một cỗ máy
trả lời. Các “thầy” thường sẽ tân tình đỡ các
bạn hơn nếu các bạn thể hiện được mình là người
chịu khó tư duy và tìm tòi hơn là chỉ biết vòi vĩnh
câu trả lời. Các bạn coi phim chắc cũng biết là cao
nhân chỉ truyền bí kíp cho kẻ có tố chất. Một mẹo
nhỏ là nhớ lịch sự nói “cảm ơn” sau mỗi lần
hỏi.
Tìm
bài nơi đâu?
Khi
học Tin học bạn có một lợi thế đó là bài tập dường
như là vô biên (SPOJ, Timus,
POJ). Nhưng bạn không cần thiết
làm hết tất cả chúng để giỏi. Vì thế ta thay vì hỏi
tìm bài ở đâu, thì nên hỏi:
Nên
làm những bài gì?
Mình gợi
ý một số cách làm bài cơ bản như sau:
-
Làm hết những bài cơ bản: vào trang SPOJ hoặc VOJ, mở list đề bài ra. Ở tiêu đề của cột “Users” khi bạn bấm vào đó một lần, thì các bài tập sẽ được sắp xếp theo thứ tự giảm dần số lượng người làm được. Bài ở những trang đầu tiêu là những bài cơ bản nhất, hầu như ai cũng làm được. Bạn nên làm khoảng vài trang đầu để luyện các kỹ thuật cơ bản.
-
Làm theo chủ đề: khi bạn đang làm những bài cơ bản sẽ gặp những bài bạn nghĩ mãi vẫn không ra. Không phải là bạn kém thông minh gì mà vì những thuật toán đó quá xa lạ với bạn. Vậy thì bạn nên tìm tòi làm những dạng bài tương tự để biết cách áp dụng các thuật toán mới học. Sau khi google mình tìm thấy trang này Problem classifier có lẽ khá hữu dụng.
Mình muốn
dừng ở đây một chút để lưu ý là cách 1 và cách 2
phải nên được áp dụng bổ trợ cho nhau bởi vì một
phương pháp chú trọng vào mở rộng kiến thức theo chiều
rộng, còn phương pháp còn lại mở rộng theo chiều sâu.
Chỉ làm theo kiểu gặp bài nào làm bài đó thì khó thể
đúc kết được những kinh nghiệm sâu sắc. Ngược lại,
làm theo chủ đề cho các bạn thời gian để tập trung
suy nghĩ về một vấn đề, nhưng cẩn thận tránh đam mê
quá một dạng bài mà trở nên không thoải mái khi làm
những dạng bài khác.
3.
Tham
gia các kì thi trực tuyến:
nếu hai phương pháp trên sẽ cho bạn nền tảng tốt thì
phương pháp này sẽ đưa bạn đến đỉnh cao. Vì mục
đích cuối của bạn là tham gia các kì thi quốc gia quốc
tế, nên việc ngồi cả ngày trời để làm một bài tập
trên các trang Online Judge một lúc nào đó sẽ trở thành
một thói quen vô cùng nguy hại. Lúc đó, bạn nên chuyển
qua làm bài theo thời gian thực. Có cảm nhận về áp lực
thời gian, đầu óc bạn sẽ trở nên nhanh nhẹn hơn
nhiều. Hơn nữa, khi thật sự thi đấu với những con
người khác, bạn cũng sẽ có cảm xúc luyện tập hơn là
chỉ ngồi cày Online Judge một mình. Hiện nay, các kì thi
trực tuyến mọc lên như nấm (Codeforces,
TopCoder,
Hackerrank, USACO,
COCI). Các bạn cũng có thể
lấy bài từ các cuộc thi khác vào tạo ra cuộc thi của
riêng rồi mời bạn bè tham gia (HUSTOJ).
Làm
sao để làm bài ít mà vẫn giỏi?
Không có
cách nào cả. Phải làm bài nhiều mới giỏi được.
Nghiên cứu về các kiện tướng ở nhiều bộ môn cho
thấy họ đều luyện tập ít nhất 10 ngàn giờ để đạt
được trình độ đó.
Làm
sao để không cần làm quá nhiều bài mà vẫn giỏi?
Điều này
thì có thể. Thậm chí mình cảm thấy làm quá nhiều sẽ
dẫn đến hoặc là quá tải hoặc là sẽ trở một cỗ
máy giải bài, giải bài xong thì bỏ qua ngay mà không suy
nghĩ thêm gì nữa. Nên nhớ là thời gian luyện tập của
các bạn có hạn, nên các bạn phải khai thác hết giá
trị của từng bài tập bạn giải. Giải một bài tập
xong rồi quăng sang một bên là vô cùng phí phạm. Việc
các bạn giải được nhiều bài trước kì thi chẳng có
nghĩa lý gì nếu bạn không rút ra được nhiều giá trị
từ chúng.
Suy cho
cùng, thì nguyên lý “muốn giỏi phải làm nhiều bài
tập” vẫn không đổi. Tuy nhiên, thay vì làm các bài tập
một cách tuần tự, các bạn có thể cùng một lúc giải
nhiều bài tập bằng cách suy nghĩ về những biến thể
của một bài tập vừa giải được. Hãy xem xem trong bài
toán có những điều kiện nào thể thay đổi được, có
thể tổng quát hóa lên được. Bài toán này có tính chất
gì đặc biệt mà thuật toán của bạn lại giải được?
Tính chất đó có thể xuất hiện dưới dạng khác hay
không? Chỉ cần bỏ một ít thời gian đặt ra những câu
hỏi dạng này và đào sâu khám phá, giá trị thu được
khi giải một bài tập sẽ được nhân lên nhiều lần.
Giải một bài mà như giải 10 bài là như vậy.
Một
ví dụ đơn giản là trong lúc làm bài tập, mình nhận ra
rằng thuật toán chia nhị phân được sử dụng để
chuyên trị những bài tập đòi hỏi “cực tiểu hóa một
giá trị cực đại” (hoặc ngược lại, ví dụ như là
tìm tập hợp sao cho số lớn nhất trong tập nhỏ nhất
trong tất cả các cách chọn). Trong một ví dụ khác, với
bài QBDIVSEQ,
nhận xét mấu chốt là “độ dài dãy con tăng dài nhất
là số lượng ít nhất các dãy con giảm mà ta có thể
phân chia dãy ban đầu thành”. Khi chứng minh nhận xét
này, mình nhận thấy một tính chất đặc biệt của mối
quan hệ “lớn bé” giúp cho chứng minh trở nên khả
thi. Đó là tính chất bắc cầu: “a < b, b < c suy ra
a < c”. Từ đó, mình suy nghĩ ra rằng thay vì sử dụng
mối quan hệ “lớn bé” thông thường khi so sánh các
số, ta có hoàn toàn có thể áp dụng nhận xét của
bài này cho một mối quan hệ “lớn bé” khác (ví
dụ quan hệ chia hết), miễn là tính chất bắc cầu được
thỏa mãn.
Cuối
cùng nhưng quan trọng nhất… tiếng Anh!
Theo
mình, có MỘT thứ tách biệt người học giỏi và người
học không giỏi trong các kì thi Tin học quốc gia và quốc
tế, đó là việc người học đó có thoải mái với
tiếng Anh hay không. Việc thoải mái với tiếng Anh giúp
cho bạn có thể vươn ra khỏi cộng đồng trong nước để
tiếp cận với nhiều luồng tri thức của nhân loại. Hồi
mình mới học Tin, tìm được một cuốn sách dạy thuật
toán bằng tiếng Việt giống như là tìm cá mập trong
vịnh Thái Lan vậy. Thực tế, chỉ có một cuốn sách về
thuật toán được viết sát với nội dung thi quốc gia,
do thầy Lê Minh Hoàng biên soạn. Nhưng chỉ luyện các
thuật toán cơ bản trong sách thầy Hoàng thì không đủ
để có thể cạnh tranh trên đấu trường quốc tế (em
xin lỗi thầy ). Lúc ấy, muốn học thêm các kỹ thuật
nâng cao về quy hoạch động hay cấu trúc dữ liệu, mình
phải tìm đến trang
dạy thuật toán của Topcoder hoặc đọc lời giải
bằng tiếng Anh của các kì thi quốc tế. Hiện nay, các
thành viên của Codeforces có viết nhiều trang blog mô tả
đủ loại kỹ xảo lập trình tiên tiến nhất. Đó là
một mỏ vàng cần được khai thác.
Thoái mái
với tiếng Anh cũng giúp bạn hòa nhập với cộng đồng
luyện thi lập trình trên thế giới thông qua việc tham
gia các kì thi trực tuyến (đề tiếng Anh). Bạn từ một
con cá nhỏ trong cái ao làng, vươn ra biển lớn. Bạn sẽ
thấy rằng con cá lớn nhất trong cái ao của bạn chẳng
to bằng một phần trăm con cá lớn của đại dương. Khi
được tôi luyện với con những con cá đó, dù cố tình
hay vô ý, khả năng sinh tồn của bạn rồi cũng sẽ được
nâng cao.
0 nhận xét:
Đăng nhận xét