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);
}
}
Related
I have an array of n integers and I need to divide any of it's elements by 2 (return the ceiling of the result) for k times such that the sum is minimum. The value of k can be very large as compared to n.
I am using this code:
private static int GetMaxSum(int[] array, int k)
{
int n = array.Length;
for (int i = 0; i < k; i++)
{
var indexAtMax = GetMaxIndex(array);
if (array[indexAtMax] == 1) break;
array[indexAtMax] = array[indexAtMax] / 2 + array[indexAtMax] % 2;
}
return array.Sum();
}
private static int GetMaxIndex(int[] array)
{
int maxIndex = 0;
int max = array[0];
for (int i=1; i<array.Length;i++)
{
if (array[i] > max)
{
max = array[i];
maxIndex = i;
}
}
return maxIndex;
}
How can we improve the performance further probably by using max heap or some other data structure?
Unless I'm misunderstanding your requirements, your solution seens way too complicated (and apparently wrong according to comments).
I can't really think this through right now, but wouldn't it be the case that the global solution is made up of optimal intermediate steps? The order in which you divide is irrelevant and the problem is linear.
If that is the case, you simply have to evaluate the optimal division in each step and that is not very hard to do:
static void Minimize(int[] arr, int k)
{
for (var j = 0; j < k; j++)
{
var maxGainIndex = -1;
var maxGain = int.MinValue;
for (var i = 0; i < arr.Length; i++)
{
var gain = arr[i] - (arr[i]/2 + arr[i] % 2);
if (gain > maxGain)
{
maxGain = gain;
maxGainIndex = i;
}
}
arr[maxGainIndex] -= maxGain;
}
}
If I'm not wrong, the asymptotic behavior of this algorithm is O(k·n).
UPDATE:
Based on claims of posted code being far less optimal, I've taken the liberty of benchmarking both algorithms with these results on my machine:
Input array: 100;120;80;55;75;115;125;150;90;35;65;77;89;10;11;113;200;300
Number of divisions: 20
Running benchmarks in Release mode without debugger attached.
1000000 of GetMimimum finished in 584 ms with result 704.
1000000 of GetMimimum2 finished in 8846 ms with result 704.
Benchmarking code can be found here: https://dotnetfiddle.net/ITx53q
The performance gain of my proposed algorithm is rather staggering (x15), which was expected because your solution is, as evaluated initally, overcomplicated at best for such a simple problem.
As the assumption was that k>>n, the simpler algorithms are of the order O(kn) which can be too much of iterations.
I have written this code thinking of the problem and how can I limit sorting or calculating min/max. I have divided the array into subarrays so that the operations can be performed on subarrays without thinking of the order of operations.
private static int GetMinSum(int[] array, int k)
{
int n = array.Length;
var sum = 0;
k = GetOptimizedListAndK(array, n, k, out var lists);
//If more sublists are needed
if (k > 0)
{
var count = lists.CountSum;
var key = lists.Key;
if (key > 0)
{
var poweroftwo = 1 << key;
sum += count * poweroftwo - k * poweroftwo / 2;
var dictionary2 = GetDictionary(array, lists, poweroftwo);
key = dictionary2.Keys.Last();
while (k > 0 && key > 0)
{
var list2 = dictionary2[key];
count = list2.Count;
if (k >= count)
{
list2.ForEach(
index => array[index] = array[index] / 2 + array[index] % 2);
dictionary2.Remove(key);
key = dictionary2.Keys.LastOrDefault();
k -= count;
}
else
{
if (k <= Log2(count))
{
for (int i = 0; i < k; i++)
{
var indexAtMax = GetMaxIndex(list2, array);
array[indexAtMax] = array[indexAtMax] / 2 + array[indexAtMax] % 2;
}
k = 0;
}
if (count - k <= Log2(count))
{
var minIndexes = GetMinIndexes(list2, array, count - k);
foreach (var i in list2)
{
if (!minIndexes.Contains(i))
{
array[i] = array[i] / 2 + array[i] % 2;
}
}
k = 0;
}
if (k > 0)
{
poweroftwo = 1 << key;
sum += list2.Count * poweroftwo - k * poweroftwo / 2;
dictionary2 = GetDictionary(array, list2, poweroftwo);
key = dictionary2.Keys.Last();
}
}
}
}
}
return array.Sum() + sum;
}
private static int GetOptimizedListAndK(int[] array, int n, int k, out Lists lists)
{
lists = null;
Dictionary<int, Lists> dictionary = new Dictionary<int, Lists>();
PopulatePowerBasedDictionary(array, n, dictionary);
var key = dictionary.Keys.Max();
while (key > 0 && k > 0)
{
lists = dictionary[key];
var count = lists.CountSum;
if (k >= count)
{
lists.ForEach(list => list.ForEach(index => array[index] = array[index] / 2 + array[index] % 2));
if (key > 1)
{
if (dictionary.TryGetValue(key - 1, out var lowerlists))
{
lowerlists.AddRange(lists);
lowerlists.CountSum += count;
}
else dictionary.Add((key - 1), lists);
}
dictionary.Remove(key);
key--;
k -= count;
}
else
{
if (k < Log2(count))
{
for (int i = 0; i < k; i++)
{
var indexAtMax = GetMaxIndex(lists, array);
array[indexAtMax] = array[indexAtMax] / 2 + array[indexAtMax] % 2;
}
k = 0;
}
if (count - k < Log2(count))
{
var minIndexes = GetMinIndexes(lists, array, count - k);
foreach (var list in lists)
{
foreach (var i in list)
{
if (!minIndexes.Contains(i))
{
array[i] = array[i] / 2 + array[i] % 2;
}
}
}
k = 0;
}
break;
}
}
return k;
}
private static void PopulatePowerBasedDictionary(int[] array, int n, Dictionary<int, Lists> dictionary)
{
for (int i = 0; i < n; i++)
{
if (array[i] < 2) continue;
var log2 = Log2(array[i]);
if (dictionary.TryGetValue(log2, out var lists))
{
lists[0].Add(i);
lists.CountSum++;
}
else
{
lists = new Lists(1,log2) { new List<int> { i } };
dictionary.Add(log2, lists);
}
}
}
private static int GetMaxIndex(List<int> list, int[] array)
{
var maxIndex = 0;
var max = 0;
foreach (var i in list)
{
if (array[i] > max)
{
maxIndex = i;
max = array[i];
}
}
return maxIndex;
}
private static SortedDictionary<int, List<int>> GetDictionary(int[] array, Lists lists, int poweroftwo)
{
SortedDictionary<int, List<int>> dictionary = new SortedDictionary<int, List<int>>();
foreach (var list in lists)
{
foreach (var i in list)
{
array[i] = array[i] - poweroftwo;
if (array[i] < 2)
{
continue;
}
var log2 = Log2(array[i]);
if (dictionary.TryGetValue(log2, out var list2))
{
list2.Add(i);
}
else
{
list2 = new List<int> { i };
dictionary.Add(log2, list2);
}
}
}
return dictionary;
}
private static SortedDictionary<int, List<int>> GetDictionary(int[] array, List<int> list, int poweroftwo)
{
SortedDictionary<int, List<int>> dictionary = new SortedDictionary<int, List<int>>();
foreach (var i in list)
{
array[i] = array[i] - poweroftwo;
if (array[i] < 2)
{
continue;
}
var log2 = Log2(array[i]);
if (dictionary.TryGetValue(log2, out var list2))
{
list2.Add(i);
}
else
{
list2 = new List<int> { i };
dictionary.Add(log2, list2);
}
}
return dictionary;
}
private static int GetMaxIndex(Lists lists, int[] array)
{
var maxIndex = 0;
var max = 0;
foreach (var list in lists)
{
foreach (var i in list)
{
if (array[i]>max)
{
maxIndex = i;
max = array[i];
}
}
}
return maxIndex;
}
private static HashSet<int> GetMinIndexes(Lists lists, int[] array, int k)
{
var mins = new HashSet<int>();
var minIndex = 0;
var min = int.MaxValue;
for (int j = 0; j < k; j++)
{
foreach (var list in lists)
{
foreach (var i in list)
{
if (array[i] < min && !mins.Contains(i))
{
minIndex = i;
min = array[i];
}
}
}
mins.Add(minIndex);
min = int.MaxValue;
}
return mins;
}
private static HashSet<int> GetMinIndexes(List<int> list, int[] array, int k)
{
var mins = new HashSet<int>();
var minIndex = 0;
var min = int.MaxValue;
for (int j = 0; j < k; j++)
{
foreach (var i in list)
{
if (array[i] < min && !mins.Contains(i))
{
minIndex = i;
min = array[i];
}
}
mins.Add(minIndex);
min = int.MaxValue;
}
return mins;
}
private static int Log2(int n)
{
return BitOperations.Log2((uint)n);
}
Lists Class:
public class Lists:List<List<int>>
{
public int Key { get; set; }
public int CountSum { get; set; }
public Lists(int countSum, int key):base()
{
CountSum = countSum;
Key = key;
}
}
I got this class to compute the CRC8 checksum of a byte[]:
public static class Crc8
{
static byte[] table = new byte[256];
// x8 + x7 + x6 + x4 + x2 + 1
const byte poly = 0xd5;
public static byte ComputeChecksum(params byte[] bytes)
{
byte crc = 0;
if (bytes != null && bytes.Length > 0)
{
foreach (byte b in bytes)
{
crc = table[crc ^ b];
}
}
return crc;
}
static Crc8()
{
for (int i = 0; i < 256; ++i)
{
int temp = i;
for (int j = 0; j < 8; ++j)
{
if ((temp & 0x80) != 0)
{
temp = (temp << 1) ^ poly;
}
else
{
temp <<= 1;
}
}
table[i] = (byte)temp;
}
}
}
And in the Main I got:
static void Main(string[] args)
{
string number = "123456789";
Console.WriteLine(Convert.ToByte(Crc8.ComputeChecksum(StringToByteArray(number))).ToString("x2"));
Console.ReadLine();
}
private static byte[] StringToByteArray(string str)
{
ASCIIEncoding enc = new ASCIIEncoding();
return enc.GetBytes(str);
}
This results in 0xBC
However, according to: http://www.scadacore.com/field-tools/programming-calculators/online-checksum-calculator/
this is incorrect, because the checksum for the CheckSum8 Xor is 0x31.
What did I wrong there?
On the linked site only some 16 and 32 bit CRCs are listed, the
CheckSum8Xor is not a CRC. The 0xBC comes from a 8-bit CRC
called "CRC-8/DVB-S2", see http://reveng.sourceforge.net/crc-catalogue/1-15.htm
Ah, ok, so I've overiterpreted this checksum computation.
Well, in that case, it's easy:
public static byte Checksum8XOR(byte[] data)
{
byte checksum = 0x00;
for (int i = 0; i < data.Length; i++)
{
checksum ^= data[i];
}
return checksum;
}
I have a byte array and wish to find the "occurrences" of some bytes.
For example 00 69 73 6F 6D in a very large byte array (> 50/100 Megabytes)
OR
even better a reverse operation: Searching the most common pattern without knowing it the code should be able to read and find it from the file.
You can use the Boyer-Moore algorithm to efficiently search for a sequence of bytes in an array of bytes.
Here's a C# version I converted from the Java version from the Wikipedia entry on Boyer-Moore.
public sealed class BoyerMoore
{
readonly byte[] needle;
readonly int[] charTable;
readonly int[] offsetTable;
public BoyerMoore(byte[] needle)
{
this.needle = needle;
this.charTable = makeByteTable(needle);
this.offsetTable = makeOffsetTable(needle);
}
public IEnumerable<int> Search(byte[] haystack)
{
if (needle.Length == 0)
yield break;
for (int i = needle.Length - 1; i < haystack.Length;)
{
int j;
for (j = needle.Length - 1; needle[j] == haystack[i]; --i, --j)
{
if (j != 0)
continue;
yield return i;
i += needle.Length - 1;
break;
}
i += Math.Max(offsetTable[needle.Length - 1 - j], charTable[haystack[i]]);
}
}
static int[] makeByteTable(byte[] needle)
{
const int ALPHABET_SIZE = 256;
int[] table = new int[ALPHABET_SIZE];
for (int i = 0; i < table.Length; ++i)
table[i] = needle.Length;
for (int i = 0; i < needle.Length - 1; ++i)
table[needle[i]] = needle.Length - 1 - i;
return table;
}
static int[] makeOffsetTable(byte[] needle)
{
int[] table = new int[needle.Length];
int lastPrefixPosition = needle.Length;
for (int i = needle.Length - 1; i >= 0; --i)
{
if (isPrefix(needle, i + 1))
lastPrefixPosition = i + 1;
table[needle.Length - 1 - i] = lastPrefixPosition - i + needle.Length - 1;
}
for (int i = 0; i < needle.Length - 1; ++i)
{
int slen = suffixLength(needle, i);
table[slen] = needle.Length - 1 - i + slen;
}
return table;
}
static bool isPrefix(byte[] needle, int p)
{
for (int i = p, j = 0; i < needle.Length; ++i, ++j)
if (needle[i] != needle[j])
return false;
return true;
}
static int suffixLength(byte[] needle, int p)
{
int len = 0;
for (int i = p, j = needle.Length - 1; i >= 0 && needle[i] == needle[j]; --i, --j)
++len;
return len;
}
}
Here's some console app test code for it:
public static void Main()
{
byte[] haystack = new byte[10000];
byte[] needle = { 0x00, 0x69, 0x73, 0x6F, 0x6D };
// Put a few copies of the needle into the haystack.
for (int i = 1000; i <= 9000; i += 1000)
Array.Copy(needle, 0, haystack, i, needle.Length);
var searcher = new BoyerMoore(needle);
foreach (int index in searcher.Search(haystack))
Console.WriteLine(index);
}
Note how the Search() method returns the indices of all the locations of the start of needle inside haystack.
If you just wanted the count, you could just do:
int count = new BoyerMoore(needle).Search(haystack).Count();
For your second question: I assume you are asking about finding the longest repeated sequence of bytes?
That's a much more complicated - and very different - question. If you want an answer for that, you should ask a separate question for it, but you should read the Wikipedia entry on the "longest repeated substring problem".
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 ;
}
}
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;
}