How do I generate a string of 8 characters using lotusscript in this pattern? Eg: 0E 1F A3 ZK (there are spaces after every 2 characters including the last). Each character can only be either 0-9 or A-Z (uppercased only). I've used the Randomize and Rnd method before and thinking of applying it here but I'm not sure if that's the correct way and how to achieve that. Another thing is this string is going to be saved into my document and I have a view that list each of the generated string. Which means each time a string is generated, it has to be unique. If the string generated is already used in another document, then continue generating until one that hasn't been used is generated.
Yes, you can use Rnd in this case too.
Define a function getRandom() which gives you a random string in format "XX XX XX XX" with every call.
Function getRandom() As String
Const charList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
getRandom = _
Mid(charList, 35*Rnd+1, 1) + Mid(charList, 35*Rnd+1, 1) + " " + _
Mid(charList, 35*Rnd+1, 1) + Mid(charList, 35*Rnd+1, 1) + " " + _
Mid(charList, 35*Rnd+1, 1) + Mid(charList, 35*Rnd+1, 1) + " " + _
Mid(charList, 35*Rnd+1, 1) + Mid(charList, 35*Rnd+1, 1)
End Function
charList is a string with all allowed characters 0-9 and A-Z.
you get an random number between 1 and 36 with 35*Rnd+1. This is your index in charList to get randomly one of the characters.
Call the function getRandom() in a cycle as long as you get a string which is not yet in your view.
sID = Join(Evaluate(|#Password(#Unique)|))
Mid$(sID, 2, 2) & " " & Mid$(sID, 4, 2) & " " & Mid$(sID, 6, 2) & " " & Mid$(sID, 8, 2)
How it works:
#Unique is a sequential string token
#Password(anyText) will return a unique 32 digit HEX string enclosed in parenthesis
Evaluate will run the #Function formula and return an array of 1 element. So the Join around the Evaluate will turn that to a string scalar value.
The Mid$ functions simply yield 2 character values at 2 character offsets.
The only issue regarding your original parameters of your question is that you will never see get values above F since we are using Hexadecimal characters (0-9, A-F)
Related
I'm trying to make a random number game but the condition is always false even though I added the b = input box statement
Option Explicit
dim b,a,max,min
'To randomize variable (a)
max=3
min=1
Randomize
a = (Int((max-min+1)*Rnd+min))
b = inputbox("Guess a number from " & min & " to " & max)
If a = b Then
msgbox("you win")
Else
msgbox("you died it was " & a)
End If
I expected when you guessed the right number it would say you when but it always you died the number was #
You are almost there but as has been mentioned in the comments you do not populate the variable be with a values so the comparison will always be False.
If you are expecting b to be populated by the user you could ask for input via the InputBox() function by adding one line;
Option Explicit
Dim beans, b, a, max, min
'To randomize variable (a)
max = 100
min = 1
Call Randomize()
'Enter the line below to collect input from the user.
b = InputBox("Enter a number between " & min & " and " & max & ".")
'Remember to round the number to make sure you have a whole number.
a = Round((Int((max - min + 1) * Rnd() + min)))
If (a = b) Then
Call MsgBox("You win")
Else
Call MsgBox("You died it was " & a)
End If
You might also consider validating the input to make sure that the user enters a value between your min and max and responding accordingly if the value is invalid.
This matches 1 - 10.
Randomize
Num = Int((10 - 1 + 1) * Rnd + 1)
If CInt(Inputbox("Enter Number")) = Num Then
Msgbox "match"
Else
Msgbox "Nope it was " & Num
End If
The formula from help is Int((upperbound - lowerbound + 1) * Rnd + lowerbound). See http://download.microsoft.com/download/winscript56/Install/5.6/W982KMeXP/EN-US/scrdoc56en.exe.
I was visiting Vxheaven.org , while i found this code to come up with a random file name .
tmpname=""
randomize(timer)
namel=int(rnd(1)*20)+1
For lettre = 1 To namel
randomize(timer)
tmpname=tmpname & chr(int(rnd(1)*26)+97)
Next
typext = "execombatbmpjpggifdocxlsppthtmhtthta"
randomize(timer)
tmpext = int(rnd(1)*11)+1
tmpname=tmpname & "." & mid(typext,((tmpext-1)*3)+1,3) & ".vbs"
I am confused between these random statements , and its usage with for loop .
Can anyone explain me what is actually happening here ?
The purpose of Chr(Int(Rnd(1) * 26) + 97) is to pick a random character in the range "a" to "z". It works because the ascii code for "a" is 97, with the rest of the alphabet following in order. Thus the For loop builds up a random lower case string whose length is somewhere between 1 and 20.
typext = "execombatbmpjpggifdocxlsppthtmhtthta"
is a string of 33 = 3x11 characters. Successive triples are common file extensions, "exe", "com", "bat", etc. The expression
Mid(typext, ((tmpext - 1) * 3) + 1, 3)
extracts one of those triples.
There are many problems with this code.
1) Randomize (Timer) the first time is needlessly verbose. Randomize by itself seeds the random number generator with the system time -- you don't need to pass it anything unless you want to be able to reproduce the stream of random numbers in the future, which isn't the case here.
2) Randomize (Timer) the second and third time is really pointless. Since Timer has a 1 millisecond resolution, using that line again is somewhat likely to reset the random number generator to exactly the same seed. Thus the repetitions of that line could well decrease the amount of randomness in the output.
3) In Rnd(1) the 1 is pointless. It has exactly the same output as Rnd
4) Why hardwire in 11 specific file extensions and why restrict yourself to file extensions of length 3? It makes more sense to have an array of file extensions and then pick a random element of the array. Something like:
typext = Array("exe","com","bat","bmp","jpg", "gif", "doc", "xls","ppt", "htm", "htt", "hta")
r = Int(Rnd * (1+ UBound(typext)))
tmpname=tmpname & "." & typext(r) & ".vbs"
This way, you can freely add other entries to the array, including things like "c", and the rest of the code will work.
Here is a cleaned-up version, written as a function:
Function RandFileName()
Dim tmpname, namel, lettre, tmpext, typext, r
Randomize
tmpname = ""
namel = Int(Rnd(1) * 20) + 1
For lettre = 1 To namel
tmpname = tmpname & Chr(Int(Rnd(1) * 26) + 97)
Next
typext = Array("exe", "com", "bat", "bmp", "jpg", "gif", "doc", "xls", "ppt", "htm", "htt", "hta")
r = Int(Rnd * (1 + UBound(typext)))
tmpname = tmpname & "." & typext(r) & ".vbs"
RandFileName = tmpname
End Function
Typical output: bgwkxjvaapr.exe.vbs
dim a(100)
a(0)=9,a(1)=3,a(2)=-3,a(3)=8,a(4)=2
how can i find size of used array(i.e used size is 5
You have to count the non-empty elements:
Option Explicit
Function UsedElms(a)
UsedElms = 0
Dim i
For i = 0 To UBound(a)
If Not IsEmpty(a(i)) Then UsedElms = UsedElms + 1
Next
End Function
Dim a(5)
a(2) = 2
a(4) = 4
WScript.Echo "ub:", UBound(a), "sz:", UBound(a) + 1, "us:", UsedElms(a)
output:
cscript 23027576.vbs
ub: 5 sz: 6 us: 2
Here's a hacky one-liner that I just thought of. It essentially counts the number of empty elements by converting them to spaces and then trimming them off.
intLastIndex = UBound(a) - Len(Join(a, " ")) + Len(Trim(Join(a, " ")))
Just for fun! Don't go putting it into your production code. It would certainly be more efficient as a two-liner:
s = Join(a, " ")
intLastIndex = UBound(a) - Len(s) + Len(Trim(s))
Ekkehard has the proper answer here, though. This hack only works if your array is filled contiguously.
I know its a really stupid question, but can anyone help me understanding these lines:
dim dmnth = array()
Redim dmnth(Rs_emp_count + 1, Rs_proj_count + 1, total_days + 1)
dmnth(emp_cnt, prj_cnt, 0) = pname & " (" & pid & ")"
thanks in advance.
dim dmnth = array()
This is an invalid statement. In VBScript you can't declare a variable and initialize it with a value in a single statement. It probably should be
Dim dmnth
dmnth = Array()
or shorter
Dim dmnth : dmnth = Array()
which declares a variable dmnth and initializes the variable with an empty array. This is, however, only useful when you want to create an empty 1-dimensional array that will grow dynamically while preserving its values (which could also be achieved via ReDim arr(-1)). Since your array has 3 dimensions, this initialization is pointless. The command below would suffice for both declaration and initialization.
Redim dmnth(Rs_emp_count + 1, Rs_proj_count + 1, total_days + 1)
If dmnth already has been declared, this resizes the variable to a 3-dimensional array with the upper bounds Rs_emp_count + 1 in the 1st dimension, Rs_proj_count + 1 in the 2nd dimension, and total_days + 1 in the 3rd dimension. Any content of the array will be discarded. If dmnth hasn't been declared, it's declared and initialized as a 3-dimensional array with the given upper bounds.
dmnth(emp_cnt, prj_cnt, 0) = pname & " (" & pid & ")"
This puts a string constructed from pname and pid into the array field at position emp_cnt, prj_cnt, 0.
dim dmnth = array(); this sets dmth to the return value of the function array(); whatever that is. It is an unnecessary step in your program; unless array() does something useful aside from returning a value back.
Redim dmnth(Rs_emp_count + 1, Rs_proj_count + 1, total_days + 1); this trashes the contents of dmth; replacing dmnth with a 3D array with sizes, for each dimension respectively, Rs_emp_count + 1, Rs_proj_count + 1 and total_days + 1. All elements are cleared.
dmnth(emp_cnt, prj_cnt, 0) = pname & " (" & pid & ")" assigns pname & " (" & pid & ")" to the (emp_cnt, prj_cnt, 0) element of the array. Remember that arrays in VBScript are zero based; i.e. (0, 0, 0) is a valid element.
First the dmnth is declared to be an array.
Then it is redeclared as a 3 dimensional array.
Then the Emp_cnt, Prj_Cnt, 0th entry is set to be pname & " (" & pid & ")"
Looking for the best way to do this in VB6. Typically, I would use this approach...
' count spaces
For i = 1 To Len(text)
If Mid$(text, i, 1) = " " Then count = count + 1
Next
Not saying it's the best way, but you code do:
distinctChr = " "
count = Len(text) - Len(Replace(text, distinctChr , ""))
Use the split command like this
Dim TempS As String
TempS = " This is a split test "
Dim V As Variant
V = Split(TempS, " ")
Cls
Print UBound(V) '7
V = Split(TempS, "i")
Print UBound(V) '3
V = Split(TempS, "e")
Print UBound(V) '1
You can combine it to a single line.
Print UBound(Split(TempS, "i"))
I did some crude timing on it. On a 40,000 character string with all spaces it seems to clock in at 17 milliseconds on a 2.4 GHz Intel Core 2 processor.
A function could look like this
Function CountChar(ByVal Text As String, ByVal Char As String) As Long
Dim V As Variant
V = Split(Text, Char)
CountChar = UBound(V)
End Function
I would use a modified bucket sort:
Dim i as Integer
Dim index As Integer
Dim count as Integer
Dim FoundByAscii(0 To 255) As Boolean
For i = 1 To Len(text)
index = Asc(Mid$(text, i, 1))
FoundByAscii(index) = True
Next i
count = 0
For i = 0 To 255
If FoundByAscii(i) Then
count = count + 1
End If
Next i
...and your result is in count. The performance is O(N) - if Mid$ is O(1).
Edit:
Based on your clarification, do this:
' count spaces
Dim asciiToSearchFor As Integer
asciiToSearchFor = Asc(" ")
For i = 1 To Len(text)
If Asc(Mid$(text, i, 1)) = asciiToSearchFor Then count = count + 1
Next
As ascii compares have to be faster that string comparison. I'd profile it just in case, but I'm pretty sure.
It's not clear what you mean by the best way to do this.
If you want something very fast, but totally unmaintainable, adapt this horrible code that delves into the underlying memory of a VB6 string to count the number of words. Courtesy of VBspeed.