Find similarities in a binary string - c#

I am currently trying to write a function that would help me find similarities between binary strings. This sounds vague so I will explain with an example.
StringA : 10111010000
StringB : 10111010011
StringC : 10111101111
I want my program to be able to find any similarities (4 digits or more) occuring at the same index. In the above example, my function would return : 0-4 (because caracters 0 to 4 are identical in all three strings).
I am not looking for code, just a logical and optimal way of doing this.

String is Array of Char.
You should do Loop in which you would compare each char.
For Example: (I had to put example, sorry)
for(int i=0;i<=length;i++) \\length = array lenght
{
if(StringA[i]==StringB[i]) CounterA++; \\or something like this
}

method 1: split the strings into either an Array, or a List, then use LINQ to find the groupings within the list...
method 2: loop through each string, then through each character, then create a new string with the character length, and compare to the same substring on the other strings...

Assuming all three items are stored in their own respective variables, I would split all of the bits into an array. From there, I would iterate through one array (since all of the arrays are the same size) and match from there. This operation would be O(n) since you have to look at n items.

Pseudocode?
array := array[numbers]
for each binary number
for each binary number
if numbers have the same binary digit at current index
array[index] := array[index] + 1
end
end
end

Iterate each character in the string, if they match add to a counter:
private static int GetDifferences(string firstStr, string secondStr)
{
int val = 0;
char[] first = firstStr.ToCharArray();
char[] second = secondStr.ToCharArray();
for (int i = 0; i < first.Length; i++)
{
if (first[i] == second[i])
{
val++;
}
}
return val;
}
By no means perfect but should get you started

i'd split them into a list:
static void Main()
{
var a = "10111010000";
var b = "10111010011";
var c = "10111101111";
var aList = Split(a, 4); //Use a custom split method
var bList = Split(b, 4);
var cList = Split(c, 4);
Dictionary<int,string> hits = new Dictionary<int, string>();
for (int i = 0; i < aList.Count(); i++)
{
if(aList[i] == bList[i] && bList[i] == cList[i])
hits.Add(i,aList[i]);
}
}

Probably you could use Bitwise operators:
get XOR result from A/B (say:A^B) and A/C (say:A^C)
get NOT result of step 1: ~(A^B); ~(A^C)
get And result from step 2: (~(A^B))&(~(A^C))
get the 1 part from step 3.
e.g.:
1.
A^B=10111010000^
10111010011
=00000000011;
A^C=10111010000^
10111101111
=00000111111
2.
~(A^B)=~(00000000011)=11111111100;
~(A^C)=~(00000111111)=11111000000;
3.
(~(A^B))&(~(A^C)) =11111111100&
11111000000
=11111000000

If you were just wanting to get a true or false as to whether there is a minimum of 4 matching characters, you could do this:
Public Function StringsHaveMin4CharsInCommon(ByVal StringA As String, ByVal StringB As String, ByVal StringC As String) As Boolean
Dim bReturn As Boolean
Dim iCounter As Integer
For i As Integer = 0 To StringA.Length - 1
If StringA.SubString(i, 1) = StringB.SubString(i, 1) And StringB.SubString(i, 1) = StringC.SubString(i, 1) Then iCounter += 1
If iCounter = 4 Then
bReturn = True
Exit For
End If
Next i
Return bReturn
End Function
If you wanted to retrieve the matching array indices then you would need to add logic to the same procedure to add each matching index to an Integer array and return that array from the function as follows.
Public Function GetCommonIndices(ByVal StringA As String, ByVal StringB As String, ByVal StringC As String) As Integer()
Dim iReturn() As Integer
Dim iCounter As Integer = -1
For i As Integer = 0 To StringA.Length - 1
If StringA.SubString(i, 1) = StringB.SubString(i, 1) And StringB.SubString(i, 1) = StringC.SubString(i, 1) Then
iCounter += 1
ReDim Preserve iReturn(iCounter)
iReturn(iCounter) = i
End If
Next i
Return iReturn
End Function
The function will return Nothing if there are no matching indices.
The functions only test for the length of StringA so it will throw an error if either StringB or StringC is shorter than String A. I inferred that the strings that you will be testing will be pre-validated as being all equal in length.

Related

How to check if a number exists in a specified digit of an integer ( C# )

I want to generally verify if a number/character exists within a specified index of an int value.
Here is pseudocode of what I want
if (octet[1].Exists){
return true;
} else {
return false;
}
// receiving int octet = 103 will return true.
// receiving int octet = 7 will return false.
Is there a function that already does this, or do you have to make one on your own?
Convert to a string then check the length?
var str = octet.ToString();
return str.Length >= 1;
I don't know a function like this, but you can write your own.
In instance:
var func = (int octet, int index) => (octet / (int)(Math.Pow(10, index)) != 0);
I would suggest using a System.Linq binding for this. Here is an example:
octet.ToString().Contains(n);
Where n is the digit you're looking for in string or char form. Hope this helps!
Just parse the int to a string and check if the number you are looking is equal to expected position.
var number = 12345;
if(number.ToString().IndexOf('2') == 1)//check if the value 2 is on the second position of the array
{
Console.WriteLine("yes");
}

Why we use -1 within a for Loop c#

I have code which checks if a word if a palindrome or not. Within the for loop there is a -1 value. Can someone explain to me why -1 is used after the name.Length in c#
public static void Main()
{
string name = "Apple";
string reverse = string.Empty;
for (int i = name.Length - 1; i >= 0; i--)
{
reverse +=name[i];
}
if (name == reverse)
{
Console.WriteLine($"{name} is palindrome");
}else
{
Console.WriteLine($"{name} is not palindrome");
}
That's because whoever wrote the code, wanted to write:
reverse += name[i];
String operator [] takes values from 0 upto (string's length-1). If you pass length or more, you will get an exception. So, code's author had to ensure that i==Length won't be ever passed there. So it starts from Length-1 and counts downwards.
Also, note that the other bound of i is 0 (>=, not >, so 0 is included), so the loop visits all values from 0 to length-1, so it visits all characters from the string. Job done.
However, it doesn't have to be written in that way. The only thing is to ensure that the string operator [] wont see values of of its range. Compare this loop, it's identical in its results:
for (int i = name.Length; i >= 1; i--)
{
reverse += name[i-1];
}
Note that I also changed 0 to 1.
Of course, it's also possible to write a loop with the same effects in a lot of other ways.
The first element in an array is at the index 0 (array[0]). Because the indexing starts at 0 instead of 1 it means that the final element in the array will be at index array.Length-1.
If you had the word and then your array would look like:
name[0] = 'a'
name[1] = 'n'
name[2] = 'd'
the name.Length would equal 3. As you can see, there isn't an element at index 3 in the array so you need to subtract 1 from the length of the array to access the last element.
The for loop in your example starts with the last element in the array (using i as the index). If you tried to set i to i = name.Length then you would get an index out of bounds error because there isn't an element at the position name.Length.
String operator [] takes values from 0. The first element in an string is at the index 0, so we need to adjust by subtracting one.
For Example:
string str = "test";
int length = str.length; //Length of the str is 4. (0 to 3)

Maximum product of 13 adjacent numbers

List<int> arr = new List<int>();
long max = 0;
long mul = 1;
string abc = #"73167176531330624919225119674426574742355349194934
85861560789112949495459501737958331952853208805511
96983520312774506326239578318016984801869478851843
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450";
foreach (char a in abc)
{
if(arr.Count == 13)
{
arr.RemoveAt(0);
}
int value = (int)Char.GetNumericValue(a);
arr.Add(value);
if(arr.Count == 13)
{
foreach(int b in arr)
{
mul = mul * b;
if (mul > max)
{
max = mul;
}
}
mul = 1;
}
}
Console.WriteLine(max);
I am getting 5377010688 which is a wrong answer and when I am trying same logic with given example in project Euler it is working fine, please help me.
Don't say the answer just correct me where I am doing wrong or where the code is not running as it should.
The string constant, as it is written down like above, contains blanks and \r\n's, e.g. between the last '4' of the first line and the first '8' on the second line. Char.GetNumericValue() returns -1 for a blank.
Propably the character sequence with the highest product spans across adjacent lines in your string, therefore there are blanks in between, which count as -1, which disables your code in finding them.
Write your constant like this:
string abc = #"73167176531330624919225119674426574742355349194934" +
"85861560789112949495459501737958331952853208805511" +
"96983520312774506326239578318016984801869478851843" + etc.
The result is then 23514624000, I hope that's correct.
Don't say the answer just correct me where I am doing wrong or where
the code is not running as it should
You have included all characters into calculation but you should not do that. The input string also contains for example carriage return '\n' at the end of each line.
Your actual string look like this:
string abc = #"73167176531330624919225119674426574742355349194934\r\n
85861560789112949495459501737958331952853208805511\r\n
...
How to solve this? You should ignore these characters, one possible solution is to check each char if it is a digit:
if(!char.IsDigit(a))
{
continue;
}

C# split 20 digit numbers and assign it to 5 string variables

I need guide as to how I can split 20 digit numbers (e.g 77772222666611118888) and uniquely assign to five declared int variables e.g int n1,n2,n3,n4,n5.
Expected result
int mynumber = 77772222666611118888;
And, after the splitting and assigning, one gets the following:
n1=7777;
n2=2222;
n3=6666;
n4=1111;
n5=8888;
Thanks
You can use a simple regex for it
string mynumber = "77772222666611118888";
var ns = Regex.Matches(mynumber, #"\d{4}").Cast<Match>()
.Select(x => x.Value)
.ToList();
If you need to use separate variables, you could do this:
string mynumber = "77772222666611118888";
string n1 = mynumber.Substring(0, 4);
string n2 = mynumber.Substring(4, 4);
string n3 = mynumber.Substring(8, 4);
string n4 = mynumber.Substring(12, 4);
string n5 = mynumber.Substring(16, 4);
If you're willing to use an array or another collection, you could do this:
int stringSize = 4;
string[] n = new string[mynumber.Length / stringSize];
for (int i = 0; i < n.Length; i ++)
{
n[i] = mynumber.Substring(i*4, stringSize);
}
You'll need a long or Decimal to store the initial number, as its too long for an int.
Once that is done, use modulus to get the digits (in reverse), and division to get rid of the used numbers:
long tempNumber = number;
List<long> splitNumbers = new List<long>();
while (tempNumber > 0)
{
long currentDigits = number % 10000;
tempNumber = tempNumber / 10000; //Make sure this is integer division!
//Store cuurentDigits off in your variables
// 8888 would be the first number returned in this loop
// then 1111 and so on
splitNumbers.Add(currentDigits);
}
//We got the numbers backwards, so reverse the list
IEnumerable<long> finalNumberList = splitNumbers.Reverse();
You could also turn it into a string, and use .Take(4) and int.Parse to get your numbers.
You should convert myNumber to a string first,
then extract each part of this number using the substring function
and parse those strings back to the desired integers
You haven't defined what the rules are for performing the split you asked about. Are you splitting based on position and length? Are you splitting based on runs of identical digits?
Assuming you're splitting based on runs of identical digits, you could use a backreference like so,
Regex rxSameDigits = new Regex(#"(\d)(\1)*") ;
The \1 says, use the value of the specified group, in this case, the group starting with the first left parenthesis in the regex. So it says to
Match any digit, followed by
zero or more of the exact same digit
So it will match sequences like 1, 22, 333, etc. So you can simply say:
string s = "1223334444555556666667777777888888889999999990000000000" ;
string[] split = rxSameDigits.Matches(s).Cast<Match>().Select( x => x.Value ).ToArray() ;
And get the expected
1
22
333
4444
55555
666666
7777777
88888888
999999999
0000000000

Calculate all possible positions of 1 in a bit array

I have a method that receives a number n as parameter and calculate all possible combinition containing exactly n 1 in a bit(0,1) array, the result returned is the positions of the number 1
for example suppose that our bit array has 3 elements and
for n = 1
the function gives : [0] - [1] - [2] (three possible positions)
for n=2
the result will be [0,1] - [0,2] - [1,2] (three possible positions)
and for n=3
the result will be [0,1,2] (one possible position)
the function work correctly for an array with 3 elements, but gives wrong results for 4 elements
n = 2 result : [0,1] - [0,2] - [0,3] -[1,2] - [1,3] - [1,2,3]
Can any one explain why it gives unexpected results for arraysize >= 4
Thanks in advance
const int arraySize = 4;
static private void Positions(int n, int start, ArrayList prepend, ArrayList results)
{
ArrayList tmp = new ArrayList(prepend);
int end = arraySize - n;
for (int i = start; i <= end; i++)
{
if (end < arraySize - 1)
{
prepend.Add(i);
Positions(n - 1, i + 1, prepend, results);
prepend = tmp;
}
else
results.Add(new ArrayList(prepend) { i });
}
}
this is how i use the method
static void Main(string[] args)
{
ArrayList results = new ArrayList();
Positions(2, 0, new ArrayList(), results);
foreach (ArrayList array in results)
{
foreach (var elem in array)
Console.Write(elem);
Console.WriteLine();
}
Console.Read();
}
I think the issue is in this line:
prepend = tmp;
You are intending I think to restore the state of the prepend array to the original at the beginning of the method. However, you are setting a direct reference, so with every loop iteration you are modifying the original prepend array. If you copy the array here as well every time, it seems to work correctly:
prepend = new ArrayList(tmp);
All this copying of arrays, however, is not very efficient. You can try removing the entry you just added as well as another alternative:
prepend.Add(i);
Positions(n - 1, i + 1, prepend);
prepend.Remove(i);
Then technically you don't even need the tmp copy any more.
Edit: Also, for your if statement, I think you want something like
if (n > 1)

Categories