Bài tập về vòng lặp cho người mới bắt đầu

BÀI 01: MÃ HÓA 1 ĐOẠN VĂN BẢN​

ABCDEFTS4BIQTOI YEU GIAI PHAP EXCEL TU 2006
GHIJKLRA5CJV
MNOPQRU06DKW?
STUVWXO17ELX
YZ0123N28FMY
456789G39HPZ
NM
Ta có bảng N với 36 ký tự & ký số được sắp xếp theo 1 trật tự qui ước



& bảng M cũng những kí tự & ký số đó ta bố trí theo mật mã có chìa khóa là 'TRUONG SA'

Đề bài yêu cầu chúng ta mã hòa câu "TOI YEU GIAI PHAP EXCEL TU 2006"

Xin lưu ý: Đề bài chỉ dành ch những lập trình viên VBA trình độ sơ cấp
Rất mong nhận được nhiều ý kiến & lời giải

[Gọi ý lần 1] (Sau 3 giờ): 'YEU' => 'NI7'
 
Lần chỉnh sửa cuối:

Bình luận

BÀI 01: MÃ HÓA 1 ĐOẠN VĂN BẢN​

ABCDEFTS4BIQTOI YEU GIAI PHAP EXCEL TU 2006
GHIJKLRA5CJV
MNOPQRU06DKW?
STUVWXO17ELX
YZ0123N28FMY
456789G39HPZ
NM
Ta có bảng N với 36 ký tự & ký số được sắp xếp theo 1 trật tự qui ước



& bảng M cũng những kí tự & ký số đó ta bố trí theo mật mã có chìa khóa là 'TRUONG SA'

Đề bài yêu cầu chúng ta mã hòa câu "TOI YEU GIAI PHAP EXCEL TU 2006"

Xin lưu ý: Đề bài chỉ dành ch những lập trình viên VBA trình độ sơ cấp
Rất mong nhận được nhiều ý kiến & lời giải

[Gọi ý lấn]: 'YEU' => 'NI7'
Cái này như kiểu là lấy đủ tên đó rồi còn thừa ký tự nào thì bỏ sang bên canh.Mà có giải thưởng không bác Sa.
 
Làm xong bài tập này thành công thì người học đạt (trình độ) gì?
Với "vòng lặp" thì nó quá căn bản. Chưa đủ để thách thức hiểu biết về vòng lặp.
Với kiến thức giải thuật (phép áp 1-1 chuyển đổi giữa hai tập hợp) thì nó lại vượt trên căn bản rồi.
Trước mắt thì có vài giải thuật về phép áp. Và độ cao cấp tuỳ thuộc vào sự uyển chuyển của bảng mã.
 
Làm xong bài tập này thành công thì người học đạt (trình độ) gì?
Với "vòng lặp" thì nó quá căn bản. Chưa đủ để thách thức hiểu biết về vòng lặp. . . . .
Bài này chỉ nhắm là ôn lại kiến thức vòng lặp bình thường thôi mà anh!

Với các bạn khác: Đáp án ở bài #4 là phương án xài 3 vòng lặp
Nếu ta xài kết hợp với phương thức FIND() thì chỉ cần 1 vòng lặp để duyệt mệnh đề cần mã hóa; Các bạn có thể thử thêm xem sao?
 
Lần chỉnh sửa cuối:
Bài này chỉ nhắm là ôn lại kiến thức vòng lặp bình thường thôi mà anh!

Với các bạn khác: Đáp án ở bài #4 là phương án xài 3 vòng lặp
Nếu ta xài kết hợp với phương thức FIND() thì chỉ cần 1 vòng lặp để duyệt mệnh đề cần mã hóa; Các bạn có thể thử thêm xem sao?
Cháu xin gửi lời giải như sau:
 

File đính kèm

Sau khi các bạn mã hóa thành công Bác SA_DG dẫn các bạn đến đây luôn

Advanced Encryption Standard (Tiêu chuẩn mã hóa tiên tiến - AES)

Hoặc Twofish

Trót học mã hóa, học thêm để thành chuyên gia.
 
Lần chỉnh sửa cuối:
Rốt cuộc lại thì bài này là học vòng lặp hay mã hoá?
Đã mang cái tiêu đề "căn bản" thì lo chu toàn cái "căn bản". Chưa gì hết đã tính lúc thành "chuyên gia".

Bài này chỉ nhắm là ôn lại kiến thức vòng lặp bình thường thôi mà anh!

Với các bạn khác: Đáp án ở bài #4 là phương án xài 3 vòng lặp
Nếu ta xài kết hợp với phương thức FIND() thì chỉ cần 1 vòng lặp để duyệt mệnh đề cần mã hóa; Các bạn có thể thử thêm xem sao?
Lúc ra cái đề ở bài #1, bạn đã hơi chủ quan.
Bạn không hề cho biết 2 cái bảng A và B nó ở dạng nào. Phải đọc đến bài #6 người ta mới đoán rằng nó là hai bản dữ liệu nằm trong một bảng tính - và chỉ đoán thôi chứ vẫn chưa có gì xác định.

Chú thích: theo tôi thì bài này chủ yếu về làm vệc với kiểu dữ liệu chuỗi. Duyệt chuỗi thì phải có căn bản vòng lặp. Thế thôi.
 
Lần chỉnh sửa cuối:
Đúng là đề bài ở #1 chưa rõ ràng & có lời xin lỗi về điều này đến cộng đồng!
Đến thời điểm này cả hai lời giải đều thỏa mãn với đề ra.
Rất mong các anh chị khác tiếp tục có những bài giải khác hơn!

Các bạn cũng có thể viết 1 macro để giải mã mệnh đề đã được mã hóa
Cũng có thể các bạn đề ra 1 khóa mật mã khác & mã hóa câu mà đề bài đưa ra với 2 khóa mật mã.
Chúc các bạn vui & hào hứng trong công việc!
 
Đúng là đề bài ở #1 chưa rõ ràng & có lời xin lỗi về điều này đến cộng đồng!
Đến thời điểm này cả hai lời giải đều thỏa mãn với đề ra.
Rất mong các anh chị khác tiếp tục có những bài giải khác hơn!

Các bạn cũng có thể viết 1 macro để giải mã mệnh đề đã được mã hóa
Cũng có thể các bạn đề ra 1 khóa mật mã khác & mã hóa câu mà đề bài đưa ra với 2 khóa mật mã.
Chúc các bạn vui & hào hứng trong công việc!
Code theo hướng dẫn của Bác với file của bài #4
Mã:
Sub MAHOA()
Dim k As Long
Dim Str As String, col As Long, rol As Long
Dim chuoiindex As String

With Sheet1
Str = .Range("P1").Value
For k = 1 To Len(Str)
    If Mid(Str, k, 1) = " " Then
        chuoiindex = chuoiindex & " "
    Else
        col = .Range("A1:F6").Find(What:=Mid(Str, k, 1), MatchCase:=True).Column
        rol = .Range("A1:F6").Find(What:=Mid(Str, k, 1), MatchCase:=True).row
        chuoiindex = chuoiindex & .Cells(rol, col + 8).Value
    End If
Next k
.Range("P2").Value = chuoiindex
End With
End Sub
 
Đúng vậy. Thay đổi từng ký tự một là trường hợp kinh điển để sử dụng hàm MID.

Code theo hướng dẫn của Bác với file của bài #4
Mã:
Sub MAHOA()
Dim k As Long
Dim Str As String, col As Long, rol As Long
Dim chuoiindex As String

With Sheet1
Str = .Range("P1").Value
For k = 1 To Len(Str)
    If Mid(Str, k, 1) = " " Then
        chuoiindex = chuoiindex & " "
    Else
        col = .Range("A1:F6").Find(What:=Mid(Str, k, 1), MatchCase:=True).Column
        rol = .Range("A1:F6").Find(What:=Mid(Str, k, 1), MatchCase:=True).row
        chuoiindex = chuoiindex & .Cells(rol, col + 8).Value
    End If
Next k
.Range("P2").Value = chuoiindex
End With
End Sub
Code này còn lủng củng lắm.
vòng lặp làm việc Len(Str) lần. Mỗi lần thì bạn lại phải gọi cái hàm tính Range("A1:F6") ra 2 lần.
Nếu đặt Set rgN = .Range("A1:F6") từ đầu thì cứ từ đó mà làm, khỏi phải tính lại.
Và chỉ cần dùng hàm Find 1 lần, set 1 object range. Bên tra thì dùng hàm Offset
Set match = rgN.Find(What:=Mid(Str, k, 1), MatchCase:=True)
chuoiindex = chuoiindex & match.Offset(0, 8).Value
Hoặc như vầy luôn cho nó nguy hiểm:
chuoiindex = chuoiindex & rgN.Find(What:=Mid(Str, k, 1), MatchCase:=True).Offset(0, 8).Value
 
Lần chỉnh sửa cuối:
Rất cảm ơn bạn vì lời giải!
Mã:
        col = .Range("A1:F6").Find(What:=Mid(Str, k, 1), MatchCase:=True).Column
        rol = .Range("A1:F6").Find(What:=Mid(Str, k, 1), MatchCase:=True).row
Đây là các dòng lệnh xác định 1 kí tự trong chuỗi cần mã hóa có trong bản N (bên trái) nằm ở cột & hàng nào.
Nhưng lỡ kí tự đó không có trong bảng N ( ví dụ " ", ":",. . . ) thì sao đây?
Nên chăng ta khai báo thêm 1 biến đối tượng để lưu kết quả công cuộc tìm kiếm này?
Khi đó nếu tìm không thấy thì thêm nó vô chuỗi mã hóa(!)
 
...Nhưng lỡ kí tự đó không có trong bảng N ( ví dụ " ", ":",. . . ) thì sao đây?
Nên chăng ta khai báo thêm 1 biến đối tượng để lưu kết quả công cuộc tìm kiếm này?
Khi đó nếu tìm không thấy thì thêm nó vô chuỗi mã hóa(!)
Thêm bằng cách nào? Lúc giải mã thì dựa vào đâu để giải?
Cách dễ hơn hết là nếu không tìm thấy thì để yên. Và vì vậy, phải thêm phần nếu không tìm thấy thì xét bên bảng mã. Nếu bên bảng mã có thì hỏng bét, không mã hoá được.

Nhưng rốt lại, đây là bài tập về vòng lặp, cứ giữ nó thế đi.
Việc rắc rối của mã hoá tính ở chỗ khác.
Điểm quan trọng hơn là độ chuẩn của hai bảng mã. Ở bài #5 tôi có nói "đây là phép áp 1-1 giữa hai tập hợp". Và phép áp này phải có tính chất nghịch đảo được (mã hoá 1 ký tự sang 1 ký tự, và giải mã cũng 1 ra 1). Điều kiện quan trọng của phép áp nghịch đảo được là phần tử không có trùng lặp.
 
Bảng N & bảng M là quan hệ với nhau 1-1; Như vậy những ký tự ngoại lai sẽ được giữ nguyện cả khi mã hóa hay giải mã mà anh.
Ý mình muốn nói là
PHP:
If Mid(Str, k, 1) = " " Then
        chuoiindex = chuoiindex & " "  '?    '
    Else
    . . . . . .
    End If
là quá chắc cú & có thể viết cách khác được chăng?
 
BÀI 01: MÃ HÓA 1 ĐOẠN VĂN BẢN​

ABCDEFTS4BIQTOI YEU GIAI PHAP EXCEL TU 2006
GHIJKLRA5CJV
MNOPQRU06DKW?
STUVWXO17ELX
YZ0123N28FMY
456789G39HPZ
NM
Ta có bảng N với 36 ký tự & ký số được sắp xếp theo 1 trật tự qui ước





& bảng M cũng những kí tự & ký số đó ta bố trí theo mật mã có chìa khóa là 'TRUONG SA'

Đề bài yêu cầu chúng ta mã hòa câu "TOI YEU GIAI PHAP EXCEL TU 2006"

Xin lưu ý: Đề bài chỉ dành ch những lập trình viên VBA trình độ sơ cấp
Rất mong nhận được nhiều ý kiến & lời giải

[Gọi ý lần 1] (Sau 3 giờ): 'YEU' => 'NI7'
Code không lấy dữ liệu trên Range
Mã:
Option Explicit
Function MaHoa(ByVal iStr$, ByVal iCode$, ByVal sRow&) As String
  Dim abc$, def$, BangMa$, j&

  abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  def = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  iStr = UCase(iStr)
  BangMa = TronMa(def, UCase(Replace(iCode, " ", "", 1)), sRow) & " "
  abc = abc & " "
  For j = 1 To Len(iStr)
    Mid(iStr, j, 1) = Mid(BangMa, InStr(1, abc, Mid(iStr, j, 1)), 1)
  Next j
  MaHoa = iStr
End Function

Function GiaiMa(ByVal iStr$, ByVal iCode$, ByVal sRow&) As String
  Dim abc$, def$, BangMa$, j&

  abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  def = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  iStr = UCase(iStr)
  BangMa = TronMa(def, UCase(Replace(iCode, " ", "", 1)), sRow) & " "
  abc = abc & " "
  For j = 1 To Len(iStr)
    Mid(iStr, j, 1) = Mid(abc, InStr(1, BangMa, Mid(iStr, j, 1)), 1)
  Next j
  GiaiMa = iStr
End Function

Private Function TronMa(ByVal def$, ByVal iCode$, ByVal sRow&) As String
  Dim Res$, sCol&, j&, jC&, q&, n&

  q = Len(def)
  sCol = (q - 1) \ sRow + 1
  def = iCode & def
  For j = 1 To Len(iCode)
    def = Mid(def, 1, j) & Replace(Mid(def, j + 1, Len(def)), Mid(iCode, j, 1), "")
  Next j
  Res = def
  n = sCol * sRow - 1
  For j = 0 To n
    If j < q Then
      If j Mod sCol = 0 Then jC = j \ sCol + 1 Else jC = jC + sRow
      If jC <= q Then Mid(Res, j + 1, 1) = Mid(def, jC, 1)
    End If
  Next j
  TronMa = Res
End Function
Công thức trên bảng tính
=MaHoa("TOI YEU GIAI PHAP EXCEL VBA","TRUONG SA",6)
=GiaiMa("165 NI7 R5T5 DATD IX4IV EST","TRUONG SA",6)
số 6 là số dòng của bảng chuyển mã
Thật ra gộp 2 Function thánh 1 sẽ gọn hơn
 
Rất cảm ơn bạn vì lời giải!

Đây là các dòng lệnh xác định 1 kí tự trong chuỗi cần mã hóa có trong bản N (bên trái) nằm ở cột & hàng nào.
Nhưng lỡ kí tự đó không có trong bảng N ( ví dụ " ", ":",. . . ) thì sao đây?
Nên chăng ta khai báo thêm 1 biến đối tượng để lưu kết quả công cuộc tìm kiếm này?
Khi đó nếu tìm không thấy thì thêm nó vô chuỗi mã hóa(!)
Xin được gửi lại bài theo hướng dẫn của Bác
Mã:
Sub MAHOA()
Dim k As Long, Lr As Long
Dim Str As String
Dim chuoiindex As String, bangma As String, Arr As Range, Rng As Range

With Sheet1
Str = .Range("P1").Value
Lr = .Range("A1000").End(xlUp).row
Set Arr = .Range("A2:F" & Lr + 1)
With WorksheetFunction
    bangma = .TextJoin("", True, Arr)
End With

For k = 1 To Len(Str)
    
    If Mid(Str, k, 1) = " " Then
        chuoiindex = chuoiindex & " "
    Else
        If InStr(bangma, Mid(Str, k, 1)) = 0 Then
            For Each Rng In Arr
                If Rng.Value = "" Then
                    Rng = Mid(Str, k, 1)
                    Rng.Offset(, 8) = InputBox("ky tu: " & Mid(Str, k, 1) & " da duoc tu dong them vao bang N " & Chr(10) & "Vui long nhap ma chuyen doi cho bang M: ", "GPE")
                    Exit For
                End If
            Next Rng
        End If
        chuoiindex = chuoiindex & Arr.Find(What:=Mid(Str, k, 1), MatchCase:=True).Offset(, 8).Value
    End If
Next k
.Range("P2").Value = chuoiindex
End With
End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
Bảng N & bảng M là quan hệ với nhau 1-1; Như vậy những ký tự ngoại lai sẽ được giữ nguyện cả khi mã hóa hay giải mã mà anh.
Ý mình muốn nói là
PHP:
If Mid(Str, k, 1) = " " Then
        chuoiindex = chuoiindex & " "  '?    '
    Else
    . . . . . .
    End If
là quá chắc cú & có thể viết cách khác được chăng?
Function mã hóa và giải mã, tịnh tiến cột chuyển mã sẽ khó dò ký tự để giải mã, các ký tự chưa khai báo sẽ giữ nguyên
Mã:
Option Explicit
Function MaHoa(ByVal iStr$, ByVal iCode$, ByVal sRow&, Optional bGiaiMa As Boolean = False) As String
  Dim abc$, def$, BangMa$, iChar$, j&, n&, jC&

  abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  iStr = UCase(iStr)
  BangMa = TronMa(abc, UCase(Replace(iCode, " ", "", 1)), sRow)
  n = Len(iStr)
  For j = 1 To n
    iChar = Mid(iStr, j, 1)
    If InStr(1, abc, Mid(iStr, j, 1)) Then
      If bGiaiMa = False Then
        jC = (InStr(1, abc, Mid(iStr, j, 1)) + j) Mod n + 1
        Mid(iStr, j, 1) = Mid(BangMa, jC, 1)
      Else
        jC = (InStr(1, BangMa, Mid(iStr, j, 1)) - j - 2) Mod n + 1
        If jC < 1 Then jC = n + jC
        Mid(iStr, j, 1) = Mid(abc, Abs(jC), 1)
      End If
    End If
  Next j
  MaHoa = iStr
End Function

Private Function TronMa(ByVal def$, ByVal iCode$, ByVal sRow&) As String
  Dim Res$, sCol&, j&, jC&, q&, k&
 
  q = Len(def)
  sCol = (q - 1) \ sRow + 1
  def = iCode & def
  For j = 1 To Len(iCode)
    def = Mid(def, 1, j) & Replace(Mid(def, j + 1, Len(def)), Mid(iCode, j, 1), "")
  Next j
  Res = def
  jC = 1 - sRow: k = 1
  For j = 1 To q
    If jC + sRow > q Then
      k = k + 1
      jC = k
    Else
      jC = jC + sRow
    End If
    Mid(Res, j, 1) = Mid(def, jC, 1)
  Next j
  TronMa = Res
End Function
Cách dùng trong file
 

File đính kèm

Top Bottom