Chọn 10 cái tên ngẫu nhiên trong danh sách 20 tên (1 người xem)

Liên hệ QC

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

Manhcuong1236985

Thành viên mới
Tham gia
23/1/19
Bài viết
11
Được thích
1
Chào các anh chị. Cho em hỏi bài toán như sau
Cho 1 danh sách gồm 20 cái tên khác nhau, yêu cầu nhấc ra 1 tổ hợp gồm 10 tên ngẫu nhiên trong danh sách 20 tên đó, sao cho không có cái tên nào trong cùng 1 tổ hợp bị trùng nhau. Kết quả nằm trong 1 cell và các tên ngăn nhau bằng dấu trừ.
Nhờ anh chị cho em xin công thức ạ. Em xin cảm ơn nhiều!
Ảnh chụp Màn hình 2019-01-23 lúc 14.59.17.png
 
=RANDBETWEEN(A1,A2) &"-"& RANDBETWEEN(A3,A4)&"-"& RANDBETWEEN(A5,A6)&"-"& RANDBETWEEN(A7,A8)&"-"& RANDBETWEEN(A9,A10)&.....
Đơn giản quá nhỉ :D
 
Chào các anh chị. Cho em hỏi bài toán như sau
Cho 1 danh sách gồm 20 cái tên khác nhau, yêu cầu nhấc ra 1 tổ hợp gồm 10 tên ngẫu nhiên trong danh sách 20 tên đó, sao cho không có cái tên nào trong cùng 1 tổ hợp bị trùng nhau. Kết quả nằm trong 1 cell và các tên ngăn nhau bằng dấu trừ.
Nhờ anh chị cho em xin công thức ạ. Em xin cảm ơn nhiều!
View attachment 211501
Bạn thử code này:
Mã:
Sub a()
Dim arr, num As Long, key, str As String
arr = [A1:A20]
With CreateObject("Scripting.dictionary")
    Do While .Count < 10
Randomize
        num = Int(Rnd() * 20) + 1
        If Not .exists(num) Then .Add num, arr(num, 1)
    Loop
        str = Join(.items(), " - ")
End With
[c1].Value = str
End Sub
 
Lần chỉnh sửa cuối:
Chào các anh chị. Cho em hỏi bài toán như sau
Cho 1 danh sách gồm 20 cái tên khác nhau, yêu cầu nhấc ra 1 tổ hợp gồm 10 tên ngẫu nhiên trong danh sách 20 tên đó, sao cho không có cái tên nào trong cùng 1 tổ hợp bị trùng nhau. Kết quả nằm trong 1 cell và các tên ngăn nhau bằng dấu trừ.
Nhờ anh chị cho em xin công thức ạ. Em xin cảm ơn nhiều!
View attachment 211501
Nếu không nối chuỗi có thể dùng công thức này:
=INDEX($A$1:$A$20,SMALL(IF(COUNTIF($E$1:E1,$A$1:$A$20)=0,ROW($1:$20)),RANDBETWEEN(1,21-COLUMN(A1))))
Bấm Ctrl+Shift+Enter rồi kéo sang phải.
 

File đính kèm

Bạn thử code này:
Mã:
Sub a()
Dim arr, num As Long, key, str As String
arr = [A1:A20]
With CreateObject("Scripting.dictionary")
    Do While .Count < 10
Randomize
        num = Int(Rnd() * 20) + 1
        If Not .exists(num) Then .Add num, ""
    Loop
    For Each key In .keys()
        str = str & IIf(str = "", "", " - ") & arr(key, 1)
    Next
End With
[c1].Value = str
End Sub
Thử dùng Join cho đẹp
 
Chào các anh chị. Cho em hỏi bài toán như sau
Cho 1 danh sách gồm 20 cái tên khác nhau, yêu cầu nhấc ra 1 tổ hợp gồm 10 tên ngẫu nhiên trong danh sách 20 tên đó, sao cho không có cái tên nào trong cùng 1 tổ hợp bị trùng nhau. Kết quả nằm trong 1 cell và các tên ngăn nhau bằng dấu trừ.
Nhờ anh chị cho em xin công thức ạ. Em xin cảm ơn nhiều!
View attachment 211501
Dùng hàm tự tạo
Mã:
Function GPE(ByVal Rng As Range, ByVal n As Long)
  Dim Str As String, tmp As String, m As Long, i As Long, j As Long
  m = Rng.Rows.Count
  Str = "- " & Join(Application.Transpose(Rng), " - ") & " -"
  Randomize
  For i = 1 To m - n
    num = Int(Rnd() * (m + 1 - i)) + 1
    tmp = Replace(Str, "-", "#", 1, num)
    j = InStrRev(tmp, "#")
    Str = Replace(Str, Mid(tmp, j + 1, InStr(1, tmp, "-") - j), "")
  Next i
  GPE = Mid(Str, 3, Len(Str) - 4)
End Function
 

File đính kèm

Sao bạn không hỏi thêm tổ hợp.
Nếu hoán vị 20 cái tên vào 10 vị vị trí khác nhau thì thành bài toán tổ hợp.
 
Cảm ơn anh @HieuCD và @excel_lv1.5 nhiều ạ. Đúng là chỉ có VBA mới giải quyết được mà em thì chưa thạo.
Theo như em nhớ hồi lớp 11 học thì đây gọi tổ hợp chập 10 của 20, tức là có tối đa 184756 cell kết quả có thể được tạo ra. :D
=> Do đó em muốn khi kéo ô B1 xuống bên dưới nhiều nhiều nữa thì sẽ xuất ra 1 loạt tổ hợp nhấc 10 phần tử ngẫu nhiên không lặp lại trong số 20 phần tử cho trước ở cột A ạ. Mong anh cho em xin giải pháp, em cảm ơn nhiều ạ!
Ảnh chụp Màn hình 2019-01-23 lúc 22.56.56.png
 
Vấn đề này có ít nhất là 3 cách giải quyết:
1. cách dễ nhất, và nếu là bài tập thì chính là cách mà Thầy/Cô đòi hỏi: đặt một hàm Rand() vào cột kế bên, sort, lấy ra 10 cái.
2. dùng công thức khủng: tôn chỉ của tôi là công thức khủng chỉ dùng để vận động đầu óc giải đố mẹo. Vì vậy toi khong tiếp thêm.
3. dùng hàm tự tạo. Thuật toán lấy k phần tử ngẫu nhiên trong n phần tử đã được giải nhiều lần ở diễn đàn này rồi.

Chú: thuật toán ở bài #3 giản dị nhưng nếu (n-k)/n là số rất nhỏ, tức là k gần bằng n thì khả năng chạm số càng lúc càng cao và theo lý thuyết, bài toán có thể chạy vòng đi vòng lại khá lâu. Yêu cầu bài này (n-k)/n = 0,5 là số tương đối chấp nhận.
 
Vấn đề này có ít nhất là 3 cách giải quyết:
1. cách dễ nhất, và nếu là bài tập thì chính là cách mà Thầy/Cô đòi hỏi: đặt một hàm Rand() vào cột kế bên, sort, lấy ra 10 cái.
2. dùng công thức khủng: tôn chỉ của tôi là công thức khủng chỉ dùng để vận động đầu óc giải đố mẹo. Vì vậy toi khong tiếp thêm.
3. dùng hàm tự tạo. Thuật toán lấy k phần tử ngẫu nhiên trong n phần tử đã được giải nhiều lần ở diễn đàn này rồi.

Chú: thuật toán ở bài #3 giản dị nhưng nếu (n-k)/n là số rất nhỏ, tức là k gần bằng n thì khả năng chạm số càng lúc càng cao và theo lý thuyết, bài toán có thể chạy vòng đi vòng lại khá lâu. Yêu cầu bài này (n-k)/n = 0,5 là số tương đối chấp nhận.
--------------------
Lỗi tại em chưa hỏi hết ý ngay từ đầu ạ, em muốn render ra 1 loạt kết quả theo cách kéo B1 xuống dưới thì có thể tạo thêm các tổ hợp mới. Nên em nhờ các anh chị giúp em phần công thức để chạy ạ
Cảm ơn anh @@HieuCD và @@excel_lv1.5 nhiều ạ. Đúng là chỉ có VBA mới giải quyết được mà em thì chưa thạo.
Theo như em nhớ hồi lớp 11 học thì đây gọi tổ hợp chập 10 của 20, tức là có tối đa 184756 cell kết quả có thể được tạo ra. :D
=> Do đó em muốn khi kéo ô B1 xuống bên dưới nhiều nhiều nữa thì sẽ xuất ra 1 loạt tổ hợp nhấc 10 phần tử ngẫu nhiên không lặp lại trong số 20 phần tử cho trước ở cột A ạ. Mong anh cho em xin giải pháp, em cảm ơn nhiều ạ!
Ảnh chụp Màn hình 2019-01-23 lúc 22.56.56.png
 
Tôi đã nói là thuật toán tạo tổ hợp đã từng được bàn cặn kẽ ở diễn đàn này. Chịu khó tìm.
Số lớn thì khó chứ 30 phần tử trở xuống thì tương đối dễ.
 
Tôi đã nói là thuật toán tạo tổ hợp đã từng được bàn cặn kẽ ở diễn đàn này. Chịu khó tìm.
Số lớn thì khó chứ 30 phần tử trở xuống thì tương đối dễ.
thực ra là em muốn nhờ mọi người cho xin 1 công thức/code để sau nhập nhiều phần tử cho trước hơn, có thể tới 50 phần tử cung cấp sẵn và nhấc ra 10 phần tử ạ
 
Cảm ơn anh @HieuCD và @excel_lv1.5 nhiều ạ. Đúng là chỉ có VBA mới giải quyết được mà em thì chưa thạo.
Theo như em nhớ hồi lớp 11 học thì đây gọi tổ hợp chập 10 của 20, tức là có tối đa 184756 cell kết quả có thể được tạo ra. :D
=> Do đó em muốn khi kéo ô B1 xuống bên dưới nhiều nhiều nữa thì sẽ xuất ra 1 loạt tổ hợp nhấc 10 phần tử ngẫu nhiên không lặp lại trong số 20 phần tử cho trước ở cột A ạ. Mong anh cho em xin giải pháp, em cảm ơn nhiều ạ!
View attachment 211533
Thử code này, show tối đa số dòng của excel trong một cột thôi, thay đổi ô B1 để thay đổi số tổ hợp!
Mã:
Sub combin()
Dim i As Long, j As Long, n As Long, m As Long, arr, darr, result, str As String
If [g1] <> "" Then Range("G1").CurrentRegion.Clear
arr = Range("A1:A" & [A100000].End(xlUp).Row):                m = UBound(arr):            n = [b1]
ReDim darr(1 To WorksheetFunction.combin(UBound(arr), n), 1 To n + 2)
For i = 1 To UBound(darr, 2) - 2
    darr(1, i + 1) = i
Next i
For i = 2 To UBound(darr)
    For j = 2 To UBound(darr, 2) - 1
        darr(i, j) = IIf(darr(i - 1, j) = m + j - n - 1, CDbl(darr(i, j - 1)) + 1, _
                     IIf(darr(i - 1, j + 1) = m + j - n Or CDbl(darr(i - 1, j + 1)) = 0, darr(i - 1, j) + 1, darr(i - 1, j)))
    Next j
Next i
ReDim result(1 To UBound(darr), 1 To 1)
For i = 1 To UBound(darr)
    str = ""
    For j = 2 To UBound(darr, 2) - 1
        str = str & IIf(str = "", "", " - ") & arr(darr(i, j), 1): result(i, 1) = str
    Next j
Next i
[g1].Resize(UBound(result), 1) = result
End Sub
 

File đính kèm

Thử code này, show tối đa số dòng của excel trong một cột thôi, thay đổi ô B1 để thay đổi số tổ hợp!
Mã:
Sub combin()
Dim i As Long, j As Long, n As Long, m As Long, arr, darr, result, str As String
If [g1] <> "" Then Range("G1").CurrentRegion.Clear
arr = Range("A1:A" & [A100000].End(xlUp).Row):                m = UBound(arr):            n = [b1]
ReDim darr(1 To WorksheetFunction.combin(UBound(arr), n), 1 To n + 2)
For i = 1 To UBound(darr, 2) - 2
    darr(1, i + 1) = i
Next i
For i = 2 To UBound(darr)
    For j = 2 To UBound(darr, 2) - 1
        darr(i, j) = IIf(darr(i - 1, j) = m + j - n - 1, CDbl(darr(i, j - 1)) + 1, _
                     IIf(darr(i - 1, j + 1) = m + j - n Or CDbl(darr(i - 1, j + 1)) = 0, darr(i - 1, j) + 1, darr(i - 1, j)))
    Next j
Next i
ReDim result(1 To UBound(darr), 1 To 1)
For i = 1 To UBound(darr)
    str = ""
    For j = 2 To UBound(darr, 2) - 1
        str = str & IIf(str = "", "", " - ") & arr(darr(i, j), 1): result(i, 1) = str
    Next j
Next i
[g1].Resize(UBound(result), 1) = result
End Sub
Cái này là Chỉnh hợp có trật tự. Bạn ấy muốn ngẫu nhiên. Hình như bạn ấy còn muốn đánh vào Cell rồi Fill xuống
Code của bạn có thể để kiểm tra kết quả sau khi lấy
 
Cái này là Chỉnh hợp có trật tự. Bạn ấy muốn ngẫu nhiên. Hình như bạn ấy còn muốn đánh vào Cell rồi Fill xuống
Code của bạn có thể để kiểm tra kết quả sau khi lấy
Đã nói tổ hợp thì trật tự hay ngẫu nhiên cũng như nhau cả, nếu ngẫu nhiên thì chỉnh code lại tý là được nhưng code sẽ chậm hơn.
Mã:
Sub combin()
Dim i As Long, j As Long, n As Long, m As Long, arr, darr, result, str As String, dic As Object, num As Long
Set dic = CreateObject("scripting.dictionary")
If [g1] <> "" Then Range("G1").CurrentRegion.Clear
arr = Range("A1:A" & [A100000].End(xlUp).Row):                m = UBound(arr):            n = [b1]
ReDim darr(1 To WorksheetFunction.combin(UBound(arr), n), 1 To n + 2)
For i = 1 To UBound(darr, 2) - 2
    darr(1, i + 1) = i
Next i
For i = 2 To UBound(darr)
    For j = 2 To UBound(darr, 2) - 1
        darr(i, j) = IIf(darr(i - 1, j) = m + j - n - 1, CDbl(darr(i, j - 1)) + 1, _
                     IIf(darr(i - 1, j + 1) = m + j - n Or CDbl(darr(i - 1, j + 1)) = 0, darr(i - 1, j) + 1, darr(i - 1, j)))
    Next j
Next i
ReDim result(1 To UBound(darr), 1 To 1)
Randomize
For i = 1 To UBound(darr)
    str = ""
    Do While dic.Count < n
    num = Int(Rnd() * n) + 1
        If Not dic.exists(num) Then dic.Add num, arr(darr(i, num + 1), 1)
    Loop
    str = Join(dic.items(), " - "): result(i, 1) = str: dic.RemoveAll
Next i
[g1].Resize(UBound(result), 1) = result
End Sub
 

File đính kèm

Đã nói tổ hợp thì trật tự hay ngẫu nhiên cũng như nhau cả, nếu ngẫu nhiên thì chỉnh code lại tý là được nhưng code sẽ chậm hơn.
Mã:
Sub combin()
Dim i As Long, j As Long, n As Long, m As Long, arr, darr, result, str As String, dic As Object, num As Long
Set dic = CreateObject("scripting.dictionary")
If [g1] <> "" Then Range("G1").CurrentRegion.Clear
arr = Range("A1:A" & [A100000].End(xlUp).Row):                m = UBound(arr):            n = [b1]
ReDim darr(1 To WorksheetFunction.combin(UBound(arr), n), 1 To n + 2)
For i = 1 To UBound(darr, 2) - 2
    darr(1, i + 1) = i
Next i
For i = 2 To UBound(darr)
    For j = 2 To UBound(darr, 2) - 1
        darr(i, j) = IIf(darr(i - 1, j) = m + j - n - 1, CDbl(darr(i, j - 1)) + 1, _
                     IIf(darr(i - 1, j + 1) = m + j - n Or CDbl(darr(i - 1, j + 1)) = 0, darr(i - 1, j) + 1, darr(i - 1, j)))
    Next j
Next i
ReDim result(1 To UBound(darr), 1 To 1)
Randomize
For i = 1 To UBound(darr)
    str = ""
    Do While dic.Count < n
    num = Int(Rnd() * n) + 1
        If Not dic.exists(num) Then dic.Add num, arr(darr(i, num + 1), 1)
    Loop
    str = Join(dic.items(), " - "): result(i, 1) = str: dic.RemoveAll
Next i
[g1].Resize(UBound(result), 1) = result
End Sub
Sao đã có đoạn "WorksheetFunction.combin(UBound(arr), n)" biết được số Tập hợp rồi sao lại viết thêm vòng lặp để Randomize vậy
Cần có giải thuật khác. Giả sử không có số Tập hợp thì làm sao?
Đoạn code của bạn là liệt kê toàn bộ tập hợp sau đó chọn ngâu nhiên.
Nếu cho i Chạy hết Data-Type Double rồi quay lại tìm 10 số ngẫu nhiên. Vậy 10 tập ở cuối tập hợp sẽ lấy thế nào, khi nào mới lấy được?
 
Lần chỉnh sửa cuối:
Sao đã có đoạn "WorksheetFunction.combin(UBound(arr), n)" biết được số Tập hợp rồi sao lại viết thêm vòng lặp để Randomize vậy
Cần có giải thuật khác. Giả sử không có số Tập hợp thì làm sao?
Đoạn code của bạn là liệt kê toàn bộ tập hợp sau đó chọn ngâu nhiên.
Nếu cho i Chạy hết Data-Type Double rồi quay lại tìm 10 số ngẫu nhiên. Vậy 10 tập ở cuối tập hợp sẽ lấy thế nào, khi nào mới lấy được?
Randomize là ngẫu nhiên của số phần tử trong chuỗi, chứ tập số không đổi và luôn xác định vì combin(,) là tính chính xác số phần tử của tập rồi, muốn không show hết thì cho thêm const để xác định số phần tử cần show.
Đã có tập rồi thì chuyện lấy ngẫu nhiên chẳng phải quá đơn giản sao, bài #3 tôi viết lấy ngẫu nhiên từ một tập đó thôi.
Bạn thử đưa ra giải thuật khác xem, chứ tôi thấy cách này cũng không nhanh.
 
Lần chỉnh sửa cuối:
Đã nói tổ hợp thì trật tự hay ngẫu nhiên cũng như nhau cả, nếu ngẫu nhiên thì chỉnh code lại tý là được nhưng code sẽ chậm hơn.
Mã:
Sub combin()
Dim i As Long, j As Long, n As Long, m As Long, arr, darr, result, str As String, dic As Object, num As Long
Set dic = CreateObject("scripting.dictionary")
If [g1] <> "" Then Range("G1").CurrentRegion.Clear
arr = Range("A1:A" & [A100000].End(xlUp).Row):                m = UBound(arr):            n = [b1]
ReDim darr(1 To WorksheetFunction.combin(UBound(arr), n), 1 To n + 2)
For i = 1 To UBound(darr, 2) - 2
    darr(1, i + 1) = i
Next i
For i = 2 To UBound(darr)
    For j = 2 To UBound(darr, 2) - 1
        darr(i, j) = IIf(darr(i - 1, j) = m + j - n - 1, CDbl(darr(i, j - 1)) + 1, _
                     IIf(darr(i - 1, j + 1) = m + j - n Or CDbl(darr(i - 1, j + 1)) = 0, darr(i - 1, j) + 1, darr(i - 1, j)))
    Next j
Next i
ReDim result(1 To UBound(darr), 1 To 1)
Randomize
For i = 1 To UBound(darr)
    str = ""
    Do While dic.Count < n
    num = Int(Rnd() * n) + 1
        If Not dic.exists(num) Then dic.Add num, arr(darr(i, num + 1), 1)
    Loop
    str = Join(dic.items(), " - "): result(i, 1) = str: dic.RemoveAll
Next i
[g1].Resize(UBound(result), 1) = result
End Sub
------------------------------------------------------------------
Cảm ơn anh @excel_lv1.5 nhiều ạ! bác nhiệt tình quá tận hơn 1h sáng vẫn làm giúp em. Phân bố phần tử số lần xuất hiện bằng nhau quá chuẩn rồi!
Anh có thể giúp em đẩy kết quả thành 10 phần tử 1 tổ hợp được không ạ, tại vì ở file của anh đây em thấy xuất kết quả ra 1 tổ hợp mới có 8 phần tử. Thanks anh!
Capture.JPG
 
thực ra là em muốn nhờ mọi người cho xin 1 công thức/code để sau nhập nhiều phần tử cho trước hơn, có thể tới 50 phần tử cung cấp sẵn và nhấc ra 10 phần tử ạ
thực ra là em muốn nhờ mọi người cho xin 1 công thức/code để sau nhập nhiều phần tử cho trước hơn, có thể tới 50 phần tử cung cấp sẵn và nhấc ra 10 phần tử ạ
Thử code
Mã:
Sub Combin_Main()
  Dim sArr(), Res() As String, iRnd() As Long, Res2() As String
  Dim K As Long, S As Long, sRow As Long, N As Long, i As Long
 
  Range("E1", Range("E1000010").End(xlUp)).ClearContents
  Range("C4").ClearContents
  sArr = Range("A1:A" & Range("A1000000").End(xlUp).Row).Value
  N = UBound(sArr)
  K = Range("C1").Value:   S = Range("C2").Value
  If S <= 0 Or K <= 0 Then MsgBox ("Phai nhap so vào 2 ô C1 và C2"): Exit Sub
  If K > N Then MsgBox ("Giá tri K phai nho hon so dòng du lieu"): Exit Sub
 
  sRow = WorksheetFunction.Combin(N, K)
  Range("C4") = sRow
  If sRow > 1000000 Then sRow = 1000000
  If S > sRow Then S = sRow
 
  iRnd = UniqueRand(sRow, S)
  Call Combin(Res, sArr, K, iRnd(S))
 
  ReDim Res2(1 To S, 1 To 1)
  For i = 1 To S
    Res2(i, 1) = Res(iRnd(i), 1)
  Next i
  Range("E1").Resize(S) = Res2
  Erase Res
End Sub

Private Function UniqueRand(ByVal N As Long, ByVal K As Long) As Variant
  Dim sArr() As Long, blArr() As Boolean, Res() As Long, i As Long, RndNum As Long
 
  ReDim sArr(1 To N)
  For i = 1 To N
    sArr(i) = i
  Next i
  ReDim blArr(1 To N):  ReDim Res(1 To K)
  For i = 1 To K
    RndNum = Int(N * Rnd() + 1)
    blArr(sArr(RndNum)) = True
    sArr(RndNum) = sArr(N)
    N = N - 1
  Next i
  K = 0: N = UBound(sArr)
  For i = 1 To N
    If blArr(i) = True Then
      K = K + 1:      Res(K) = i
    End If
  Next i
  UniqueRand = Res
End Function

Private Sub Combin(ByRef Res, ByVal sArr, ByVal K As Long, ByVal sRow As Long)
  Dim iD() As Long, tmp() As String
  Dim N As Long, i As Long, j As Long, q As Long
 
  N = UBound(sArr):   K = Range("C1").Value
  ReDim Res(1 To sRow, 1 To 1)
  ReDim iD(1 To K): ReDim tmp(1 To K)
  For j = 1 To K
    iD(j) = j: tmp(j) = sArr(j, 1)
  Next j
  Res(1, 1) = Join(tmp, " - ")
  For i = 2 To sRow
    For j = 1 To K - 1
      If iD(j + 1) = N - K + j + 1 Then
        iD(j) = iD(j) + 1
        tmp(j) = sArr(iD(j), 1)
        For q = j + 1 To K
          iD(q) = iD(q - 1) + 1
          tmp(q) = sArr(iD(q), 1)
        Next q
        Exit For
      ElseIf j = K - 1 Then
        iD(K) = iD(K) + 1
        tmp(K) = sArr(iD(K), 1)
      End If
    Next j
    Res(i, 1) = Join(tmp, " - ")
  Next i
End Sub
 

File đính kèm

Thử code
Mã:
Sub Combin_Main()
  Dim sArr(), Res() As String, iRnd() As Long, Res2() As String
  Dim K As Long, S As Long, sRow As Long, N As Long, i As Long

  Range("E1", Range("E1000010").End(xlUp)).ClearContents
  Range("C4").ClearContents
  sArr = Range("A1:A" & Range("A1000000").End(xlUp).Row).Value
  N = UBound(sArr)
  K = Range("C1").Value:   S = Range("C2").Value
  If S <= 0 Or K <= 0 Then MsgBox ("Phai nhap so vào 2 ô C1 và C2"): Exit Sub
  If K > N Then MsgBox ("Giá tri K phai nho hon so dòng du lieu"): Exit Sub

  sRow = WorksheetFunction.Combin(N, K)
  Range("C4") = sRow
  If sRow > 1000000 Then sRow = 1000000
  If S > sRow Then S = sRow

  iRnd = UniqueRand(sRow, S)
  Call Combin(Res, sArr, K, iRnd(S))

  ReDim Res2(1 To S, 1 To 1)
  For i = 1 To S
    Res2(i, 1) = Res(iRnd(i), 1)
  Next i
  Range("E1").Resize(S) = Res2
  Erase Res
End Sub

Private Function UniqueRand(ByVal N As Long, ByVal K As Long) As Variant
  Dim sArr() As Long, blArr() As Boolean, Res() As Long, i As Long, RndNum As Long

  ReDim sArr(1 To N)
  For i = 1 To N
    sArr(i) = i
  Next i
  ReDim blArr(1 To N):  ReDim Res(1 To K)
  For i = 1 To K
    RndNum = Int(N * Rnd() + 1)
    blArr(sArr(RndNum)) = True
    sArr(RndNum) = sArr(N)
    N = N - 1
  Next i
  K = 0: N = UBound(sArr)
  For i = 1 To N
    If blArr(i) = True Then
      K = K + 1:      Res(K) = i
    End If
  Next i
  UniqueRand = Res
End Function

Private Sub Combin(ByRef Res, ByVal sArr, ByVal K As Long, ByVal sRow As Long)
  Dim iD() As Long, tmp() As String
  Dim N As Long, i As Long, j As Long, q As Long

  N = UBound(sArr):   K = Range("C1").Value
  ReDim Res(1 To sRow, 1 To 1)
  ReDim iD(1 To K): ReDim tmp(1 To K)
  For j = 1 To K
    iD(j) = j: tmp(j) = sArr(j, 1)
  Next j
  Res(1, 1) = Join(tmp, " - ")
  For i = 2 To sRow
    For j = 1 To K - 1
      If iD(j + 1) = N - K + j + 1 Then
        iD(j) = iD(j) + 1
        tmp(j) = sArr(iD(j), 1)
        For q = j + 1 To K
          iD(q) = iD(q - 1) + 1
          tmp(q) = sArr(iD(q), 1)
        Next q
        Exit For
      ElseIf j = K - 1 Then
        iD(K) = iD(K) + 1
        tmp(K) = sArr(iD(K), 1)
      End If
    Next j
    Res(i, 1) = Join(tmp, " - ")
  Next i
End Sub
Ngẫu nhiên sao mà A1 xếp đều vậy anh.
Ví dụ muốn biết Chỉnh hợp 50 chập 10 trong hoán vị P50 tại vị trí P50 - 200 được sắp xếp thế nào thì sao
(50 học sinh xếp vào 10 vị trí bất kí sau đó lấy ra vị trí thứ 18000 xem sắp xếp thế nào. Chắc dùng vòng lặp chạy đến 18000)
Không biết có được không
 
Lần chỉnh sửa cuối:
Chào các anh chị. Cho em hỏi bài toán như sau
Cho 1 danh sách gồm 20 cái tên khác nhau, yêu cầu nhấc ra 1 tổ hợp gồm 10 tên ngẫu nhiên trong danh sách 20 tên đó, sao cho không có cái tên nào trong cùng 1 tổ hợp bị trùng nhau. Kết quả nằm trong 1 cell và các tên ngăn nhau bằng dấu trừ.
Nhờ anh chị cho em xin công thức ạ. Em xin cảm ơn nhiều!
Có lẽn bạn cần phân biệt rõ là tổ hợp hay không.
Vi dụ : Nhóm 1,2,3,4,5,6,7,8,9,10 và 10,9,8,7,6,5,4,3,2,1 theo yêu cầu của bạn là 2 nhóm khác nhau hay là không
 
Có lẽn bạn cần phân biệt rõ là tổ hợp hay không.
Vi dụ : Nhóm 1,2,3,4,5,6,7,8,9,10 và 10,9,8,7,6,5,4,3,2,1 theo yêu cầu của bạn là 2 nhóm khác nhau hay là không
Em ghi là tổ hợp thì không phân biệt thứ tự miễn là có đủ các phần tử như vậy. Còn nếu ghi theo cách của anh thì gọi là chỉnh hợp, số lượng phần tử sẽ lớn hơn rất nhiều.
 
Em ghi là tổ hợp thì không phân biệt thứ tự miễn là có đủ các phần tử như vậy. Còn nếu ghi theo cách của anh thì gọi là chỉnh hợp, số lượng phần tử sẽ lớn hơn rất nhiều.
Vì thấy mấy bài nói tới chỉnh hợp & hoán vị nen hỏi cho chắc vậy.
 
Ngẫu nhiên sao mà A1 xếp đều vậy anh.
Ví dụ muốn biết Chỉnh hợp 50 chập 10 trong hoán vị P50 tại vị trí P50 - 200 được sắp xếp thế nào thì sao
(50 học sinh xếp vào 10 vị trí bất kí sau đó lấy ra vị trí thứ 18000 xem sắp xếp thế nào. Chắc dùng vòng lặp chạy đến 18000)
Không biết có được không
Code mình đã có thêm 2 đoạn lệnh xếp thứ tự cho dể nhìn, không xếp thứ tự thì bỏ các lệnh nầy cho ra vẽ ngẫu nhiên
Vị trí thứ 18000 chỉ là tương đối, tùy theo cách xếp thứ tự như thế nào, bài toán ngẫu nhiên nên thứ tự bao nhiêu không quan trọng
Nếu xếp thứ tự theo qui luật như trong file của mình, lấy vị trí nào đó như thứ tự 18000 thì bạn tự viết code được
Nếu muốn code chạy nhanh cần phân tích tình huống để chọn cách xử lý, chủ yếu dựa vào tương quan số khả năng và số dòng cần lấy
 
Lần chỉnh sửa cuối:
Theo đề trong bài #22 của bạn HieuCD, ( lấy 10 phần tử bất kỳ, không trùng trong 20 phần tử cho trước, số dòng lấy....tùy hỷ) tui đố hội người cao tuổi viết được code với số vòng lặp ngắn nhất có thể, ai viết được đầu năm tui thưởng.......(bí mật)
CHÚC MỪNG NĂM MỚI.........SỚM
 

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

Back
Top Bottom