#include <algorithm>
#include <bits/stdc++.h>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <map>
#include <utility>
#include <vector>

// lib/square.hpp
#ifndef SQUARE_HPP
#define SQUARE_HPP

/*
usage:

tools::square(5) => 25
*/

namespace tools {
  template <typename T>
  constexpr T square(const T x) {
    return x * x;
  }
}

#endif

// lib/util.hpp
#ifndef UTIL_HPP
#define UTIL_HPP


typedef std::int_fast64_t i64;
typedef std::uint_fast64_t u64;
typedef std::int_fast32_t i32;
typedef std::uint_fast32_t u32;

namespace tools {
  template <typename T>
  void read(std::vector<T>& vector, const typename std::vector<T>::size_type size) {
    vector.reserve(size);
    std::copy_n(std::istream_iterator<T>(std::cin), size, std::back_inserter(vector));
  }

  template <typename T, std::size_t N>
  void read(std::array<T, N>& array) {
    std::copy_n(std::istream_iterator<T>(std::cin), N, array.begin());
  }
}

#endif

// lib/prime_sieve.hpp
#ifndef PRIME_SIEVE_HPP
#define PRIME_SIEVE_HPP


/*
// primes are all primes less than or equal to 100
std::vector<std::int_fast64_t> primes = tools::prime_sieve<std::int_fast64_t>(100);
*/

namespace tools {
  template <typename T>
  std::vector<T> prime_sieve(const T n) {
    std::vector<bool> is_prime(n + 1, true);
    is_prime[0] = false;
    is_prime[1] = false;

    const T max = static_cast<T>(std::sqrt(n));
    for (T i = 2; i <= max; ++i) {
      if (is_prime[i]) {
        for (T j = i * 2; j <= n; j += i) {
          is_prime[j] = false;
        }
      }
    }

    std::vector<T> result;
    for (T i = 0; i <= n; ++i) {
      if (is_prime[i]) {
        result.push_back(i);
      }
    }
    return result;
  }
}

#endif

// lib/pow.hpp
#ifndef POW_H
#define POW_H


/*
usage:

tools::pow(2, 5) => 32
*/

namespace tools {
  template <typename T>
  constexpr T pow(const T base, const T exponent) {
    return exponent == 0
      ? 1
      : exponent % 2 == 0
        ? square(pow(base, exponent / 2))
        : pow(base, exponent - 1) * base;
  }
}

#endif

// lib/prime_factorization.hpp
#ifndef PRIME_FACTORIZATION_HPP
#define PRIME_FACTORIZATION_HPP


namespace tools {
  template <typename T>
  std::map<T, T> prime_factorization(T n) {
    std::map<T, T> result;
    for (const T& p : prime_sieve(static_cast<T>(std::sqrt(n)))) {
      while (n % p == static_cast<T>(0)) {
        ++result[p];
        n /= p;
      }
    }
    if (n > static_cast<T>(1)) {
      ++result[n];
    }
    return result;
  }
}

#endif

// lib/divisors.hpp
#ifndef DIVISORS_HPP
#define DIVISORS_HPP


namespace tools {
  template <typename T>
  std::vector<T> divisors(const T n) {
    const std::map<T, T> prime_factor_map = prime_factorization(n);
    std::vector<std::pair<T, T>> prime_factors;
    prime_factors.reserve(prime_factor_map.size());
    std::copy(prime_factor_map.begin(), prime_factor_map.end(), std::back_inserter(prime_factors));

    std::vector<std::size_t> indices(prime_factors.size(), 0);
    bool end = false;
    auto increment = [&prime_factors, &indices, &end]() {
      bool requires_next = true;
      for (std::size_t i = 0; i < indices.size() && requires_next; ++i) {
        ++indices[i];
        if (indices[i] <= prime_factors[i].second) {
          requires_next = false;
        } else {
          indices[i] = 0;
          requires_next = true;
        }
      }
      end = requires_next;
    };

    std::vector<T> result;
    for (; !end; increment()) {
      T divisor = 1;
      for (std::size_t i = 0; i < indices.size(); ++i) {
        divisor *= pow<T>(prime_factors[i].first, indices[i]);
      }
      result.push_back(divisor);
    }
    std::sort(result.begin(), result.end());
    return result;
  }
}

#endif

// main.cpp

int main() {
  i64 N, M;
  std::cin >> N >> M;
  const std::vector<i64> divisors = tools::divisors(M);
  std::cout << *std::lower_bound(divisors.rbegin(), divisors.rend(), M / N, std::greater<i64>()) << std::endl;
  return 0;
}

Measured memory_bytes: 256