Tạo mã từ một ma trận không vuông (2 người xem)

Liên hệ QC

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

Wanderman

Thành viên mới
Tham gia
30/6/08
Bài viết
47
Được thích
8
Em đang vướng việc tạo mã chạy kiểu giai thừa trong một ma trận không vuông cho trước. Em có gửi file đính kèm, nhờ các bác giúp em với.

Thực tế ma trận của em rộng hơn và không vuông, nhưng em chỉ cần cách tính thôi. Cảm ơn các bác trước!
 

File đính kèm

Cái này bạn có tổng cộng là bao nhiêu cột? đại khái thôi
 
Bài này nếu xác định số cột thì viết code dễ dàng. Nếu không xác định được số cột thì phải viết code đệ quy để đi ruồng hết tất cả các cột, rắc rối lắm.

Vả lại cách tạo mã như trên chả theo một tiêu chuẩn nào cả. Dùng cho 3 cột thì được, nhưng trên 3 cột thì bố ai biết nó sẽ ra sao?
Ta có thể đoán rằng mã chỉ gồm 8 ký tự, 2 ký tự đầu là cột 1, 3 ký tự kế là cột 2, 3 ký tự kế là cột 3 ?
 

File đính kèm

Bạn dùng công thức nhé, bắt tí lỗi cho giới hạn số phần tử nữa là ok
Mã:
=OFFSET($D$4,MOD(INT((ROW(1:1)-1)/25),25),0)&OFFSET($E$4,MOD(INT((ROW(1:1)-1)/5),5),0)&OFFSET($F$4,MOD(ROW(1:1)-1,5),0)
 
Bài này nếu xác định số cột thì viết code dễ dàng. Nếu không xác định được số cột thì phải viết code đệ quy để đi ruồng hết tất cả các cột, rắc rối lắm.

Vả lại cách tạo mã như trên chả theo một tiêu chuẩn nào cả. Dùng cho 3 cột thì được, nhưng trên 3 cột thì bố ai biết nó sẽ ra sao?
Ta có thể đoán rằng mã chỉ gồm 8 ký tự, 2 ký tự đầu là cột 1, 3 ký tự kế là cột 2, 3 ký tự kế là cột 3 ?
À, chỉ lấy theo thứ tự từ cột đầu đến cột cuối, chứ không lấy bắt đầu từ cột 2,3,... mình có ví dụ làm bằng tay tại file rồi mà?
 
...
Ta có thể đoán rằng mã chỉ gồm 8 ký tự, 2 ký tự đầu là cột 1, 3 ký tự kế là cột 2, 3 ký tự kế là cột 3 ?

À, chỉ lấy theo thứ tự từ cột đầu đến cột cuối, chứ không lấy bắt đầu từ cột 2,3,... mình có ví dụ làm bằng tay tại file rồi mà?

Theo ví dụ tay, bạn có VT0902AB; đấy là do bạn lấy VT từ cột 1, 90 từ cột 2, và 2AB từ cột 3. Cộng lại. Vì 90 chỉ có 2 ký tự mà bạn cần 3 ký tự từ cột 2 cho nên bạn chêm vào 0.

Bạn đem ra đối chiếu các màu với nhau xem tôi nói có đúng không?
 
@phihndhsp: cocde thì dễ rồi. Nhưng code làm thế nào để không bị lệ thuộc vào số cột số dòng?
Theo toán thì bắt buộc phải dùng kỹ thuật vét cạn. Kỹ thuật vét cạn đơn giản nhất là hàm đệ quy.

Mã:
Sub t()
Dim a As Variant, b As Variant ' input and output arrays
Dim r As Integer, s As String, i As Integer
a = Range("d4:f8").Value ' input matrix
ReDim b(1 To UBound(a) ^ UBound(a, 2)) ' output array
r = 0
' I am too lazy to write a full recursive routine
' thus I will let the main program go thru each line of the first column
' and the called routine automatically recurses over the rest
For i = 1 To UBound(a) ' go thru the first column
Call Combi(b, r, "", a, i, 1) ' combi is a recursive routine, it will go thru all other columns
Next i
For i = 1 To UBound(b) ' output
    Range("G11").Offset(i - 1).Value = b(i)
Next i
End Sub

Sub Combi(ByRef oarr As Variant, ByRef oRow As Integer, ByVal oStr As String, _
    ByVal iarr As Variant, ByVal iRow As Integer, ByVal iCol As Integer)
' parameters: output array, current output row, output string,
'               input array, input array current row, input array current column
Dim i As Integer, s As String
s = iarr(iRow, iCol)
If iCol > 1 And Len(s) < 3 Then s = Right("000" & s, 3) ' patch the length with 0's
oStr = oStr & s
If iCol >= UBound(iarr, 2) Then ' last column, no need to go any further
    oRow = oRow + 1
    oarr(oRow) = oStr
    Exit Sub
End If
For i = 1 To UBound(iarr) ' continue to go thru every line of the next level
Combi oarr, oRow, oStr, iarr, i, iCol + 1
Next i
End Sub
 
@phihndhsp: cocde thì dễ rồi. Nhưng code làm thế nào để không bị lệ thuộc vào số cột số dòng?
Theo toán thì bắt buộc phải dùng kỹ thuật vét cạn. Kỹ thuật vét cạn đơn giản nhất là hàm đệ quy.
dạ em biết cái này nhưng sợ khi mình viết xong người hỏi lại yêu cầu thêm khác nữa nên chưa có viết tổng quát được. viết tạm cái đã rồi tính sau
 
Em đang vướng việc tạo mã chạy kiểu giai thừa trong một ma trận không vuông cho trước. Em có gửi file đính kèm, nhờ các bác giúp em với.

Thực tế ma trận của em rộng hơn và không vuông, nhưng em chỉ cần cách tính thôi. Cảm ơn các bác trước!
Bạn thử code này, thay arr=range("D4:F8").value thành range khác hoặc đặt name hoặc Selection.
Mã:
Sub abc()
    Dim arr(), m&, n&, mn&, i&, j&, brr(), kq()
    arr = Range("D4:F8").Value2
    m = UBound(arr, 1)
    n = UBound(arr, 2)
    ReDim brr(1 To n)
    mn = 1
    For i = 1 To n
        brr(i) = 1
        mn = mn * m
    Next
    ReDim kq(1 To mn, 1 To 1)
    For j = 1 To mn
        For i = 1 To n
            kq(j, 1) = kq(j, 1) & arr(brr(i), i)
        Next
        For i = n To 1 Step -1
            brr(i) = brr(i) + 1
            If brr(i) <= m Then Exit For
            brr(i) = 1
        Next
    Next
    Range("B11").Resize(mn) = kq
End Sub
 
Bạn thử code này, thay arr=range("D4:F8").value thành range khác hoặc đặt name hoặc Selection.
Mã:
Sub abc()
    Dim arr(), m&, n&, mn&, i&, j&, [COLOR=#ff0000]brr()[/COLOR], kq()
    arr = Range("D4:F8").Value2
    m = UBound(arr, 1)
    n = UBound(arr, 2)
    ReDim brr(1 To n)
    mn = 1
    For i = 1 To n
        brr(i) = 1
        mn = mn * m
    Next
    ReDim kq(1 To mn, 1 To 1)
    For j = 1 To mn
        For i = 1 To n
            kq(j, 1) = kq(j, 1) & arr(brr(i), i)
        Next
        For i = n To 1 Step -1
            brr(i) = brr(i) + 1
            If brr(i) <= m Then Exit For
            brr(i) = 1
        Next
    Next
    Range("B11").Resize(mn) = kq
End Sub

Không bàn đến code nha... chỉ là mình nhìn cái tên biến brr tự dưng tức cười --=0 (hổng biết tại sao nữa )
 
@phihndhsp: cocde thì dễ rồi. Nhưng code làm thế nào để không bị lệ thuộc vào số cột số dòng?
Theo toán thì bắt buộc phải dùng kỹ thuật vét cạn. Kỹ thuật vét cạn đơn giản nhất là hàm đệ quy.

Mã:
Sub t()
Dim a As Variant, b As Variant ' input and output arrays
Dim r As Integer, s As String, i As Integer
a = Range("d4:f8").Value ' input matrix
ReDim b(1 To UBound(a) ^ UBound(a, 2)) ' output array
r = 0
' I am too lazy to write a full recursive routine
' thus I will let the main program go thru each line of the first column
' and the called routine automatically recurses over the rest
For i = 1 To UBound(a) ' go thru the first column
Call Combi(b, r, "", a, i, 1) ' combi is a recursive routine, it will go thru all other columns
Next i
For i = 1 To UBound(b) ' output
    Range("G11").Offset(i - 1).Value = b(i)
Next i
End Sub

Sub Combi(ByRef oarr As Variant, ByRef oRow As Integer, ByVal oStr As String, _
    ByVal iarr As Variant, ByVal iRow As Integer, ByVal iCol As Integer)
' parameters: output array, current output row, output string,
'               input array, input array current row, input array current column
Dim i As Integer, s As String
s = iarr(iRow, iCol)
If iCol > 1 And Len(s) < 3 Then s = Right("000" & s, 3) ' patch the length with 0's
oStr = oStr & s
If iCol >= UBound(iarr, 2) Then ' last column, no need to go any further
    oRow = oRow + 1
    oarr(oRow) = oStr
    Exit Sub
End If
For i = 1 To UBound(iarr) ' continue to go thru every line of the next level
Combi oarr, oRow, oStr, iarr, i, iCol + 1
Next i
End Sub
Cám ơn bác VetMini và các bác khác. Thực ra giải pháp các bác đều xử lý được vấn đề của em. Tuy nhiên để xử lý được mọi tình huống có thể xảy ra thì em đang cân nhắc các giải pháp đặc biệt là cách của bác VetMini.:D
 
Web KT

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

Back
Top Bottom