How to capitalise a random letter? - vbscript

In VBScript is it possible to select a random letter and capitalize it until all letters have been capitalized at least once?
Dim a
a = "Hello"
For i=o To Len(a)-1
If Mid(a,i+1, 1) = Mid(a, i+1, 1) Then
b = Mid(a, i+1, 1)
MsgBox b
End If
Next
That's some code I gathered. So far it reads a string letter by letter.
I want the output to be something like:
hello
Hello
hEllo
etc.
but I can't see how to do it without getting into super complex Mid Left Right statements that become confusing. Is it possible? Or do I need to use something like Mid(LCase(s,1,1) & Mid(UCase(s,2,1)) & Mid(LCase(s,3,3)?

Use Len() to determine the positions of letters to capitalize and Left() + UCase(Mid()) + Mid() to actually uppercase the letter at p =
Option Explicit
Dim s : s = "hello"
Dim l : l = Len(s)
Dim i : i = 0
Do Until s = UCase(s)
Dim p : p = Fix(Rnd() * l) + 1
If Mid(s, p, 1) <> UCase(Mid(s, p, 1)) Then s = Left(s, p - 1) & UCase(Mid(s, p, 1)) & Mid(s, p + 1)
WScript.Echo i, p, s
i = i + 1
Loop
output:
cscript 52911013.vbs
0 4 helLo
1 3 heLLo
2 3 heLLo
3 2 hELLo
4 2 hELLo
5 4 hELLo
6 1 HELLo
7 4 HELLo
8 5 HELLO

Related

splitting a string in chunks using classic asp

i got a list coma separated values (a,b,c,d,e,f,g,h,....)
i wish to split them into chunks of 5 like (a,b,c,d,e) (f,g,h,i,j)....
can someone help me with the code in classic asp ?
arr = Split(messto, ",") ' convert to array
totalemails = UBound(arr) ' total number of emails
if totalemails mod 5 = 0 then
totalloops = int(totalemails/5)
else
totalloops = int(totalemails/5) + 1
end if
x = 0
y = 0
b = 0
for x = 0 to totalloops
for counter = (5* x) to ((b+5)-1)
if Trim(arr(counter)) <> "" and isnull(trim(arr(counter))) = false then
response.Write(Trim(arr(counter)))
response.Write(counter & "<br>")
mymssto = mymssto & Trim(arr(counter)) & ","
response.Write(mymssto)
end if
next
You want to use Mod() to do this it's very powerful and underutilised function.
Here is a simple example based on the code in the question;
<%
Dim mumberToGroupBy: numberToGroupBy = 5
Dim index, counter, arr, messto
messto = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q"
arr = Split(messto, ",") ' convert to array
For counter = 0 To UBound(arr)
'Can't divide by 0 so we need to make sure our counter is 1 based.
index = counter + 1
Call Response.Write(Trim(arr(counter)))
'Do we have any remainder in the current grouping?
If index Mod numberToGroupBy = 0 Then Response.Write("<br>")
Next
%>
Output:
abcde
fghij
klmno
pq
Useful Links
A: Change response to only respond one set of values (details the use of Mod())

Converting a number to normalized scientific notation

I'm trying to create a method converting a number to normalized scientific notation, here is the code that I'm using to calculate mantissa and exponent:
ConvNSN 1000, M, P
MsgBox M & "e" & P
Sub ConvNSN(N, M, P)
If N = 0 Then
P = 0
M = 0
Else
P = Int(Log(Abs(N)) / Log(10))
M = N / 10 ^ P
End If
End Sub
The problem I am facing is that this code gives wrong exponent value for some numbers, eg 1000, 10E+6, 10E+9, 10E+12, 10E+13, etc... Exactly for 1000 converted should be 1e3, but not 10e2. It's obvious that the same problem with numbers, whose logarithms are close to an integer value, like Log(1 - 5.55111512312578E-17) / Log(10), which result is 0, however 1 - 5.55111512312578E-17 less then 1, and result has to be negative.
How can I get rid of Double type imprecision, and get this code to work properly?
UPDATE
I assume the fastest and quite accurate method to calculate mantissa and exponent of number in normalized scientific notation may be as follows:
Sub ConvNSN(N, M, P)
Dim A
If N = 0 Then
P = 0
M = 0
Exit Sub
End If
A = Abs(N)
If A < 1 Then
P = Int(Log(A) / Log(10))
Else
P = Int(Log(A) / Log(10) * (2 + Log(.1) / Log(10)))
End If
M = N / 10 ^ P
End Sub
Or another one, based on #Bob's solution:
Sub ConvNSN(N, M, P)
If N = 0 Then
P = 0
M = 0
Else
P = Int(Log(Abs(N)) / Log(10))
M = N / 10 ^ P
End If
If Abs(M) = "10" Then
M = M / 10
P = P + 1
End If
End Sub
First one slightly faster. Both of them process exponent from -322 to 308, but return not normalized mantissa with powers of 10 less then -310. I have not tested them yet with numbers, whose logarithms are a marginally less but very close to an integer values.
UPDATE 2
I decided to attach here an extra Sub ConvEN(), allowing to represent a number in engineering notation with SI prefixes from "p" to "T":
N = .0000456789
ConvNSN N, M, P
M = Round(M, 2)
ConvEN M, P, R, S
MsgBox R & " " & S & "Units"
Sub ConvNSN(N, M, P)
Dim A
If N = 0 Then
P = 0
M = 0
Exit Sub
End If
A = Abs(N)
If A < 1 Then
P = Int(Log(A) / Log(10))
Else
P = Int(Log(A) / Log(10) * (2 + Log(.1) / Log(10)))
End If
M = N / 10 ^ P
End Sub
Sub ConvEN(M, P, R, S)
DIM Q, P3
Q = int(P / 3)
P3 = Q * 3
If Q >= -4 And Q <= 4 Then
S = Array("p", "n", ChrW(&H03BC), "m", "", "k", "M", "G", "T")(Q + 4)
Else
S = "e" & P3 & " "
End If
R = M * 10 ^ (P - P3)
End Sub
Try this:
ConvNSN 1000, M, P
MsgBox M & "E" & P
ConvNSN 0.00000000000000001234, M, P
MsgBox M & "E" & P
ConvNSN -0.00000000000000001234, M, P
MsgBox M & "E" & P
Sub ConvNSN(N, M, P)
P = 0
If N < 0 Then
S = -1
ElseIf N > 0 Then
S = 1
Else
M = 0
Exit Sub
End If
M = Abs(N)
If M >= 10 Then
While M >= 10
M = M / 10
P = P + 1
Wend
M = M * S
Exit Sub
End If
If M < 1 Then
While M < 1
M = M * 10
P = P - 1
Wend
M = M * S
Exit Sub
End If
End Sub
Based on the comments, I re-wrote this my way, ignoring the structure from the OP.
MsgBox NSN(-0.0000000000000000000123456789,4)
MsgBox NSN(1234567890000000000000000000,4)
Function NSN(Number, Accuracy)
Exponent = 0
If Number > 0 Then
Sign = 1
ElseIf Number < 0 Then
Sign = -1
Else
NSN = 0
Exit Function
End If
Number = Number * Sign
If Number >= 10 Then
While Number >= 10
Number = Number / 10
Exponent = Exponent + 1
Wend
ElseIf Number < 1 Then
While Number < 1
Number = Number * 10
Exponent = Exponent - 1
Wend
End If
Number = Round(Number, Accuracy)
If Number = "10" Then
Number = 1
Exponent = Exponent + 1
End If
Number = Number * Sign
If Exponent = 0 Then
NSN = Number
Else
NSN = Number & "E" & Exponent
End If
End Function
Using strings rather than maths can help. Add your own error checking.
Num = "1000000.0005"
NumOfDigits = 4
Mag = Instr(Num, ".")
Num = Replace(Num, ".", "")
MSD = Left(Num, 1)
Rest = Mid(num, 2, NumOfDigits)
msgbox MSD & "." & Rest & " x 10^" & (Mag -2)

VBScript: How to select text after 6th occurence of char?

I have this string:
0|1|2|3|4|5|6|7|8|9
I need to return the text after the 6th occurence of | and before the 7th. In this example, it would be 6.
Can his be achieved using the simple String functions (Mid, Left, Right, InStr)?
In addition, you could use a RegExp to look for the possibly empty sequence of non-| before a | and after 6 such sequences:
>> Set r = New RegExp
>> r.Pattern = "^(?:[^\|]*\|){6}([^\|]*)\|"
>> WScript.Echo r.Execute("0|1|2|3|4|5|6|7|8|9")(0).SubMatches(0)
>>
6
For production code, you'd need a check against non-confirming data.
s = "0|1|2|3|4|5|6|7|8|9"
For i = 1 To 6
intPos1 = InStr(intPos1 + 1, s, "|")
If intPos1 = 0 Then Exit For
Next
If intPos1 > 0 Then
intPos2 = InStr(intPos1 + 1, s, "|")
If intPos2 > intPos1 Then MsgBox Mid(s, intPos1 + 1, intPos2 - intPos1 - 1)
End If
Or, like #Filburt said, it could be a one-liner with Split():
MsgBox Split(s, "|")(6)
Dim s, c, n, i, p, e, r
s = "0|1|2|3|4|5|6|7|8|9" ' examined string
c = "|" ' split char
n = 6 ' occurance to start from
i = 0
p = 0
r = ""
Do
p = InStr(p + 1, s, c)
If p = 0 Then Exit Do
i = i + 1
If i = n Then
e = InStr(p + 1, s, c)
If e > 0 Then r = Mid(s, p + 1, e - p - 1)
Exit Do
End If
Loop
MsgBox r

Excel formula to do the same as x=(b/N)*(-floor(N/2):floor(N/2)) in MATLAB

I'm converting my MATLAB code into an excel document but are having difficulty transferring the following formula across.
x=(b/N)*(-floor(N/2):floor(N/2))
Which if for example b =2 and N = 5
the results will be :
x = -0.8000 -0.4000 0 0.4000 0.8000
and if b = 2 and N =6 the results will be:
x = -1.0000 -0.6667 -0.3333 0 0.3333 0.6667 1.0000
Note: If N is odd there are N elements in x, if N is even there are N+1 elements in x.
Any ideas for how to write it within Excel?
This answer is follows from comments to my another answer.
It's a really big array formula. Select F3:F19 , enter formula in the formula bar and press CTRL+SHIFT+ENTER to evaluate it.
(suppose your b in A1 cell, your N in C4 cell.
=IFERROR(INDEX(($A$1/$C$4)*INT(($C$4-(ROW(INDIRECT($C$4 & ":" & 3* $C$4-1))-$C$4))/2),SMALL(IF(MATCH(($A$1/$C$4)*INT(($C$4-(ROW(INDIRECT($C$4 & ":" & 3* $C$4-1))-$C$4))/2),($A$1/$C$4)*INT(($C$4-(ROW(INDIRECT($C$4 & ":" & 3* $C$4-1))-$C$4))/2),0)=ROW(INDIRECT("1:" & ROWS(($A$1/$C$4)*INT(($C$4-(ROW(INDIRECT($C$4 & ":" & 3* $C$4-1))-$C$4))/2)))),MATCH(($A$1/$C$4)*INT(($C$4-(ROW(INDIRECT($C$4 & ":" & 3* $C$4-1))-$C$4))/2),($A$1/$C$4)*INT(($C$4-(ROW(INDIRECT($C$4 & ":" & 3* $C$4-1))-$C$4))/2),0),""),ROW(IDIRECT("1:" & ROWS(($A$1/$C$4)*INT(($C$4-(ROW(INDIRECT($C$4 & ":" & 3* $C$4-1))-$C$4))/2)))))),"")
here is my test workbook
In Excel VBA:
Dim j As Integer = 0
Dim b As Double, N As Double, M As Double, k As Double
b = Cells(3, 3)
N = Cells(3, 4)
If Int(N/2) = N/2 Then
M = N + 1
Else
M = N
End If
For k = -(b/N)*(floor(N/2) To (b/N)*(floor(N/2) Step 2*(b/N)*(floor(N/2)/M
j = j + 1
x(j)=k
Next k

vbscript error: expected statement (do until)

ok so im trying to do an assignment and i have written this code but it has errors, and i cant see why.
its saying expected statement, and im looking over it and i cant find what the problem is. Would be amazing if someone could shed some light on the error and possibly help me out.
here is the do until statement:
Sub btnTransformY_onclick()
Do Until r = 4 And n = 3
Do Until m = 1 To 8
Change(r,c) = (transformationY(r,1) * meh(1, m)) + transformationY(r, 2) * meh(2,m) + TransformationY(r,3) * meh(3,m)
m = m + 1
Next
c = c + 1
If c = 8 Then r = r + 1 And c = 1
Next
End Sub
unfortunately this hasnt worked, although it does seem to be the Do Until m = 1 To 8
does anyone know if to is valid syntax for a do until loop?
I reckon you want something on these lines, except I suspect you want two Next loops for r and n rather than one Do Until.
Sub btnTransformY_onclick()
r = 0
n = 0
Do Until r = 4 And n = 3
For m = 1 To 8
Change(r,c) = (transformationY(r,1) * meh(1, m)) + transformationY(r, 2) * meh(2,m) + TransformationY(r,3) * meh(3,m)
''m = m + 1
Next
c = c + 1
If c = 8 Then
r = r + 1
c = 1
''Where does n get counted up?
End If
Loop
End Sub
Next is for for loops, to close a do loop use loop:
do until ..
...
loop
Also
if c = 8 then r = r + 1 and c = 1
Is a bitwise comparison (bits of LHS anded with RHS) which is probably not what you want, so instead;
if c = 8 then
r = r + 1
c = 1
end if

Resources