# Simplify Rubik's Cube Moves

## Background

On a Rubik's cube there are 54 moves that you can execute, for example, turn the right face anti-clockwise, or rotate the top face and the horizontal slice twice. To notate any move, each face (or slice) has a letter assigned to it. To move that face clockwise once, you just write the letter on its own, so for the top face it would be U (for "up"). You can put a ' (pronounced "prime") after the letter to notate moving the face anti-clockwise, or a 2 to turn the face twice. You can see more details on this here.

## The Challenge

Your challenge is to take a list of moves which all rotate the same face, and simplify it into one move. For example if the input was R R2, you'd be turning the right face clockwise once, then twice, which results in the equivalent of R' — turning the right face anti-clockwise once.

## Rules

• If the result doesn't modify the cube, the output should be nothing or a falsey value.
• Input must be taken in the proper notation described above, otherwise, it's up to you.
• You can assume that no move will have a 2 and a ' in it.

## Test Cases

R R2 -> R'
L2 L L' L -> L'
u' u2 u2 -> u'
y y' ->
F F' F F F' -> F
E' E2 E E E' -> E2

• "You may take input in any format that you think is reasonable." I really don't sure what could be considered "reasonable". If I take L2 L L' L as [2, 1, 3, 1] (and another input LLLL which is ignored) and simply sum them up, mod 4, outputs 3, is this still something "reasonable"?
– tsh
Jul 11 at 6:28
• I was wondering if that would be ambiguous. I'll say that the input must be in the proper notation mentioned in the background section. What I meant by "any format that you think is reasonable" was more that you can take input as a list, a string, delimited by anything, etc. Jul 11 at 6:33
• Can we assume that all of the moves will start with the same letter?
– Neil
Jul 11 at 7:31
• @Neil Yes, "moves which all rotate the same face" means that they'll all start with the same letter Jul 11 at 8:29
• I think the1st rule simply needlessly complicates the challenge. Why cant we just output the original string? Jul 11 at 15:51

# Python 2, 49 bytes (inspired by @math junkie)

lambda s:(s[0]+"2'"[len(s)%2])[:len(s)%4]

Attempt This Online!

Python 3 version is 51 bytes.

This takes the input sequence as a string without delimiters.

### How?

By applying the backtick operator twice we gain two pairs of quotation marks which is neutral modulo 4 and we get all apostrophes escaped, a cheap way of replacing them with two characters each. Now, we can simply count characters because "A","A2","A\'" have the right lengths in terms of quarter turns. It remains to format the residue modulo 4 as required.

### Python, 56 bytes

lambda s:(s[0]+"**2'"[i:=-sum(map(" *'".find,s))%4])[:i]

Attempt This Online!

This version can handle a proper delimiter (single space).

### Old Python, 60 bytes

lambda s:(s[0]+"2'")[:(i:=-sum(map("  '2".find,s)))%4:1+i%2]

Attempt This Online!

• 54 bytes by taking a string without separators as input: ATO Jul 12 at 3:01
• @mathjunkie If we are willing to be that opportunistic with the input format then we can do much better... Jul 12 at 4:21

# Retina 0.8.2, 24 bytes

'
22
\B.
2
+....$22 '  Try it online! Takes input as a smashed string of moves but link is to test suite that removes spaces for convenience. Explanation: ' 22  Change anti-clockwise rotations to three rotations (2 means "repeat last rotation"). \B. 2  Change face rotations after the first to 2s too. +....$



Reduce modulo 4, making sure to keep the first face.

22
'


Change three rotations back to an anti-clockwise rotation.

# K (ngn/k), 26 bytes

{|(0," 2'",'*x)4!+/1+39=x}


Try it online!

-4 bytes thanks to @ovs!

Inspired by @Neil's Retina answer for a bunch of bytes saved.

## Explanation

• 1+39= 1 for A, 2 for A2, 3 for A'
• 4+/ sum mod 4
• |(0," 2'",'*x) convert back to move or 0
• 26: {|(0," 2'",'*x)4!+/1+39=x}
– ovs
Jul 11 at 10:10
• @ovs Thanks! Very clever, evidently charcode math is still quite a stretch for me to intuitively wrap my head around. Jul 11 at 10:19
• Not really relevant anymore because its longer, but maybe still interesting: {|(" 2'",'**x)4!3+/1|4!x@'1} is what I had with the previous list-of-moves input format (unsure if " " is a valid output for no move)
– ovs
Jul 11 at 10:23

# Cubestack, 166 bytes

I think this language is quite fitting.

b' S S' y S S' y2 M R' M' M R2 M' l2 M2 M R2 M' D x U' M R2 M' x2 l x M r M' x2 M R' M' x' x' R y' M r' M' U M2 x S R' r R B2 R' U2 S' l' r b' M M' r M R M' r l' R x'


Try it Online!

Formatted nicely:

b' S S' y
S S' y2 M R' M' M R2 M' l2 M2
M R2 M' D x
U' M R2 M' x2
l x
M r M' x2
M R' M'
x'
x' R
y' M r' M' U M2 x
S R' r R B2 R' U2 S' l' r
b' M M' r M R M' r
l' R
x'


Goes through each move, if the move ending is 2, then 2 is added to the total, if it's ' 3 is added, otherwise 1 is added. The total mod 4 is then used to index into the string ' 2 and the appropriate letter is prepended.

# 05AB1E, 1817 15 bytes

''T:g4%ø¤£3'':


-1 byte being inspired by @mathJunkie's Pyth answer
-2 bytes thanks to @CommandMaster

Input as a string without delimiter.

Explanation:

''T:      # Replace all "'" with "10" in the (implicit) input-string
g     # Pop and push the length
4%   # Modulo-4
ø         # Create pairs with the (implicit) input-string, implicitly only using
# the first character since we zip it with a single digit
# Pop this single-item list and push the string-pair to the stack
¤       # Push its last character, the digit (without popping the string)
£      # Pop both, and leave just that many leading characters
3'':  # Replace a potential "3" with "'"
# (after which the result is output implicitly)

• ''T:g4%ø¤¤£3'': seems to work for 15 bytes Jul 12 at 7:07
• @CommandMaster So it does, thanks. Smart way of using the zip-builtin! :) Jul 12 at 7:15

# Charcoal, 23 21 bytes

≔﹪⁺Ｌθ№θ'⁴η✂⁺§θ⁰§2'η⁰η


Try it online! Link is to verbose version of code. Takes a smashed list as input. Explanation:

≔﹪⁺Ｌθ№θ'⁴η


Add the length to the count of 's and reduce modulo 4.

✂⁺§θ⁰§2'η⁰η


Concatenate 2 or ' to the face depending on whether the total is even, but then truncate the string to the reduced length.

# Pyth, 2220 17 bytes

-3 bytes using @loopy wait's idea

<X+hQJ%lQ4\3\'J

<X+hQJ%lQ4\3\'J
Q            Surround the input with two pairs of quotes
(Which also escapes ' characters as \')
%l   4           Take the length mod 4
J                 (Set J to the result)
+hQ                  Prepend the first letter of the input
X           \3\'      Translate 3s to 's
<                J     Keep the first J elements


# JavaScript (Node.js), 60 bytes

a=>['',p=a[s=0][0],p+2,p+"'",a.map(([,v])=>s+=!v|v||3)][s%4]


Try it online!

• -1 bytes by Arnauld

# Jelly, 19 bytes

ḢɓḟḲOȯ€1S%4ị⁾'2⁹;ḣƲ


Try it online!

There's probably shorter! Calculates the rotation, R, using the sum of the ordinals of the characters trailing each letter or 1 if none exists modulo 4. Concatenates ' or 2 to the leading letter depending on R mod two and then heads this to the first (up to) R characters.