Created
January 17, 2022 22:35
-
-
Save Hafthor/a61ff9793e15107584e44817a2e1aff9 to your computer and use it in GitHub Desktop.
command line rubik's cube
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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