use std::cmp;

fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());

    let k: usize = sc.read();

    let mut cur = 1;
    for _ in 1..k {
        cur = get_next(cur);
    }
    println!("{}", cur);
}

fn get_next(cur: i64) -> i64 {
    let mut add = 1;
    for i in 0.. {
        let mut next = cur / add;
        next += 1;
        for _ in 0..i {
            let d = next % 10;
            next *= 10;
            next += cmp::max(d - 1, 0);
        }
        if is_run(next) {
            return next;
        }
        add *= 10;
    }
    unreachable!()
}

fn is_run(v: i64) -> bool {
    let v: Vec<_> = v
        .to_string()
        .chars()
        .map(|c| c as i64 - '0' as i64)
        .collect();
    let n = v.len();
    for i in 1..n {
        if (v[i] - v[i - 1]).abs() > 1 {
            return false;
        }
    }
    true
}

fn count(max: usize) -> usize {
    let max = max
        .to_string()
        .chars()
        .map(|c| c as usize - '0' as usize)
        .collect::<Vec<_>>();
    let n = max.len();
    let mut dp = [[0; 10]; 4];
    for i in 0..n {
        let mut next = [[0; 10]; 4];
        for prev_digit in 0..10 {
            for mask in 0..4 {
                let is_below = mask & 2 == 1;
                let is_started = mask & 1 == 1;
                if is_started {
                    for next_digit in 0..10 {
                        if prev_digit > next_digit && prev_digit - next_digit > 1 {
                            continue;
                        }
                        if next_digit > prev_digit && next_digit - prev_digit > 1 {
                            continue;
                        }
                        if !is_below && max[i] < next_digit {
                            continue;
                        }
                        let next_below = if is_below || max[i] > next_digit {
                            2
                        } else {
                            0
                        };
                        next[next_below + 1][next_digit] += dp[mask][prev_digit];
                    }
                }
            }
        }
        for first_digit in 1..10 {
            if i == 0 && first_digit > max[i] {
                continue;
            }
            let is_below = i > 0 || first_digit < max[i];
            let mask = if is_below { 3 } else { 1 };
            next[mask][first_digit] += 1;
        }
        dp = next;
    }

    let mut sum = 0;
    for i in 0..10 {
        for mask in 0..4 {
            sum += dp[mask][i];
        }
    }
    sum
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> IO<R, W> {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: ToString>(&mut self, s: S) {
        use std::io::Write;
        self.1.write(s.to_string().as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


Measured memory_bytes: 4352