Tạo dãy số ngẫu nhiên không trùng
Trên diển đàn GPE đã có rất nhiều bài viết nói về vấn đề này!
Tôi cũng đã tham khảo rất nhiều code ở các trang nước ngoài nhưng thấy rằng hầu hết đều viết rất khó hiểu và dài dòng!
Trong 1 dịp tình cờ khi nghiên cứu về Dictionary Object, tôi nhận thấy rằng nó có khả năng làm được điều này mà code lại cực kỳ đơn giản
Thuật toán dựa vào định nghĩa của Dictionary có đoạn: Key là những phần tử duy nhất trong Keys
Tôi đã xây dựng code như sau:
Function UniqueRandomNum(Bottom As Long, Top As Long, Amount As Long)
'Application.Volatile '<— Neu muon gia tri thay doi khi bam F9
On Error Resume Next
If Amount > Top – Bottom + 1 Then Amount = Top – Bottom + 1
With CreateObject("Scripting.Dictionary")
Do
.Add Int(Rnd() * (Top – Bottom + 1)) + Bottom, ""
Loop Until .Count = Amount
UniqueRandomNum = WorksheetFunction.Transpose(.Keys)
End With
End Function
Cú pháp hàm:
=UniqueRandomNum(Số nhỏ, Số lớn, bao nhiêu số cần tạo)
Giả sử các bạn muốn tạo ra 30 số ngẩu nhiên không trùng nằm trong khoảng từ 1 đến 100, các bạn làm như sau:
– Quét chọn 30 cell tùy ý theo chiều dọc, chẳng hạn là A1:A30
– Gõ vào thanh Formula công thức =UniqueRandomNum(1,100,30)
– Bấm tổ hợp phím Ctrl + Shift + Enter
Hãy thí nghiệm với đoạn Test sau:
Sub Test()
Range("A1:A30").Value = UniqueRandomNum(1, 100, 30)
End Sub
————–
Ghi chú: Dictionary Object còn làm được nhiều thứ khác nữa, chẳng hạn có thể xây dựng hàm trích lọc các phần tử duy nhất (ngẫu nhiên và duy nhất đã làm được, đương nhiên duy nhất sẽ càng dể hơn)
www.giaiphapexcel.com/diendan/threads/t%E1%BA%A1o-d%C3%A3y-s%E1%BB%91-ng%E1%BA%ABu-nhi%C3%AAn-kh%C3%B4ng-tr%C3%B9ng.27286/
Khoá học Trưởng phòng nhân sự
Nguồn nhân lực là một trong Tứ trụ kinh doanh của doanh nghiệp, có tác động tới sự tồn tại và phát triển bền...
Xem khóa học
Tôi xin giả lập 1 file, dùng ứng dụng trên để tạo phòng thi
– Có 146 sinh viên
– Tạo 5 phòng thì, mỗi phòng 30 sinh viên được lấy ngẫu nhiên từ dử liệu gốc
Xem file
– Bạn mở file tác giả lên, bấm Alt + F11 vào xem người ta viết code gì trong đó
– Copy toàn bộ code
– Mở file của bạn lên, cũng bấm Alt + F11 rồi paste code đã copy vào (y chang file gốc)
Lưu ý: Code này đặt trong 1 Module, vậy bạn cũng phải vào menu InsertModule (để có 1 Module như người ta) rồi hẳn paste code vào
Hãy dùng code của bạn tạo ra 60000 số ngẫu nhiên trên bảng tính, từ 1 đến 100000 —> Làm xong xem thử tốc độ code của bạn là bao nhiêu giây rồi hẳn bàn tiếp nhé
(Tốc độ chạy code của "người ta" là < 1 giây đấy —> Còn của bạn = ? )
1> Không phải là CHẬM HƠN mà gọi là QUÁ QUÁ.. CHẬM mới đúng —-> Trong 1 chương trình hoàn chỉnh thường có nhiều module, và trong từng module người ta hơn thua nhau từng ms một (chứ tốc độ rùa thế thì.. không ăn thua)
2> Dictionary Object là món chuyên về Unique rồi —> Thiết nghĩ chẳng cần phải "cải biên" thêm làm gì —-> Chẳng ai lại đi bỏ cái "sở trường" mà đi dùng cái "sở đoản" cho mất công
3> Cái vụ On Error Resume Next chẳng qua là "người ta" quá hiểu lỗi có thể xuất hiện ở đây là gì rồi —> Nếu viết cho rõ thì vầy:
Function UniqueRandomNum(Bottom As Long, Top As Long, Amount As Long)
Dim Tmp as Long
'Application.Volatile '<— Neu muon gia tri thay doi khi bam F9
If Amount > Top – Bottom + 1 Then Amount = Top – Bottom + 1
With CreateObject("Scripting.Dictionary")
Do
Tmp = Int(Rnd() * (Top – Bottom + 1)) + Bottom
If Not .Exists(Tmp) then .Add Tmp, ""
Loop Until .Count = Amount
UniqueRandomNum = WorksheetFunction.Transpose(.Keys)
End With
End Function
4> Xét về mặt "dễ hiểu" thì cũng không chắc code của bạn đã dễ hiểu hơn đâu (thuật toán dạng này đã từng có trên diễn đàn rồi)
—————————–
Bạn còn ý kiến gì khác hơn không? Tôi rất mong có thể học hỏi thêm những điều mới lạ (mà tôi chưa biết) từ bạn
Collection gần giống với Dictionary, nó được cái khỏi cần dùng CreateObject gì đó… nhưng nó cũng có cái dở, đó là:
– Không có Exists method để xác định sự tồn tại, cuối cùng thì bạn vẫn phải On Error Resume Next đấy thôi —> rõ ràng bạn hiểu rất rõ lỗi có thể xãy ra nên mới dùng On Error… đúng không? —> Vậy cũng có khác gì bài số #1?
– Gọi là Collection cũng đúng, nó chỉ làm nhiệm vụ "thu gom" vào 1 đóng lộn xộn (chẳng phải mảng) nên cuối cùng lại phải tốn thêm 1 vòng lập để duyệt qua các phần tử (Dictionary có Keys và Items đã là mảng rồi, cứ thế mà xài, khỏi thêm vòng lập)
—————————————————-
Phân tích để thấy được hết sự ưu việt của Dictionary trong bài toán này —> Tin chắc rằng dùng cách khác không thể tối ưu hơn được (chứ không phải nói là không thể dùng cách khác)
Đã biết cách dùng Dictionary rồi thì Collection là tương tự… Có điều nó chỉ có thế này:
1141
"4 món ăn chơi" này xài y chang như Dictionary object thôi ThuNghi à
Còn "before, after" gì gì đó, mình chưa hiểu lắm
Ah… tôi hiểu cái vụ After, before rồi
Nó giống như Add sheet ấy
Nói nhiều không bằng ví dụ
Sub Test()
Dim i As Long, Col As New Collection
Col.Add "A", "1"
For i = 2 To 10
Col.Add Chr(64 + i), CStr(i), 1
Next
For i = 1 To 10
MsgBox Col.Item(i)
Next
End Sub
Hy vọng bạn hiểu
Ẹc… Ẹc…
Nếu bạn thích Collection như thế thì "tặng" bạn hàm tôi tự viết
Function UniqueRandomNum(Bottom As Long, Top As Long, Amount As Long)
Dim Arr(), i As Long, Tmp As Long, iCount As Long
On Error Resume Next
If Amount > Top – Bottom + 1 Then Amount = Top – Bottom + 1
ReDim Arr(1 To Amount, 1 To 1)
With New Collection
Do
iCount = .Count
Tmp = Int(Rnd() * (Top – Bottom + 1)) + Bottom
.Add Tmp, CStr(Tmp)
If iCount <> .Count Then
i = i + 1
Arr(i, 1) = Tmp
End If
Loop Until .Count = Amount
UniqueRandomNum = Arr
End With
End Function
Sub Test()
Dim TG As Double
TG = Timer
Range("A1:A60000").Value = UniqueRandomNum(1, 100000, 60000)
MsgBox Timer – TG
End Sub
Thuật toán như trên chắc bạn thừa hiểu: Hể Add được thằng nào thì quăng luôn thằng đó vào mảng (chẳng viêc gì phải thêm vòng lập nữa cho lòng vòng)
Hàm này tuy cũng chẳng hay ho gì nhưng được cái là:
– Chỉ dùng 1 vòng lập
– Tốc độ nhanh ít nhất gấp 100 lần code của bạn
– Code của tôi chạy 20000 dòng trong 0.2 giây, của bạn 51 giây
– Code của tôi chạy 60000 dòng trong 0.5 giây, của bạn thì… Ẹc… Ẹc… chẳng biết bao lâu mới xong, vì tôi chờ 5 phút và.. mất kiên nhân quá nên Ctrl + Break cho rồi (nếu không thì phải đi uống cafe để chờ)
—————————-
Kết luận cuối cùng: Đã tối ưu hết mức. bằng cách dùng mảng, có thể tăng tốc độ code lên đến mức cực khủng… Nhưng dù sao vẫn phải dùng tí "mẹo" —> khả năng uyển chuyển không thể như Dictionary được
Thật ra tôi biết Collection đã lâu nhưng từ khi biết được Dictionary thì tôi không còn thích dùng Collection nữa, vì nói chung là tôi chẳng thấy nó có gì hay cả (nếu không nói là… quá tệ)
Mời xem file nha
Thì bạn cứ tạo số bình thường, sau khi xong việc, bạn quét chọn vùng dữ liệu, vào menu FormatCells … Trong tab Number, bạn chọn Custom rồi gõ vào khung Type ở bên phải 4 số 0 (0000) —> Vậy là xong!
Hình như đây là bài toán tìm kiếm và lọc… không thuộc chủ đề tạo số ngẫu nhiên thì phải
Cũng dễ thôi —> Lấy 50 số ngãu nhiên trong khoảng từ 10910 đến 11020, xong chia kết quả cho 100
Tức =UniqueRandomNum(10910,11020,50)/100
Do sơ sót thôi!
Sửa hàm UniqueRandomNum thành vầy:
Thêm thằng em [Randomize vào nữa, bảo đảm các lần chạy sẽ không bao giờ giống nhau
Sẵn góp ý trong thớt này. Tôi có một vài điều nói thêm cho hàm này. Lưu ý trước là tôi không hề nhận xét vấn đề thuật toán nhanh chậm hay tốt xấu, xin đừng hiểu lầm sinh ra tranh cãi vô ích. Mục đích tôi là bổ sung phần phạm vi (giới hạn) và phương pháp sử dụng.
1. Thứ nhất, hàm này dùng kỹ thuật lặp lại nếu bị trùng số. Vì vậy, nếu khoảng tính lớn (cỡ 100000) và số lượng cần lấy ra rất gần với khoảng tính (cỡ 99000) thì càng về sau số trùng càng gặp nhiều, tốc đọ sẽ bị giảm. Trong trường hợp thật tệ, có thể hàm chạy hoài không dứt.
Như vậy, cần lưu ý khi dùng hàm này rằng số cần lấy không được gần sát với khảng tính. Lưu ý lần nữa: toi không nói hàm sai, không dùng được. Ở đây chỉ bàn phạm vi sử dụng thôi.
2. Thứ hai, Hàm nguyên thuỷ được viết theo kiểu số ngẫu nhiên giả tạo. Tức là mỗi lần chạy thì cho ra loạt sô in hệt nhau. Ở khoảng bài #37, tác giả có thêm lệnh ramdomize vào hàm để dùng trong trường hợp ngẫu nhiên thật (mỗi lần chạy cho ra loạt số khác nhau)
Bình thường, ta có thể dùng lệnh chỉ dẫn trình dịch (compiler dirrectives) để làm việc này. Điển hình là lệnh #If
Ở đầu module chứa hàm, đặt code này
#Const NGAUNHIENTHAT = True
' sửa thành False khi cần chạy code random giả
Bên trong hàm, đặt lệnh này ở dòng đầu tiên
#If NGAUNHIENTHAT Then
Randomize
#End If
(random giả có nghĩa là một loạt số ngẫu nhiên được tạo sẵn trong máy. Mỗi lượt chạy, loạt số này được lôi ra dùng, cho nên chúng in hệt nhau. Đôi khi vì lý do thí nghiệm thống kê người ta phải dùng random giả)
3. Thứ ba, hàm này để yên như vậy thì gọn và đơn giản. Nhưng nếu thêm mọt chút thì cách sử dụng có thể đơn giản hơn.
Sửa dòng cuối của hàm UniqueRandomNum, cho nó trả về nguyên mảng/collection .keys
(sau khi sửa, hàm này không còn gọi Application.Transpose, và không phải lệ thuộc vào Excel nữa, và có thể dùng cho Word, Access)
Thêm vào cùng module một hàm UnqRnd(Bottom, Top)
Bên trong hàm này, đặt code giám sát vùng được chọn và gọi hàm UniqueRndomNum
Nếu vùng được chọn là dọc thì trả lại:
Application.Transpose(UniqueRandomNum(bottom, top, amount))
Nếu vùng được chọn là ngang thì trả lại:
Application.Transpose(Application.Transpose(UniqueRandomNum(bottom, top, amount)))
Đại khái:
Public Function UnqRnd(Bottom As Long, Top As Long)
UnqRnd = UniqueRandomNum(Bottom, Top, Application.Caller.Cells.Count)
if Application.Caller.Rows.Count > 1 Then UnqRnd = Application.Transpose(UnqRnd)
End Function
Sử dụng hàm này chỉ cần bôi đen vùng chọn, gõ công thức với chận dưới, chận trên và Ctrl+Shift+Enter. Hàm sẽ tự động tính số dữ liệu cần lấy. Hàm cũng tự động biết trải ngang hay dọc tuỳ theo vùng chọn.
@haonlh: đúng rồi, ở bai #63, tôi gõ nhầm Variant (mọt từ khoá của VBA) thành Variance (một đối tượng trong toán thống kê)
B1: Khai báo 1 biến kiểu chuỗi;
B2: Thiết lập vòng lặp nhét tất các số vô biến chuỗi
B2.1: Xáo trộn tùy í trong chuỗi bằng vòng lặp;
B3: Cắt khúc theo í bạn
Option Explicit
Sub Tao3NhomNgau()
Dim Num As Integer, J As Long
Dim StrC As String
1 'Tao Chuoi:'
For J = 1 To 10
If J Mod 2 = 1 Then
StrC = StrC & Right("0" & CStr(J), 2)
Else
StrC = Right("0" & CStr(J), 2) & StrC
End If
Next J
2 'Tron Chuoi:'
Randomize
For J = 1 To 999
Num = 2 * (1 + 3 * Rnd 1)
StrC = Mid(StrC, Num + 1, 20) & Left(StrC, Num)
Next J
3 'Cát Chuoi:'
MsgBox Left(StrC, 4) & "; " & Mid(StrC, 5, 6) & "; " & Mid(StrC, 11, 4)
End Sub
thử bấm nút trong file đính kèm , theo tôi thì nên ghi kết quả ra sheet khác , vì mỗi người bạn đâu biết trước có mấy tem đâu mà chừa dòng , nếu bạn vẫn muốn ghi kết quả luôn vào sheet "SO TEM" thì báo lại nhé
cứ từ rồi cũng xong chứ làm gì nhắn tin gửi thư ghê vậy ?
Bạn kiểm tra file này
file minh họa bạn gửi lên ngoài việc có thêm 2 sheet ra thì không chú thích gì thêm thì sao tôi hiểu được , mấy con số trong các sheet kiểm tra tem phải thỏa mãn điều kiện gì ? và thật ra file có bao nhiêu sheet ? để làm luôn 1 lần , chứ chơi kiểu mỗi ngày đẻ ra thêm 2 sheet mới là tôi nghỉ luôn đó .
giải pháp thì có , nhưng hôm qua tôi đã nhắc nhở 1 lần , cứ từ từ thì cái gì cũng xong , thế mà hôm nay vẫn tiếp tục tái diễn trò spam hối nhau , đã vậy tôi cho chủ đề này trôi luôn . Từ bây giờ đến thứ 2 tuần sau , nếu không ai làm giúp bạn thì tôi mới up file lên nhé , để bạn biết spam hối thúc tôi thì sẽ thế nào .
làm thử bạn kiểm tra lại, để tiện cho bạn kiểm tra mình làm thêm sheet2
à có khiếu nại thì ta tính tiếp . Bạn cho biết 1 cửa hàng nằm trên nhiều khu vực có thật không ? tôi thấy có vẻ vô lý . Bạn giải thích dùm tôi khúc này1146
Nếu 1 khu vực chứa nhiều cửa hàng và 1 cửa hàng cũng nằm trên nhiều khu vực thì đây là bài toán thật sự khó , hoặc có thể là tôi chưa nhìn ra chìa khóa giúp đơn giản hóa vấn đề . Bạn thử chạy file này xem sao
Lần sau nên lập topic riêng, xen ngang bị xóa hết là ráng chịu đó nghe!
Tuy chưa hiểu hết í bạn, nhưng bạn tham khảo hàm tự tạo sau:
Code trên có một điểm yếu mà rất dễ gây treo máy Until .Count = Amount
Nếu Amount=99% * Top và top tương đối lớn thì nó chạy rất là chậm và không ổn định về mặt thời gian. Giả sử top=1000, và amount=999, hàm tìm được 998 giá trị. Khi tìm giá trị cuối cùng thì xác xuất thành công sẽ là (1000-998)/1000, khá nhỏ, nên dễ gây treo máy. Thử nghiệm top=500000 và amount=495000 có khi chạy mất 20s tới 40s.
Với code dưới, nó chạy cực nhanh luôn mà không cần dùng dic hoặc collect.
Dùng bao nhiêu vòng lặp mình nghĩ không quan trọng, thuật toán mới là thứ để nói, vòng lặp Do của mình viết ra cho nó có, chứ hầu như mỗi lần nó chỉ thực hiện duy nhất một lần thôi nhé. Mình cho nó vào để đề phòng những trường hợp do sai số tính toán mà có thể gây lôi.
Mình thì chưa biết code mới như thế nào, nhưng nếu dùng dic thì chưa chắc nhanh đâu nhé, bởi code trên đều thao tác trên mảng.
Đề tài này cũng lâu lắm rồi bạn à (năm 2009) và sau đó đã được cải tiến rất nhiều
Sao mình ghét mấy cái Darr hay (Sarr) này ghê! Chẳng đúng chuẩn mực tên biến tí nào!
Biết rằng việc đặt tên biến là tùy sở thích, code chạy chính xác vẫn quan trọng hơn. Tuy nhiên, nếu tất cả mọi người đều tuân thủ 1 nguyên tắc chung thì việc đọc code sẽ trở nên rất dễ dàng (liếc qua đã hiểu)
Các bạn có tưởng tượng ngày nào đó chúng ta lập nhóm viết phần mềm rồi trưởng dự án giao cho mỗi người viết 1 module… Khi ấy mà mỗi người viết mỗi kiểu thì đố mà kiểm tra được đấy (được cũng mất rất nhiều thời gian)
Trên mạng người ta kháo nhau rằng: 1 người Việt Nam có thể giỏi hơn 1 người Nhật hoặc Hàn Quốc nhưng 10 người Việt Nam cộng lại thì.. dở ẹc. Tôi tin rằng người ta đang muốn nói đến vấn đề làm việc nhóm
Hãy tham khảo các trang lập trình nước ngoài (nhất là trang từ MS) hoặc đọc tài liệu về các hàm API, các bạn sẽ thấy người ta viết rất chuẩn mực (ngay từ khâu đặt tên biến)
Với người mới tập tành VBA tôi không đề cập, riêng bạn hieuCD (và nhiều bạn khác) đã giỏi lắm rồi, cũng đến lúc các bạn nên chăm chút cho các phần mà tôi đề cập ở trên đi là vừa
Nếu ý kiến cá nhân tôi có làm mích lòng ai đó thì xem như tôi chưa nói gì (tại thấy… ngứa miệng chút)
Nạp 1/2 xị nếp Long An, nắn lại gân cốt, thử sức xem sao
Nếu lỡ được thưởng, xin được phép chia cho anh chị trong hội người cao tuổi GPE :pimp:
chúc các bạn một ngày vui/-*+//-*+//-*+/
Bạn xem file, dùng công thức trực tiếp hoặc bấm nút lệnh chạy code
Mình thấy có hàm RandBetween mà ít thấy anh em sử dụng. Bài này mình thử viết theo hướng dùng nó thử xem sao
Code cho 1-100; 20: ( các code khác tương tự)
Sub Matrix3()
Dim I, Wf, Vung, Kq, K, kK, iHang, A
iHang = 20
Vung = [row(1:100)]
Set Wf = Application.WorksheetFunction
ReDim Kq(1 To iHang, 1 To 1)
For I = UBound(Vung) To 1 Step -1
A = Wf.RandBetween(1, I)
K = K + 1: kK = kK + 1
Kq(K, 1) = Vung(A, 1): Vung(A, 1) = Vung(I, 1)
If kK = iHang Then Exit For
Next I
.Resize(iHang) = Kq
End Sub
Thì mình quy ước ký tự là số, sau khi tạo được dãy số theo ý muốn mình tra ngược lại chỗ cái quy ước.
Hay là:
Biến kí số thành kí tự số, xâu hết chúng lại thành 1 (gồm kí tự số & các kí tự muốn có);
Sau đó băm chúng ra như băm bèo, sau mỗi lần băm nối chúng lại (thực hiện đến khi chán thì nghỉ giai đoạn)
Sau đó xắc lấy từ đầu đến đít hay ngược lại, tùy í sướng bản thân mỗi người.
Từ AA đến ZZ có 26*26 = 676 trị.
Dùng 1 trong các hàm đã được chỉ dẫn ở trên, lấy ngấu nhiên 1000 số trong khoảng từ 10000 đến 6769999.
Biển số xe làm sao cấp kiểu ngẫu nhiên được? Chả lẽ chỉ cấp 1 lần rồi thôi?
Hay đây là một hình thức làm sổ ma. Tôi khai báo rằng cty tôi có 1000 chiếc xe, bây giờ cần nộp sổ chứng từ chi tiêu cho từng chiếc. Khi ấy tôi cần 1000 biển số tạo ngẫu nhiên.
– Quét chọn từ E2 đến E15
– Gõ vào thanh Formula công thức =INDEX($B$2:$B$19,UniqueRandomNum(1,18,14))
– Bấm Ctrl + Shift + Enter để kết thúc
——————————–
Vấn đề của bạn là: bạn chưa biết cách dùng
Cái này không phải là lỗi. Đây là tác giả muốn hiển thị kết quả như vậy.
Nếu muốn thành dòng, trong code của link trên, thử thay dòng trên bằng dòng dưới xem sao
Bạn thử.Chỉnh 1 chút không biết có đúng ý không.
Hi em sửa theo bài 1 thôi anh.
Lâu lắm không đụng đến hàm này rồi nên cũng quên khá nhiều
Bạn thử sửa lại thế này xem:
Thử dùng hàm tự tạo
Phải có danh sách các số bỏ đi, mới né nó được
Thử hàm tự tạo
cú pháp ví dụ: =xyz(100,500,{200;201;202})
Kết qua trả về 1 chuỗi
—
Dãy số phải là nguyên dương nhé bạn
Cách của bạn có lẽ phải chờ rất lâu mới có kết quả.
Theo code của bạn: lập tổ hợp chập 50 của 101 phần tử, sau đó so sánh với 10 số cho trước.
Dùng hàm COMBIN(101,50) để tính, số tổ hợp có thể > 10^29, đây là chưa kể trường hợp lặp lại nhiều lần 1 tổ hợp -> để so sánh đạt yêu cầu với 10 số cho trước có lẽ phải chờ hơi lâu
Tốt nhất là bạn loại trừ 10 số ngay từ đầu khỏi tập cho trước, sau đó lấy ngẫu nhiên.
@domjnjc
Hàm xyz ở trên, bạn nhập thế nào
Theo bạn, ra 9 đúng hay ra 10 đúng?
Thử lại:
Rút gọn còn 2 vòng lặp:
Function xxx(dau, cuoi, loaitru)
Dim mang, Kq
Dim i, j, k, rd
ReDim mang(dau To cuoi)
For Each j In loaitru
mang(j) = 1
k = k + 1
Next j
ReDim Kq(1 To (cuoi – dau + 1 – k))
k = 0
Randomize
For i = dau To cuoi
If mang(i) = "" Then
k = k + 1
rd = Int(Rnd() * k) + 1
Kq(k) = Kq(rd)
Kq(rd) = i
End If
Next i
xxx = Join(Kq)
End Function
Nếu chỉ lấy N Kết quả thì sao
Mượn code của bài 151, bạn thử xem
—
Sửa lại cú pháp ví dụ: =xxx(100,200,{101},3)
Thử UDF này:
Function zzz(ByVal dau As Long, ByVal cuoi As Long, ByVal loaitru As Variant, Optional ByVal soluong As Long = 0)
Dim mang, Kq
Dim i, j, k, rd, temp
Dim pt As Long
ReDim mang(dau To cuoi)
For Each j In loaitru
If j >= dau And j <= cuoi Then
mang(j) = 1
k = k + 1
End If
Next j
pt = cuoi – dau + 1 – k
ReDim Kq(1 To pt)
k = 0
For i = dau To cuoi
If mang(i) = "" Then
k = k + 1
Kq(k) = i
End If
Next i
If soluong = 0 Or soluong > pt Then soluong = pt
Randomize
For i = 1 To soluong
rd = Int(Rnd() * pt) + 1
temp = Kq(i)
Kq(i) = Kq(rd)
Kq(rd) = temp
Next i
ReDim Preserve Kq(1 To soluong)
zzz = Join(Kq)
End Function
Biến loaitru phải nên là dạng Optional (có hoặc không cũng được). Ví dụ:
Có nghĩa là lấy 5 phần tử ngẫu nhiên từ 1 đến 10, loại trừ số 2 và số 4
nhưng nếu là vầy
thì có nghĩa là lấy 5 phần tử ngẫu nhiên từ 1 đến 10, không loại trừ gì cả
Ngoài ra nếu loaitru chi là 1 phần tử duy nhất (số 2 chẳng hạn) thì code phải cho phép viết theo dạng
mà không cần phải là:
—————————————-
Vân… vân… phải sửa nhiều lắm!
Tôi đang tự hỏi: 3 vòng lập liệu có nhiều lắm không?