how to program this in basic without goto, but also without low computing time - goto

nam() is a string Array, and should not be compared too often, takes long. vnr() is an integer Array, and normally is the only thing that is compared. this means vnr(i2) = vnr(i3) is a rare event. how to make it that there are even not two integer comparisons (the second // line is optional, because already compared in first line).
if vnr(i2) >= vnr(i3) Then
if vnr(i2) = vnr(i3) Then
If nam(i2) > nam(i3) Then
GoTo tausche
End If
Else
tausche:
i4 = vnr(i2)
s8 = nam(i2)
vnr(i2) = vnr(i3)
nam(i2) = nam(i3)
vnr(i3) = i4
nam(i3) = s8
End If
End If

The normal thing to do would be to (a) use a subroutine to avoid the goto, and (b) either reverse the logic or remove the extra condition so that the more common event comes first. Reversing the logic would produce something like:
if vnr(i2) < vnr(i3) then
gosub tausche
else if vnr(i2) = vnr(i3) then
if nam(i2) > nam(i3) then
gosub tausche
end if
end if
sub tausche
i4 = vnr(i2)
s8 = nam(i2)
vnr(i2) = vnr(i3)
nam(i2) = nam(i3)
vnr(i3) = i4
nam(i3) = s8
end sub
Removing the extra condition would produce something like:
if vnr(i2) > vnr(i3) then
rem do nothing
else if vnr(i2) < vnr(i3) then
gosub tasuche
else if nam(i2) > nam(i3) then
gosub tausche
end if
sub tausche
i4 = vnr(i2)
s8 = nam(i2)
vnr(i2) = vnr(i3)
nam(i2) = nam(i3)
vnr(i3) = i4
nam(i3) = s8
end sub
To remove the double-check, instead of checking the combined condition of vnr(i2) >= vnr(i3), separate out the greater than and the equal to.
In the second example, the first check checks that vnr(i2) > vnr(i3) and the second if they’re less than, so that we know that by the time the third comes around, they are equal, and we can simply leave that condition out and go straight to comparing the strings.
To remove the goto, use a subroutine. Depending on your implementation of BASIC, you may need a return at the end of the subroutine, of course.

Related

How to evaluate without unnecessary parentheses in Julia?

I have a case struct which holds an expression with the type of SymbolicUtils.Term{Bool}. Also I have defined rules from SymbolicUtils library which takes these cases as input and simplifies them. In order to simplify these cases the form should be like: (i == j) & (i == 3) & (j == 3) & (i == 3) & (j == 3) without unnecessary parentheses. For example it's not good to have this one: ((i == j) & ((i == 3) & (j == 3))) & ((i == 3) & (j == 3))
In order to solve this, I thought I can convert the expression with extra parentheses to string then I can process this string to get the desired form. I did this actually:
function reduce_parentheses(case::Case)
main_exp_string = ""
exp_to_str = repr(case.condition) #Convert case's condition into a string.
condition_list = split(exp_to_str, "&") #Split cases to subcases into a list.
for i in 1:length(condition_list) # Iterate cases list one by one.
stripped = lstrip(condition_list[i], [' ']) #Remove the whitespace at the beginning of the expression.
stripped = rstrip(stripped, [' ']) #Remove the whitespace at the end of the expression.
stripped = lstrip(stripped, ['(']) #Add opening parentheses at the beginning of the expression.
stripped = rstrip(stripped, [')']) #Add closing parentheses at the end of the expression.
#Get the desired form.
if i != 1
main_exp_string = main_exp_string * ' ' * '(' *stripped * ')'
elseif i == 1
main_exp_string = main_exp_string * '(' *stripped * ')'
end
if i != length(condition_list)
main_exp_string = main_exp_string * ' ' * '&'
end
end
println(main_exp_string)
exp = (Meta.parse(main_exp_string)) #Convert string back to an expression.
println(typeof(eval(exp))) #Convert expression back to SymbolicUtils.Term{Bool} type.
end
I can get the string in the desired form but when I try to turn it back into an expression I'm getting unnecessary parentheses with the different form because it's evaluating left to right I think.
Example:
The case with unnecessary parentheses: ((i == j) & ((i == 3) & (j == 3))) & ((i == 3) & (j == 3))
The processed string(desired form): (i == j) & (i == 3) & (j == 3) & (i == 3) & (j == 3)
Evaluated case: ((((i == j) & (i == 3)) & (j == 3)) & (i == 3)) & (j == 3)
How can I solve this? Maybe instead of converting it into a string can I do it in a smarter way?

Julia: Console Input Validation

How do you guys handle console input validation? In C++, case/switch is my goto...
I was trying a recursive function but was getting locked in lower levels. Plus that might be overdoing it. I did manage a while loop with an "exclusive or" but, that is not really scalable.
function prob6()
println("Pick a number; any number:")
x = readline(stdin)
y = parse(Int64, x)
z = 0
println("Select 1 or 2")
p1 = readline(stdin)
p2 = parse(Int64, p1)
select = p2
while xor((p2 == 1), (p2 == 2)) == false
println("Select 1 or 2")
p1 = readline(stdin)
p2 = parse(Int64, p1)
select = p2
end
if select == 1
for i in 1:y
print("$i ")
z = z + i
end
else
z = 1
for i in 1:y
print("$i ")
z = z * i
end
end
println(z)
end
Any alternatives?
There are many ways. I usually create a validation loop to check the type of the input item, and will use tryparse instead of parse, since it will not throw an error if input is malformed:
function queryprompt(query, typ)
while true
print(query, ": ")
choice = uppercase(strip(readline(stdin)))
if (ret = tryparse(typ, choice)) != nothing
return ret
end
println()
end
end
n = queryprompt("Integer please", Int64)
println(n)
x = queryprompt("Float please", Float64)
println(x)

VBS multidimensional array from a For Each

Perspective: This script will run on user login and on command with a shortcut on the desktop. The order the application start is imperative. Throughout the script, I require the full path and the program name.
Problem: Each program path is a value in an array. I am trying to split each program path by “\” and get the upper bound to get the program name. Then Redim Preserve the original array and add the program on the second dimension. After reading for many hours, I grasp I can only change the last dimension, but I can’t figure out how to not get out of bound errors. This Creating a Multidimensional, Associative Array in VBScript is not trying to redim preserve from a For Each split.
Set objFso = CreateObject("Scripting.FileSystemObject")
'---Create Program Variables
strProgram1 = "%SystemRoot%\notepad.exe"
strProgram2 = "C:\Program Files\Microsoft Office\root\Office16\OUTLOOK.EXE"
strProgram3 = "C:\Program Files\Microsoft Office\root\Office16\ONENOTE.EXE"
strProgram4 = "C:\Program Files (x86)\Internet Explorer\iexplore.exe" & " https://www.google.com" 'IE with URL
'---Add Program Path Variables to an Array
ReDim strProgramList(3)
strProgramList = Array(strProgram1,strProgram2,strProgram3,strProgram4)
strProgramNameList = Array()
strProgramRestartList = Array()
boolNeedsRestart = false
'---Iterating using For each loop to get program name.
ReDim Preserve strProgramList(3, 1)
For Each strProgramPath In strProgramList
strPathComponents = Split(strProgramPath, "\")
strProgramName = strPathComponents(Ubound(strPathComponents))
strProgramList(0, LBound(strProgramList) + 1) = strProgramName
Next
MsgBox strProgramList(0,0) & vbNewLine & strProgramList(1,0) & vbNewLine & strProgramList(2,0) & vbNewLine & strProgramList(3,0) & vbNewLine & strProgramList(0,1) & vbNewLine & strProgramList(1,1) & vbNewLine & strProgramList(2,1) & vbNewLine & strProgramList(3,1)
How to use the FileSystemObject to parse/build pathes and how to work with two-dimensional arrays:
Option Explicit
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim a : a = Split("A:\B\CC.EXE A:\CC\DD.CMD C:\You\Got\It.pl")
ReDim b(2, UBound(a))
Dim i
For i = 0 To UBound(a)
b(0, i) = a(i)
b(1, i) = goFS.GetParentFolderName(a(i))
b(2, i) = goFS.GetFileName(a(i))
Next
ReDim Preserve b(2, UBound(b, 2) + 1)
b(0, UBound(b, 2)) = "P:\i\pa\po.py"
b(1, UBound(b, 2)) = goFS.GetParentFolderName(b(0, UBound(b, 2)))
b(2, UBound(b, 2)) = goFS.GetFileName(b(0, UBound(b, 2)))
For i = 0 To UBound(b, 2)
WScript.Echo b(0, i), "=", b(1, i), "+", b(2, i), "=>", goFS.BuildPath(b(1, i), b(2, i))
Next
output:
cscript twodim.vbs
A:\B\CC.EXE = A:\B + CC.EXE => A:\B\CC.EXE
A:\CC\DD.CMD = A:\CC + DD.CMD => A:\CC\DD.CMD
C:\You\Got\It.pl = C:\You\Got + It.pl => C:\You\Got\It.pl
P:\i\pa\po.py = P:\i\pa + po.py => P:\i\pa\po.py

Call function recursively without additional parameter

I wrote vbscript function which search the list of free ports on Unix. So my code looks like this:
Function FindFreePorts(ByVal intPortToStart, ByVal intCountOfPortToSearch, ByVal arrFreePorts)
Dim i, arrCommand, arrTmp, blnFindAllPort, j, strCommand
Dim blnFree, intCountOfFreePorts
strCommand = "lsof -i | awk '{print $8}' | sed -n '/"
For i = intPortToStart To intPortToStart+intCountOfPortToSearch - 1
If i = intPortToStart+intCountOfPortToSearch - 1 Then
strCommand = strCommand & ".*"& i & "$/s/.*://p'"
Else
strCommand = strCommand & ".*:" & i &"\|"
End If
Next
Push arrCommand, strCommand
arrTmp = Array()
arrTmp = ExecuteCommandOnUnix(arrCommand, Null, _
Environment.Value("UNIXHOST_NAME"), _
Environment.Value("UNIXHOST_USER"), _
Environment.Value("UNIXHOST_PWD"))
' Count of busy port is UBound(arrTmp) - the other ports are free
' Find free ports
intCountOfFreePorts = intCountOfPortToSearch
For i = intPortToStart To intPortToStart+intCountOfPortToSearch - 1
blnFree = True
For j = 0 To UBound(arrTmp)
If arrTmp(j) = CStr(i) Then
blnFree = False
j = UBound(arrTmp)
End If
Next
If blnFree Then
Push arrFreePorts, i
intCountOfFreePorts = intCountOfFreePorts - 1
End If
Next
'
If intCountOfFreePorts = 0 Then
blnFindAllPort = True
Else
blnFindAllPort = False
End If
If Not blnFindAllPort Then
' We found UBound(arrFreePorts), we need to find intCountOfPortToSearch - UBound(arrFreePorts)
Do While intCountOfPortToSearch - UBound(arrFreePorts) - 1 <> 0
arrFreePorts = FindFreePorts(intPortToStart + intCountOfPortToSearch + 1, intCountOfPortToSearch - UBound(arrFreePorts) - 1, arrFreePorts)
If intCountOfPortToSearch - UBound(arrFreePorts) - 1 = 0 Then
Exit Do
End If
Loop
End If
FindFreePorts = arrFreePorts
End Function
As you can see I call this function recursively in Do While cycle. Everything works ok but I don't like arrFreePorts parameter here. So I should write this code to execute my function:
arrPort = FindFreePorts(intStartFromPort, intCountToSearch, arrPort)
But I have no idea how to rewrite this function without this parameter. Then I could call it in more simple way:
arrPort = FindFreePorts(intStartFromPort, intCountToSearch)
Thanks in advance.
To keep things (experiments, illustration of #Bond's contribution) simple, let's consider the task of putting the chars of a string into an array.
A function that shall return an array (without getting it via parameter or global) needs to create the array:
Function f1(s) ' default ByRef is ok, because Left and Mid return new (sub)strings
If "" = s Then
f1 = Array() ' return empty array for empty string
Else
Dim t : t = f1(Mid(s, 2)) ' recurse for tail - sorry no tail recursion
f1 = cons(Left(s, 1), t) ' copy! result of cons to f1/function's return value
End If
End Function
The growing of the array could be done inline, but for clarity I use a helper function cons():
Function cons(e, a) ' default ByRef is ok; neither e nor a are changed
ReDim aTmp(UBound(a) + 1) ' create larger array
Dim i : i = 0
aTmp(i) = e ' 'new' head
For i = 1 To UBound(aTmp)
aTmp(i) = a(i - 1) ' copy 'old' elms
Next
cons = aTmp ' copy! aTmp to cons/function's return value
End Function
Calling the function is nice:
WScript.Echo 3, "[" & Join(f1("12456789"), ",") & "]"
The price to pay for avoiding the passing of 'the' array:
a lot of copies (array assingment copies in VBScript)
no tail recursion (I doubt, however, that VBScript exploits it)
about factor 10 slower than the Sub approach ((c) Bond) below
As in this case the recursive calls can/should work on the 'same' array, a Sub does the task more efficiently (and is less complex):
Sub s1(s, a) ' default ByRef is ok; a should be modified, s isn't touched
If "" <> s Then
ReDim Preserve a(UBound(a) + 1) ' grow! a
a(UBound(a)) = Left(s, 1)
s1 Mid(s, 2), a ' tail recursion for tail
End If
End Sub
Calling it looks nasty:
ReDim a(-1) : s1 "123456789", a : WScript.Echo 3, "[" & Join(a, ",") & "]"
But that can be avoided by a wrapper:
Function f2(s)
ReDim aTmp(-1)
s1 s, aTmp
f2 = aTmp
End Function

How do I find out if the first character of a string is a number in VB.NET?

How do I check to see if the first character of a string is a number in VB.NET?
I know that the Java way of doing it is:
char c = string.charAt(0);
isDigit = (c >= '0' && c <= '9');
But I'm unsure as to how to go about it for VB.NET.
Thanks in advance for any help.
Here's a scratch program that gives you the answer, essentially the "IsNumeric" function:
Sub Main()
Dim sValue As String = "1Abc"
Dim sValueAsArray = sValue.ToCharArray()
If IsNumeric(sValueAsArray(0)) Then
Console.WriteLine("First character is numeric")
Else
Console.WriteLine("First character is not numeric")
End If
Console.ReadLine()
End Sub
Public Function StartsWithDigit(ByVal s As String) As Boolean
Return (Not String.IsNullOrEmpty(s)) AndAlso Char.IsDigit(s(0))
End Function
Public Function StartsWithDigit(ByVal s As String) As Boolean
Return s Like "#*"
End Function
If I were you I will use
Dim bIsNumeric = IsNumeric(sValue.Substring(0,1))
and not
Dim sValueAsArray = sValue.ToCharArray()
It does not matter what you use, both will yield the same result,
but having said that; Dim sValueAsArray = sValue.ToCharArray() will use more memory & Dim bIsNumeric = IsNumeric(sValue.Substring(0,1)) will use less resources. though both of them are negligible
It is more of a suggestion of programming practice than anything else.
Char.IsNumber(c)
More details here: https://msdn.microsoft.com/en-us/library/yk2b3t2y(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
The VB.Net code that is equivalent to your Java code can be done using following lines
Dim c = sText(0)
bIsDigit = (c >= "0" AndAlso c <= "9")
where
Dim bIsDigit As Boolean
Dim sText as String = "2 aeroplanes" 'example for test
But, there exist also other solutions
bIsDigit = Char.IsDigit(c)
bIsDigit = Char.IsNumber(c)
bIsDigit = Information.IsNumeric(c)
and when sText is an empty string, you can also use one of following lines
Dim c = Mid(sText, 1, 1)
Dim c = (sText & "-")(0)
Dim c = Strings.Left(sText, 1)
Dim c As Char = sText
But, for me, the best solution is
bIsDigit = Char.IsDigit(Mid(sText, 1, 1))
or
bIsDigit = Char.IsDigit(sText(0))
if you are sure that sText is not empty.
And the shorter (but tricky) solution is
bIsDigit = Char.IsDigit(sText)
In this last line, first character of sText is implicitely converted to Char.

Resources