CodeEff/ECCO huggingface dataset:
# Original solution
N, M = list(map(int, input().split()))
to = [[] for _ in range(N)]

for _ in range(M):
    a, b = list(map(int, input().split()))
    a, b = a - 1, b - 1
    to[a].append(b)
    to[b].append(a)


res = 0
def dfs(v, seen):
    global res
    if seen == [1] * N:
        res += 1
        return
    for nv in to[v]:
        if not seen[nv]:
            seen[nv] = 1
            dfs(nv, seen)
            seen[nv] = 0


def main():
    seen = [0] * N
    seen[0] = 1
    dfs(0, seen)
    print(res)


if __name__ == "__main__":
    main()


# Optimized solution
N, M = list(map(int, input().split()))
to = [[] for _ in range(N)]

for _ in range(M):
    a, b = list(map(int, input().split()))
    a, b = a - 1, b - 1
    to[a].append(b)
    to[b].append(a)


def dfs(v, seen):
    if seen == [1] * N:
        return 1
    
    res = 0
    for nv in to[v]:
        if not seen[nv]:
            seen[nv] = 1
            res += dfs(nv, seen)
            seen[nv] = 0
    return res


def main():
    seen = [0] * N
    seen[0] = 1
    print((dfs(0, seen)))    


if __name__ == "__main__":
    main()
# Original solution
# coding: utf-8
count=0
def check(now,v,n):
    global count
    v[now]=1
    if sum(v)==n:
        count+=1
    else:
        for i in range(8):
            if v[i]==0 and g[now][i]==1:
                check(i,v[:],n)

n,m=list(map(int,input().split()))
g=[[0 for i in range(8)]for i in range(8)]
for i in range(m):
    a,b=list(map(int,input().split()))
    g[a-1][b-1]=1
    g[b-1][a-1]=1
check(0,[0,0,0,0,0,0,0,0][:],n)
print(count)

# Optimized solution
# coding: utf-8
count=0
def check(now,v,n):
    global count
    v[now]=1
    if sum(v)==n:
        count+=1
    else:
        for i in range(n):
            if v[i]==0 and g[now][i]==1:
                check(i,v[:],n)

n,m=list(map(int,input().split()))
g=[[0 for i in range(n)]for i in range(n)]
for i in range(m):
    a,b=list(map(int,input().split()))
    g[a-1][b-1]=1
    g[b-1][a-1]=1
check(0,[0 for i in range(n)],n)
print(count)
# Original solution
import itertools

N, M = list(map(int, input().split()))
ab = [0] * M
for i in range(M):
  ab[i] = list(map(int, input().split()))

perms = itertools.permutations(list(range(1, N+1)))
ans = 0
for perm in perms:
  if perm[0] != 1:
    continue
  is_goal = True
  for i in range(N-1):
    a = perm[i]
    b = perm[i+1]
    if not a < b:
      a, b = b, a
    if not [a, b] in ab:
      is_goal = False
  if is_goal:
    ans += 1

print(ans)


# Optimized solution
# https://img.atcoder.jp/abc054/editorial.pdf

N, M = list(map(int, input().split()))

graph = [[False for _ in range(N)] for i in range(N)]
for i in range(M):
  a, b = list(map(int, input().split()))
  graph[a-1][b-1] = graph[b-1][a-1] = True

def dfs(v, visited):
  all_visited = True
  for i in range(N):
    if not visited[i]:
      all_visited = False
      
  if all_visited:
    return 1
  
  ret = 0
  for i in range(N):
    if not graph[v][i]: continue
    if visited[i]: continue
    
    visited[i] = True
    ret += dfs(i, visited)
    visited[i] = False
  
  return ret

visited = [False] * N
visited[0] = True
ans = dfs(0, visited)
print(ans)
# Original solution
import sys
readline = sys.stdin.readline

N,M = list(map(int,readline().split()))
G = [[] for i in range(N)]

for i in range(M):
  a,b = list(map(int,readline().split()))
  G[a-1].append(b-1)
  G[b-1].append(a-1)
  
ans = 0
stack = []
stack.append([0,set()])
while stack:
  v,visited = stack.pop()
  if v in visited:
    continue
  visited2 = visited.copy()
  visited2.add(v)
  if len(visited2) == N:
    ans += 1
    continue
  for child in G[v]:
    stack.append([child,visited2])

print(ans)

# Optimized solution
import sys
readline = sys.stdin.readline

N,M = list(map(int,readline().split()))
G = [[] for i in range(N)]

for i in range(M):
  a,b = list(map(int,readline().split()))
  G[a - 1].append(b - 1)
  G[b - 1].append(a - 1)

stack = []
stack.append([0, set()])
ans = 0
while stack:
  v, visited = stack.pop()
  visited.add(v)
  if len(visited) == N:
    ans += 1
    continue
  for child in G[v]:
    if child in visited:
      continue
    visited_c = visited.copy()
    stack.append([child, visited_c])
  
print(ans)
# Original solution
import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time,queue,copy

sys.setrecursionlimit(10**7)
inf=10**20
mod=10**9+7
dd=[(-1,0),(0,1),(1,0),(0,-1)]
ddn=[(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x)-1 for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS(): return sys.stdin.readline().split()
def S(): return eval(input())

nmax=8
graph=[[False for __ in range(nmax)]for _ in range(nmax)]

def dfs(v,n,visited):
  visited[v]=True

  all_visited=True
  for i in range(n):
    if visited[i]==False:
      all_visited=False
  if all_visited:
    return 1

  ret=0
  for i in range(n):
    if graph[v][i]==False:
      continue
    if visited[i]:
      continue
    visited[i]=True
    ret+=dfs(i,n,visited)
    visited[i]=False

  return ret

def main():
  n,m=LI()
  for _ in range(m):
    a,b=LI()
    graph[a-1][b-1]=True
    graph[b-1][a-1]=True

  visited=[False for _ in range(n)]
  visited[0]=True
  return dfs(0,n,visited)

# main()
print((main()))


# Optimized solution
# https://atcoder.jp/contests/abc054/tasks/abc054_c

import math,itertools,fractions,heapq,bisect,sys,queue,copy

sys.setrecursionlimit(10**7)
inf=10**20
mod=10**9+7
dd=[(-1,0),(0,1),(1,0),(0,-1)]
ddn=[(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS(): return sys.stdin.readline().split()
def S(): return eval(input())

nmax=8
graph=[[False]*nmax for _ in range(nmax)]

def dfs(n,v,visited):
  all_visited=True
  for i in range(n):
    if visited[i]==False:
      all_visited=False
  if all_visited:
    return 1

  ret=0
  for i in range(n):
    if visited[i]:
      continue
    if graph[i][v]==False:
      continue
    visited[i]=True
    ret+=dfs(n,i,visited)
    visited[i]=False

  return ret

def main():
  n,m=LI()
  for _ in range(m):
    a,b=LI()
    a-=1
    b-=1
    graph[a][b]=True
    graph[b][a]=True

  visited=[False]*n
  visited[0]=True
  return dfs(n,0,visited)

# main()
print((main()))
# Original solution
# https://atcoder.jp/contests/abc054/tasks/abc054_c

import math,itertools,fractions,heapq,bisect,sys,queue,copy

sys.setrecursionlimit(10**7)
inf=10**20
mod=10**9+7
dd=[(-1,0),(0,1),(1,0),(0,-1)]
ddn=[(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS(): return sys.stdin.readline().split()
def S(): return eval(input())

nmax=8
graph=[[False]*nmax for _ in range(nmax)]

def dfs(n,v,visited):
  all_visited=True
  for i in range(n):
    if visited[i]==False:
      all_visited=False
  if all_visited:
    return 1

  ret=0
  for i in range(n):
    if visited[i]:
      continue
    if graph[i][v]==False:
      continue
    visited[i]=True
    ret+=dfs(n,i,visited)
    visited[i]=False

  return ret

def main():
  n,m=LI()
  for _ in range(m):
    a,b=LI()
    a-=1
    b-=1
    graph[a][b]=True
    graph[b][a]=True

  visited=[False]*n
  visited[0]=True
  return dfs(n,0,visited)

# main()
print((main()))


# Optimized solution
import math,itertools,fractions,heapq,collections,bisect,sys,queue,copy

sys.setrecursionlimit(10**7)
inf=10**20
mod=10**9+7
dd=[(-1,0),(0,1),(1,0),(0,-1)]
ddn=[(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
# def LF(): return [float(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def F(): return float(sys.stdin.readline())
def LS(): return sys.stdin.readline().split()
def S(): return eval(input())

N,M=LI()
graph=[[False]*8 for _ in range(8)]

for _ in range(M):
  a,b=LI()
  a-=1
  b-=1
  graph[a][b]=True
  graph[b][a]=True

def dfs(v,visited):
  all_visited=True
  for i in range(N):
    if not visited[i]:
      all_visited=False
  if all_visited:
    return 1

  ret=0
  for i in range(N):
    if not graph[v][i]:
      continue
    if visited[i]:
      continue
    visited[i]=True
    ret+=dfs(i,visited)
    visited[i]=False

  return ret

visited=[False]*N
visited[0]=True
print((dfs(0,visited)))
# Original solution
import itertools
 
N, M = list(map(int, input().split()))
graph = [[0] * N for i in range(N)]
for i in range(M):
    a, b = list(map(int, input().split()))
    graph[a-1][b-1] = 1
    graph[b-1][a-1] = 1
 
p = list(itertools.permutations(list(range(N))))
 
Sum = 0
 
for i in range(len(p)):
    if p[i][0] != 0:
        break
    for j in range(N - 1):
        if graph[p[i][j]][p[i][j + 1]] != 1:
            break
        elif j == N - 2:
            Sum += 1
 
print(Sum)

# Optimized solution
N, M = list(map(int, input().split()))

g = [[] for _ in range(N)]

for i in range(M):
  a, b = list(map(int, input().split()))
  g[a-1].append(b-1)
  g[b-1].append(a-1)

visited = [False for _ in range(N)]

def dfs(v, visited):
  if all(visited):
    return 1
  total = 0
  for cv in g[v]:
    if not visited[cv]:
      visited[cv] = True
      total += dfs(cv, visited)
      visited[cv] = False
  return total
    
visited[0] = True
ret = dfs(0, visited)
print(ret)
# Original solution
import itertools
N, M = list(map(int, input().split()))
E = set([tuple(sorted(map(int, input().split()))) for x in range(M)])
cnt = 0
for i in itertools.permutations(list(range(2,N+1)), N-1):
    l = [1]+list(i)
    if sum(1 for x in range(N-1) if tuple(sorted(l[x:x+2])) in E) == N-1:
        cnt += 1
print(cnt)

# Optimized solution
import itertools
N, M = list(map(int, input().split()))
D = {tuple(sorted(map(int, input().split()))) for x in range(M)}
cnt = 0
for i in itertools.permutations(list(range(2, N+1)), N-1):
    l = [1]+list(i)
    cnt += sum(1 for x in zip(l,l[1:]) if tuple(sorted(x)) in D) == N-1
print(cnt)
# Original solution
# ABC054 C One-stroke Path
N,M = list(map(int, input().split()))

G = [[] for _ in range(N)]
reached = [False]*N

for _ in range(M):
    a,b = list(map(int, input().split()))
    G[a-1].append(b-1)
    G[b-1].append(a-1)

cnt = 0

def DFS(x):

    global cnt
    global reached

    reached[x] = True
 
    if all(reached):
        cnt += 1
        reached[x] = False
 
        return

    for i in G[x]:
        if reached[i]:
            continue

        else:
            DFS(i)

    reached[x] = False

DFS(0)
print(cnt)

# Optimized solution
#ABC054 C - One-stroke Path

# v：現在の頂点 seen:訪問済みの頂点
def dfs(v,seen):
    if all(seen):
        return 1
    res = 0
    # 頂点ｖに隣接しているnvを探索していく
    for nv in G[v]:
        if seen[nv]:
            continue
        seen[nv]=True
        res += dfs(nv,seen)
        # 次の隣接頂点nvを探索した時の探索経路で、
        # 今回探索した隣接頂点nv通る可能性があるので
        # 元に戻しておく
        seen[nv]=False
    return res

n,m = list(map(int, input().split()))
G = [[] for _ in range(n)]
seen = [False]*n
res = 0

for i in range(m):
    a,b = list(map(int, input().split()))
    G[a-1].append(b-1)
    G[b-1].append(a-1)

# 頂点1を訪問済みとして探索を開始する
seen[0]=True
print((dfs(0,seen)))
# Original solution
n,m=list(map(int,input().split()))
G=[[0]*n for i in range(n)]
for i in range(m):
  a,b=list(map(int,input().split()))
  G[a-1][b-1]=G[b-1][a-1]=1

from itertools import permutations
ans=0
p=list(permutations([x for x in range(1,n)]))
for pp in p:
  ok=True
  t=[0]+list(pp)
  for i in range(1,n):
    if G[t[i-1]][t[i]]==0:
      ok=False
  if ok:ans+=1
print(ans)


# Optimized solution
def dfs(v,visited):
  if all(visited):
    return 1
  res=0
  for nv in G[v]:
    if visited[nv]:
      continue
    visited[nv]=1
    res+=dfs(nv,visited)
    visited[nv]=0
  return res
 
n,m=list(map(int, input().split()))
G=[[] for _ in range(n)]
visited=[0]*n
res=0
 
for i in range(m):
  a,b=list(map(int, input().split()))
  G[a-1].append(b-1)
  G[b-1].append(a-1)

visited[0]=1
print((dfs(0,visited)))
# Original solution
import itertools

n,m= list(map(int, input().split()))
a= [list(map(int, input().split())) for i in range(m)]
# 経路全探索
ans=0
for v in itertools.combinations(a, n-1):
    b=[[] for i in range(n)]
    for x,y in v:
        b[x - 1].append(y - 1)
        b[y - 1].append(x - 1)

    import collections
    from collections import deque


    def tree(s):

        INF = -10 ** 9
        dis = [INF for i in range(n)]
        dis[s] = 0

        def bfs():
            d = deque()
            d.append(s)

            while len(d):
                x = d.popleft()

                for i in range(len(b[x])):
                    y = b[x][i]
                    if dis[y] == INF:
                        d.append(y)
                        dis[y] = dis[x] + 1

            return max(dis)

        return bfs()
    if tree(0)==n-1:
        ans+=1

print(ans)

# Optimized solution
N, M = list(map(int, input().split()))
es = [[] for i in range(N)]
for i in range(M):
    a, b = list(map(int, input().split()))
    es[a-1].append(b-1)
    es[b-1].append(a-1)

def dfs(v, used, cnt):
    used[v] = 1
    if all(used):
        cnt.append(1)
    for nv in es[v]:
        if used[nv]:
            continue
        dfs(nv, used, cnt)
    used[v] = 0

used = [0] * N
cnt = []
dfs(0, used, cnt)

print((sum(cnt)))
# Original solution
def multival(): return list(map(int,input().split()))
def data(N=1): return [list(map(int,input().split())) for _ in range(N)]
mod = 10**9 + 7
inf = float("inf")

N,M = multival()
nemat = [[0]*N for _ in range(N)]
ans = 0
for _ in range(M):
    a,b = multival()
    a -= 1; b-= 1
    nemat[a][b] = 1
    nemat[b][a] = 1

def dfs(now=0,visited=[False]*N):
    visited[now] = True
    if all(visited) is True:
        global ans
        ans += 1
    for ne in range(N):
        if nemat[now][ne] == 1 and visited[ne] is False:
            dfs(ne,visited[:])
            # visited[:]
            # n方向に分かれて探索する際にそれぞれ別のvisitedを持たせる
            # そうしなければ例えばsample1では 1->2->3 と進んで全てに訪問済みの印が付く
            # 次に1->2と進もうとしても2は既にTrueに更新済みなので探索が終了してしまう

dfs()
print(ans)

# Optimized solution
N,M = list(map(int,input().split()))
ad = [[0]*N for _ in range(N)]
for _ in range(M):
    a,b = list(map(int,input().split()))
    a -= 1; b -= 1
    ad[a][b] = 1
    ad[b][a] = 1

ans = 0

def dfs(v=0,d=0,visited=[1]+[0]*(N-1)):
    if d == N-1:
        global ans
        ans += 1
        return
    for nv, bit in enumerate(ad[v]):
        if bit == 0: continue
        if visited[nv] == 1: continue
        visited[nv] = 1
        dfs(nv,d+1)
        visited[nv] = 0

dfs()
print(ans)
# Original solution
N,M = list(map(int, input().split()))
edge= [[] for i in range(N+1)]
for i in range(M):
    a,b = list(map(int, input().split()))
    edge[a].append(b)
    edge[b].append(a)

result = []

import copy
def dfs(n,used,d):
    if d == N-1:
        result.append(1)
    for e in edge[n]:
        if used[e] == False:
            usedf = copy.deepcopy(used)
            usedf[e] = True
            dfs(e,usedf,d+1)


used = [False]*(N+1)
used[1] = True
dfs(1,used,0)
print((len(result)))


# Optimized solution
N,M = list(map(int, input().split()))
edge= [[] for i in range(N+1)]
for i in range(M):
    a,b = list(map(int, input().split()))
    edge[a].append(b)
    edge[b].append(a)

import itertools
per = itertools.permutations([i for i in range(1,N+1)])
ans = 0
for item in per:
    if item[0] != 1:
        continue
    f = True
    for ind,num in enumerate(item):
        if ind + 1<= N-1:
            nnum = item[ind+1]
            if nnum not in edge[num]:
                f = False

    if f:
        ans += 1

print(ans)
# Original solution
N, M = list(map(int, input().split()))
graph ={i+1:[] for i in range(N)}
for _ in range(M):
    a, b = list(map(int, input().split()))
    graph[a].append(b)
    graph[b].append(a)
    
def dfs(path, n, cnt):
    if(len(path) == N):
        return cnt+1
    for j in graph[n]:
        if(j in path):
            continue
        cnt = dfs(path+[j], j, cnt)
    return cnt
print((dfs([1], 1, 0)))

# Optimized solution
N, M = list(map(int, input().split()))
dict = {i+1:[] for i in range(N)}
for _ in range(M):
    a, b = list(map(int, input().split()))
    dict[a].append(b)
    dict[b].append(a)
    
def DFS(visited, sight, cnt):
    if(len(visited) == N):
        return cnt+1
    for num in dict[sight]:
        if num in visited:
            continue
        cnt = DFS(visited+[num], num, cnt)
    return cnt

print((DFS([1], 1, 0)))
# Original solution
def main():
    k = eval(input())
    n = [
        1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51
    ]
    print((n[int(k) - 1]))
main()


# Optimized solution
def main():
    X = [1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
    K = int(eval(input()))
    return X[K - 1]
print((main()))
# Original solution
def mi():return list(map(int,input().split()))

l=[1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]

k=int(eval(input()))

print((l[k-1]))



# Optimized solution
l=[1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
print((l[int(eval(input()))-1]))
# Original solution
A = [1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
k = int(eval(input()))
print((A[k - 1]))

# Optimized solution
print(([1,1,1,2,1,2,1,5,2,2,1,5,1,2,1,14,1,5,1,5,2,2,1,15,2,2,5,4,1,4,1,51][int(eval(input()))-1]))
# Original solution
l = [1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
print((l[int(eval(input()))-1]))

# Optimized solution
#!/usr/bin/env python3
print(([0, 1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51][int(eval(input()))]))
# Original solution
A = [1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
k = int(eval(input()))
print((A[k-1]))

# Optimized solution
A=[1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
K = int(eval(input()))
print((A[K-1]))
# Original solution
print((ord(' 3    '[int(eval(input()))%14])))

# Optimized solution
print((b' 3    '[int(eval(input()))%14]))
# Original solution
print((b' 3    '[int(eval(input()))%14]))

# Optimized solution
print(ord(' 3    '[eval(input())%14]))
# Original solution
A = [1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
K = int(eval(input()))
print((A[K-1]))

# Optimized solution
K = int(eval(input()))
a = [1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
print((a[K-1]))
# Original solution
def main():
    A = [1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
    K = int(eval(input()))
    print((A[K-1]))

if __name__ == "__main__":
    main()

# Optimized solution
def main():
    num = [1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, 5, 4, 1, 4, 1, 51]
    K = int(eval(input()))
    print((num[K-1]))


if __name__ == "__main__":
    main()
# Original solution
n = int(eval(input()))
x = []
y = []
h = []
for i in range(n):
    xi,yi,hi = list(map(int, input().split()))
    x.append(xi)
    y.append(yi)
    h.append(hi)


cxyl = []
for i in range(101):
    for j in range(101):
        cxyl.append((i,j))
cxy = set(cxyl)
hd = {}
hzero = []
for i in range(n):
    for c in list(cxy):
        H = abs(x[i]-c[0]) + abs(y[i]-c[1]) + h[i]
        if h[i] == 0:
            hzero.append((x[i],y[i]))
            if 1 > H:
                cxy.remove(c)
                continue
        else:
            if c in hd:
                if hd[c] != H:
                    cxy.remove(c)
                    continue
            else:
                hd[c] = H

for xy in hzero:
    xi = xy[0]
    yi = xy[1]
    for c in list(cxy):
        H = abs(xi-c[0]) + abs(yi-c[1])
        if hd[c] - H > 0:
            cxy.remove(c)

ret = cxy.pop()
print((str(ret[0]) + ' ' + str(ret[1]) + ' ' + str(hd[ret])))


# Optimized solution
n = int(eval(input()))
x = []
y = []
h = []
for i in range(n):
    xi,yi,hi = list(map(int, input().split()))
    x.append(xi)
    y.append(yi)
    h.append(hi)


cxyl = []
for i in range(101):
    for j in range(101):
        cxyl.append((i,j))
cxy = set(cxyl)
hd = {}
hzero = set([])
for i in range(n):
    for c in list(cxy):
        H = abs(x[i]-c[0]) + abs(y[i]-c[1]) + h[i]
        if h[i] == 0:
            hzero.add((x[i],y[i]))
            if 1 > H:
                cxy.remove(c)
                continue
        else:
            if c in hd:
                if hd[c] != H:
                    cxy.remove(c)
                    continue
            else:
                hd[c] = H

for xy in list(hzero):
    xi = xy[0]
    yi = xy[1]
    for c in list(cxy):
        H = abs(xi-c[0]) + abs(yi-c[1])
        if hd[c] - H > 0:
            cxy.remove(c)

ret = cxy.pop()
print((str(ret[0]) + ' ' + str(ret[1]) + ' ' + str(hd[ret])))
# Original solution
# 2019-11-10 20:23:41(JST)
import sys
# import collections
# import math
# from string import ascii_lowercase, ascii_uppercase, digits
# from bisect import bisect_left as bi_l, bisect_right as bi_r
# import itertools
# from functools import reduce
# import operator as op
# from scipy.misc import comb # float
# import numpy as np 

def main():
    n = int(sys.stdin.readline().rstrip())
    info = [[int(x) for x in sys.stdin.readline().split()] for _ in range(n)]
    
    # 基準を決める
    for i in range(n):
        if info[i][2] >= 1:
            x0, y0, h0 = info[i][0], info[i][1], info[i][2]
            break
    # else: すべてのhは h = 0

    for x in range(101):
        for y in range(101):
            H = h0 + abs(x - x0) + abs(y - y0)
            for i in range(n):   # 中心(x, y, H)が条件を満たしているか確認する
                h = max(H - abs(x - info[i][0]) - abs(y - info[i][1]), 0)
                if h != info[i][2]: #　本当に中心なら同じ値になるはず
                    break     # そうでないならこれは正しくない
            else:  # 全ての座標に対して条件を満たしていたなら
                res = [x, y, H]
                break # 中心は一意に決まるので見つかったらそれ以上調べる必要ない
    
    for i in range(3):
        res[i] = str(res[i])
    
    print((' '.join(res)))
            

if __name__ == "__main__":
    main()

# Optimized solution
# 2019-11-10 20:23:41(JST)
import sys
# import collections
# import math
# from string import ascii_lowercase, ascii_uppercase, digits
# from bisect import bisect_left as bi_l, bisect_right as bi_r
# import itertools
# from functools import reduce
# import operator as op
# from scipy.misc import comb # float
# import numpy as np 

def main():
    n = int(sys.stdin.readline().rstrip())
    info = [[int(x) for x in sys.stdin.readline().split()] for _ in range(n)]
    
    # 基準を決める
    for i in range(n):
        if info[i][2] >= 1:
            x0, y0, h0 = info[i][0], info[i][1], info[i][2]
            break
    # else: すべてのhは h = 0

    for x in range(101):
        for y in range(101):
            H = h0 + abs(x - x0) + abs(y - y0)
            for i in range(n):   # 中心(x, y, H)が条件を満たしているか確認する
                h = max(H - abs(x - info[i][0]) - abs(y - info[i][1]), 0)
                if h != info[i][2]: #　本当に中心なら同じ値になるはず
                    break     # そうでないならこれは正しくない
            else:  # 全ての座標に対して条件を満たしていたなら
                res = [x, y, H]
                for i in range(3):
                    res[i] = str(res[i])
                print((' '.join(res)))
                sys.exit() # 中心は一意に決まるので見つかったらそれ以上調べる必要ない
    
            

if __name__ == "__main__":
    main()