Rolling the Dice

CJam, 43 40 37 34 bytes

Thanks to Dennis for helping me save 6 bytes.

lW%3/$1f=q{i8%"ÉĔɠƂ!"=i\m!=}/c

Test it here.

Explanation

lW%    e# Read the first line and reverse it.
S/     e# Split it around spaces.
$      e# Sort it. This puts the faces in order [B E N S T W].
1f=    e# Select the second character from each face, which is the number.
q      e# Read the remainder of the input (the instructions).
{      e# For each instruction...
  i8%  e#   Convert the character (NWSE) to an integer and take modulo 8.
  "ÉĔɠƂ!"=i
       e#   Use that to (cyclically) index this string and convert *that* character
       e#   to an integer.
  \    e#   Swap with the list of faces.
  m!   e#   Generate all permutations of the faces.
  =    e#   Select the permutation corresponding to the above integer.
}/     e# At the end of the loop, the bottom face will be the first character.
c      e# Convert the string to a character, which discards everything but the bottom face.

As for how the mapping of instruction characters to permutations works, here is a handy table:

   i   8%  5%  ""=   i   [0 1 2 3 4 5]m!=

N  78   6   1   Ĕ   276  [2 1 4 0 3 5]
W  87   7   2   ɠ   608  [5 0 2 3 1 4]
S  83   3   3   Ƃ   386  [3 1 0 4 2 5]
E  69   5   0   É   201  [1 4 2 3 5 0]

I've included the 5% column because that is what the cyclic indexing into the string does implicitly. For the four permutations we can see that each of them leaves two (opposite) sides untouched and cyclically permutes the other four.


Perl, 166 158 154 144 139 135 134 132 116 bytes

includes +1 for -p

s/(\d)(.)/$h{$2}=$1/eg;$N='NTSB',$S='STNB',$E='ETWB',$W='WTEB';map{@h{@l}=@h{(@l=$$_=~/./g)[1..3,0]}}/\w/g;$_=$h{B}

With comments:

                                    # example input: "NS, 1S 2B 3E 4W 5T 6N"
s/(\d)(.)/$h{$2}=$1/eg;             # construct %h ( S=>1, B=>2, E=>3, W=>4, B=>2, N=>6 )

                                    # = Transformations =
$N='NTSB',                          # N becomes T, T becomes S, S becomes B, B becomes N
$S='STNB',
$E='ETWB',
$W='WTEB';

map {                               # iterate the moves "NS"
    @h{ @l } =                      # LHS: bulk-assign new values; @l defined in RHS
      @h{                           # RHS: init @l, transform
          (@l=$$_=~/./g)            # get transform, put ('N','T','S','B') in @l for LHS
          [1..3,0]                  # construct a rotated slice for RHS
    }    
} /\w/g;                            # match the movements in list context

$_=$h{B}                            # assign the bottom face to output.


Input file:

, 1S 2B 3E 4W 5T 6N
N, 1S 2B 3E 4W 5T 6N
NS, 1S 2B 3E 4W 5T 6N
NWS, 1S 2B 3E 4W 5T 6N
NWSNWS, 1S 2B 3E 4W 5T 6N
NWSS, 1S 2B 3E 4W 5T 6N
NNNNNN, 1S 2B 3E 4W 5T 6N
SNWEEWS, 1N 2T 3E 4W 5B 6S
SNEEWS, 1N 2T 3W 4S 5B 6E

Run with

perl -p dice.pl < input.txt

Output: 262223564


  • update 158 Using $N, $S, $E, $W global variables instead of %t = {N=>, S=>, E=>, $W=>} saves 8 bytes.

  • update 154 Since the requirement is that the program output a number, not printing the newline print "$h{B}\n" saves 4 bytes: print $h{B}.

  • update 144 Save 10 bytes by doing

    ($s)=/^(\w+),/;            s/(\d)(.)/$h{$2}=$1/eg;
    

    instead of

    ($s,@i)=split /,? |\n/;    %h=reverse map{split//}@i;
    
  • update 139 Move the regex for the command to the end to eliminate a variable, saving 6 bytes.

  • update 135 Save 4 bytes on @l[0..3,0] instead of @l[1..3],$l[0].

  • update 134 Save 1 byte by using assignment @l=split//,$$_ as value.

  • update 132 Save 2 bytes by doing /^\w+/ && $& instead of /^(\w+)/ && $1.

  • update 129 Save 3 bytes by using -p instead of -n and assigning $_ for print.

  • update 116 Save 13 bytes by rewriting split//, /^\w+/ && $& into /^\w+/g.


Python 2, 204 bytes

Thought it was time to respond to my own question.

def x(p,m):
    d={p[3*i-2]:i for i in range(1,7)}
    for j in m:n=2if j in'NE'else-2;x='BSTN'if j in'NS'else'BETW';d[x[0]],d[x[1]],d[x[2]],d[x[3]]=d[x[1+n]],d[x[(2+n)%4]],d[x[(3+n)%4]],d[x[0+n]]
    print d['B']

Not very short, but works.

Run as:

x('1B 2T 3N 4S 5W 6E','SNEEWS')
#Output: 4

Edit: Counted bytes wrong. Now longer. :(