Hình như thớt diễn tả câu hỏi không rõ.Hai, ba, và năm. Đủ nhỉ?
Đối với câu đố này thì không cần VBA, chỉ cần thuộc định nghĩa số nguyên tố là gì rồi xòe bàn tay là thấy 3 con.Đáp án đúng, nhưng bài làm (các câu lệnh VBA) đâu vậy?!?
Hiển nhiên là không rõ ràng. Nếu tôi viết code để có 2, 3, 5 thì thủ thuật khác, nếu tôi viết code để lấy bộ 3 bất kỳ thì thủ thuật khác, nếu liệt kê hết các bộ 3 thì thủ thuật lại khác nữa. Nếu lấy bộ 3 gần 600 nhất, thì lại khác nữa.Hình như thớt diễn tả câu hỏi không rõ.
Có lẽ muốn nói "các bộ ba số nguyên tố liên liếp"
Sub FindConsecutivePrimes()
Dim count As Integer
Dim num As Integer
Dim primes(2) As Integer
count = 0
num = 100
Do While count < 3
If IsPrime(num) Then
primes(count) = num
count = count + 1
End If
num = num + 1
Loop
' In ra ba số nguyên tố liên tiếp
For i = 0 To 2
Debug.Print primes(i)
Next i
End Sub
Function IsPrime(n As Integer) As Boolean
Dim i As Integer
If n <= 1 Then
IsPrime = False
Exit Function
End If
For i = 2 To Int(Sqr(n))
If n Mod i = 0 Then
IsPrime = False
Exit Function
End If
Next i
IsPrime = True
End Function
Tôi thì cho CoPilot 7 điểm, người làm theo chỉ 2 điểm. Không làm theo mà copy code về chạy thì cho ốc zịt.1. Nếu chỉ theo đúng chỉ dẫn 3 của bài #7: tối đa 7/10 điểm
Đúng. Vì vậy thuật toán xét đã được ưu hóa là xét xem nó có phải là số lẻ trước. Lúc xét chia chẵn thì cũng chỉ xét chia cho số lẻ (từ 3 đến căn hai số step 2)Có 1 tính chất của các SNT (số nguyên tố) lớn hơn 100 là toàn số lẻ
Như vậy bài toán có thể rút ngắn gần phân nữa đoạn đường nhờ khảo sát chỉ những số lẽ 101, 103,. . . .,999
Để snh động hơn, ta có thể tìm số lẽ N bất kỳ trong khoảng 101.. 505 & bắt đầu tìm 3 SNT liền kề ( > N) từ N này
Xin được góp vui và rất mong nhận được nhiều góp ý để nâng cao kiến thứcCó 1 tính chất của các SNT (số nguyên tố) lớn hơn 100 là toàn số lẻ
Như vậy bài toán có thể rút ngắn gần phân nữa đoạn đường nhờ khảo sát chỉ những số lẽ 101, 103,. . . .,999
Để snh động hơn, ta có thể tìm số lẽ N bất kỳ trong khoảng 101.. 505 & bắt đầu tìm 3 SNT liền kề ( > N) từ N này
Option Explicit
Public t&, KQ()
Sub SoNguyenTo(ByVal S1 As Long, S2 As Long, Chon As Integer)
'Chon =1 lay tât ca cac sô nguyen tô tim đươc thành 1 cot
'Chon=2 lay 1 tap gôm 3 sô nguyên to liên kê
'Chon = 3 lay 1 tâp gôm nhiêu tâp 3 sô nguyên to liên kê xêp vào 1 côt
Dim i&, j&, k&, a&, N&, Nhay&, SN&
Dim S, L
S = Array(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37)
ReDim KQ(1 To (S2 - S1), 1 To 1)
SN = SoNgauNghien(S1, S2)
t = 0
If SN = 1 Then SN = 2
If SN >= 100 Then
If SN Mod 2 = 0 Then SN = SN + 1
Nhay = 2
Else
Nhay = 1
End If
For i = SN To S2 Step Nhay
For j = LBound(S) To UBound(S)
If i = S(j) Or i Mod S(j) <> 0 Then N = 1 Else N = 0: Exit For
Next j
If N = 1 Then
Select Case Chon
Case Is = 1
t = t + 1: KQ(t, 1) = i
Case Is = 2
a = a + 1: If L = Empty Then L = i Else L = L & ";" & i
If a = 3 Then t = t + 1: KQ(t, 1) = L: Exit For
Case Is = 3
a = a + 1: If L = Empty Then L = i Else L = L & ";" & i
If a Mod 3 = 0 Then t = t + 1: KQ(t, 1) = L: L = Empty
End Select
End If
Next i
End Sub
Sub Test()
Call SoNguyenTo(100, 999, 3)
Sheet2.[A10].Resize(1000, 1).ClearContents
Sheet2.[A10].Resize(t, 1) = KQ
End Sub
Function SoNgauNghien(iMin As Long, iMax As Long)
Call Randomize
SoNgauNghien = Int((iMax - iMin + 1) * Rnd + iMin)
End Function
Tuy sinh động nhưng nó liên quan đến loại toán khác, không nằm trong tinh thần "số nguyên tố",Có 1 tính chất của các SNT (số nguyên tố) lớn hơn 100 là toàn số lẻ
Như vậy bài toán có thể rút ngắn gần phân nữa đoạn đường nhờ khảo sát chỉ những số lẽ 101, 103,. . . .,999
Để snh động hơn, ta có thể tìm số lẽ N bất kỳ trong khoảng 101.. 505 & bắt đầu tìm 3 SNT liền kề ( > N) từ N này
Nếu trong khoảng từ 101 đến 999 có n số nguyên tố, thì giải bài 4 sẽ được n - 2 bộ 3 liền kề. Vẫn phải liệt kê hết n số ra rồi mới ghép bộ, và quá trình liệt kê vẫn phải dựa vào định nghĩa (đặc tính) số nguyên tố rồi. Ý anh cũng không rõ ràng như bài 1 vậy á.Bài toán tôi đề nghị ở bài #4 là một loại triển khai đặc tính nguyên tố. Gợi ý đến đây là gần hết cái thuật toán mà tôi muốn nói rồi.
Không phải vậy.Nếu trong khoảng từ 101 đến 999 có n số nguyên tố, thì giải bài 4 sẽ được n - 2 bộ 3 liền kề. Vẫn phải liệt kê hết n số ra rồi mới ghép bộ, và quá trình liệt kê vẫn phải dựa vào định nghĩa (đặc tính) số nguyên tố rồi. Ý anh cũng không rõ ràng như bài 1 vậy á.
Còn giải thuật thì cũng chỉ là vònglặp với step 2. Hoặc giải thuật khác cũng vậy, không giúp gì cho việc liệt kê hết n số tốt hơn.
À còn 1 ý nữa, số (2 ký số trở lên) tận cùng là 5 cũng là số lẻ nhưng không phải số nguyên tố, có thể bỏ qua để giảm thiểu số vòng lặp.
Vụ này giờ tôi mới biết. Cấp 2, cấp 3 đều không có dạy. Tôi học lớp 6 năm 1972, lớp 6, 7, 8 học chương trình trước giải phóng, qua lớp 9 là chương trình sau giải phóng mà không có cái này. Giới hạn chia thử là căn 2 thì tôi tự suy luận ra chứ trường cũng không dạy.Cũng toán số cấp 2:
Lúc mò xem một số có phải là nguyên tố, ta chỉ cần chia thử cho các số nguyên tố nhỏ hơn hay bằng căn hai nó.
Có lẽ do bà cô dạy toán của tôi thêm vào. Bả dạy như bài tập thức hành cho hệ luận:Vụ này giờ tôi mới biết. Cấp 2, cấp 3 đều không có dạy. Tôi học lớp 6 năm 1972, lớp 6, 7, 8 học chương trình trước giải phóng, qua lớp 9 là chương trình sau giải phóng mà không có cái này. Giới hạn chia thử là căn 2 thì tôi tự suy luận ra chứ trường cũng không dạy.
À phải, tôi có đọc câu này (nguyên văn) nhưng không để ý vì nó nằm trong bài toán khác: Phân tích 1 số thành các thừa số nguyên tố, áp dụng trong việc tìm ước số chung lớn nhất.Có lẽ do bà cô dạy toán của tôi thêm vào. Bả dạy như bài tập thức hành cho hệ luận:
Mọi số không nguyên tố đều là tích nhân của nhiều số nguyên tố nhỏ hơn nó.
Cảm ơn anh đã chỉ bảo.Có lẽ do bà cô dạy toán của tôi thêm vào. Bả dạy như bài tập thức hành cho hệ luận:
Mọi số không nguyên tố đều là tích nhân của nhiều số nguyên tố nhỏ hơn nó.
Chú:
Tôi để ý thấy bài #12 có theo giải thuật "sàng nguyên tố". Tức là bạn này có biết qua.
Nhắn tác giả lài #12:
1. sàng của bạn có số 9, không phải là nguyên tố.
2. khi code dài và phức tạp. Bạn nên đặt tên tham theo kiểu khác với biến nội, dễ đọc và chơn. Đọc bài của bạn, tôi cứ bị nhầm S, S1, S2 đều là biến nội trong khi thực tế chỉ có S là biến nội
3. khi code dùng nhiều đến mảng thì đặt mảng một chiều thay vì hai chiều mà các chỉ số cột đều là 1 thì code chạy không hiệu quả (con tính địa chỉ phần tử của mảng 1 chiều nhanh hơn 2 chiếu). Lúc cần thì dùng hàm INDEX và TRANSPOSE chỉnh lại.
Sub BangSoNguyenTo111_999()
Dim Rw As Integer, Col As Integer, Num As Integer, Cot As Integer, RwMax As Integer
ReDim Arr(1 To 50, 1 To 9) As Integer
[A1].Resize(50, 9).Value = Space(0)
For Num = 101 To 999 Step 2
If IsPrime(Num) Then
Col = Num \ 100
If Col > Cot Then
If Rw > RwMax Then RwMax = Rw
Cot = Col: Rw = 1
Else
Rw = Rw + 1
End If
Arr(Rw, Col) = Num
End If
Next Num
[A1].Resize(RwMax, 9).Value = Arr()
End Sub
Function IsPrime(n As Integer) As Boolean
Dim i As Integer
For i = 2 To Sqr(n)
If n Mod i = 0 Then
IsPrime = False: Exit Function
End If
Next i
IsPrime = True
End Function
Function GeneratePrimes(maxNumber As Long) As Long()
' Tạo sàng Eratosthenes để lọc số nguyên tố đến maxNumber
Dim sieve() As Boolean
Dim primes() As Long
Dim i As Long, j As Long, count As Long
ReDim sieve(2 To maxNumber)
For i = 2 To maxNumber
sieve(i) = True
Next i
For i = 2 To Int(Sqr(maxNumber))
If sieve(i) Then
For j = i * i To maxNumber Step i
sieve(j) = False
Next j
End If
Next i
' Đếm số nguyên tố trong khoảng 101-999
count = 0
For i = 101 To maxNumber - 2 ' Đảm bảo có 3 số liên tiếp
If sieve(i) And sieve(i + 2) And sieve(i + 4) Then
count = count + 1
End If
Next i
' Lưu các bộ ba số nguyên tố liên tiếp
ReDim primes(1 To count, 1 To 3)
count = 0
For i = 101 To maxNumber - 2
If sieve(i) And sieve(i + 2) And sieve(i + 4) Then
count = count + 1
primes(count, 1) = i
primes(count, 2) = i + 2
primes(count, 3) = i + 4
End If
Next i
GeneratePrimes = primes
End Function
Sub FindConsecutivePrimesOptimized()
Dim primes() As Long
Dim ws As Worksheet
Dim startTime As Double
startTime = Timer
Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Cells.ClearContents
ws.Range("A1:C1") = Array("Prime 1", "Prime 2", "Prime 3")
' Tạo danh sách số nguyên tố và xuất kết quả
primes = GeneratePrimes(999)
If UBound(primes, 1) >= 1 Then
ws.Range("A2").Resize(UBound(primes, 1), 3).Value = primes
MsgBox "Tìm thấy " & UBound(primes, 1) & " bộ ba." & vbCrLf & _
"Thời gian chạy: " & Format(Timer - startTime, "0.000") & " giây.", vbInformation
Else
MsgBox "Không tìm thấy bộ ba nào.", vbExclamation
End If
End Sub
Function GeneratePrimes(minNumber as Long, maxNumber As Long) As Long()
' Tạo sàng Eratosthenes để lọc số nguyên tố đến maxNumber
Dim sieve() As Boolean
Dim primesList() As Long
Dim tripletArray() As Long
Dim i As Long, j As Long
Dim primeCount As Long, tripletCount As Long
' Khởi tạo sàng
ReDim sieve(2 To maxNumber)
For i = 2 To maxNumber
sieve(i) = True
Next i
For i = 2 To Int(Sqr(maxNumber))
If sieve(i) Then
For j = i * i To maxNumber Step i
sieve(j) = False
Next j
End If
Next i
' Lọc các số nguyên tố trong khoảng minNumber-maxNumber
primeCount = 0
For i = minNumber To maxNumber
If sieve(i) Then primeCount = primeCount + 1
Next i
If primeCount = 0 Then
GeneratePrimes = Array()
Exit Function
End If
' Lưu vào mảng primesList
ReDim primesList(1 To primeCount)
primeCount = 0
For i = minNumber To maxNumber
If sieve(i) Then
primeCount = primeCount + 1
primesList(primeCount) = i
End If
Next i
' Tìm các bộ ba liên tiếp trong danh sách
tripletCount = 0
For i = 1 To primeCount - 2
tripletCount = tripletCount + 1
Next i
If tripletCount = 0 Then
GeneratePrimes = Array()
Exit Function
End If
' Lưu kết quả vào mảng 2D
ReDim tripletArray(1 To tripletCount, 1 To 3)
For i = 1 To tripletCount
tripletArray(i, 1) = primesList(i)
tripletArray(i, 2) = primesList(i + 1)
tripletArray(i, 3) = primesList(i + 2)
Next i
GeneratePrimes = tripletArray
End Function
'---------------------------------------------------------
Sub FindConsecutivePrimesOptimized()
Dim primes() As Long
Dim ws As Worksheet
Dim startTime As Double
startTime = Timer
Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Cells.ClearContents
ws.Range("A1:C1") = Array("Prime 1", "Prime 2", "Prime 3")
primes = GeneratePrimes(101,999) '****
If Not IsEmpty(primes) Then
ws.Range("A2").Resize(UBound(primes, 1), 3).Value = primes
MsgBox "Tìm thấy " & UBound(primes, 1) & " bộ ba." & vbCrLf & _
"Thời gian chạy: " & Format(Timer - startTime, "0.000") & " giây.", vbInformation
Else
MsgBox "Không tìm thấy bộ ba nào.", vbExclamation
End If
End Sub
Sub TaoBang100SoNguyenTo3ChuSoLonNhat()
Dim Num As Integer, Col As Integer, Cot As Integer, Rw As Integer, Dem As Integer
ReDim Arr(1 To 30, 1 To 9) As String: Dim RwMax As Integer
Sheet2.Select
[B2].Resize(30, 9).Value = Arr(): Cot = 9
For Num = 999 To 101 Step -2
If IsPrime(Num) Then
Col = Num \ 100
If Col < Cot Then
If Rw > RwMax Then RwMax = Rw
Cot = Col: Rw = 1
Else
Rw = Rw + 1
End If
Arr(Rw, Col) = CStr(Num): Dem = Dem + 1
If Dem = 100 Then
[B2].Resize(RwMax, 9).Value = Arr(): Exit Sub
End If
End If
Next Num
End Sub
//fNguyenTo
(so as number) as logical =>
let
kq= List.Count(List.Select({2..Number.RoundDown(Number.Sqrt(so))}, each Number.Mod(so, _) = 0 )) = 0
in
kq
let
// thay vong lap FOR
a = List.Generate(
() => 997,
each _ > 100,
each _ - 2,
each if fNguyenTo(_) then _ else null),
// Lay 20 ket qua dau tien
kq = List.FirstN(List.RemoveNulls(a), 20)
in
kq
Sub xyz()
Dim a(1 To 1000), res(1 To 1000, 1 To 1)
Dim xMin&, xMax&, xU, i&, j&, k&, n&
xMin = 100: xMax = 9999
For i = xMin To 2
n = n + 1: res(n, 1) = i
Next i
'Tao mang cac so nguyen to lam co so so sanh
xU = Int(Sqr(xMax))
For i = 3 To xU Step 2
For j = 1 To k
If i Mod a(j) = 0 Then Exit For
Next j
If j > k Then
k = k + 1: a(k) = i
If i >= xMin Then n = n + 1: res(n, 1) = i
End If
Next i
If n > 0 Then
If xMin < res(n, 1) Then xMin = res(n, 1) + 1
End If
xMin = ((xMin \ 2) * 2 + 1) 'Lay gia tri le
For i = xMin To xMax Step 2
For j = 1 To k
If i Mod a(j) = 0 Then Exit For
Next j
If j > k Then n = n + 1: res(n, 1) = i
Next i
Range("B2").Resize(UBound(res), 1) = res
End Sub
Định hướng các bước:Có VBA, có Query rồi. Bi giờ ai xung phong viết hàm Lambda hôn?
Thử lại, dùng công thức, không cần VBA hay QueryBa số nguyên tố liên tiếp này bé hơn con số 999 & lớn hơn 100. (đã sửa sau góp ý của các bài 2 - 5)
Chúc các bạn vui vẻ nhân dịp xuân về!
=LET(
IsPrime,
LAMBDA(n,
IF(n < 2, FALSE,
IF(n = 2, TRUE,
IF(n = 3, TRUE,
IF(MOD(n, 2) = 0, FALSE,
LET(
maxDiv, SQRT(n),
floorMaxDiv, ROUNDDOWN(maxDiv, 0),
divs, SEQUENCE((floorMaxDiv - 1)/2, 1, 3, 2),
IFERROR(AND(MOD(n, divs) <> 0), TRUE)
)
)
)
)
)
),
nums, SEQUENCE(899, 1, 101, 1),
isPrimeArray, MAP(nums, LAMBDA(x, IsPrime(x))),
primes, FILTER(nums, isPrimeArray),
count, ROWS(primes),
IF(count < 3, "Không tìm thấy bộ ba nào",
HSTACK(
INDEX(primes, SEQUENCE(count - 2)),
INDEX(primes, SEQUENCE(count - 2) + 1),
INDEX(primes, SEQUENCE(count - 2) + 2)
)
)
)
Hàm Lambda dùng đệ quy để thay thế vòng lặp.....
Nhưng chưa làm hoàn toàn bằng 1 công thức duy nhất.
Function DeQuyNT(ByVal So As Long, Optional Kd As Long = 3) As Boolean
DeQuyNT = False
Select Case So
Case 0, 1: Exit Function
Case 2: DeQuyNT = True: Exit Function
Case Else
If (So And 1) = 0 Then Exit Function
DeQuyNT = True
If Kd > Sqrt(So) Then Exit Function
If So Mod Kd = 0 Then DeQuyNT = False: Exit Function
DeQuyNT = DeQuyNT(So, Kd + 2)
End Select
End Function
TẠO BẢNG 100 SỐ NGUYÊN TỐ GỒM 3 KÝ SỐ LỚN NHẤT.
=SORT(
LET(
IsPrime,
LAMBDA(n,
IF(n < 2, FALSE,
IF(n = 2, TRUE,
IF(n = 3, TRUE,
IF(MOD(n, 2) = 0, FALSE,
LET(
maxDiv, SQRT(n),
floorMaxDiv, ROUNDDOWN(maxDiv, 0),
divs, SEQUENCE((floorMaxDiv - 1)/2, 1, 3, 2),
IFERROR(AND(MOD(n, divs) <> 0), TRUE)
)
)
)
)
)
),
nums, SEQUENCE(900, 1, 100, 1),
isPrimeArray, MAP(nums, LAMBDA(x, IsPrime(x))),
primes, FILTER(nums, isPrimeArray),
top50Primes, INDEX(primes, SEQUENCE(50, 1, ROWS(primes) - 49, 1)),
top50Primes
)
,,-1
)
Nếu dùng vùng là từ 0 đến 100 thì sao anh nhỉ ?Function IsPrime(n As Integer) As Boolean Dim i As Integer For i = 2 To Sqr(n) If n Mod i = 0 Then IsPrime = False: Exit Function End If Next i IsPrime = True End Function
Em cũng hay coi video từ kênh: https://www.youtube.com/c/ToánThúVịSub TimSoHoanHao():