Skip to content

Instantly share code, notes, and snippets.

@Hafthor
Created January 17, 2022 22:35
Show Gist options
  • Save Hafthor/a61ff9793e15107584e44817a2e1aff9 to your computer and use it in GitHub Desktop.
Save Hafthor/a61ff9793e15107584e44817a2e1aff9 to your computer and use it in GitHub Desktop.
command line rubik's cube
package com.hafthor;
import java.util.Scanner;
public class Main {
public static void main(final String[] args) {
final RubiksCube rc = new RubiksCube();
rc.print();
Scanner scanner = new Scanner(System.in);
for (; ; ) {
System.out.print("\033[0mCommand: ");
final String s = scanner.nextLine();
if (s.length() == 0) break;
for (final char c : s.toCharArray()) {
try {
rc.rotate(c);
} catch (Exception e) {
System.err.println(e);
}
}
rc.print();
}
}
public static class RubiksCube {
// model z top layer 0a1
// / bAc
// / 2d3 eBf
// +----x C?D
// | middle layer gEh 4i5
// | jFk
// | bottom layer 6l7
// y
// 0,0,0 is the front top left of the cube
// x - negative is left, positive is right
// y - negative is down, positive is up
// z - negative is front, positive is back
// each piece is a subcube, starting position is all subcubes the same
// each subcube is Up=White, Down=Yellow, Front=Red, Back=Orange, Left=Blue, Right=Green
static final int SIZE = 3, WHITE = 0, YELLOW = 1, RED = 2, ORANGE = 3, GREEN = 4, BLUE = 5;
static final int UP = WHITE, DOWN = YELLOW, FRONT = RED, BACK = ORANGE, RIGHT = GREEN, LEFT = BLUE;
static final String COLORS = "wyrogb", DIRECTIONS = "udfbrl";
static final String[] ANSICOLOR = new String[]{"\033[37m", "\033[33m", "\033[31m", "\033[35m", "\033[34m", "\033[32m"};
static final String ANSIRESET = "\033[0m";
// corners are numbers, edges are lowercase, centers are uppercase, hidden parts are ?
static final String POS_LETTERS = new String[]{"01234567", "0a1bAc2d3" + "eBfC?DgEh" + "4i5jFk6l7", "0ab1cABdeCDf2gh3" + "iEFjG??HI??JkKLl" + "mMNnO??PQ??RoSTp" + "4qr5sUVtuWXv6wx7"}[SIZE - 2];
final Piece[][][] pieces = new Piece[SIZE][SIZE][SIZE], temp = new Piece[SIZE][SIZE][SIZE];
public RubiksCube() {
for (int z = 0; z < SIZE; z++)
for (int y = 0; y < SIZE; y++)
for (int x = 0; x < SIZE; x++)
pieces[z][y][x] = new Piece(RED, WHITE, POS_LETTERS.charAt(z * SIZE * SIZE + y * SIZE + x));
}
public void rotateFrontCubeClockwise() {
for (int z = 0; z < SIZE; z++)
for (int y = 0; y < SIZE; y++)
for (int x = 0; x < SIZE; x++)
pieces[z][y][x] = temp[z][SIZE - 1 - x][y].rotateFrontClockwise(1);
}
public void rotateUpCubeClockwise() {
for (int z = 0; z < SIZE; z++)
for (int y = 0; y < SIZE; y++)
for (int x = 0; x < SIZE; x++)
pieces[z][y][x] = temp[x][y][SIZE - 1 - z].rotateUpClockwise(1);
}
public void rotateRightCubeClockwise() {
for (int z = 0; z < SIZE; z++)
for (int y = 0; y < SIZE; y++)
for (int x = 0; x < SIZE; x++)
pieces[z][y][x] = temp[y][SIZE - 1 - z][x].rotateRightClockwise(1);
}
public void rotate(final String s) {
for (final char c : s.toCharArray()) rotate(c);
}
public void rotate(final char c) {
// copy cube to temp
for (int z = 0; z < SIZE; z++)
for (int y = 0; y < SIZE; y++)
for (int x = 0; x < SIZE; x++)
temp[z][y][x] = pieces[z][y][x];
switch (c) {
case 'z' -> rotateFrontCubeClockwise();
case 'y' -> rotateUpCubeClockwise();
case 'x' -> rotateRightCubeClockwise();
case 'f' -> rotateFrontFaceClockwise(0);
case 'F' -> rotateFrontFaceClockwise(1);
case 'b' -> rotateBackFaceClockwise(SIZE-1);
case 'B' -> rotateBackFaceClockwise(SIZE-2);
case 'u' -> rotateUpFaceClockwise(0);
case 'U' -> rotateUpFaceClockwise(1);
case 'd' -> rotateDownFaceClockwise(SIZE-1);
case 'D' -> rotateDownFaceClockwise(SIZE-2);
case 'r' -> rotateRightFaceClockwise(SIZE - 1);
case 'R' -> rotateRightFaceClockwise(SIZE - 2);
case 'l' -> rotateLeftFaceClockwise(0);
case 'L' -> rotateLeftFaceClockwise(1);
default -> throw new IllegalArgumentException("Invalid command '" + c + "'");
}
}
public void rotateFrontFaceClockwise(final int z) {
for (int y = 0; y < SIZE; y++)
for (int x = 0; x < SIZE; x++)
pieces[z][y][x] = temp[z][SIZE - 1 - x][y].rotateFrontClockwise(1);
}
public void rotateBackFaceClockwise(final int z) {
for (int y = 0; y < SIZE; y++)
for (int x = 0; x < SIZE; x++)
pieces[z][y][x] = temp[z][x][SIZE - 1 - y].rotateFrontClockwise(3);
}
public void rotateUpFaceClockwise(final int y) {
for (int z = 0; z < SIZE; z++)
for (int x = 0; x < SIZE; x++)
pieces[z][y][x] = temp[x][y][SIZE - 1 - z].rotateUpClockwise(1);
}
public void rotateDownFaceClockwise(final int y) {
for (int z = 0; z < SIZE; z++)
for (int x = 0; x < SIZE; x++)
pieces[z][y][x] = temp[SIZE - 1 - x][y][z].rotateUpClockwise(3);
}
public void rotateRightFaceClockwise(final int x) {
for (int z = 0; z < SIZE; z++)
for (int y = 0; y < SIZE; y++)
pieces[z][y][x] = temp[y][SIZE - 1 - z][x].rotateRightClockwise(1);
}
public void rotateLeftFaceClockwise(final int x) {
for (int z = 0; z < SIZE; z++)
for (int y = 0; y < SIZE; y++)
pieces[z][y][x] = temp[SIZE - 1 - y][z][x].rotateRightClockwise(3);
}
public void print() {
final String leftPad = " ".repeat(SIZE + 1);
for (int z = SIZE - 1; z >= 0; z--) {
System.out.print(leftPad);
for (int x = 0; x < SIZE; x++) // up
System.out.print(pieces[z][0][x].faceAnsiChar(UP));
System.out.println(ANSIRESET);
}
for (int y = 0; y < SIZE; y++) {
for (int x = 0; x < SIZE; x++) // left
System.out.print(pieces[SIZE - 1 - x][y][0].faceAnsiChar(LEFT));
System.out.print(' ');
for (int x = 0; x < SIZE; x++) // front
System.out.print(pieces[0][y][x].faceAnsiChar(FRONT));
System.out.print(' ');
for (int x = 0; x < SIZE; x++) // right
System.out.print(pieces[x][y][SIZE - 1].faceAnsiChar(RIGHT));
System.out.print(' ');
for (int x = 0; x < SIZE; x++) // back
System.out.print(pieces[SIZE - 1][y][SIZE - 1 - x].faceAnsiChar(BACK));
System.out.println(ANSIRESET);
}
for (int z = 0; z < SIZE; z++) {
System.out.print(leftPad);
for (int x = 0; x < SIZE; x++) // down
System.out.print(pieces[z][SIZE - 1][x].faceAnsiChar(DOWN));
System.out.println(ANSIRESET);
}
}
public static class Piece {
int front, up;
final char c; // up down front back right left
private static final String[] ROTATIONS = new String[]{"bogr", "brgo", "wgyb", "wbyg", "woyr", "wryo"};
public Piece(final int front, final int up, final char c) {
this.front = front;
this.up = up;
this.c = c;
}
public int faceColor(int face) {
if (face < RIGHT) {//up down front back
return new int[]{up, up ^ 1, front, front ^ 1}[face];
}
final String rot = ROTATIONS[front];
final int right = COLORS.indexOf(rot.charAt((rot.indexOf(COLORS.charAt(up)) + 3) % rot.length()));
return face == RIGHT ? right : (right ^ 1);
}
public String faceAnsiChar(int face) {
return ANSICOLOR[faceColor(face)] + c;
}
public Piece rotateFrontClockwise(final int amt) {
final String rot = ROTATIONS[front];
up = COLORS.indexOf(rot.charAt((rot.indexOf(COLORS.charAt(up)) + amt) % rot.length()));
return this;
}
public Piece rotateUpClockwise(final int amt) {
final String rot = ROTATIONS[up];
front = COLORS.indexOf(rot.charAt((rot.indexOf(COLORS.charAt(front)) + amt) % rot.length()));
return this;
}
public Piece rotateRightClockwise(final int amt) {
final String rot = ROTATIONS[front];
final int right = COLORS.indexOf(rot.charAt((rot.indexOf(COLORS.charAt(up)) + 3) % rot.length()));
final String rot2 = ROTATIONS[right];
final int indexUp = rot2.indexOf(COLORS.charAt(up));
up = COLORS.indexOf(rot2.charAt((indexUp + amt) % rot.length()));
front = COLORS.indexOf(rot2.charAt((indexUp + amt + 1) % rot.length()));
return this;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment