#include <bits/stdc++.h>
#pragma GCC optimize("O0")
using namespace std;

constexpr long MAX_P = 1000001;
bool isPrime[MAX_P];
long board[2000][2000];
long primeBoard[2000][2000];
bool use[1000][1000];
long score[2000][2000];
long bottom[2000][2000];

void make() {
  for (int i = 0; i < MAX_P; i++) isPrime[i] = 1;
  isPrime[0] = 0;
  isPrime[1] = 0;
  for (int i = 2; i < MAX_P; i++) {
    if (isPrime[i]) {
      for (int j = 2; i * j < MAX_P; j++) {
        isPrime[i * j] = 0;
      }
    }
  }
}

void test() {
  for (int i = 995; i < 1005; i++) {
    for (int j = 995; j < 1005; j++) {
      cout << board[i][j]<<":"<<score[i][j] << '\t';
    }
    cout << endl;
  }
}

void makeboards() {
  int dir = 0;
  // 0: right, 1: up, 2: left, 3: down
  int size = 2;
  long x = 1000;
  long y = 1000;
  int i = 1;
  while (i < MAX_P) {
    for (int k = 0; k < size / 2; k++) {
      assert(0 <= dir && dir < 4);
      switch (dir) {
        case 0:
        board[x][y + k] = i;
        primeBoard[x][y + k] = isPrime[i];
        break;
        case 1:
        board[x - k][y] = i;
        primeBoard[x - k][y] = isPrime[i];
        break;
        case 2:
        board[x][y - k] = i;
        primeBoard[x][y - k] = isPrime[i];
        break;
        case 3:
        board[x + k][y] = i;
        primeBoard[x + k][y] = isPrime[i];
        break;
      }
      i++;
    }
    assert(0 <= dir && dir < 4);
    switch (dir) {
      case 0:
      y += size / 2;
      break;
      case 1:
      x -= size / 2;
      break;
      case 2:
      y -= size / 2;
      break;
      case 3:
      x += size / 2;
      break;
    }
    size += 1;
    dir = (dir + 1) % 4;
  }
}

using P = pair<long, long>;

void solve(long m, long n) {
  long xmin = 2000;
  long xmax = 0;
  long ymin = 2000;
  long ymax = 0;
  for (long i = 0; i < 2000; i++) {
    for (long j = 0; j < 2000; j++) {
      use[i][j] = 0;
      score[i][j] = 0;
      bottom[i][j] = 0;
    }
  }
  for (long i = 0; i < 2000; i++) {
    for (long j = 0; j < 2000; j++) {
      if (board[i][j] && board[i][j] <= m) {
        use[i][j] = 1;
        xmin = min(xmin, i);
        xmax = max(xmax, i);
        ymin = min(ymin, j);
        ymax = max(ymax, j);
      }
    }
  }

  for (int i = xmax; i >= xmin; i--) {
    for (int j = ymin; j <= ymax; j++) {
      // cout << "searching" << board[i][j] << endl;
      if (score[i + 1][j - 1] + score[i + 1][j] + score[i + 1][j + 1] == 0 && primeBoard[i][j] * use[i][j]) {
        // cout << "hoge" << board[i][j] << endl;
        score[i][j] = 1;
        bottom[i][j] = board[i][j];
        continue;
      }
      vector<P> scores;
      scores.push_back(P(score[i + 1][j - 1], bottom[i + 1][j - 1]));
      scores.push_back(P(score[i + 1][j], bottom[i + 1][j]));
      scores.push_back(P(score[i + 1][j + 1], bottom[i + 1][j + 1]));
      sort(scores.begin(), scores.end(), greater<P>());
      if (primeBoard[i][j] * use[i][j]) {
        // cout << "hit!" << board[i][j] << endl;
        score[i][j] = scores[0].first + 1;
        // cout << scores[0].first << endl;
        // cout << score[i][j] << endl;
        bottom[i][j] = scores[0].second;
      } else {
        score[i][j] = scores[0].first;
        bottom[i][j] = scores[0].second;
      }
    }
  }

  for (int i = 0; i < 2000; i++) {
    for (int j = 0; j < 2000; j++) {
      if (board[i][j] == n) {
        cout << score[i][j] << " " << bottom[i][j] << endl;
        // test();
        // exit(1);
        return;
      }
    }
  }
}

int main() {
  long m, n;
  make();
  makeboards();
  while (1) {
    cin >> m >> n;
    if (m + n == 0) return 0;
    solve(m, n);
  }
}



Measured memory_bytes: 91308