I am trying to calculate the average between all the numbers in a text file (every number is on a different line), no matter how many numbers there are. (Using VBScript)
Here is an example of the text file that I am trying to find the average between its numbers:
1
9
4
4
2
Also, sorry if I didn't word this well, it's my first question.
Can you try this script (I suppose that numbers are integer):
filename = "myfile.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(filename)
i = 0 'Elements number
sum = 0 'Sum of values
Do Until f.AtEndOfStream
sum = sum + CInt(trim(f.ReadLine))
i = i + 1
Loop
avg = sum / i 'Calculate the average
f.Close
Thank you
I have been trying to create this sequence:
2,7,17,37,67,...
I have to print first 10 numbers of the series.
To do this, I have created the following:
option explicit
Dim m,n,i,str,d
m=2
d=10
n=7
For i=0 to 10
n=n+d
d=d+10
str=str&n&vbcrlf
msgbox str
next
I am unable to print first two numbers, 2 and 7, as they are declared before the for loop. Even if I store them in a variable called str, they get printed after every execution. Is there a way to add these two and print them only once.
You could add your initial value of m to your string before you start running your sequence. Then, append the value of n to your string at the start of your loop instead of the end so that you capture n's initial value. For example:
m=2: d=10: n=7
str = m & vbCrLf ' Capture initial value of m
For i = 1 to 9
str = str & n & vbCrLf ' Capture initial value of n
n = n + d
d = d + 10
Next
MsgBox str
Note that you're only looping 9 times now, since you've already captured the first number in your sequence (m) prior to your loop.
I also moved MsgBox outside your loop so that it only appears once, after the full 10-number sequence has been generated.
I'm working with vb6 and I want to generate multiple randum numbers (the range from to is detirmend by user and also the number of generated answers) and send them to a listbox
But I don't want to duplicate generated numbers So..
I want before sending the generated number to the listbox to check if it already exists in the lisbox. if it already exists then generate another number if it does't then send it the the listbox
here is what I have till now
max and min are the range to chose numbers between
answers is the number of generated numbers
Randomize
For i = 1 To answers Step 1
generated = CInt(Int((max - min + 1) * Rnd() + min))
For n = 0 To List1.ListCount
If List1.List(n) <> gen Then
List1.AddItem (gen)
Else
If List1.List = gen Then
'I don't know what to do from here
'(how to go back to generate another number)
Next n
Next i
Thank you in advance
keep in minde I need to keep things simple
Thank you soo much
Use a boolean value to keep the result if same value generated is in list.
Private Sub AddRandomNumbers()
Dim blnIfFound As Boolean
Dim max As Integer
Dim min As Integer
Dim answers As Integer
max = 10
min = 1
answers = 5
Randomize
Do While List1.ListCount < answers
generated = CInt(Int((max - min + 1) * Rnd() + min))
blnIfFound = False
For n = 0 To List1.ListCount
If List1.List(n) = generated Then
blnIfFound = True
Exit For
End If
Next n
If blnIfFound = False Then List1.AddItem (generated)
Loop
End Sub
I'm trying to make a program that will generate a random number, and you have to guess it by typing in the answer. The problem is that it won't match the right number as shown.
Objects:
2 Labels, 1 textbox, 1 Command button
My first code:
Private Sub Command1_Click()
Dim Num, Random As Integer
Label2.Caption = ""
Num = Val(Text1.Text)
Randomize (Random)
Random = Val(Label1.Caption)
Label1.Caption = Int(10 * Rnd + 1)
For Num = 1 To Num
If Num = Random Then
Label2.Caption = "you won "
Else
End If
Next
End Sub
you don't need that for loop, its checking each number up to the number you guessed.
Private Sub Command1_Click()
Dim Num, Random As Integer
Label2.Caption = ""
Num = Val(Text1.Text)
Randomize (Random)
Random = Val(Label1.Caption)
Label1.Caption = Int(10 * Rnd + 1)
If Num = Random Then
Label2.Caption = "you won "
Else
End If
End Sub
to debug it put
If Num = Random Then
Label2.Caption = "you won "
Else
Label2.Caption = "The number " & Num & " Does not equal " & Random
End If
First of all, the current code will always result in number zero being the first "randomly" generated number. Second, the formula will produce a predictable random number sequence.
The issue behind this is that computers are not smart and cannot really create random numbers, that's why you need to "seed" them with Randomize to sort of "shake" the dice and come up with a different number. But, if you randomize with the same number, it will produce exactly the same sequence of "random" numbers.
For example, if you use your code, it will always produce the following sequence of numbers: 0, 8, 7, 5 ...
That's why you need to "seed" the random number with... a random number! LOL. But how do you get a random number? Technically, you can't, but you can cheat. You can do Randomize (Timer) or Randomize, which takes Timer as a parameter and what it does is "seeds" the random number generation with a number of seconds and milliseconds elapsed since midnight. So, the only time where you will get the same sequence of random numbers if you click the button to guess the random number every day at exactly the same second and millisecond.
You can try and expand on this theory by adding day, month or year - that would expand the "seed" exponentially and you will never see repeating sequence of random numbers, but it is extremely hard to do that because once you start playing around with large seed numbers you will encounter weird issues such as if you change a very large number by 1, it would still generate the same sequence of random numbers (in my test scenario, randomizing with any number in the range from 5969992 to 5969995 will result in the same sequence of random numbers: 9, 8, 6, 6, 1). This is probably a limitation of the Randomize function itself. Personally, I don't think its worth trying to go beyond seeding with timer.
Below is your code adjusted to generate a more "random" sequence of numbers:
Dim Num, Random As Integer
Label2.Caption = ""
Num = Val(Text1.Text)
Randomize
Label1.Caption = Int(10 * Rnd + 1)
Random = Val(Label1.Caption)
If Num = Random Then
Label2.Caption = "you won "
Else
Label2.Caption = "The number " & Num & " Does not equal " & Random
End If
dim num, Random as integer
label2.caption =""
num = val(text1.text)
randomize
label1.caption = int((10 +1-1)*rnd+1)
random = val(label1.caption)
if num = random then
label2.caption ="you won"
else
label2.caption = "Try again"
end if
I have to lists like these:
a = ["1a","2a","3a","4a","5a","6a","7a","8a","9a","10a","11a","12a","13a","14a"]
b = ["1b","2b","3b","4b","5b","6b","7b","8b","9b","10b","11b","12b","13b","14b"]
And what I want is to combine them, so that there is at least a difference of n elements between an element from a and it's corresponding element in b.
As an example, if my n is 10, and "3a" is in position 3 and "3b" is in position 5, that isn't a solution since there's only a distance of 2 between these corresponding elements.
I have already solved this for the purpose I want through a brute force method: shuffle the union of the two arrays and see if the constraint is met; if not, shuffle again and so on... Needless to say, that for 14 elements array, sometimes there is 5 to 10 second computation to yield a solution with a minimum distance of 10. Even though that's kind of ok for what I am looking for, I am curious about how I could solve this in a more optimized way.
I am currently using Python, but code in any language (or pseudo-code) is more than welcomed.
EDIT: The context of this problem is something like a questionnarie, in which around 100 participants are expected to join in. Therefore, I am not necessarily interested in all the solutions, but rather something like the first 100.
Thanks.
For your specific scenario, you could use a randomized approach -- though not as random as what you've already tried. Something like this:
start with a random permutation of the items in both lists
create a new permutation by creating a copy of the other and randomly swapping two items
measure the quality of the permutations, e.g., the sum of the distances of each pair of related items, or the minimum of such distances
if the quality of the new permutation is better than that of the original permutation, keep the new one, otherwise discard the new one and continue with the original permutation
repeat from 2. until each distance is at least 10 or until quality does not improve over a number of iterations
The difference to shuffling the whole list in each iteration (as in your approach) is that in each iteration the permutation can only get better, until a satisfying solution is found.
Each time you run this algorithm, the result will be slightly different, so you can run it 100 times for 100 different solutions. Of course, this algorithm does not guarantee to find a solution (much less all such solutions), but it should be fast enough so that you could just restart it in case it fails.
In Python, this could look somewhat like this (slightly simplified, but still working):
def shuffle(A, B):
# original positions, i.e. types of questions
kind = dict([(item, i) for i, item in list(enumerate(A)) + list(enumerate(B))])
# get positions of elements of kinds, and return sum of their distances
def quality(perm):
pos = dict([(kind[item], i) for i, item in enumerate(perm)])
return sum(abs(pos[kind[item]] - i) for i, item in enumerate(perm))
# initial permutation and quality
current = A + B
random.shuffle(current)
best = quality(current)
# improve upon initial permutation by randomly swapping items
for g in range(1000):
i = random.randint(0, len(current)-1)
j = random.randint(0, len(current)-1)
copy = current[:]
copy[i], copy[j] = copy[j], copy[i]
q = quality(copy)
if q > best:
current, best = copy, q
return current
Example output for print shuffle(a, b):
['14b', '2a', '13b', '3a', '9b', '4a', '6a', '1a', '8a', '5b', '12b', '11a', '10b', '7b', '4b', '11b', '5a', '7a', '8b', '12a', '13a', '14a', '1b', '2b', '3b', '6b', '10a', '9a']
As I understand from your question, it is possible to perform all the ordering by relying exclusively on the indices of the arrays (i.e., on pure integers) and thus the problem can be reduced to create (valid) ranges instead of analysing each element.
for each a <= total_items-n , valid b = if(a + n == total_items){total_items} else{[a + n, total_items]}
For example:
n = 10;
total_items = 15;
for a = 1 -> valid b = [11, 15]
for a = 2 -> valid b = [12, 15]
, etc.
This would be perfomed 4 times: forwards and backwards for a respect to b and the same for b respect to a.
In this way you would reduce the number of iterations to its minimum expression and would get, as an output, a set of "solutions" for each position, rather than a one-to-one binding (that is what you have right now, isn't it?).
If there are equivalents in Python to .NET's Lists and LINQ, then you may be able to directly convert the following code. It generates up to 100 lists really quickly: I press "debug" to run it and up pops a windows with the results in much less than a second.
' VS2012
Option Infer On
Module Module1
Dim minDistance As Integer = 10
Dim rand As New Random ' a random number generator
Function OkToAppend(current As List(Of Integer), x As Integer) As Boolean
' see if the previous minDistance values contain the number x
Return Not (current.Skip(current.Count - minDistance).Take(minDistance).Contains(x))
End Function
Function GenerateList() As List(Of String)
' We don't need to start with strings: integers will make it faster.
' The "a" and "b" suffixes can be sprinkled on at random once the
' list is created.
Dim numbersToUse() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
Dim pool As New List(Of Integer)
' we need all the numbers twice
pool.AddRange(numbersToUse)
pool.AddRange(numbersToUse)
Dim newList As New List(Of Integer)
Dim pos As Integer
For i = 0 To pool.Count - 1
' limit the effort it puts in
Dim sanity As Integer = pool.Count * 10
Do
pos = rand.Next(0, pool.Count)
sanity -= 1
Loop Until OkToAppend(newList, pool(pos)) OrElse sanity = 0
If sanity > 0 Then ' it worked
' append the value to the list
newList.Add(pool(pos))
' remove the value which has been used
pool.RemoveAt(pos)
Else ' give up on this arrangement
Return Nothing
End If
Next
' Create the final list with "a" and "b" stuck on each value.
Dim stringList As New List(Of String)
Dim usedA(numbersToUse.Length) As Boolean
Dim usedB(numbersToUse.Length) As Boolean
For i = 0 To newList.Count - 1
Dim z = newList(i)
Dim suffix As String = ""
If usedA(z) Then
suffix = "b"
ElseIf usedB(z) Then
suffix = "a"
End If
' rand.Next(2) generates an integer in the range [0,2)
If suffix.Length = 0 Then suffix = If(rand.Next(2) = 1, "a", "b")
If suffix = "a" Then
usedA(z) = True
Else
usedB(z) = True
End If
stringList.Add(z.ToString & suffix)
Next
Return stringList
End Function
Sub Main()
Dim arrangements As New List(Of List(Of String))
For i = 1 To 100
Dim thisArrangement = GenerateList()
If thisArrangement IsNot Nothing Then
arrangements.Add(thisArrangement)
End If
Next
'TODO: remove duplicate entries and generate more to make it up to
' the required quantity.
For Each a In arrangements
' outputs the elements of a with ", " as a separator
Console.WriteLine(String.Join(", ", a))
Next
' wait for user to press enter
Console.ReadLine()
End Sub
End Module