find with how many digits array is filled? - c#

Let's say I have array of bytes
byte[] arr = new byte[16];
and I filled only 10 of those 16 bytes
arr[0] = 1;
arr[1] = 1;
arr[2] = 2;
arr[3] = 3;
arr[4] = 4;
arr[5] = 5;
arr[6] = 6;
arr[7] = 7;
arr[8] = 8;
arr[9] = 9;
arr[10] = 1;
the problem is that user can input up to 10 digits, and the last digit could be 0
How can I find how many digits my array holds, since arr.Length and arr.Count() will give 16 but I need to know that it's 10?

I think you'd be better off using a generic List. Then you can use the Count property to get the correct number of items.
List<byte> arr = new List<byte>();
arr.Add(1);
arr.Add(2);
arr.Add(3);
arr.Add(4);
arr.Add(5);
int count = arr.Count; // returns 5;
byte[] myArray = arr.ToArray(); // returns byte array
UPDATE
If an array is your only option and you cannot switch to a List<T> then you are out of luck. The problem is, by default, C# will initialize each byte in the array to 0. So as soon as the compiler gets to the new byte[16]; initialization, the entire byte array is filled with 0's. Once this happens, there is no way to know if the 0 is the default value or if its a valid value. If there is a number between 0 and 255 that you 100% know will not be used, you could initialize the array with that number and get a count of each element != to that number.
Another thing you can do though is you can just initialize the array to one byte (e.g. new byte[1]) and each time you need more elements, resize the array an additional byte. Then you can use the standard Length property to see how many are filled.

Well if "0" means the item isn't filled (which means you can't use 0 as a valid entry) you could use:
int numFilled = arr.Count(b => b != 0);
Otherwise you're going to have to use a "magic" number (e.g. 255) to indicate an "unused" item.
Either way it's not foolproof. If there's not a reason to use a fixed-length array then I'd suggest using a different structure like List<byte> which can be filled dynamically and easily converted to an array.

int count = arr.Where(item => item != 0).Count();
Or
int count = arr.Count(item => item != 0);
[EDIT] As Jon Skeet says above, this assumes that you did not fill any of the entries with 0.

Related

Array of bytes[] has no values when is converted from int[]

I'm passing int[] array that hold image, later I want to convert it to bytes[] and save the image to local path. However, I notice that the bytePic[] length is equal to int[] arrPic just the values are missing. There is a screenshot below:
Below is the entire function:
public string ChangeMaterialPicture(int[] arrPic, int materialId,string defaultPath)
{
var material = _warehouseRepository.GetMaterialById(materialId);
if(material is not null)
{
// Convert the Array to Bytes
byte[] bytePic = new byte[arrPic.Length];
for(var i = 0; i < arrPic.Length; i++)
{
AddByteToArray(bytePic, Convert.ToByte(arrPic[i]));
}
// Convert the Bytes to IMG
string filename = Guid.NewGuid().ToString() + "_.png";
System.IO.File.WriteAllBytes(#$"{defaultPath}\materials\{material.VendorId}\{filename}", bytePic);
// Update the Image
material.Picture = filename;
_warehouseRepository.UpdateMaterial(material);
return material.Picture;
}
else
{
return String.Empty;
}
}
public byte[] AddByteToArray(byte[] bArray, byte newByte)
{
byte[] newArray = new byte[bArray.Length + 1];
bArray.CopyTo(newArray, 1);
newArray[0] = newByte;
return newArray;
}
You are creating the new array newArray in AddByteToArray and return it. But at the call site you are never using this returned value and the bytePic array remains unchanged.
The code in AddByteToArray makes no sense. Why create a new array when the intention was to insert one byte into an existing array? What you need to do is to cast the int into byte. Simply write:
byte[] bytePic = new byte[arrPic.Length];
for (int i = 0; i < arrPic.Length; i++)
{
bytePic[i] = (byte)arrPic[i];
}
And delete the method AddByteToArray.
This assumes that every value in the int array is in the range 0 to 255 and therefore fits into one byte.
There are different ways to do this. With LINQ you could also write:
byte[] bytePic = arrPic.Select(i => (byte)i).ToArray();
I would assume your original array uses a int to represent a full RGBA-pixel, since 32bit per pixel mono images are very rare in my experience. And if you do have such an image, you probably want to be more intelligent in how you do this conversion. The only time just casting int to bytes would be a good idea is if you are sure only the lower 8 bits are used, but if that is the case, why are you using an int-array in the first place.
If you actually have RGBA-pixles you do not want to convert individual int-values to bytes, but rather convert a single int value to 4 bytes. And this is not that difficult to do, you just need to use the right methods. The old school options is to use Buffer.BlockCopy.
Example:
byte[] bytePic = new byte[arrPic.Length * 4];
Buffer.BlockCopy(arrPic, 0, bytePic, 0, bytePic.Length);
But if your write-method accepts a span you might want to just convert your array to a span and cast this to the right type, avoiding the copy.

Find remaining elements in the sequence

everyone. I've this small task to do:
There are two sequences of numbers:
A[0], A[1], ... , A[n].
B[0], B[1], ... , B[m].
Do the following operations with the sequence A:
Remove the items whose indices are divisible by B[0].
In the items remained, remove those whose indices are divisible by B[1].
Repeat this process up to B[m].
Output the items finally remained.
Input is like this: (where -1 is delimiter for two sequences A and B)
1 2 4 3 6 5 -1 2 -1
Here goes my code (explanation done via comments):
List<int> result = new List<int>(); // list for sequence A
List<int> values = new List<int>(); // list for holding value to remove
var input = Console.ReadLine().Split().Select(int.Parse).ToArray();
var len = Array.IndexOf(input, -1); // getting index of the first -1 (delimiter)
result = input.ToList(); // converting input array to List
result.RemoveRange(len, input.Length - len); // and deleting everything beyond first delimiter (including it)
for (var i = len + 1; i < input.Length - 1; i++) // for the number of elements in the sequence B
{
for (var j = 0; j < result.Count; j++) // going through all elmnts in sequence A
{
if (j % input[i] == 0) // if index is divisible by B[i]
{
values.Add(result[j]); // adding associated value to List<int> values
}
}
foreach (var value in values) // after all elements in sequence A have been looked upon, now deleting those who apply to criteria
{
result.Remove(value);
}
}
But the problem is that I'm only passing 5/11 tests cases. The 25% is 'Wrong result' and the rest 25% - 'Timed out'. I understand that my code is probably very badly written, but I really can't get to understand how to improve it.
So, if someone more experienced could explain (clarify) next points to me it would be very cool:
1. Am I doing parsing from the console input right? I feel like it could be done in a more elegant/efficient way.
2. Is my logic of getting value which apply to criteria and then storing them for later deleting is efficient in terms of performance? Or is there any other way to do it?
3. Why is this code not passing all test-cases or how would you change it in order to pass all of them?
I'm writing the answer once again, since I have misunderstood the problem completely. So undoubtly the problem in your code is a removal of elements. Let's try to avoid that. Let's try to make a new array C, where you can store all the correct numbers that should be left in the A array after each removal. So if index id is not divisible by B[i], you should add A[id] to the array C. Then, after checking all the indices with the B[i] value, you should replace the array A with the array C and do the same for B[i + 1]. Repeat until you reach the end of the array B.
The algorithm:
1. For each value in B:
2. For each id from 1 to length(A):
3. If id % value != 0, add A[id] to C
4. A = C
5. Return A.
EDIT: Be sure to make a new array C for each iteration of the 1. loop (or clear C after replacing A with it)

C# Random number doesn't Generate 0

I'm working on a football league fixture project on C# Console Application.
I'm trying to choose random teams from the array which contains the teams which plays at their home and away.
When I'm trying to generate 9 random numbers, only 8 numbers are generated and 0 are not, so the code can't break the for loop.
I suppose that the problem is that the if statement does not allow to generate the same number and int array's elements' default value is 0.
Here is the code and the output:
C# Code Output
int randomHome; //Random number genetator for choosing a random iteration value from home array which containss the teams which plays at their home
int randomAway; //Random number genetator for choosing a random iteration value from awayarray which containss the teams which plays at away
Random randomNum = new Random();
int[] randomHomeNumArray = new int[home.Length]; //array will hold the randomHome values and home array is the array which is holding the team's iteration values which plays at their home
int[] randomAwayNumArray = new int[away.Length]; //array will hold the randomAway values and away array is the array which is holding the team's iteration values which plays at away
for (int homeArrayCounter = 0; homeArrayCounter < randomHomeNumArray.Length; homeArrayCounter++)
{
randomHome = randomNum.Next(home.Length)
if (!randomHomeNumArray.Contains(randomHome) )
{
randomHomeNumArray[homeArrayCounter] = randomHome; //It will hold the randomHome values
Console.WriteLine(homeArrayCounter + ". iterasyon in Home " + randomHomeNumArray[homeArrayCounter]);
}
else
{
homeArrayCounter--;
}
}
Console.WriteLine("\n\n");
for (int awayArrayCounter = 0; awayArrayCounter < randomAwayNumArray.Length; awayArrayCounter++)
{
randomAway = randomNum.Next(randomAwayNumArray.Length);
if (!randomAwayNumArray.Contains(randomAway))
{
randomAwayNumArray[awayArrayCounter] = randomAway; //It holds the random valures from away array which contains the teams which plays at away
Console.WriteLine(awayArrayCounter + ". iterasyon in Away " + randomAwayNumArray[awayArrayCounter]);
}
else
{
awayArrayCounter--;
}
}
When you initalize an array, it has the value 0 by default for each index. When you are using the random number, it always skips 0 because it already exists.
You can try like this:-
for(int i= 0; i<randomHomeNumArray.Length; i++){
randomHomeNumArray[i] = -1;
}
for (int homeArrayCounter = 0; homeArrayCounter < randomHomeNumArray.Length; homeArrayCounter++)
{
do{
randomHome = randomNum.Next(home.Length);
} while(!randomHomeNumArray.Contains(randomHome));
randomHomeNumArray[homeArrayCounter] = randomHome; //It will hold the randomHome values
Console.WriteLine(homeArrayCounter + ". iterasyon in Home " + randomHomeNumArray[homeArrayCounter]);
}
It appears you're trying to just randomize arrays.
Try this instead:
Random randomNum = new Random();
int[] randomHomeNumArray = Enumerable.Range(0, home.Length).OrderBy(_ => randomNum.Next()).ToArray();
int[] randomAwayNumArray = Enumerable.Range(0, away.Length).OrderBy(_ => randomNum.Next()).ToArray();
That's it. Done.
Your problem is the default initialization of your arrays:
int[] randomHomeNumArray = new int[home.Length];
This creates an array filled with 0s, because 0 is the default value for int.
So your if condition
if (!randomHomeNumArray.Contains(randomHome))
is always false for 0 because 0 is already contained in the array.
You may initialize your arrays instead like this:
int[] randomHomeNumArray = Enumerable.Repeat(-1, home.Length).ToArray();
So you fill it with -1 instead of 0 and your if condition works.
Because int is not a null-able data type, by default, an int[] gets initialized with zeroes. So even if you think it's an empty array, it's actually an array with all elements set to zero.
To rectify the problem, you can consider using an int?[] (null-able int array) instead. Or, you can initialize the array with either a negative integer or some integer greater than the maximum inclusive upper bound. Better yet, to achieve what you want, in a better way, use the solution provided by #Enigmativity, and mark his answer accepted, if it helped.

Cartesian product subset returning set of mostly 0

I'm trying to calculate
If we calculated every possible combination of numbers from 0 to (c-1)
with a length of x
what set would occur at point i
For example:
c = 4
x = 4
i = 3
Would yield:
[0000]
[0001]
[0002]
[0003] <- i
[0010]
....
[3333]
This is very nearly the same problem as in the related question Logic to select a specific set from Cartesian set. However, because x and i are large enough to require the use of BigInteger objects, the code has to be changed to return a List, and take an int, instead of a string array:
int PossibleNumbers;
public List<int> Get(BigInteger Address)
{
List<int> values = new List<int>();
BigInteger sizes = new BigInteger(1);
for (int j = 0; j < PixelArrayLength; j++)
{
BigInteger index = BigInteger.Divide(Address, sizes);
index = (index % PossibleNumbers);
values.Add((int)index);
sizes *= PossibleNumbers;
}
return values;
}
This seems to behave as I'd expect, however, when I start using values like this:
c = 66000
x = 950000
i = (66000^950000)/2
So here, I'm looking for the ith value in the cartesian set of 0 to (c-1) of length 950000, or put another way, the halfway point.
At this point, I just get a list of zeroes returned. How can I solve this problem?
Notes: It's quite a specific problem, and I apologise for the wall-of-text, I do hope it's not too much, I was just hoping to properly explain what I meant. Thanks to you all!
Edit: Here are some more examples: http://pastebin.com/zmSDQEGC
Here is a generic base converter... it takes a decimal for the base10 value to convert into your newBase and returns an array of int's. If you need a BigInteger this method works perfectly well with just changing the base10Value to BigInteger.
EDIT: Converted method to BigInteger since that's what you need.
EDIT 2: Thanks phoog for pointing out BigInteger is base2 so changing the method signature.
public static int[] ConvertToBase(BigInteger value, int newBase, int length)
{
var result = new Stack<int>();
while (value > 0)
{
result.Push((int)(value % newBase));
if (value < newBase)
value = 0;
else
value = value / newBase;
}
for (var i = result.Count; i < length; i++)
result.Push(0);
return result.ToArray();
}
usage...
int[] a = ConvertToBase(13, 4, 4) = [0,0,3,1]
int[] b = ConvertToBase(0, 4, 4) = [0,0,3,1]
int[] c = ConvertToBase(1234, 12, 4) = [0,8,6,10]
However the probelm you specifically state is a bit large to test it on. :)
Just calculating 66000 ^ 950000 / 2 is a good bit of work as Phoog mentioned. Unless of course you meant ^ to be the XOR operator. In which case it's quite fast.
EDIT: From the comments... The largest base10 number that can be represented given a particular newBase and length is...
var largestBase10 = BigInteger.Pow(newBase, length)-1;
The first expression of the problem boils down to "write 3 as a 4-digit base-4 number". So, if the problem is "write i as an x-digit base-c number", or, in this case, "write (66000^950000)/2 as a 950000-digit base 66000 number", then does that make it easier?
If you're specifically looking for the halfway point of the cartesian product, it's not so hard. If you assume that c is even, then the most significant digit is c / 2, and the rest of the digits are zero. If your return value is all zeros, then you may have an off-by-one error, or the like, since actually only one digit is incorrect.

How to put a specific byte from a byte array into a single byte

I have here a code where i set up a byte[1] to fill with a random byte which i then need to have this random generated byte from array [0] into a single byte to be able to compare it. (x is either 16 or 32, z is always staring with 0)
byte compareByte = 0x00;
byte[] rndByte = new byte[1];
byte[] buffer = new byte[x];
Random rnd = new Random();
for (int i = 0; i < dalmatinerRound.Length; i++)
{
while (z != x)
{
Application.DoEvents();
rnd.NextBytes(rndByte);
compareByte = (byte) rndByte[0];
if (compareByte == dalmatinerRound[i])
{
buffer[z] = compareByte;
z++;
if (z == x)
{
string str = Encoding.ASCII.GetString(buffer);
textPass.Text = str;
}
}
}
}
The problem is that compareByte is everytime "A". Regardless of how often i trie. Or even if i use the random byte to compare like:
if (rndByte[0] == dalmatinerRound[i])
it also returns "A". I can't get the byte from offset 0x00 of the array into a single byte.
But when i do some test and use:
string str = Encoding.ASCII.GetString(rndByte);
textPass.Text = str;
then it works and i get everytime a other letter.
To be more clear. This code will generate a Random passwort in length of 16 or 32 diggis. The dalmatinerRound is a Array of bytes in length of 101 contaning Alphabetical letters, lower and upper case, 0-9 and also !"ยง$%&/()=?*+}][{
thanks
Why not just use (byte)rnd.Next(0, 256)? In any case, rnd.NextBytes works just fine, and you get the first byte by using rndByte[0] just the way you did. In other words, the error must be somewhere else, not in the random generator or reading the byte value. Is this really the code, or have you made some changes? In any case, your code seems incredibly complicated and wasteful. You should probably just use your array of allowable values (no need to have it a byte array, chars are more useful) and use rnd.Next(0, dalmatinerRound.Length); to get a random allowed character.
What your code actually does is that it loops until you get a "random" byte... which is equal to (byte)'A'. Your loops are all wrong. Instead, you can use this:
StringBuilder pwd = new StringBuilder(wantedLength);
for (var i = 0; i < wantedLength; i++)
pwd.Append(dalmatinerRound[rnd.Next(0, dalmatinerRound.Length)]);
And there you have your random password :)
This expects that dalmatinerRound is an array of strings, which is quite useful anyway, so you should do that.
You're looping over the array of eligible characters, I assume starting "ABC...", and for each of those doing something. With your while loop you're trying to generate a count of x bytes in your buffer, but you don't stop until this is done - you never get a chance to increment i until you finish filling up the buffer.
You're also generating a random byte and only adding it to your buffer if it happens to be the current "candidate" character in dalmatinerRound. So the buffer sloooowly fills up with "A" characters. Then once this is full, the next time i is incremented, the while loop immediately exits, so no other characters are tried.
You should instead loop over the character index i in the target buffer, generating one random character in each iteration - just think how you would go about this process by hand.
It looks like your for loop is in the wrong place. Currently, the whole password is generated on the first (and presumably the only) iteration of the for loop. That means your comparison only ever compares the random byte to the first entry in dalmatinerRound, which is presumably the letter A.
You need to put the for loop inside the while loop, so that each random byte gets compared to every element of dalmatinerRound. (Make sure you put the loop after you generate the random byte!)
As a side note, there are much better ways of generating what you need. Since you have an array of all valid characters, you could just pick a random element from that to get a password digit (i.e. generate a random number between 0 and the length of the array).

Categories

Resources