Shifting a BitArray - c#

I'm currently trying to shift a BitArray while keeping its length. Since there's no built-in method I'm struggling to build one but can't make it work, unfortunatly.
My initial BitArray code sets a length of 421 for the BitArray.
var b = new BitArray(length: 421);
Than, I'm assigning some values for testing. For instance:
b.Set(0, true);
b.Set(1, true);
However, I can't figure out how to shift the bit array.
Attempts:
- I thought that I could convert it into long and than make the bit manipulation. However, long does not match my exact BitArray length, which results in errors later on when I apply bitwise operations on two BitArrays (my full requirements is (array1 |= array2 >> 20).
- I tried to convert the BitArray into byte[], do the manipulation and return it (see Bit shifting N bits):
public static byte[] ToBytesArray(this BitArray array, int startIndex, int count)
{
// Get the size of bytes needed to store all bytes
int bytesize = count / ByteLength;
// Any bit left over another byte is necessary
if (count % ByteLength > 0)
{
bytesize++;
}
// For the result
byte[] bytes = new byte[bytesize];
// Must init to good value, all zero bit byte has value zero
// Lowest significant bit has a place value of 1, each position to
// to the left doubles the value
byte value = 0;
byte significance = 1;
int bytepos = 0;
int bitpos = startIndex;
while (bitpos - startIndex < count)
{
// If the bit is set add its value to the byte
if (array[bitpos])
value += significance;
bitpos++;
if (bitpos % ByteLength == 0)
{
// A full byte has been processed, store it
// increase output buffer index and reset work values
bytes[bytepos] = value;
bytepos++;
value = 0;
significance = 1;
}
else
{
// Another bit processed, next has doubled value
significance *= 2;
}
}
return bytes;
}
public static BitArray ShiftLeft(this BitArray array, int bitcount)
{
byte[] value = array.ToBytesArray();
byte[] temp = new byte[value.Length];
if (bitcount >= 8)
{
Array.Copy(value, bitcount / 8, temp, 0, temp.Length - (bitcount / 8));
}
else
{
Array.Copy(value, temp, temp.Length);
}
if (bitcount % 8 != 0)
{
for (int i = 0; i < temp.Length; i++)
{
temp[i] <<= bitcount % 8;
if (i < temp.Length - 1)
{
temp[i] |= (byte)(temp[i + 1] >> 8 - bitcount % 8);
}
}
}
return new BitArray(temp);
}
However, byte's length is 8, which can't fit well with my length too. The result is 416 or 424 (another byte) instead of 421.
Finally, I tried the "primitive" way:
for (int i = 0; i < bitcount; i++)
{
var lastValue = array[0];
for (var j = 0; j < array.Length - 1; j++)
{
array[j] = array[j + 1];
}
array[array.Length - 1] = lastValue;
}
I also check up SO (e.g. BitArray - Shift bits) but nothing worked for me.
Any help will be very appreciated!

Still not 100% sure what's the issue. Here's a naive implementation:
void Main()
{
// Creates and initializes a BitArrays of size 7 (you have 421).
bool[] myBools = new bool[7] { true,false,false,true,true,false,true };
BitArray myBA1 = new BitArray(myBools );
PrintBitArray(myBA1); // 1001101
PrintBitArray(ShiftRight(myBA1)); // 0100110
PrintBitArray(ShiftLeft (myBA1)); // 0011010
}
BitArray ShiftRight(BitArray aSource) {
bool[] new_arr = new bool[( aSource.Count)];
for (int i = 0; i < aSource.Count -1; i++)
new_arr[i+1] = aSource[i];
return new BitArray(new_arr);
}
BitArray ShiftLeft(BitArray aSource) {
bool[] new_arr = new bool[( aSource.Count)];
for (int i = 0; i < aSource.Count -1; i++)
new_arr[i] = aSource[i+1];
return new BitArray(new_arr);
}
string PrintBitArray(BitArray aSource) {
StringBuilder sb = new StringBuilder();
foreach (var bit in aSource)
{
sb.Append( (bool)bit ? 1 : 0 );
}
return sb.ToString();
}
Note how bits are copied in the loops, and that the third PrintBitArray is done on the original input, not on the outcome of the second.

public static bool[] Left_shiftBitArray(bool[] Array, int count)
{
Array = BitArray_LRotat(Array, count);
for (int i=Array.GetLength(0)-1; i>=(Array.GetLength(0)-count); i--)
{
Array[i] = false;
}
return Array;
}
public static bool[] BitArray_LRotat(bool[] input, int x)
{
//bool [] temp= new bool[input.Length];
bool[] final = new bool[input.Length];
for (int i = input.Length; i > x; i--)
{
final[i - x - 1] = input[i - 1];
}
for (int i = x; i > 0; i--)
{
final[(input.Length) - i] = input[x - i];
}
return final;
}

Related

Getting Time limit Exceed for last 3 Test Cases in a Program:C# [duplicate]

Given an array of n integers and a number, d, perform left rotations on the array. Then print the updated array as a single line of space-separated integers.
Sample Input:
5 4
1 2 3 4 5
The first line contains two space-separated integers denoting the respective values of n (the number of integers) and d (the number of left rotations you must perform).
The second line contains n space-separated integers describing the respective elements of the array's initial state.
Sample Output:
5 1 2 3 4
static void Main(String[] args)
{
string[] arr_temp = Console.ReadLine().Split(' ');
int n = Int32.Parse(arr_temp[0]);
int d = Int32.Parse(arr_temp[1]);
string[] arr = Console.ReadLine().Split(' ');
string[] ans = new string[n];
for (int i = 0; i < n; ++i)
{
ans[(i + n - d) % n] = arr[i];
}
for (int j = 0; j < n; ++j)
{
Console.Write(ans[j] + " ");
}
}
How to use less memory to solve this problem?
This will use less memory in most cases as the second array is only as big as the shift.
public static void Main(string[] args)
{
int[] n = { 1, 2, 3, 4, 5 };
LeftShiftArray(n, 4);
Console.WriteLine(String.Join(",", n));
}
public static void LeftShiftArray<T>(T[] arr, int shift)
{
shift = shift % arr.Length;
T[] buffer = new T[shift];
Array.Copy(arr, buffer, shift);
Array.Copy(arr, shift, arr, 0, arr.Length - shift);
Array.Copy(buffer, 0, arr, arr.Length - shift, shift);
}
This problem can get a bit tricky but also has a simple solution if one is familiar with Queues and Stacks.
All I have to do is define a Queue (which will contain the given array) and a Stack.
Next, I just have to Push the Dequeued index to the stack and Enqueue the Popped index in the Queue and finally return the Queue.
Sounds confusing? Check the code below:
static int[] rotLeft(int[] a, int d) {
Queue<int> queue = new Queue<int>(a);
Stack<int> stack = new Stack<int>();
while(d > 0)
{
stack.Push(queue.Dequeue());
queue.Enqueue(stack.Pop());
d--;
}
return queue.ToArray();
}
Do you really need to physically move anything? If not, you could just shift the index instead.
Actually you asked 2 questions:
How to efficiently rotate an array?
and
How to use less memory to solve this problem?
Usually efficiency and low memory usage are mutually exclusive. So I'm going to answer your second question, still providing the most efficient implementation under that memory constraint.
The following method can be used for both left (passing negative count) or right (passing positive count) rotation. It uses O(1) space (single element) and O(n * min(d, n - d)) array element copy operations (O(min(d, n - d)) array block copy operations). In the worst case scenario it performs O(n / 2) block copy operations.
The algorithm is utilizing the fact that
rotate_left(n, d) == rotate_right(n, n - d)
Here it is:
public static class Algorithms
{
public static void Rotate<T>(this T[] array, int count)
{
if (array == null || array.Length < 2) return;
count %= array.Length;
if (count == 0) return;
int left = count < 0 ? -count : array.Length + count;
int right = count > 0 ? count : array.Length - count;
if (left <= right)
{
for (int i = 0; i < left; i++)
{
var temp = array[0];
Array.Copy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = temp;
}
}
else
{
for (int i = 0; i < right; i++)
{
var temp = array[array.Length - 1];
Array.Copy(array, 0, array, 1, array.Length - 1);
array[0] = temp;
}
}
}
}
Sample usage like in your example:
var array = Enumerable.Range(1, 5).ToArray(); // { 1, 2, 3, 4, 5 }
array.Rotate(-4); // { 5, 1, 2, 3, 4 }
Isn't using IEnumerables better? Since It won't perform all of those maths, won't allocate that many arrays, etc
public static int[] Rotate(int[] elements, int numberOfRotations)
{
IEnumerable<int> newEnd = elements.Take(numberOfRotations);
IEnumerable<int> newBegin = elements.Skip(numberOfRotations);
return newBegin.Union(newEnd).ToArray();
}
IF you don't actually need to return an array, you can even remove the .ToArray() and return an IEnumerable
Usage:
void Main()
{
int[] n = { 1, 2, 3, 4, 5 };
int d = 4;
int[] rotated = Rotate(n,d);
Console.WriteLine(String.Join(" ", rotated));
}
I have also tried this and below is my approach...
Thank you
public static int[] RotationOfArray(int[] A, int k)
{
if (A == null || A.Length==0)
return null;
int[] result =new int[A.Length];
int arrayLength=A.Length;
int moveBy = k % arrayLength;
for (int i = 0; i < arrayLength; i++)
{
int tmp = i + moveBy;
if (tmp > arrayLength-1)
{
tmp = + (tmp - arrayLength);
}
result[tmp] = A[i];
}
return result;
}
I have tried to used stack and queue in C# to achieve the output as follows:
public int[] rotateArray(int[] A, int rotate)
{
Queue<int> q = new Queue<int>(A);
Stack<int> s;
while (rotate > 0)
{
s = new Stack<int>(q);
int x = s.Pop();
s = new Stack<int>(s);
s.Push(x);
q = new Queue<int>(s);
rotate--;
}
return q.ToArray();
}
I've solve the challange from Hackerrank by following code. Hope it helps.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace ConsoleApp1
{
class ArrayLeftRotationSolver
{
TextWriter mTextWriter;
public ArrayLeftRotationSolver()
{
mTextWriter = new StreamWriter(#System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
}
public void Solve()
{
string[] nd = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nd[0]);
int d = Convert.ToInt32(nd[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] result = rotLeft(a, d);
mTextWriter.WriteLine(string.Join(" ", result));
mTextWriter.Flush();
mTextWriter.Close();
}
private int[] rotLeft(int[] arr, int shift)
{
int n = arr.Length;
shift %= n;
int[] vec = new int[n];
for (int i = 0; i < n; i++)
{
vec[(n + i - shift) % n] = arr[i];
}
return vec;
}
static void Main(string[] args)
{
ArrayLeftRotationSolver solver = new ArrayLeftRotationSolver();
solver.Solve();
}
}
}
Hope this helps.
public static int[] leftrotation(int[] arr, int d)
{
int[] newarr = new int[arr.Length];
var n = arr.Length;
bool isswapped = false;
for (int i = 0; i < n; i++)
{
int index = Math.Abs((i) -d);
if(index == 0)
{
isswapped = true;
}
if (!isswapped)
{
int finalindex = (n) - index;
newarr[finalindex] = arr[i];
}
else
{
newarr[index] = arr[i];
}
}
return newarr;
}
Take the Item at position 0 and add it at the end. remove the item at position 0. repeat n times.
List<int> iList = new List<int>();
private void shift(int n)
{
for (int i = 0; i < n; i++)
{
iList.Add(iList[0]);
iList.RemoveAt(0);
}
}
An old question, but I thought I'd add another possible solution using just one intermediate array (really, 2 if you include the LINQ Take expression). This code rotates to right rather than left, but may be useful nonetheless.
public static Int32[] ArrayRightRotation(Int32[] A, Int32 k)
{
if (A == null)
{
return A;
}
if (!A.Any())
{
return A;
}
if (k % A.Length == 0)
{
return A;
}
if (A.Length == 1)
{
return A;
}
if (A.Distinct().Count() == 1)
{
return A;
}
for (var i = 0; i < k; i++)
{
var intermediateArray = new List<Int32> {A.Last()};
intermediateArray.AddRange(A.Take(A.Length - 1).ToList());
A = intermediateArray.ToArray();
}
return A;
}
O(1) space, O(n) time solution
I think in theory this is as optimal as it gets, since it makes a.Length in-place swaps and 1 temp variable swap per inner loop.
However I suspect O(d) space solutions would be faster in real life due to less code branching (fewer CPU command pipeline resets) and cache locality (mostly sequential access vs in d element steps).
static int[] RotateInplaceLeft(int[] a, int d)
{
var swapCount = 0;
//get canonical/actual d
d = d % a.Length;
if(d < 0) d += a.Length;
if(d == 0) return a;
for (var i = 0; swapCount < a.Length; i++) //we're done after a.Length swaps
{
var dstIdx = i; //we need this becasue of ~this: https://youtu.be/lJ3CD9M3nEQ?t=251
var first = a[i]; //save first element in this group
for (var j = 0; j < a.Length; j++)
{
var srcIdx = (dstIdx + d) % a.Length;
if(srcIdx == i)// circled around
{
a[dstIdx] = first;
swapCount++;
break; //hence we're done with this group
}
a[dstIdx] = a[srcIdx];
dstIdx = srcIdx;
swapCount++;
}
}
return a;
}
If you take a look at constrains you will see that d <= n (number of rotations <= number of elements in array). Because of that this can be solved in 1 line.
static int[] rotLeft(int[] a, int d)
{
return a.Skip(d).Concat(a.Take(d)).ToArray();
}
// using the same same array, and only one temp variable
// shifting everything several times by one
// works, simple, but slow
public static int[] ArrayRotateLeftCyclical(int[] a, int shift)
{
var length = a.Length;
for (int j = 0; j < shift; j++)
{
int t = a[0];
for (int i = 0; i < length; i++)
{
if (i == length - 1)
a[i] = t;
else
a[i] = a[i + 1];
}
}
return a;
}
Let's say if I have a array of integer 'Arr'. To rotate the array 'n' you can do as follows:
static int[] leftRotation(int[] Arr, int n)
{
int tempVariable = 0;
Queue<int> TempQueue = new Queue<int>(a);
for(int i=1;i<=d;i++)
{
tempVariable = TempQueue.Dequeue();
TempQueue.Enqueue(t);
}
return TempQueue.ToArray();`
}
Let me know if any comments. Thanks!
This is my attempt. It is easy, but for some reason it timed out on big chunks of data:
int arrayLength = arr.Length;
int tmpCell = 0;
for (int rotation = 1; rotation <= d; rotation++)
{
for (int i = 0; i < arrayLength; i++)
{
if (arr[i] < arrayElementMinValue || arr[i] > arrayElementMaxValue)
{
throw new ArgumentException($"Array element needs to be between {arrayElementMinValue} and {arrayElementMaxValue}");
}
if (i == 0)
{
tmpCell = arr[0];
arr[0] = arr[1];
}
else if (i == arrayLength - 1)
{
arr[arrayLength - 1] = tmpCell;
}
else
{
arr[i] = arr[i + 1];
}
}
}
what about this?
public static void RotateArrayAndPrint(int[] n, int rotate)
{
for (int i = 1; i <= n.Length; i++)
{
var arrIndex = (i + rotate) > n.Length ? n.Length - (i + rotate) : (i + rotate);
arrIndex = arrIndex < 0 ? arrIndex * -1 : arrIndex;
var output = n[arrIndex-1];
Console.Write(output + " ");
}
}
It's very straight forward answer.
Main thing is how you choose the start index.
public static List<int> rotateLeft(int d, List<int> arr) {
int n = arr.Count;
List<int> t = new List<int>();
int h = d;
for (int j = 0; j < n; j++)
{
if ((j + d) % n == 0)
{
h = 0;
}
t.Add(arr[h]);
h++;
}
return t;
}
using this code, I have successfully submitted to hacker rank problem,
// fast and beautiful method
// reusing the same array
// using small temp array to store replaced values when unavoidable
// a - array, s - shift
public static int[] ArrayRotateLeftWithSmallTempArray(int[] a, int s)
{
var l = a.Length;
var t = new int[s]; // temp array with size s = shift
for (int i = 0; i < l; i++)
{
// save cells which will be replaced by shift
if (i < s)
t[i] = a[i];
if (i + s < l)
a[i] = a[i + s];
else
a[i] = t[i + s - l];
}
return a;
}
https://github.com/sam-klok/ArraysRotation
public static void Rotate(int[] arr, int steps)
{
for (int i = 0; i < steps; i++)
{
int previousValue = arr[arr.Length - 1];
for (int j = 0; j < arr.Length; j++)
{
int currentValue = arr[j];
arr[j] = previousValue;
previousValue = currentValue;
}
}
}
Here is an in-place Rotate implementation of a trick posted by גלעד ברקן in another question. The trick is:
Example, k = 3:
1234567
First reverse in place each of the two sections delineated by n-k:
4321 765
Now reverse the whole array:
5671234
My implementation, based on the Array.Reverse method:
/// <summary>
/// Rotate left for negative k. Rotate right for positive k.
/// </summary>
public static void Rotate<T>(T[] array, int k)
{
ArgumentNullException.ThrowIfNull(array);
k = k % array.Length;
if (k < 0) k += array.Length;
if (k == 0) return;
Debug.Assert(k > 0);
Debug.Assert(k < array.Length);
Array.Reverse(array, 0, array.Length - k);
Array.Reverse(array, array.Length - k, k);
Array.Reverse(array);
}
Live demo.
Output:
Array: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
Rotate(5)
Array: 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7
Rotate(-2)
Array: 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9

How to convert 16Bit byte array to audio clip data correctly?

I work with Media Foundataion and what I need to do is convert sound sample frame from byte to audio float data. In order to do it I use such method (that I found somewhere at google):
private static float[] Convert16BitByteArrayToAudioClipData(byte[] source, int headerOffset, int dataSize)
{
int wavSize = BitConverter.ToInt32(source, headerOffset);
headerOffset += sizeof(int);
Debug.AssertFormat(wavSize > 0 && wavSize == dataSize, "Failed to get valid 16-bit wav size: {0} from data bytes: {1} at offset: {2}", wavSize, dataSize, headerOffset);
int x = sizeof(Int16); // block size = 2
int convertedSize = wavSize / x;
float[] data = new float[convertedSize];
Int16 maxValue = Int16.MaxValue;
int i = 0;
while (i < convertedSize)
{
int offset = i * x + headerOffset;
data[i] = (float)BitConverter.ToInt16(source, offset) / maxValue;
++i;
}
Debug.AssertFormat(data.Length == convertedSize, "AudioClip .wav data is wrong size: {0} == {1}", data.Length, convertedSize);
return data;
}
I use it like this :
...
byte[] source = ...; // lenght 43776
... = Convert16BitByteArrayToAudioClipData(source , 0, 0);
...
Looks like this method works wrong, because if I pass an array with size 43776 as a result in while loop at index i = 21886 offset value will be offset = 43776 it lead to exception at this next method
data[i] = (float)BitConverter.ToInt16(source /*43776*/, offset /*43776*/) / maxValue;
because this values could not be the same.
Question is - how to fix this method? Or maybe someone can advice what to use instead?
EDIT
private static float[] Convert16BitByteArrayToAudioClipData(byte[] source)
{
float[] data = new float[source.Length];
for (int i = 0; i < source.Length; i++)
{
data[i] = (float) source[i];
}
return data;
}
Integers need to become -1..+1 floating point values
private static float[] Convert16BitByteArrayToAudioClipData(byte[] source)
{
float[] data = new float[source.Length];
for (int i = 0; i < source.Length; i++)
{
data[i] = ((float) source[i] / Int16.MaxValue); // <<---
}
return data;
}
Eventually I did it this way:
public static float[] Convert16BitByteArrayToAudioClipData(byte[] source)
{
int x = sizeof(Int16);
int convertedSize = source.Length / x;
float[] data = new float[convertedSize];
Int16 maxValue = Int16.MaxValue;
for (int i = 0; i < convertedSize; i++)
{
int offset = i * x;
data[i] = (float)BitConverter.ToInt16(source, offset) / maxValue;
++i;
}
return data;
}

C# - Array transposing bit level

I have an array of 10 x 8 bit(bytes), named Matrix[10], e.g.
byte[] Matrix = new byte[] {
0b01111011,
0b10001100,
0b10101101,
0b10100001,
0b11010110,
0b00011100,
0b00111000,
0b11001111,
0b01111011,
0b10101010,
};
What I want to do is create another array named Matrix_res10 which will have 8 x 10bit (used Int32) elements:
int[] Matrix_res10 = new int[] {
0b0111100101,
0b1000100110,
0b1011001011,
0b1000111010,
0b1110011111,
0b0110110100,
0b1000100111,
0b1011000110
};
Additional explanation in the attached "description" picture.
description
Now, I was able to do it, but I feel the code is too complicated, and can be made simpler, or more logical :)
Any tips ?
my code:
private void button11_Click(object sender, EventArgs e)
{
Int32 i,j;
byte temp;
Random r = new Random();
richTextBox5.Clear();
richTextBox6.Clear();
for (i = 0; i < 10; i++)
{
Matrix[i] = Convert.ToByte(r.Next(0,255));// initialize the matrix with random bytes 0-255
richTextBox5.Text += Convert.ToString(Matrix[i], 2).PadLeft(8, '0')+"\n";//print it
}
for (i = 0; i < 8; i++)
{
Matrix_res10[i] = 0;
for (j = 0; j < 10; j++)
{
temp = (byte)(Matrix[j] << i);
temp = (byte)(temp >> 7);
Matrix_res10[i] += temp*(long)(Math.Pow(2, 9-j)); //convert the bits to a int
}
}
for (i = 0; i < 8; i++)
{
richTextBox6.Text += Convert.ToString(Matrix_res10[i],2).PadLeft(10,'0') + "\n";
}
}
All you have to do is to compute what is jth bit of ith item:
byte[] Matrix = new byte[] {
0b01111011,
0b10001100,
0b10101101,
0b10100001,
0b11010110,
0b00011100,
0b00111000,
0b11001111,
0b01111011,
0b10101010,
};
// 8 - byte has 8 bits; more exact: new int[sizeof(byte) * 8];
// int[] - we have to store 10 bits, that's why byte is not long enough
int[] Matrix_res10 = new int[8];
for (int i = 0; i < Matrix_res10.Length; ++i)
for (int j = 0; j < Matrix.Length; ++j)
Matrix_res10[i] |= ((Matrix[j] >> (Matrix_res10.Length - i - 1)) & 1) <<
(Matrix.Length - j - 1);
Let's have a look at the result:
string report = string.Join(Environment.NewLine, Matrix_res10
.Select(item => Convert.ToString(item, 2).PadLeft(Matrix.Length, '0')));
Console.Write(report);
Outcome:
0111100101
1000100110
1011001011
1000111010
1110011111
0110110100
1000100111
1011000110
A bit of binary arithmetic might help here:
static int[] Transpose(byte[] x) {
var result = new int[8];
for (int i = 7; i >= 0; i--) {
for (int j = 0; j < x.Length; j++) {
// get i-th bit of byte
var mask = 1 << i;
var bit = (x[j] & mask) >> i;
// set that bit at j-th position of target number
result[7 - i] |= bit << (x.Length - 1 - j);
}
}
return result;
}

Bitwise operators on different length BitArrays

I have 2 BitArray items and I need to know if any of bits are the same in each, "AND".
However, the length of the BitArrays can be different and ether one can be larger or smaller than the other.
How can I do an "AND" of two BitArrays, without getting an exception because of different sizes?
This is going to happen a lot, so I need it to be fairly quick.
Example
int[] ids = new int[3];
ids[0] = 1;
ids[1] = 3;
ids[2] = 5;
BitArray bs1 = new BitArray(ids.Max()+1);
for (int i = 0; i < ids.Count(); ++i)
{
bs1[ids[i]] = true;
}
ids[0] = 1;
ids[1] = 59;
ids[2] = 1111;
BitArray bs2 = new BitArray(ids.Max()+1);
for (int i = 0; i < ids.Count(); ++i)
{
bs2[ids[i]] = true;
}
ids[0] = 0;
ids[1] = 5;
ids[2] = 33;
BitArray bs3 = new BitArray(ids.Max()+1);
for (int i = 0; i < ids.Count(); ++i)
{
bs3[ids[i]] = true;
}
//if bs1 AND bs2 bitcount > 0 DisplayMessage("1 and 2 has some same items")
//if bs1 AND bs3 bitcount > 0 DisplayMessage("1 and 3 has some same items")
//if bs2 AND bs3 bitcount > 0 DisplayMessage("2 and 3 has some same items")
To solve my problem I modified the BitArray code and added the following
public static MyBitArray TruncateCopy(MyBitArray source, int size)
{
MyBitArray dest = new MyBitArray(size);
//copy all the arrays
for (int i = 0; i < dest.m_array.Length; ++i)
{
dest.m_array[i] = source.m_array[i];
}
//remove any of the items over the given size
for (int i = ((size % 32) + 1); i < 32; ++i)
{
dest.m_array[i >> 5] &= ~(1 << (i & 31));
}
return dest;
}
public bool HasCommonBits(MyBitArray comp)
{
MyBitArray copied, other;
if (this.Length < comp.Length)
{
other = this;
copied = TruncateCopy(comp, this.Length);
}
else
{
copied = TruncateCopy(this, comp.Length);
other = comp;
}
MyBitArray compareEq = copied.And(other);
return (!compareEq.IsEmpty());
}
public bool IsEmpty()
{
for (int i = 0; i < this.m_array.Length; ++i)
{
if (m_array[i] != 0)
return false;
}
return true;
}
public bool IsFull()
{
//run through all the full sets
for (int i = 0; i < this.m_array.Length - 1; ++i)
{
if (m_array[i] != -1) //-1 is all bits set in an integer
return false;
}
//go through the partial one
for (int i = 0; i < (this.Length % 32); ++i)
{
if (!this[i])
return false;
}
return true;
}
}
First, define what you want to happen in case of differing lengths. Maybe you just want to compare the first Math.Min(len1, len2) elements. In that case write a for loop whose index variable ranges from 0 to Math.Min(len1, len2). Compare the respective array elements in the loop body.
I examined BitArray with reflector. There is no way to trim it, or to perform a partial And. You're out of luck with this class. Replace it with a custom-written class that supports what you need. Writing a bit array is not especially hard.
Completely revised based on this comment:
The result bitarray of your example would be 01010. My original problem states that I need to see if any of the bits are the same. Thus the a resulting bitarray with any 1's would be True and all 0's would be False
BitArrray truncateCopyBA(BitArray source, int size)
{
BitArray dest = new BitArray(size);
for(int i = 0; i < size; ++i)
{
dest[i] = source[i];
}
return dest;
}
bool YourFunc(BitArray a, BitArray b)
{
BitArray one, two;
if (a.Length < b.Length)
{
one = a;
two = truncateCopyBA(b, a.Length);
}
else
{
one = truncateCopyBA(a, b.Length);
two = b;
// If you want to see which bits in both arrays are both ones, then use .And()
// If you want to see which bits in both arrays are the same, use .Not(.Xor()).
BitArray compareEq = a.And(b);
bool anyBitsSame=false;
for(int i = 0; i < compareEq.Length; ++i)
{
if(compareEq.Get(i))
{
return true;
}
}
return false
}
}
I believe this is what you're looking for, but honestly your question is still quite vague after clarifications.

Integer to Integer Array C# [duplicate]

This question already has answers here:
Is there an easy way to turn an int into an array of ints of each digit?
(11 answers)
Closed 1 year ago.
I had to split an int "123456" each value of it to an Int[] and i have already a Solution but i dont know is there any better way :
My solution was :
public static int[] intToArray(int num){
String holder = num.ToString();
int[] numbers = new int[Holder.ToString().Length];
for(int i=0;i<numbers.length;i++){
numbers[i] = Convert.toInt32(holder.CharAt(i));
}
return numbers;
}
A simple solution using LINQ
int[] result = yourInt.ToString().Select(o=> Convert.ToInt32(o) - 48 ).ToArray()
I believe this will be better than converting back and forth. As opposed to JBSnorro´s answer I reverse after converting to an array and therefore avoid IEnumerable´s which I think will contribute to a little bit faster code. This method work for non negative numbers, so 0 will return new int[1] { 0 }.
If it should work for negative numbers, you could do a n = Math.Abs(n) but I don't think that makes sense.
Furthermore, if it should be more performant, I could create the final array to begin with by making a binary-search like combination of if-statements to determine the number of digits.
public static int[] digitArr(int n)
{
if (n == 0) return new int[1] { 0 };
var digits = new List<int>();
for (; n != 0; n /= 10)
digits.Add(n % 10);
var arr = digits.ToArray();
Array.Reverse(arr);
return arr;
}
Update 2018:
public static int numDigits(int n) {
if (n < 0) {
n = (n == Int32.MinValue) ? Int32.MaxValue : -n;
}
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if (n < 1000000000) return 9;
return 10;
}
public static int[] digitArr2(int n)
{
var result = new int[numDigits(n)];
for (int i = result.Length - 1; i >= 0; i--) {
result[i] = n % 10;
n /= 10;
}
return result;
}
int[] outarry = Array.ConvertAll(num.ToString().ToArray(), x=>(int)x);
but if you want to convert it to 1,2,3,4,5:
int[] outarry = Array.ConvertAll(num.ToString().ToArray(), x=>(int)x - 48);
I'd do it like this:
var result = new List<int>();
while (num != 0) {
result.Insert(0, num % 10);
num = num / 10;
}
return result.ToArray();
Slightly less performant but possibly more elegant is:
return num.ToString().Select(c => Convert.ToInt32(c.ToString())).ToArray();
Note that these both return 1,2,3,4,5,6 rather than 49,50,51,52,53,54 (i.e. the byte codes for the characters '1','2','3','4','5','6') as your code does. I assume this is the actual intent?
Using conversion from int to string and back probably isn't that fast. I would use the following
public static int[] ToDigitArray(int i)
{
List<int> result = new List<int>();
while (i != 0)
{
result.Add(i % 10);
i /= 10;
}
return result.Reverse().ToArray();
}
I do have to note that this only works for strictly positive integers.
EDIT:
I came up with an alternative. If performance really is an issue, this will probably be faster, although you can only be sure by checking it yourself for your specific usage and application.
public static int[] ToDigitArray(int n)
{
int[] result = new int[GetDigitArrayLength(n)];
for (int i = 0; i < result.Length; i++)
{
result[result.Length - i - 1] = n % 10;
n /= 10;
}
return result;
}
private static int GetDigitArrayLength(int n)
{
if (n == 0)
return 1;
return 1 + (int)Math.Log10(n);
}
This works when n is nonnegative.
Thanks to ASCII character table. The simple answer using LINQ above yields answer + 48.
Either
int[] result = youtInt.ToString().Select(o => Convert.ToInt32(o) - 48).ToArray();
or
int[] result = youtInt.ToString().Select(o => int.Parse(o.ToString())).ToArray();
can be used
You can do that without converting it to a string and back:
public static int[] intToArray(int num) {
List<int> numbers = new List<int>();
do {
numbers.Insert(0, num % 10);
num /= 10;
} while (num > 0);
return numbers.ToArray();
}
It only works for positive values, of course, but your original code also have that limitation.
I would convert it in the below manner
if (num == 0) return new int[1] { 0 };
var digits = new List<int>();
while (num > 0)
{
digits.Add(num % 10);
num /= 10;
}
var arr = digits.ToArray().Reverse().ToArray();
string DecimalToBase(int iDec, int numbase)
{
string strBin = "";
int[] result = new int[32];
int MaxBit = 32;
for(; iDec > 0; iDec/=numbase)
{
int rem = iDec % numbase;
result[--MaxBit] = rem;
}
for (int i=0;i<result.Length;i++)
if ((int)result.GetValue(i) >= base10)
strBin += cHexa[(int)result.GetValue(i)%base10];
else
strBin += result.GetValue(i);
strBin = strBin.TrimStart(new char[] {'0'});
return strBin;
}
int BaseToDecimal(string sBase, int numbase)
{
int dec = 0;
int b;
int iProduct=1;
string sHexa = "";
if (numbase > base10)
for (int i=0;i<cHexa.Length;i++)
sHexa += cHexa.GetValue(i).ToString();
for(int i=sBase.Length-1; i>=0; i--,iProduct *= numbase)
{
string sValue = sBase[i].ToString();
if (sValue.IndexOfAny(cHexa) >=0)
b=iHexaNumeric[sHexa.IndexOf(sBase[i])];
else
b= (int) sBase[i] - asciiDiff;
dec += (b * iProduct);
}
return dec;
}
i had similar requirement .. i took from many good ideas, and added a couple missing pieces .. where many folks weren’t handling zero or negative values. this is what i came up with:
public static int[] DigitsFromInteger(int n)
{
int _n = Math.Abs(n);
int length = ((int)Math.Log10(_n > 0 ? _n : 1)) + 1;
int[] digits = new int[length];
for (int i = 0; i < length; i++)
{
digits[(length - i) - 1] = _n % 10 * ((i == (length - 1) && n < 0) ? -1 : 1);
_n /= 10;
}
return digits;
}
i think this is pretty clean .. although, it is true we're doing a conditional check and several extraneous calculations with each iteration .. while i think they’re nominal in this case, you could optimize a step further this way:
public static int[] DigitsFromInteger(int n)
{
int _n = Math.Abs(n);
int length = ((int)Math.Log10(_n > 0 ? _n : 1)) + 1;
int[] digits = new int[length];
for (int i = 0; i < length; i++)
{
//digits[(length - i) - 1] = _n % 10 * ((i == (length - 1) && n < 0) ? -1 : 1);
digits[(length - i) - 1] = _n % 10;
_n /= 10;
}
if (n < 0)
digits[0] *= -1;
return digits;
}
A slightly more concise way to do MarkXA's one-line version:
int[] result = n.ToString().Select(c => (int)Char.GetNumericValue(c)).ToArray();
GetNumericValue returns the visible number in your char as a double, so if your string is "12345", it will return the doubles 1,2,3,4,5, which can each be cast to an int. Note that using Convert.ToInt32 on a char in C# returns the ASCII code, so you would get 49,50,51,52,53. This can understandably lead to a mistake.
Here is a Good Solution for Convert Your Integer into Array i.e:
int a= 5478 into int[]
There is no issue if You Have a String and You want to convert a String into integer Array for example
string str=4561; //Convert into
array[0]=4;
array[1]=5;
array[2]=6;
array[3]=7;
Note: The Number of zero (0) in devider are Equal to the Length of input and Set Your Array Length According to Your input length
Now Check the Coding:
string str=4587;
int value = Convert.ToInt32(str);
int[] arr = new int[4];
int devider = 10000;
for (int i = 0; i < str.Length; i++)
{
int m = 0;
devider /= 10;
arr[i] = value / devider;
m = value / devider;
value -= (m * devider);
}
private static int[] ConvertIntToArray(int variable)
{
string converter = "" + variable;
int[] convertedArray = new int[converter.Length];
for (int i=0; i < convertedArray.Length;i++) //it can be also converter.Length
{
convertedArray[i] = int.Parse(converter.Substring(i, 1));
}
return convertedArray;
}
We get int via using method. Then, convert it to string immediately (123456->"123456"). We have a string called converter and carry to int value. Our string have a string.Length, especially same length of int so, we create an array called convertedArray that we have the length, that is converter(string) length. Then, we get in the loop where we are convert the string to int one by one via using string.Substring(i,1), and assign the value convertedArray[i]. Then, return the convertedArray.At the main or any method you can easily call the method.
public static int[] intToArray(int num)
{
num = Math.Abs(num);
int length = num.ToString().Length;
int[] arr = new int[length];
do
{
arr[--length] = num % 10;
num /= 10;
} while (num != 0);
return arr;
}
Dividing by system base (decimal in this case) removes the right most digit, and we get that digit by remainder operator. We keep repeating until we end up with a zero. Each time a digit is removed it will be stored in an array starting from the end of the array and backward to avoid the need of revering the array at the end. The Math.Abs() function is to handle the negative input, also the array is instantiated with the same size as input length.
Integer or Long to Integer Array C#
Convert it to char array and subtract 48.
public static int[] IntToArray(int value, int length)
{
char[] charArray = new char[length];
charArray = value.ToString().ToCharArray();
int[] intArray = new int[length];
for (int i = 0; i < intArray.Length; i++)
{
intArray[i] = charArray[i] - 48;
}
return intArray;
}
public static int[] LongToIntArray(long value, int length)
{
char[] charArray = new char[length];
charArray = value.ToString().ToCharArray();
int[] intArray = new int[length];
for (int i = 0; i < intArray.Length; i++)
{
intArray[i] = charArray[i] - 48;
}
return intArray;
}

Categories