Problem:
Score : 100 points

Problem Statement

A programming competition site AtCode regularly holds programming contests.

The next contest on AtCode is called ABC, which is rated for contestants with ratings less than 1200.

The contest after the ABC is called ARC, which is rated for contestants with ratings less than 2800.

The contest after the ARC is called AGC, which is rated for all contestants.

Takahashi's rating on AtCode is R. What is the next contest rated for him?

Constraints

0 ≤ R ≤ 4208

R is an integer.

Input

Input is given from Standard Input in the following format:

R

Output

Print the name of the next contest rated for Takahashi (ABC, ARC or AGC).

Sample Input 1

1199

Sample Output 1

ABC

1199 is less than 1200, so ABC will be rated.

Sample Input 2

1200

Sample Output 2

ARC

1200 is not less than 1200 and ABC will be unrated, but it is less than 2800 and ARC will be rated.

Sample Input 3

4208

Sample Output 3

AGC

Solution in Rust (1.15.1) (judge verdict: Accepted)

// 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, BufReader };

fn abc104_a() {
  let stdin = stdin();
  let mut reader = my::ByteReader::with_capacity(8, BufReader::new(stdin.lock()));

  let stdout = stdout();
  let mut writer = BufWriter::new(stdout.lock());

  let r = reader.read_uint_until_lf::<usize>();

  if r < 1200 {
    writer.write(b"ABC\n").unwrap();
  } else if r < 2800 {
    writer.write(b"ARC\n").unwrap();
  } else {
    writer.write(b"AGC\n").unwrap();
  }

  writer.flush().unwrap();
}

fn main() {
  abc104_a();
}

//------------------------------------------------------------------------
mod my {

  #[allow(dead_code)]
  pub fn rotate_right(vec: &mut Vec<u8>) {
    if vec.len() <= 1 {
      return;
    }

    let len = vec.len() - 1;
    let tmp = vec[len];
    for i in 0..len {
      vec[len - i] = vec[len - i - 1];
    }
    vec[0] = tmp;
  }

  #[allow(dead_code)]
  pub fn rotate_left(vec: &mut Vec<u8>) {
    if vec.len() <= 1 {
      return;
    }

    let len = vec.len() - 1;
    let tmp = vec[0];
    for i in 0..len {
      vec[i] = vec[i + 1];
    }
    vec[len] = tmp;
  }

  //----------------------------------------------------------------------
  const PLUS_SIGN : u8 = b'+';
  const MINUS_SIGN: u8 = b'-';
  const ASCII_0   : u8 = b'0';
  const ASCII_9   : u8 = b'9';

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

  #[allow(dead_code)]
  pub fn is_ascii_digit(b: u8) -> bool {
    _if!(b >= ASCII_0 && b <= ASCII_9,
      true,
      false)
  }

  #[allow(dead_code)]
  pub fn is_ascii_uppercase(b: u8) -> bool {
    _if!(b >= b'A' && b <= b'Z',
      true,
      false)
  }

  #[allow(dead_code)]
  pub fn is_ascii_lowercase(b: u8) -> bool {
    _if!(b >= b'a' && b <= b'z',
      true,
      false)
  }

  #[allow(dead_code)]
  pub fn is_ascii_alphabetic(b: u8) -> bool {
    _if!(is_ascii_uppercase(b) || is_ascii_lowercase(b),
      true,
      false)
  }

  #[allow(dead_code)]
  pub fn to_ascii_lowercase(mut b: u8) -> u8 {
    if is_ascii_uppercase(b) {
      b += 0x20;
    }
    b
  }

  #[allow(dead_code)]
  pub fn to_ascii_uppercase(mut b: u8) -> u8 {
    if is_ascii_lowercase(b) {
      b -= 0x20;
    }
    b
  }

  //----------------------------------------------------------------------
  macro_rules! pub_fn_Int2Byte_from_ty {
    (uint, $($name:ident => $_type:ty),*) => {$(
      #[allow(dead_code)]
      pub fn $name(&mut self, mut i: $_type) -> &[u8] {
        self.buf.clear();
        if i == 0 {
          self.buf.push(ASCII_0);
          return self.buf.as_slice();
        }

        while i > 0 {
          self.buf.push((i % 10) as u8 + ASCII_0);
          i /= 10;
        }
        self.buf.reverse();
        self.buf.as_slice()
      }
    )*};

    (int, $($name:ident => $_type:ty),*) => {$(
      #[allow(dead_code)]
      pub fn $name(&mut self, mut i: $_type) -> &[u8] {
        self.buf.clear();
        if i == 0 {
          self.buf.push(ASCII_0);
          return self.buf.as_slice();
        }

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

        while i > 0 {
          self.buf.push((i % 10) as u8 + ASCII_0);
          i /= 10;
        }
        if negative {
          self.buf.push(MINUS_SIGN);
        }
        self.buf.reverse();
        self.buf.as_slice()
      }
    )*};
  }

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

  impl Int2Byte {
    #[allow(dead_code)]
    pub fn new() -> Self {
      Int2Byte {
        buf: Vec::new(),
      }
    }

    #[allow(dead_code)]
    pub fn with_capacity(capa: usize) -> Self {
      Int2Byte {
        buf: Vec::with_capacity(capa),
      }
    }

    pub_fn_Int2Byte_from_ty!(
      uint,
      from_usize => usize,
      from_u8    => u8,
      from_u16   => u16,
      from_u32   => u32,
      from_u64   => u64
    );

    pub_fn_Int2Byte_from_ty!(
      int,
      from_isize => isize,
      from_i8    => i8,
      from_i16   => i16,
      from_i32   => i32,
      from_i64   => i64
    );
  } // impl Int2Byte

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

  //----------------------------------------------------------------------
  #[allow(dead_code)]
  pub fn intersection<T>(mut x: (T, T), mut y: (T, T)) -> Option<(T, T)>
    where T: PartialOrd +
             Copy +
             Debug
  {
    if x.0 > x.1 {
      mem::swap(&mut x.0, &mut x.1);
    }
    if y.0 > y.1 {
      mem::swap(&mut y.0, &mut y.1);
    }

    if x.0 >= y.1 || x.1 <= y.0 {
      return None;
    }

    if x.0 < y.0 {
      x.0 = y.0;
    }
    if x.1 > y.1 {
      x.1 = y.1;
    }

    Some(x)
  }

  #[allow(dead_code)]
  pub fn gcd<T>(x: T, y: T) -> T
    where T: Rem<Output=T> +
             Default +
             PartialEq +
             Copy +
             Debug
  {
    _if!(y == T::default(),
      x,
      gcd(y, x % y))
  }

  //----------------------------------------------------------------------
  pub trait WriteWithDelim {
    fn write_delim(&mut self, buf: &[u8], delim: &[u8]) -> usize;
    fn write_sp(&mut self, buf: &[u8]) -> usize;
    fn write_lf(&mut self, buf: &[u8]) -> usize;
  }

  impl<W> WriteWithDelim for BufWriter<W>
    where W: Write
  {
    #[allow(dead_code)]
    fn write_delim(&mut self, buf: &[u8], delim: &[u8]) -> usize
    {
      self.write(buf).unwrap() +
      self.write(delim).unwrap()
    }

    #[allow(dead_code)]
    fn write_sp(&mut self, buf: &[u8]) -> usize
    {
      self.write_delim(buf, b" ")
    }

    #[allow(dead_code)]
    fn write_lf(&mut self, buf: &[u8]) -> usize
    {
      self.write_delim(buf, b"\n")
    }
  } // impl<W> WriteWithDelim for BufWriter<W>

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

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

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

  impl<R> ByteReader<R>
    where R: BufRead
  {
    #[allow(dead_code)]
    pub fn new(reader: R) -> Self {
      ByteReader {
        reader: reader,
        buf   : Vec::new(),
      }
    }

    #[allow(dead_code)]
    pub fn with_capacity(capa: usize, reader: R) -> Self {
      ByteReader {
        reader: reader,
        buf   : Vec::with_capacity(capa),
      }
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_1byte(&mut self) -> Option<u8> {
      self.buf.resize(1, 0);
      _if!(self.reader.read(&mut self.buf).unwrap() != 0,
        Some(self.buf[0]),
        None)
    }

    //--------------------------------------------------------------------
    fn read_until(&mut self, delim: u8) -> usize {
      self.buf.clear();
      self.reader.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()
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_byte_until_lf(&mut self) -> Vec<u8> {
      self.read_until(LF);
      let len = self.buf.len() - 1;
      if self.buf[len] == LF {
        self.buf.truncate(len);
      }
      self.buf.clone()
    }

    #[allow(dead_code)]
    pub fn read_string_until_lf(&mut self) -> String {
      unsafe { String::from_utf8_unchecked(self.read_byte_until_lf()) }
    }

    //--------------------------------------------------------------------
    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] == MINUS_SIGN {
        minus = true;
        i += 1;
      } else if self.buf[i] == PLUS_SIGN {
        i += 1;
      }

      while i < len && is_ascii_digit(self.buf[i]) {
        n = (n * T::from(10)) + T::from(self.buf[i] - ASCII_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] == PLUS_SIGN {
        i += 1;
      }

      while i < len && is_ascii_digit(self.buf[i]) {
        n = (n * T::from(10)) + T::from(self.buf[i] - ASCII_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 - 1 {
        vec.push(self.read_int_until_delim(delim));
      }
      vec.push(self.read_int_until_delim(LF));
      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 - 1 {
        vec.push(self.read_uint_until_delim(delim));
      }
      vec.push(self.read_uint_until_delim(LF));
      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)
    }

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

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

    // N M
    // s11 s12 s13 ... s1M
    // s21 s22 s23 ... s2M
    // s31 s32 s33 ... s3M
    //   :
    // sN1 sN2 sN3 ... sNM
    // -> [
    //      [n11, n12, n13, ..., n1M],
    //      [n21, n22, n23, ..., n2M],
    //      [n31, n32, n33, ..., n3M],
    //          :
    //      [nN1, nN2, nN3, ..., nNM],
    //    ]
    #[allow(dead_code)]
    pub fn read_int_vec2<T>(&mut self, n: usize, m: usize) -> Vec<Vec<T>>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let mut vec = Vec::with_capacity(n);
      for _ in 0..n {
        vec.push(self.read_int_vec(m, Direction::Horizontal));
      }
      vec
    }

  } // impl<R> ByteReader<R>

} // mod my