type vec = Vec of int * int * int

type dice_state = Dice of vec * vec

type command = North | East | South | West | Right | Left

let initial_dice_state = Dice ((Vec (0, 0, 1)), (Vec (1, 0, 0)))

let outer_prod (Vec (x1, y1, z1)) (Vec (x2, y2, z2)) =
  Vec ((y1 * z2 - z1 * y2), (z1 * x2 - x1 * z2), (x1 * y2 - y1 * x2))

let roll ?(rev=false) (Vec (x, y, z)) =
  let f = if rev then -1 else 1 in
  Vec (x, f * -z, f * y)

let pitch ?(rev=false) (Vec (x, y, z)) =
  let f = if rev then -1 else 1 in
  Vec (f * z, y, f * -x)

let yaw ?(rev=false) (Vec (x, y, z)) =
  let f = if rev then -1 else 1 in
  Vec (f * -y, f * x, z)

let top (Dice ((Vec (_, _, z1) as v1), (Vec (_, _, z2) as v2))) =
  let Vec (_, _, z3) = outer_prod v1 v2 in
  let z, n = List.find (fun p -> (fst p) <> 0) [(z1, 1); (z2, 2); (z3, 3)] in
  if z > 0 then n else 7 - n

let next_state (Dice (v1, v2)) command =
  let f = match command with
    | North -> pitch ~rev:true
    | East -> roll ~rev:true
    | Right -> yaw ~rev:true
    | South -> pitch ~rev:false
    | West -> roll ~rev:false
    | Left -> yaw ~rev:false in
  Dice (f v1, f v2)

let parse_command = function
  | "North" -> North
  | "East" -> East
  | "Right" -> Right
  | "South" -> South
  | "West" -> West
  | "Left" -> Left
  | _ -> failwith "Something wrong"

let read_lines n =
  let rec read_lines n acc =
    if n = 0 then List.rev acc
    else read_lines (pred n) ((read_line ()) :: acc) in
  read_lines n []

let rec solve () =
  let n = int_of_string @@ read_line () in
  if n = 0 then ()
  else
    let commands = List.map parse_command (read_lines n) in
    let _, sum = List.fold_left
                   (fun (dice, acc) command ->
                    let dice = next_state dice command in
                    (dice, acc + (top dice)))
                   (initial_dice_state, top initial_dice_state)
                   commands in
    print_endline @@ string_of_int sum;
    solve ()

let () = solve ()