Neat natural way to simulate

Stefan

Legend
Joined
May 7, 2006
Messages
7,286
WCA ID
2003POCH01
YouTube
Visit Channel
Not sure if new, but I came up with a neat way to simulate.

Represent the state as a string like
"UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR"
which for those 20 pieces tell their current location. If we do a U turn, we get:
"UL UF UR UB DF DR DB DL FR FL BR BL ULF UFR URB UBL DRF DFL DLB DBR"
This says the first piece (UF) is now at UL, etc.

This can be implemented by changing exactly those locations having the turn name (U)
"UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR"
and cycling all other characters in that cubie location ("U" cycles F->L->B->R->F):
"UL UF UR UB DF DR DB DL FR FL BR BL ULF UFR URB UBL DRF DFL DLB DBR"

So a state is given as such a string, and moves are defined by for example "U"=>"FLBR". It's really easy and natural to implement, no ugly numbers, which is why I find it neat. Could also be used for Megaminx and Pyraminx, for example (edit: darn, I just realized there aren't many people face-turning the pyraminx :p).

Here's a Perl program simulating a T perm (also available for playing at http://ideone.com/bbOhtk):
Code:
@moves = qw(R U R' U' R' F R2 U' R' U' R U R' F');

$state = "UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR";
%turns = (U => 'FLBR', D => 'FRBL', R => 'FUBD', L => 'FDBU', F => 'URDL', B => 'ULDR');

sub move {
  my ($pos) = @_;
  ($cycled = $turns{$side}) =~ s/(.)(.*)/$2$1/;
  eval "\$pos =~ y/$turns{$side}/$cycled/";
  $pos;
}

print "Moves: @moves\nStart: $state\n";
for $move (@moves) {
  $move =~ s/'/3/;
  ($side, $angle) = split //, $move . 1;
  $state =~ s/\w*$side\w*/move($&)/ge while $angle--;
}
print "End:   $state\n";

That code prints this:
Code:
Moves: R U R' U' R' F R2 U' R' U' R U R' F'
Start: UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
End:   UF UL UB UR DF DR DB DL FR FL BR BL URB UFR UBL ULF DRF DFL DLB DBR
 
Last edited:
Hmm, actually the color scheme is provided by the corner locations in
$state = "UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR";
already, so I shouldn't even need
%turns = (U => 'FLBR', D => 'FRBL', R => 'FUBD', L => 'FDBU', F => 'URDL', B => 'ULDR'); ...
 
Inspired by the minimalist javascript simulators? :)

Unfortunatly I don't understand the code perfectly (I don't speak pearl...)
Can it be that URF becames UFR after some rotations?
 
Inspired by the minimalist javascript simulators? :)

Inspired/reminded, yes (I had thought of this a while back but never got around to post it).

Unfortunatly I don't understand the code perfectly (I don't speak pearl...)

Is the idea clear, though? I chose Perl because it's good with string manipulation and I'm fairly familiar with it (tried doing it in javascript but quickly gave up).

Can it be that URF becames UFR after some rotations?

No, that shouldn't happen. The three sides should always be read the same direction around the corner.

I rewrote the program, now I don't need that explicit %turns definition anymore and get all information from the state (code also on ideone):
Code:
@moves = qw(R U R' U' R' F R2 U' R' U' R U R' F');
$state = "UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR";

sub move {
  my ($pos) = @_;
  eval "\$pos =~ y/$from/$to/";
  $pos;
}

print "Moves: @moves\nStart: $state\n";
for $move (@moves) {
  $move =~ s/'/3/;
  ($side, $angle) = split //, $move . 1;
  $from = $to = '';
  for (split ' ', $state) {
    if (/.../ && /$side/) {
      ($t, $f) = split '', "$'$`";
      $from .= $f;
      $to .= $t;
    }
  }
  $state =~ s/\w*$side\w*/move($&)/ge while $angle--;
}
print "End:   $state\n";
 
Wow. I've used this idea for years, but never have I seen it expressed so concisely.

You can also do the rotations and reflections pretty easily just by substituting colors forward
and back, so this approach works well for symmetry calculations as well. (But you can also
do rotations and reflections on move sequences of course.)

Impressive Perl coding!
 
Reminds me very much of this, I think it's basically the same idea but in text format.

Indeed, that looks like it. Gotta learn about those complex puzzles now. Thanks.

Impressive Perl coding!

Ha, and here I was, thinking it's too long and not perlish :) (still think so). I don't like that I have a separate function, and I don't like the big block in my second program just to compute $from/$to. I got a hash for the cycling with
%cycle = map {/.../ && /$side/ && split('', "$'$`")} split ' ', $state;
or cleaner
%cycle = map {/.../ && /$side/ ? split('', "$'$`") : ()} split ' ', $state;
but then didn't find a good way to use it.
 
Here you go, that's better (using look-ahead/behind, don't know why I didn't think of that right away):

Code:
@moves = qw(R U R' U' R' F R2 U' R' U' R U R' F');
$state = "UF UR UB UL DF DR DB DL FR FL BR BL URF UBR ULB UFL DFR DLF DBL DRB";

print "Moves: @moves\nStart: $state\n";
for $move (@moves) {
  $move =~ s/'/3/;
  ($side, $angle) = split //, $move . 1;
  %cycle = map {/.../ && /$side/ ? split('', "$'$`") : ()} split ' ', $state;
  $state =~ s/\w(?=\w?$side)|(?<=$side)\w|(?<=$side\w)\w|/$cycle{$&}/g while $angle--;
}
print "End:   $state\n";
 
Last edited:
Can this concept (in js) beat te sims in the 3x3x3 sim thread in length?

Maybe. Especially when it comes to supporting turning all six sides. I'm no good at javascript, though.

Also, can you write a more readable pseudo-code?

I'll try:
Code:
[COLOR="#FF0000"]moves[/COLOR] = list of moves
[COLOR="#FF0000"]state[/COLOR] = state string "UF UR UB UL DF DR DB DL FR FL BR BL URF UBR ULB UFL DFR DLF DBL DRB"

print [COLOR="#FF0000"]moves[/COLOR] and [COLOR="#FF0000"]state[/COLOR]
for each [COLOR="#FF0000"]move[/COLOR] in [COLOR="#FF0000"]moves[/COLOR]:
  replace "'" with "3" in [COLOR="#FF0000"]move[/COLOR]
  append "1" to [COLOR="#FF0000"]move[/COLOR] (just in case there's no angle given, if there is then this will get ignored)
  [COLOR="#FF0000"]side[/COLOR], [COLOR="#FF0000"]angle[/COLOR] = first two characters in [COLOR="#FF0000"]move[/COLOR] (i.e. like side=U, angle=2)
  build map like [COLOR="#FF0000"]cycle[/COLOR] = {'F' => 'L', 'R' => 'F', 'L' => 'B', 'B' => 'R'} by looking at the corners in [COLOR="#FF0000"]state[/COLOR]
  do the following [COLOR="#FF0000"]angle[/COLOR] times:
    in [COLOR="#FF0000"]state[/COLOR], replace every letter followed/preceded by [COLOR="#FF0000"]side[/COLOR] with what [COLOR="#FF0000"]cycle[/COLOR] maps to
}
print [COLOR="#FF0000"]state[/COLOR]

My code relies heavily on regular expressions and how Perl uses them. Everybody should be familiar at least with regular expressions :p
 
Last edited:
207 bytes in Perl acting somewhat like our recent javascript simulators (reacting to input, supporting letters UDLRFB):

Code:
$s="UF UR UB UL DF DR DB DL FR FL BR BL URF UBR ULB UFL DFR DLF DBL DRB";while(<>){chop;$f=$_;%c=map{/.../&&/$f/?split('',"$'$`"):()}split' ',$s;$s=~s/\w(?=\w?$f)|(?<=$f)\w|(?<=$f\w)\w|/$c{$&}/g;print"$s\n"}

It's not golfed much, could probably save a few more bytes. I wish say was supported already.

Code:
R
U
R
R
R
U
U
U
R
R
R
F
R
R
U
U
U
R
R
R
U
U
U
R
U
R
R
R
F
F
F
Code:
UF BR UB UL DF FR DB DL UR FL DR BL BRU BDR ULB UFL FUR DLF DBL FRD
UL BR UR UB DF FR DB DL UF FL DR BL RFU BDR UBR ULB LUF DLF DBL FRD
UL DR BR UB DF UR DB DL UF FL FR BL RUB DFR BDR ULB LUF DLF DBL URF
UL FR DR UB DF BR DB DL UF FL UR BL RBD FUR DFR ULB LUF DLF DBL BRU
UL UR FR UB DF DR DB DL UF FL BR BL RDF UBR FUR ULB LUF DLF DBL DRB
UB UF FR UR DF DR DB DL UL FL BR BL RDF URF LUF UBR BUL DLF DBL DRB
UR UL FR UF DF DR DB DL UB FL BR BL RDF UFL BUL URF RUB DLF DBL DRB
UF UB FR UL DF DR DB DL UR FL BR BL RDF ULB RUB UFL FUR DLF DBL DRB
UF UB UR UL DF FR DB DL BR FL DR BL RFU ULB RBD UFL UBR DLF DBL FRD
UF UB BR UL DF UR DB DL DR FL FR BL RUB ULB RDF UFL BDR DLF DBL URF
UF UB DR UL DF BR DB DL FR FL UR BL RBD ULB RFU UFL DFR DLF DBL BRU
RF UB DR UL LF BR DB DL FD FU UR BL RBD ULB DFR RFU LFD LUF DBL BRU
RU UB FR UL LF DR DB DL FD FU BR BL RDF ULB FUR RUB LFD LUF DBL DRB
RB UB UR UL LF FR DB DL FD FU DR BL RFU ULB UBR RBD LFD LUF DBL FRD
RB UR UF UB LF FR DB DL FD LU DR BL FLU UBR URF RBD LFD BUL DBL FRD
RB UF UL UR LF FR DB DL FD BU DR BL LBU URF UFL RBD LFD RUB DBL FRD
RB UL UB UF LF FR DB DL FD RU DR BL BRU UFL ULB RBD LFD FUR DBL FRD
RD UL UB UF LF UR DB DL FD RB FR BL DRB UFL ULB RDF LFD UBR DBL URF
RF UL UB UF LF BR DB DL FD RD UR BL FRD UFL ULB RFU LFD BDR DBL BRU
RU UL UB UF LF DR DB DL FD RF BR BL URF UFL ULB RUB LFD DFR DBL DRB
FU UB UR UL LF DR DB DL FD RF BR BL UFL ULB UBR FUR LFD DFR DBL DRB
LU UR UF UB LF DR DB DL FD RF BR BL ULB UBR URF LUF LFD DFR DBL DRB
BU UF UL UR LF DR DB DL FD RF BR BL UBR URF UFL BUL LFD DFR DBL DRB
BU UF UL BR LF FR DB DL FD RU DR BL BDR BRU UFL BUL LFD FUR DBL FRD
RU UL UB BR LF FR DB DL FD FU DR BL BDR RFU ULB RUB LFD LUF DBL FRD
RB UL UB DR LF UR DB DL FD FU FR BL DFR RUB ULB RBD LFD LUF DBL URF
RD UL UB FR LF BR DB DL FD FU UR BL FUR RBD ULB RDF LFD LUF DBL BRU
RF UL UB UR LF DR DB DL FD FU BR BL UBR RDF ULB RFU LFD LUF DBL DRB
DF UL UB UR UF DR DB DL FL FR BR BL UBR DLF ULB DFR UFL URF DBL DRB
LF UL UB UR RF DR DB DL FU FD BR BL UBR LUF ULB LFD RFU RDF DBL DRB
UF UL UB UR DF DR DB DL FR FL BR BL UBR URF ULB UFL DFR DLF DBL DRB
Demo at ideone (check the output at the bottom).
 
Last edited:
207 bytes in Perl acting somewhat like our recent javascript simulators (reacting to input, supporting letters UDLRFB):

Code:
$s="UF UR UB UL DF DR DB DL FR FL BR BL URF UBR ULB UFL DFR DLF DBL DRB";while(<>){chop;$f=$_;%c=map{/.../&&/$f/?split('',"$'$`"):()}split' ',$s;$s=~s/\w(?=\w?$f)|(?<=$f)\w|(?<=$f\w)\w|/$c{$&}/g;print"$s\n"}

It's not golfed much, could probably save a few more bytes. I wish say was supported already.

Code:
R
U
R
R
R
U
U
U
R
R
R
F
R
R
U
U
U
R
R
R
U
U
U
R
U
R
R
R
F
F
F
Code:
UF BR UB UL DF FR DB DL UR FL DR BL BRU BDR ULB UFL FUR DLF DBL FRD
UL BR UR UB DF FR DB DL UF FL DR BL RFU BDR UBR ULB LUF DLF DBL FRD
UL DR BR UB DF UR DB DL UF FL FR BL RUB DFR BDR ULB LUF DLF DBL URF
UL FR DR UB DF BR DB DL UF FL UR BL RBD FUR DFR ULB LUF DLF DBL BRU
UL UR FR UB DF DR DB DL UF FL BR BL RDF UBR FUR ULB LUF DLF DBL DRB
UB UF FR UR DF DR DB DL UL FL BR BL RDF URF LUF UBR BUL DLF DBL DRB
UR UL FR UF DF DR DB DL UB FL BR BL RDF UFL BUL URF RUB DLF DBL DRB
UF UB FR UL DF DR DB DL UR FL BR BL RDF ULB RUB UFL FUR DLF DBL DRB
UF UB UR UL DF FR DB DL BR FL DR BL RFU ULB RBD UFL UBR DLF DBL FRD
UF UB BR UL DF UR DB DL DR FL FR BL RUB ULB RDF UFL BDR DLF DBL URF
UF UB DR UL DF BR DB DL FR FL UR BL RBD ULB RFU UFL DFR DLF DBL BRU
RF UB DR UL LF BR DB DL FD FU UR BL RBD ULB DFR RFU LFD LUF DBL BRU
RU UB FR UL LF DR DB DL FD FU BR BL RDF ULB FUR RUB LFD LUF DBL DRB
RB UB UR UL LF FR DB DL FD FU DR BL RFU ULB UBR RBD LFD LUF DBL FRD
RB UR UF UB LF FR DB DL FD LU DR BL FLU UBR URF RBD LFD BUL DBL FRD
RB UF UL UR LF FR DB DL FD BU DR BL LBU URF UFL RBD LFD RUB DBL FRD
RB UL UB UF LF FR DB DL FD RU DR BL BRU UFL ULB RBD LFD FUR DBL FRD
RD UL UB UF LF UR DB DL FD RB FR BL DRB UFL ULB RDF LFD UBR DBL URF
RF UL UB UF LF BR DB DL FD RD UR BL FRD UFL ULB RFU LFD BDR DBL BRU
RU UL UB UF LF DR DB DL FD RF BR BL URF UFL ULB RUB LFD DFR DBL DRB
FU UB UR UL LF DR DB DL FD RF BR BL UFL ULB UBR FUR LFD DFR DBL DRB
LU UR UF UB LF DR DB DL FD RF BR BL ULB UBR URF LUF LFD DFR DBL DRB
BU UF UL UR LF DR DB DL FD RF BR BL UBR URF UFL BUL LFD DFR DBL DRB
BU UF UL BR LF FR DB DL FD RU DR BL BDR BRU UFL BUL LFD FUR DBL FRD
RU UL UB BR LF FR DB DL FD FU DR BL BDR RFU ULB RUB LFD LUF DBL FRD
RB UL UB DR LF UR DB DL FD FU FR BL DFR RUB ULB RBD LFD LUF DBL URF
RD UL UB FR LF BR DB DL FD FU UR BL FUR RBD ULB RDF LFD LUF DBL BRU
RF UL UB UR LF DR DB DL FD FU BR BL UBR RDF ULB RFU LFD LUF DBL DRB
DF UL UB UR UF DR DB DL FL FR BR BL UBR DLF ULB DFR UFL URF DBL DRB
LF UL UB UR RF DR DB DL FU FD BR BL UBR LUF ULB LFD RFU RDF DBL DRB
UF UL UB UR DF DR DB DL FR FL BR BL UBR URF ULB UFL DFR DLF DBL DRB
Demo at ideone (check the output at the bottom).

Neat. :tu

I'll try:
Code:
[COLOR="#FF0000"]moves[/COLOR] = list of moves
[COLOR="#FF0000"]state[/COLOR] = state string "UF UR UB UL DF DR DB DL FR FL BR BL URF UBR ULB UFL DFR DLF DBL DRB"

print [COLOR="#FF0000"]moves[/COLOR] and [COLOR="#FF0000"]state[/COLOR]
for each [COLOR="#FF0000"]move[/COLOR] in [COLOR="#FF0000"]moves[/COLOR]:
  replace "'" with "3" in [COLOR="#FF0000"]move[/COLOR]
  append "1" to [COLOR="#FF0000"]move[/COLOR] (just in case there's no angle given, if there is then this will get ignored)
  [COLOR="#FF0000"]side[/COLOR], [COLOR="#FF0000"]angle[/COLOR] = first two characters in [COLOR="#FF0000"]move[/COLOR] (i.e. like side=U, angle=2)
  build map like [COLOR="#FF0000"]cycle[/COLOR] = {'F' => 'L', 'R' => 'F', 'L' => 'B', 'B' => 'R'} by looking at the corners in [COLOR="#FF0000"]state[/COLOR]
  do the following [COLOR="#FF0000"]angle[/COLOR] times:
    in [COLOR="#FF0000"]state[/COLOR], replace every letter followed/preceded by [COLOR="#FF0000"]side[/COLOR] with what [COLOR="#FF0000"]cycle[/COLOR] maps to
}
print [COLOR="#FF0000"]state[/COLOR]

My code relies heavily on regular expressions and how Perl uses them. Everybody should be familiar at least with regular expressions :p

Thanks, that helps a lot!

Readable code is for wimps. Make it even shorter please! :)

It's for understanding. :)
 
Last edited:
Back
Top