Converting Suprema Biostar C++ code to C# - c#

I got the Biostation T2 from Suprema, they provided a wrapped Dll made with C#, they also provide example using: VB6, VB.net, C++ and C#.Most of the documentation is in C++ and am having a hard time trying to convert that logic to C#.I am unable to enroll a user using the below functions in the pastie.Mainly cause am not sure if the logic in C# and C++ matches up.
See the C++ code for enrolling user and my C# attempt pastie
I get error attempted to read or write protected memory as captured here
Here ia a link of the sdk samples they provide sdk samples in vc,c#,C++

We have no way of compiling and testing your code with what you have shown us. That being said, comparing the c++ and c# side by side, I see the following inconsistencies:
The c++ has the following code:
unsigned char* templateBuf = (unsigned char*)malloc( userHeader.numOfFinger * 2 * BS_TEMPLATE_SIZE );
int bufPos = 0;
for( int i = 0; i < userHeader.numOfFinger * 2; i++ )
{
result = BS_ScanTemplate( handle, templateBuf + bufPos );
bufPos += BS_TEMPLATE_SIZE;
}
This code calls BS_ScanTemplate multiple times and stores the results sequentially in a byte array. Your code does the following:
byte[] templateBuf = new byte[userHdr.numOfFinger * 2 * BS_TEMPLATE_SIZE];
int bufPos = 0;
for (int i = 0; i < userHdr.numOfFinger * 2; i++)
{
templateBuf = new byte[userHdr.numOfFinger * 2 * BS_TEMPLATE_SIZE * bufPos];
result = BSSDK.BS_ScanTemplate(m_Handle, templateBuf);
bufPos += BS_TEMPLATE_SIZE;
}
Rather than storing the results of BS_ScanTemplate sequentially, this code throws away the results from each preceding call by reallocating the array. Perhaps you want something like:
byte[] templateBuf = new byte[userHdr.numOfFinger * 2 * BS_TEMPLATE_SIZE];
for (int i = 0, bufPos = 0; i < userHdr.numOfFinger * 2; i++)
{
byte[] singleBuf = new byte[BS_TEMPLATE_SIZE];
result = BSSDK.BS_ScanTemplate(m_Handle, singleBuf);
Array.Copy(singleBuf, 0, templateBuf, bufPos, singleBuf.Length);
bufPos += singleBuf.Length;
}
The c++ code does
for( int i = 0; i < userHeader.numOfFinger; i++ )
{
userHeader.duress[i] = 0; // no duress finger
}
The c# code does:
userHdr.duressMask = 0; // no duress finger
This is completely different.
The c++ code does:
for( int i = 0; i < userHeader.numOfFinger * 2; i++ )
{
if( i % 2 == 0 )
{
userHeader.fingerChecksum[i/2] = 0;
}
unsigned char* templateData = templateBuf + i * BS_TEMPLATE_SIZE;
for( int j = 0; j < BS_TEMPLATE_SIZE; j++ )
{
userHeader.fingerChecksum[i/2] += templateData[j];
}
}
The c# code does:
for (int i = 0; i < userHdr.numOfFinger * 2; i++)
{
if (i % 2 == 0)
{
userHdr.checksum[i / 2] = 0;
}
byte[] templateData = templateBuf;
for (int j = 0; j < 2000 - 1; j++)
{
userHdr.checksum[i / 2] += templateData[j];
}
}
As you can see the c++ code loops twice as many times as the c# code. The c# code probably should be:
for (int i = 0; i < userHdr.numOfFinger; i++)
{
if (i % 2 == 0)
{
userHdr.checksum[i / 2] = 0;
}
for (int j = 0; j < BS_TEMPLATE_SIZE; j++)
{
userHdr.checksum[i / 2] += templateBuf[i * BS_TEMPLATE_SIZE + j];
}
}
You don't show the c++ call to BS_EnrollUserBioStation2 in your pastie so it can't be compared with the c# call.
userHdr.checksum = new ushort[] { 0 }; looks wrong. Shouldn't it be something like userHdr.checksum = new ushort[userHdr.numOfFinger];
Thus I'd suggest the following:
Update BSUserHdrEx as follows:
public const int BS_MAX_NAME_LEN = 32;
public const int BS_MAX_PASSWORD_LEN = 16;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct BSUserHdrEx
{
public static BSUserHdrEx CreateDefaultBSUserHdrEx()
{
var userHdr = new BSUserHdrEx();
userHdr.name = new byte[BSSDK.BS_MAX_NAME_LEN + 1];
userHdr.department = new byte[BSSDK.BS_MAX_NAME_LEN + 1];
userHdr.password = new byte[BSSDK.BS_MAX_PASSWORD_LEN];
userHdr.checksum = new ushort[5];
return userHdr;
}
public uint ID;
public ushort reserved1;
public ushort adminLevel;
public ushort securityLevel;
public ushort statusMask; // internally used by BioStation
public uint accessGroupMask;
//char name[BS_MAX_NAME_LEN + 1];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = BSSDK.BS_MAX_NAME_LEN + 1)]
public byte[] name;
//char department[BS_MAX_NAME_LEN + 1];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = BSSDK.BS_MAX_NAME_LEN + 1)]
public byte[] department;
// char password[BS_MAX_PASSWORD_LEN + 1];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = BSSDK.BS_MAX_PASSWORD_LEN + 1)]
public byte[] password;
public ushort numOfFinger;
public ushort duressMask;
//public ushort checksum[5];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public ushort[] checksum;
public ushort authMode;
public ushort authLimitCount; // 0 for no limit
public ushort reserved;
public ushort timedAntiPassback; // in minutes. 0 for no limit
public uint cardID; // 0 for not used
public bool bypassCard;
public bool disabled;
public uint expireDateTime;
public uint customID; //card Custom ID
public int version; // card Info Version
public uint startDateTime;
};
Update btngetUserInfo_Click as follows:
private void btngetUserInfo_Click(object sender, EventArgs e)
{
int result;
BSSDK.BSUserHdrEx userHdr = BSSDK.BSUserHdrEx.CreateDefaultBSUserHdrEx();
userHdr.ID = 2; // 0 cannot be assigned as a user ID
userHdr.startDateTime = 0; // no check for start date
userHdr.expireDateTime = 0; // no check for expiry date
userHdr.adminLevel = BSSDK.BS_USER_NORMAL;
userHdr.securityLevel = BSSDK.BS_USER_SECURITY_DEFAULT;
userHdr.authMode = BSSDK.BS_AUTH_MODE_DISABLED; // use the authentication mode of the device
userHdr.accessGroupMask = 0xffff0201; // a member of Group 1 and Group 2;
Encoding.UTF8.GetBytes("Madman").CopyTo(userHdr.name, 0);
Encoding.UTF8.GetBytes("INC").CopyTo(userHdr.department, 0);
Encoding.UTF8.GetBytes("").CopyTo(userHdr.password, 0);
userHdr.password = Encoding.UTF8.GetBytes(""); // no password is enrolled. Password should be longer than 4 bytes.
userHdr.numOfFinger = 2;
byte[] templateBuf = new byte[userHdr.numOfFinger * 2 * BSSDK.BS_TEMPLATE_SIZE];
for (int i = 0, bufPos = 0; i < userHdr.numOfFinger * 2; i++)
{
byte[] singleBuf = new byte[BSSDK.BS_TEMPLATE_SIZE];
result = BSSDK.BS_ScanTemplate(m_Handle, singleBuf);
Array.Copy(singleBuf, 0, templateBuf, bufPos, singleBuf.Length);
bufPos += singleBuf.Length;
}
userHdr.duressMask = 0; // no duress finger
for (int i = 0; i < userHdr.numOfFinger * 2; i++)
{
if (i % 2 == 0)
{
userHdr.checksum[i / 2] = 0;
}
// byte[] templateData = templateBuf;
for (int j = 0; j < BSSDK.BS_TEMPLATE_SIZE; j++)
{
userHdr.checksum[i / 2] += templateBuf[i * BSSDK.BS_TEMPLATE_SIZE + j];
}
}
// enroll the user
result = BSSDK.BS_EnrollUserBioStation2(m_Handle, ref userHdr, templateBuf);
if (result == (int)BSSDK.BS_RET_CODE.BS_SUCCESS)
{
MessageBox.Show("user " + userHdr.name.ToString() + " enrolled");
}
update
The struct you are marshalling is BSUserHdrEx. BS_EnrollUserBioStation2 does not take this as an argument. BS_EnrollUserBioStation2 takes a BS2UserHdr as an argument (source: Page 158 of "BioStar SDK Manual V1.8.pdf".) BSUserHdrEx is an argument to BS_EnrollUserEx. (Page 129).
BS_EnrollUserEx "Enrolls a user to BioStation. Maximum 5 fingers can be enrolled per user."
BS_EnrollUserBioStation2 "Enrolls a user to BioStation T2. Maximum 10 fingers per user."
Either you need to switch to the former function, or use the latter data structure.

Related

ARC4 encryption not working correctly server side

I have a socket.io client which sends data to each other where encryption is based on ARC4.
I tried multiple different scenarios but it keeps failing to decrypt anything and I'm not sure why.
The class: ARC4_New
public class ARC4_New
{
private int i;
private int j;
private byte[] bytes;
public const int POOLSIZE = 256;
public ARC4_New()
{
bytes = new byte[POOLSIZE];
}
public ARC4_New(byte[] key)
{
bytes = new byte[POOLSIZE];
this.Initialize(key);
}
public void Initialize(byte[] key)
{
this.i = 0;
this.j = 0;
for (i = 0; i < POOLSIZE; ++i)
{
this.bytes[i] = (byte)i;
}
for (i = 0; i < POOLSIZE; ++i)
{
j = (j + bytes[i] + key[i % key.Length]) & (POOLSIZE - 1);
this.Swap(i, j);
}
this.i = 0;
this.j = 0;
}
private void Swap(int a, int b)
{
byte t = this.bytes[a];
this.bytes[a] = this.bytes[b];
this.bytes[b] = t;
}
public byte Next()
{
this.i = ++this.i & (POOLSIZE - 1);
this.j = (this.j + this.bytes[i]) & (POOLSIZE - 1);
this.Swap(i, j);
return this.bytes[(this.bytes[i] + this.bytes[j]) & 255];
}
public void Encrypt(ref byte[] src)
{
for (int k = 0; k < src.Length; k++)
{
src[k] ^= this.Next();
}
}
public void Decrypt(ref byte[] src)
{
this.Encrypt(ref src);
}
}
public System.Numerics.BigInteger RandomInteger(int bitSize)
{
var integerData = new byte[bitSize / 8];
_numberGenerator.NextBytes(integerData);
integerData[integerData.Length - 1] &= 0x7f;
return new System.Numerics.BigInteger(integerData);
}
My script which generates a key:
System.Numerics.BigInteger DHPrivate = RandomInteger(256);
System.Numerics.BigInteger DHPrimal = RandomInteger(256);
System.Numerics.BigInteger DHGenerated = RandomInteger(256);
if (DHGenerated > DHPrimal)
{
System.Numerics.BigInteger tempG = DHGenerated;
DHGenerated= DHPrimal;
DHPrimal = tempG;
}
Then with those values I generate a public key:
System.Numerics.BigInteger DHPublic = System.Numerics.BigInteger.ModPow(DHGenerated, DHPrivate, DHPrimal);
Then I encrypt this key:
string pkey = EncryptY(CalculatePublic, DHPublic);
(Additional code for the encryption below)
protected virtual string EncryptY(Func<System.Numerics.BigInteger, System.Numerics.BigInteger> calculator, System.Numerics.BigInteger value)
{
byte[] valueData = Encoding.UTF8.GetBytes(value.ToString());
valueData = PKCSPad(valueData);
Array.Reverse(valueData);
var paddedInteger = new System.Numerics.BigInteger(valueData);
System.Numerics.BigInteger calculatedInteger = calculator(paddedInteger);
byte[] paddedData = calculatedInteger.ToByteArray();
Array.Reverse(paddedData);
string encryptedValue = Utils.Converter.BytesToHexString(paddedData).ToLower();
return encryptedValue.StartsWith("00") ? encryptedValue.Substring(2) : encryptedValue;
}
protected virtual byte[] PKCSPad(byte[] data)
{
var buffer = new byte[128 - 1];
int dataStartPos = (buffer.Length - data.Length);
buffer[0] = (byte)Padding;
Buffer.BlockCopy(data, 0, buffer, dataStartPos, data.Length);
int paddingEndPos = (dataStartPos - 1);
bool isRandom = (Padding == PKCSPadding.RandomByte);
for (int i = 1; i < paddingEndPos; i++)
{
buffer[i] = (byte)(isRandom ?
_numberGenerator.Next(1, 256) : byte.MaxValue);
}
return buffer;
}
After all that I sent the string PKEY to the server.
And after decrypting the string, the server gets the public key which is for example: 127458393
When I connect both my client and server using: 127458393
Like:
BigInteger key = System.Numerics.BigInteger.Parse("127458393");
client = new ARC4_New(PrimalDing.ToByteArray());
My client sends a string like:
client.Encrypt(BYTE_HERE);
And my server reads it like:
client.Decrypt(BYTE_HERE);
But it fails, and gets a random unreadable string.
What am I doing wrong here?
I managed to fix the issue
For some reason, my server was and is reversing the bytes i used in the ARC4 client..
So i simple reverse it now as a hotfix
System.Numerics.BigInteger temp = System.Numerics.BigInteger.Parse(textBox1.Text);
client = new ARC4_New(temp.ToByteArray().Reverse().ToArray());

Calculate values of the spectrum with FFT

I have to calculate the spectrum values of an audio.
I used aForge's FFT in Sources/Math/FourierTransform.cs and I used an example of sampling with 16 samples as used in this video to check the results with excel (I tested the results in a spreadsheet like in the video).
FFT:
public enum Direction
{
Forward = 1,
Backward = -1
};
private const int minLength = 2;
private const int maxLength = 16384;
private const int minBits = 1;
private const int maxBits = 14;
private static int[][] reversedBits = new int[maxBits][];
private static Complex[,][] complexRotation = new Complex[maxBits, 2][];
static void Main(string[] args)
{
var Data = new Complex[16];
Data[0] = new Complex(0, 0);
Data[1] = new Complex((float)0.998027, 0);
Data[2] = new Complex((float)0.125333, 0);
Data[3] = new Complex((float)-0.98229, 0);
Data[4] = new Complex((float)-0.24869, 0);
Data[5] = new Complex((float)0.951057, 0);
Data[6] = new Complex((float)0.368125, 0);
Data[7] = new Complex((float)-0.90483, 0);
Data[8] = new Complex((float)-0.48175, 0);
Data[9] = new Complex((float)0.844328, 0);
Data[10] = new Complex((float)0.587785, 0);
Data[11] = new Complex((float)-0.77051, 0);
Data[12] = new Complex((float)-0.68455, 0);
Data[13] = new Complex((float)0.684547, 0);
Data[14] = new Complex((float)0.770513, 0);
Data[15] = new Complex((float)-0.58779, 0);
FFT(Data, Direction.Forward);
for (int a = 0; a <= Data.Length - 1; a++)
{
Console.WriteLine(Data[a].Re.ToString());
}
Console.ReadLine();
}
public static void FFT(Complex[] data, Direction direction)
{
int n = data.Length;
int m = Tools.Log2(n);
// reorder data first
ReorderData(data);
// compute FFT
int tn = 1, tm;
for (int k = 1; k <= m; k++)
{
Complex[] rotation = GetComplexRotation(k, direction);
tm = tn;
tn <<= 1;
for (int i = 0; i < tm; i++)
{
Complex t = rotation[i];
for (int even = i; even < n; even += tn)
{
int odd = even + tm;
Complex ce = data[even];
Complex co = data[odd];
double tr = co.Re * t.Re - co.Im * t.Im;
double ti = co.Re * t.Im + co.Im * t.Re;
data[even].Re += tr;
data[even].Im += ti;
data[odd].Re = ce.Re - tr;
data[odd].Im = ce.Im - ti;
}
}
}
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
}
private static int[] GetReversedBits(int numberOfBits)
{
if ((numberOfBits < minBits) || (numberOfBits > maxBits))
throw new ArgumentOutOfRangeException();
// check if the array is already calculated
if (reversedBits[numberOfBits - 1] == null)
{
int n = Tools.Pow2(numberOfBits);
int[] rBits = new int[n];
// calculate the array
for (int i = 0; i < n; i++)
{
int oldBits = i;
int newBits = 0;
for (int j = 0; j < numberOfBits; j++)
{
newBits = (newBits << 1) | (oldBits & 1);
oldBits = (oldBits >> 1);
}
rBits[i] = newBits;
}
reversedBits[numberOfBits - 1] = rBits;
}
return reversedBits[numberOfBits - 1];
}
private static Complex[] GetComplexRotation(int numberOfBits, Direction direction)
{
int directionIndex = (direction == Direction.Forward) ? 0 : 1;
// check if the array is already calculated
if (complexRotation[numberOfBits - 1, directionIndex] == null)
{
int n = 1 << (numberOfBits - 1);
double uR = 1.0;
double uI = 0.0;
double angle = System.Math.PI / n * (int)direction;
double wR = System.Math.Cos(angle);
double wI = System.Math.Sin(angle);
double t;
Complex[] rotation = new Complex[n];
for (int i = 0; i < n; i++)
{
rotation[i] = new Complex(uR, uI);
t = uR * wI + uI * wR;
uR = uR * wR - uI * wI;
uI = t;
}
complexRotation[numberOfBits - 1, directionIndex] = rotation;
}
return complexRotation[numberOfBits - 1, directionIndex];
}
// Reorder data for FFT using
private static void ReorderData(Complex[] data)
{
int len = data.Length;
// check data length
if ((len < minLength) || (len > maxLength) || (!Tools.IsPowerOf2(len)))
throw new ArgumentException("Incorrect data length.");
int[] rBits = GetReversedBits(Tools.Log2(len));
for (int i = 0; i < len; i++)
{
int s = rBits[i];
if (s > i)
{
Complex t = data[i];
data[i] = data[s];
data[s] = t;
}
}
}
These are the results after the transformation:
Output FFT results: Excel FFT results:
0,0418315622955561 0,669305
0,0533257974328085 0,716163407
0,137615673627316 0,908647001
0,114642731070279 1,673453043
0,234673940537634 7,474988602
0,0811255020953362 0,880988382
0,138088891589122 0,406276784
0,0623766891658306 0,248854492
0,0272978749126196 0,204227
0,0124250144575261 0,248854492
0,053787064184711 0,406276784
0,00783331226557493 0,880988382
0,0884368745610118 7,474988602
0,0155431246384978 1,673453043
0,0301093757152557 0,908647001
0 0,716163407
The results are not at all similar. Where is it wrong?
Is the implementation of complex (Data) wrong or is the FFT method wrong or other?
Thanks in advance!
First, the resulting FFT is a complex function in general. You're only displaying the real parts in your code but the thing you're comparing to is displaying the magnitudes, so of course they're going to be different: you're comparing apples to oranges.
When you use magnitudes and compare apples to apples, you should get this:
for (int a = 0; a <= Data.Length - 1; a++)
{
Console.WriteLine(Data[a].Magnitude.ToString());
}
...
0.0418315622955561
0.0447602132472683
0.0567904388057513
0.104590813761862
0.46718679147454
0.0550617784710375
0.025392294285886
0.0155534081359397
0.0127641875296831
0.0155534081359397
0.025392294285886
0.0550617784710375
0.46718679147454
0.104590813761862
0.0567904388057513
0.0447602132472683
That looks a little better -- it has the same symmetry property as the Excel output and there appear to be peaks in the same locations.
It almost looks like the scale is off. If I divide each element by the corresponding element from the Excel output, I get:
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
So your results are pretty much correct, just off by a scaling factor.
You're dividing everything by n in the last step of your FFT:
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
This is conventionally done for the inverse transform, not the forward transform.
In summary, changing the output from Data[a].Re to Data[a].Magnitude and changing the condition at the end of FFT from if (direction == Direction.Forward) to if (direction == Direction.Backward), I get this output:
0.669304996728897
0.716163411956293
0.908647020892022
1.67345302018979
7.47498866359264
0.880988455536601
0.406276708574176
0.248854530175035
0.20422700047493
0.248854530175035
0.406276708574176
0.880988455536601
7.47498866359264
1.67345302018979
0.908647020892022
0.716163411956293
which matches the Excel output.

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.

C# Function to translate Binary-Code

Right now I try to write a C# Program to translate 8 Base Binary into Text.
But I guess I am not experienced enough with C# to truly make it Work.
I think the code I come up with, should, from a logical Point-of-View somewhat do what I want, but the Syntax isn't properly doing it, since donĀ“t know it better.
This is what I have so far:
using System;
using System.Linq;
using System.Text;
class binaryTranslate
{
public int convertBin(string CodeInput)
{
int [] code = CodeInput.ToArray();
int CodeCount = code.ToString().Length;
int EightBaseSegAmount = CodeCount / 8;
int ByteCapacity = 8;
StringBuilder translated = new StringBuilder();
for (var i = 1; i < EightBaseSegAmount + 1; i++)
{
StringBuilder Byte = new StringBuilder(ByteCapacity);
int ByteStart = (i * 8) - 8;
int ByteEnd = (i * 8) - 1;
int ByteIncrement = 1;
for (var j = ByteStart ; j < ByteEnd + 1; j++)
{
Byte.Append(code[j]);
}
for (var k = 0; k > 7; k++)
{
int BitValue = 128;
if (Byte[k] == 1)
{
if (k > 0)
{
int Squared = Math.Pow(2, k);
ByteIncrement += BitValue / Squared;
}
else
{
ByteIncrement += BitValue;
}
}
}
char toSymbol = Convert.ToChar(ByteIncrement);
translated.Append(toSymbol);
}
return translated;
}
public static int Main()
{
convertBin("010010000110000101101100011011000110111100100001");
}
}
First of all, your code won't compile. Here are the errors/mistakes.
The first one is, at the first line of your function, you are converting the input string to an array using String.ToArray(), which returns a char[] but your try to assign it to a variable (code) typed int[]. You can solve this by replacing the int[] with either char[] or var.
The second one is, inside the second for loop (k = 0; k > 7), you use Math.Pow() and assign it's return value to an int variable (Squared). But Math.Pow returns double. You can solve this by casting the return value of Math.Pow to int. Like; int Squared = (int)Math.Pow(2, k);
The last thing is not easily solvable like the first two because, your code is not exactly correct. You are trying to return something called translated, which is a variable of type StringBuilder. But your function is defined to return an int.
Now these were compile errors. There are a bunch of logical and decision errors/mistakes. Your algorithm also isn't very correct.
Here is a sample code you can use/examine. I'd like to help you further, why your code was incorrect, what was your design mistakes etc. if you want to.
class binaryTranslate
{
public enum IncompleteSegmentBehavior
{
Skip = 0,
ZerosToStart = 1,
ZerosToEnd = 2
}
private byte ConvertBinstrToByte(string sequence)
{
if (string.IsNullOrEmpty(sequence))
return 0; // Throw?
if (sequence.Length != sizeof(byte) * 8)
return 0; // Throw?
const char zero = '0';
const char one = '1';
byte value = 0;
for (int i = 0; i < sequence.Length; i++)
{
if (sequence[i] != zero && sequence[i] != one)
return 0; // Throw
value |= (byte)((sequence[i] - zero) << (7 - i));
}
return value;
}
private string HandleIncompleteSegment(string segment, int segmentSize, IncompleteSegmentBehavior behavior)
{
string result = null;
var zeroAppender = new StringBuilder();
for (int i = 0; i < segmentSize - segment.Length; i++)
zeroAppender.Append('0');
var zeros = zeroAppender.ToString();
switch (behavior)
{
case IncompleteSegmentBehavior.Skip:
break;
case IncompleteSegmentBehavior.ZerosToStart:
result = zeros + result;
break;
case IncompleteSegmentBehavior.ZerosToEnd:
result = result + zeros;
break;
default:
break;
}
return result;
}
public byte[] ConvertBinstrToBytes(string binarySequence, IncompleteSegmentBehavior behavior = IncompleteSegmentBehavior.Skip)
{
var segmentSize = sizeof(byte) * 8;
var sequenceLength = binarySequence.Length;
var numberOfBytes = (int)Math.Ceiling((double)sequenceLength / segmentSize);
var bytes = new byte[numberOfBytes];
for (int i = 0; i < numberOfBytes; i++)
{
var charactersLeft = sequenceLength - i * segmentSize;
var segmentLength = (charactersLeft < segmentSize ? charactersLeft : segmentSize);
var segment = binarySequence.Substring(i * segmentSize, segmentLength);
if (charactersLeft < segmentSize)
{
segment = HandleIncompleteSegment(segment, segmentSize, behavior);
if (segment == null)
continue;
}
bytes[i] = ConvertBinstrToByte(segment);
}
return bytes;
}
}
This code passes these assertions.
var bytes = new binaryTranslate()
.ConvertBinstrToBytes("00000000");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b00000000);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("10000000");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b10000000);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("11111111");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b11111111);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("00000001");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b00000001);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("1100110000110011");
Assert.Equal(bytes.Length, 2);
Assert.Equal(bytes[0], 0b11001100);
Assert.Equal(bytes[1], 0b00110011);
If you are really converting to a string the code should look like this
namespace binaryTranslate
{
class Program
{
static void Main(string[] args)
{
//convertBin("01001000 01100001 01101100 01101100 01101111 00100001");
string results = BinaryTranslate.convertBin(new byte[] { 0x44, 0x61, 0x6c, 0x6c, 0x6f, 0x21 });
}
}
public class BinaryTranslate
{
public static string convertBin(byte[] CodeInput)
{
return string.Join("", CodeInput.Select(x => x.ToString("X2")));
}
}
}
this should do the trick.
public static string FromBinary(string binary)
{
int WordLength = 8;
binary = binary.Replace(' ', '');
while(binary.Length % WordLength != 0)
binary += "0";
string output = String.Empty;
string word = String.Empty;
int offset = 0;
while(offset < binary.Length)
{
int tmp = 0;
word = binary.Substring(offset, 8);
for(int i=0; i<(WordLength - 1); i++)
if(word[i] == '1')
tmp += (int) Math.Pow(2, i);
output += Convert.ToChar(tmp);
offset += WordLength;
}
return output;
}

Get longest substring between two strings

I have two words,
britanicaeng and
britanicahin
I need to find out the longest common word between these i.e, britanica.
How can I do this in C# ?
Try this method:
public static string FindLongestCommonSubstring(string s1, string s2)
{
int[,] a = new int[s1.Length + 1, s2.Length + 1];
int row = 0; // s1 index
int col = 0; // s2 index
for (var i = 0; i < s1.Length; i++)
for (var j = 0; j < s2.Length; j++)
if (s1[i] == s2[j])
{
int len = a[i + 1, j + 1] = a[i, j] + 1;
if (len > a[row, col])
{
row = i + 1;
col = j + 1;
}
}
return s1.Substring(row - a[row, col], a[row, col]);
}
Usage example:
Console.WriteLine(FindLongestCommonSubstring("britanicaeng", "britanicahin"));
I refactored the C++ code from Ashutosh Singh at https://iq.opengenus.org/longest-common-substring-using-rolling-hash/ to create a rolling hash approach in C# - this will find the substring in O(N * log(N)^2) time and O(N) space
using System;
using System.Collections.Generic;
public class RollingHash
{
private class RollingHashPowers
{
// _mod = prime modulus of polynomial hashing
// any prime number over a billion should suffice
internal const int _mod = (int)1e9 + 123;
// _hashBase = base (point of hashing)
// this should be a prime number larger than the number of characters used
// in my use case I am only interested in ASCII (256) characters
// for strings in languages using non-latin characters, this should be much larger
internal const long _hashBase = 257;
// _pow1 = powers of base modulo mod
internal readonly List<int> _pow1 = new List<int> { 1 };
// _pow2 = powers of base modulo 2^64
internal readonly List<long> _pow2 = new List<long> { 1L };
internal void EnsureLength(int length)
{
if (_pow1.Capacity < length)
{
_pow1.Capacity = _pow2.Capacity = length;
}
for (int currentIndx = _pow1.Count - 1; currentIndx < length; ++currentIndx)
{
_pow1.Add((int)(_pow1[currentIndx] * _hashBase % _mod));
_pow2.Add(_pow2[currentIndx] * _hashBase);
}
}
}
private class RollingHashedString
{
readonly RollingHashPowers _pows;
readonly int[] _pref1; // Hash on prefix modulo mod
readonly long[] _pref2; // Hash on prefix modulo 2^64
// Constructor from string:
internal RollingHashedString(RollingHashPowers pows, string s, bool caseInsensitive = false)
{
_pows = pows;
_pref1 = new int[s.Length + 1];
_pref2 = new long[s.Length + 1];
const long capAVal = 'A';
const long capZVal = 'Z';
const long aADif = 'a' - 'A';
unsafe
{
fixed (char* c = s)
{
// Fill arrays with polynomial hashes on prefix
for (int i = 0; i < s.Length; ++i)
{
long v = c[i];
if (caseInsensitive && capAVal <= v && v <= capZVal)
{
v += aADif;
}
_pref1[i + 1] = (int)((_pref1[i] + v * _pows._pow1[i]) % RollingHashPowers._mod);
_pref2[i + 1] = _pref2[i] + v * _pows._pow2[i];
}
}
}
}
// Rollingnomial hash of subsequence [pos, pos+len)
// If mxPow != 0, value automatically multiply on base in needed power.
// Finally base ^ mxPow
internal Tuple<int, long> Apply(int pos, int len, int mxPow = 0)
{
int hash1 = _pref1[pos + len] - _pref1[pos];
long hash2 = _pref2[pos + len] - _pref2[pos];
if (hash1 < 0)
{
hash1 += RollingHashPowers._mod;
}
if (mxPow != 0)
{
hash1 = (int)((long)hash1 * _pows._pow1[mxPow - (pos + len - 1)] % RollingHashPowers._mod);
hash2 *= _pows._pow2[mxPow - (pos + len - 1)];
}
return Tuple.Create(hash1, hash2);
}
}
private readonly RollingHashPowers _rhp;
public RollingHash(int longestLength = 0)
{
_rhp = new RollingHashPowers();
if (longestLength > 0)
{
_rhp.EnsureLength(longestLength);
}
}
public string FindCommonSubstring(string a, string b, bool caseInsensitive = false)
{
// Calculate max neede power of base:
int mxPow = Math.Max(a.Length, b.Length);
_rhp.EnsureLength(mxPow);
// Create hashing objects from strings:
RollingHashedString hash_a = new RollingHashedString(_rhp, a, caseInsensitive);
RollingHashedString hash_b = new RollingHashedString(_rhp, b, caseInsensitive);
// Binary search by length of same subsequence:
int pos = -1;
int low = 0;
int minLen = Math.Min(a.Length, b.Length);
int high = minLen + 1;
var tupleCompare = Comparer<Tuple<int, long>>.Default;
while (high - low > 1)
{
int mid = (low + high) / 2;
List<Tuple<int, long>> hashes = new List<Tuple<int, long>>(a.Length - mid + 1);
for (int i = 0; i + mid <= a.Length; ++i)
{
hashes.Add(hash_a.Apply(i, mid, mxPow));
}
hashes.Sort(tupleCompare);
int p = -1;
for (int i = 0; i + mid <= b.Length; ++i)
{
if (hashes.BinarySearch(hash_b.Apply(i, mid, mxPow), tupleCompare) >= 0)
{
p = i;
break;
}
}
if (p >= 0)
{
low = mid;
pos = p;
}
else
{
high = mid;
}
}
// Output answer:
return pos >= 0
? b.Substring(pos, low)
: string.Empty;
}
}

Categories

Resources