// ternary operation
#[allow(unused_macros)]
macro_rules! _if {
  ($_test:expr, $_then:expr, $_else:expr) => {
    if $_test { $_then } else { $_else }
  };
  ($_test:expr, $_pat:pat, $_then:expr, $_else:expr) => {
    match $_test {
      $_pat => $_then,
      _     => $_else
    }
  };
}

use std::io::{ stdin, stdout, BufWriter, Write };

fn write_num<W>(w: &mut W, buf: &mut Vec<u8>, n: u64)
  where W: Write
{
  w.write(b" ").unwrap();
  my::u64_to_byte(buf, n);
  w.write(buf.as_slice()).unwrap();
}

fn itp1_5_d() {
  let stdin = stdin();
  let mut reader = my::AsciiReader::new(stdin.lock(), 8);

  let stdout = stdout();
  let mut writer = BufWriter::new(stdout.lock());
  let mut bytes = Vec::with_capacity(8);

  let n = reader.read_uint_until_lf::<usize>();
  for i in 1..n + 1 {
    let mut x = i;
    if x % 3 == 0 {
      write_num(&mut writer, &mut bytes, i as u64);
      continue;
    }
    while x > 0 {
      if x % 10 == 3 {
        write_num(&mut writer, &mut bytes, i as u64);
        break;
      }
      x /= 10;
    }
  }

  writer.write(b"\n").unwrap();
  writer.flush().unwrap();
}

fn main() {
  itp1_5_d();
}

mod my {

  #[allow(dead_code)]
  pub fn u64_to_byte(buf: &mut Vec<u8>, mut i: u64) {
    buf.clear();
    if i == 0 {
      buf.push(b'0');
      return;
    }

    while i > 0 {
      buf.push((i % 10) as u8 + b'0');
      i /= 10;
    }
    buf.reverse();
  }

  #[allow(dead_code)]
  pub fn i64_to_byte(buf: &mut Vec<u8>, mut i: i64) {
    buf.clear();
    if i == 0 {
      buf.push(b'0');
      return;
    }

    let mut negative = false;
    if i.is_negative() {
      negative = true;
      i = i.abs();
    }

    while i > 0 {
      buf.push((i % 10) as u8 + b'0');
      i /= 10;
    }
    if negative {
      buf.push(b'-');
    }
    buf.reverse();
  }

  //----------------------------------------------------------------------
  use std::io::BufRead;
  use std::fmt::Debug;
  use std::ops::{ Add, Sub, Mul, Neg };
  use std::str::{ self, FromStr };

  const SP: u8 = b' ';
  const LF: u8 = b'\n';

  #[allow(dead_code)]
  #[derive(Debug)]
  pub enum Direction {
    Horizontal,
    Vertical
  }

  #[derive(Debug)]
  pub struct AsciiReader<R> {
    input : R,
    buf   : Vec<u8>,
  }

  impl<R> AsciiReader<R>
    where R: BufRead
  {
    #[allow(dead_code)]
    pub fn new(input: R, capa: usize) -> Self {
      AsciiReader {
        input : input,
        buf   : Vec::with_capacity(capa),
      }
    }

    //--------------------------------------------------------------------
    fn read_until(&mut self, delim: u8) -> usize {
      self.buf.clear();
      self.input.read_until(delim, &mut self.buf).unwrap()
    }

    #[allow(dead_code)]
    pub fn read_until_lf(&mut self) -> &[u8] {
      self.read_until(LF);
      self.buf.as_slice()
    }

    #[allow(dead_code)]
    pub fn read_until_sp(&mut self) -> &[u8] {
      self.read_until(SP);
      self.buf.as_slice()
    }

    //--------------------------------------------------------------------
    fn parse_int<T>(&self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let len = self.buf.len();
      let mut i = 0;
      let mut n = T::default();
      let mut minus = false;

      if self.buf[i] == b'-' {
        minus = true;
        i += 1;
      } else if self.buf[i] == b'+' {
        i += 1;
      }

      while i < len && b'0' <= self.buf[i] && self.buf[i] <= b'9' {
        n = (n * T::from(10)) + T::from(self.buf[i] - b'0');
        i += 1;
      }

      _if!(minus,
        n.neg(),
        n)
    }

    fn parse_uint<T>(&self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let len = self.buf.len();
      let mut i = 0;
      let mut n = T::default();

      if self.buf[i] == b'+' {
        i += 1;
      }

      while i < len && b'0' <= self.buf[i] && self.buf[i] <= b'9' {
        n = (n * T::from(10)) + T::from(self.buf[i] - b'0');
        i += 1;
      }
      n
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_int_until_delim<T>(&mut self, delim: u8) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_until(delim);
      self.parse_int()
    }

    // s -> n
    #[allow(dead_code)]
    pub fn read_int_until_lf<T>(&mut self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_int_until_delim(LF)
    }

    // s -> n
    #[allow(dead_code)]
    pub fn read_int_until_sp<T>(&mut self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_int_until_delim(SP)
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_uint_until_delim<T>(&mut self, delim: u8) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_until(delim);
      self.parse_uint()
    }

    // s -> n
    #[allow(dead_code)]
    pub fn read_uint_until_lf<T>(&mut self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_uint_until_delim(LF)
    }

    // s -> n
    #[allow(dead_code)]
    pub fn read_uint_until_sp<T>(&mut self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_uint_until_delim(SP)
    }

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

    fn from_utf8_unchecked(&mut self) -> &str {
      unsafe { str::from_utf8_unchecked(&self.buf) }
    }

    fn parse_tok<T>(&mut self) -> T
      where T: FromStr + Debug,
            <T as FromStr>::Err: Debug
    {
      self.from_utf8_unchecked()
        .trim()
        .parse()
        .unwrap()
    }

    // s -> n
    #[allow(dead_code)]
    pub fn parse_until_delim<T>(&mut self, delim: u8) -> T
      where T: FromStr + Debug,
            <T as FromStr>::Err: Debug
    {
      self.read_until(delim);
      self.parse_tok()
    }

    // s -> n
    #[allow(dead_code)]
    pub fn parse_until_lf<T>(&mut self) -> T
      where T: FromStr + Debug,
            <T as FromStr>::Err: Debug
    {
      self.parse_until_delim(LF)
    }

    // s -> n
    #[allow(dead_code)]
    pub fn parse_until_sp<T>(&mut self) -> T
      where T: FromStr + Debug,
            <T as FromStr>::Err: Debug
    {
      self.parse_until_delim(SP)
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_int_vec<T>(&mut self, n: usize, dir: Direction) -> Vec<T>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let delim = _if!(dir, Direction::Horizontal, SP, LF);
      let mut vec = Vec::with_capacity(n);
      for _ in 0..n {
        vec.push(self.read_int_until_delim(delim));
      }
      vec
    }

    #[allow(dead_code)]
    pub fn read_uint_vec<T>(&mut self, n: usize, dir: Direction) -> Vec<T>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let delim = _if!(dir, Direction::Horizontal, SP, LF);
      let mut vec = Vec::with_capacity(n);
      for _ in 0..n {
        vec.push(self.read_uint_until_delim(delim));
      }
      vec
    }

    // horizontal
    //
    // N
    // s1 s2 s3, ..., sN -> [n1, n2, n3, ..., nN]
    #[allow(dead_code)]
    pub fn read_int_vec_h<T>(&mut self) -> Vec<T>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let n: usize = self.read_uint_until_lf();
      self.read_int_vec(n, Direction::Horizontal)
    }

  } // impl<R> AsciiReader<R>

} // mod my



Measured memory_bytes: 5012