Search code examples
algorithmmatrixdicespiral

Rolling a dice in a spiral


Given a grid size of nxn, a dice is put on the top-left field (1,1) with the number 6 facing down, 5 facing (1,2) and 4 facing (2,1). The dice will roll in a spiral (clockwise) to fill every field with a number (only once). Calculate the total sum of the numbers printed. Visual representation of the moves of the dice and the numbers printed when n=5 (result = 81)

01 02 03 04 05
16 17 18 19 06
15 24 25 20 07
14 23 22 21 08
13 12 11 10 09

6 5 1 2 6
4 5 3 2 4
1 1 3 1 1
3 2 3 5 3
6 5 1 2 6

This is a homework question, but I can't figure out how to do this efficiently without going through all possible cases. If someone could give me a solution and explanation, that would be amazing (no code needed, I want to do it myself).


Solution

  • A possible clean way t do this is by define a class Dice as mentioned below.

    class Dice
    {
    public:
        Dice();
        int face_down();
        void roll_west();
        void roll_east();
        void roll_north();
        void roll_south();
        void set_initial_config(int face_down,int east,int north,int west,int south);
        ~Dice();
    private:
        /// variables for your state etc
    };
    

    If you implement Dice successfully then rest of work will be simple simulation of the rolling of the dice.

    int roll(int n,int m){ // grid dimensions
    
        std::vector<std::vector<bool> > visited(n,std::vector<bool>(m,0));
    
        int i=0,j=-1;
        int dir=0;
        bool dir_changed;
        int dir_change_count=0;
        int sum=0;
        Dice d;
    
        while(dir_change_count<4){
    
            dir_changed=0;
            switch(dir){
                case 0:
                    if(j+1<m and !visited[i][j+1]){
                        j++;
                        visited[i][j+1]=1;
                        d.roll_east();
                    }else{
                        dir_changed=1;
                        dir++;
                    }
                    break;
                case 1:
                    if(i+1<n and !visited[i+1][j]){
                        i++;
                        visited[i+1][j]=1;
                        d.roll_south();
                    }else{
                        dir_changed=1;
                        dir++;
                    }
                    break;
                case 2:
                    if(j-1>=0 and !visited[i][j-1]){
                        j--;
                        visited[i][j-1]=1;
                        d.roll_west();
                    }else{
                        dir_changed=1;
                        dir++;
                    }
                    break;
                case 3:
                    if(i-1>=0 and !visited[i-1][j]){
                        i--;
                        visited[i-1][j]=1;
                        d.roll_north();
                    }else{
                        dir_changed=1;
                        dir++;
                    }
                    break;
            }
            if(!dir_changed){
                sum+=d.face_down();
                dir_change_count=0;
            }else{
                dir_change_count++;
            }
        }
    
        return sum;
    }