1

I have a list of string which provide information about a trip working in days e.g. "0111110" means trips are not available in first and last day of week.

Now there is a list which contains info something like "0111110", "1000001"

so the operation day for whole block will be "1111111".

My question here is how can I efficiently merge trips to get block operational days?

Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101

5 Answers5

5

You can use the | Operator (bitwise OR):

var x1 = Convert.ToByte("0111110", 2);
var x2 = Convert.ToByte("1000001", 2);

var foo = x1 | x2;

var bar = Convert.ToString(foo, 2);
Kristoffer Jälén
  • 4,112
  • 3
  • 30
  • 54
1

You can use Zip to combine the strings using some simple logic.

    var combined= input1.Zip
        (
            input2, 
            (a,b) => a == '1' ? a : b
        ); 

This gives you an enumerable of characters which you can make into a new string using String's constructor.

var output = new string(combined.ToArray());

Complete example:

public static void Main()
{
    var input1 = "1110000";
    var input2 = "0001110";
    var combined = input1.Zip
        (
            input2, 
            (a,b) => a == '1' ? a : b
        ); 

    var result = new string(combined.ToArray());

    Console.WriteLine(result);
}

Output:

1111110

Example on DotNetFiddle

John Wu
  • 50,556
  • 8
  • 44
  • 80
0

With nested loops:

string[] strs = new string[] { "0111110", "1000001" };

char[] main = strs[0].ToCharArray();



for(int i = 0; i < 7; i++)
{
    if(main[i] == '1')
        continue;
    for(int j = 1; j < strs.Length; j++)
    {
        if(strs[j][i] == '1')
        {
            main[i] = '1';
            break;
        }
    }
}

string result = new string(main);

It's more wordy than kristoffer's bitwise or but it should be pretty quick if you're merging a large number of strings, as it gives up as soon as it makes a 1 in a particular position. The bitwise or approach is a bit more naive and would incur more unnecessary conversions. Which one is more performant probably depends on the particulars of your situation. The bitwise approach may also have some padding/length issues and is limited to 8 digits if using byte; you only have 7 days but someone might upgrade it to do full months one day. This approach doesn't have a limit in that regard

An "N number of strings" bitwise approach:

byte r = 0;
for(int i = 0; i < strs.Length && r != 127; i++)
  r |= Convert.ToByte(strs[i], 2);

string res = Convert.ToString(t, 2).PadLeft(7, '0');

We can stop early if we hit 127 as this is indicative of reaching 1111111. Leading zeroes are lost and must be restored with PadLeft

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
0

Assuming you can't use a different type than the strings you provided, you can copy the results into an array and create a string from that:

var result = new char[7];
for (int i=0; i<7; i++)
    if (s1[i] == '1' || s2 == ['1'])
        result[i] = '1';

var finalResult = new string(result);

This is efficient because you only have two allocations (the array and the string), seven iterations/comparisons, and up to seven char copies.

Kit
  • 20,354
  • 4
  • 60
  • 103
0
    public static class OperationalBlockCalculator
    {
        public static string GetOperationalBlock(List<string> workingDays)
        {
            var operationalBlock = new StringBuilder("0000000");
            for (var day = 0; day < 7; day++)
            {
                if (workingDays.Any(x => x.ElementAt(day).Equals('1')))
                {
                    operationalBlock[day] = '1';
                }
            }
            return operationalBlock.ToString();
        }
    }

    [TestFixture]
    public class WhenIMergeTripWorkingDays
    {
        [Test]
        public void ThenItShouldReturnOperationalBlock()
        {
            var workingDays = new List<string> { "0110110", "1000001" };
            OperationalBlockCalculator.GetOperationalBlock(workingDays).Should().Be("1110111");
        }
    }
Luke Hutton
  • 10,612
  • 6
  • 33
  • 58