0

Very new to C#, so this could be a silly question.

I am working with alot of UInt64's. These are expressed as hex right? If we look at its binary representation, can we return such an array that if we apply the 'or' operation to, we will arrive back at the original UInt64?

For example, let's say

x = 1011

Then, I am looking for an efficient way to arrive at,

f(x) = {1000, 0010, 0001}

Where these numbers are in hex, rather than binary. Sorry, I am new to hex too.

I have a method already, but it feels inefficient. I first convert to a binary string, and loop over that string to find each '1'. I then add the corresponding binary number to an array.

Any thoughts?

Here is a better example. I have a hexadecimal number x, in the form of,

UInt64 x = 0x00000000000000FF

Where the binary representation of x is

0000000000000000000000000000000000000000000000000000000011111111

I wish to find an array consisting of hexadecimal numbers (UInt64??) such that the or operation applied to all members of that array would result in x again. For example,

f(x) = {0x0000000000000080, // 00000....10000000
        0x0000000000000040, // 00000....01000000
        0x0000000000000020, // 00000....00100000
        0x0000000000000010, // 00000....00010000
        0x0000000000000008, // 00000....00001000
        0x0000000000000004, // 00000....00000100
        0x0000000000000002, // 00000....00000010
        0x0000000000000001  // 00000....00000001
}

I think the question comes down to finding an efficient way to find the index of the '1's in the binary expansion...

public static UInt64[] findOccupiedSquares(UInt64 pieces){
    UInt64[] toReturn = new UInt64[BitOperations.PopCount(pieces)];
    if (BitOperations.PopCount(pieces) == 1){
        toReturn[0] = pieces;
    }
    else{
        int i = 0;
        int index = 0;
        while (pieces != 0){
            i += 1;
            pieces = pieces >> 1;
            if (BitOperations.TrailingZeroCount(pieces) == 0){ // One
                int rank = (int)(i / 8);
                int file = i - (rank * 8);
                toReturn[index] = LUTable.MaskRank[rank] & LUTable.MaskFile[file];
                index += 1;
            }
        }
    }
    return toReturn;
}
  • Hi Kieran, the question is a bit confusing. Do you want an array of strings that represent the base-2 components of the number (e.g. 0001, 0100)? Or do you just want an array of numbers that represent each base-2 components of the number (e.g. 1, 4)? – Igby Largeman Jun 18 '20 at 02:46
  • Hi @IgbyLargeman. Thank you for the reply. I have edited my original question, I hope that makes it more clear. At the end of the day, I still need the result to be an array of UInt64's. – Kieran Montgomery Jun 18 '20 at 10:18
  • Hi Kieran, your edit helps, but I'm still not sure if you want an array of integers or an array of strings. The reason I ask is that you can't have an 'array of hexadecimal numbers'. You can certainly have an array of strings that represent the numbers in hexadecimal format, but if you put the actual *numbers* in an array, there is no representation; they are just numbers. If you store them 'in hexadecimal format' then you are storing them as strings, and you would have to convert them back to integers before you OR them together again. – Igby Largeman Jun 19 '20 at 00:37
  • @IgbyLargeman Thank you for your continued interest in this problem. I hope my latest edit will prove more helpful. It is my latest attempt at this problem. AS I said, I am new to C#, but I am sure you can figure out how it works. Bare in mind, I am developing a chess engine, so there is a reason for the names! – Kieran Montgomery Jun 19 '20 at 01:19

1 Answers1

0

Your question still confuses me as you seem to be mixing the concepts of numbers and number representations. i.e. There is an integer and then there is a hexadecimal representation of that integer.

You can very simply break any integer into its base-2 components.

ulong input = 16094009876; // example input
ulong x = 1;
var bits = new List<ulong>();
do
{
    if ((input & x) == x)
    {
        bits.Add(x);
    }
    x <<= 1;
} while (x != 0);

bits is now a list of integers which each represent one of the binary 1 bits within the input. This can be verified by adding (or ORing - same thing) all the values. So this expression is true:

bits.Aggregate((a, b) => a | b) == input

If you want hexadecimal representations of those integers in the list, you can simply use ToString():

var hexBits = bits.Select(b => b.ToString("X16"));

If you want the binary representations of the integers, you can use Convert:

var binaryBits = bits.Select(b => Convert.ToString((long)b, 2).PadLeft(64, '0'));
Igby Largeman
  • 16,495
  • 3
  • 60
  • 86
  • Thanks for the answer. I think this could help! Would you happen to know of a way I could test this against my solution? I am sorry for the confusion in this question. We use a 64bit binary number to represent a chess board state, for example, the board of white pawns could be 000....1111111100000000. So each '1' is a pawn. I would like the location of each pawn in a 64 bit binary number. What makes it more challenging for me, is that instead of represented in the binary format, most people represent these numbers in their hexadecimal format. – Kieran Montgomery Jun 19 '20 at 11:24
  • Still not sure exactly what you need but I will add a bit about getting the binary format. I've already showed you how to get the hex format. – Igby Largeman Jun 21 '20 at 02:52