package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"sort"
	"strconv"
)

const (
	MOD = int(1e9) + 7
)

// IO struct
// >>>>>>> functions for io
type IO struct {
	scanner *bufio.Scanner
	writer  *bufio.Writer
}

func newIO() *IO {
	return &IO{
		scanner: bufio.NewScanner(os.Stdin),
		writer:  bufio.NewWriter(os.Stdout),
	}
}

func (io *IO) nextLine() string {
	io.scanner.Scan()
	return io.scanner.Text()
}

func (io *IO) nextInt() int {
	i, e := strconv.Atoi(io.nextLine())
	if e != nil {
		panic(e)
	}
	return i
}

func (io *IO) nextInt64() int64 {
	a, _ := strconv.ParseInt(io.nextLine(), 10, 64)
	return a
}

func (io *IO) nextfloat64() float64 {
	a, _ := strconv.ParseFloat(io.nextLine(), 64)
	return a
}

func (io *IO) scanNums(len int) (nums []int) {
	var num int
	for i := 0; i < len; i++ {
		num = io.nextInt()
		nums = append(nums, num)
	}
	return
}

func (io *IO) printLn(a ...interface{}) {
	fmt.Fprintln(io.writer, a...)
}

// <<<<<<< functions for io

// >>>>>>> functions for basic calculation
func min(nums ...int) int {
	if len(nums) == 0 {
		panic("funciton min() requires at least one argument.")
	}
	res := nums[0]
	for i := 0; i < len(nums); i++ {
		res = int(math.Min(float64(res), float64(nums[i])))
	}
	return res
}

func max(nums ...int) int {
	if len(nums) == 0 {
		panic("funciton max() requires at least one argument.")
	}
	res := nums[0]
	for i := 0; i < len(nums); i++ {
		res = int(math.Max(float64(res), float64(nums[i])))
	}
	return res
}

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

// calc a^b
func powInt(a, b int) int {
	result := 1
	for i := 1; i <= b; i++ {
		result *= a
	}
	return result
}

func sumSlice(nums []int) int {
	sum := 0
	for _, n := range nums {
		sum += n
	}
	return sum
}

func sumSliceFloat64(nums []float64) float64 {
	sum := float64(0)
	for _, n := range nums {
		sum += n
	}
	return sum
}

// <<<<<<< functions for basic calculation

// >>>>>>> functions for typical algorithm

func gcd(a, b int) int {
	for {
		a, b = b, a%b
		if b == 0 {
			break
		}
	}
	return a
}

func binarySearch(target int, list []int) int {
	left := 0
	right := len(list) - 1
	mid := (left + right) / 2

	for {
		if list[mid] < target {
			left = mid + 1
		} else {
			right = mid
		}
		mid = (left + right) / 2
		if left >= right {
			break
		}
	}
	return mid
}

// calculate nPk
func permutation(n, k int) int {

	if k < 0 || n < k {
		panic("invalid k is given")
	}

	if k == 0 {
		return 1
	}

	v := 1
	for i := 0; i < k; i++ {
		v *= (n - i)
		v %= MOD
	}

	return v
}

// calculate n!
func factorial(n int) int {
	if n == 0 {
		return 1
	}
	return permutation(n, n-1)
}

// calculate nCk
func combination(n, k int) int {
	if n/2 < k {
		k = n - k
	}
	factor := getInverseElement(factorial(k))
	return permutation(n, k) * factor % MOD
}

// <<<<<<< functions for typical algorithm

// >>>>>>> functions for 2D array
type array2D [][]int

func (a array2D) Len() int {
	return len(a)
}

func (a array2D) Less(i, j int) bool {
	// return a[i][0] < a[j][0] // sort by 1st arg
	return a[i][1] < a[j][1] // sort by 2nd arg
}

func (a array2D) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}

func (a array2D) sort() {
	sort.Sort(a)
}

// <<<<<<< functions for 2D array

// >>>>>>> functions for prime numbers
type sieveEratos struct {
	max   int
	sieve []int
}

func newSieveEratos(n int) *sieveEratos {
	s := sieveEratos{
		max:   n,
		sieve: make([]int, n+1),
	}
	s.createSieve()
	return &s
}

func (s *sieveEratos) createSieve() {
	s.sieve[1] = 1
	for i := 2; i <= s.max; i++ {
		if s.sieve[i] > 0 {
			continue
		}
		s.sieve[i] = i
		for j := i * 2; j <= s.max; j += i {
			s.sieve[j] = i
		}
	}
}

func (s *sieveEratos) isPrime(n int) bool {
	if n < 2 {
		return false
	}
	return s.sieve[n] == n
}

func (s *sieveEratos) factorize(n int) map[int]int {
	factors := map[int]int{}
	for {
		f := s.sieve[n]
		factors[f]++
		if f == n {
			break
		}
		n = n / f
	}
	return factors
}

// <<<<<<< functions for prime numbers

// >>>>>>> functions for inverse element

// calc a^n MOD
func modPow(a, n int) int {
	res := 1
	for {
		if n&1 == 1 {
			res = res * a % MOD
		}
		n = n >> 1
		a = a * a % MOD
		if n == 0 {
			break
		}
	}
	return res
}

// calc a^-1 MOD
func getInverseElement(a int) int {
	return modPow(a, MOD-2)
}

// <<<<<<< functions for inverse element

// >>>>>>> functions for Unin Find

type UnionFind struct {
	data []int
}

func newUnionFind(n int) *UnionFind {
	d := make([]int, n) // if > 0 represents root, else represents size of tree
	for i := range d {
		d[i] = -1 // initialize all nodes as root of single node tree
	}
	union := UnionFind{
		data: d,
	}
	return &union
}

func (u *UnionFind) findRoot(x int) int {
	if u.data[x] < 0 {
		return x
	}
	u.data[x] = u.findRoot(u.data[x])
	return u.data[x]
}

func (u *UnionFind) belongingToSameTree(a, b int) bool {
	return u.findRoot(a) == u.findRoot(b)
}

func (u *UnionFind) unite(a, b int) {
	rootA := u.findRoot(a)
	rootB := u.findRoot(b)

	if rootA == rootB {
		return
	}

	if u.data[rootA] > u.data[rootB] { // if tree from rootA is smaller than the other
		rootA, rootB = rootB, rootA // always make tree from rootA larger than the other
	}

	u.data[rootA] += u.data[rootB]
	u.data[rootB] = rootA
}

// <<<<<<< functions for Union Find

var io = newIO()

func main() {
	io.scanner.Split(bufio.ScanWords)      // switch to separating by space
	io.scanner.Buffer([]byte{}, 100000007) // switch to read large size input
	defer io.writer.Flush()

	solve()
}

func solve() {
	K := io.nextInt()

	lns := make([]int, max(K, 9)+3)

	for i := range make([]int, 9) {
		lns[i] = i + 1
	}

	i := 0
	tail := 8
	for tail < K {
		n := lns[i]
		head := n % 10

		for b := -1; b < 2; b++ {
			bias := head + b
			if bias < 0 || 9 < bias {
				continue
			}
			tail++
			lns[tail] = n*10 + bias
		}
		i++
	}
	io.printLn(lns[K-1])
}


package main

import (
	"bufio"
	"container/list"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func main() {
	scanInit()

	k := nextInt()

	for i := 1; i < 10; i++ {
		enq(i)
	}

	lidx := 0
	for queue.Len() > 0 {
		ei := deq()
		lidx++
		if lidx == k {
			fmt.Println("DBG HIT Kth") //! DBG
			fmt.Println(ei)
			return
		}

		eis := fmt.Sprintf("%d", ei)
		base := ei*10 + ei%10
		if eis[len(eis)-1] != '0' {
			enq(base - 1)
		}
		enq(base)
		if eis[len(eis)-1] != '9' {
			enq(base + 1)
		}
	}
}

// 正数の桁数を返す
func keta(n int) int {
	keta := 0
	if n == 0 {
		return 1
	}
	for n > 0 {
		keta++
		n /= 10
	}
	return keta
}

var queue = list.New()

func enq(a int) {
	queue.PushBack(a)
}
func deq() int {
	e := queue.Front()
	queue.Remove(e)
	return e.Value.(int) // 明示的キャストが必要
}

// DBGprintqueue print the queue
//! DBG
func DBGprintqueue() {
	fmt.Printf("DBGqueue: [")
	now := queue.Front()
	for now != nil {
		fmt.Printf("%d ", now.Value.(int))
		now = now.Next()
	}
	fmt.Printf(" ]")
}

// ---- readfunc
func scanInit() {
	const cap = 200 * 1024 // default=64*1024
	var buf = make([]byte, cap)
	sc.Buffer(buf, cap)
	sc.Split(bufio.ScanWords)
	return
}
func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}
func nextStr() string {
	sc.Scan()
	return sc.Text()
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func main() {
	scanInit()

	k := nextInt()
	lcnt := 0
	ans := 0
	for i := 1; i < 1000000; i++ {
		fl := true
		si := fmt.Sprintf("%d", i)
		for j := 0; j < len(si)-1; j++ {
			diff := abs(int(si[j]) - int(si[j+1]))
			if diff > 1 {
				fl = false
				break
			}
		}
		if fl == true {
			lcnt++
			if lcnt == k {
				ans = i
				break
			}
		}
	}

	fmt.Println(ans)
}
func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

// ---- readfunc
func scanInit() {
	const cap = 200 * 1024 // default=64*1024
	var buf = make([]byte, cap)
	sc.Buffer(buf, cap)
	sc.Split(bufio.ScanWords)
	return
}
func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}
func nextStr() string {
	sc.Scan()
	return sc.Text()
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func nextInt() int {
	var i int
	if sc.Scan() {
		if num, err := strconv.Atoi(sc.Text()); err == nil {
			i = num
		}
	}
	return i
}

func main() {
	sc.Split(bufio.ScanWords)
	k := nextInt()
	var count int
	str := strconv.Itoa(k)
	maxDigit := len(str)
	var backLunluns []int

	for i := 1; i < 10; i++ {
		backLunluns = append(backLunluns, i)
		count++
		if count == k {
			fmt.Println(i)
			return
		}
	}
	for d := 2; d <= maxDigit; d++ {
		var lunluns []int
		for i := 0; i < len(backLunluns); i++ {
			str := strconv.Itoa(backLunluns[i])
			last := str[len(str)-1]
			num, _ := strconv.Atoi(string(last))
			v := backLunluns[i]*10 + num
			if v%10 == 0 {
				lunluns = append(lunluns, v)
				count++
				if count == k {
					fmt.Println(v)
					return
				}
				lunluns = append(lunluns, v+1)
				count++
				if count == k {
					fmt.Println(v + 1)
					return
				}
			} else {
				lunluns = append(lunluns, v-1)
				count++
				if count == k {
					fmt.Println(v - 1)
					return
				}
				lunluns = append(lunluns, v)
				count++
				if count == k {
					fmt.Println(v)
					return
				}
				lunluns = append(lunluns, v+1)
				count++
				if count == k {
					fmt.Println(v + 1)
					return
				}
			}
		}
		backLunluns = lunluns
	}
}


K = gets.to_i
DP_L = Array.new(11){ Array.new(11, 0) }
DP_S = Array.new(11){ Array.new(10, 0) }

(0 .. 9).each{|i| DP_L[1][i] = 1; DP_S[1][i] = i }

(2 .. 10).each do |n|
  (0 .. 9).each do |i|
    DP_L[n][i] = DP_L[n - 1][i - 1] + DP_L[n - 1][i] + DP_L[n - 1][i + 1]
  end
  DP_S[n][0] = DP_S[n - 1][9]
  (1 .. 9).each do |i|
    DP_S[n][i] = DP_S[n][i - 1] + DP_L[n][i]
  end
  break if DP_S[n][9] >= K
end

def lunlun(n,i,k,a)
  return a if n == 1

  if DP_L[n - 1][i - 1] >= k
    lunlun(n - 1, i - 1, k, a * 10 + i - 1)
  elsif DP_L[n - 1][i - 1] +  DP_L[n - 1][i] >= k
    lunlun(n - 1, i, k - DP_L[n - 1][i - 1], a * 10 + i)
  elsif DP_L[n - 1][i - 1] + DP_L[n - 1][i] + DP_L[n - 1][i + 1] >= k
    lunlun(n - 1, i + 1, k - DP_L[n - 1][i - 1] - DP_L[n - 1][i], a * 10 + i + 1)
  else
    raise "illegal state"
  end
end

def answer(k)
  n = DP_S.index{|sum| sum[9] >= K }
  i = DP_S[n].index{|sum| sum >= K }
  lunlun(n, i, k - DP_S[n][i - 1], i)
end

puts answer(K)


K = gets.chomp.to_i

if K < 10
  puts K
  exit
end

def search(x, i, n, res = [])
  if x <= 1
    cs = [res[-1]-1, res[-1], res[-1]+1].select{|v| 0 <= v && v <= 9}
    res << cs[n-1]
    puts res.join
    exit
  end
  res << i
  nn = n
  cs = [i-1, i, i+1].select{|v| 0 <= v && v <= 9}
  cs.each do |j|
    if nn - PAT[x-1][j] <= 0
      return search(x-1, j, nn, res)
    end
    nn -= PAT[x-1][j]
  end
end

PAT = {}
PAT[1] = Hash.new(0)
0.upto(9) do |i|
  PAT[1][i] = [i-1, i, i+1].select{|v| 0 <= v && v <= 9}.size
end
k = 9

PAT[2] = Hash.new(0)
0.upto(9) do |i|
  PAT[2][i] = [i-1, i, i+1].select{|v| 0 <= v && v <= 9}.size
  if i > 0
    search(2, i, K-k) if k + PAT[2][i] >= K
    k += PAT[2][i]
  end
end

# x桁
3.upto(10) do |x|
  PAT[x] = Hash.new(0)
  0.upto(9) do |i|
    PAT[x][i] = PAT[x-1][i-1] + PAT[x-1][i] + PAT[x-1][i+1]
    if i > 0
      search(x, i, K-k) if k + PAT[x][i] >= K
      k += PAT[x][i]
    end
  end
end


k = gets.to_i

table = [
[1,2,5,13,35,96,267,750,2123,6046],
[1,3,8,22,61,171,483,1373,3923,11256],
[1,3,9,26,75,216,623,1800,5210,15104],
[1,3,9,27,80,236,694,2037,5971,17486],
[1,3,9,27,81,242,720,2134,6305,18581],
[1,3,9,27,81,242,720,2134,6305,18581],
[1,3,9,27,80,236,694,2037,5971,17486],
[1,3,9,26,75,216,623,1800,5210,15104],
[1,3,8,22,61,171,483,1373,3923,11256],
[1,2,5,13,35,96,267,750,2123,6046],
]

counts =
[9,35,110,327,956,2782,8089,23527,68468,199368]

max = counts.index{ |x| x >= k}
if max > 0 then
	k -= counts[max - 1]
end

result = []

max.downto(0){ |keta|
	if keta == max then
		(1..9).each{ |i|
			if k > table[i][keta] then
				k -= table[i][keta]
			else
				result << i
				break
			end
		}
	else
		st = [result[-1] - 1, 0].max
		ed = [result[-1] + 1, 9].min

		(st..ed).each{ |i|
			if k > table[i][keta] then
				k -= table[i][keta]
			else
				result << i
				break
			end
		}
	end
}

puts result.join("")


def join(i1,i2)
	return (i1.to_s + i2.to_s).to_i
end

K = gets.chomp.to_i
queue = [1,2,3,4,5,6,7,8,9]
ix = 9

while ix < K
	f = queue.first

	if f % 10 > 0
		ix += 1
		queue.push(join(f,f%10-1))
	end
	if ix != K
		ix += 1
		queue.push(join(f,f))
	end

	if f % 10 < 9 && ix != K
		ix += 1
		queue.push(join(f,f%10+1))
	end
	queue.shift
end
if K < 10
	puts queue[K-1]
else
	puts queue.last
end


def lunlun?(string)
  c = string.chars
  ok = true
  c.each_index do |i|
    next if i == c.length - 1
    if (c[i].to_i - c[i + 1].to_i).abs > 1
      ok = false
    end
  end

  ok
end

k = gets.to_i

now = 0
while k > 0 do
  now += 1
  if lunlun?(now.to_s)
    k -= 1
  end
end

puts now


k=gets.to_i
z=*1..9
a=0
k.times{
  a=z.shift
  b=a%10
  z << a*10 + (a-1) if a != 0
  z << a*10 + a
  z << a*10 + (a+1) if a != 9
  }
p a


#![allow(unused_imports)]

use std::cmp::{max, min};
use std::ops::Range;

const MAXDIGIT: usize = 15;

fn neighbor(i: usize) -> Range<usize> {
    let start = i.saturating_sub(1);
    let end = min(i + 2, 10);
    start..end
}

fn make_dp(mut n: usize) -> (Vec<Vec<usize>>, usize, usize, usize) {
    let mut dp = vec![vec![0; MAXDIGIT]; 10];

    for d in 1..MAXDIGIT {
        for i in 0..10 {
            if d == 1 {
                dp[i][d] = 1;
            } else {
                for l in neighbor(i) {
                    dp[i][d] += dp[l][d - 1];
                }
            }

            if i != 0 {
                if n <= dp[i][d] {
                    return (dp, n, i, d);
                }

                n -= dp[i][d];
            }
        }
    }

    unreachable!("too large query");
}

fn get_nth(dp: &Vec<Vec<usize>>, mut n: usize, i: usize, d: usize) -> String {

    if d == 1 {
        assert_eq!(n, 1);
        return i.to_string();
    }

    assert!(n <= dp[i][d]);

    for l in neighbor(i) {
        if dp[l][d - 1] >= n {
            return format!("{}{}", i, get_nth(dp, n, l, d - 1));
        }
        n -= dp[l][d - 1];
    }

    unreachable!("bug");
}

fn main() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    let n = s.trim().parse::<usize>().unwrap();

    let (dp, n, i, d) = make_dp(n);

    println!("{}", get_nth(&dp, n, i, d));
}


use std::io::*;
use std::str::FromStr;
use std::collections::VecDeque;

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn solve(n: u64) -> u64 {
    if n < 10 {
        return n;
    }

    let mut cnt = 0;
    let mut queue: VecDeque<u64> = VecDeque::new();
    for i in 1..10 {
        queue.push_back(i as u64);
        cnt += 1;
    }

    let mut ans = 0;
    loop {
        let num = queue.pop_front().unwrap();
        let n2 = num % 10;

        if n2 != 0 {
            ans = num * 10 + n2 - 1;
            queue.push_back(ans);
            cnt += 1;
        }
        if n == cnt {
            break
        }

        ans = num * 10 + n2;
        queue.push_back(ans);
        cnt += 1;
        if n == cnt {
            break
        }

        if n2 != 9 {
            ans = num * 10 + n2 + 1;
            queue.push_back(ans);
            cnt += 1;
        }
        if n == cnt {
            break
        }
    }

    return ans;
}

fn main() {
    let n: u64 = read();

    println!("{}", solve(n));
}


macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

use std::collections::vec_deque::VecDeque;

fn main() {
    input! {
        k: usize
    }
    let mut q: VecDeque<i64> = VecDeque::new();
    for i in 1..10 {
        q.push_back(i);
    }
    if k <= 9 {
        println!("{}", q[k-1]);
        return;
    }
    let mut cnt = q.len();
    loop {
        let x = *q.front().unwrap();
        q.pop_front();
        for i in &[-1,0,1] {
            let d = x % 10 + i;
            if d < 0 || 9 < d { continue; }
            let nx = x * 10 + d;
            q.push_back(nx);
            cnt += 1;
            if cnt == k {
                println!("{}", q.back().unwrap());
                return;
            }
        }
    }
}


// -*- coding:utf-8-unix -*-

#[macro_use]
extern crate lazy_static;

// use proconio::derive_readable;
use proconio::fastout;
use proconio::input;
// use std::convert::TryInto;
use libm::*;
use std::cmp::*;
use std::collections::BinaryHeap;
use std::io::*;
use std::str::FromStr;
use superslice::*;

pub fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

//abc161-D
// #[fastout]
fn main() {
    input![n: usize];

    let mut is_rnrn = vec![false; 1000000];

    let mut count = 0;
    is_rnrn[0] = true;
    for i in 1..10 {
        count += 1;
        eprintln!("{}'s rnrn: {}", count, i);
        if n == count {
            println!("{}", i);
            return;
        }
        is_rnrn[i] = true;
    }

    for i in 10..(1000000) {
        let d = log10(i as f64) as u32;
        let a = 10i64.pow(d);
        let max_d = i as i64 / a as i64;
        let no2_d = i as i64 / (10i64.pow(d - 1)) % 10 as i64;
        let rest_digits = i - max_d * a;
        // eprintln!("{}, {}, {}, {}", i, max_d, no2_d, rest_digits);
        if !is_rnrn[rest_digits as usize] {
            is_rnrn[i as usize] = false;
        } else if fabs((max_d - no2_d) as f64) as usize <= 1 {
            count += 1;
            eprintln!("{}'s rnrn: {}", count, i);
            if n == count {
                println!("{}", i);
                break;
            }
            is_rnrn[i as usize] = true;
        } else {
            is_rnrn[i as usize] = false;
        }
    }
}

fn go(mid: usize, d: usize, use_num: usize, num753_cand: &mut Vec<usize>, n: usize) {}

// use lazy_static::lazy_static;
// use std::sync::Mutex;

// lazy_static! {
//     static ref VALUES: Mutex<Vec<i32>> = Mutex::default();
// }

// let mut values = VALUES.lock().unwrap();
// values.extend_from_slice(&[1, 2, 3, 4]);
// assert_eq!(&*values, &[1, 2, 3, 4]);


// -*- coding:utf-8-unix -*-

#[macro_use]
extern crate lazy_static;

// use proconio::derive_readable;
use proconio::fastout;
use proconio::input;
// use std::convert::TryInto;
use libm::*;
use std::cmp::*;
use std::collections::BinaryHeap;
use std::io::*;
use std::str::FromStr;
use superslice::*;

pub fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

//abc161-D
// #[fastout]
fn main() {
    input![n: usize];

    let mut is_rnrn = vec![false; 1000000];

    let mut count = 0;
    is_rnrn[0] = true;
    for i in 1..10 {
        count += 1;
        eprintln!("{}'s rnrn: {}", count, i);
        if n == count {
            println!("{}", i);
            break;
        }
        is_rnrn[i] = true;
    }

    for i in 10..(1000000) {
        let d = log10(i as f64) as u32;
        let a = 10i64.pow(d);
        let max_d = i as i64 / a as i64;
        let no2_d = i as i64 / (10i64.pow(d - 1)) % 10 as i64;
        let rest_digits = i - max_d * a;
        // eprintln!("{}, {}, {}, {}", i, max_d, no2_d, rest_digits);
        if !is_rnrn[rest_digits as usize] {
            is_rnrn[i as usize] = false;
        } else if fabs((max_d - no2_d) as f64) as usize <= 1 {
            count += 1;
            eprintln!("{}'s rnrn: {}", count, i);
            if n == count {
                println!("{}", i);
                break;
            }
            is_rnrn[i as usize] = true;
        } else {
            is_rnrn[i as usize] = false;
        }
    }
}

fn go(mid: usize, d: usize, use_num: usize, num753_cand: &mut Vec<usize>, n: usize) {}

// use lazy_static::lazy_static;
// use std::sync::Mutex;

// lazy_static! {
//     static ref VALUES: Mutex<Vec<i32>> = Mutex::default();
// }

// let mut values = VALUES.lock().unwrap();
// values.extend_from_slice(&[1, 2, 3, 4]);
// assert_eq!(&*values, &[1, 2, 3, 4]);


use proconio::input;
use std::collections::VecDeque;

#[fastout]
fn main() {
  input! { K: u32 }
  let mut queue:VecDeque<u32> = vec![1,2,3,4,5,6,7,8,9].into_iter().collect();
  let mut answer = 0;

  for _ in 0..K {
    let val = queue.pop_front().unwrap();
    answer = val;

    let next = val * 10 + val % 10;
    if next % 10 != 0 {
      queue.push_back(next - 1);
    }
    queue.push_back(next);
    if next % 10 != 9 {
      queue.push_back(next + 1);
    }
  }
  println!("{}", answer);
}


// Lunlun Number

func main() {
    let k = Int(readLine()!)!
    var rest = k - 9

    var lunlun: [[Int]] = []

    var digits = 0
    lunlun.append([1,2,3,4,5,6,7,8,9])
    var count = 9

    while count < k {
        var currentLunlun: [Int] = []
        for i in lunlun[digits] {
            let lastNumber = i % 10
            switch lastNumber {
            case 0:
                currentLunlun.append(i * 10 + lastNumber)
                currentLunlun.append(i * 10 + lastNumber + 1)
            case 9:
                currentLunlun.append(i * 10 + lastNumber - 1)
                currentLunlun.append(i * 10 + lastNumber)
            default:
                currentLunlun.append(i * 10 + lastNumber - 1)
                currentLunlun.append(i * 10 + lastNumber)
                currentLunlun.append(i * 10 + lastNumber + 1)
            }
        }

        if rest <= currentLunlun.count {
            print(currentLunlun[rest-1])
            return
        }
        rest -= currentLunlun.count
        lunlun.append(currentLunlun)
        count += currentLunlun.count
        digits += 1
    }
    print(lunlun[0][k-1])
}

main()


import Foundation
let main: () = {
    let K = nextInt()
    var ans = [Int]()
    (0 ... 9).forEach { ans.append($0) }
    var p = 1
    while (p < K) {
        let x = ans[p]
        p += 1
        for a in -1 ... 1 {
            let d = x % 10 + a
            if d !=~ 0 ... 9 { continue }
            ans.append(10 * x + d)
        }
    }
    print(ans[K])
}()

//----------------------------------

let dx = [1, 0, -1, 0] //[1, 0, -1, 0, -1,  1, -1, 1]
let dy = [0, 1, 0, -1] //[0, 1, 0, -1, -1, -1,  1, 1]

@inlinable func gcd(_ a: Int, _ b: Int) -> Int { (b > 0) ? gcd(b, a % b) : a }
@inlinable func lcm(_ a: Int, _ b: Int) -> Int { a / gcd(a, b) * b }

//----------------------------------

infix operator  =~ : ComparisonPrecedence
infix operator !=~ : ComparisonPrecedence
func =~ <T: FixedWidthInteger>(left: T, right: Range<T>) -> Bool { right ~= left }
func !=~ <T: FixedWidthInteger>(left: T, right: Range<T>) -> Bool { !(right ~= left) }
func =~ <T: FixedWidthInteger>(left: T, right: ClosedRange<T>) -> Bool { right ~= left }
func !=~ <T: FixedWidthInteger>(left: T, right: ClosedRange<T>) -> Bool { !(right ~= left) }

func =~ <T: Collection > (left: T.Element, right: T) -> Bool where T.Element : Equatable { right.contains(left) }
func !=~ <T: Collection > (left: T.Element, right: T) -> Bool where T.Element : Equatable { !right.contains(left) }

infix operator /^ : MultiplicationPrecedence
infix operator /^= : AssignmentPrecedence
func /^ <T: FixedWidthInteger>(left: T, right: T) -> T { (left + (right - 1)) / right }
func /^= <T: FixedWidthInteger>(left: inout T, right: T) { left = (left + (right - 1)) / right }

@inlinable func chmax<T: Comparable>(_ m: inout T, _ q: T) { if (m < q) { m = q } }
@inlinable func chmin<T: Comparable>(_ m: inout T, _ q: T) { if (m > q) { m = q } }
@inlinable func chRmax<T: Comparable>(_ m: inout T, _ q: T) -> Bool { if (m < q) { m = q; return true } else { return false } }
@inlinable func chRmin<T: Comparable>(_ m: inout T, _ q: T) -> Bool { if (m > q) { m = q; return true } else { return false } }

prefix operator *
prefix func * <T> (a: [T]) -> (T, T) { (a[0], a[1]) }
prefix func * <T> (a: [T]) -> (T, T, T) { (a[0], a[1], a[2]) }
prefix func * <T> (a: [T]) -> (T, T, T, T) { (a[0], a[1], a[2], a[3]) }
prefix func * <T> (a: [T]) -> (T, T, T, T, T) { (a[0], a[1], a[2], a[3], a[4]) }
prefix func * <T> (a: [T]) -> (T, T, T, T, T, T) { (a[0], a[1], a[2], a[3], a[4], a[5]) }

func printErr(_ str: String, terminator: String = "\n") {
    let s = str + terminator
    FileHandle.standardError.write(s.data(using: .utf8)!)
    FileHandle.standardError.synchronizeFile()
}

@inlinable func next() -> String { readLine()! }
@inlinable func nextInt() -> Int { Int(next())! }
@inlinable func nextDouble() -> Double { Double(next())! }
@inlinable func listOfString() -> [String] { next().split(separator: " ").map(String.init) }
@inlinable func listOfInt() -> [Int] { listOfString().map { Int($0)! } }
@inlinable func listOfInt(_ offset: Int = 0) -> [Int] { listOfString().map { Int($0)! + offset } }
@inlinable func listOfInt(_ offsets: Int ...) -> [Int] { listOfString().enumerated().map { Int($0.element)! + offsets[$0.offset % offsets.count] } }
@inlinable func listOfDouble(_ offset: Double = 0.0) -> [Double] { listOfString().map { Double($0)! + offset } }
@inlinable func listOfDouble(_ offsets: Double ...) -> [Double] { listOfString().enumerated().map { Double($0.element)! + offsets[$0.offset % offsets.count] } }

extension Int {
    init(s: String) { self.init(s)! }
    var isEven: Bool { self.isMultiple(of: 2) }
    var isOdd: Bool { !self.isEven }
    var isTrue: Bool { self != 0 }
    var isFalse: Bool { !self.isTrue }
    var toString: String { String(self) }
    var toChar: Character { Character(UnicodeScalar(UInt8(self))) }
}
func + (left: Int, right: Bool) -> Int { left + (right ? 1 : 0) }
extension Character {
    var asciiCode: Int { Int(self.asciiValue!) }
    var string: String { String(self) }
}
extension String {
    @inlinable subscript (position: Int) -> Character { self[self.index(self.startIndex, offsetBy: position)] }
    @inlinable func repeate(_ times: Int) -> String { String(repeating: self, count: times) }
    //  @inlinable subscript (n: Int) -> String { String(self[self.index(self.startIndex, offsetBy: n)]) }
    //  @inlinable subscript (n: Int) -> Int { Int(self[self.index(self.startIndex, offsetBy: n)].asciiValue!) }
    var toInt: Int { Int(self)! }
}
extension String { // VB like
    @inlinable func _index(_ position: Int) -> String.Index! {
        if !(0 ..< self.count ~= position) { return nil }
        return self.index(self.startIndex, offsetBy: position)
    }
    @inlinable func mid(from index: Int, length: Int) -> String! {
        if let startPosition = self._index(index) {
            if let endPosition = self._index(index + length - 1) {
                return String(self[startPosition...endPosition])
            } else {
                let endPosition = self.index(before: self.endIndex)
                return String(self[startPosition...endPosition])
            }
        }
        return ""
    }
    @inlinable func left(_ length: Int) -> String { String(self.prefix(length)) }
    @inlinable func right(_ length: Int) -> String { String(self.suffix(length)) }
}

extension Dictionary {
    @inlinable mutating func getOrSet(_ key: Key, _ defaultValue: () -> Value) -> Value {
        if let stored = self[key] { return stored }
        else {
            let newValue = defaultValue()
            self[key] = newValue
            return newValue
        }
    }
    @inlinable mutating func getOrElse(_ key: Key, _ defaultValue: () -> Value) -> Value {
        if let stored = self[key] { return stored } else { return defaultValue() }
    }
    @inlinable func containsKey(_ key: Key) -> Bool { self.keys.contains(key) }
}

extension Set {
    static func += (left: inout Set<Element>, right: Element) { left.insert(right) }
    static func -= (left: inout Set<Element>, right: Element) { left.remove(right) }
}

extension Array {
    static func += (left: inout Array<Element>, right: Element) { left.append(right) }
    init(_ size: Int, _ initValue: ((Int) -> Element)) {
        self = [Element]()
        for index in 0 ..< size {
            let value = initValue(index)
            self.append(value)
        }
    }
    init(_ size: Int, _ initValue: (() -> Element)) {
        self = [Element]()
        for _ in 0 ..< size {
            let value = initValue()
            self.append(value)
        }
    }
}
typealias IntArray = Array<Int>
typealias DoubleArray = Array<Double>
typealias BoolArray = Array<Bool>
typealias StringArray = Array<String>

extension Array where Element == Int {
    init(_ size: Int) {
        self = [Element](repeating: 0, count: size)
    }
}
extension Array where Element == Double {
    init(_ size: Int) {
        self = [Element](repeating: 0.0, count: size)
    }
}
extension Array where Element == Bool {
    init(_ size: Int) {
        self = [Element](repeating: false, count: size)
    }
}
extension Array where Element == String {
    init(_ size: Int) {
        self = [Element](repeating: "", count: size)
    }
}

extension Array {
    @inlinable func count(_ predicate: ((Element) -> Bool)) -> Int {
        var cnt = 0; for e in self { if (predicate(e)) { cnt += 1 } }
        return cnt
    }
    @inlinable func groupBy<K>(_ keySelector: (Element) -> K) -> [K : [Element]] {
        var destination = [K : [Element]]()
        for element in self {
            let key = keySelector(element)
            var list = destination.getOrSet(key) { [Element]() }
            list.append(element)
            destination[key] = list
        }
        return destination
    }
    @inlinable func groupByIndexed<K>(_ keySelector: (Element) -> K) -> [K : [Int]] {
        var destination = [K : [Int]]()
        for element in self.enumerated() {
            let key = keySelector(element.element)
            var list = destination.getOrSet(key) { [Int]() }
            list.append(element.offset)
            destination[key] = list
        }
        return destination
    }
}

extension Array {
    func binarySearch(_ element: Element, by compare: (Element, Element) -> Int, fromIndex: Int = 0, toIndex: Int = -1) -> Int {
        var low = fromIndex
        var high = (toIndex == -1) ? self.count - 1 : toIndex - 1
        while (low <= high) {
            let mid = (low + high) >> 1 // safe from overflows
            let midVal = self[mid]
            let cmp = compare(midVal, element)
            if (cmp < 0) { low = mid + 1 }          //-1
            else if (0 < cmp) { high = mid - 1 }    // 1
            else { return mid } // key found        // 0
        }
        return -(low + 1)  // key not found
    }
}
extension Array where Element : Comparable {
    func binarySearch(_ element: Element, fromIndex: Int = 0, toIndex: Int = -1) -> Int {
        var low = fromIndex
        var high = (toIndex == -1) ? self.count - 1 : toIndex - 1
        while (low <= high) {
            let mid = (low + high) >> 1 // safe from overflows
            let midVal = self[mid]
            if (midVal < element) { low = mid + 1 }
            else if (midVal > element) { high = mid - 1 }
            else { return mid } // key found
        }
        return -(low + 1)  // key not found
    }
}

extension Array where Element == Int {
    @inlinable func distinct() -> [Element] {
        var set = Set<Element>(), ary = [Element]()
        for n in self.indices { if !set.contains(self[n]) { ary.append(self[n]); set.insert(self[n]) } }
        return ary
    }
    @inlinable func any(_ predicate: (Element) -> Bool) -> Bool {
        var any = false; for element in self { if predicate(element) { any = true } }
        return any
    }
    @inlinable func all(_ predicate: (Element) -> Bool) -> Bool {
        self.allSatisfy(predicate)
    }
    @inlinable func sum() -> Element { self.reduce(0, +) }
    @inlinable func sum(by predicate: (Element) -> Element) -> Element {
        var sum = 0; for e in self { sum += predicate(e) }
        return sum
    }
    @inlinable func joinToString(_ sepatator: String = " ") -> String { self.map { String($0) }.joined(separator: sepatator) }
}

extension Array where Element == Double {
    @inlinable func sum() -> Element { self.reduce(0.0, +) }
    @inlinable func sum(by predicate: (Element) -> Element) -> Element {
        var sum = 0.0; for e in self { sum += predicate(e) }
        return sum
    }
    @inlinable func joinToString(_ sepatator: String = " ") -> String { self.map { String($0) }.joined(separator: sepatator) }
}
extension Array where Element == String {
    @inlinable func toIntDouble() -> (Int, Double) { (Int(self[0])!, Double(self[1])!) }
    @inlinable func toIntString() -> (Int, String) { (Int(self[0])!, self[1]) }
    @inlinable func toIntIntString() -> (Int, Int, String) { (Int(self[0])!, Int(self[1])!, self[2]) }
}

@inlinable func repeate(_ times1: Int, _ action: () -> Void) {
    for _ in 0 ..< times1 { action() }
}
@inlinable func repeate(_ times1: Int, _ action: (Int) -> Void) {
    for index1 in 0 ..< times1 {
        action(index1)
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ action: (Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            action(index1, index2)
        }
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ times3: Int, _ action: (Int, Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            for index3 in 0 ..< times3 {
                action(index1, index2, index3)
            }
        }
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ times3: Int, _ times4: Int, _ action: (Int, Int, Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            for index3 in 0 ..< times3 {
                for index4 in 0 ..< times4 {
                    action(index1, index2, index3, index4)
                }
            }
        }
    }
}

func measureTimeSeconds(block: (() -> Void)) -> Double {
    let startTime = Date()
    block()
    let duration = -startTime.timeIntervalSinceNow
    return duration
}

extension Array {
    func permutation (_ length: Int) -> [[Element]] {
        if length < 0 || length > self.count {
            return []
        } else if length == 0 {
            return [[]]
        } else {
            var permutations: [[Element]] = []
            let combinations = combination(length)
            for combination in combinations {
                var endArray: [[Element]] = []
                var mutableCombination = combination
                permutations += self.permutationHelper(length, array: &mutableCombination, endArray: &endArray)
            }
            return permutations
        }
    }
    private func permutationHelper(_ n: Int, array: inout [Element], endArray: inout [[Element]]) -> [[Element]] {
        if n == 1 {
            endArray += [array]
        }
        for i in 0  ..< n {
            _ = permutationHelper(n - 1, array: &array, endArray: &endArray)
            let j = n % 2 == 0 ? i : 0
            let temp: Element = array[j]
            array[j] = array[n - 1]
            array[n - 1] = temp
        }
        return endArray
    }
    /**
     - parameter length:
     - returns: Returns all of the combinations in the array of the given length
     */
    func combination (_ length: Int) -> [[Element]] {
        if length < 0 || length > self.count {
            return []
        }
        var indexes: [Int] = (0..<length).reduce([]) {$0 + [$1]}
        var combinations: [[Element]] = []
        let offset = self.count - indexes.count
        while true {
            var combination: [Element] = []
            for index in indexes {
                combination.append(self[index])
            }
            combinations.append(combination)
            var i = indexes.count - 1
            while i >= 0 && indexes[i] == i + offset {
                i -= 1
            }
            if i < 0 {
                break
            }
            i += 1
            let start = indexes[i-1] + 1
            for j in (i-1)..<indexes.count {
                indexes[j] = start + j - i + 1
            }
        }
        return combinations
    }
    /**
     - parameter length: The length of each permutations
     - returns: All of the permutations of this array of a given length, allowing repeats
     */
    func repeatedPermutation(_ length: Int) -> [[Element]] {
        if length < 1 {
            return []
        }
        var indexes: [[Int]] = []
        indexes.repeatedPermutationHelper([], length: length, arrayLength: self.count, indexes: &indexes)
        return indexes.map({ $0.map({ i in self[i] }) })
    }
    private func repeatedPermutationHelper(_ seed: [Int], length: Int, arrayLength: Int, indexes: inout [[Int]]) {
        if seed.count == length {
            indexes.append(seed)
            return
        }
        for i in (0..<arrayLength) {
            var newSeed: [Int] = seed
            newSeed.append(i)
            self.repeatedPermutationHelper(newSeed, length: length, arrayLength: arrayLength, indexes: &indexes)
        }
    }
}


import Foundation
class Node {
  var val: Int64
  var next: Node?
  init(val: Int64) {
    self.val = val
  }
}

class Queue {
  var head: Node?
  var tail: Node?
  init(){}
  func enqueue(val: Int64) {
    let node = Node(val: val)
    if head == nil {
      head = node
      tail = head
    } else {
      tail!.next = node
      tail = node
    }
  }
  func dequeue() -> Int64 {
    let val = self.head!.val
    self.head = self.head!.next
    if self.head == nil {
      self.tail = nil
    }
    return val
  }
}
func solve(K: Int64) -> Int64 {
  if K < 10 {
    return K
  }
  let queue = Queue()
  for i in 1...9 {
    queue.enqueue(Int64(i))
  }
  var count: Int64 = 9
  var result: Int64 = -1
  while count < K {
    let top = queue.dequeue()
    let last = top % 10
    for start in last-1...last+1 {
      if start < 0 || start > 9 {
        continue
      }
      let next = top * 10 + start
      queue.enqueue(next)
      count += 1
      if count == K {
        result = next
        break
      }
    }
  }
  return result
}

let input = readLine()!
let info = input.componentsSeparatedByString(" ")
let K = Int64(info[0])!

print(solve(K))


import Foundation

let K = (readLine()!)
var kArray = K
var stored: [Int] = [1,2,3,4,5,6,7,8,9]
var i = 10

while stored.count != (Int(K) ?? 0){
   let iArray = String(i).characters.flatMap { Int("\($0)") }
   for j in  0..<iArray.count-1{

     var bool1 = abs(((Int (iArray[j]) ?? 0) ) - (Int(iArray[j+1]) ?? 0)) == 1
     var bool2 = abs(((Int(iArray[j+1]) ?? 0  - (Int (iArray[j]) ?? 0) ))) == 1
     var bool3 = abs(((Int (iArray[j]) ?? 0) ) - (Int(iArray[j+1]) ?? 0)) == 0

     if !(bool1 || bool2 || bool3){
       break
     }
     stored.append(i)
   }
   i += 1
}
print(stored.last!)


import Foundation

let K = (readLine()!)
var kArray = K
var stored: [Int] = [1,2,3,4,5,6,7,8,9]
var i = 10

while stored.count != (Int(K) ?? 0){
   let iArray = String(i).characters.flatMap { Int("\($0)") }
   for j in  0..<iArray.count-1{

     var bool1 = abs(((Int (iArray[j]) ?? 0) ) - (Int(iArray[j+1]) ?? 0)) == 1
     var bool2 = abs(((Int(iArray[j+1]) ?? 0  - (Int (iArray[j]) ?? 0) ))) == 1
     var bool3 = abs(((Int (iArray[j]) ?? 0) ) - (Int(iArray[j+1]) ?? 0)) == 0

     if bool1 || bool2 || bool3{
       stored.append(i)
     }

   }

   i += 1
}
print(stored)


export class Main {
  static main(input: string): string {
    const tmp: string[] = input.split("\n");
    const [k]: number[] = tmp.shift().split(" ").map(int => parseInt(int));
    if (k < 10) {
      return `${k}`;
    }
    const cache = {
      1: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
      2: []
    };
    let count = 9;
    let keta = 2;
    let startNum = 1;
    while (true) {
      let count2 = count;
      if (startNum == 9) {
        cache[keta][0] = cache[keta - 1][0] + cache[keta - 1][1];
        cache[keta][9] = cache[keta - 1][8] + cache[keta - 1][9];
      } else {
        cache[keta][startNum] = cache[keta - 1][startNum - 1] + cache[keta - 1][startNum] + cache[keta - 1][startNum + 1];
      }
      count2 += cache[keta][startNum];
      if (count2 >= k) {
        break;
      }
      if (startNum == 9) {
        keta++;
        cache[keta] = [];
        startNum = 1;
      } else {
        startNum++;
      }
      count = count2;
    }
    let startNum2 = startNum;
    keta--;
    let result = `${startNum2}`;
    while (keta > 0) {
      let count2 = count;
      if (startNum2 == 0) {
        count2 += cache[keta][startNum2];
        if (count2 >= k) {
          result += `${startNum2}`;
          keta--;
          continue;
        }
        count = count2;
        startNum2  = startNum2 + 1;
        count2 += cache[keta][startNum2];
        result += `${startNum2}`;
        keta--;
      } else if (startNum2 == 9) {
        count2 += cache[keta][startNum2 - 1];
        if (count2 >= k) {
          startNum2  = startNum2 - 1;
          result += `${startNum2}`;
          keta--;
          continue;
        }
        count = count2;
        count2 += cache[keta][startNum2];
        result += `${startNum2}`;
        keta--;
      } else {
        count2 += cache[keta][startNum2 - 1];
        if (count2 >= k) {
          startNum2 = startNum2 - 1;
          result += `${startNum2}`;
          keta--;
          continue;
        }
        count = count2;
        count2 += cache[keta][startNum2];
        if (count2 >= k) {
          result += `${startNum2}`;
          keta--;
          continue;
        }
        count = count2;
        startNum2  = startNum2 + 1;
        count2 += cache[keta][startNum2];
        result += `${startNum2}`;
        keta--;
      }
    }
    return result;
  }
}
console.log(Main.main(require("fs").readFileSync("/dev/stdin", "utf8")));


import * as fs from "fs";

// 前計算して100個ごとに並べておきました
const table = [0, 878, 4445, 8788, 21122, 33322, 45434, 56776, 76667, 88888, 110111, 122345, 221122, 233322, 323234, 343211, 432332, 444444, 456556, 545676, 565566, 655543, 667655, 765432, 776767, 788989, 887765, 987777, 1001012, 1101111, 1122111, 1212233, 1232232, 2101234, 2122234, 2221010, 2233211, 2322345, 2334544, 3210122, 3223212, 3234555, 3332332, 3344444, 3434343, 3445677, 4321222, 4333344, 4345456, 4443211, 4454545, 4544443, 4556555, 4567889, 5443345, 5455543, 5545433, 5556767, 5654444, 5666556, 5677899, 6545667, 6565565, 6655456, 6667654, 6678999, 6776766, 6788988, 7665434, 7676777, 7766767, 7778889, 7877666, 7889987, 8767676, 8787667, 8877789, 8898789, 8998887, 9887656, 9987676, 10000121, 10101001, 10121223, 11010111, 11110123, 11123221, 11221212, 11233334, 12111123, 12123344, 12222122, 12234321, 12323455, 12343432, 21010010, 21110101, 21122343, 21221112, 21233234, 22111101, 22123322, 22222100, 22233443, 22323433, 22343332, 23211223, 23223444, 23321212, 23333334, 23345454, 23434567, 23454543, 32110010, 32122323, 32221100, 32233222, 32323212, 32334555, 33211001, 33223223, 33234566, 33332343, 33344455, 33434432, 33454322, 34321233, 34333433, 34345545, 34443222, 34454556, 34544454, 34556566, 43210000, 43222321, 43234434, 43332211, 43344323, 43433444, 43445556, 44321101, 44333223, 44344565, 44434456, 44454432, 44544322, 44555656, 44567776, 45443232, 45454566, 45544456, 45556654, 45654323, 45665665, 45677778, 54323432, 54343323, 54433222, 54444556, 54456676, 54554344, 54565678, 55433434, 55445554, 55543222, 55554556, 55566676, 55656567, 55676544, 56543456, 56555654, 56567766, 56665443, 56676778, 56766776, 56778898, 65433232, 65444566, 65456678, 65554432, 65566544, 65655665, 65667777, 66543332, 66555444, 66566778, 66656677, 66676654, 66766566, 66778766, 67654543, 67666655, 67678777, 67776545, 67788766, 67878888, 67899987, 76554445, 76566565, 76655678, 76667876, 76765567, 76777766, 77654322, 77665656, 77677777, 77767767, 77787766, 77877888, 77898888, 78767898, 78787889, 78878876, 78899888, 78999987, 87665556, 87677677, 87767667, 87787666, 87877788, 87898788, 88767876, 88787789, 88878776, 88898998, 88999878, 89887778, 89987876, 98765666, 98777787, 98876565, 98888778, 98988876, 99877776, 99898776, 99998788, 100012110, 100112122, 101000100, 101100112, 101121210, 101212111, 101232110, 110001112, 110101210, 110122210, 111011110, 111111122, 111123343, 111222121, 111233456, 112112110, 112210001, 112222322, 112234443, 112332212, 112344332, 121011001, 121111100, 121123321, 121221234, 121233434, 122111223, 122123444, 122222222, 122234343, 122332112, 122343454, 123212210, 123232123, 123322121, 123333456, 123345654, 123443323, 123455443, 210011001, 210111100, 210123321, 211012222, 211112234, 211211010, 211223232, 211234567, 212121011, 212211212, 212223433, 212321123, 212333323, 212345443, 221012122, 221112212, 221210112, 221223210, 221234545, 222112343, 222211112, 222223333, 222321101, 222333223, 222344565, 223221112, 223233234, 223323232, 223334567, 223432322, 223444434, 223456554, 232112122, 232210100, 232222334, 232234455, 232332232, 232344344, 233212322, 233232321, 233322233, 233334432, 233432101, 233443443, 233455555, 234323323, 234343222, 234432343, 234444455, 234456567, 234554321, 234565655, 321010012, 321110111, 321122345, 321221122, 321233322, 322111111, 322123332, 322222110, 322233445, 322323443, 322343334, 323211233, 323223454, 323321222, 323333344, 323345456, 323443211, 323454545, 332110012, 332122333, 332221110, 332233232, 332323222, 332334565, 333211011, 333223233, 333321000, 333332345, 333344543, 333434434, 333454332, 334322100, 334333443, 334345555, 334443232, 334454566, 334544456, 334556654, 343210010, 343222323, 343234444, 343332221, 343344333, 343433454, 343445566, 344321111, 344333233, 344344567, 344434544, 344454434, 344544332, 344555666, 344567778, 345443234, 345455432, 345544544, 345556656, 345654333, 345665667, 345677788, 432111233, 432123454, 432222232, 432234345, 432332122, 432343456, 433212212, 433232211, 433322123, 433334322, 433345656, 433443333, 433455445, 434323221, 434334556, 434432233, 434444345, 434456543, 434545655, 434565545, 443211223, 443223444, 443321212, 443333334, 443345454, 443434567, 443454543, 444322233, 444334432, 444432101, 444443443, 444455555, 444545445, 444556787, 445432321, 445444433, 445456545, 445545665, 445565555, 445655454, 445666788, 445678989, 454332334, 454344454, 454434345, 454454321, 454543433, 454555545, 454567665, 455434565, 455454455, 455544345, 455556543, 455567877, 455665554, 455677667, 456545443, 456556777, 456654454, 456666566, 456678766, 456767899, 456787898, 543221010, 543233211, 543322345, 543334544, 543432221, 543444333, 543455667, 544323443, 544343334, 544433233, 544444567, 544456765, 544554433, 544566545, 545433445, 545445565, 545543233, 545554567, 545566765, 545656656, 545676555, 554322123, 554334322, 554345656, 554443333, 554455445, 554544565, 554556677, 555432211, 555444323, 555455665, 555545555, 555565445, 555654566, 555666678, 555678878, 556554345, 556566543, 556655656, 556667776, 556765545, 556777666, 556789987, 565443343, 565455455, 565544567, 565556765, 565654434, 565666554, 565677889, 566545665, 566565555, 566655454, 566666788, 566678989, 566776678, 566788899, 567665432, 567676767, 567766765, 567778887, 567877656, 567889898, 654323322, 654343221, 654432334, 654444454, 654456566, 654545678, 654565654, 655433332, 655445444, 655456778, 655554454, 655566566, 655656543, 655667877, 656543432, 656555544, 656567656, 656656777, 656676676, 656766666, 656778788, 665432344, 665444456, 665456654, 665554322, 665565656, 665655555, 665667667, 666543222, 666554556, 666566676, 666656567, 666676544, 666765678, 666777877, 667654433, 667666545, 667677888, 667767878, 667787877, 667878778, 667899876, 676554343, 676565677, 676655654, 676667766, 676765543, 676777656, 676789898, 677665554, 677677667, 677767665, 677787656, 677877778, 677898778, 678767788, 678787787, 678878766, 678898988, 678999876, 765443233, 765454567, 765544543, 765556655, 765654332, 765665666, 765677787, 766545555, 766565445, 766654566, 766666678, 766678878, 766776654, 766788789, 767656766, 767676665, 767766655, 767778777, 767876776, 767888998, 776544556, 776556676, 776654345, 776666543, 776677878, 776767876, 776787789, 777656545, 777667887, 777765656, 777777777, 777876555, 777888776, 778766565, 778778765, 778876678, 778888899, 778988998, 787655667, 787667787, 787765556, 787777677, 787789998, 787887889, 788766543, 788777878, 788876656, 788888877, 788988889, 789877789, 789898789, 789998887, 876545667, 876565565, 876655456, 876667654, 876678999, 876776766, 876788988, 877665434, 877676777, 877766767, 877778889, 877877666, 877889987, 878767676, 878787667, 878877789, 878898789, 878998887, 887656778, 887676677, 887766667, 887778789, 887876788, 887889878, 888767654, 888778999, 888877767, 888898767, 888998787, 889878988, 889987654, 898765444, 898776787, 898789877, 898887777, 898987789, 899876776, 899888998, 899989878, 987656543, 987667877, 987765654, 987777767, 987876545, 987888766, 988766555, 988777898, 988876676, 988888889, 988988988, 989877887, 989898887, 989998899, 998776544, 998788765, 998878887, 998899899, 998999998, 999887889, 999988766, 1000001223, 1000110000, 1000122321, 1001011221, 1001111233, 1001123454, 1001222232, 1001234345, 1010012221, 1010112233, 1011001001, 1011101100, 1011122100, 1011212222, 1011232221, 1012101223, 1012122223, 1012212345, 1012232344, 1012322334, 1012334455, 1100000111, 1100100123, 1100121221, 1101010101, 1101110121, 1101123211, 1101221210, 1101233332, 1110011121, 1110111211, 1110123432, 1111012333, 1111112345, 1111211122, 1111223343, 1112100111, 1112121123, 1112212110, 1112232101, 1112321234, 1112333434, 1112345554, 1121012233, 1121112323, 1121211100, 1121223321, 1122100010, 1122121101, 1122211223, 1122223444, 1122321212, 1122333334, 1122345454, 1123221223, 1123233345, 1123323343, 1123343234, 1123433211, 1123444545, 1123456665, 1210012233, 1210112323, 1211001100, 1211101112, 1211122112, 1211212234, 1211232233, 1212110000, 1212122321, 1212221011, 1212233212, 1212323210, 1212334545, 1221000123, 1221101011, 1221121233, 1221212212, 1221232211, 1222101221, 1222122221, 1222212343, 1222232334, 1222322332, 1222334445, 1223210101, 1223222343, 1223234456, 1223332233, 1223344345, 1223434322, 1223445656, 1232100123, 1232121221, 1232212122, 1232232121, 1232322111, 1232333454, 1232345566, 1233222122, 1233234321, 1233323455, 1233343432, 1233433323, 1233445443, 1233456777, 1234332332, 1234344444, 1234434343, 1234445677, 1234543345, 1234555543, 1234567655, 2100012121, 2100112211, 2101000111, 2101100123, 2101121221, 2101212122, 2101232121, 2110001123, 2110101221, 2110122221, 2111011121, 2111111211, 2111123432, 2111222210, 2111234323, 2112112121, 2112210012, 2112222333, 2112234454, 2112332223, 2112344343, 2121011012, 2121111111, 2121123332, 2121222110, 2121233445, 2122111234, 2122123455, 2122222233, 2122234432, 2122332123, 2122344321, 2123212221, 2123232212, 2123322210, 2123334323, 2123345665, 2123443334, 2123455454, 2210011012, 2210111111, 2210123332, 2211012233, 2211112323, 2211211100, 2211223321, 2212100010, 2212121101, 2212211223, 2212223444, 2212321212, 2212333334, 2212345454, 2221012211, 2221112223, 2221210123, 2221223221, 2221234556, 2222121000, 2222211123, 2222223344, 2222321112, 2222333234, 2222345432, 2223221123, 2223233323, 2223323321, 2223343212, 2223432333, 2223444445, 2223456565, 2232112211, 2232210111, 2232222345, 2232234544, 2232332321, 2232344433, 2233212333, 2233232332, 2233322322, 2233334443, 2233432112, 2233443454, 2233455566, 2234323334, 2234343233, 2234433210, 2234444544, 2234456656, 2234554332, 2234565666, 2321010110, 2321110122, 2321123212, 2321221211, 2321233333, 2322111122, 2322123343, 2322222121, 2322233456, 2322323454, 2322343345, 2323212101, 2323232100, 2323321233, 2323333433, 2323345545, 2323443222, 2323454556, 2332110110, 2332122344, 2332221121, 2332233321, 2332323233, 2332343210, 2333211101, 2333223322, 2333321011, 2333333212, 2333344554, 2333434445, 2333454343, 2334322111, 2334333454, 2334345566, 2334443321, 2334455433, 2334544545, 2334556665, 2343210100, 2343222334, 2343234455, 2343332232, 2343344344, 2343434321, 2343445655, 2344321122, 2344333322, 2344345434, 2344434555, 2344454445, 2344544343, 2344555677, 2344567789, 2345443323, 2345455443, 2345544555, 2345556667, 2345654344, 2345665678, 2345677877, 3210012101, 3210112121, 3211000012, 3211100111, 3211121123, 3211212110, 3211232101, 3212101111, 3212122111, 3212212233, 3212232232, 3212322222, 3212334343, 3212345677, 3221100010, 3221121101, 3221211223, 3221223444, 3222101010, 3222121232, 3222212211, 3222232210, 3222322122, 3222334321, 3222345655, 3223222211, 3223234332, 3223332101, 3223343443, 3223433334, 3223445454, 3223456788, 3232121010, 3232211211, 3232223432, 3232321122, 3232333322, 3232345434, 3233221211, 3233233333, 3233323323, 3233343222, 3233432343, 3233444455, 3233456567, 3234332122, 3234343456, 3234433433, 3234445545, 3234543221, 3234554555, 3234566667];

function check(n: number) {
	const s = n + "";
	let c = s[0];
	for (let i = 0; i < s.length; i++) {
		if (Math.abs((+s[i]) - (+c)) > 1) return s.length - 1 - i;
		c = s[i];
	}
	return -1;
}

const sep = 100;
const input = (fs.readFileSync("/dev/stdin", "utf8") as string).split("\n");
const k = +input[0];
const index = Math.floor(k / sep);

if (k % sep === 0) {
	console.log(table[index]);
} else {
	let count = index * sep;
	for (let i = table[index] + 1; i <= 3234566667; i++) {
		const d = check(i);
		if (d === -1) {
			count++;
		} else if (d > 3) {
			i += 99;
		}
		if (count === k) {
			console.log(i);
			break;
		}
	}

}


import * as fs from 'fs';

const input: string = fs.readFileSync('/dev/stdin', 'utf8');
const args: string[][] = input.split('\n').map(l => l.split(' '));

const nextNumbers: number[][] = [];
for (let i = 0; i < 10; i++) {
  const tmp: number[] =
    [i + 9, i, i + 1]
      .map(x => x % 10)
      .filter(x => Math.abs(i - x) <= 1)
      .sort((x, y) => x - y);
  nextNumbers.push(tmp);
}

function getLunlun(n: number): number {
  let tmp = n - 1;
  let a: number[][] = [];
  for (let i = 1; i <= 9; i++) a.push([i]);
  if (tmp < a.length) return getNum(a[tmp])

  while (tmp >= a.length) {
    tmp -= a.length;
    let tmpArray: number[][] = [];
    a.forEach(array => {
      const nexts: number[] = nextNumbers[array[array.length - 1]];
      nexts.forEach(x => {
        const array2: number[] = [...array, x];
        tmpArray.push(array2);
      })
    });
    a = tmpArray;
  }
  return getNum(a[tmp])
}

function getNum(ns: number[]): number {
  return ns.reduce((x, y) => 10 * x + y)
}

const k = parseInt(args[0][0]);
console.log(getLunlun(k));


import * as fs from 'fs';

const input: string = fs.readFileSync('/dev/stdin', 'utf8');
const args: string[][] = input.split('\n').map(l => l.split(' '));

const k = parseInt(args[0][0]);
console.log(getLunlun(k));

function getLunlun(n: number): number {
  function getNum(ns: number[]): number {
    return ns.reduce((x, y) => 10 * x + y)
  }

  let tmp = n - 1;
  let a: number[][] = [];
  for (let i = 1; i <= 9; i++) a.push([i]);
  if (tmp < a.length) return getNum(a[tmp])

  const nextNumbers: number[][] =
    [...Array(10)]
      .map((_, i) => i)
      .map(i => [i + 9, i, i + 1])
      .map((array, i) =>
        array.map(x => x % 10)
          .filter(x => Math.abs(x - i) <= 1)
          .sort((x, y) => x - y));

  while (tmp >= a.length) {
    tmp -= a.length;

    a =
      a.map(
        array =>
          nextNumbers[array.length - 1]
            .map(x => [...array, x]))
        .flat();
  }
  return getNum(a[tmp])
}


import * as fs from 'fs';
import {arrayify} from "tslint/lib/utils";

const input: string = fs.readFileSync('/dev/stdin', 'utf8');
const args: string[][] = input.split('\n').map(l => l.split(' '));

const k = parseInt(args[0][0]);
console.log(getLunlun(k));

function getLunlun(n: number): number {
  function getNum(ns: number[]): number {
    return ns.reduce((x, y) => 10 * x + y)
  }

  let tmp = n - 1;
  let a: number[][] = [];
  for (let i = 1; i <= 9; i++) a.push([i]);
  if (tmp < a.length) return getNum(a[tmp])

  const nextNumbers: number[][] =
    [...Array(10)]
      .map((_, i) => i)
      .map(i => [i + 9, i, i + 1])
      .map((array, i) =>
        array.map(x => x % 10)
          .filter(x => Math.abs(x - i) <= 1)
          .sort((x, y) => x - y));

  while (tmp >= a.length) {
    tmp -= a.length;
    let tmpArray: number[][] = [];
    a.forEach(array => {
      const nexts: number[] = nextNumbers[array[array.length - 1]];
      nexts.forEach(x => {
        tmpArray.push([...array, x]);
      })
    });
    a = tmpArray;
  }
  return getNum(a[tmp])
}


process.stdin.resume();
process.stdin.setEncoding('utf8');

// 標準入力取込
let gInput = '';
process.stdin.on('data', (chunk) => (gInput += chunk));
process.stdin.on('end', () => main(gInput.split(/\r?\n/)));

// 解答
function main(inputs: string[]): void {
  const k = Number(inputs[0].split(' ')[0]);
  // 途中計算用配列
  let temp = [1, 2, 3, 4, 5, 6, 7, 8, 9];
  // 解答用配列
  let ans: number[] = [];

  while (ans.length <= k) {
    const num = temp[0];

    ans.push(num);

    const num1 = num % 10;
    const num2 = num * 10 + num1;

    // 一の位が0でない場合、num - 1の値もセット
    if (num1 !== 0) {
      temp.push(num2 - 1);
    }

    temp.push(num2);

    // 一の位が9でない場合、num + 1の値もセット
    if (num1 !== 9) {
      temp.push(num2 + 1);
    }

    // 途中計算用配列から先頭要素を削除
    temp.shift();
  }

  console.log(ans[k - 1]);
}


S = input()

#print('S=', S)

n = len(S)

#print('len(S)=', n)

list_S = list(S)

#print('list(S)=', list_S)

count = 0

for i in range((n-1)//2):
  if list_S[i] != list_S[n-1-i]:
    count += 1
if count > 0:
  print('No')
  exit()

list_left = list_S[0 : (n-1)//2]
#print('list_left=', list_left)
list_right = list_S[(n+3)//2-1 : n]
#print('list_right=', list_right)

n_edge = len(list_left)
#print('n_edge=', n_edge)

if n_edge % 2 == 1:
  for i in range((n_edge-1)//2):
    if list_left[i] != list_left[n_edge-1-i]:
      print('No')
      exit()

if n_edge % 2 == 0:
  for i in range(n_edge//2):
    if list_left[i] != list_left[n_edge-1-i]:
      print('No')
      exit()

print('Yes')


S=input()
N=len(S)
f=0
for i in range((N-1)//4):
    if S[i]!=S[(N-3)//2-i]:
        f=-1
        #print(i)
        break
for i in range((N+1)//2,(3*N+1)//4):
    if S[i]!=S[N-1-i]:
        f=-1
        #print(i)
        break
for i in range((N-1)//2):
    if S[i]!=S[N-1-i]:
        f=-1
        #print(i)
        break
if f==-1:
    print("No")
else:
    print("Yes")


s = input()
n = len(s)

a = s[0:int((n-1)/2)]
b = s[int((n+1)/2):n]

if s[::-1] == s and a[::-1] == a and b[::-1] == b:
  print('Yes')
else:
  print('No')


import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time, copy,bisect
from operator import itemgetter
#from heapq import heappush, heappop
#import numpy as np
#from scipy.sparse.csgraph import shortest_path, floyd_warshall, dijkstra, bellman_ford, johnson
#from scipy.sparse import csr_matrix
#from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
sys.setrecursionlimit(10**7)
inf = 10**20
mod = 10**9 + 7

stdin = sys.stdin

ni = lambda: int(ns())
nf = lambda: float(ns())
na = lambda: list(map(int, stdin.readline().split()))
nb = lambda: list(map(float, stdin.readline().split()))
ns = lambda: stdin.readline().rstrip()  # ignore trailing spaces

def judge(S):
    for i in range(len(S) // 2):
        if S[i] != S[-(i+1)]:
            return False
    return True

S = ns()
N = len(S)
p = S[:(N-1)//2]
l = S[(N+3)//2 - 1:]
if judge(p) and judge(l):
    print('Yes')
else:
    print('No')


s=input()
n=len(s)
m=(n-1)//2
t=s[:m]

for i in range(m):
  #print(s[i],s[-i-1])
  if s[i]!=s[-i-1]:
    print('No')
    exit()

l=(m-1)//2
for i in range(l):
  #print(t[i],t[-i-1])
  if t[i]!=t[-i-1]:
    print('No')
    exit()
print('Yes')


s=input()
n=len(s)
m=(n-1)//2
t=s[:m]
if m%2==0:
  print('No')
  exit()

for i in range(m):
  #print(s[i],s[-i-1])
  if s[i]!=s[-i-1]:
    print('No')
    exit()

l=(m-1)//2
for i in range(l):
  #print(t[i],t[-i-1])
  if t[i]!=t[-i-1]:
    print('No')
    exit()
print('Yes')


import java.util.*;
import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException{
    	// Solution sol = new Solution();
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	String s = br.readLine();
    	int N = s.length();
    	if(N%2==0)
    		System.out.println("No");
    	else if(checkPal(s)&&checkPal(s.substring(0,(N-1)/2))&&checkPal(s.substring((N+3)/2-1,N)))
    		System.out.println("Yes");
    	else
    		System.out.println("No");

    }

    public static boolean checkPal(String s){

    	for(int i=0; i<=s.length()/2; i++){
    		if(s.charAt(i)!=s.charAt(s.length()-1-i))
    			return false;
    	}
    	return true;
    }
}


import java.io.*;
import java.lang.*;
import java.util.*;
public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String s=br.readLine();
        int N=s.length();
        int mid=N/2;
        boolean flag=true;
        for(int i=0;i<=mid;i++){
            if(s.charAt(i)!=s.charAt(N-1-i)){
                flag=false;
                break;
            }
        }
        int mid1=mid/2;
        for(int i=0;flag && i<=mid1;i++){
            if(s.charAt(i)!=s.charAt(mid-1-i)) flag=false;
        }
        int mid2=mid/2+mid+1;
        for(int i=mid+1;flag && i<=mid2;i++){
            if(s.charAt(i)!=s.charAt(2*mid-i)) flag=false;
        }
        if(flag) System.out.println("Yes");
        else System.out.println("No");
    }
}


    import java.io.*;
    public class Main{ public static void main(String...args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String subString = br.readLine(); int len = subString.length();
        String r1 = new StringBuilder(subString).reverse().toString(); String s1 = subString.substring(0,(len-1)/2);
        String r2 = new StringBuffer(s1).reverse().toString(); String s2 = subString.substring(((len+3)/2)-1, len);
        String r3 = new StringBuffer(s2).reverse().toString();
        if(subString.equals(r1) && s1.equals(r2) && s2.equals(r3)) System.out.println("Yes");
      	else System.out.println("No");}
    }


import java.util.*;

public class Main {
  	public static void main(String[] args) {
      Scanner sc = new Scanner(System.in);
      String s = sc.next();
      int n = s.length();

      String a = s.substring(0, n/2);
      String b = s.substring(n/2+1, n);

      boolean ans = isKaibun(a) && isKaibun(b) && isKaibun(s);
      System.out.println(ans ? "Yes" : "No");

    }
}

private static boolean isKaibun(String s) {
  	boolean ans = true;
  	for (int i = 0; i < s.length() / 2; i++) {
    	if (s.charAt(i) != s.charAt(s.length() - 1 - i)) ans = false;
  	}
 	return ans;
	}
}


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        try (Scanner sc = new Scanner(System.in)) {
            String S = sc.next();
            int N = S.length();
            System.out.println(isPalindrome(S) && isPalindrome(S.substring(0, (N - 1) / 2)) && isPalindrome(S.substring((N + 3) / 2 + 1, N)) ? "Yes" : "No");
        }
    }

    private static boolean isPalindrome(String s) {
        for (int l = 0, r = s.length() - 1; l < r; l++, r--) {
            if (s.charAt(l) != s.charAt(r)) {
                return false;
            }
        }
        return true;
    }
}


#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N = 1e5 + 5;
char s[N];
inline void rror() {
	puts("No");
	exit(0);
}
int main() {
	scanf("%s",s+1);
	n = strlen(s+1);
	for(int i = 1;i <= n/2;++i)
		if(s[i] != s[1+n-i]) rror();
	m = n/2;
	for(int i = 1;i <= m/2;++i)
		if(s[i] != s[m+1-i] || s[m+1+i] != s[n+1-i]) rror();
	puts("Yes");
	return 0;
}


#include<bits/stdc++.h>
#define ll long long int
#define mod 1000000007
using namespace std;
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	string ss;
	cin>>ss;
	ll x,y,z,n,ans=1;
	n=ss.size();
	char s[n+1];
	for(int a=0;a<n;a++)
	s[a+1]=ss[a];
	for(int a=1;a<=n;a++)
	{
		if(s[a]!=s[n+1-a])
		{
			ans=0;
			break;
		}
	}
	ll m=(n-1)/2;
	for(int a=1;a<=m;a++)
	{
		if(s[a]!=s[m+1-a])
		{
			ans=0;
			break;
		}
	}
	ll mm=(n+3)/2;
	for(int a=mm;a<=n;a++)
	{
		if(s[a]!=s[n+1-a])
		{
			ans=0;
			break;
		}
	}
	if(ans==0)
	cout<<"No";
	else
	cout<<"Yes";
	return 0;
}


#include <bits/stdc++.h>
/**
*   author: j o s e m a g o
*   date:
**/
using namespace std;
#pragma GCC optimize ("Ofast")
#define f first
#define s second
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(),(v).end()
#define mset(a,v) memset(a,v,sizeof(a))
#define pb push_back
#define sz(x) ((int)(x).size())
#define rsz resize
#define ln "\n"

typedef double db;
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
const ld PI = 2*acos(0.0);
const int MOD = 1000000007;

int main(){

  //freopen("input.in","r",stdin);
  //freopen("input.out","w",stdout);

    ios_base::sync_with_stdio(0); cin.tie(0);

    string s;
    cin >> s;

    bool a = false,b = false,c = false;
    string aa,bb,cc;
    aa = s;
    reverse(aa.begin(),aa.end());
    if(aa == s) a = true;
    int n = s.size();

    for(int i = 0;i < (n-1)/2;i++){
        bb+=s[i];
    }
    string c_b = bb;
    reverse(c_b.begin(),c_b.end());
    if(c_b == bb) b = true;

    for(int i = ((n+3)/2)-1;i < n;i++){
        cc+=s[i];
    }
    string c_c = cc;
    reverse(c_c.begin(),c_c.end());
    if(cc == c_c) c = true;

    if(a && b && c) cout<<"Yes\n";
    else cout<<"No\n";

    return 0;
}


#include<iostream>
#include<string>
using namespace std;
int main()
{
  string s;
  cin>>s;
  int n=s.size();
  int count=0;
  for(int i=0;i<n;i++){
    if(s[i]==s[n-1-i]){
      count++;
    }
  }
  if(count==n){
    int x=(n-1)/2;
    for(int i=0;i<x;i++){
      if(s[i]==s[x-1-i]){
        count++;
      }
    }
    int y=(n+3)/2;
    for(int i=0;i<n-y+1;i++){
      if(s[y-1+i]==s[n-1-i]){
        count++;
        y++;
      }
    }
    if(count==n+n+1+x-y){
      cout<<"Yes";
    }
    else{
      cout<<"No";
    }
  }
  else{
    cout<<"No";
  }

}


#include<iostream>
#include<string>
using namespace std;
int main()
{
  string s;
  cin>>s;
  int n=s.size();
  int count=0;
  for(int i=0;i<n;i++){
    if(s[i]==s[n-1-i]){
      count++;
    }
  }
  if(count==n){
    int x=(n-1)/2;
    for(int i=0;i<x;i++){
      if(s[i]==s[x-1-i]){
        count++;
      }
    }
    int y=(n+3)/2;
    for(int i=0;i<n-y;i++){
      if(s[y-1+i]==s[n-1-i]){
        count++;
        y++;
      }
    }
    if(count==n+n+x-y){
      cout<<"Yes";
    }
    else{
      cout<<"No";
    }
  }
  else{
    cout<<"No";
  }

}


#include<iostream>
#include<string>
using namespace std;
int main()
{
  string s;
  cin>>s;
  int n=s.size();
  int count=0;
  for(int i=0;i<n;i++){
    if(s[i]==s[n-1-i]){
      count++;
    }
  }
  if(count==n){
    int x=(n-1)/2;
    for(int i=0;i<x;i++){
      if(s[i]==s[x-1-i]){
        count++;
      }
    }
    int y=(n+3)/2;
    for(int i=0;i<n-y;i++){
      if(s[y-1]==s[n-1-i]){
        count++;
        y++;
      }
    }
    if(count==n+n+x-y){
      cout<<"Yes";
    }
    else{
      cout<<"No";
    }
  }
  else{
    cout<<"No";
  }

}


#include<stdio.h>
#include<string.h>
int main(void){
char s[100];
  scanf("%s",&s);
  char mae[50],ato[50];
  for(int i=0;i<50;i++){
	mae[i]=0;
    ato[i]=0;
  }
  for(int i=0;i<strlen(s)/2;i++){
	mae[i]=s[i];
    ato[i]=s[i+strlen(s)/2+1];
    //printf("%c %c\n",mae[i],ato[i]);
  }
  //printf("%d\n%d\n%d\n",strlen(s),strlen(mae),strlen(ato));
  for(int i=0;i<strlen(s)/2;i++){
    if(s[i]!=s[strlen(s)-1-i]){
      printf("No");
      return 0;
    }
    }
     for(int i=0;i<strlen(mae)/2;i++){
    if(mae[i]!=mae[strlen(mae)-1-i]){
      printf("No");
      return 0;
    }}
       for(int i=0;i<strlen(ato)/2;i++){
    if(ato[i]!=ato[strlen(ato)-1-i]){
      printf("No");
      return 0;
    }}
         printf("Yes");
    //  printf("%d\n%d\n",strlen(mae),strlen(ato));
      return 0;
      }


#include<stdio.h>
#include<string.h>

int main(void){

    char S[100];
    int i,j,ans = 0,lenth,check_kaibun;

    scanf("%s",S);
    lenth = strlen(S);

    check_kaibun = 1;
    for(i = 0;i < lenth;i++){
        //printf("左から%d番目：%c 右から%d番目；%c\n",i,S[i],i,S[lenth - 1 - i]);
        if(S[i] != S[lenth - 1 - i]) check_kaibun = 0;
    }
    if(check_kaibun == 1){
        ans++;
        //printf("Condition1 Successed!\n");
    }else{
        //printf("Condition1 Failed!");
    }
    //printf("\n");

    check_kaibun = 1;
    int Condition2 = (lenth - 1)/2;
    for(i = 0;i < Condition2;i++){
        //printf("左から%d番目：%c 右から%d番目；%c\n",i,S[i],i,S[Condition2 - 1 - i]);
        if(S[i] != S[Condition2 - 1 - i])  check_kaibun = 0;
    }
    if(check_kaibun == 1){
        ans++;
        //printf("Condition2 Successed!\n");
    }else{
        //printf("Condition2 Failed!\n");
    }
    //printf("\n");

    check_kaibun = 1;
    int Condition3 = (lenth + 3)/2;
    for(i = Condition3 - 1;i < lenth;i++){
        //printf("左から%d番目：%c 右から%d番目：%c\n",i,S[i],i,S[lenth - 1 - i]);
        if(S[i] != S[lenth - 1 - i]) check_kaibun = 0;
    }
    if(check_kaibun == 1){
        ans++;
        //printf("Condition3 Successed!\n");
    }else{
        //printf("Condition3 Failed!\n");
    }
    //printf("\n");

    if(ans == 3) printf("Yes\n");
    else printf("No\n");
    return 0;
}


#include<stdio.h>
#include<string.h>
int main()
{
  int n, l, h, h1, h2, x, y, z;
  char a[100];
  gets(a);
  n = strlen(a);
  l = 0;
  h = n - 1;
  h1 = ((n-1)/2) - 1;
  h2 = ((n+3)/2) - 1;

  while(h>l)
  {
      if(a[l++]!=a[h--])
      {
          x = 0;
          break;
      }
      if(l>=h)
      x = 1;
  }

  l = 0;
  while(h1>l)
  {
      if(a[l++]!=a[h1--])
      {
          y = 0;
          break;
      }
      if(l>=h1)
      y = 1;
  }

  h = n - 1;
  while(h>h2)
  {
      if(a[h2++]!=a[h--])
      {
          z = 0;
          break;
      }
      if(h2>=h)
      z = 1;
  }

  if(x==1 && y==1 && z==1)
  printf("Yes\n");
  else
  printf("No\n");

  return 0;
}


#include<stdio.h>
#include<string.h>

int main(void){
 char s[100],t[100];
  scanf("%s",s);
  int l=strlen(s);
  for(int i=0;i<l;i++){
    t[l-1-i]=s[i];
  }
  for(int i=0;i<l;i++){
    if(s[i]!=t[i] || s[0]!=s[(l-1)/2]){
      printf("No");
      return 0;
  }
  }
  printf("Yes");
    return 0;
}


#include<stdio.h>
#include<string.h>

int main(void){
 char s[100],t[100];
  scanf("%s",s);
  int l=strlen(s);
  for(int i=0;i<l;i++){
    t[l-1-i]=s[i];
  }
  for(int i=0;i<l;i++){
    if(s[i]!=t[i]){
      printf("No");
      return 0;
  }
  }
  printf("Yes");
    return 0;
}


#include<stdio.h>
#include<string.h>

int main(void){
 char s[100],t[100];
  scanf("%s",s);
  int l=strlen(s);
  for(int i=0;i<l;i++){
    s[i]=t[l-1-i];
  }
  for(int i=0;i<l;i++){
    if(s[i]!=t[i]){
      printf("No");
      return 0;
  }
  }
  printf("Yes");
    return 0;
}


"use strict";

const isCycle = function(s){
    let l = 0
    let r = s.length-1
    while(l<=r){
        if(s[l] !== s[r]) return false
        l++
        r--
    }
    return true
}

const main = arg => {
    const input = arg.trim().split("\n");

    const S = input[0];
    const N = S.length
    let first = isCycle(S)
    let sec = isCycle(S.slice(0, (N-1)/2))
    let third = isCycle(S.slice((N+3)/2-1))
    if(first && sec && third) console.log("Yes")
    else console.log("No")
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


"use strict";function Main(t){const e=t=>{const e=t.length;for(let n=0;n<(e-1)/2;n++){if(t[n]!=t[e-1-n])return!1}return!0},n=(t=t.split("")).length;console.log(e(t)&&e(t.slice(0,(n-1)/2))&&e(t.slice((n+3)/2-1))?"Yes":"No")} Main(require("fs").readFileSync("/dev/stdin", "utf8").trim());


function main(input) {
  var S = input[0];
  var N = S.length;

  var resCount = 0;
  if(palindrome(N, S)){
  	resCount +=1;
  };

  var headS = S.slice(0, (N-1)/2);
  if(palindrome(headS.length, headS)){
    resCount +=1;
  }

  var TailS = S.slice((N +3)/2 -1, N);
  if(palindrome(TailS.length, TailS)){
    resCount +=1;
  }

  if(resCount === 3){
  	console.log('Yes');
  }else{
  	console.log('No');
  }
}

function palindrome(N, S){

    var mid = Math.floor(N/2);
	for ( var i = 0; i < mid; i++ ) {
    if (S[i] !== S[N - 1 - i]) {
      return false;
    }
  }

  return true;
}

main(require('fs').readFileSync('/dev/stdin', 'utf8').trim().split("\n"));


'use strict';
function Main(input) {
	input = input.trim().split("");

  	let n = input.length;
  	let l = (n - 1) / 2;
  	let r = (n + 3) / 2;
  	let left = [];
  	let right = [];
  	for(let i = 0; i < l; i++){
      left.push(input[i])
    }
  	for(let i = r-1; i < n; i++){
      right.push(input[i])
    }

	for(let i = 0 ; i < Math.floor(left.length/2); i++){
      let e = left.length-1-i;
      if(left[i] !== left[e]){
        console.log('No');
        return;
      }
    }
  	for(let i = 0 ; i < Math.floor(right.length/2); i++){
      let e = right.length-1-i;
	  if(right[i] !== right[e]){
        console.log('No');
        return;
      }
    }
  	console.log('Yes');
}

//*この行以降は編集しないでください（標準入出力から一度に読み込み、Mainを呼び出します）
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


'use strict';
function main(input) {
  const arr = input.trim().split('\n')[0];
  const howLong = arr.length;
  let isStrong = false;
  let isKaibun = false;

  if (kaibun(howLong)) {
    if (kaibun((howLong - 1) / 2)) {
      if (kaibun(howLong + 3) / 2) {
        isStrong = true;
      }
    }
  }

  function kaibun (howLong) {
    for (let i = 0; i < (howLong / 2); i ++) {
      if (arr[i] !== arr[howLong - i]) {
        return;
      }
      return isKaibun = true;
    }
  }

  console.log(isStrong ? 'Yes' : 'No');
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));


'use strict';
function main(input) {
  const arr = input.trim().split('\n')[0];
  const howLong = arr.length;
  let isStrong = false;
  let isKaibun = false;

  if (kaibun(howLong)) {
    if (kaibun((howLong - 1) / 2)) {
      if (kaibun(howLong+ 3) / 2) {
        isStrong = true;
      }
    }
  }

  function kaibun (howLong) {
    for (let i = 0; i < (howLong / 2); i ++) {
      if (arr[i] !== arr[howLong - 1]) {
        return;
      }
      return isKaibun = true;
    }
  }

  console.log(isStrong ? 'Yes' : 'No');
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));


package main

import "fmt"

func main() {
	var S string
	fmt.Scanf("%s", &S)

	if isKaibun(S) && isKaibun(S[0:(len(S)-1)/2]) && isKaibun(S[(len(S)+3)/2-1:]) {
		fmt.Println("Yes")
		return
	}

	fmt.Println("No")
}

func isKaibun(s string) bool {
	for i := 0; i < len(s)/2; i++ {
		if s[i] != s[len(s)-1-i] {
			return false
		}
	}
	return true
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	nextReader = newScanner()
	s := nextString()

	n := len(s)
	if !palindrome(s) {
		fmt.Println("No")
		return
	}
	if !palindrome(s[:(n-1)/2]) {
		fmt.Println("No")
		return
	}
	if !palindrome(s[(n+3)/2-1 : n]) {
		fmt.Println("No")
		return
	}
	fmt.Println("Yes")
}

func palindrome(s string) bool {
	i, j := 0, len(s)-1
	for i < j {
		if s[i] != s[j] {
			return false
		}
		i++
		j--
	}
	return true
}

// ---------------------------------------------------------------
// I/O
// ---------------------------------------------------------------
var nextReader func() string

func newScanner() func() string {
	sc := bufio.NewScanner(os.Stdin)
	sc.Buffer(make([]byte, 1024), int(1e11))
	sc.Split(bufio.ScanWords)
	return func() string {
		sc.Scan()
		return sc.Text()
	}
}

func nextString() string { return nextReader() }

func nextInt() int { n, _ := strconv.Atoi(nextReader()); return n }

func nextInts(size int) []int {
	ns := make([]int, size)
	for i := 0; i < size; i++ {
		ns[i] = nextInt()
	}
	return ns
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"reflect"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)
var out = bufio.NewWriter(os.Stdout)

func main() {
	sc.Split(bufio.ScanWords)
	defer out.Flush() // !!!!coution!!!! you must use Fprint(out, ) not Print()
	/* --- code --- */
	S := next()
	N := len(S)
	if S == reverse(S) {
		if S[:(N-1)/2] == reverse(S[:(N-1)/2]) {
			fmt.Println("Yes")
			return
		}
	}
	fmt.Println("No")
}

func reverse(s string) string {
	rs := []rune(s)
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		rs[i], rs[j] = rs[j], rs[i]
	}
	return string(rs)
}

// -*-*-*-*-*-*-*-*-
// * I/O utilities *
// -*-*-*-*-*-*-*-*-

func next() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	a, _ := strconv.Atoi(next())
	return a
}

func nextInt64() int64 {
	a, _ := strconv.ParseInt(next(), 10, 64)
	return a
}

func nextFloat64() float64 {
	a, _ := strconv.ParseFloat(next(), 64)
	return a
}

func nextInts(n int) []int {
	ret := make([]int, n)
	for i := 0; i < n; i++ {
		ret[i] = nextInt()
	}
	return ret
}
func nextFloats(n int) []float64 {
	ret := make([]float64, n)
	for i := 0; i < n; i++ {
		ret[i] = nextFloat64()
	}
	return ret
}
func nextStrings(n int) []string {
	ret := make([]string, n)
	for i := 0; i < n; i++ {
		ret[i] = next()
	}
	return ret
}

func split(s string) []string {
	ret := make([]string, len([]rune(s)))
	for i, v := range []rune(s) {
		ret[i] = string(v)
	}
	return ret
}

func PrintOut(src interface{}, joinner string) {
	switch reflect.TypeOf(src).Kind() {
	case reflect.Slice:
		s := reflect.ValueOf(src)
		for idx := 0; idx < s.Len(); idx++ {
			fmt.Fprintf(out, "%v", s.Index(idx))
			if idx < s.Len()-1 {
				fmt.Fprintf(out, "%s", joinner)
			} else {
				fmt.Fprintln(out)
			}
		}
	default:
		fmt.Fprintln(out, "fuck")
	}
}

// -*-*-*-*-*-*-*-*-
// * tool snippets *
// -*-*-*-*-*-*-*-*-
func duplicate2Int(base [][]int) (ret [][]int) {
	ret = make([][]int, len(base))
	for i, v := range base {
		ret[i] = append([]int{}, v...)
	}
	return
}

// -*-*-*-*-*-*-*-*-*-*-*-*-*-
// * Algorithms Utility Zone *
// -*-*-*-*-*-*-*-*-*-*-*-*-*-

// -*-*-*-*-*-*-*-
// * 1. nibutan  *
// -*-*-*-*-*-*-*-
func lower_bound(arr []int, target int) int {
	l, r := 0, len(arr)
	for l < r {
		mid := (l + r) / 2
		if arr[mid] < target {
			l = mid + 1
		} else {
			r = mid
		}
	}
	return l
}

func upper_bound(arr []int, target int) int {
	l, r := 0, len(arr)
	for l < r {
		mid := (l + r) / 2
		if target < arr[mid] {
			r = mid
		} else {
			l = mid + 1
		}
	}
	return l
}

// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
// * math flavor typical theories *
// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
func gcd(a, b int) int {
	if a > b {
		return gcd(b, a)
	}
	for a != 0 {
		a, b = b%a, a
	}
	return b
}

func pow(a, b int) (ret int) {
	ret = a
	// 10^2 = 100ってことは10に10を1回掛けることだね
	// なので初期値を含めると上限b-1未満
	for i := 0; i < b-1; i++ {
		ret *= a
	}
	return
}

func powMod(n, m, mod int) (ret int) {
	ret = 1
	for m > 0 {
		if m&1 == 1 {
			ret *= n
			ret %= mod
		}
		n *= n
		n %= mod
		m >>= 1
	}
	return ret
}


//go:generate echo "https://atcoder.jp/contests/abc159/tasks/abc159_b"
package main

import (
	"bufio"
	"fmt"
	"io"
	"math/big"
	"os"
	"strconv"
)

var scan = newScanner(os.Stdin)

func Solve(S string) bool {
	isPalindrome := func(s string) bool {
		for l, r := 0, len(s)-1; l < r; l, r = l+1, r-1 {
			if s[l] != s[r] {
				return false
			}
		}
		return true
	}

	if len(S) <= 4 {
		return false
	}

	return isPalindrome(S) && isPalindrome(S[0:(len(S)-1)/2]) && isPalindrome(S[(len(S)+3)/2+1:])
}

func main() {
	S := scan.String()
	if Solve(S) {
		fmt.Println("Yes")
	} else {
		fmt.Println("No")
	}
}

type scanner struct {
	*bufio.Scanner
}

func newScanner(r io.Reader) *scanner {
	s := bufio.NewScanner(r)
	s.Split(bufio.ScanWords)
	s.Buffer(nil, 100000000)
	return &scanner{s}
}

func (s *scanner) String() string {
	s.Scan()
	return s.Text()
}

func (s *scanner) Strings(l int) []string {
	if l == 0 {
		return []string{}
	}
	sl := make([]string, l, l)
	for i := range sl {
		sl[i] = s.String()
	}
	return sl
}

func (s *scanner) Int() int {
	n, _ := strconv.Atoi(s.String())
	return n
}

func (s *scanner) Ints(l int) []int {
	if l == 0 {
		return []int{}
	}
	sl := make([]int, l, l)
	for i := range sl {
		sl[i] = s.Int()
	}
	return sl
}

func (s *scanner) Float64() float64 {
	f, _ := strconv.ParseFloat(s.String(), 64)
	return f
}

func (s *scanner) Floats64(l int) []float64 {
	if l == 0 {
		return []float64{}
	}
	sl := make([]float64, l, l)
	for i := range sl {
		sl[i] = s.Float64()
	}
	return sl
}

func (s *scanner) BigInt() *big.Int {
	n, _ := strconv.ParseInt(s.String(), 10, 64)
	return big.NewInt(n)
}

func (s *scanner) BigInts(l int) []*big.Int {
	if l == 0 {
		return []*big.Int{}
	}
	sl := make([]*big.Int, l, l)
	for i := range sl {
		sl[i] = s.BigInt()
	}
	return sl
}

func iabs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

func imax(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func imin(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func ipow(x, n int) int {
	if n == 0 {
		return 1
	}
	a := ipow(x, n>>1)
	a *= a
	if n&1 != 0 {
		a *= x
	}
	return a
}

func chmax(x *int, v int) {
	if *x < v {
		*x = v
	}
}

func chmin(x *int, v int) {
	if *x > v {
		*x = v
	}
}

func factor(n int) map[int]int {
	m := map[int]int{}
	for i := 2; i*i <= n; i++ {
		for n%i == 0 {
			n /= i
			m[i]++
		}
	}
	if n != 1 {
		m[n]++
	}
	return m
}

var mod = 1000000007

func setMintMod(x int) {
	mod = x
}

type mint int

func newMint(v int) mint {
	return mint((v%mod + mod) % mod)
}

func (x mint) Add(y mint) mint {
	v := x + y
	if v >= mint(mod) {
		return v - mint(mod)
	}
	return v
}

func (x mint) Sub(y mint) mint {
	v := x + mint(mod) - y
	if v >= mint(mod) {
		return v - mint(mod)
	}
	return v
}

func (x mint) Mul(y mint) mint {
	return (x * y) % mint(mod)
}

func (x mint) pow(n int) mint {
	if n == 0 {
		return mint(1)
	}
	a := x.pow(n >> 1)
	a = a.Mul(a)
	if n&1 != 0 {
		a = a.Mul(x)
	}
	return a
}

func (x mint) Inverse() mint {
	return x.pow(mod - 2)
}

func (x mint) Div(y mint) mint {
	return x * y.Inverse()
}

func (x mint) Neg() mint {
	return newMint(int(-x))
}

type factorial struct {
	fact        []mint
	factInverse []mint
}

func newFactorial(n int) *factorial {
	f := new(factorial)
	f.init(n)
	return f
}

func (f *factorial) init(n int) {
	fact := make([]mint, n+1, n+1)
	fact[0] = newMint(1)
	for i := 1; i <= n; i++ {
		fact[i] = fact[i-1].Mul(newMint(i))
	}

	inv := make([]mint, n+1, n+1)
	inv[n] = fact[n].Inverse()
	for i := n; i >= 1; i-- {
		inv[i-1] = inv[i].Mul(newMint(i))
	}

	f.fact = fact
	f.factInverse = inv
}

func (f *factorial) Get(n int) mint {
	return f.fact[n]
}

func (f *factorial) GetInverse(n int) mint {
	return f.factInverse[n]
}

func (f *factorial) Permutation(n, k int) mint {
	if k < 0 || n < k {
		return 0
	}
	return f.fact[n].Mul(f.factInverse[n-k])
}

func (f *factorial) Combination(n, k int) mint {
	if k < 0 || n < k {
		return 0
	}
	return f.fact[n].Mul(f.factInverse[k]).Mul(f.factInverse[n-k])
}

type sieve struct {
	n          int
	primes     []int
	maxFactors []int
}

func newSieve(n int) *sieve {
	s := &sieve{
		n:          n,
		primes:     []int{},
		maxFactors: make([]int, n+1, n+1),
	}
	s.init()
	return s
}

func (s *sieve) init() {
	s.maxFactors[0] = -1
	s.maxFactors[1] = -1
	for i := 2; i <= s.n; i++ {
		if s.maxFactors[i] != 0 {
			continue
		}
		s.primes = append(s.primes, i)
		s.maxFactors[i] = i
		for j := i * i; j <= s.n; j += i {
			if s.maxFactors[j] == 0 {
				s.maxFactors[j] = i
			}
		}
	}
}

func (s *sieve) IsPrime(x int) bool {
	return s.maxFactors[x] == x
}

func (s *sieve) Factor(x int) map[int]int {
	m := map[int]int{}
	for x != 1 {
		m[s.maxFactors[x]]++
		x /= s.maxFactors[x]
	}
	return m
}


//go:generate echo "https://atcoder.jp/contests/abc159/tasks/abc159_b"
package main

import (
	"bufio"
	"fmt"
	"io"
	"math/big"
	"os"
	"strconv"
)

var scan = newScanner(os.Stdin)

func Solve(S string) bool {
	isPalindrome := func(s string) bool {
		for l, r := 0, len(s)-1; l < r; l, r = l+1, r-1 {
			if s[l] != s[r] {
				return false
			}
		}
		return true
	}
	return isPalindrome(S) && isPalindrome(S[0:(len(S)-1)/2]) && isPalindrome(S[imin(len(S)-1, (len(S)+3)/2+1):])
}

func main() {
	S := scan.String()
	if Solve(S) {
		fmt.Println("Yes")
	} else {
		fmt.Println("No")
	}
}

type scanner struct {
	*bufio.Scanner
}

func newScanner(r io.Reader) *scanner {
	s := bufio.NewScanner(r)
	s.Split(bufio.ScanWords)
	s.Buffer(nil, 100000000)
	return &scanner{s}
}

func (s *scanner) String() string {
	s.Scan()
	return s.Text()
}

func (s *scanner) Strings(l int) []string {
	if l == 0 {
		return []string{}
	}
	sl := make([]string, l, l)
	for i := range sl {
		sl[i] = s.String()
	}
	return sl
}

func (s *scanner) Int() int {
	n, _ := strconv.Atoi(s.String())
	return n
}

func (s *scanner) Ints(l int) []int {
	if l == 0 {
		return []int{}
	}
	sl := make([]int, l, l)
	for i := range sl {
		sl[i] = s.Int()
	}
	return sl
}

func (s *scanner) Float64() float64 {
	f, _ := strconv.ParseFloat(s.String(), 64)
	return f
}

func (s *scanner) Floats64(l int) []float64 {
	if l == 0 {
		return []float64{}
	}
	sl := make([]float64, l, l)
	for i := range sl {
		sl[i] = s.Float64()
	}
	return sl
}

func (s *scanner) BigInt() *big.Int {
	n, _ := strconv.ParseInt(s.String(), 10, 64)
	return big.NewInt(n)
}

func (s *scanner) BigInts(l int) []*big.Int {
	if l == 0 {
		return []*big.Int{}
	}
	sl := make([]*big.Int, l, l)
	for i := range sl {
		sl[i] = s.BigInt()
	}
	return sl
}

func iabs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

func imax(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func imin(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func ipow(x, n int) int {
	if n == 0 {
		return 1
	}
	a := ipow(x, n>>1)
	a *= a
	if n&1 != 0 {
		a *= x
	}
	return a
}

func chmax(x *int, v int) {
	if *x < v {
		*x = v
	}
}

func chmin(x *int, v int) {
	if *x > v {
		*x = v
	}
}

func factor(n int) map[int]int {
	m := map[int]int{}
	for i := 2; i*i <= n; i++ {
		for n%i == 0 {
			n /= i
			m[i]++
		}
	}
	if n != 1 {
		m[n]++
	}
	return m
}

var mod = 1000000007

func setMintMod(x int) {
	mod = x
}

type mint int

func newMint(v int) mint {
	return mint((v%mod + mod) % mod)
}

func (x mint) Add(y mint) mint {
	v := x + y
	if v >= mint(mod) {
		return v - mint(mod)
	}
	return v
}

func (x mint) Sub(y mint) mint {
	v := x + mint(mod) - y
	if v >= mint(mod) {
		return v - mint(mod)
	}
	return v
}

func (x mint) Mul(y mint) mint {
	return (x * y) % mint(mod)
}

func (x mint) pow(n int) mint {
	if n == 0 {
		return mint(1)
	}
	a := x.pow(n >> 1)
	a = a.Mul(a)
	if n&1 != 0 {
		a = a.Mul(x)
	}
	return a
}

func (x mint) Inverse() mint {
	return x.pow(mod - 2)
}

func (x mint) Div(y mint) mint {
	return x * y.Inverse()
}

func (x mint) Neg() mint {
	return newMint(int(-x))
}

type factorial struct {
	fact        []mint
	factInverse []mint
}

func newFactorial(n int) *factorial {
	f := new(factorial)
	f.init(n)
	return f
}

func (f *factorial) init(n int) {
	fact := make([]mint, n+1, n+1)
	fact[0] = newMint(1)
	for i := 1; i <= n; i++ {
		fact[i] = fact[i-1].Mul(newMint(i))
	}

	inv := make([]mint, n+1, n+1)
	inv[n] = fact[n].Inverse()
	for i := n; i >= 1; i-- {
		inv[i-1] = inv[i].Mul(newMint(i))
	}

	f.fact = fact
	f.factInverse = inv
}

func (f *factorial) Get(n int) mint {
	return f.fact[n]
}

func (f *factorial) GetInverse(n int) mint {
	return f.factInverse[n]
}

func (f *factorial) Permutation(n, k int) mint {
	if k < 0 || n < k {
		return 0
	}
	return f.fact[n].Mul(f.factInverse[n-k])
}

func (f *factorial) Combination(n, k int) mint {
	if k < 0 || n < k {
		return 0
	}
	return f.fact[n].Mul(f.factInverse[k]).Mul(f.factInverse[n-k])
}

type sieve struct {
	n          int
	primes     []int
	maxFactors []int
}

func newSieve(n int) *sieve {
	s := &sieve{
		n:          n,
		primes:     []int{},
		maxFactors: make([]int, n+1, n+1),
	}
	s.init()
	return s
}

func (s *sieve) init() {
	s.maxFactors[0] = -1
	s.maxFactors[1] = -1
	for i := 2; i <= s.n; i++ {
		if s.maxFactors[i] != 0 {
			continue
		}
		s.primes = append(s.primes, i)
		s.maxFactors[i] = i
		for j := i * i; j <= s.n; j += i {
			if s.maxFactors[j] == 0 {
				s.maxFactors[j] = i
			}
		}
	}
}

func (s *sieve) IsPrime(x int) bool {
	return s.maxFactors[x] == x
}

func (s *sieve) Factor(x int) map[int]int {
	m := map[int]int{}
	for x != 1 {
		m[s.maxFactors[x]]++
		x /= s.maxFactors[x]
	}
	return m
}


//go:generate echo "https://atcoder.jp/contests/abc159/tasks/abc159_b"
package main

import (
	"bufio"
	"fmt"
	"io"
	"math/big"
	"os"
	"strconv"
)

var scan = newScanner(os.Stdin)

func Solve(S string) bool {
	isPalindrome := func(s string) bool {
		for l, r := 0, len(s)-1; l < r; l, r = l+1, r-1 {
			if s[l] != s[r] {
				return false
			}
		}
		return true
	}
	return isPalindrome(S) && isPalindrome(S[0:(len(S)-1)/2]) && isPalindrome(S[(len(S)+3)/2+1:])
}

func main() {
	S := scan.String()
	if Solve(S) {
		fmt.Println("Yes")
	} else {
		fmt.Println("No")
	}
}

type scanner struct {
	*bufio.Scanner
}

func newScanner(r io.Reader) *scanner {
	s := bufio.NewScanner(r)
	s.Split(bufio.ScanWords)
	s.Buffer(nil, 100000000)
	return &scanner{s}
}

func (s *scanner) String() string {
	s.Scan()
	return s.Text()
}

func (s *scanner) Strings(l int) []string {
	if l == 0 {
		return []string{}
	}
	sl := make([]string, l, l)
	for i := range sl {
		sl[i] = s.String()
	}
	return sl
}

func (s *scanner) Int() int {
	n, _ := strconv.Atoi(s.String())
	return n
}

func (s *scanner) Ints(l int) []int {
	if l == 0 {
		return []int{}
	}
	sl := make([]int, l, l)
	for i := range sl {
		sl[i] = s.Int()
	}
	return sl
}

func (s *scanner) Float64() float64 {
	f, _ := strconv.ParseFloat(s.String(), 64)
	return f
}

func (s *scanner) Floats64(l int) []float64 {
	if l == 0 {
		return []float64{}
	}
	sl := make([]float64, l, l)
	for i := range sl {
		sl[i] = s.Float64()
	}
	return sl
}

func (s *scanner) BigInt() *big.Int {
	n, _ := strconv.ParseInt(s.String(), 10, 64)
	return big.NewInt(n)
}

func (s *scanner) BigInts(l int) []*big.Int {
	if l == 0 {
		return []*big.Int{}
	}
	sl := make([]*big.Int, l, l)
	for i := range sl {
		sl[i] = s.BigInt()
	}
	return sl
}

func iabs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

func imax(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func imin(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func ipow(x, n int) int {
	if n == 0 {
		return 1
	}
	a := ipow(x, n>>1)
	a *= a
	if n&1 != 0 {
		a *= x
	}
	return a
}

func chmax(x *int, v int) {
	if *x < v {
		*x = v
	}
}

func chmin(x *int, v int) {
	if *x > v {
		*x = v
	}
}

func factor(n int) map[int]int {
	m := map[int]int{}
	for i := 2; i*i <= n; i++ {
		for n%i == 0 {
			n /= i
			m[i]++
		}
	}
	if n != 1 {
		m[n]++
	}
	return m
}

var mod = 1000000007

func setMintMod(x int) {
	mod = x
}

type mint int

func newMint(v int) mint {
	return mint((v%mod + mod) % mod)
}

func (x mint) Add(y mint) mint {
	v := x + y
	if v >= mint(mod) {
		return v - mint(mod)
	}
	return v
}

func (x mint) Sub(y mint) mint {
	v := x + mint(mod) - y
	if v >= mint(mod) {
		return v - mint(mod)
	}
	return v
}

func (x mint) Mul(y mint) mint {
	return (x * y) % mint(mod)
}

func (x mint) pow(n int) mint {
	if n == 0 {
		return mint(1)
	}
	a := x.pow(n >> 1)
	a = a.Mul(a)
	if n&1 != 0 {
		a = a.Mul(x)
	}
	return a
}

func (x mint) Inverse() mint {
	return x.pow(mod - 2)
}

func (x mint) Div(y mint) mint {
	return x * y.Inverse()
}

func (x mint) Neg() mint {
	return newMint(int(-x))
}

type factorial struct {
	fact        []mint
	factInverse []mint
}

func newFactorial(n int) *factorial {
	f := new(factorial)
	f.init(n)
	return f
}

func (f *factorial) init(n int) {
	fact := make([]mint, n+1, n+1)
	fact[0] = newMint(1)
	for i := 1; i <= n; i++ {
		fact[i] = fact[i-1].Mul(newMint(i))
	}

	inv := make([]mint, n+1, n+1)
	inv[n] = fact[n].Inverse()
	for i := n; i >= 1; i-- {
		inv[i-1] = inv[i].Mul(newMint(i))
	}

	f.fact = fact
	f.factInverse = inv
}

func (f *factorial) Get(n int) mint {
	return f.fact[n]
}

func (f *factorial) GetInverse(n int) mint {
	return f.factInverse[n]
}

func (f *factorial) Permutation(n, k int) mint {
	if k < 0 || n < k {
		return 0
	}
	return f.fact[n].Mul(f.factInverse[n-k])
}

func (f *factorial) Combination(n, k int) mint {
	if k < 0 || n < k {
		return 0
	}
	return f.fact[n].Mul(f.factInverse[k]).Mul(f.factInverse[n-k])
}

type sieve struct {
	n          int
	primes     []int
	maxFactors []int
}

func newSieve(n int) *sieve {
	s := &sieve{
		n:          n,
		primes:     []int{},
		maxFactors: make([]int, n+1, n+1),
	}
	s.init()
	return s
}

func (s *sieve) init() {
	s.maxFactors[0] = -1
	s.maxFactors[1] = -1
	for i := 2; i <= s.n; i++ {
		if s.maxFactors[i] != 0 {
			continue
		}
		s.primes = append(s.primes, i)
		s.maxFactors[i] = i
		for j := i * i; j <= s.n; j += i {
			if s.maxFactors[j] == 0 {
				s.maxFactors[j] = i
			}
		}
	}
}

func (s *sieve) IsPrime(x int) bool {
	return s.maxFactors[x] == x
}

func (s *sieve) Factor(x int) map[int]int {
	m := map[int]int{}
	for x != 1 {
		m[s.maxFactors[x]]++
		x /= s.maxFactors[x]
	}
	return m
}


s = gets.chomp
n = s.size

s1 = s[0,(n-1)/2]
s2 = s[(n+1)/2..-1]

if s === s.reverse && s1 === s1.reverse && s2 === s2.reverse
  puts "Yes"
else
  puts "No"
end


s = gets.chomp
n = s.size
ss = s[0...n/2]
sss = s[(n/2+1)...n]

if s == s.reverse && ss == ss.reverse && sss == sss.reverse
  puts "Yes"
else
  puts "No"
end


s = gets.chomp
n = s.length
v = s[0..((n - 1) / 2) - 1]
w = s[(((n + 3) / 2) - 1)..n]

if (s == s.reverse) && (v == v.reverse) && (w == w.reverse)
  puts "Yes"
else
  puts "No"
end


s = gets.chomp.chars
i = 0
while i < s.size/2
  puts s[i]
  puts s[((s.size - 1)/2)-i-1]
  puts s[s.size - i - 1]
  puts s[(s.size + 3)/2+i-1]
  unless (s[i] == s[((s.size - 1)/2)-i-1]) && (s[i] == s[s.size - i - 1]) && (s[i] == s[(s.size + 3)/2+i-1])
    break
  end
  i += 1
end
if i == s.size/2
  puts "Yes"
else
  puts "No"
end


s = gets.chomp.split("").map(&:to_s);
sl=s.length

ans = "Yes"

ck1 = s.slice(0..(sl/2)-1)
ck2 = s.slice(((sl/2)+1)..sl-1).reverse

if (ck1!=ck2) then
	ans = "No"
end

#check2
s2 = s.slice(0..(sl/2)-1)
s2l=s2.length

if s2l%2==0 then
	ck3 = s2.slice(0..(s2l/2))
	ck4 = s2.reverse.slice(0..(s2l/2))
	if ck3 != ck4 then
		ans ="No"
	end

else
	ck3 = s2.slice(0..(s2l/2)-1)
	ck4 = s2.revers.slice(0..(s2l/2)-1)
	if ck3 != ck4 then
		ans ="No"
	end
end

puts ans


s = gets.chomp.split("").map(&:to_s);
sl=s.length

ans = "Yes"

ck1 = s.slice(0..(sl/2)-1)
ck2 = s.slice(((sl/2)+1)..sl-1).reverse

if (ck1!=ck2) then
	ans = "No"
end

#check2
s2 = s.slice(0..(sl/2)-1)
s2l=s2.length

if s2l%2==0 then
	ck3 = s2.slice(0..(s2l/2))
	ck4 = s2.slice(((s2l/2)+1)..s2l-1).reverse
	if ck3 != ck4 then
		ans ="No"
	end
else
	ck3 = s2.slice(0..(s2l/2)-1)
	ck4 = s2.slice(((s2l/2)+1)..s2l-1).reverse
	if ck3 != ck4 then
		ans ="No"
	end
end
puts ans


use std::io::Read;

fn main() {
    let mut buf = String::new();
    std::io::stdin().read_to_string(&mut buf).unwrap();

    let answer = solve(&buf);

    println!("{}", answer);
}

fn solve(input: &str) -> String {
    let mut iterator = input.split_whitespace();

    let s: Vec<char> = iterator.next().unwrap().chars().collect();
    let n = s.len();
    for i in 0..(n / 2) {
        if s[i] != s[n - 1 - i] {
            return "No".to_string();
        }
    }
    for i in 0..(n / 4) {
        if s[i] != s[n / 2 - 1 - i] {
            return "No".to_string();
        }
        if s[n / 2 + 1 + i] != s[n - 1 - i] {
            return "No".to_string();
        }
    }

    return "Yes".to_string();
}


/* {{{ */
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}
/* }}} */

fn main() {
    input! {
        s: chars
    }
    let n = s.len();
    let f = |a: &[char]| -> bool {
        let mut b = Vec::from(a);
        b.reverse();
        a.iter().zip(b.iter()).all(|(a,b)| a == b)
    };
    if f(&s) && f(&s[0..(n/2)]) && f(&s[(n/2+1)..n]) {
        println!("Yes");
    } else {
        println!("No");
    }
}
/* vim:set foldmethod=marker: */


fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn main() {
    let s:String = read();
    let s:Vec<_> = s.chars().collect();
    let n = s.len();

    let parin = |xs:&[_]| {
        let n = xs.len();
        for i in 0..(n/2) {
            if xs[i] != xs[n-i-1] {
                return false
            }
        }
        true
    };

    let flg = parin(&s[..]);
    let flg = flg && parin(&s[..(n-1)/2]);
    let flg = flg && parin(&s[(n+1)/2..]);

    println!("{}", if flg { "Yes" } else { "No" });
}