#include <bits/stdc++.h>
using namespace std;
const double pi = acos(0.0) * 2.0;
const long double eps = 1e-10;
const int step[8][2] = {{-1, 0}, {0, 1}, {1, 0},  {0, -1},
                        {-1, 1}, {1, 1}, {1, -1}, {-1, -1}};
template <class T>
inline T abs1(T a) {
  return a < 0 ? -a : a;
}
template <typename t, typename t1>
t min1(t a, t1 b) {
  return a < b ? a : b;
}
template <typename t, typename... arg>
t min1(t a, arg... arr) {
  return min1(a, min1(arr...));
}
template <typename t, typename t1>
t max1(t a, t1 b) {
  return a > b ? a : b;
}
template <typename t, typename... arg>
t max1(t a, arg... arr) {
  return max1(a, max1(arr...));
}
inline int jud(double a, double b) {
  if (abs(a) < eps && abs(b) < eps)
    return 0;
  else if (abs1(a - b) / max(abs1(a), abs1(b)) < eps)
    return 0;
  if (a < b) return -1;
  return 1;
}
template <typename t>
inline int jud(t a, t b) {
  if (a < b) return -1;
  if (a == b) return 0;
  return 1;
}
template <typename it, typename t1>
inline int find(t1 val, it a, int na, bool f_small = 1, bool f_lb = 1) {
  if (na == 0) return 0;
  int be = 0, en = na - 1;
  if (*a <= *(a + na - 1)) {
    if (f_lb == 0)
      while (be < en) {
        int mid = (be + en + 1) / 2;
        if (jud(*(a + mid), val) != 1)
          be = mid;
        else
          en = mid - 1;
      }
    else
      while (be < en) {
        int mid = (be + en) / 2;
        if (jud(*(a + mid), val) != -1)
          en = mid;
        else
          be = mid + 1;
      }
    if (f_small && jud(*(a + be), val) == 1) be--;
    if (!f_small && jud(*(a + be), val) == -1) be++;
  } else {
    if (f_lb)
      while (be < en) {
        int mid = (be + en + 1) / 2;
        if (jud(*(a + mid), val) != -1)
          be = mid;
        else
          en = mid - 1;
      }
    else
      while (be < en) {
        int mid = (be + en) / 2;
        if (jud(*(a + mid), val) != 1)
          en = mid;
        else
          be = mid + 1;
      }
    if (!f_small && jud(*(a + be), val) == -1) be--;
    if (f_small && jud(*(a + be), val) == 1) be++;
  }
  return be;
}
template <class T>
inline T lowb(T num) {
  return num & (-num);
}
inline int bitnum(unsigned int nValue) { return __builtin_popcount(nValue); }
inline int bitnum(int nValue) { return __builtin_popcount(nValue); }
inline int bitnum(unsigned long long nValue) {
  return __builtin_popcount(nValue) + __builtin_popcount(nValue >> 32);
}
inline int bitnum(long long nValue) {
  return __builtin_popcount(nValue) + __builtin_popcount(nValue >> 32);
}
inline int bitmaxl(unsigned int a) {
  if (a == 0) return 0;
  return 32 - __builtin_clz(a);
}
inline int bitmaxl(int a) {
  if (a == 0) return 0;
  return 32 - __builtin_clz(a);
}
inline int bitmaxl(unsigned long long a) {
  int temp = a >> 32;
  if (temp) return 32 - __builtin_clz(temp) + 32;
  return bitmaxl(int(a));
}
inline int bitmaxl(long long a) {
  int temp = a >> 32;
  if (temp) return 32 - __builtin_clz(temp) + 32;
  return bitmaxl(int(a));
}
long long pow(long long n, long long m, long long mod = 0) {
  if (m < 0) return 0;
  long long ans = 1;
  long long k = n;
  while (m) {
    if (m & 1) {
      ans *= k;
      if (mod) ans %= mod;
    }
    k *= k;
    if (mod) k %= mod;
    m >>= 1;
  }
  return ans;
}
template <class t1, class t2>
inline void add(t1 &a, t2 b, int mod = -1) {
  if (mod == -1) mod = 1000000007;
  a += b;
  while (a >= mod) a -= mod;
  while (a < 0) a += mod;
}
template <class t>
void output1(t arr) {
  for (int i = 0; i < (int)arr.size(); i++) cerr << arr[i] << ' ';
  cerr << endl;
}
template <class t>
void output2(t arr) {
  for (int i = 0; i < (int)arr.size(); i++) output1(arr[i]);
}
set<int> ansx, ansy;
const int maxn = 100100;
int arr[2][maxn];
int larr[2];
int nqueries;
int get(int x, int y) {
  int rdis;
  printf("0 %d %d\n", x, y);
  fflush(stdout);
  scanf("%d", &rdis);
  return rdis;
}
bool in(int x, pair<int, int> r) { return x >= r.first && x <= r.second; }
void jud(pair<int, int> st) {
  bool flag = 1;
  for (int i = 0; i < 2; i++) {
    int p = -5231345 + rand();
    if (get(st.first, p) != 0) flag = 0;
  }
  if (flag) ansx.insert(st.first);
  flag = 1;
  for (int i = 0; i < 2; i++) {
    int p = -1563091 + rand();
    if (get(p, st.second) != 0) flag = 0;
  }
  if (flag) ansy.insert(st.second);
}
void justdoit(pair<int, int> &st, pair<int, int> d, pair<int, int> rx,
              pair<int, int> ry) {
  int rrd = get(st.first, st.second);
  srand(unsigned(time(NULL)));
  if (rrd == 0) {
    jud(st);
    st.first += d.first * rrd;
    st.second += d.second * rrd;
  } else {
    if (get(st.first + rrd * d.first, st.second) == 0) {
      ansx.insert(st.first + rrd * d.first);
    }
    if (get(st.first, st.second + rrd * d.second) == 0) {
      ansy.insert(st.second + rrd * d.second);
    }
    st.first += d.first * rrd;
    st.second += d.second * rrd;
  }
  while (in(st.first, rx) && in(st.second, ry)) {
    bool flag = 0;
    for (int rd = 1;
         in(st.first + rd * d.first, rx) && in(st.second + rd * d.second, ry);
         rd *= 2) {
      int rdis = get(st.first + rd * d.first, st.second + rd * d.second);
      if (rdis < rd) {
        flag = 1;
        if (rdis == 0) {
          jud(make_pair(st.first + (rd + rdis) * d.first,
                        st.second + (rd + rdis) * d.second));
        } else {
          int have = 0;
          if (in(st.first + (rd + rdis) * d.first, rx) &&
              get(st.first + (rd + rdis) * d.first,
                  st.second + rd * d.second) == 0) {
            ansx.insert(st.first + (rd + rdis) * d.first);
            have = 1;
          }
          if (!have || (in(st.second + (rd + rdis) * d.second, ry) &&
                        get(st.first + rd * d.first,
                            st.second + (rd + rdis) * d.second) == 0)) {
            ansy.insert(st.second + (rd + rdis) * d.second);
          }
        }
        st.second += (rd + rdis) * d.second;
        st.first += (rd + rdis) * d.first;
        break;
      }
    }
    if (!flag) break;
  }
}
int main() {
  pair<int, int> st = make_pair(-100000000, -100000000),
                 r = make_pair(-100000000, 100000000), r1;
  justdoit(st, make_pair(1, 1), r, r);
  printf("1 %d %d\n", (int)ansx.size(), (int)ansy.size());
  for (auto it : ansx) printf("%d ", it);
  puts("");
  for (auto it : ansy) printf("%d ", it);
  puts("");
  fflush(stdout);
  return 0;
}
