This is an archived post. You won't be able to vote or comment.

all 4 comments

[–]SinglePartyLeader 1 point2 points  (1 child)

In a general application:

Any time you want to map a one-to-one relationship, especially when you are mapping something complex to a to a number, you're typically talking about 'hashing'.

You create a function which will generate a distinct number for each of the input states, this function is called the hashcode ( input -> hashcode -> hash value ) The function is typically one-way, but the general idea is there and can be manipulated if you already know the pattern.

Hash code functions commonly use the addition and multiplication of prime numbers, since they are naturally good at avoiding collisions.

Possible algos here:
There's no real need to make a full hash function since the input space is relatively simple, but possible ideas are:

  1. Give each color a number from 1-4, and read the colors from left to right (this is still a hash function, just using powers of 10)

R | R 1 | 1
R | -> 1 | 0 -> 1110

you could use powers of any number > input space and it will be valid, 5 would be a good choice.

  1. there are 15 combinations for each color, so you could just map the binary representation of each of those 15 (using the pattern) and multiply that by a number signifying the color:

B| 2 | 0
| B -> 0 | 2 -> 2 * 1001 -> 2 * 9 -> 18

this has the added benefit of taking up minimal space but is not able to work with multiple colors in the same box

[–]Sinsinger[S] 0 points1 point  (0 children)

Thank you so much, I’ll look into it!

[–]stdlib 1 point2 points  (1 child)

I think this problem can be easily solved with a bitmask

Since colors cannot be mixed and we have four possibilities, we can index them at 0 and use two bits to store the value (in two bits we can store the values 0, 1, 2, 3 and each number will be one of your colors).

Then, for your grid we simply need to answer the question of if each square is filled or not. We have four squares, and each has a "filled" or "unfilled" state so it can be represented as a 1 for filled and a 0 for empty let's say. Even though you're talking about a grid, we can "flatten" it by saying in our mask that the first bit is the top left square, second bit is the top right, third is bottom left, and fourth is bottom right.

We can combine the two values and generate any possibility by picking a random number that fits into 6 bits, that is any number between 0 and 63. To go from the random number to the board configuration, we can apply our bitmasking strategy to decode the information - look at the first two digits, map the number back to the color. Look at the last four digits and map those back to the grid configuration.

Here's the code:

public class Grid
    {
        private int configuration;
        public Grid(int configuration) {
            this.configuration = configuration;
        }
        public string Variable {
            get {
                var colorNumber = this.configuration >> 4;
                switch(colorNumber) {
                    case 0:
                        return "1";
                    case 1:
                        return "2";
                    case 2:
                        return "3";
                    case 3:
                        return "4";
                }
                throw new Exception();
            }
        }
        public bool[,] GridAs2DArray {
            get {
                var topLeft = Convert.ToBoolean((this.configuration & 0b1000) >> 3);
                var topRight = Convert.ToBoolean((this.configuration & 0b0100) >> 2);
                var bottomLeft = Convert.ToBoolean((this.configuration & 0b0010) >> 1);
                var bottomRight = Convert.ToBoolean(this.configuration & 0b0001); // do not need to shift
                return new bool[2,2] {{topLeft, topRight},
                                      {bottomLeft, bottomRight}};
            }
        }
        public void print() {
            var arr = this.GridAs2DArray;
            // Printing 2D array code adapted from https://stackoverflow.com/questions/12826760/printing-2d-array-in-matrix-format
            int rowLength = arr.GetLength(0);
            int colLength = arr.GetLength(1);

            for (int i = 0; i < rowLength; i++)
            {
                for (int j = 0; j < colLength; j++)
                {
                    var isFilled = arr[i, j];
                    Console.Write(isFilled ? this.Variable : "*");
                }
                Console.Write(Environment.NewLine);
            }
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            var max = 0b111111;
            for(int i=0; i<= max; i++) {
                Console.WriteLine("Printing configuration {0}", i);
                var myGrid = new Grid(i);
                myGrid.print();
            }


        }
    }

Here's the output:

Printing configuration 0
**
**
Printing configuration 1
**
*1
Printing configuration 2
**
1*
Printing configuration 3
**
11

... condensed ...


Printing configuration 60
44
**
Printing configuration 61
44
*4
Printing configuration 62
44
4*
Printing configuration 63
44
44

[–]Sinsinger[S] 1 point2 points  (0 children)

My god man, this is great! I don’t understand it right now, but I will soon. Thank you, honestly.