Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Dice IV

Write a program which reads $n$ dices constructed in the same way as Dice I, and determines whether they are all different. For the determination, use the same way as Dice III.

Input

In the first line, the number of dices $n$ is given. In the following $n$ lines, six integers assigned to the dice faces are given respectively in the same way as Dice III.

Output

Print "Yes" if given dices are all different, otherwise "No" in a line.

Constraints

$2 \leq n \leq 100$

$0 \leq $ the integer assigned to a face $ \leq 100$

Sample Input 1

3
1 2 3 4 5 6
6 2 4 3 5 1
6 5 4 3 2 1

Sample Output 1

No

Sample Input 2

3
1 2 3 4 5 6
6 5 4 3 2 1
5 4 3 2 1 6

Sample Output 2

Yes

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ITP1_11_D
{
    class Program
    {


        public static IEnumerable<string[]> ReadSplitWords(Func<string> reader, char splitChar)
        {
            while (true)
            {
                yield return reader().Split(splitChar);
            }
        }


        public static bool HasDuplicate<T>(IEnumerable<T> stream, Func<T, T, bool> isEquals)
        {
            Func<T, bool> recursiveFunction = _ => false;

            foreach (var n in stream) {
                if (recursiveFunction(n)) 
                {
                    return true;
                }

                var currentFunc = recursiveFunction;
                recursiveFunction = (m) => isEquals(m, n) || currentFunc(m);
            }

            return false;
        }


        public static void Main(string[] args)
        {
            var count = int.Parse(Console.ReadLine());

            // (1)
            //var alias = ReadSplitWords(Console.ReadLine, ' ').Take(count).ToArray();
            //var hasDuplicate = HasDuplicate(alias, Dice.EqualsAliasOfDice);


            // (2)
            var hasDuplicate = false;
            var diceAliasList = new string[count][];
            var h = 0;
            foreach (var n in ReadSplitWords(Console.ReadLine, ' ').Take(count))
            {
                if (diceAliasList.Take(h).Any(_ => Dice.EqualsAliasOfDice(_, n)))
                {
                    hasDuplicate = true;
                    break;
                }
                //    if (Dice.EqualsAliasOfDice(n, diceAliasList[i]))
                //    {
                //        hasDuplicate = true;
                //        break;
                //    }
                //}

                if (hasDuplicate == true)
                {
                    break;
                }
                diceAliasList[h] = n;
                ++h;
            }

            Console.WriteLine(hasDuplicate ? "No" : "Yes");
        }
    }

    class Dice
    {
        public Dice()
        {
            Top = 0;
            Front = 1;
            Right = 2;
        }

        public void RotateNorth()
        {
            var temp = Inverse(Top);
            Top = Front;
            Front = temp;
        }


        public void RotateSouth()
        {
            var temp = Inverse(Front);
            Front = Top;
            Top = temp;
        }


        public void RotateEast()
        {
            var temp = Inverse(Right);
            Right = Top;
            Top = temp;
        }


        public void RotateWest()
        {
            var temp = Inverse(Top);
            Top = Right;
            Right = temp;
        }


        public enum Surface { TOP, BOTTOM, FRONT, BACK, RIGHT, LEFT, NONE }

        public Surface Match(int surface)
        {
            if (surface == Top) return Surface.TOP;
            if (surface == Bottom) return Surface.BOTTOM;
            if (surface == Front) return Surface.FRONT;
            if (surface == Back) return Surface.BACK;
            if (surface == Right) return Surface.RIGHT;
            if (surface == Left) return Surface.LEFT;

            return Surface.NONE;
        }


        public bool RotateToTop(int top)
        {
            switch (Match(top))
            {
                case Surface.TOP: break;
                case Surface.BOTTOM: RotateNorth(); RotateNorth(); break;
                case Surface.FRONT: RotateNorth(); break;
                case Surface.BACK: RotateSouth(); break;
                case Surface.RIGHT: RotateWest(); break;
                case Surface.LEFT: RotateEast(); break;
            }

            return Top == top;
        }


        public bool RotateToTopAndFront(int top, int front)
        {
            if (RotateToTop(top) == false)
            {
                return false;
            }

            switch (Match(front))
            {
                case Surface.RIGHT: RotateRightOfZCoords(); break;
                case Surface.BACK: RotateRightOfZCoords(); RotateRightOfZCoords(); break;
                case Surface.LEFT: RotateLeftOfZCoords(); break;
            }

            return Top == top && Front == front;
        }


        public void RotateRightOfZCoords()
        {
            var temp = Back;
            Front = Right;
            Right = temp;
        }


        public void RotateLeftOfZCoords()
        {
            var temp = Left;
            Right = Front;
            Front = temp;
        }



        public int RightOf(int front)
        {
            switch (Match(front))
            {
                case Surface.FRONT: return Right;
                case Surface.RIGHT: return Back;
                case Surface.BACK: return Left;
                case Surface.LEFT: return Front;
            }
            return -1;
        }


        public int Top { get; private set; }


        public int Front { get; private set; }


        public int Right { get; private set; }


        public int Bottom { get { return Inverse(Top); } }


        public int Back { get { return Inverse(Front); } }


        public int Left { get { return Inverse(Right); } }



        public int Inverse(int surface)
        {
            return 5 - surface;
        }


        public IEnumerable<int> Surfaces()
        {
            yield return Top;
            yield return Front;
            yield return Right;
            yield return Left;
            yield return Back;
            yield return Bottom;
        }


        public static bool EqualsAliasOfNoDuplication(string[] alias1, string[] alias2)
        {
            var dice1 = new Dice();
            var dice2 = new Dice();

            var top = -1;
            var front = -1;
            for (var i = 0; i < alias1.Length; ++i)
            {
                if (alias1[0] == alias2[i])
                {
                    top = i;
                }
                if (alias1[1] == alias2[i])
                {
                    front = i;
                }
            }

            if (dice2.RotateToTopAndFront(top, front) == false)
            {
                return false;
            }

            var orderedAlias1 = dice1.Surfaces().Select(n => alias1[n]);
            var orderedAlias2 = dice2.Surfaces().Select(n => alias2[n]);
            return Enumerable.SequenceEqual(orderedAlias1, orderedAlias2);
        }


        public static bool EqualsAliasOfDice(string[] alias1, string[] alias2)
        {
            var dice1 = new Dice();
            var dice2 = new Dice();

            var orderedAlias1 = dice1.Surfaces().Select(n => alias1[n]);
            var orderedAlias2 = dice2.Surfaces().Select(n => alias2[n]);

            for (var i = 0; i < 6; ++i)
            {
                dice2.RotateToTop(i);
                if (Enumerable.SequenceEqual(orderedAlias1, orderedAlias2)) return true;

                dice2.RotateLeftOfZCoords();
                if (Enumerable.SequenceEqual(orderedAlias1, orderedAlias2)) return true;

                dice2.RotateLeftOfZCoords();
                if (Enumerable.SequenceEqual(orderedAlias1, orderedAlias2)) return true;

                dice2.RotateLeftOfZCoords();
                if (Enumerable.SequenceEqual(orderedAlias1, orderedAlias2)) return true;
            }

            return false;
        }

    }
}