//spnauti-rusT
use std::io::*;
use std::str::{self,*};
use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_macros)]
macro_rules! m {
    ($c:tt, $x:expr, $y:expr) => {{
        let b = $y; let a = &mut $x;
        if b $c *a { *a = b; true } else { false }
    }};
}
#[allow(unused_macros)]
macro_rules! l {
    ($($v:ident),* = $i:ident.$f:ident $a:tt) => {
        $( let $v = $i.$f$a; )*
    };
    ($($v:ident),*:$t:ty = $i:ident.$f:ident $a:tt) => {
        $( let $v:$t = $i.$f$a; )*
    };
}
struct WordReader<'a> { it : SplitAsciiWhitespace<'a> }
#[allow(dead_code)]
impl<'a> WordReader<'a> {
    fn new<T: Read>(b: &mut String, mut r: T) -> WordReader {
        b.clear();
        r.read_to_string(b).ok();
        WordReader { it: b.split_ascii_whitespace() }
    }
    fn from_stdin(b: &mut String) -> WordReader {
        WordReader::new(b, stdin())
    }
    fn sl(&mut self) ->  &str { self.it.next().unwrap() }
    fn bs(&mut self) -> &[u8] { self.sl().as_bytes()    }
    fn s(&mut self) -> String { String::from(self.sl()) }
    fn i(&mut self) ->    i32 { self.p()                }
    fn f(&mut self) ->    f64 { self.p()                }
    fn u(&mut self) ->  usize { self.p()                }
    fn sk(&mut self, n: usize) { self.it.nth(n - 1); }
    fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> {
        self.ip(n).into_iter()
    }
    fn vi(&mut self, n: usize) -> Vec<i32> {
        self.vp::<i32>(n)
    }
    fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
        self.sl().parse::<T>().unwrap()
    }
    fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
        self.vp(n).into_iter()
    }
    fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
        (0..n).map(|_| self.p()).collect()
    }
}
//------------------- End rusT

fn main() {
    let mut bin = String::new();
    let mut input = WordReader::from_stdin(&mut bin);

    l!(a,b = input.u());
    for i in a..=b {
        let mut x = i;
        let mut c = [0; 10];
        while x > 0 {
            c[x % 10] += 1;
            x /= 10;
        }
        if c.iter().max().unwrap() == &1 {
            println!("{}", i);
            return;
        }
    }
    println!("-1");
}

#[allow(unused_imports)]
use std::io::{BufReader, BufWriter, stdin, stdout, Write};
use std::cmp::{min, max};
use std::collections::{VecDeque, HashMap, BTreeMap, HashSet, BTreeSet, BinaryHeap};

fn check(mut x:i64) -> bool {
	let mut ch = vec![false; 10];
	while x > 0 {
		if ch[(x % 10) as usize] {
			return false;
		}
		ch[(x % 10) as usize] = true;
		x /= 10;
	}
	return true;
}

fn main() {
	let mut inp = my_input::default();
	let out = &mut BufWriter::new(stdout());
	let l:i64 = inp.scan::<i64>();
	let r:i64 = inp.scan::<i64>();
	for i in l..r+1 {
		if check(i) {
			writeln!(out, "{}", i);
			return;
		}
	}
	writeln!(out, "-1");
}

#[derive(Default)]
struct my_input {
	buffer: Vec<String>
}

impl my_input {
	fn scan<T: std::str::FromStr>(&mut self) -> T {
		loop {
			if let Some(token) = self.buffer.pop() {
				return token.parse().ok().expect("Parsing Error");
			}
			let mut s = String::new();
			stdin().read_line(&mut s).expect("Reading Error");
			self.buffer = s.split_whitespace().rev().map(String::from).collect();
		}
	}
}

use std::io::{Read,stdin};

fn main() {
    let mut buf = String::new();
    stdin().read_to_string(&mut buf).unwrap();
    let mut tok = buf.split_whitespace();
    let mut get = || tok.next().unwrap();
    macro_rules! get {
        ($t:ty) => (get().parse::<$t>().unwrap());
        () => (get!(i64));
    }

    let l = get!(usize);
    let r = get!(usize);

    for x in l ..= r {
        let mut y = x;
        let mut f = vec![false; 10];
        let mut ok = true;
        while y > 0 {
            if f[y % 10] {
                ok = false;
                break;
            }
            f[y % 10] = true;
            y /= 10;
        }
        if ok {
            println!("{}", x);
            return;
        }
    }

    println!("-1");
}

use std::io::{self, BufRead, Write};
use std::str::{self, FromStr, SplitAsciiWhitespace};

fn main() {
    let stdin = io::stdin();
    solve(stdin.lock(), io::stdout());
}

type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;

struct Scanner<'a, R> {
    reader: R,
    buf_str: Vec<u8>,
    buf_iter: SplitAsciiWhitespace<'a>,
}

impl<R: BufRead> Scanner<'_, R> {
    pub fn new(reader: R) -> Self {
        Self {
            reader,
            buf_str: Vec::new(),
            buf_iter: "".split_ascii_whitespace(),
        }
    }

    fn try_token<T>(&mut self) -> Result<T>
        where T: FromStr,
              <T as FromStr>::Err: 'static + std::error::Error
    {
        loop {
            if let Some(token) = self.buf_iter.next() {
                return Ok(token.parse()?);
            }
            self.buf_str.clear();
            let bytes_read = self.reader
                .read_until(b'\n', &mut self.buf_str)?;
            if bytes_read == 0 {
                return Err(Box::new(io::Error::from(io::ErrorKind::UnexpectedEof)));
            }
            self.buf_iter = unsafe {
                let slice = str::from_utf8_unchecked(&self.buf_str);
                ::std::mem::transmute(slice.split_ascii_whitespace())
            }
        }
    }

    fn token<T>(&mut self) -> T
        where T: FromStr,
              <T as FromStr>::Err: 'static + std::error::Error
    {
        self.try_token().unwrap()
    }
}

fn solve<R: BufRead, W: Write>(input: R, mut output: W) {
    let mut scan = Scanner::new(input);

    let l: u32 = scan.token();
    let r: u32 = scan.token();
    let mut met;
    'numbers: for x in l..=r {
        met = [false; 10];
        let mut xx = x;
        while xx != 0 {
            let digit = (xx % 10) as usize;
            if met[digit] { continue 'numbers; }
            met[digit] = true;
            xx /= 10;
        }
        writeln!(output, "{}", x).unwrap();
        return;
    }
    writeln!(output, "-1").unwrap();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn example1() {
        let inp = &b"121 130\n"[..];
        let mut out = String::new();
        solve(inp, unsafe { out.as_mut_vec() });
        assert_eq!(out, "123\n");
    }

    #[test]
    fn example2() {
        let inp = &b"98766 100000\n"[..];
        let mut out = String::new();
        solve(inp, unsafe { out.as_mut_vec() });
        assert_eq!(out, "-1\n");
    }

    #[test]
    fn badhead() {
        let inp = &b"110 119\n"[..];
        let mut out = String::new();
        solve(inp, unsafe { out.as_mut_vec() });
        assert_eq!(out, "-1\n");
    }

    #[test]
    fn t() {
        let inp = &b"1211 1240\n"[..];
        let mut out = String::new();
        solve(inp, unsafe { out.as_mut_vec() });
        assert_eq!(out, "1230\n");
    }
}

//https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 より
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 run() {
    input! {
        l: usize,
        r: usize,
    }
    for x in l..=r {
        let s: Vec<char> = x.to_string().chars().collect();
        let k = s.len();
        let mut ok = true;
        for i in 0..k {
            for j in 0..i {
                if s[i] == s[j] {
                    ok = false;
                }
            }
        }
        if ok {
            println!("{}", x);
            return;
        }
    }
    println!("-1");
}

fn main() {
    run();
}

use std::io;

use std::collections::HashSet;

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let input: Vec<u32> = buf.trim().split(' ').map(|x| x.parse().unwrap()).collect();
    let (left, right) = (input[0], input[1]);
    let res = (left..=right)
        .map(|x| {
            let s = x.to_string();
            (
                x.to_string(),
                s.chars().collect::<HashSet<_>>().len(),
                s.chars().count(),
            )
        })
        .find(|(_, len1, len2)| len1 == len2);
    let res = match res {
        Some(r) => r.0,
        None => (-1).to_string(),
    };
    println!("{}", res);
}

struct Scan {
    buffer: std::collections::VecDeque<String>,
}

impl Scan {
    fn new() -> Scan {
        Scan {
            buffer: std::collections::VecDeque::new(),
        }
    }

    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop_front() {
                break token.parse::<T>().ok().unwrap();
            }
            let mut line = String::new();
            std::io::stdin().read_line(&mut line).expect("Fail to read");
            self.buffer = line.split_whitespace().map(String::from).collect();
        }
    }
}

fn is_good(x: usize) -> bool {
    let mut isused: [bool; 10] = [false; 10];
    let mut a = x;
    while a > 0 {
        let dig = a % 10;
        a /= 10;
        if isused[dig] {
            return false;
        }
        isused[dig] = true;
    }
    return true;
}

fn _main() {
    let mut scan = Scan::new();
    let l: usize = scan.next();
    let r: usize = scan.next();
    for i in l..=r {
        if is_good(i) {
            println!("{}", i);
            return;
        }
    }
    println!("-1");
}

fn main() {
    std::thread::Builder::new()
        .stack_size(1 << 23)
        .spawn(_main)
        .unwrap()
        .join()
        .unwrap();
}

fn ud(mut a: i32) -> bool {
    let mut m = 0;
    while a != 0 {
        let c = 1 << (a % 10);
        if m & c != 0 {
            return false;
        }
        m |= c;
        a /= 10;
    }
    true
}

fn solve(a: i32, b: i32) -> i32 {
    for i in a..=b {
        if ud(i) {
            return i;
        }
    }
    -1
}

fn main() {
    let mut buf = String::new();
    std::io::stdin().read_line(&mut buf).unwrap();
    let mut it = buf.trim().split_whitespace();
    println!(
        "{}",
        solve(
            it.next().unwrap().parse().unwrap(),
            it.next().unwrap().parse().unwrap()
        )
    );
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_canonical() {
        assert_eq!(solve(121, 130), 123);
        assert_eq!(solve(98766, 100000), -1);
    }
}

use std::io;
use std::collections::HashSet;

// type Matrix = Vec<Vec<char>>;

fn read_line() -> String {
    let mut input_line = String::new();
    io::stdin().read_line(&mut input_line).unwrap();
    return String::from(input_line.trim());
}

fn read_line_vec() -> Vec<i64> {
    return read_line().split(' ')
        .map(|s| s.parse().unwrap())
        .collect();
}

fn read_line_pair() -> (i64, i64) {
    let vec = read_line_vec();
    return (vec[0], vec[1]);
}

fn is_diff(n: i64) -> bool {
    let mut nn = n;
    let mut hs = HashSet::new();
    while nn > 0 {
        let ni = nn % 10;
        nn /= 10;
        if hs.contains(&ni) {
            return false;
        }
        hs.insert(ni);
    }
    return true;
}

fn has(l: i64, r: i64) -> Option<i64> {
    for i in l..(r+1) {
        if is_diff(i) {
            return Some(i);
        }
    }
    return None;
}

fn main() {
    let (l, r) = read_line_pair();

    // let r = is_diff(1101231);

    match has(l, r) {
        Some(n) => println!("{}", n),
        None => println!("-1")
    }

    // println!("{:?}", r);

}

#![allow(unused_imports, unused_macros, dead_code)]

macro_rules! min {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| min!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = min!($($ys),*);
        if $x < t { $x } else { t }
    }}
}
macro_rules! max {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| max!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = max!($($ys),*);
        if $x > t { $x } else { t }
    }}
}

macro_rules! ewriteln {
    ($($args:expr),*) => { let _ = writeln!(&mut std::io::stderr(), $($args),*); };
}
macro_rules! trace {
    ($x:expr) => { ewriteln!(">>> {} = {:?}", stringify!($x), $x) };
    ($($xs:expr),*) => { trace!(($($xs),*)) }
}
macro_rules! put {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        if let Some(x) = it.next() { print!("{}", x); }
        for x in it { print!(" {}", x); }
        println!("");
    }};
    ($x:expr) => { println!("{}", $x) };
    ($x:expr, $($xs:expr),*) => { print!("{} ", $x); put!($($xs),*) }
}

fn ok(a: usize) -> bool {
    let mut a = a;
    let mut d = vec![];
    while a > 0 {
        d.push(a % 10);
        a /= 10;
    }
    use std::collections::HashSet;
    let s : HashSet<_> = d.iter().collect();
    d.len() == s.len()
}

fn main() {
    let mut sc = Scanner::new();
    let n: usize = sc.cin();
    let m: usize = sc.cin();
    for a in n..m+1 {
        if ok(a) {
            put!(a);
            return;
        }
    }
    put!(-1);
}

use std::io::{self, Write};
use std::str::FromStr;
use std::collections::VecDeque;

struct Scanner { stdin: io::Stdin, buffer: VecDeque<String>, }
impl Scanner {
    fn new() -> Self { Scanner { stdin: io::stdin(), buffer: VecDeque::new() } }
    fn cin<T: FromStr>(&mut self) -> T {
        while self.buffer.len() == 0 {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
        self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
    }
}

#[allow(unused_imports)]
use std::cmp::{max, min};
use std::collections::HashSet;

type GenError = Box<dyn std::error::Error>;
type GenResult<T> = Result<T, GenError>;

struct Reader {}

impl Reader {
    #[allow(unused)]
    fn read_string() -> GenResult<String> {
        let mut string: String = String::new();
        std::io::stdin().read_line(&mut string)?;
        Ok(string.trim().to_string())
    }

    #[allow(unused)]
    fn read_tokens() -> GenResult<Vec::<String>> {
        let mut string: String = String::new();
        std::io::stdin().read_line(&mut string)?;
        let mut v = Vec::new();
        for value in string.split_whitespace() {
            v.push(value.to_string());
        }
        Ok(v)
    }
}

fn main() {
    let tokens = Reader::read_tokens().unwrap();
    let n: i32 = tokens[0].parse().unwrap();
    let m: i32 = tokens[1].parse().unwrap();
    for value in n .. m + 1 {
        let mut chars = HashSet::new();
        let string = value.to_string();
        for ch in string.chars(){
            chars.insert(ch);
        }
        if chars.len() == string.len() {
            println!("{}", string);
            return;
        }
    }
    println!("{}", -1);
}

use std::io;
use std::collections::HashSet;

// type Matrix = Vec<Vec<char>>;

fn read_line() -> String {
    let mut input_line = String::new();
    io::stdin().read_line(&mut input_line).unwrap();
    return String::from(input_line.trim());
}

fn read_line_vec() -> Vec<i64> {
    return read_line().split(' ')
        .map(|s| s.parse().unwrap())
        .collect();
}

fn read_line_pair() -> (i64, i64) {
    let vec = read_line_vec();
    return (vec[0], vec[1]);
}

fn is_diff(n: i64) -> bool {
    let mut nn = n;
    let mut hs = HashSet::new();
    while nn > 0 {
        let ni = nn % 10;
        nn /= 10;
        if hs.contains(&ni) {
            return false;
        }
        hs.insert(ni);
    }
    return true;
}

fn has(l: i64, r: i64) -> Option<i64> {
    for i in l..r {
        if is_diff(i) {
            return Some(i);
        }
    }
    return None;
}

fn main() {
    let (l, r) = read_line_pair();

    // let r = is_diff(1101231);

    match has(l, r) {
        Some(n) => println!("{}", n),
        None => println!("-1")
    }

    // println!("{:?}", r);

}