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
2and 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
9 Answers 9
Python 2, 49 bytes (inspired by @math junkie)
lambda s:(s[0]+"2'"[len(``s``)%2])[:len(``s``)%4]
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]
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]
-
\$\begingroup\$ 54 bytes by taking a string without separators as input: ATO \$\endgroup\$math junkie– math junkie2022年07月12日 03:01:43 +00:00Commented Jul 12, 2022 at 3:01
-
1\$\begingroup\$ @mathjunkie If we are willing to be that opportunistic with the input format then we can do much better... \$\endgroup\$loopy walt– loopy walt2022年07月12日 04:21:24 +00:00Commented Jul 12, 2022 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}
-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
-
1\$\begingroup\$ 26:
{|(0," 2'",'*x)4!+/1+39=x}\$\endgroup\$ovs– ovs2022年07月11日 10:10:36 +00:00Commented Jul 11, 2022 at 10:10 -
\$\begingroup\$ @ovs Thanks! Very clever, evidently charcode math is still quite a stretch for me to intuitively wrap my head around. \$\endgroup\$Mama Fun Roll– Mama Fun Roll2022年07月11日 10:19:16 +00:00Commented Jul 11, 2022 at 10:19
-
1\$\begingroup\$ 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) \$\endgroup\$ovs– ovs2022年07月11日 10:23:30 +00:00Commented Jul 11, 2022 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'
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, (削除) 18 (削除ここまで) (削除) 17 (削除ここまで) 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.
Try it online or verify all test cases.
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)
-
1\$\begingroup\$
''T:g4%ø¤¤£3'':seems to work for 15 bytes \$\endgroup\$Command Master– Command Master2022年07月12日 07:07:12 +00:00Commented Jul 12, 2022 at 7:07 -
\$\begingroup\$ @CommandMaster So it does, thanks. Smart way of using the zip-builtin! :) \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2022年07月12日 07:15:17 +00:00Commented Jul 12, 2022 at 7:15
Charcoal, (削除) 23 (削除ここまで) 21 bytes
≔%+LθNoθ'4η✂+§θ0§2'η0η
Try it online! Link is to verbose version of code. Takes a smashed list as input. Explanation:
≔%+LθNoθ'4η
Add the length to the count of 's and reduce modulo 4.
✂+§θ0§2'η0η
Concatenate 2 or ' to the face depending on whether the total is even, but then truncate the string to the reduced length.
Pyth, (削除) 22 (削除ここまで) (削除) 20 (削除ここまで) 17 bytes
-3 bytes using @loopy wait's idea
<X+hQJ%l``Q43円\'J
Try it online! -- Try all test cases
<X+hQJ%l``Q43円\'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 `3`s 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]
- -1 bytes by Arnauld
Jelly, 19 bytes
ḢɓḟḲOȯ1ドルS%4ị)'29;ḣƲ
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.
L2 L L' Las[2, 1, 3, 1](and another inputLLLLwhich is ignored) and simply sum them up, mod 4, outputs3, is this still something "reasonable"? \$\endgroup\$