import java.util.*;

public class Euler244 {
    static final int MOD = 100000007;

    static final int ASCII_L = 76;
    static final int ASCII_R = 82;
    static final int ASCII_U = 85;
    static final int ASCII_D = 68;

    static final String START_BOARD = "WRBBRRBBRRBBRRBB";
    static final String TARGET_BOARD = "WBRBBRBRRBRBBRBR";

    static int getCell(int s, int idx) {
        return (s >> (2 * idx)) & 3;
    }

    static int setCell(int s, int idx, int val) {
        int mask = 3 << (2 * idx);
        s &= ~mask;
        s |= (val << (2 * idx));
        return s;
    }

    static int encodeBoard(String board) {
        if (board.length() != 16)
            return 0;
        int s = 0;
        for (int i = 0; i < 16; ++i) {
            int val = 0;
            if (board.charAt(i) == 'R')
                val = 1;
            else if (board.charAt(i) == 'B')
                val = 2;
            s = setCell(s, i, val);
        }
        return s;
    }

    static int findBlank(int s) {
        for (int i = 0; i < 16; ++i) {
            if (getCell(s, i) == 0)
                return i;
        }
        return -1;
    }

    static class Move {
        int nextState;
        int ascii;

        Move(int n, int a) {
            nextState = n;
            ascii = a;
        }
    }

    static List<Move> generateMoves(int s) {
        int blank = findBlank(s);
        int r = blank / 4;
        int c = blank % 4;
        List<Move> moves = new ArrayList<>();

        if (c < 3) {
            int nBlank = blank + 1;
            int tile = getCell(s, nBlank);
            int ns = setCell(s, blank, tile);
            ns = setCell(ns, nBlank, 0);
            moves.add(new Move(ns, ASCII_L));
        }
        if (c > 0) {
            int nBlank = blank - 1;
            int tile = getCell(s, nBlank);
            int ns = setCell(s, blank, tile);
            ns = setCell(ns, nBlank, 0);
            moves.add(new Move(ns, ASCII_R));
        }
        if (r < 3) {
            int nBlank = blank + 4;
            int tile = getCell(s, nBlank);
            int ns = setCell(s, blank, tile);
            ns = setCell(ns, nBlank, 0);
            moves.add(new Move(ns, ASCII_U));
        }
        if (r > 0) {
            int nBlank = blank - 4;
            int tile = getCell(s, nBlank);
            int ns = setCell(s, blank, tile);
            ns = setCell(ns, nBlank, 0);
            moves.add(new Move(ns, ASCII_D));
        }
        return moves;
    }

    public static String solve() {
        int startState = encodeBoard(START_BOARD);
        int targetState = encodeBoard(TARGET_BOARD);

        List<Integer> states = new ArrayList<>();
        Map<Integer, Integer> idOf = new HashMap<>();
        List<Integer> distFromStart = new ArrayList<>();

        states.add(startState);
        idOf.put(startState, 0);
        distFromStart.add(0);

        List<Integer> queue = new ArrayList<>();
        queue.add(0);

        int head = 0;
        while (head < queue.size()) {
            int v = queue.get(head++);
            int s = states.get(v);
            for (Move m : generateMoves(s)) {
                int ns = m.nextState;
                if (!idOf.containsKey(ns)) {
                    int nid = states.size();
                    idOf.put(ns, nid);
                    states.add(ns);
                    distFromStart.add(distFromStart.get(v) + 1);
                    queue.add(nid);
                }
            }
        }

        if (!idOf.containsKey(targetState))
            return "0";
        int targetId = idOf.get(targetState);
        int shortestLen = distFromStart.get(targetId);

        List<List<Move>> adjacency = new ArrayList<>(states.size());
        for (int i = 0; i < states.size(); ++i) {
            List<Move> edges = new ArrayList<>();
            for (Move m : generateMoves(states.get(i))) {
                edges.add(new Move(idOf.get(m.nextState), m.ascii));
            }
            adjacency.add(edges);
        }

        int[] distToTarget = new int[states.size()];
        Arrays.fill(distToTarget, -1);
        distToTarget[targetId] = 0;

        List<Integer> qRev = new ArrayList<>();
        qRev.add(targetId);
        int headRev = 0;
        while (headRev < qRev.size()) {
            int v = qRev.get(headRev++);
            int nd = distToTarget[v] + 1;
            int s = states.get(v);
            for (Move m : generateMoves(s)) {
                int to = idOf.get(m.nextState);
                if (distToTarget[to] == -1) {
                    distToTarget[to] = nd;
                    qRev.add(to);
                }
            }
        }

        class DFSState {
            int node, depth;
            long checksum;

            DFSState(int n, int d, long c) {
                node = n;
                depth = d;
                checksum = c;
            }
        }

        Stack<DFSState> stack = new Stack<>();
        stack.push(new DFSState(0, 0, 0L));

        long checksumSum = 0;

        while (!stack.isEmpty()) {
            DFSState curr = stack.pop();

            if (curr.depth == shortestLen) {
                if (curr.node == targetId) {
                    checksumSum += curr.checksum;
                }
                continue;
            }

            for (Move m : adjacency.get(curr.node)) {
                int to = m.nextState;
                if (distFromStart.get(to) == curr.depth + 1
                        && distToTarget[to] == shortestLen - distFromStart.get(to)) {
                    long ncs = (curr.checksum * 243 + m.ascii) % MOD;
                    stack.push(new DFSState(to, curr.depth + 1, ncs));
                }
            }
        }

        return String.valueOf(checksumSum);
    }

    public static void main(String[] args) {
        System.out.println(solve());
    }
}
