// Slower C++ solution:
#include <bits/stdc++.h>

#define rep(i,n) for (int i = 0; i < (n); i++)

#define repf(i,a,b) for (int i = (a); i < (b); i++)

#define repi(i,a,b) for (int i = (a); i <= (b); i++)

#define repr(i,a,b) for (int i = (a); i >= (b); i--)

#define all(x) (x).begin(),(x).end()

#define rall(x) (x).rbegin(),(x).rend()

#define debug(x)  cout << #x << " = " << (x) << endl;

#define SORT(x) sort(all(x));

#define RSORT(x) sort(rall(x));

using namespace std;

using ll = long long;

using vi = vector<int>;

using vvi = vector<vi>;

using vd = vector<double>;

using vb = vector<bool>;

using pii = pair<int, int>;

using vc = vector<char>;

using vvc = vector<vc>;

using vs = vector<string>;

using tiii = tuple<int, int, int>;

const int inf = 1<<29;

const ll mod = 1000000007;

const double eps = 1e-9;

const int dx[4] = {1,0,-1,0};

const int dy[4] = {0,1,0,-1};

//cout << fixed << setprecision(10);



ll N, x[1009], y[1009], h[1009]; vector<tuple<ll,ll,ll>> vec;



int main () {

  cin >> N;

  tuple<ll,ll,ll> G = make_tuple(-1,-1,-1);



  for (int i = 1; i <= N; i++) {

    cin >> x[i] >> y[i] >> h[i];

    if (h[i] >= 1) G = make_tuple(x[i],y[i],h[i]);

  }

  for(int Cx = 0; Cx <= 100; Cx++) {

    for (int Cy = 0; Cy <= 100; Cy++) {

      ll H = get<2>(G) + abs(get<0>(G)-Cx) + abs(get<1>(G)-Cy);

      H = max(H,0LL);

      bool flag = true;

      for (int i = 1; i <= N; i++) {

        ll hh = H - abs(x[i]-Cx) - abs(y[i]-Cy);

        hh = max(hh,0LL);

        if (h[i] != hh) flag = false;

      }

      if(flag == true) vec.push_back(make_tuple(Cx,Cy,H));

    }

  }



  if (vec.size() == 1) {

    cout << get<0>(vec[0]) << " " << get<1>(vec[0]) << " " << get<2>(vec[0]) << endl;

  }

}

// Faster C++ solution for the same problem (measured speedup: 1.130373456337828x):
#include <bits/stdc++.h>

#define rep(i,n) for (int i = 0; i < (n); i++)

#define repf(i,a,b) for (int i = (a); i < (b); i++)

#define repi(i,a,b) for (int i = (a); i <= (b); i++)

#define repr(i,a,b) for (int i = (a); i >= (b); i--)

#define all(x) (x).begin(),(x).end()

#define rall(x) (x).rbegin(),(x).rend()

#define debug(x)  cout << #x << " = " << (x) << endl;

#define SORT(x) sort(all(x));

#define RSORT(x) sort(rall(x));

using namespace std;

using ll = long long;

using vi = vector<int>;

using vvi = vector<vi>;

using vd = vector<double>;

using vb = vector<bool>;

using pii = pair<int, int>;

using vc = vector<char>;

using vvc = vector<vc>;

using vs = vector<string>;

using tiii = tuple<int, int, int>;

const int inf = 1<<29;

const ll mod = 1000000007;

const double eps = 1e-9;

const int dx[4] = {1,0,-1,0};

const int dy[4] = {0,1,0,-1};

//cout << fixed << setprecision(10);



int main () {

  int N; cin >> N;

  vi x(N), y(N), h(N); rep(i,N) cin >> x[i] >> y[i] >> h[i];



  int MAX = 100;



  rep(Cy,MAX+1) {

    rep(Cx,MAX+1) {

      int needH = -1;

      rep(i,N) {

        if(h[i] > 0) {

          int tmp = h[i] + abs(Cy-y[i]) + abs(Cx-x[i]);

          if(needH == -1) {

            needH = tmp;

          }

          else {

            if(needH != tmp) {

              needH = -2;

              break;

            }

          }

        }

      }



      if(needH == -2) continue;



      rep(i,N) {

        if(h[i] == 0) {

          int dist = abs(Cy-y[i]) + abs(Cx-x[i]);

          if(needH > dist) {

            needH = -2;

            break;

          }

        }

      }

      if(needH == -2) continue;



      cout << Cx << " " << Cy << " " << needH << endl;

      return 0;

    }

  }



}