Đố chơi đầu năm (1 người xem)

  • Thread starter Thread starter VetMini
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

VetMini

Đang đi tìm hòn đá
Tham gia
21/12/12
Bài viết
17,868
Được thích
24,782
Nghề nghiệp
Thầy bói bài ta
Bài này khá dễ. Tôi chỉ đưa ra cho các con gà chiến chai mặt có dịp chỉ dẫn các gà tơ về nghệ thuật code.

Điều kiện: không dùng các hàm có sẵn trong VBA hoặc WorkSheet.

Cho ba con số nguyên ngay, thang, nam. Viết code VBA thử xét tính cách hợp lệ của ba con số này khi đi với nhau.
(hàm Date của WorkSheet nhận 2021, 50, 50 và đổi nó thành ngày đâu đó trong năm 2025. Nhưng hàm của bạn phải xét là nó không hợp lệ)

Sau khi viết xong, bạn có thể thêm ý kiến nếu dùng VBA hay WorkSheet function thì code của bạn như thế này...

Lưu ý:
- bạn nào thích Google Sheets thì viết Apps Code, hay JavaScript cũng được.
- viết theo Delphi, hay Python thì tôi cũng ủng hộ tuốt.
- bài này tôi đoạt giải viết code C. Nếu bạn viết bằng ngôn ngữ khác thì có dịp chúng ta so sánh.
 
Mùa dịch không có chỗ đi chơi, thôi thì ...
Mã:
Function ngaythang(ByVal ngay As Long, ByVal thang As Long, ByVal nam As Long) As Boolean
    If thang < 0 Or thang > 12 Or nam < 1900 Or nam > 2100 Then Exit Function
    Select Case thang
        Case 2
            ngaythang = ngay <= 28 - (nam Mod 4 = 0) And ((nam Mod 100 <> 0) Or (nam Mod 400 = 0))
        Case 1, 3, 5, 7, 8, 10, 12:
            ngaythang = ngay <= 31
        Case Else
            ngaythang = ngay <= 30
    End Select
End Function
 
Mùa dịch không có chỗ đi chơi, thôi thì ...
Mã:
    If thang < 0 Or thang > 12 Or nam < 1900 Or nam > 2100 Then Exit Function
Tôi cho rằng mọi năm <> 0 đều là hợp lệ chứ anh nhỉ? Kể cả năm trước công nguyên (số âm), trừ khi xa quá thì chưa có lịch hoặc chưa có chữ viết, hoặc tương lai tận thế đánh số lại như phim "tận thế 2012".
 
Tôi cho rằng mọi năm <> 0 đều là hợp lệ chứ anh nhỉ? Kể cả năm trước công nguyên (số âm), trừ khi xa quá thì chưa có lịch hoặc chưa có chữ viết, hoặc tương lai tận thế đánh số lại như phim "tận thế 2012".
Năm của tôi chỉ giới hạn thế thôi. Chừa cho người khác cơ hội nữa chứ anh.

Cho code Delphi/Object Pascal đi bác ơi. :p
Thôi để cho người khác. Delphi đời mới hơn Delphi5 thì tôi không muốn nghiên cứu, rất có thể có nhiều hàm "độc lạ", mà tôi có cài Delphi đâu. Còn Delphi5 thì code tôi vừa đưa ra ở đoạn xét năm nhuận chính là code của Delphi 200%. - hàm IsLeapYear :D
 
Lần chỉnh sửa cuối:
Khi làm bài này (C) thì tôi không viết code trực tiếp xét ngày tháng năm.
Tôi viết một hàm con tính số ngày trong tháng, và so sánh với ngày cần xét.

Code JavaScript (cũng gần như C thôi)

PHP:
function SoNgayTrongThang(thang, nam) {
// fucntion tính số ngày trong tháng (thang), thuộc về năm (nam)
// nếu tháng không hợp lệ (không trong 1-12), hoặc năm <0 thì hàm trả về 0
if (nam < 0) return 0;
switch (thang) {
  case 1: case 3: case 5: case 7: case 8: case 10: case 12: return 31;
  case 4: case 6: case 9: case 11: return 30;
  case 2: return ((nam % 4 != 0 || nam % 100 == 0 && nam % 400 != 0)? 28 : 29);
}
return 0;
}

var ng = 30, th = 15, nm = 2021;
console.log((ng <= 0 || ng > SoNgayTrongThang(th,nm))? "không hợp lệ" : "hợp lệ");

Lưu ý cho các bạn mới tập làm quen với Select Case:
So sánh code này với code bài #2 sẽ thấy Select Case của VBA hoạt động khác hẳn switch của JavaScript.[/code]
 
Ăn uống no nê rồi, đi chơi cũng chán rồi. Nào ta cùng nhau thư giãn chút.

Có anh A, ta coi anh A như là 1 điểm trong hình học. Anh A hôm qua đi thăm bạn bè, đi chơi đi nhậu, tẩm quất khắp nơi. Tổng cộng về tới nhà thì anh A đã đi trong ngày một đoạn đường dài bằng 2*k (mét, cm - không quan trọng đơn vị tính.). Chứng minh rằng trong ngày hôm qua anh A không đi ra khỏi một hình tròn nào đấy có đường kính k.
 
... Chứng minh rằng trong ngày hôm qua anh A không đi ra khỏi một hình tròn nào đấy có đường kính k.

Đoán được. Nhưng chứng minh thì chưa tìm được hướng đi.
Cứ lẩn quẩn mãi ở chỗ bất đẳng thức tam giác - tổng hai cạnh luôn luôn lớn hơn cạnh thứ ba. Cõ lẽ đi trật đường?
 
Đoán được. Nhưng chứng minh thì chưa tìm được hướng đi.
Cứ lẩn quẩn mãi ở chỗ bất đẳng thức tam giác - tổng hai cạnh luôn luôn lớn hơn cạnh thứ ba. Cõ lẽ đi trật đường?
:D Nếu nối đỉnh với trung điểm cạnh thứ ba rồi kéo dài thêm một đoạn bằng trung tuyến thì tổng 2 cạnh kia sẽ được biểu diễn như thế nào?
 
:D Nếu nối đỉnh với trung điểm cạnh thứ ba rồi kéo dài thêm một đoạn bằng trung tuyến thì tổng 2 cạnh kia sẽ được biểu diễn như thế nào?
Đầu đoạn nói ấy sẽ là một góc hình bình hành. Chuyển tam giác sang phần thứ hai của hình bình hành. Ta được tam giác khác, với hai cạnh bằng tam giác cũ, và cạnh thứ ba là hai đoạn nối kia. Tiếp tục áp dụng bất đẳng thức, tổng hai cạnh dài hơn cả hai đoạn nối kia. Như vậy, tổng hai cạnh lớn hơn hai lần trung tuyến.
Từ đó đi ra vòng tròn thì tôi bí. :(
 
Đầu đoạn nói ấy sẽ là một góc hình bình hành. Chuyển tam giác sang phần thứ hai của hình bình hành. Ta được tam giác khác, với hai cạnh bằng tam giác cũ, và cạnh thứ ba là hai đoạn nối kia. Tiếp tục áp dụng bất đẳng thức, tổng hai cạnh dài hơn cả hai đoạn nối kia. Như vậy, tổng hai cạnh lớn hơn hai lần trung tuyến.
Từ đó đi ra vòng tròn thì tôi bí. :(
Khoảng cách từ đỉnh tới trung điểm của cạnh thứ ba so với k là như thế nào? Nói cách khác trung tuyến so với k là như thế nào?

Nếu bác xác định chính xác cái mà bác gọi là "cạnh thứ ba" thì bác đã có cốc nước đầy. Chỉ cần 1 giọt nhỏ nữa là sẽ có nước tràn ly.
 
Lần chỉnh sửa cuối:
Khoảng cách từ đỉnh tới trung điểm của cạnh thứ ba so với k là như thế nào? Nói cách khác trung tuyến so với k là như thế nào?

Nếu bác xác định chính xác cái mà bác gọi là "cạnh thứ ba" thì bác đã có cốc nước đầy. Chỉ cần 1 giọt nhỏ nữa là sẽ có nước tràn ly.
Tôi tưởng tượng, sau đó thử vẽ ra giấy thì thấy được cái đường chéo hình bình hành. Dùng đường chéo lớn của hình bìnhn hành, chuyển sang chữ nhật thì biết được cái góc thức nhất (đường đi) bắt buộc phải nằm trong vòng tròn tiếp xúc hình chữ nhật.
Tuy nhiên, moi óc hoài mà không nhớ nổi cái định luật nào giản dị hơn để chứng minh.
 
Tôi tưởng tượng, sau đó thử vẽ ra giấy thì thấy được cái đường chéo hình bình hành. Dùng đường chéo lớn của hình bìnhn hành, chuyển sang chữ nhật thì biết được cái góc thức nhất (đường đi) bắt buộc phải nằm trong vòng tròn tiếp xúc hình chữ nhật.
Tuy nhiên, moi óc hoài mà không nhớ nổi cái định luật nào giản dị hơn để chứng minh.
Tôi không hiểu bác xét hình chữ nhật nào và góc nào để làm gì.

Cái mà bác gọi là đường chéo lớn nó có độ dài bằng 2 đường trung tuyến tới cạnh thứ ba. Nếu tôi và bác cùng nghĩ tới 1 cạnh thứ ba thì có nghĩa là điểm C bất kỳ trên đường gấp khúc khép kín - lộ trình của anh A cách điểm cố định - trung điểm cạnh thứ ba một khoảng bằng trung tuyến xuống cạnh thứ ba. Nếu chứng minh được trung tuyến đó LUÔN NHỎ HƠN HOẶC BẰNG k/2 thì có nghĩa là điểm C phải nằm trong đường tròn có bán kính là k/2, tức đường kính k.

Tóm lại bài toán thực chất là: "Hãy chứng minh là khoảng cách từ một điểm bất kỳ của lộ trình (đường gấp khúc khép kín) luôn cách một điểm O cố định nào đó một khoảng nhỏ hơn hoặc bằng k/2"
 
Ngày Xuân ngồi nhàn dỗi, xin góp vui một bài toán: Lúc 12 giờ đêm 3 kim (giờ, phút, giây) của đồng hồ có kim trùng kít lên nhau ở điểm 12. Hỏi bao nhiêu lâu nữa thì 3 kim lại trùng kít lên nhau?
Tôi đã giải được bài này bằng đại số (nhưng là hồi còn học phổ thông-cách đây đã hơn 50 năm), giờ không thể nhớ được cách giải và làm mãi mà không ra.
Mong anh chị em ghé xem cho lời giải. Nếu bằng VBA thì cũng cho luôn giải thuật.
Trân trọng.
 
Ngày Xuân ngồi nhàn dỗi, xin góp vui một bài toán: Lúc 12 giờ đêm 3 kim (giờ, phút, giây) của đồng hồ có kim trùng kít lên nhau ở điểm 12. Hỏi bao nhiêu lâu nữa thì 3 kim lại trùng kít lên nhau?
Chỉ là bài toán tốc độ và rượt đuổi thôi mà. Khác toán lớp 5 ở chỗ đây là tốc độ góc.
 
Chỉ là bài toán tốc độ và rượt đuổi thôi mà. Khác toán lớp 5 ở chỗ đây là tốc độ góc.
Vâng, chỉ là bài toán tốc độ và dượt đuổi nhưng các kim nó chạy vòng tròn. Tôi không còn nhớ nổi cách giải mà chỉ nhớ máng là hình như nó có đến 11 nghiệm.
Nếu anh đã có lời giải bằng đại số hoặc bằng VBA thì cho tôi xin nhé.
 
Ngày Xuân ngồi nhàn dỗi, xin góp vui một bài toán: Lúc 12 giờ đêm 3 kim (giờ, phút, giây) của đồng hồ có kim trùng kít lên nhau ở điểm 12. Hỏi bao nhiêu lâu nữa thì 3 kim lại trùng kít lên nhau?
Tôi đã giải được bài này bằng đại số (nhưng là hồi còn học phổ thông-cách đây đã hơn 50 năm), giờ không thể nhớ được cách giải và làm mãi mà không ra.
Mong anh chị em ghé xem cho lời giải. Nếu bằng VBA thì cũng cho luôn giải thuật.
Trân trọng.
Trước tiên không cần tra tấn tôi cũng khai là chưa suy nghĩ sâu, và rất có thể các kết luận không chính xác.

Trước hết ta thấy là muộn nhất là sau 12 tiếng 3 kim lại gặp nhau. Vậy khoảng cách giữa 2 lần liên tiếp mà 3 kim gặp nhau <= 12 tiếng.

Trên đồng hồ cứ 1 tiếng có 5 "nấc" (vạch kẻ). Tức mỗi vòng có 60 "nấc".

Ta coi là ở thời điểm 12:00 thì kim giờ ở trước kim phút 60 nấc và kim phút đuổi theo kim giờ. Trong 12 phút kim phút đi được 12 nấc, kim giờ đi được 1 nấc. Tức nếu cự li giữa 2 kim là 11 nấc thì kim phút đuổi kịp kim giờ sau 12 phút. Vậy cự li 60 nấc thì kim phút mất 60*12/11 phút = 12/11 giờ để đuổi kịp kim giờ. Tóm lại cứ 12/11 giờ thì 2 kim giờ và phút trùng nhau.

Ta coi là ở thời điểm 12:00 thì kim phút ở trước kim giây 60 nấc và kim giây đuổi theo kim phút. Trong 1 phút kim giây đi được 60 nấc, kim phút đi được 1 nấc. Tức nếu cự li giữa 2 kim là 59 nấc thì kim giây đuổi kịp kim phút sau 1 phút. Vậy cự li 60 nấc thì kim giây mất 60/59 phút = 1/59 giờ để đuổi kịp kim phút. Tóm lại cứ 1/59 giờ thì 2 kim giây và phút trùng nhau.

Giả sử sau một thời gian 3 kim lại trùng nhau và đó là lần thứ x kim giờ và phút gặp nhau, cũng là lần thứ y kim phút và giây gặp nhau. Ta có x, y là nguyên dương và

12x/11 = y/59 (thời gian trôi qua tính từ lần trùng trước)

=> 12*59*x = 11*y

Vế phải chia hết cho 11 vậy vế trái cũng chia hết cho 11, tức x chia hết cho 11 do 12 và 59 là số nguyên tố lớn hơn 11. x nhỏ nhất là x = 11.
Tức lần gặp tiếp là sau 12*x/11 [giờ] = 12 [giờ]

Kiểm tra lại ta thấy là rõ ràng sau 12 tiếng thì 3 kim lại gặp nhau.
 
Thấy không ai tham gia nữa nên tôi đưa ra lời giải bài #1 và kết thúc.

Lộ trình của anh A là một đường gấp khúc khép kín (đi từ nhà và về nhà). Ta biết rằng đoạn thẳng nối 2 điểm là đường đi ngắn nhất từ 1 điểm tới điểm còn lại. ***

Lấy A và B bất kỳ trên lộ trình nhưng chia lộ trình thành 2 nửa có độ dài như nhau và đều bằng k, với 2*k là độ dài toàn lộ trình. Gọi O là trung điểm AB. Ta xét điểm C BẤT KỲ trên lộ trình. Gọi D là điểm đối xứng với C qua tâm O. Dễ thấy ACBD là hình bình hành và:

k = <đường gấp khúc AC> + <đường gấp khúc CB> >= AC + CB (do ***) = AC + AD >= CD = 2*OC

=> OC <= k/2

Điểm C luôn cách điểm cố định O một khoảng <= k/2 nên nằm trọn trong hình tròn tâm O có bán kính k/2, tức đường kính k. Dấu =, tức điểm nằm trên đường tròn (bờ biên của hình tròn) khi lộ trình là 2 đoạn AB và BA (lộ trình ABA) và điểm xét là A hoặc B.
 
chỉ nhớ máng là hình như nó có đến 11 nghiệm.
Theo tôi thì phải sau 12 giờ 3 kim mới gặp lại nhau. Giữa khoảng 12 giờ không có nghiệm nào. Tôi suy luận kém nên không dùng suy luận ra kết quả như anh @batman1 mà dùng phép tính rượt đuổi như thời học sinh:
Tốc độ quay của kim giờ là 1/12 vòng / giờ = 30 độ góc/ giờ
Tốc độ quay của kim phút là 1 vòng/ giờ = 360 độ góc/ giờ
Đặt 12 giờ là gốc 0 độ.
Sau 1 giờ thì kim giờ nằm ở số 1 tức là 30 độ, kim phút nằm ở số 12 tức là 0 độ. Vậy khoảng cách 2 động tử cùng chiều là 30 độ
Thời gian kim phút đuổi kịp kim giờ là 1 giờ cộng thêm:
t = khoảng cách / hiệu số vận tốc
t = 30 / (360 - 30) = 1/11 giờ = 5.454545 phút (gần bằng 5.5 phút tức là gần bằng 5'30")
Nghĩa là kim giây đã vượt qua cả 2 kim còn lại khoảng 25 giây (có thập phân).
Suy luận tí nữa thì không khi nào kim giờ gặp kim phút mà kim giây không vượt qua miếng nào. Trừ khi quay về vạch12:00:00 tiếp theo. Tôi kết luận là không phải 11 nghiệm mà là vô nghiệm trong khoảng 0 - 12 giờ
-------------
Chỉ có kim giờ và kim phút gặp nhau 11 lần.
 
Xin các bạn giúp tôi sửa vài câu lệnh làm sao để rút gọn (BỎ BỚT) khoảng trên ba câu lệnh trong macro trong #19 sau:
 
Lần chỉnh sửa cuối:
Xin các bạn giúp tôi sửa vài câu lệnh làm sao để rút gọn (BỎ BỚT) khoảng trên ba câu lệnh trong macro trong #19 sau:
Đoán đại
Mã:
Function SumIf_22(Ma As String, CSDL As Range)
Dim Arr()
Dim J As Long, Tong As Double, SoChia As Integer, DD As Integer, VTr As Integer
 
For J = 1 To CSDL.Rows.Count
    VTr = InStr(CSDL.Cells(J, 1).Value, Ma)
    DD = Len(CSDL.Cells(J, 1).Value)  '** '
    If VTr Then
        Tong = Tong + CSDL.Cells(J, 2).Value * 6 / (DD + 1)
    End If
Next J
SumIf_22 = Tong
End Function
 
Mình cảm ơn bạn CHAOQUAY 3 lần luôn vì đã giúp mình:
Thứ nhất: Rút bớt các câu lệnh trong hàm để hàm thanh thoát hơn;
Thứ nhì: Giúp mình phát hiện ra 1 'lỗi' trong hàm mình viết, một khi ta cung cấp tham biến Ma là trị rỗng thì kết quả sai;
Thứ ba: Từ đấy mình bắt chước & tìm ra cách rút gọn trên nền tảng tương tự::
PHP:
Function SumIf_22(Ma As String, CSDL As Range)
 Dim J As Long, Tong As Double, SoChia As Integer, DD As Integer, VTr As Integer
 
 If Ma = Space(0) Then
    SumIf_22 = "Mã NV":                   Exit Function
 End If
 For J = 1 To CSDL.Rows.Count
    VTr = InStr(CSDL.Cells(J, 1).Value, Ma)        '   '
    DD = Len("@" & CSDL.Cells(J, 1).Value)
    If VTr Then
        SoChia = DD / 6
        Tong = Tong + CSDL.Cells(J, 2).Value / SoChia
    End If
 Next J
 SumIf_22 = Tong
End Function
 
[Giành cho những người mới bắt đầu VBA]​

Thực hiện macro để có kết quả như trong hình
 

File đính kèm

  • 29 Thg 02.jpg
    29 Thg 02.jpg
    21.9 KB · Đọc: 39
[Giành cho những người mới bắt đầu VBA]​

Thực hiện macro để có kết quả như trong hình
[Giành cho những người mới bắt đầu lập trình]
(tức là không nhất thiết phải VBA)

Phân tích xem yêu cầu của cái hình trên là gì. Và các bước chính để đáp ứng những yêu cầu ấy.
 
Tôi đang thắc mắc ngôn ngữ lập trình khác (không phải VBA) có gọi là macro không?
Có.
Hồi tôi học Assembly Language của PDP-11 (DEC) thì một nhóm lệnh có thể được gộp thành một Macro. Đại khái như một Sub.

Và trong C thì Macro có vị trí rõ rệt. Trích GNU:

1644501159979.png
 
[Giành cho những người mới bắt đầu VBA]​
Cách 1 dễ: Dùng 2 vòng lặp và 1 mảng trung gian hoặc dùng sheet làm trung gian. Dễ đối với người suy luận kiểu phân bước. Tôi thuộc loại này.
Cách 2 cũng dễ: 1 vòng lặp duy nhất, bỏ qua trung gian, dễ đối với người có tư duy trừu tượng. Tôi trừu tượng dở nên làm cách 1 trước rồi tìm cách rút gọn bớt 1 vòng lặp sau.
 
Nếu là 19 giá trị cụ thể cách nhau (4 * 365 + 1) = 1461 ngày, rải vào 19 ô như hình thì dùng phương pháp cần cù thôi - nhập giá trị lần lượt vào 19 ô.
Mã:
Sub ngay_cuoi_thang2_nam_nhuan()
Dim k As Long, c As Long, kq(1 To 3, 1 To 7)
    c = 5
    For k = 1 To 19
        kq((k - 1) \ 7 + 1, (c + 34) Mod 7 + 1) = DateSerial(2024 + (k - 1) * 4, 2, 29)
        c = c - 2
    Next k
    Range("A2:G4") = kq
End Sub
 
Nếu chỉ với 19 năm nhuận theo hình
Mã:
Sub ABC()
  Dim i&, ngay As Date
  For i = 1 To 19
    ngay = DateSerial(2024 + (i - 1) * 4, 2, 29)
    Cells((i - 1) \ 7 + 1, Weekday(ngay)) = ngay
  Next i
End Sub
 
Có thể xài vòng lặp (?):
Mã:
 Dim J As Long, Dat As Date
 For J = 2024 To 2099 Step 4
'    . . . . . .  '
'  . . . . . . . .    '  
 Next J

Toàn là các 'Cộm cán' không hà!
 
Cách 1
PHP:
Sub nhuan()
Dim ArrS(1 To 19, 1 To 2), k As Long

For i = 2024 To 2096 Step 4
    k = k + 1
    ArrS(k, 1) = DateSerial(i, 2, 29)
    ArrS(k, 2) = Weekday(ArrS(k, 1))
Next

For i = 1 To 19
    n = ArrS(i, 2) + 3
    k = Cells(100, n).End(xlUp).Row + 1
    Cells(k, n).Value = ArrS(i, 1)
Next
End Sub
Cách 2
PHP:
Sub nhuan2()
For i = 2024 To 2096 Step 4
    n = Weekday(DateSerial(i, 2, 29)) + 3
    k = Cells(100, n).End(xlUp).Row + 1
    Cells(k, n).Value = DateSerial(i, 2, 29)
Next
End Sub
 
Cách 1
PHP:
Sub nhuan()
Dim ArrS(1 To 19, 1 To 2), k As Long

For i = 2024 To 2096 Step 4
    k = k + 1
    ArrS(k, 1) = DateSerial(i, 2, 29)
    ArrS(k, 2) = Weekday(ArrS(k, 1))
Next

For i = 1 To 19
    n = ArrS(i, 2) + 3
    k = Cells(100, n).End(xlUp).Row + 1
    Cells(k, n).Value = ArrS(i, 1)
Next
End Sub
Cách 2
PHP:
Sub nhuan2()
For i = 2024 To 2096 Step 4
    n = Weekday(DateSerial(i, 2, 29)) + 3
    k = Cells(100, n).End(xlUp).Row + 1
    Cells(k, n).Value = DateSerial(i, 2, 29)
Next
End Sub
Êêê, sáng kiến mới là đố vui trên bàn nhậu chứ Weekday thì là đi thi rồi. :D
 
Lần chỉnh sửa cuối:
Mã:
(c + 34) Mod 7 + 1)
Tôi bó tay vụ lấy đâu ra con 5, con 34 và cộng 1. Anh vừa sáng kiến vừa mà mắt người ta
Khởi đầu bằng 5 vì giá trị đầu tiên (năm 2024) phải đập vào cột 5 theo hình.

Theo dõi ta có các năm 2024, 2028, ... được nhập vào các cột 5, 3, 1, 6, 4, 2, 7, 5, 3, 1, 6, 4, 2, 7, 5, 3, 1, 6, 4 (chu kỳ 5, 3, 1, 6, 4, 2, 7) *. Từ đó có ý tưởng c = c - 2 và dùng MOD.

Trong trường hợp cần xác định chỉ số cột thì thực ra là (c - 1) Mod 7 + 1.

Nhưng nếu thế thì từ lúc c ÂM thì chỉ số cũng sẽ ra ÂM. Vì thế cộng thêm với bội của 7 để chỉ số DƯƠNG. Nhưng phải cộng tới 35 *** tất cả các chỉ số mới DƯƠNG

(c - 1 + 35) Mod 7 + 1 = (c + 34) Mod 7 + 1

*: Ta coi CN là 1, xuất phát từ 5 và đi ngược chiều kim đồng hồ, sau CN là 7 (thứ 7) - kiểu đi vòng tròn, thì ta luôn phải nhẩy 2 bước. Vì thế sau 1 (CN) là 6 (thứ 6), sau 2 (thứ 2) là 7 (thứ 7).

***: Giá trị c cuối cùng là c = 5 - 2*18 = -31 -> c - 1 = -32, vậy phải cộng thêm ít nhất là 35. Cộng thêm bội của 7 mà > 35 cũng được.
 
Lần chỉnh sửa cuối:
Trong vòng lặp của #30 ta có thể xài 2 dòng lệnh thiệt rùa, như sau:

Dat = DateSerial(J, 2, 29)
Cells(100, 3 + Weekday(Dat)).End(xlUp).Offset(1).Value = Dat

[Con số 3 là tùy thích của mỗi người]
 
Trong vòng lặp của #30 ta có thể xài 2 dòng lệnh thiệt rùa, như sau:

Dat = DateSerial(J, 2, 29)
Cells(100, 3 + Weekday(Dat)).End(xlUp).Offset(1).Value = Dat
Em muốn viết tường minh cho người nào cũng hiểu 1 cách dễ dàng. Gộp lệnh không phải lúc nào cũng rõ ràng, dễ đọc dễ sửa
 
Điều kiện là "mới bắt đầu" mà quý vị đốt giai đoạn dữ quá. Lúc vừa thấy câu đó, tôi đã nghi là quý vị sẽ chơi toàn những bài tính toán chỉ số mảng cho nên mới ra thêm phần "phân tích bằng lời" (bài #24).
@Bác tác giả bài #34:
Nếu người học có khả năng toán như bác thì người ta đã học lên đến trình độ cao như những người góp code khác rồi.
@các tác giả khác (tức những người góp bài):
Quý vị quen cách tính nhẩm giải thuật rồi cho nên làm dễ dàng. Quý vị quen rằng nếu không giải thích thì người mới học sẽ chả hiểu gì cả. Bài này thực ra có 3 bước mà quý vị tính nhẩm 2 bước đầu:
1. Đọc kỹ cái hình. Nhận định cái pattern và khám phá ra cái hình đó nó trưng bày những dữ liệu gì.
2. Suy tính cách thực hiện. Nghiên cứu những thuật toán, những công cụ trợ giúp.
3. Viết code.
(thực ra lập trình thực tế còn bước thứ tư là test lại xem mình có đúng ở những bước 1, 2, rồi 3. Nếu khong đúng thì phải bắt đầu lại. Bài này khá dễ - tức khá ít output, và output dạng "cứng" cho nên bước thứ tư này không quan trọng)

Trong một đồ án tầm cỡ, cả 4 bước tôi đều có lập tư liệu (documentation) đàng hoàng, với đầy đủ chỉ tiêu (metrics, benchmarks)

Thôi thì không ai nhã hứng nên tôi làm luôn cho các bạn mới học lập trình theo dõi:

Phân tích dưới đây là nói về cái hình ở bài #23:

1. Output là một cái bảng trên Excel Sheet
1.1. Bảng có dòng tiêu đề là tên 7 ngày trong tuần, đặt thành 7 cột, bắt đầu là ngày chúa nhật. (điểm này các code của quý vị đã đưa ra thiếu hết. Phần output chỉ có ngày và hiểu ngầm là sắp xếp theo thứ)
1.2. Dữ liệu trong bảng là các ngày 29 tháng 2. Vì vậy chỉ có thể là các năm nhuần.
1.3. Giới hạn: ngày nhỏ nhất trong bảng là năm 2024. Ngày lớn nhất là năm 2096.
Như vậy, bài toán bao gồm liệt kê các ngày 29 tháng 2 kể từ thời gian hiện tại đến cuối thể kỷ (2099, hay 2100 cũng vậy thôi). Liệt kê theo bảng 7 cột, biểu thị theo các thứ tuần, bắt đầu là chủ nhật.

2. Giải thuật gồm hai phần, phần tính các năm nhuần và phần trình bày.
2.1. Có hai cách tính, cách biết sẵn và cách tính trâu bò.
2.1.1. Cách biết sẵn: biết năm nhuần gần đây nhất là 2024, và cứ 4 năm lại nhuần. Giải thuật là vòng lặp bắt đầu từ đấy (bài #31) cho đên 2099. Hoặc đi thêm một bước nữa thì biết từ đây đến cuối thế kỷ còn 19 lần và dùng số đại diện 1-19 (bài #28, #29).
2.1.2. Cách trâu bò: bắt đầu từ năm nay, tính đến năm 2099. Cứ năm nào có ngày 20/02 thì lấy ra.
2.1.2.1. Dùng hàm Cdate(năm & "02-29") và bẫy lỗi.
2.2. Cách trình bày thì cũng tuỳ thuộc vào cách tính ở trên.
2.2.1. Nếu biết sẵn thì ceiling(19/7) = 3. Và dùng một mảng 7x3. Dùng con tính như bài #28,#29 để tính ra chỉ số.
2.2.2. Nếu trâu bò thì dựng một mảng 7 phần tử cho biết vị trí dòng trống của mỗi cột. Cứ tính ngày ra thứ nào thì dựa theo đó mà chép xuống.

3. Viết code. Để chiều rảnh tính tiếp.
 
Điều kiện là "mới bắt đầu" mà quý vị đốt giai đoạn dữ quá. Lúc vừa thấy câu đó, tôi đã nghi là quý vị sẽ chơi toàn những bài tính toán chỉ số mảng cho nên mới ra thêm phần "phân tích bằng lời" (bài #24).
Tôi có đọc bài 24, tôi biết bài ấy chứa 1 yêu cầu phải "nhìn hình đoán chữ" trước khi giải, và cũng biết rằng tác giả bài 24 muốn giải thích từ gốc đến ngọn nên tôi để dành cho bác ấy đấy chứ. Thế nên bài 27 tôi chỉ gợi ý mà chưa viết code, khi thấy bài 28 và 29 viết code cao siêu quá nên tôi mới ngứa tay viết 1 code loại dễ hiểu liền kề.
 
khi thấy bài 28 và 29 viết code cao siêu quá
Nhìn hình thì biết tất cả đều là ngày cuối cùng của tháng 2 của 19 năm nhuận liên tiếp. Nhưng thứ tự các năm nhuận không đúng với thứ tự đi trong mảng là từ dòng đầu tới cuối, trong mỗi dòng từ cột đầu tới cuối. Vì thế không thể dùng vòng FOR đơn giản mà phải tính toán chỉ số dòng cột dành cho các năm LIÊN TIẾP. Nhìn hình thì cũng thấy về chỉ số cột thì luôn lùi 2 bước, nhưng là đi "theo vòng tròn". Tức từ 1 sang 6 và từ 2 sang 7. Xuất phát từ cột 5 luôn lùi 2 bước sẽ có chuỗi 5, 3, 1, 6, 4, 2, 7 lặp lại.

Code có cao siêu gì đâu. Chẳng qua là anh thấy "cờ" đang vuột khỏi tay anh, người ta đang phất cờ lia lịa. Vì thế anh sốt ruột mà lao vào thôi. :D

Điều kiện là "mới bắt đầu" mà quý vị đốt giai đoạn dữ quá. Lúc vừa thấy câu đó, tôi đã nghi là quý vị sẽ chơi toàn những bài tính toán chỉ số mảng cho nên mới ra thêm phần "phân tích bằng lời" (bài #24).
@Bác tác giả bài #34:
Đây là đố vui. Nếu là đi thi thì lại khác. Còn trên bàn nhậu người ta đố liên tiếp nhiều trò, kể liên tiếp nhiều câu chuyện cười, tiếu lâm. Cứ đủng đỉnh như bác thì người ta đi tăng 2 tăng 3 rồi bác vẫn còn ngồi nghiền ngẫm lời giải, suy nghĩ xem có nên cười hay không.
Thực ra là tôi tham gia thôi. Không có ý định giúp ai hiểu. Nếu tôi làm gia sư, đang giảng bài thì lại khác.
 
...
Đây là đố vui. Nếu là đi thi thì lại khác. Còn trên bàn nhậu người ta đố liên tiếp nhiều trò, kể liên tiếp nhiều câu chuyện cười, tiếu lâm. Cứ đủng đỉnh như bác thì người ta đi tăng 2 tăng 3 rồi bác vẫn còn ngồi nghiền ngẫm lời giải, suy nghĩ xem có nên cười hay không.
...
Lúc đi "chén chú chén anh", tôi vẫn đi chung với một người bạn khác. Vào tới bàn là hai tôi phá lên cười như nắc nẻ. Những người khác trong bàn thắc mắc hỏi thì tôi trả lời:
- À, tôi cười những câu chuyện tếu các bác kể lần trước. Đến hôm nay tôi mới hiểu.
- Thế còn thằng B. Nó vốn thông minh lắm mà. Cũng phải đến nay mới cười được sao?
- Không, nó cười trước các câu chuyện mấy bác kể hôm nay đấy.

...
Thực ra là tôi tham gia thôi. Không có ý định giúp ai hiểu. Nếu tôi làm gia sư, đang giảng bài thì lại khác.
Bác ngứa tay code. Tôi thì ngứa mồm giảng. :p
Chỉ cần tay vả mồm hay mồm cắn tay thì cả hai đều hết ngứa?
 
thứ tự các năm nhuận không đúng với thứ tự dòng cột ... không thể dùng vòng FOR đơn giản mà phải tính toán chỉ số dòng cột dành cho các năm LIÊN TIẾP.
Tại anh nhìn kỹ quá. Tôi thì chỉ cần nhìn tới chỗ năm nào để vào cột có thứ nấy (trong tuần) là làm luôn. Vì dùng weekday (không phải whiskey) nên có sẵn thứ tự cột.
Code có cao siêu gì đâu. Chẳng qua là anh thấy "cờ" đang vuột khỏi tay anh, người ta đang phất cờ lia lịa. Vì thế anh sốt ruột mà lao vào thôi. :D
Cũng có 1 chút chút :p :p . Tuy vậy tôi vẫn chủ trương thuật toán đơn giản, code cho rõ ràng dù cho có dài hơn người ta.
 
Tại anh nhìn kỹ quá. Tôi thì chỉ cần nhìn tới chỗ năm nào để vào cột có thứ nấy (trong tuần) là làm luôn. ...
Bài này, theo tôi phân tích thì nó đâu có cần dữ liệu năm. Chỉ cần biết năm nhuần đầu tiên (2024) và năm giới hạn cuối cùng (2099) thôi.

Dim dte As Date
For dte = DateSerial(2024, 2, 29) To DateSerial(2099) Step 365 * 4 + 1
' code ghi dte ra bảng ở đây
Next dte

1. Cái công thức trên trông hỗn đọn nhưng thực ra nó chỉ phải tính mỗi thứ 1 lần. Các giải thuật trước dây phải gọi hàm dateserial ít nhất 19 lần.
2. Vì năm không gồm năm đầu thế kỷ (chia chẵn 100) cho nên con số 365 * 4 + 1 là đúng 4 năm.

Có cả phần ghi ra bảng:

Dim ngayThu(1 To 7) As Long ' mảng ghi nhớ vị trí hiện tại ở mỗi cột
Dim rg As Range, thu As Long
Set rg = #WorkSheet#.Range("ô gì đó") ' ô này là ô bắt đầu ghi dữ liệu
rg.Cells(0, 1).Resize(1, 7).Value = Array("CN", "T2", "T3", "T4", "T5", "T6", "T7") ' tiêu đề, 0 có nghĩa là dòng trên nó
Dim dte As Date
For dte = DateSerial(2024, 2, 29) To DateSerial(2099, 2, 29) Step 365 * 4 + 1
' code ghi dte ra bảng ở đây
thu = Weekday(dte)
ngayThu(thu) = ngayThu(thu) + 1
rg.Cells(ngayThu(thu), thu) = dte
Next dte
 
Giành cho người chưa có bài đăng trong chuyên mục này.

Trăm trâu, trăm cỏ
Trâu đứng ăn năm
Trâu nằm ăn ba
Trâu zà lựm khượm
Ba con một bó

Xin các bạn đưa ra mọi đáp án có thể!

Chúc các bạn vui xuân hạnh phúc & vui vẻ!
 
Giành cho người chưa có bài đăng trong chuyên mục này.

Trăm trâu, trăm cỏ
Trâu đứng ăn năm
Trâu nằm ăn ba
Trâu zà lựm khượm
Ba con một bó

Xin các bạn đưa ra mọi đáp án có thể!

Chúc các bạn vui xuân hạnh phúc & vui vẻ!
Đang lúc chờ kết quả
Mã:
Option Explicit

Sub trau_co()
Dim i, j, k, x, z
Sheet1.UsedRange.Clear
For i = 1 To 96
    For j = 1 To 96
        For k = 3 To 98 Step 3
            x = i + j + k
            z = i * 5 + j * 3 + k / 3
            If x = 100 And z = 100 Then
                Sheet1.Range("A" & Rows.Count).End(xlUp).Offset(1).Resize(1, 3) = Array(i, j, k)
            End If
        Next k
    Next j
Next i
End Sub
 
Bạn đang thiếu 1 nghiệm, 1 khi trước đó người ta đem 1 loại trâu nào đó giết thịt hết!
$$$$@
Có trường hợp đang ăn đứng chuyển thành ăn nằm không bác
Mã:
Option Explicit

Sub trau_co()
Dim i, j, k, x, z
Sheet1.UsedRange.Clear
For i = 0 To 100 Step 5
    For j = 0 To 100 Step 3
        For k = 3 To 100 Step 3
            x = i / 5 + j / 3 + k
            z = i + j + k / 3
            If x = 100 And z = 100 Then
                Sheet1.Range("A" & Rows.Count).End(xlUp).Offset(1).Resize(1, 3) = Array(i / 5, j / 3, k)
            End If
        Next k
    Next j
Next i
End Sub
 
...
(1) Trăm trâu, trăm cỏ. (2) Trâu đứng ăn năm. (3) Trâu nằm ăn ba. (4) Trâu zà lựm khượm. Ba con một bó

Xin các bạn đưa ra mọi đáp án có thể!

Khoan nói chuyện đáp án. Nói chuyện phân tích đề trước đã.
"trâu" theo tiếng Việt là danh tự. Theo văn phạm thì danh tự số nhiều hay ít viết và đọc in hệt nhau, không hề phân biệt.
Câu (1) xác định rõ ràng 100X và 100Y
Từ 3 câu (2), (3), (4), ta có thể chia thêm X = Xd + Xn + Xg
ĐOÁN rằng câu hỏi là tìm d, n, g
d + n + g = 100
Nhưng câu (2) (3) không xác định rõ:
(i) Tất cả các trâu đứng chỉ ăn chung 5, tất cả trâu nằm chỉ ăn chung 3:
5 + 3 + (g/3) = 100
(ii) Các trâu đứng mỗi con ăn 5, các trâu nằm mỗi con ăn 3:
5*d + 3*n + g/3 = 100

Tức là ở đây có 2 đề bài chứ không phải 1.
 
Khoan nói chuyện đáp án. Nói chuyện phân tích đề trước đã.
"trâu" theo tiếng Việt là danh tự. Theo văn phạm thì danh tự số nhiều hay ít viết và đọc in hệt nhau, không hề phân biệt.
Câu (1) xác định rõ ràng 100X và 100Y
Từ 3 câu (2), (3), (4), ta có thể chia thêm X = Xd + Xn + Xg
ĐOÁN rằng câu hỏi là tìm d, n, g
d + n + g = 100
Nhưng câu (2) (3) không xác định rõ:
(i) Tất cả các trâu đứng chỉ ăn chung 5, tất cả trâu nằm chỉ ăn chung 3:
5 + 3 + (g/3) = 100
(ii) Các trâu đứng mỗi con ăn 5, các trâu nằm mỗi con ăn 3:
5*d + 3*n + g/3 = 100

Tức là ở đây có 2 đề bài chứ không phải 1.
Tôi không giỏi tiếng Việt đến mức này nhưng ngay từ đầu tôi đã thấy. Tôi bỏ qua nhưng bây giờ lại thấy. Ở đây nói chuyện giành giật cái gì đấy mọi người ơi.
 
Tôi quên mất.
Bài ấy đâu có nói trâu già không được quyền đứng hay nằm? Vậy là phải phân tích lại.

Tôi có nói là mình chậm tiêu. Đố mẹo hôm nay, cả tuần sau tôi mới nghiệm ra. :p
 
Đặt các ẩn Dg, Nm và Gia lần lượt là số trâu đứng, nằm và trâu già, ta lập được 2 phương trình :
Dg + Nm +Gia = 100 (1),
5Dg + 3 Nm + Gia/3 = 100 (2).
Khử ẩn Gia ta lấy (2) x 3, xong trừ cho (1) ta được:
14Dg + 8Nn = 200 (3)
Chia cả 2 vế của (3) cho 8 ta nhận đươc đẳng thức sau: 7xDg/4 + Nm = 25, (5).
Từ (5) ta có nhận xét: Dg < 25 (điều này có thể nhận xét ngay từ đề bài)
(& quan trọng để xài trong VBA là: ) Dg chỉ có thể là 0 hay bội số của 4
Vậy vòng lặp ngoài cùng cho trâu đứng (của bài 47) được rút ngăn lại chỉ là
For I = 0 to 24

Next I;

& phát huy chiến quả này, vòng lặp kế tiếp (cho trâu nằm) cũng chỉ là
For J =0 to 34 Step 3

Next J
Xin cảm ơn CHAOQUAY nhiều &
Chúc các bác vui vẻ nhân dịp xuân về!
 
Lần chỉnh sửa cuối:
... Từ (5) ta có nhận xét: Dg < 25 (điều này có thể nhận xét ngay từ đề bài)
....
Trời đất, bạn đi lòng vòng mấy lượt mới về đây.
Chận trên của các ẩn số có thể xác định bằng cách đặt hai ẩn số còn lại bằng 0.
5d + 3n + g/3 = 100 ==> d <= 20; n <= 33 ; g = 3t (t=0-33)
Điểm mấu chốt của bài toán là chúng ta tính trên số nguyên.
Nếu dùng VBA thì dùng thuật toán vét cạn dễ hiểu nhất. Và dùng thuật toán vét cạn thì phân tích rất dễ. Điểm phân tích duy nhất là số trâu già phải chia chẵn 3 (3 con là một đơn vị ăn)

1644722424702.png

Chú thích:
...
& phát huy chiến quả này, vòng lặp kế tiếp (cho trâu nằm) cũng chỉ là
For J =0 to 34 Step 3

Next J
...
Theo thuật toán vét cạn thì vòng lặp trong chỉ đi theo giới hạn được định ra bởi vòng lặp ngoài. Ở code trên, bạn sẽ thấy vòng lặp ngoài cùng xét số trâu già, {số trâu - trâu già} là số trâu không già. Vòng lặp trong xét trâu nằm cho nên nó chỉ tính tới {số trâu - trâu già}. Step có thể giúp giảm số một chút nhưng mất công phân tích số trâu nằm phải chia chẵn bao nhiêu. Vòng lặp thứ ba không cần thiết bởi vì nếu đã vét cạn g và n rồi thì d tự nhiên là {số trâu - g - n}. Con toán tôi dùng rất giản dị, biểu hiện đúng phương trình bài toán.
 

Bài viết mới nhất

Back
Top Bottom