Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store two Binary Strings in C# and use OR operator

Tags:

c#

Input:

10101
11100

I would like to store this two strings in a datatype so that I can call the | OR operator on the two.

Here is my code:

        var g = new byte[2][];

        g[0] = "10101".Select(item => byte.Parse(item.ToString())).ToArray();
        g[1] = "11100".Select(item => byte.Parse(item.ToString())).ToArray();

        //won't compile
        Console.WriteLine(g[0] | g[1]);

The compiler error I am getting is:

Cannot apply operator '|' to operands byte[] and byte[]

I have also tried BitArray but this didn't seem right either. And I tried byte.Parse("10101") which just causes an overflow, this makes some sense to me.

What I am trying to do is OR the bits of both strings and the result would = 1, perhaps I need to shift through the bits in a for loop, I thought maybe I could just OR both binary representations of the matching length binary strings

Obviously I am choosing the wrong data type, byte[], to store my binary strings, I am just not experienced enough to know how to represent these binary strings in the right data type.

UPDATE

It's difficult to chose a correct answer because there are multiple correct answers. Just wanted to be clear that there is multiple solutions to this question presented that are good answers.

My question resulted from a problem I am trying to solve on HackerRank: https://www.hackerrank.com/challenges/acm-icpc-team

"You are given a list of N people who are attending ACM-ICPC World Finals. Each of them are either well versed in a topic or they are not. Find out the maximum number of topics a 2-person team can know. And also find out how many teams can know that maximum number of topics."

Thanks to help I received on Stack Overflow I came up with a not to bad solution:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

class Solution {
static void Main(String[] args) {
    var inputArr = Console.ReadLine().Split(' ').Select(item => int.Parse(item)).ToArray();
    var n = inputArr[0];
    var m = inputArr[1];


    var g = new byte[n];
    var team = new List<byte>();

    var teamsKnowMax = 0;
    var maxTopics = byte.MinValue >> sizeof(byte) * 8 - m;

    for(var i = 0; i < n; i++){
        g[i] = Convert.ToByte(Console.ReadLine(), 2);
        maxTopics = maxTopics | g[i];
    }

    for(var j = 0; j < n -1; j++){
        for(var k = j+1; k < n; k++){
            var or = g[j] | g[k];
            if((or & maxTopics) == maxTopics)
                teamsKnowMax++;
        }
    }

    Console.WriteLine(Convert.ToString(maxTopics,2).ToCharArray().Count(item => item == '1'));
    Console.WriteLine(teamsKnowMax);
}

}

But I failed to consider the constraints:

2≤N≤500 
1≤M≤500

So now I will need to work on a solution that breaks long binary strings into 8 bit chunks like an area of bytes that breaks up the long binary string and see if that works, rather than do that than go through each character of the string.

Initially I started to break up large binary strings into segments of 8, and deal with a reminder if there was one, this created a complex data structure that I couldn't manage. So often, solving these algorithms is about choosing the right data structure from the start. Then I went back to a BitArray and this gave me something I could | OR even if the binary string was very large. Credit to this link and content providers: https://codereview.stackexchange.com/questions/80458/acm-icpc-team-challenge-on-hackerrank-easy

   static void Main(String[] args) {
    var input = Console.ReadLine().Split(' ').Select(item => int.Parse(item)).ToArray();
    var N = input[0];
    var M = input[1];
    var maxTopics = 0;
    var maxTeams = 0;
    var bitArray = new BitArray[N];

    for(var n = 0; n < N; n++){
        bitArray[n] = new BitArray(M);

        var topics = Console.ReadLine();

        for(var m = 0; m < M; m++){
            bitArray[n].Set(m, topics[m] == '1');
        }
    }

    for(int i = 0; i < N -1; i ++){
        for(int j = i + 1; j < N; j++){
            var tempTopics = BitsOnCount(new BitArray(M).Or(bitArray[i]).Or(bitArray[j]));

            if (tempTopics > maxTopics){
                maxTopics = tempTopics;
                maxTeams = 1;
            }else if(tempTopics == maxTopics){
                maxTeams++;
            }

        }
    }

    Console.WriteLine(maxTopics);
    Console.WriteLine(maxTeams);
}

static int BitsOnCount(BitArray bitArray)
{
    var count = 0;
    foreach (var bit in bitArray)
    {
        if ((bool) bit)
            count++;
    }

    return count;
}
like image 430
Brian Ogden Avatar asked Jan 07 '23 04:01

Brian Ogden


1 Answers

The solution with only manipulating numbers, without loops, LINQ, etc. Should be the best performance.

var str1 = "10101";
var str2 = "11100";

var num1 = Convert.ToByte(str1, 2);
var num2 = Convert.ToByte(str2, 2);
var or = num1 | num2;

// We need to lookup only that bits, that are in original input values.
// So, create a mask with the same number of bits.
var mask = byte.MaxValue >> sizeof(byte) * 8 - Math.Max(str1.Length, str2.Length);
var result = (or & mask) == mask;

// True, when all bits after OR are 1, otherwise - False.
Console.WriteLine(result);
like image 70
kyrylomyr Avatar answered Jan 09 '23 18:01

kyrylomyr