"Bánh xe Can Chi" là bài tập số 59 trích trong quyển "250 bài tập kỹ thuật lập trình C" của tác giả Dương Thiên Tứ, một trong những quyển sách mà tôi vô cùng ưa thích đã giúp tôi sống sót qua thời sinh viên.
Đề bài như sau:
Nhập vào năm dương lịch, xuất tên năm âm lịch tương ứng. Lấy năm 0 là năm Canh Thân để làm mốc tính toán. Kết quả sau khi chạy chương trình tương tự như sau:
Nhap nam: 2000
2000 - Canh Thin
2060 - Canh Thin
Trước tiên chúng ta cần phải hiểu Can Chi là gì đã. Theo Wikipedia thì: Can Chi là hệ thống đánh số thành chu kỳ được dùng tại các nước có nền văn hóa Á Đông như: Trung Quốc, Việt Nam, bán đảo Triều Tiên, Nhật Bản, Đài Loan, Singapore và một số quốc gia khác. Nó được áp dụng với tổ hợp chu kỳ sáu mươi (60) trong âm lịch nói chung để xác định tên gọi của thời gian (ngày, giờ, năm, tháng) cũng như trong chiêm tinh học. Người ta cho rằng nó có xuất xứ từ thời nhà Thương ở Trung Quốc.
Danh sách 10 can:
Năm kết thúc bằng số nào thì có can số đó.
+----+------+
| Số | Can |
+----+------+
| 0 | Canh |
| 1 | Tân |
| 2 | Nhâm |
| 3 | Quý |
| 4 | Giáp |
| 5 | Ất |
| 6 | Bính |
| 7 | Đinh |
| 8 | Mậu |
| 9 | Kỷ |
+----+------+
Danh sách 12 chi (hay còn gọi là 12 con giáp):
+----+------+
| Số | Chi |
+----+------+
| 0 | Tý |
| 1 | Sửu |
| 2 | Dần |
| 3 | Mão |
| 4 | Thìn |
| 5 | Tỵ |
| 6 | Ngọ |
| 7 | Mùi |
| 8 | Thân |
| 9 | Dậu |
| 10 | Tuất |
| 11 | Hợi |
+----+------+
Cài đặt bằng C của chương trình như sau:
Cũng như mọi khi, hãy cố gắng tự suy nghĩ và viết mã lệnh trước khi tham khảo bài giải nhé.
#include <stdio.h>
#include <stdlib.h>
int main() {
char can[10][5] = {"Canh", "Tan", "Nham", "Quy", "Giap", "At", "Binh", "Dinh", "Mau", "Ky"};
char chi[12][5] = {"Than", "Dau", "Tuat", "Hoi", "Ty", "Suu", "Dan", "Mao", "Thin", "Ty", "Ngo", "Mui"};
int n;
printf("Nhap nam: ");
scanf("%d", &n);
printf("%d - %s %s\n", n, can[n % 10], chi[n % 12]);
n += 60;
printf("%d - %s %s\n", n, can[n % 10], chi[n % 12]);
return 0;
}
Chú thích:
- Theo bảng Chi thì Tý phải đứng đầu. Tuy nhiên, chúng ta lấy năm 0 (Canh Thân) làm mốc tính toán nên Thân được đưa lên đầu mảng, nhờ vậy logic tính toán của chương trình sẽ trở nên bớt phức tạp hơn rất nhiều.
- Phương pháp giải dùng mảng cho sẵn như trên gọi là bảng tra cứu (lookup table), tương tự như bài Forming a Magic Square mà tôi đã từng giải.
Nâng cao:
- Cũng bài tập trên, nhưng với input là một loạt năm cho trước như sau, in ra năm âm lịch tương ứng. Sử dụng mảng động để lưu input.
Input:
0
60
1996
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2018
2019
2020
2060
Output:
0: Canh Than
60: Canh Than
1996: Binh Ty
2000: Canh Thin
2001: Tan Ty
2002: Nham Ngo
2003: Quy Mui
2004: Giap Than
2005: At Dau
2006: Binh Tuat
2007: Dinh Hoi
2008: Mau Ty
2009: Ky Suu
2010: Canh Dan
2011: Tan Mao
2012: Nham Thin
2018: Mau Tuat
2019: Ky Hoi
2020: Canh Ty
2060: Canh Thin
Bải giải:
#include <stdio.h>
#include <stdlib.h>
int main() {
char can[10][5] = {"Canh", "Tan", "Nham", "Quy", "Giap", "At", "Binh", "Dinh", "Mau", "Ky"};
char chi[12][5] = {"Than", "Dau", "Tuat", "Hoi", "Ty", "Suu", "Dan", "Mao", "Thin", "Ty", "Ngo", "Mui"};
int n = 0;
int* year = (int*) malloc(n);
while (scanf("%d", &year[n]) != EOF)
year = (int*) realloc(year, ++n * sizeof(int));
for (int i = 0; i < n; i++)
printf("%4d: %s %s\n", year[i], can[year[i] % 10], chi[year[i] % 12]);
return 0;
}