Mentoria de Inglês - Carlos de Alcântara
Nicolas Omori

Criação de Embaralhadores

18 posts neste tópico

Bom dia, pessoas.

Estou estudando bastante lógica de programação nesses últimos dias, aí resolvi tentar criar um embaralhador para as modalidades que treino. Planejo conseguir criar embaralhadores para as seguintes modalidades:

  • 2x2
  • 3x3
  • 4x4
  • 5x5+
  • Megaminx
  • Square (Esse vai dar trabalho)

Até agora, consegui um embaralhador de 2x2, que pode ser usado como um embaralhador 3-gen para 3x3, e também consegui criar um para o Megaminx, que não usa random-state, e sim uma notação que consegue ser gerada apenas com RNG(random number generator).

O motivo da criação desse tópico é: Discutir algoritmos para gerar embaralhamentos para os puzzles aos quais não criei um embaralhador ainda.

Também podemos discutir, começando pelo 2x2, como criar uma maneira de usar um estado aleatório das peças para gerar o scramble.

Seguem os códigos, Ruby, que utilizei para criar os embaralhadores.

Megaminx:

def embaralha_mega
  7.times {
    line = ""
    5.times {
      move_R = ["R++", "R--"].shuffle.first
      move_D = ["D++", "D--"].shuffle.first
      line << move_R
      line << move_D
    }
    move_U = ["U", "U'"].shuffle.first
    line << move_U
    puts linha
  }
end

Exemplos gerados:

R-- D-- R-- D++ R-- D++ R++ D-- R-- D-- U

R++ D++ R++ D++ R-- D-- R-- D++ R++ D-- U'

R++ D++ R-- D-- R++ D++ R++ D-- R-- D-- U'

R-- D-- R-- D++ R++ D-- R-- D-- R-- D++ U

R-- D-- R++ D++ R-- D++ R-- D++ R-- D-- U'

R-- D++ R++ D-- R++ D++ R++ D-- R++ D++ U

R-- D-- R++ D++ R++ D-- R++ D-- R-- D-- U'

R-- D-- R-- D-- R-- D++ R-- D-- R++ D-- U

R-- D++ R++ D-- R-- D++ R-- D++ R-- D-- U'

R-- D-- R-- D++ R++ D++ R-- D++ R++ D-- U'

R++ D-- R-- D++ R++ D-- R++ D++ R++ D++ U

R-- D++ R++ D-- R-- D++ R-- D++ R++ D++ U'

R++ D++ R++ D-- R-- D++ R++ D-- R++ D++ U

R-- D-- R-- D-- R++ D++ R-- D-- R-- D-- U

R++ D-- R-- D++ R-- D++ R++ D-- R++ D-- U

R++ D-- R++ D++ R-- D++ R++ D++ R++ D++ U'

R-- D++ R++ D++ R-- D-- R-- D-- R++ D-- U'

R-- D++ R-- D++ R-- D-- R++ D++ R-- D++ U'

R-- D-- R++ D-- R++ D-- R-- D-- R++ D++ U'

R++ D++ R-- D++ R-- D-- R++ D++ R-- D-- U

R++ D-- R++ D++ R++ D-- R++ D++ R-- D-- U

2x2:

def embaralha_dois
  last = ""
  scramble = ""
  i = 0
  while i < 12
    sides = ["F", "R", "U"]
    current = sides.shuffle.first
    if current != last
      attribute = [" ", "' ", "2 "].shuffle.first
      move = "#{current}#{attribute}"
      scramble << move
      last = current
      i += 1
    else
      loop
    end
  end  
  puts scramble
end

Exemplos gerados:

R2 U F2 R F U R' U' F' R' U F

R U' R' U F2 R2 U R U F U2 F2

R F2 R U R2 U' F2 R2 U' F2 U2 F

R2 F U2 R2 F R2 U F2 R2 F2 R2 F

F' R' U' R F R F' R2 U' R2 U2 F

Editado por Nicolas Omori
1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Que bacana, simplesinho.

Também já quis fazer embaralhadores.

A propósito, alguém sabe sobre 'regras oficiais' para o embaralhamento além

do código fonte do embaralhador da WCA ?

p.ex movimentos por scramble etc

Editado por andersonaap
1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Consegui chegar a um embaralhador para 3x3. Novamente, sem usar random state, mas já está gerando scrambles aceitáveis.

def embaralha_tres
  scramble = ""
  last = ""
  embaralhado = {f:  true, r: true, u: true, b: true, l:true, d: true}
  i = 0
  while i < 30
    sides = [:f, :r, :u, :b, :l, ]
    current = sides.shuffle.first
    if current == last
      loop
    elsif embaralhado[current] != true
      loop
    else
      attribute = [" ", "' ", "2 "].shuffle.first
      case current
      when :f, :b
        move = "#{current.upcase}#{attribute}"
        @scramble << move
        embaralhado.each { |k, v| embaralhado[k] = true }
        embaralhado[:f] = false
        embaralhado[:b] = false
        i += 1
      when :r, :l
        move = "#{current.upcase}#{attribute}"
        @scramble << move
        embaralhado.each { |k, v| embaralhado[k] = true }
        embaralhado[:r] = false
        embaralhado[:l] = false
        i += 1
      when :u, 
        move = "#{current.upcase}#{attribute}"
        @scramble << move
        embaralhado.each { |k, v| embaralhado[k] = true }
        embaralhado[:u] = false
        embaralhado[] = false
        i += 1
      end
    end
  end
  puts scramble
end

Exemplos gerados:

B' U' B' D' R U' R F D B R2 U2 R2 B2 D B2 U F2 U2 F2 U' R' U B L2 F2 U2 L' U2 L2

F' L' U' B L D' L' F' L2 D' R' B D' F' R F L' F' R' F' D2 F U' R2 U B' L' F2 D' L2

F' D' R' U' R2 B' D2 B' L' F' D L F2 L2 B D' R D2 F2 U B L2 D B2 R2 D2 F2 D L2 D2

F2 D' R U' L2 U' R F' R2 F R B2 D' F2 L2 D B D' L2 D' B' R' B' R' D' R2 F' D F2 L2

L F' D' B L' D F D B' R2 F' L' U L U B2 R' D' R' F2 R2 B2 D' L2 F D' R2 U2 L D'

R2 F2 U L F2 L B' L F2 L F2 U2 B' U L B D2 F2 L F' R2 U2 R' F2 R F2 D L2 U' B

Editado por Nicolas Omori
1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Dei uma olhada nesse tópico e já percebi algumas coisas que faltam no meu embaralhador de 3x3. Ele não gera movimentos opostos consecutivamente, ex: U' D2.

Vou editar o primeiro post para colocar alguns scrambles gerados pelo programa.

1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Dei uma olhada nesse tópico e já percebi algumas coisas que faltam no meu embaralhador de 3x3. Ele não gera movimentos opostos consecutivamente, ex: U' D2.

Vou editar o primeiro post para colocar alguns scrambles gerados pelo programa.

Ia comentar sobre isso mesmo, o embaralhador deve poder gerar movimentos do mesmo eixo mas camadas diferentes consecutivamente, mas também tem de evitar coisas do tipo U2 D' U. Isso você pode resolver colocando o estado de falso para gerar em cada camada, mas apenas sair desse estado quando executar um movimento em outro eixo.

Um tempo atrás também tinha feito um gerador de scrambles em C para o 3x3...

Sobre o Square-1, a parte do embaralhamento que permanece a cube shape sera fácil, acho que apenas somando todos os movimentos já realizado em U e D e verificando que a diferença entre eles não é múltipla de 3 já garante que ele ira manter a cubeshape. Agora quando for perder a forma dai vai complicar.....

Editado por Luís Felipe Hartmann
1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tu tá se repetindo muito no teu código do 3x3.

Aqui vai minha tentativa em Python:

from random import choice as escolheRandomico

def gerarEmbaralhamento(numero_de_movimentos):

    eixos = {'x': 'RL', 'y': 'UD', 'z': 'FB'}
    sentidos = ["'", '2', ' ']
    movimentos = []
    ultimos2eixos = []
    ultimo_movimento = ''

    for x in range(numero_de_movimentos):

        repetir = True

        while repetir:

            eixo = escolheRandomico(eixos.keys())

            if ultimos2eixos != [eixo, eixo]:
            
                movimentos_atuais = eixos[eixo]
                movimentos_elegiveis = movimentos_atuais.replace(ultimo_movimento, '')
                movimento_atual = escolheRandomico(movimentos_elegiveis)
                movimento_completo = movimento_atual + escolheRandomico(sentidos)
                movimentos.append(movimento_completo)
                ultimos2eixos.append(eixo)
                
                if len(ultimos2eixos) == 3:

                    ultimos2eixos.pop(0)
                
                ultimo_movimento = movimento_atual
                
                repetir = False

    return ' '.join(movimentos)
    
for x in range(12):

    print gerarEmbaralhamento(25)

Resultado:

B2 F D2 F U2 L2 D2 B R' F' U D' R' U L' U2 D' L B' U F' B' L2 D L2

L U2 B' U' F' U' D L' R' B2 F2 D2 L2 D L R' F' R U2 D' B U' L2 D' U
U D2 L D2 B2 F' R' U' D F' R2 F2 L2 D2 L' R' B' F' L B R2 L F L' R'
B D2 F2 U D' L2 F B2 L2 B2 R2 L2 B L D L' U B' R L' F' B D2 U R2
L F' L' B' D2 F R2 B2 L2 R U' R2 F2 B' D2 F D B2 U2 D2 B R F U2 D
U R' U2 D L2 F' U D2 B2 R' U R U' L2 D2 B D2 B L' F2 D' F R' B' F
F2 B' L R F B R D2 L U2 L B U2 F2 L' D F R B' L D2 U2 B2 D B
F' U' F2 B2 U2 L B L2 R2 D F R2 L' F D' F R' F R' B' F2 D2 U' B' L'
D' U' L D2 R2 L2 B U2 B D2 R' L' U' L D B2 R' B' R D U' F' L2 F B'
R2 B F2 R' L B U2 R U B U D L R' F D L R' B2 U2 R L2 B R' U
U' D' F' D2 U2 L' F2 D U' B' D2 B R L2 D F' B' U2 D L2 U2 F2 B2 L' R2
F2 U2 D' R2 L F2 B' U2 D R U2 D' B' F' U R L' U2 B F' R2 U D' B2 D
Editado por Filipe Teixeira
1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ia comentar sobre isso mesmo, o embaralhador deve poder gerar movimentos do mesmo eixo mas camadas diferentes consecutivamente, mas também tem de evitar coisas do tipo U2 D' U. Isso você pode resolver colocando o estado de falso para gerar em cada camada, mas apenas sair desse estado quando executar um movimento em outro eixo.

Vou tentar modificar o código para utilizar eixos ao invés de lados então. Atualizo no post quando eu conseguir chegar a um resultado.

1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vou tentar modificar o código para utilizar eixos ao invés de lados então. Atualizo no post quando eu conseguir chegar a um resultado.

Chegou a ver meu código? ;_;

2 pessoas curtiram isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Chegou a ver meu código? ;_;

Quando eu comentei ainda estava em construção. Agora estou tentando entender o que foi feito.

Pelo que entendi:

  • Escolhe o eixo
  • Verifica se os dois últimos eixos não são os mesmos
  • Se verdadeiro:
    • Seleciona os movimentos possíveis para o eixo
    • Cria uma nova String substituindo o vazio em ultimo_movimento pelos movimentos_atuais
    • Escolhe um dos movimentos
    • Escolhe um dos sentidos, montando o movimento completo
    • Popula a array de movimentos
    • Se a array de 2 ultimos eixos for = 3 , a array é zerada
    • Coloca a face do último movimento na string ultimo_movimento e sai do laço while
  • E por fim, isso é repetido n vezes

Se for dessa forma, achei interessante a sua lógica.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Quando eu comentei ainda estava em construção. Agora estou tentando entender o que foi feito.

Pelo que entendi:

  • Escolhe o eixo
  • Verifica se os dois últimos eixos não são os mesmos
  • Se verdadeiro:
    • Seleciona os movimentos possíveis para o eixo
    • Cria uma nova String substituindo o vazio em ultimo_movimento pelos movimentos_atuais
    • Escolhe um dos movimentos
    • Escolhe um dos sentidos, montando o movimento completo
    • Popula a array de movimentos
    • Se a array de 2 ultimos eixos for = 3 , a array é zerada
    • Coloca a face do último movimento na string ultimo_movimento e sai do laço while
  • E por fim, isso é repetido n vezes

Se for dessa forma, achei interessante a sua lógica.

1 - Remove a última camada usada das possibilidades de movimentos

2 - Na verdade, se o número de eixos for 3, elimina o primeiro. Isso faz com que tenha sempre os dois últimos eixos na array.

Editado por Filipe Teixeira

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pra quem me conhece, square-1 é meu puzzle favorito. Dessa forma resolvi criar uma classe pra me dar scrambles para ele! :D

/**
 * Created by lucas on 06/12/15.
 */
public enum TipoDaPeca {
    MEIO, CANTO;
}
/**
 * Created by lucas on 06/12/15.
 */
public enum Peca {

    A(TipoDaPeca.MEIO, "A"), B(TipoDaPeca.CANTO, "B"), C(TipoDaPeca.MEIO, "C"), D(TipoDaPeca.CANTO, "D"),
    E(TipoDaPeca.MEIO, "E"), F(TipoDaPeca.CANTO, "F"), G(TipoDaPeca.MEIO, "G"), H(TipoDaPeca.CANTO, "H"),
    I(TipoDaPeca.MEIO, "I"), J(TipoDaPeca.CANTO, "J"), K(TipoDaPeca.MEIO, "K"), L(TipoDaPeca.CANTO, "L"),
    M(TipoDaPeca.MEIO, "M"), N(TipoDaPeca.CANTO, "N"), O(TipoDaPeca.MEIO, "O"), P(TipoDaPeca.CANTO, "P");

    String name;
    TipoDaPeca pieceType;

    Peca(TipoDaPeca pieceType, String name){
        this.name = name;
        this.pieceType = pieceType;
    }

    public String getPieceName(Peca p){
        //retorna o nome da peca
        return p.name;
    }

    public TipoDaPeca getPieceType(Peca p){
        //retorna o tipo da peca
        return p.pieceType;
    }
} 
/**
 * Created by lucas on 06/12/15.
 */
public class Posicao {

    private Peca piece;

    public Posicao(Peca piece){
        this.piece = piece;
    }

    public Peca getPiece(){
        return piece;
    }

    @Override
    public String toString() {
        return piece.getPieceName(piece);
    }
} 
/**
 * Created by lucas on 06/12/15.
 */
public class Cubo {

    private Posicao[] posicoes = new Posicao[24];

    public Cubo() {
        //Posicoes contendo as pecas da camada U
        posicoes[0] = new Posicao(Peca.A);
        posicoes[1] = new Posicao(Peca.;
        posicoes[2] = new Posicao(Peca.;
        posicoes[3] = new Posicao(Peca.C);
        posicoes[4] = new Posicao(Peca.D);
        posicoes[5] = new Posicao(Peca.D);
        posicoes[6] = new Posicao(Peca.E);
        posicoes[7] = new Posicao(Peca.F);
        posicoes[8] = new Posicao(Peca.F);
        posicoes[9] = new Posicao(Peca.G);
        posicoes[10] = new Posicao(Peca.H);
        posicoes[11] = new Posicao(Peca.H);

        //Posicoes contendo as pecas da camada D
        posicoes[12] = new Posicao(Peca.I);
        posicoes[13] = new Posicao(Peca.J);
        posicoes[14] = new Posicao(Peca.J);
        posicoes[15] = new Posicao(Peca.K);
        posicoes[16] = new Posicao(Peca.L);
        posicoes[17] = new Posicao(Peca.L);
        posicoes[18] = new Posicao(Peca.M);
        posicoes[19] = new Posicao(Peca.N);
        posicoes[20] = new Posicao(Peca.N);
        posicoes[21] = new Posicao(Peca.O);
        posicoes[22] = new Posicao(Peca.P);
        posicoes[23] = new Posicao(Peca.P);
    }

    public void fazerMovimentoU(int move) {
        for (int i = 0; i <= (11 - move); i++) {
            this.moverTopo();
        }
    }

    /**
     * Esse metodo privado move o topo do square
     */
    private void moverTopo() {
        Posicao[] uPositions = new Posicao[12];
        for (int i = 0; i < uPositions.length; i++) {
            uPositions[i] = posicoes[i];
        }
        for (int i = 0; i < uPositions.length; i++) {
            Posicao aux = uPositions[i];
            uPositions[i] = uPositions[i + 1];
            uPositions[i + 1] = aux;
            if (i == (uPositions.length - 2)) {
                break;
            }
        }
        for (int i = 0; i < uPositions.length; i++) {
            posicoes[i] = uPositions[i];
        }
    }

    public void fazerMovimentoD(int move) {
        for (int i = 0; i <= (11 - move); i++) {
            this.moverBase();
        }
    }

    /**
     * Esse metodo privado move a base do square
     */
    private void moverBase() {
        Posicao[] dPositions = new Posicao[12];
        for (int i = 0; i < dPositions.length; i++) {
            dPositions[i] = posicoes[i + 12];
        }
        for (int i = 0; i < dPositions.length; i++) {
            Posicao aux = dPositions[i];
            dPositions[i] = dPositions[i + 1];
            dPositions[i + 1] = aux;
            if (i == (dPositions.length - 2)) {
                break;
            }
        }
        for (int i = 0; i < dPositions.length; i++) {
            posicoes[i + 12] = dPositions[i];
        }
    }

    /**
    Esse metodo faz uma "barra" no square.
     A barra permuta as pecas contidas nas posicoes 1 a 6 com as posicoes de 12 a 17.
     */
    public void fazerBarra() {
        Posicao[] udPositions = new Posicao[12];
        Posicao[] uPositions = new Posicao[6], dPositions = new Posicao[6];

        for (int i = 0; i < 6; i++) {
            uPositions[i] = posicoes[i + 1];
            dPositions[i] = posicoes[i + 12];
        }
        for (int i = 0; i < 6; i++) {
            udPositions[i] = uPositions[i];
            udPositions[i + 6] = dPositions[i];
        }
        for (int j = 0; j < 6; j++) {
            for (int i = 0; i < udPositions.length; i++) {
                Posicao aux = udPositions[i];
                udPositions[i] = udPositions[i + 1];
                udPositions[i + 1] = aux;
                if (i == (udPositions.length - 2)) {
                    break;
                }
            }
        }
        for (int i = 0; i < 6; i++) {
            posicoes[i + 1] = udPositions[i];
            posicoes[i + 12] = udPositions[i + 6];
            if (i == 5) {
                posicoes[i + 1] = udPositions[i - 1];
            }
        }
    }

    /***
     * @return true se a linha esta bloqueada e false se esta tudo OK
     */
    public boolean linhaPrincipalBloqueada() {
        if ((posicoes[0].getPiece().pieceType == TipoDaPeca.CANTO && posicoes[1].getPiece().pieceType == TipoDaPeca.CANTO) ||
                (posicoes[6].getPiece().pieceType == TipoDaPeca.CANTO && posicoes[7].getPiece().pieceType == TipoDaPeca.CANTO ||
                        (posicoes[17].getPiece().pieceType == TipoDaPeca.CANTO && posicoes[18].getPiece().pieceType == TipoDaPeca.CANTO ||
                                (posicoes[23].getPiece().pieceType == TipoDaPeca.CANTO && posicoes[12].getPiece().pieceType == TipoDaPeca.CANTO)))) {
            Peca p1 = posicoes[0].getPiece();
            Peca p2 = posicoes[1].getPiece();
            Peca p3 = posicoes[6].getPiece();
            Peca p4 = posicoes[7].getPiece();
            Peca p5 = posicoes[17].getPiece();
            Peca p6 = posicoes[18].getPiece();
            Peca p7 = posicoes[23].getPiece();
            Peca p8 = posicoes[12].getPiece();
            if (p1.equals(p2) || p3.equals(p4) || p5.equals(p6) || p7.equals(p8)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        String retorno = "Camada U:\n";
        for (int i = 0; i < posicoes.length; i++) {
            retorno += "A posicao " + (i + 1) + " contem a peca " + posicoes[i].toString() + "\n";
            if (i == 11) {
                retorno += "\nCamada D:\n";
            }
        }
        return retorno;
    }
} 
import java.util.ArrayList;
import java.util.Random;

public class ClassePrincipal {

    private Cubo cubo = new Cubo();
    private Random r = new Random();
    private int[] movimentosDisponiveis = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6};
    private ArrayList<int[]> sorteadosOk = new ArrayList<>();

    public ClassePrincipal(){
        System.out.println(scramble());
    }

    public void gerarSequencia(){
        int u = movimentosDisponiveis[r.nextInt(12)];
        int d = movimentosDisponiveis[r.nextInt(12)];
        cubo.fazerMovimentoU(u);
        cubo.fazerMovimentoD(d);
        if (cubo.linhaPrincipalBloqueada()){
            /*
            como a linha ficou bloqueada faz os movimentos contrarios pra voltar o cubo pra posicao inicial
             */
            cubo.fazerMovimentoU(u * (-1));
            cubo.fazerMovimentoD(d * (-1));
            this.gerarSequencia(); // <- chamada recursiva
        } else {
            int[] xy = {u, d}; // <- se der certo adiciona o par de movimentos OK na lista
            sorteadosOk.add(xy);
            cubo.fazerBarra(); // <- como deu certo ai pode aplicar um "/" no square pra poder continuar
        }
    }

    public String scramble(){
        for (int i = 0; i < 10; i++){
            gerarSequencia();
        }
        String retorno = "";
        for (int i = 0; i < sorteadosOk.size(); i++){
            retorno += "(" + sorteadosOk.get(i)[0] + "," + sorteadosOk.get(i)[1] + ")/";
        }
        return retorno;
    }

    public static void main(String[] args) {
        new ClassePrincipal();
    }
} 

Escrevi em Java, mas pretendo escrever ele em Python também, vai ser bacana! Mesmo se você não escreve em Java espero que te ajude em algo, até porque lógica é comum a todas as linguagens. Qualquer duvida é só falar. ^^

Criei um gist das classes nesse link, se preferir:

https://gist.github.com/LucasAlfare/910b35912a7c45811b4f

Editado por Lucas Sousa-1
2 pessoas curtiram isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Como expressar o quanto me impressionei sem usar palavrões?

Com certeza vou reler seu post várias vezes até conseguir pegar a lógica. Tem muito conhecimento também sobre o puzzle que daria pra eu adquirir.

1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Como expressar o quanto me impressionei sem usar palavrões?

Com certeza vou reler seu post várias vezes até conseguir pegar a lógica. Tem muito conhecimento também sobre o puzzle que daria pra eu adquirir.

Amigo, fico feliz por meus códigos terem aberto mais possibilidades lógicas em sua mente. Espero que eu possa continuar te ajudando. ^^

Pretendo fazer umas classes de Clock (na verdade já comecei alguns esboços), e quiser me ajudar tâmo aê.

Editado por Lucas Sousa-1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bem, refiz a classe geradora de embaralhamentos para Square-1 em Python. Aproveitei e dei uma "otimizada" nos métodos, apesar de, diferentemente do Java, ainda estar consumindo MUITA memória ao ser executada...Segue o código:

import random as r


class Peca(object):
    pass


class Edge(Peca):
    def __init__(self, name):
        self.name = name

    def getPieceName(self):
        return self.name

    def __str__(self):
        return self.name


class Corner(Peca):
    def __init__(self, name):
        self.name = name

    def getPieceName(self):
        return self.name

    def __str__(self):
        return self.name


class SquareOne(object):
    a = Edge('a')
    b = Corner('b')
    c = Edge('c')
    d = Corner('d')
    e = Edge('e')
    f = Corner('f')
    g = Edge('g')
    h = Corner('h')
    #
    i = Edge('i')
    j = Corner('j')
    k = Edge('k')
    l = Corner('l')
    m = Edge('m')
    n = Corner('n')
    o = Edge('o')
    p = Corner('p')

    posicoes = [
        # Peças da camada U
        a, b, b, c, d, d, e, f, f, g, h, h,
        # Peças da camada D
        i, j, j, k, l, l, m, n, n, o, p, p]

    def U(self, movimento):
        TOOOOOOP_pieces = self.posicoes[0:12]
        ll = len(TOOOOOOP_pieces)

        if movimento > 0:
            for i in range(movimento):
                aux = [TOOOOOOP_pieces[ll - 1]]
                for j in range(ll):
                    aux.append(TOOOOOOP_pieces[j])
                    if j is (ll - 1):
                        break
                TOOOOOOP_pieces = aux
        elif movimento < 0:
            for i in range(movimento * (-1)):
                deleted = TOOOOOOP_pieces[0]
                TOOOOOOP_pieces.remove(deleted)
                TOOOOOOP_pieces.append(deleted)

        ultimos = self.posicoes[12:len(self.posicoes)]

        self.posicoes[0:12] = TOOOOOOP_pieces
        self.posicoes[12:24] = ultimos

    def D(self, movimento):
        botton_pieces = self.posicoes[12:24]
        ll = len(botton_pieces)

        if movimento > 0:
            for i in range(movimento):
                aux = [botton_pieces[ll - 1]]
                for j in range(ll):
                    aux.append(botton_pieces[j])
                    if j is (ll - 1):
                        break
                botton_pieces = aux
        elif movimento < 0:
            for i in range(movimento * (-1)):
                deleted = botton_pieces[0]
                botton_pieces.remove(deleted)
                botton_pieces.append(deleted)

        primeiros = self.posicoes[0:12]

        self.posicoes[0:12] = primeiros
        self.posicoes[12:24] = botton_pieces

    def barra(self):

        corte_de_U = self.posicoes[1:7]
        corte_de_D = self.posicoes[12:18]

        for i in range(6):
            aux = corte_de_U[i]
            aux2 = corte_de_D[i]
            corte_de_U[i] = aux2
            corte_de_D[i] = aux

        self.posicoes[1:7] = corte_de_U
        self.posicoes[12:18] = corte_de_D

    def isTravado(self):
        aux = self.posicoes
        if aux[0] is aux[1] or aux[6] is aux[7] or aux[17] is aux[18] or aux[23] is aux[12]:
            return True
        return False

    def __str__(self):
        toPrint = ''
        for i in range(self.posicoes.__len__()):
            toPrint += self.posicoes[i].__str__() + " "
            if i is 11:
                toPrint += "\n\n"
        return toPrint


class Embaralhador(object):
    moves = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6]
    sq1 = SquareOne()

    sorteadosOk = []

    def embaralhar(self):

        u = r.choice(self.moves)
        d = r.choice(self.moves)

        self.sq1.U(u)
        self.sq1.D(d)

        if self.sq1.isTravado():
            self.sq1.U(u*-1)
            self.sq1.D(d*-1)
            self.embaralhar()
        else:
            self.sq1.barra()
            self.sorteadosOk.append([u, d])

    def scramble(self):
        for i in range(5):
            self.embaralhar()

        s = ''
        oks = self.sorteadosOk

        for i in range(len(oks)):
            s += '(' + str(oks[i][0]) + ',' + str(oks[i][1]) + ')/'

        return s


print(Embaralhador().scramble())
1 pessoa curtiu isso

Compartilhar este post


Link para o post
Compartilhar em outros sites