Bob is an avid fan of the video game "League of Leesins", and today he celebrates as the League of Leesins World Championship comes to an end! 

The tournament consisted of n (n ≥ 5) teams around the world. Before the tournament starts, Bob has made a prediction of the rankings of each team, from 1-st to n-th. After the final, he compared the prediction with the actual result and found out that the i-th team according to his prediction ended up at the p_i-th position (1 ≤ p_i ≤ n, all p_i are unique). In other words, p is a permutation of 1, 2, ..., n.

As Bob's favorite League player is the famous "3ga", he decided to write down every 3 consecutive elements of the permutation p. Formally, Bob created an array q of n-2 triples, where q_i = (p_i, p_{i+1}, p_{i+2}) for each 1 ≤ i ≤ n-2. Bob was very proud of his array, so he showed it to his friend Alice.

After learning of Bob's array, Alice declared that she could retrieve the permutation p even if Bob rearranges the elements of q and the elements within each triple. Of course, Bob did not believe in such magic, so he did just the same as above to see Alice's respond.

For example, if n = 5 and p = [1, 4, 2, 3, 5], then the original array q will be [(1, 4, 2), (4, 2, 3), (2, 3, 5)]. Bob can then rearrange the numbers within each triple and the positions of the triples to get [(4, 3, 2), (2, 3, 5), (4, 1, 2)]. Note that [(1, 4, 2), (4, 2, 2), (3, 3, 5)] is not a valid rearrangement of q, as Bob is not allowed to swap numbers belong to different triples.

As Alice's friend, you know for sure that Alice was just trying to show off, so you decided to save her some face by giving her any permutation p that is consistent with the array q she was given. 

Input

The first line contains a single integer n (5 ≤ n ≤ 10^5) — the size of permutation p.

The i-th of the next n-2 lines contains 3 integers q_{i, 1}, q_{i, 2}, q_{i, 3} (1 ≤ q_{i, j} ≤ n) — the elements of the i-th triple of the rearranged (shuffled) array q_i, in random order. Remember, that the numbers within each triple can be rearranged and also the positions of the triples can be rearranged.

It is guaranteed that there is at least one permutation p that is consistent with the input. 

Output

Print n distinct integers p_1, p_2, …, p_n (1 ≤ p_i ≤ n) such that p is consistent with array q. 

If there are multiple answers, print any. 

Example

Input


5
4 3 2
2 3 5
4 1 2


Output


1 4 2 3 5 
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.Scanner; 
import java.util.StringTokenizer; 
import java.util.*;
import java.io.*;
public class codeforces 
{ 
   static class Student{
       int x,y;
        Student(int x,int y){
            this.x=x;
            this.y=y;
        }
    }
    static int prime[];
    static void sieveOfEratosthenes(int n) 
    { 
        // Create a boolean array "prime[0..n]" and initialize 
        // all entries it as true. A value in prime[i] will 
        // finally be false if i is Not a prime, else true. 
        int pos=0;
        prime= new int[n+1]; 
        for(int p = 2; p*p <=n; p++) 
        { 
            // If prime[p] is not changed, then it is a prime 
            if(prime[p] == 0)
            { 
                // Update all multiples of p
                prime[p]=p;
                for(int i = p*p; i <= n; i += p) 
                    prime[i] = p; 
            } 
        } 
    }
static    class Sortbyroll implements Comparator<Student> 
{ 
    // Used for sorting in ascending order of 
    // roll number 
    public int compare(Student c, Student b) 
    { 
        return c.y-b.y;
    } 
} 
    static class FastReader 
    { 
        BufferedReader br; 
        StringTokenizer st; 
  
        public FastReader() 
        { 
            br = new BufferedReader(new
                     InputStreamReader(System.in)); 
        } 
  
        String next() 
        { 
            while (st == null || !st.hasMoreElements()) 
            { 
                try
                { 
                    st = new StringTokenizer(br.readLine()); 
                } 
                catch (IOException  e) 
                { 
                    e.printStackTrace(); 
                } 
            } 
            return st.nextToken(); 
        } 
  
        int nextInt() 
        { 
            return Integer.parseInt(next()); 
        } 
  
        long nextLong() 
        { 
            return Long.parseLong(next()); 
        } 
  
        double nextDouble() 
        { 
            return Double.parseDouble(next()); 
        } 
  
        String nextLine() 
        { 
            String str = ""; 
            try
            { 
                str = br.readLine(); 
            } 
            catch (IOException e) 
            { 
                e.printStackTrace(); 
            } 
            return str; 
        } 
    }
    static class Edge{
        int a,b;
        Edge(int a,int b){
            this.a=a;
            this.b=b;
        }
    }
    static int parent[];
    static int rank[];
    public static void main(String[] args){
        //long sum=0;
        FastReader sc=new FastReader();
        ArrayList<ArrayList<Integer>>temp=new ArrayList<>();
        int n,i,x,y,z,k,j,pos=0;
        HashMap<String,Integer>map=new HashMap<>();
        n=sc.nextInt();
        int a[]=new int[n+1];
        for(i=0;i<=n;i++)
            temp.add(new ArrayList<>());
        for(i=0;i<n-2;i++){
            x=sc.nextInt();
            a[x]+=1;
            y=sc.nextInt();
            a[y]+=1;
            z=sc.nextInt();
            a[z]+=1;
            map.put(x+" "+y,1);
            map.put(y+" "+x,1);
            map.put(x+" "+z,1);
            map.put(z+" "+x,1);
            map.put(z+" "+y,1);
            map.put(y+" "+z,1);
            temp.get(x).add(y);
            temp.get(x).add(z);
            temp.get(y).add(x);
            temp.get(y).add(z);
            temp.get(z).add(x);
            temp.get(z).add(y);
        }
        HashMap<Integer,Integer>v=new HashMap<>();
        //Collections.sort(arr,new Sortbyroll());
        int ans[]=new int[n];
        for(i=1;i<=n;i++){
            if(a[i]==1)
            {
                if(ans[0]==0)
                    ans[0]=i;
                else
                    ans[n-1]=i;
            }
        }
        for(i=1;i<=n;i++){
            if(a[i]==2){
        if(map.containsKey(ans[0]+" "+i)){
            ans[1]=i;
        }
        else{
            ans[n-2]=i;
        }
            }
        }
        i=2;
        j=n-3;
        pos=0;
        v.put(ans[0],1);
        v.put(ans[1],1);
        v.put(ans[n-1],1);
        v.put(ans[n-2],1);
        while(i<=j){
            pos=0;
         for(k=0;k<temp.get(ans[i-1]).size();k++){
             if(!v.containsKey(temp.get(ans[i-1]).get(k))&&map.containsKey(temp.get(ans[i-1]).get(k)+" "+ans[i-2])){
                 pos=1;
                 v.put(temp.get(ans[i-1]).get(k),1);
                 ans[i]=temp.get(ans[i-1]).get(k);
                 ++i;
                 break;
             }
         }
           for(k=0;k<temp.get(ans[j+1]).size();k++){
             if(!v.containsKey(temp.get(ans[j+1]).get(k))&&map.containsKey(temp.get(ans[j+1]).get(k)+" "+ans[j+2])){
                 pos=1;
                 v.put(temp.get(ans[j+1]).get(k),1);
                 ans[j]=temp.get(ans[j+1]).get(k);
                 --j;
                 break;
             }
         }
            if(pos==0)
                break;
        }
        StringBuilder sb=new StringBuilder();
        for(i=0;i<n;i++)
            sb.append(ans[i]+" ");
        System.out.println(sb.toString());
    }
 /*static long power(long x, long y, long p) 
{ 
    long res = 1;      // Initialize result 
  
    x = x % p;  // Update x if it is more than or  
                // equal to p 
  
    while (y > 0) 
    { 
        // If y is odd, multiply x with result 
        if ((y & (long)1)%2!=0) 
            res = (res*x) % p; 
  
        // y must be even now 
        y = y>>1; // y = y/2 
        x = (x*x) % p;   
    } 
    return res%p; 
} */
   static int find(int x) 
    { 
        // Finds the representative of the set 
        // that x is an element of 
        while(parent[x]!=x) 
        { 
            // if x is not the parent of itself 
            // Then x is not the representative of 
            // his set,
            x=parent[x];
  
            // so we recursively call Find on its parent 
            // and move i's node directly under the 
            // representative of this set 
        } 
  
        return x; 
    }
    static void union(int x, int y) 
    { 
        // Find representatives of two sets 
        int xRoot = find(x), yRoot = find(y); 
  
        // Elements are in the same set, no need 
        // to unite anything. 
        if (xRoot == yRoot) 
            return; 
  
         // If x's rank is less than y's rank 
        if (rank[xRoot] < rank[yRoot]) 
  
            // Then move x under y  so that depth 
            // of tree remains less 
            parent[xRoot] = yRoot; 
  
        // Else if y's rank is less than x's rank 
        else if (rank[yRoot] < rank[xRoot]) 
  
            // Then move y under x so that depth of 
            // tree remains less 
            parent[yRoot] = xRoot; 
  
        else // if ranks are the same 
        { 
            // Then move y under x (doesn't matter 
            // which one goes where) 
            parent[yRoot] = xRoot; 
  
            // And increment the the result tree's 
            // rank by 1 
            rank[xRoot] = rank[xRoot] + 1; 
        } 
    } 
    static long gcd(long a, long b) 
    { 
        if (a == 0) 
            return b; 
        return gcd(b % a, a); 
    }
}