So I have tried different types of visual basic code for this problem that i'm trying to solve but non of them is working :(
I have a jagged array for example {{1 10 20 50 53};{5 15 25 55}}
and I want to convert this information in a binary matrix given the condition that each array in the jagged array corresponds to a row, and the element in it corresponds to a column number. Am I being clear?
The matrix has the same rows as the number of arrays in the jagged array 2, but the columns in the matrix can go for example till 200.
1 0 ... 1 ... 1 ... 1 .. 1..................0
0 0 ... 1 ... 1 ... 1 .... 1 ...............0
My last attempt was this one:
For a = 0 To noRows - 1
For b = 0 To noCols - 1
Do While d < jarray(a).GetUpperBound(0)
If array(a)(d) = b Then
matrix(a, b) = 1
Exit Do
Else
matrix(a, b) = 0
d += 1
End If
Loop
Next
Next
What should I do?
When you make a new array its values are automatically initialised to the default value of the type of variable in the array - for an Integer, that is 0. So you don't need to do the setting to zero unless there is something else that isn't shown in the question.
You have the indexes of the locations which need to be set to 1, so you can do that directly:
Option Infer On
Option Strict On
Module Module1
Sub Main()
'Dim jArray = {New Integer() {1, 10, 20, 50, 53}, New Integer() {5, 15, 25, 55}}
Dim jArray = {New Integer() {1, 3, 4}, New Integer() {2, 5, 6, 7, 9}}
' find the number of columns needed for the resultant array
Dim nCols = jArray.Max(Function(r) r.Max())
' find the number of rows needed for the resultant array
Dim nRows = jArray.GetUpperBound(0) + 1
' the resultant array is automatically initialised to zeros
Dim matrix(nRows, nCols) As Integer
' fill in the ones as specified by the locations in jArray:
For i = 0 To nRows - 1
For j = 0 To jArray(i).GetUpperBound(0)
matrix(i, jArray(i)(j) - 1) = 1
Next
Next
' show the resultant array:
For i = 0 To nRows - 1
For j = 0 To nCols - 1
Console.Write(matrix(i, j) & If(j < nCols - 1, ", ", ""))
Next
Console.WriteLine()
Next
Console.ReadLine()
End Sub
End Module
Outputs:
1, 0, 1, 1, 0, 0, 0, 0, 0
0, 1, 0, 0, 1, 1, 1, 0, 1
I know that there have been a few similar questions to this but there still doesn't seem to be a definitive answer to this so I will ask it..
I have an array of values and am trying to find the correct values that will sum to a limit value or the closest it can get (without exceeding it) from any given combination.
Using this answer https://stackoverflow.com/questions/23168934/calculating-minimal-subset-with-given-sum I have this:
def getLimitArr(arr: Array[Int], limit: Int): Unit = {
scala.util.Sorting.quickSort(arr) // Array(2, 3, 4, 5, 11, 34)
var sum = 0L
var i = arr.length-1
val arr2 = ArrayBuffer[Integer]()
while (i >= 0 && sum < limit) {
if(sum + arr(i)<=limit) {
sum += arr(i)
arr2 += arr(i)
}
i -= 1 // 6, 5, 4, 3, 2, 1
}
println(arr2.mkString(", ") + " = " + sum)
}
And calling it using this in the main method:
val arr = Array(3, 34, 4, 11, 5, 2)
getLimitArr(arr, 9)
Which returns:
println(arr2.mkString(", ") + " = " + sum) // 5, 4 = 9
This is good but only if the values (that make up the sum) can be made from the highest value that is lower than the limit; in this example 5 - which works with this array as we can see. But if the limit value was 12 (getLimitArr(arr, 12)) with this array then it would return 11 = 11 rather than using 5 + 4 + 3.
I have done this using subsets but when the array is more than 10 I get the memory heap error as it is formulating all of the combinations before being able to obtain the answer.
So how would we do this by being memory efficient, using the current format or taking advantage of Scala's functional programming capabilities?
Recursion is often useful when we want to terminate as soon as the first correct answer is found.
def getLimit(nums: Array[Int], limit: Int): Array[Int] = {
val subset = nums.filter(limit.>=)
if (subset.isEmpty) Array()
else (1 to subset.length).flatMap(subset.combinations)
.find(_.sum == limit)
.fold(getLimit(subset, limit-1))(identity)
}
getLimit(Array(3, 34, 4, 11, 5, 2), 5) // res0: Array[Int] = Array(5)
getLimit(Array(3, 34, 4, 11, 5, 2), 9) // res1: Array[Int] = Array(4, 5)
getLimit(Array(3, 34, 4, 11, 5, 2), 12) // res2: Array[Int] = Array(3, 4, 5)
getLimit(Array(3, 34, 4, 11, 5, 2), 24) // res3: Array[Int] = Array(3, 4, 11, 5)
Note that the last one sums to 23 because there is no combination that sums to 24.
update
A better shortcut added and the method is now tail recursive.
def getLimit(nums: Array[Int], limit: Int): Array[Int] = {
val subset = nums.filter(limit.>=)
if (subset.sum <= limit) subset
else {
val res = (1 to subset.length).view
.flatMap(subset.combinations)
.find(_.sum == limit)
if (res.isEmpty) getLimit(subset, limit-1)
else res.get
}
}
I have two arrays
x = [1 1 1 0 2 3 1 1]
y = [1 2 3 4 5 6 7 8]
How to calculate the sum of y's elements for all x(i) = 1 to get the result 1+2+3+7+8 ?
I have used for loop and if then method to calculate the sum value like this
if x(i) = 1 then sum = sum + y(i)
Have other methods to get the results (sum, average, count ...) ?
Thank you.
Since you only want to sum the numbers in y corresponding to 1s in x, but not 0s in x, you can multiply x * y which looks a bit cleaner than the If. Here are a few ways
Dim x = {1, 1, 1, 0, 0, 0, 1, 1}
Dim y = {1, 2, 3, 4, 5, 6, 7, 8}
' using a for loop
Dim sum1 As Integer = 0
For i = 0 To x.Length - 1
sum1 += If(x(i) = 1, 1, 0) * y(i)
Next
Console.WriteLine(sum1)
' using LINQ #1
Dim sum2 As Integer = x.Select(Function(i, index) If(i = 1, 1, 0) * y(index)).Sum()
Console.WriteLine(sum2)
' using LINQ #2
Dim sum3 As Integer = x.Zip(y, Function(x1, y1) If(x1 = 1, 1, 0) * y1).Sum()
Console.WriteLine(sum3)
' using LINQ #3
Dim sum4 As Integer = Enumerable.Range(0, x.Length).Sum(Function(i) If(x(i) = 1, 1, 0) * y(i))
Console.WriteLine(sum4)
Console.ReadLine()
The For is very clear so I don't know why you wouldn't use it, but you can use LINQ for this as well:
Sub Main
Dim x = {1, 1, 1, 0, 2, 3, 1, 1}
Dim y = {1, 2, 3, 4, 5, 6, 7, 8}
Dim sum = y.Where(Function(v, i) x(i) = 1).Sum()
Console.WriteLine("Sum is {0}", sum)
End Sub
Prints
Sum is 21
I have an Array of chars, which is completely random except that every character occurs at most once.
I also have a string containing only characters that are present in the array. I want this string to be "counted upwards" (if that makes sense), like "111" becomes "112", or "aaa" becomes "aab".
Let´s say the Array of chars contains 1, 2, and 3. The example above works, but when the string is "333" (should become "1111"), my function returns an empty - or wrong - string.
If I call the function again, providing the wrong string, after a few times it returns the correct value ("1111").
Why does this happen?
This is my function:
Public Function getNextString(ByVal currentStr As String, ByVal pattern() As Char) As String
'currentStr is the string which I want to count upwards, pattern() is the array of chars
Dim nextStr As String = ""
Dim currentStrArray() As Char = currentStr.ToCharArray
Dim currenStrPosition As Integer = currentStrArray.Length - 1
Dim finished As Boolean = False
Do Until finished = True
Dim newPosition As Integer = getPositionInArray(currentStrArray(currentStrPosition)) 'this is a custom function, should be self-explaining
If newPosition = Nothing Then Return Nothing
newPosition += 1
Try
currentStrArray(currenStrPosition) = pattern(newPosition)
finished = True
Catch ex As IndexOutOfRangeException
currentStrArray(currentStrPosition) = pattern(0)
currentStrPosition -= 1
End Try
If currentStrPosition < 0 Then
nextStr = pattern(0)
finished = True
End If
Loop
For i As Integer = 0 To currentStrArray.Length - 1
nextStr = nextStr & currentStrArray(i)
Next
Return nextStr
End Function
Any ideas?
EDIT:
As an example, I have the array {"1","2","3"}. My string is first "111". I want to test these strings hashsums. After testing that string, I need the next string, "112". Then, "113", "121", "122", and so on. When the string reaches "333" and the string is not the one I'm looking for, it was obviously no string with only 3 characters (all 3-character-combinations possible with the array have been tried). So I need to start again using 4 characters. That´s why "333" is supposed to become "1111".
Hope this helps.
EDIT #2:
I found the error. I redimensioned my array incorrectly, so the last index was empty. This made my strings look weird. Thank you all for your working solutions, have a good day!
Well, I would convert to a number, add 1 and then convert back to a string.
Convert the string to a number:
Function ConvertStringToNumber(input As String, pattern As Char()) As Integer
Dim number As Integer = 0
Dim charDigits = pattern.ToList()
Dim numberBase = charDigits.Count
For i As var = 0 To input.Length - 1
Dim digit = charDigits.IndexOf(input(input.Length - 1 - i))
If digit <> -1 Then
number += digit * CInt(Math.Pow(numberBase, i))
End If
Next
Return number
End Function
Convert the number back to a string:
Function convertNumberToString(number As Integer, pattern As Char()) As String
Dim charDigits = pattern.ToList()
Dim numberBase = charDigits.Count
Dim buffer = New Stack(Of Char)()
'var j = buffer.Length;
While number > 0
buffer.Push(charDigits(number Mod numberBase))
number = number / numberBase
End While
Dim sb = New StringBuilder()
While buffer.Count > 0
sb.Append(buffer.Pop())
End While
Return sb.ToString()
End Function
Now that you have conversion functions, all you have to do is something like this:
Function getNextString(ByVal currentStr As String, ByVal pattern() As Char) As String
Dim number = ConvertStringToNumber(currentStr, pattern)
number += 1
Return convertNumberToString(number, pattern)
End Function
If I understand correctly you want to increment in a specific base (length of your array). What you need is a mapping function that maps your array chars to their respective numbers, then convert from your base to decimal, increment, convert back and remap.
Can you check if this link helps? Quickest way to convert a base 10 number to any base in .NET?
I just wrote the following in c#, it seems to work.
static void Main(string[] args)
{
char[] definition = new char[] { 'a', 'b', 'c', 'd', '9', 'x', 'y', 'z', '1', '2', '3'};
string helperstring = new String(definition);
int basenumber = definition.Length;
string mynumberasstring = "333";
Console.WriteLine(mynumberasstring);
int correspondingdecimal = 0;
for (int i = 0; i < mynumberasstring.Length; i++)
{
char x = mynumberasstring[mynumberasstring.Length - i - 1];
int index = helperstring.IndexOf(x);
int magnitude = 1;
for (int j = 0; j < i; j++)
magnitude *= basenumber;
Console.WriteLine(x + " -> " + index);
correspondingdecimal += magnitude * index;
}
Console.WriteLine(correspondingdecimal + " -> " + ++correspondingdecimal);
List<int> indicesofnewnumber = new List<int>();
int newmagnitude = basenumber;
while(correspondingdecimal > 0)
{
int div = correspondingdecimal / basenumber;
int remainder = correspondingdecimal % basenumber;
Console.WriteLine("{0} -> {1} ; {2}", correspondingdecimal, div, remainder);
indicesofnewnumber.Add(remainder);
correspondingdecimal = div;
}
string newnumberasstring = "";
for (int i = 0; i < indicesofnewnumber.Count; i++)
newnumberasstring += definition[indicesofnewnumber[indicesofnewnumber.Count - 1 - i]];
Console.WriteLine(newnumberasstring);
Console.ReadLine();
}
Here's the smallest code that I can think of to convert a number into an arbitrary base with arbitrary digits:
Dim convert As Func(Of Integer, Char(), String) = Nothing
convert = Function (n, cs) _
If(n \ cs.Length = 0, "", convert(n \ cs.Length, cs)) + cs(n Mod cs.Length)
So, to convert 4 to binary I could do convert(4, { "0"c, "1"c }) and I would get 100.
As a sanity check if I view the first 32 (starting from zero) binary numbers using String.Join(", ", Enumerable.Range(0, 32).Select(Function (n) convert(n, { "0"c, "1"c }))) and I get this:
0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111, 10000, 10001, 10010, 10011, 10100, 10101, 10110, 10111, 11000, 11001, 11010, 11011, 11100, 11101, 11110, 11111
Or the first 102 decimal numbers starting from zero with String.Join(", ", Enumerable.Range(0, 102).Select(Function (n) convert(n, "0123456789".ToCharArray()))) I get this:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101
So I can now use the same kind of code to get the first 50 numbers from the digits { "1"c, "2"c, "3"c } using String.Join(", ", Enumerable.Range(0, 50).Select(Function (n) convert(n, "123".ToCharArray()))) and I get this:
1, 2, 3, 21, 22, 23, 31, 32, 33, 211, 212, 213, 221, 222, 223, 231, 232, 233, 311, 312, 313, 321, 322, 323, 331, 332, 333, 2111, 2112, 2113, 2121, 2122, 2123, 2131, 2132, 2133, 2211, 2212, 2213, 2221, 2222, 2223, 2231, 2232, 2233, 2311, 2312, 2313, 2321, 2322
This is the correct "counting" using the digits { "1"c, "2"c, "3"c }. So, it would be correct to say that "333" + 1 = "2111" in this numbering system. This is the same as saying 999 + 1 = 1000 in our decimal system - it clearly doesn't go from 999 + 1 = 0000 which is the implication that "333" + 1 = "1111" would mean in this "123" system. Strictly speaking I should have written "333" + "2" = "2111" (since "2" represents 1).
If you want all combinations then you would need to pad the strings to the left with the "zero" character - in this case 1. Then this code:
String.Join(", ", _
Enumerable _
.Range(0, 500) _
.Select(Function (n) convert(n, "123".ToCharArray()).PadLeft(4, "1"c)) _
.Where(Function (x) x.Length = 4))
...gives the following 81 numbers:
1111, 1112, 1113, 1121, 1122, 1123, 1131, 1132, 1133, 1211, 1212, 1213, 1221, 1222, 1223, 1231, 1232, 1233, 1311, 1312, 1313, 1321, 1322, 1323, 1331, 1332, 1333, 2111, 2112, 2113, 2121, 2122, 2123, 2131, 2132, 2133, 2211, 2212, 2213, 2221, 2222, 2223, 2231, 2232, 2233, 2311, 2312, 2313, 2321, 2322, 2323, 2331, 2332, 2333, 3111, 3112, 3113, 3121, 3122, 3123, 3131, 3132, 3133, 3211, 3212, 3213, 3221, 3222, 3223, 3231, 3232, 3233, 3311, 3312, 3313, 3321, 3322, 3323, 3331, 3332, 3333
...and 81 is the total number of combinations as 3 x 3 x 3 x 3 = 81.
Here are the pair of functions to convert both ways:
Function Convert(number As Integer, digits As Char()) As String
Dim r = digits(number Mod digits.Length).ToString()
If number \ digits.Length <> 0 Then
r = Convert(number \ digits.Length, digits) + r
End If
Return r
End Function
Function Convert(number As String, digits As Char()) As Integer
Dim r = Array.IndexOf(digits, number(0))
If number.Substring(1).Length > 0 Then
r = r * digits.Length + Convert(number.Substring(1), digits)
End If
Return r
End Function