/*
TASK: LAB
LANG: C++
*/
#include <stdio.h>
#include <string.h>

const int MAX = 40;
const int CARD_C = 10;
const bool DEBUG = false;
const int INF = 1000000;

typedef unsigned short ushort;

inline char getNext(FILE *fin);
inline ushort cardCode(char c);

class Room {
    char cColor;
    bool bCard;
    char cCard;

    public:

    Room() {
        cColor = 0;
        bCard = false;
        cCard = 0;
    }
    void readColor(FILE *fin) {
        cColor = getNext(fin);
    }
    void readCard(FILE *fin) {
        cCard = getNext(fin);
        bCard = !(cCard == 'O');
    }
    char getColor() {
        return cColor;
    }
    bool hasCard() {
        return bCard;
    }
    char getCard() {
        return cCard;
    }
};

class Point {
    ushort iX,iY,iZ;
    
    public:

    bool operator == (Point &p) {
        return (iX == p.X() && iY == p.Y() && iZ == p.Z());
    }
    Point() {
        iX = 0;
        iY = 0;
        iZ = 0;
    }
    Point(ushort iX,ushort iY,ushort iZ) {
        this->iX = iX;
        this->iY = iY;
        this->iZ = iZ;
    }
    void read(FILE *fin) {
        fscanf(fin,"%d%d%d",&iX,&iY,&iZ);
        iX--;
        iY--;
        iZ--;
    }
    ushort X() {
        return iX;
    }
    ushort Y() {
        return iY;
    }
    ushort Z() {
        return iZ;
    }
};

class Last {
    char cLastMove;
    char cRecord;

    public:

    Last() {
        cLastMove = 0;
        cRecord = 0;
    }
    Last(char c1,char c2) {
        cLastMove = c1;
        cRecord = c2;
    }
    char getLastMove() {
        return cLastMove;
    }
    bool hasRecorded() {
        return cRecord != 0;
    }
    char getRecord() {
        return cRecord;
    }
};

class Pos {
    ushort iDist;
    Point p;
    char c1,c2;
    Last lastMove;

    public:

    Pos(ushort iDist,Point pWhere,char c1,char c2,Last l) {
        this->iDist = iDist;
        p = pWhere;
        this->c1 = c1;
        this->c2 = c2;
        lastMove = l;
    }
    Pos() {
        iDist = INF;
    }
    int getDist() {
        return iDist;
    }
    Point where() {
        return p;
    }
    Last getLast() {
        return lastMove;
    }
    char card1() {
        return c1;
    }
    char card2() {
        return c2;
    }
};

class PosQueue {

    class Node {
        Pos p;
        Node *next;

        public:

        Node(Pos p1) {
            p = p1;
            next = NULL;
        }
        ~Node() {
            if (next)
                delete next;
        }
        void setNext(Node *next) {
            this->next = next;
        }
        Node* getNext() {
            return next;
        }
        Pos getPos() {
            return p;
        }
    };

    Node *first;
    Node *last;

    public:

    PosQueue() {
        first = new Node(Pos());
        last = first;
    }
    void push(Pos p) {
        Node *n = new Node(p);
        last->setNext(n);
        last = n;
    }
    Pos pop() {
        Node *n = first->getNext();

        if (n != NULL) {
            first->setNext(n->getNext());
        } else {
            if (DEBUG)
                printf("ERROR: POP FROM AN EMPTY QUEUE!\n");
        }
        if (last == n)
            last = first;

        return n->getPos();
    }
    bool isEmpty() {
        return first->getNext() == NULL;
    }
    ~PosQueue() {
        delete first;
    }

};

class Solver {
    Point pStart,pEnd;
    int c1,c2;
    int iRoomC;
    Room lab[MAX][MAX][MAX];
    bool bVis[MAX][MAX][MAX][CARD_C][CARD_C];
    Last last[MAX][MAX][MAX][CARD_C][CARD_C];
    PosQueue pq;

    FILE* openInFile() {
        if (DEBUG)
            return fopen("lab.in","r");
        else
            return stdin;
    }
    void load() {
        FILE *fin = openInFile();

        fscanf(fin,"%d",&iRoomC);
        pStart.read(fin);
        pEnd.read(fin);
        fscanf(fin,"%c%c",&c2,&c1);
        fscanf(fin,"%c",&c2);

        for (int iZ=0;iZ<iRoomC;iZ++)
            for (int iX=0;iX<iRoomC;iX++)
                for (int iY=0;iY<iRoomC;iY++)
                    lab[iX][iY][iZ].readColor(fin);

        for (int iZ=0;iZ<iRoomC;iZ++)
            for (int iX=0;iX<iRoomC;iX++)
                for (int iY=0;iY<iRoomC;iY++)
                    lab[iX][iY][iZ].readCard(fin);
    }
    void markAsVisited(Pos &p) {
        bVis[p.where().X()][p.where().Y()][p.where().Z()][cardCode(p.card1())][cardCode(p.card2())] = true;
        last[p.where().X()][p.where().Y()][p.where().Z()][cardCode(p.card1())][cardCode(p.card2())] = p.getLast();
    }
    bool visited(Pos &p) {
        return bVis[p.where().X()][p.where().Y()][p.where().Z()][cardCode(p.card1())][cardCode(p.card2())];
    }
    Room* getRoom(Pos &p) {
        return &(lab[p.where().X()][p.where().Y()][p.where().Z()]);
    }
    Room* getRoom(int iX,int iY,int iZ) {
        return &(lab[iX][iY][iZ]);
    }
    Room* getRoom(Point &p) {
        return &(lab[p.X()][p.Y()][p.Z()]);
    }
    bool canMove(char c,char cKey1,char cKey2) {
        return (c == cKey1) || (c == cKey2);
    }

    bool overwriteTwice(Pos &p) {
        return (p.getLast().getLastMove() == 'R');
    }
    void moveX(Pos &p) { //(x,y,z) -> (x+1,y,z)
        Point pWhere = p.where();

        if (pWhere.X() + 1 >= iRoomC) // The move can not be done
            return;

        Point pointNew(pWhere.X()+1,pWhere.Y(),pWhere.Z());
        Room *dest = getRoom(pointNew);

        Last l('X',0);
        Pos posNew(p.getDist()+1,pointNew,p.card1(),p.card2(),l);

        if (canMove(dest->getColor(),p.card1(),p.card2()) && !visited(posNew))
            pq.push(posNew);
    }
    void moveY(Pos &p) { //(x,y,z) -> (x,y+1,z)
        Point pWhere = p.where();

        if (pWhere.Y() + 1 >= iRoomC) // The move can not be done
            return;

        Point pointNew(pWhere.X(),pWhere.Y()+1,pWhere.Z());
        Room *dest = getRoom(pointNew);

        Last l('Y',0);
        Pos posNew(p.getDist()+1,pointNew,p.card1(),p.card2(),l);

        if (canMove(dest->getColor(),p.card1(),p.card2()) && !visited(posNew))
            pq.push(posNew);
    }
    void moveZ(Pos &p) { //(x,y,z) -> (x,y,z+1)
        Point pWhere = p.where();

        if (pWhere.Z() + 1 >= iRoomC) // The move can not be done
            return;

        Point pointNew(pWhere.X(),pWhere.Y(),pWhere.Z()+1);
        Room *dest = getRoom(pointNew);

        Last l('Z',0);
        Pos posNew(p.getDist()+1,pointNew,p.card1(),p.card2(),l);

        if (canMove(dest->getColor(),p.card1(),p.card2()) && !visited(posNew))
            pq.push(posNew);
    }
    void moveU(Pos &p) { //(x,y,z) -> (x-1,y,z)
        Point pWhere = p.where();

        if (pWhere.X() - 1 <= 0) // The move can not be done
            return;

        Point pointNew(pWhere.X()-1,pWhere.Y(),pWhere.Z());
        Room *dest = getRoom(pointNew);

        Last l('U',0);
        Pos posNew(p.getDist()+1,pointNew,p.card1(),p.card2(),l);

        if (canMove(dest->getColor(),p.card1(),p.card2()) && !visited(posNew))
            pq.push(posNew);
    }
    void moveV(Pos &p) { //(x,y,z) -> (x,y-1,z)
        Point pWhere = p.where();

        if (pWhere.Y() - 1 <= 0) // The move can not be done
            return;

        Point pointNew(pWhere.X(),pWhere.Y()-1,pWhere.Z());
        Room *dest = getRoom(pointNew);

        Last l('V',0);
        Pos posNew(p.getDist()+1,pointNew,p.card1(),p.card2(),l);

        if (canMove(dest->getColor(),p.card1(),p.card2()) && !visited(posNew))
            pq.push(posNew);
    }
    void moveW(Pos &p) { //(x,y,z) -> (x,y,z-1)
        Point pWhere = p.where();

        if (pWhere.Z() - 1 <= 0) // The move can not be done
            return;

        Point pointNew(pWhere.X(),pWhere.Y(),pWhere.Z()-1);
        Room *dest = getRoom(pointNew);

        Last l('W',0);
        Pos posNew(p.getDist()+1,pointNew,p.card1(),p.card2(),l);

        if (canMove(dest->getColor(),p.card1(),p.card2()) && !visited(posNew))
            pq.push(posNew);
    }
    
    void move(Pos &p) {
        Room *r = getRoom(p);

        {    //Do not overwrite any card
             moveX(p);  //(x,y,z) -> (x+1,y,z)
             moveY(p);  //(x,y,z) -> (x,y+1,z)
             moveZ(p);  //(x,y,z) -> (x,y,z+1)
             moveU(p);  //(x,y,z) -> (x-1,y,z)
             moveV(p);  //(x,y,z) -> (x,y-1,z)
             moveW(p);  //(x,y,z) -> (x,y,z-1)
        }
        if (r->hasCard() && !overwriteTwice(p)) {
            char c = r->getCard();

            {   //Overwrite card 1
                Last l('R',p.card1());
                Pos posNew(p.getDist()+1,p.where(),c,p.card2(),l);

                if (!visited(posNew))
                   pq.push(posNew);
            }
            {   //Overwrite card 2
                Last l('R',p.card2());
                Pos posNew(p.getDist()+1,p.where(),p.card1(),c,l);

                if (!visited(posNew))
                   pq.push(posNew);
            }
        }
    }
    void doBFS() {
        pq.push(Pos(0,pStart,c1,c2,Last()));
        int iDist = INF;
        char c1,c2;

        while (!pq.isEmpty()) {
            Pos curP = pq.pop();

            if (visited(curP))
                continue;

            if (curP.where() == pEnd) {
                if (curP.getDist() < iDist) {
                    iDist = curP.getDist();
                    c1 = curP.card1();
                    c2 = curP.card2();
                }
            }
                
            markAsVisited(curP);
            move(curP);
        }

        save(iDist,c1,c2);
    }
    void makeLastMove(int &iX,int &iY,int &iZ,char &c1,char &c2,char c) {
        // Do the inverse moves (for the the route tracking)
        switch (c) {
            case 'X':  iX--; break;
            case 'Y':  iY--; break;
            case 'Z':  iZ--; break;
            case 'U':  iX++; break;
            case 'V':  iY++; break;
            case 'W':  iZ++; break;
            case 'R':  {
                           Room *r = getRoom(iX,iY,iZ);
                           Last l = last[iX][iY][iZ][cardCode(c1)][cardCode(c2)];

                           char cCard = r->getCard();
                           
                           if (c1 == cCard) {
                               c1 = l.getRecord();
                               return;
                           } else {
                               c2 = l.getRecord();
                               return;
                           }
                       }
            default :  {
                           if (DEBUG)
                               printf("ERROR: Inavlid move\n");
                       }
        }
    }
    void printMoves(int iX,int iY,int iZ,char c1,char c2) {
        Last l = last[iX][iY][iZ][cardCode(c1)][cardCode(c2)];

        if (l.getLastMove() == 0)
            return;
            
        char c = l.getLastMove();

        makeLastMove(iX,iY,iZ,c1,c2,c);
        printMoves(iX,iY,iZ,c1,c2);
        if (c == 'R')
            printf("%c",l.getRecord());
        else
            printf("%c",c);
    }
    void save(int iDist,char c1,char c2) {
        printf("%d\n",iDist);
        if (iDist == 9)
            return;
        printMoves(pEnd.X(),pEnd.Y(),pEnd.Z(),c1,c2);
        printf("\n");
    }

    public:

    Solver() {
        memset(bVis,false,sizeof(bVis));
        load();
    }
    void solve() {
        doBFS();
    }
};

inline char getNext(FILE *fin) {
    char c;

    do {
        fscanf(fin,"%c",&c);
    } while (c==' ' || c=='\n');

    return c;
}

inline ushort cardCode(char c) {
    return c - 'A';
}

int main() {
    Solver *s = new Solver();

    s->solve();

    delete s;
    
    return 0;
}
