use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::collections::hash_set::Iter;
use std::rc::Rc;
use std::ops::DivAssign;
use std::ops::MulAssign;
use std::ops::SubAssign;
use std::collections::BinaryHeap;
use std::str::FromStr;
use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::{HashMap, BTreeSet};
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer.trim().to_owned()
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split_whitespace().map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_map {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: String) => {
        let mut $ident = read_value::<String>();
    };
    ($ident: ident: String) => {
        let $ident = read_value::<String>();
    };
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}
#[derive(Eq, PartialEq)]
struct Rev<T: Ord>(T);
impl <T: std::cmp::Ord> PartialOrd for Rev<T> {
    fn partial_cmp(&self, rhs: &Rev<T>) -> std::option::Option<std::cmp::Ordering> { 
        rhs.0.partial_cmp(&self.0)
    }
}
impl <T: Ord> Ord for Rev<T> {
    fn cmp(&self, rhs: &Self) -> std::cmp::Ordering { 
        rhs.0.cmp(&self.0)
    }
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Ord, PartialOrd)]
struct Coordinate {
    x: i32, y: i32
}

impl Coordinate {
    fn move_to(&self, dir: Dir) -> Option<Coordinate> {
        if (dir.to_int() as i32 + self.x + self.y) & 1 == 0 {
            match dir {
                Dir::Dir0 => Some(Coordinate{x: self.x, y: self.y + 1}),
                Dir::Dir60 | Dir::Dir120 => Some(Coordinate{x: self.x + 1, y: self.y}),
                Dir::Dir180 => Some(Coordinate{x: self.x, y: self.y - 1}),
                Dir::Dir240 | Dir::Dir300 => Some(Coordinate{x: self.x - 1, y: self.y}),
            }
        }else {
            None
        }
    }
}
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
enum Dir {
    Dir0, Dir60, Dir120, Dir180, Dir240, Dir300
}
impl Dir {
    fn from_int(value: usize) -> Dir {
        vec![Dir::Dir0, Dir::Dir60, Dir::Dir120, Dir::Dir180, Dir::Dir240, Dir::Dir300][value % 6]
    }
    fn to_int(&self) -> usize {
        match *self {
            Dir::Dir0 => 0,
            Dir::Dir60 => 1,
            Dir::Dir120 => 2,
            Dir::Dir180 => 3,
            Dir::Dir240 => 4,
            Dir::Dir300 => 5
        }
    }
    fn flip(&self) -> Dir {
        Dir::from_int(self.to_int() + 3)
    }
    fn next(&self) -> Vec<Dir> {
        match *self {
            Dir::Dir0 | Dir::Dir120 | Dir::Dir240 => vec![Dir::Dir0, Dir::Dir120, Dir::Dir240],
            Dir::Dir60 | Dir::Dir180 | Dir::Dir300 => vec![Dir::Dir60, Dir::Dir180, Dir::Dir300],
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
struct Face {
    num: usize, dir: Dir
}
impl Face {
    fn roll(&self, dir: Dir) -> Option<Face> {
        if (self.dir.to_int() + dir.to_int()) & 1 == 0 {
            let new_num = Face::neighbor_face(self.num)[(6 + dir.to_int() - self.dir.to_int()) % 6 >> 1];
            Some(Face{num: new_num, dir: Face::detect_dir(new_num, self.num, dir.flip()).unwrap()})
        }else {
            None
        }
    }
    fn detect_dir(num: usize, other_num: usize, other_dir: Dir) -> Option<Dir> {
        if let Some(dir) = Face::neighbor_face(num).iter().position(|&c| c == other_num) {
            Some(Dir::from_int(6 - (dir << 1) + other_dir.to_int()))
        }else {
            None
        }
    }
    fn neighbor_face(num: usize) -> Vec<usize> {
        match num {
            0 => vec![5, 1, 4],
            1 => vec![6, 2, 0],
            2 => vec![7, 3, 1],
            3 => vec![8, 4, 2],
            4 => vec![9, 0, 3],
            5 => vec![0, 10, 11],
            6 => vec![1, 11, 12],
            7 => vec![2, 12, 13],
            8 => vec![3, 13, 14],
            9 => vec![4, 14, 10],
            10 => vec![15, 5, 9],
            11 => vec![16, 6, 5],
            12 => vec![17, 7, 6],
            13 => vec![18, 8, 7],
            14 => vec![19, 9, 8],
            15 => vec![10, 19, 16],
            16 => vec![11, 15, 17],
            17 => vec![12, 16, 18],
            18 => vec![13, 17, 19],
            19 => vec![14, 18, 15],
            _ => unreachable!()
        }
    }
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
struct Rover {
    position: Coordinate, bottom: Face
}

impl Rover {
    fn new() -> Rover {
        Rover{position: Coordinate{x: 0, y: 0}, bottom: Face{num: 0, dir: Face::detect_dir(0, 5, Dir::Dir0).unwrap()}}
    }
    fn next(&self) -> Vec<Rover> {
        self.bottom.dir.next().into_iter().map(|dir| Rover{position: self.position.move_to(dir).unwrap(), bottom: self.bottom.roll(dir).unwrap()}).collect::<Vec<_>>()
    }
    fn expect(position: Coordinate, face: usize) -> Vec<Rover> {
        if (position.x + position.y) & 1 == 0 {
            Dir::Dir0.next().into_iter().map(|dir| Rover{position: position, bottom: Face{num: face, dir: dir}}).collect::<Vec<_>>()
        }else {
            Dir::Dir60.next().into_iter().map(|dir| Rover{position: position, bottom: Face{num: face, dir: dir}}).collect::<Vec<_>>()
        }
    }
}

fn main() {
    let mut memo = BTreeMap::<Rover, usize>::new();
    let mut queue = VecDeque::new();
    memo.insert(Rover::new(), 0);
    queue.push_back(Rover::new());
    for count in 1 .. 101 {
        for _ in 0 .. queue.len() {
            let current = queue.pop_front().unwrap();
            //println!("current: {:?}", current);
            for next in current.next() {
                //println!("next: {:?}, count: {}", next, count);
                match memo.entry(next) {
                    std::collections::btree_map::Entry::Vacant(e) => {
                        e.insert(count);
                        queue.push_back(next);
                    },
                    _ => ()
                }
            }
        }
    }
    loop {
        read!(x: i32, y: i32, face: usize);
        if x == 0 && y == 0 && face == 0 {break;}
        println!("{}", Rover::expect(Coordinate{x: x, y: y}, face).into_iter().flat_map(|r| memo.get(&r)).min().unwrap())
    }
}



Measured memory_bytes: 60208