Dynamic Bit Shifting / Unshifting - c#

i'd like to store multiple values of blocks into an integer in the same way as i can convert an ip into an int. My problem is that i need to do this for n blocks, not only 4. Also i need to specifiy the maximum value of each block, which is allways the same for all blocks.
So, for the Example below, if i'd like to store the whole IP range my BlockCount is 4 and my BlockSize is 255, which is the max value of each block. But it seems not to work if i lower my BlockSize and/or BlockCount.
This is my first try, but it's not working correctly:
const int BlockSize = 100;
const int BlockCount = 3;
int shiftedValues = Shift(BlockSize, BlockCount);
for (int shiftedValue = 1; shiftedValue <= shiftedValues; shiftedValue++)
{
for (int index = 0; index <= BlockCount; index++)
{
int blockValue = Unshift(index, shiftedValue);
}
}
private static int Shift(int blockSize, int blockCount)
{
int result = 0;
for (int i = 0; i < blockCount; i++)
{
result += ( blockSize << 8 * i );
}
return result;
}
private static int Unshift(int blockIndex, int shiftedValue)
{
return ( shiftedValue >> ( blockIndex * 8 ) ) & 0xFF;
}

The code above is my solution, it's pretty simple code, but feel free to ask clarification about it.
class Program
{
static void Main(string[] args)
{
int [] items = { 150 , 78 , 44 } ;
int x = Program.Pack ( items , 150 ) ;
int [] unpacked = Program.UnPack ( x , 150 , 3 ) ;
}
public static int Pack ( int[] blocks , int blockSize )
{
int size = (int)Math.Ceiling(Math.Log(blockSize, 2));
int len = size * blocks.Length;
if (len > 32)
throw new Exception("Int Limit Exceeded");
if ( blocks.Any ( x => x > blockSize ) )
throw new Exception ( "There are some blocks that exceede the maximum block size" );
List<bool> bools = new List<bool>();
bools = bools.InitBoolArray(32);
int i = 0 ;
foreach (int block in blocks)
{
BitArray temp = block.ToBinary().Take(size);
for ( int j = 0 ; j < size ; i++ , j++ )
bools[i] = temp.Get(j);
}
return (new BitArray ( bools.ToArray() ) ).ToNumeral() ;
}
public static int[] UnPack ( int entry , int blockSize , int blockCount )
{
BitArray number = entry.ToBinary();
int size = (int)Math.Ceiling(Math.Log(blockSize, 2));
if (size > 32)
throw new Exception("Int Limit Exceeded");
List<int> result = new List<int>();
for (int i = 0; i < blockCount; i++)
{
BitArray temp = number.Take(size);
number = number.Shift (size );
result.Add(temp.FitSize(32).ToNumeral());
}
return result.ToArray() ;
}
}
There extension method used
public static class BinaryConverter
{
public static BitArray ToBinary(this int numeral)
{
return new BitArray(new[] { numeral });
}
public static int ToNumeral(this BitArray binary)
{
if (binary == null)
throw new ArgumentNullException("binary");
if (binary.Length > 32)
throw new ArgumentException("must be at most 32 bits long");
var result = new int[1];
binary.CopyTo(result, 0);
return result[0];
}
public static BitArray Take (this BitArray current, int length )
{
if (current.Length < length)
throw new Exception("Invalid length parameter");
List<bool> taken = new List<bool>();
for (int i = 0; i < length; i++)
taken.Add(current.Get(i));
return new BitArray(taken.ToArray());
}
public static BitArray Shift (this BitArray current, int length )
{
if (current.Length < length)
throw new Exception("Invalid length parameter");
List<bool> shifted = new List<bool>();
for (int i = 0; i < current.Length - length; i++)
shifted.Add(current.Get(length + i));
return new BitArray(shifted.ToArray());
}
public static BitArray FitSize (this BitArray current, int size)
{
List<bool> bools = new List<bool>() ;
bools = bools.InitBoolArray(size);
for (int i = 0; i < current.Count; i++)
bools[i] = current.Get(i) ;
return new BitArray(bools.ToArray());
}
public static List<bool> InitBoolArray(this List<bool> current, int size)
{
List<bool> bools = new List<bool> ();
for (int i = 0; i < size; i++)
bools.Add(false);
return bools ;
}
}

Related

convert string to int32 with LSB c#

I have binary string and Int32 array.
How to convert binary string (each 11 bit of string) to Int32 value(11 LSB) on int array?
I tried this:
for (int i = 0; i <(string.Length); i++) {
if (count1 >= string.Length - 21)
break;
else
string = string.Insert(count1, "000000000000000000000");
count1 += 31;
}
int numOfBytes = string.Length / 32;
int[] ints = new int[numOfBytes];
for (int i = 0; i < numOfBytes; ++i) {
ints[i] = Convert.ToInt32(string.Substring(32 * i, 32), 2);
}
but it returns false values
Int32[] BinaryStringToInt32Array(const string binaryString, const int bitCount)
{
Int32[] results = new Int32[binaryString.Length/bitCount];
for (int i = 0; i < results.Length; i++)
{
string str = binaryString.Substring(i * bitCount, bitCount);
results[i] = Convert.ToInt32(str, 2);
}
return results;
}
Take note this function will ignore all leftover bits if binaryString's length is not multiple of bitCount. In your case, bitCount is 11.

Convert byte/int to List<int> reversed and vice versa

Was wondering how can I convert an int to a List in reverse order padded with zeroes and vice versa?
Have a byte that represents List(8), sometimes 2 bytes for List(16), 8 bytes for List(64); so looking for a good solution to handle converting to an int list, manipulate then back again.
e.g. Input of 3 to a List of 1,1,0,0,0,0,0,0
Or input of 42 to a List of 0,1,0,1,0,1,0,0
And vice-versa, take a List of 1,1,0,0,0,0,0,0 and return 3 or List of 0,1,0,1,0,1,0,0 and return 42
What I have done at present is build a couple of functions to handle both scenarios, all works fine, just wondering if there is a better / more elegant solution that I've completelt overlooked?
private List<int> IntToList(int _Input)
{
string _Binary = ReverseString(Convert.ToString(_Input, 2).PadLeft(8, '0'));
List<int> _List = new List<int>(8);
for (int i = 0; i < _Binary.Length; i++)
{
_List.Add(Convert.ToInt32(_Binary.Substring(i, 1)));
}
return _List;
}
private int IntsToByte(List<int> _List)
{
string _Binary = "";
for (int i = 7; i > -1; i--)
{
_Binary += _List[i];
}
return Convert.ToInt32(_Binary, 2);
}
You can work with bitwise operations. They might be fast.
Warning : Be aware of Little/Big Endian (More here)
The following code works :
private List<int> IntToList(int _Input, int _MaxSize = 8)
{
int padding = 1;
List<int> resultList = new List<int>(_MaxSize);
while (padding < 1 << _MaxSize)
{
resultList.Add((_Input & padding) == padding ? 1 : 0);
padding = padding << 1;
}
return resultList;
}
private int IntsToByte(List<int> _List)
{
int result = 0, padding = 0;
foreach (int i in _List)
{
result = result | (i << padding++);
}
return result;
}
This should work
int number = 42
char[] reverse = Convert.ToString(number, 2).PadLeft(8, '0').ToCharArray();
Array.Reverse(reverse);
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<ulong> results = null;
List<byte> output = null;
List<byte> input1 = new List<byte>() { 1, 1, 0, 0, 0, 0, 0, 0 };
results = ReadList(input1, 1);
output = WriteList(results,1);
List<byte> input2 = new List<byte>() { 0, 1, 0, 1, 0, 1, 0, 0 };
results = ReadList(input2, 1);
output = WriteList(results,1);
}
static List<ulong> ReadList(List<byte> input, int size)
{
List<ulong> results = new List<ulong>();
input.Reverse();
MemoryStream stream = new MemoryStream(input.ToArray());
BinaryReader reader = new BinaryReader(stream);
int count = 0;
ulong newValue = 0;
while (reader.PeekChar() != -1)
{
switch (size)
{
case 1:
newValue = ((ulong)Math.Pow(2, size) * newValue) + (ulong)reader.ReadByte();
break;
case 2:
newValue = ((ulong)Math.Pow(2, size) * newValue) + (ulong)reader.ReadInt16();
break;
}
if (++count == size)
{
results.Add(newValue);
newValue = 0;
count = 0;
}
}
return results;
}
static List<byte> WriteList(List<ulong> input, int size)
{
List<byte> results = new List<byte>();
foreach (ulong num in input)
{
ulong result = num;
for (int count = 0; count < size; count++)
{
if (result > 0)
{
byte bit = (byte)(result % Math.Pow(2, size));
results.Add(bit);
result = (ulong)(result / Math.Pow(2, size));
}
else
{
results.Add(0);
}
}
}
results.Reverse();
return results;
}
}
}
​
Solution from OP.
Have gone with Jean Bob's suggestion of using BitWise.
For anyone elses benefit, here is my modified version to read / write in blocks of 8 to/from the list.
private List<int> IntToList(List<int> _List, int _Input)
{
int _Padding = 1;
while (_Padding < 1 << 8)
{
_List.Add((_Input & _Padding) == _Padding ? 1 : 0);
_Padding = _Padding << 1;
}
return _List;
}
private int IntsToByte(List<int> _List, int l)
{
int _Result = 0, _Padding = 0;
for (int i = l; i < (l + 8); i++)
{
_Result = _Result | (_List[i] << _Padding++);
}
return _Result;
}

How to get minimum value from 2D array in c# and the indices of that cell?

I want to get the minimum value from 2 dimensional array [1024,9] ,and I want the position of this minimum value.
Hint: the last column is flag "if flag == 0 : check this row, else : skip this row"
I tried this cod ,but it did not help me ...
float min = fill_file[0, 0];
int ind = 0;
int ind2 = 0;
for (int i = 0; i < 1024; i++)
{
for (int j = 0; j < 8; j++)
{
if (fill_file[i, j] < min && fill_file[i, 8] == 0)
{
min = fill_file[i, j];
ind2 = i;
ind = j;
}
}
}
This is all code based on your request
int t = 0;
while (t < 1024)
{
float min = fill_file[0, 0];
int ind = 0;
int ind2 = 0;
for (int i = 0; i < 1024; i++)
{
for (int j = 0; j < 8; j++)
{
if (fill_file[i, j] < min && fill_file[i, 8] == 0)
{
min = fill_file[i, j];
ind2 = i;
ind = j;
}
}
}
machens[ind] = machens[ind] + min;
fill_file[ind2, 8] = 1;
for (int r = 0; r < 1024; r++)
{
if (fill_file[r, 8] != 1)
fill_file[r, ind] = fill_file[r, ind] + min;
}
t++;
}//End while
Firstly:
If it happens that none of the rows have the "use this row" flag set to zero (with zero meaning "use this row"), you will obviously get a wrong result.
I guess this will never happen for your data?
Secondly:
If fill_file[0,8] is nonzero, you will still be initialising min to fill_file[0,0] even though the flag says you shouldn't use that row.
In that case, if fill_file[0,0]happens to be less than all the values in any of the rows for which fill_file[row,8] is zero then you will get the wrong result.
I would be tempted to initialise min to float.MaxValue and ind and ind2 to -1 each, so you know if they haven't been updated.
And call them minRow and minCol.
Thirdly:
There's an obvious optimisation: If [row,8] is nonzero, there's no point in running the inner iteration for that row.
Putting this all together:
float minValue = float.MaxValue;
int minCol = -1;
int minRow = -1;
for (int row = 0; row < 1024; row++)
{
if (fill_file[row, 8] == 0)
{
for (int col = 0; col < 8; col++)
{
if (fill_file[row, col] < minValue)
{
minValue = fill_file[row, col];
minRow = row;
minCol = col;
}
}
}
}
// If minRow is < 0, then no valid data exists.
// Otherwise, fill_file[minRow, minCol] contains minVal
This code:
var min_ij = Enumerable.Range(0, 1024)
.Where(i => fillFile[i, 9] == 0)
.SelectMany(i => Enumerable.Range(0, 8)
.Select(j => new { i, j }))
.ArgMin(ij => fillFile[ij.i, ij.j]);
int min_i = min_ij.i;
int min_j = min_ij.j;
Using this helper function:
public static TElem ArgMin<TElem, TField>(this IEnumerable<TElem> set, Func<TElem, TField> objective, bool allowEmptySet = false)
where TField : IComparable<TField>
{
if (!set.Any() && !allowEmptySet)
throw new InvalidOperationException("Cannot perform ArgMin on an empty set.");
bool first = true;
TElem bestElem = default(TElem);
TField bestObjective = default(TField);
foreach (TElem currElem in set)
{
TField currObjective = objective(currElem);
if (first || currObjective.CompareTo(bestObjective) < 0)
{
first = false;
bestElem = currElem;
bestObjective = currObjective;
}
}
return bestElem;
}
This is a straightforward problem. Try something like this:
static void Main( string[] args )
{
int[,] values = new int[1024,9];
Random rng = new Random() ;
// initialise the array
for ( int r = 0 ; r < 1024 ; ++r )
{
for ( int c = 0 ; c < 9 ; ++c )
{
values[r,c] = rng.Next() ;
}
int x = rng.Next(10) ;
if ( x == 1 )
{
values[r,8] = 0 ;
}
}
int? minValue = null ;
int? minRow = null ;
int? minCol = null ;
for ( int r = 0 ; r < 1024 ; ++r )
{
bool skipRow = 0 == values[r,8] ;
if ( skipRow ) continue ;
for ( int c = 0 ; c < 8 ; ++c )
{
int cell = values[r,c] ;
if ( !minValue.HasValue || cell < minValue )
{
minValue = cell ;
minRow = r ;
minCol = c ;
}
}
}
// display the results
if ( minValue.HasValue )
{
Console.WriteLine( "Minimum: values[{0},{1}] is {2}" , minRow , minCol , minValue );
}
else
{
Console.WriteLine( "all rows skipped" );
}
return ;
}

C# byte[] to List<bool>

From bool[] to byte[]: Convert bool[] to byte[]
But I need to convert a byte[] to a List where the first item in the list is the LSB.
I tried the code below but when converting to bytes and back to bools again I have two totally different results...:
public List<bool> Bits = new List<bool>();
public ToBools(byte[] values)
{
foreach (byte aByte in values)
{
for (int i = 0; i < 7; i++)
{
Bits.Add(aByte.GetBit(i));
}
}
}
public static bool GetBit(this byte b, int index)
{
if (b == 0)
return false;
BitArray ba = b.Byte2BitArray();
return ba[index];
}
You're only considering 7 bits, not 8. This instruction:
for (int i = 0; i < 7; i++)
Should be:
for (int i = 0; i < 8; i++)
Anyway, here's how I would implement it:
byte[] bytes = ...
List<bool> bools = bytes.SelectMany(GetBitsStartingFromLSB).ToList();
...
static IEnumerable<bool> GetBitsStartingFromLSB(byte b)
{
for(int i = 0; i < 8; i++)
{
yield return (b % 2 == 0) ? false : true;
b = (byte)(b >> 1);
}
}

How can a large Array be split into smaller arrays?

Given a large array how can it be split into smaller arrays with the size of the smaller arrays specified as an argument of the method?
For instance, given numbers, what would Split's implementation be?
int[] numbers = new int[7845];
int[][] sectionedNumbers = numbers.Split(1000);
sectionedNumbers.Length; //outputs 8
sectionedNumbers[7].Length; //outputs 845
You can do it with an extension method:
using System;
static class Program
{
static T[][] Split<T>(this T[] arrayIn, int length)
{
bool even = arrayIn.Length%length == 0;
int totalLength = arrayIn.Length/length;
if (!even)
totalLength++;
T[][] newArray = new T[totalLength][];
for (int i = 0; i < totalLength;++i )
{
int allocLength = length;
if (!even && i == totalLength - 1)
allocLength = arrayIn.Length % length;
newArray[i] = new T[allocLength];
Array.Copy(arrayIn, i * length, newArray[i], 0, allocLength);
}
return newArray;
}
static void Main(string[] args)
{
int[] numbers = new int[8010];
for (int i = 0; i < numbers.Length; ++i)
numbers[i] = i;
int[][] sectionedNumbers = numbers.Split(1000);
Console.WriteLine("{0}", sectionedNumbers.Length);
Console.WriteLine("{0}", sectionedNumbers[7].Length);
Console.WriteLine("{0}", sectionedNumbers[1][0]);
Console.WriteLine("{0}", sectionedNumbers[7][298]);
Console.ReadKey();
}
}
This prints:
9
1000
1000
7298
This isn't necessarily a good idea, but here's an implementation that generalises this splitting operation to IEnumerable<T>, returning an IEnumerable<IEnumerable<T>>.
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> input, int size)
{
return input.Select((a, i) => new { Item = a, Index = i })
.GroupBy( b => (b.Index / size))
.Select(c => c.Select(d => d.Item));
}
Reed beat me to it, but here's my method anyway:
public int[][] Split(int[] source, int size)
{
int fullArrayCount = source.Length / size;
int totalArrayCount = fullArrayCount;
int remainder = source.Length - (fullArrayCount * size);
if (remainder > 0)
{
totalArrayCount++;
}
int[][] output = new int[totalArrayCount][];
for (int i = 0; i < fullArrayCount; i++)
{
output[i] = new int[size];
Array.Copy(source, i * size, output[i], 0, size);
}
if (totalArrayCount != fullArrayCount)
{
output[fullArrayCount] = new int[remainder];
Array.Copy(source, fullArrayCount * size,
output[fullArrayCount], 0, remainder);
}
return output;
}

Categories

Resources