Byte array percentage similarity - arrays

I am kinda new in VB.net; pretty much what I have been looking for is a way to calculate the similarity of a byte array. I have been able to determine whether they are equal or not, but I haven't figured out how to calculate how similar they are in percentage. Any idea is appreciated. Thanks! Leo.

The following function takes two Byte arrays as its arguments. If the arrays are not the same length, it throws an exception. Otherwise, it returns the fraction of the elements in one array that are equal to the element at the same position in the other array.
Function PercentAlike(array1() As Byte, array2() As Byte) As Double
If array1.Length <> array2.Length Then Throw New ArgumentException("Arrays must have the same length")
Dim same As Integer
For i As Integer = 0 To array1.Length - 1
If array1(i) = array2(i) Then same += 1
Next
Return same / array1.Length
End Function
[Added in response to the comment that the arrays may not be the same length]
If you need to calculate a percentage even if the arrays are of different lengths, you can use the following function. It returns the number of elements in one array that are equal to the element at the same position in the other array (ignoring the extra elements in the longer array) as a fraction of the number of elements in the longer array.
Function PercentAlike(array1() As Byte, array2() As Byte) As Double
Dim same As Integer
For i As Integer = 0 To Math.Min(array1.Length, array2.Length) - 1
If array1(i) = array2(i) Then same += 1
Next
Return same / Math.Max(array1.Length, array2.Length)
End Function

Related

Julia / Cellular Automata: efficient way to get neighborhood

I'd like to implement a cellular automaton (CA) in Julia. Dimensions should be wrapped, this means: the left neighbor of the leftmost cell is the rightmost cell etc.
One crucial question is: how to get the neighbors of one cell to compute it's state in the next generation? As dimensions should be wrapped and Julia does not allow negative indices (as in Python) i had this idea:
Considered a 1D CA, one generation is a one-dimensional array:
0 0 1 0 0
What if we create a two dimensional Array, where the first row is shifted right and the third is shifted left, like this:
0 0 0 1 0
0 0 1 0 0
0 1 0 0 0
Now, the first column contain the states of the first cell and it's neighbors etc.
i think this can easily be generalized for two and more dimensions.
First question: do you think this is a good idea, or is this a wrong track?
EDIT: Answer to first question was no, second Question and code example discarded.
Second question: If the approach is basically ok, please have a look at the following sketch:
EDIT: Other approach, here is a stripped down version of a 1D CA, using mod1() for getting neighborhood-indices, as Bogumił Kamiński suggested.
for any cell:
- A array of all indices
- B array of all neighborhood states
- C states converted to one integer
- D lookup next state
function digits2int(digits, base=10)
int = 0
for digit in digits
int = int * base + digit
end
return int
end
gen = [0,0,0,0,0,1,0,0,0,0,0]
rule = [0,1,1,1,1,0,0,0]
function nextgen(gen, rule)
values = [mod1.(x .+ [-1,0,1], size(gen)) for x in 1:length(gen)] # A
values = [gen[value] for value in values] # B
values = [digits2int(value, 2) for value in values] # C
values = [rule[value+1] for value in values] # D
return values
end
for _ in 1:100
global gen
println(gen)
gen = nextgen(gen, rule)
end
Next step should be to extend it to two dimensions, will try it now...
The way I typically do it is to use mod1 function for wrapped indexing.
In this approach, no matter what dimensionality of your array a is then when you want to move from position x by delta dx it is enough to write mod1(x+dx, size(a, 1)) if x is the first dimension of an array.
Here is a simple example of a random walk on a 2D torus counting the number of times a given cell was visited (here I additionally use broadcasting to handle all dimensions in one expression):
function randomwalk()
a = zeros(Int, 8, 8)
pos = (1,1)
for _ in 1:10^6
# Von Neumann neighborhood
dpos = rand(((1,0), (-1,0), (0,1), (0,-1)))
pos = mod1.(pos .+ dpos, size(a))
a[pos...] += 1
end
a
end
Usually, if the CA has cells that are only dependent on the cells next to them, it's simpler just to "wrap" the vector by adding the last element to the front and the first element to the back, doing the simulation, and then "unwrap" by taking the first and last elements away again to get the result length the same as the starting array length. For the 1-D case:
const lines = 10
const start = ".........#........."
const rules = [90, 30, 14]
rule2poss(rule) = [rule & (1 << (i - 1)) != 0 for i in 1:8]
cells2bools(cells) = [cells[i] == '#' for i in 1:length(cells)]
bools2cells(bset) = prod([bset[i] ? "#" : "." for i in 1:length(bset)])
function transform(bset, ruleposs)
newbset = map(x->ruleposs[x],
[bset[i + 1] * 4 + bset[i] * 2 + bset[i - 1] + 1
for i in 2:length(bset)-1])
vcat(newbset[end], newbset, newbset[1])
end
const startset = cells2bools(start)
for rul in rules
println("\nUsing Rule $rul:")
bset = vcat(startset[end], startset, startset[1]) # wrap ends
rp = rule2poss(rul)
for _ in 1:lines
println(bools2cells(bset[2:end-1])) # unwrap ends
bset = transform(bset, rp)
end
end
As long as only the adjacent cells are used in the simulation for any given cell, this is correct.
If you extend this to a 2D matrix, you would also "wrap" the first and last rows as well as the first and last columns, and so forth.

remove an item from an integer array

I'm trying to remove an element from an integer array given its index, are there any simple ways of accomplishing just that in VB.Net?
All I can find is .RemoveAt() for removing a string in an ArrayList, but none for an integer in an integer array.
Dim PossibleValues(8) As Integer
For x As Integer = 0 To 8
PossibleValues(x) = x + 1
Next
Added the code, don't think it entails much as I am now trying to find ways to remove an element from the array PossibleValues
The problem with removing an item from an array is that it is of fixed size. So The simplest way is to convert the array to a list, ToList(), and then do the RemoveAt and then, if you need to, convert it back to a new array with ToArray().
EDIT
Dim PossibleValues(8) As Integer
For x As Integer = 0 To 8
PossibleValues(x) = x + 1
Next
Dim tempList = PossibleValues.ToList()
tempList.RemoveAt(1)
PossibleValues = tempList.ToArray()

struggling summing my array

I am trying to fix a subroutine that creates an array of 10 Integers such that each element of the array stores the sum of its own index number and all previous indexes. (Indexes start at 1.) The values in the array would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55
For example, the value 6 in the 3rd element is the sum of the index values 1 + 2 + 3. At the end all I am doing is copying the contents of the array to the range A1:J1.
The code I have thus far goes as follows:
Sub SumNum()
Dim Ints(1 to 10) As Integer
Dim Sum As Integer
Dim i As Integer
i = 0
For i = LBound(Ints) to UBound(Ints)
Sum = i + Ints(i)
Range("A1").offset(0,1).Value = Sum
Next i
End Sub
It seems in theory I guess that it should work out since I have the loop going and having the sum pasted to each offset, however this sub is giving me errors and unable to perform. Any guidance will be appreciated!
Edit: when I run my code the only output is on B2 of the value 10. Strange!
Range("A1:J1").Formula = "=(COLUMN()*(COLUMN()+1))/2"
Two things to note here:
You can assign a range to an array directly without looping. That is, after computing your array, you can say myRange.Value = myArray. You need to transpose the array if the range is a column.
The above code exploits a known mathematical formula: 1+2+3+...+n = (n(n+1))/2. It didn't need to compute any array. The formula applies this equation and gets the index from the Column property of each cell.
Hope this helps.

Finding an average value using integer arrays

In my program I have designed it so that it reads from a file, parses the file for any integers and saves them to a sorted list. From that list I have then created three arrays which would each hold different values based off the values in the list except the values would go up by 1 for each array so:
Example Values:
array 1 will hold the regular values e.g. - 2,3,4,5
array 2 will hold the regular values (+1) - 3,4,5,6
array 3 will hold the regular values (+2) - 4,5,6,7
2,3,4 = 1st user's score
3,4,5 = 2nd user's score
4,5,6 = 3rd user's score
From this I now want to add these arrays together and divide by 3 to get the average results and then save and join the values with their corresponding user, however am not sure if I can add the arrays directly.
This is the code I have so far:
Dim basenum As New System.Collections.Generic.List(Of Integer)
Dim num As String
num = Regex.Replace(line, "\D+", "")
For Each lin As String In num
basenum.Add(Convert.ToInt32(lin))
Next
basenum.Sort()
basenum.Reverse()
For Each element As Integer In basenum
Console.WriteLine(element)
Next
Dim number1() As Integer
Dim number2() As Integer
Dim number3() As Integer
number1 = basenum.ToArray
For Each element As Integer In number1
Console.WriteLine(element)
Next
number2 = basenum.ToArray 'insert 2nd numbers into second array
For Each element As Integer In number2
element += 1
Console.WriteLine(element)
Next
number3 = basenum.ToArray 'insert 3rd numbers into third array
For Each element As Integer In number3
element += 2
Console.WriteLine(element)
Next
The numbers go into the arrays fine however am not sure how I can add the arrays together and calculate the average.
Any help would be appreciated guys :)

Trouble looping through a data file and storing integers in an array

I am having a problem with a loop. I am writing a program that loops through lottery drawings and does some different analysis' on the drawings. The problem I am having is since a loop is 0-based but there is no number 0 in lottery drawings I cant figure out how to start the loop at 1 instead of 0. Also, when I cut out an integer, if the integer is a single digit the loop doesn't see the zero before the single digit and counts all of the 0-9 in all of the integers. I am trying to grab an integer and then tick that element of the array. Here is the loop.
'Choices(59) is passed into the loop from a click event
Private Sub GetFrequency(Choices() As Integer)
Dim Size As Integer = UsersChosenHistory.Length() 'Size
Dim Number As Integer = 1
Dim Start As Integer = 0
Dim Finish As Integer = 3'Grab 3 chars, a space + 2 digit Integer
For i As Integer = 1 To Size - 1 Step 1
Number.ToString("d2")'I've also tried Number.ToString("D2") (Capitol D)
Number = UsersChosenHistory.Substring(Start, Finish) 'Grab an integer
Choices(Number) += "1" 'Store it in the corresponding array element
Start += 1
Next
End Sub
When running through the loop with the F11 key the single digits do not show the leading "0" even though the data file does include the "0", and as I mentioned above the array shows a "0" as the first digit in the frequence grid. I'm really confused with this loop, any help will be greatly appreciated. I'm just learning VB.Net and this has me stumped. Thanks in advance.
For i As Integer = 0 To Size - 1 Step 1
Number = int.Parse(UsersChosenHistory.Substring(i*3,3).Replace(" ",""))
Choices(Number) += "1"
Next
For the "0" issue, ignore it. Choices(0) will never be incremented.

Resources