Esempio n. 1
0
        private void MelodicContourDistanceTest()
        {
            Console.WriteLine("MelodicContour Distance Test");

            MelodicContour mc   = new MelodicContour(0);
            int            cost = 0;

            mc.InsertNote(0, 16, 0);
            mc.InsertNote(1, 16, -1);
            mc.InsertNote(2, 8, -2);
            mc.InsertNote(3, 8, -1);
            mc.InsertNote(4, 8, 0);
            mc.InsertNote(5, 8, -4);
            mc.Print();

            Console.WriteLine("(1)");
            MelodicContour mc2 = mc.Copy();

            cost = mc2.ReplaceNote(5, new MelodicContourNote(8, 4));
            Console.WriteLine(cost);
            cost = mc2.ReplaceNote(4, 8, 3);
            Console.WriteLine(cost);
            cost = mc2.ReplaceNote(3, new MelodicContourNote(8, 0));
            Console.WriteLine(cost);

            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine();

            Console.WriteLine("(2)");
            mc2  = mc.Copy();
            cost = mc2.ReplaceNote(4, 8, 3);
            Console.WriteLine(cost);
            cost = mc2.ReplaceNote(3, 12, 1);
            Console.WriteLine(cost);
            cost = mc2.ReplaceNote(1, 16, 3);
            Console.WriteLine(cost);

            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine();

            Console.WriteLine("(3)");
            MelodicContour mc3 = mc2.Copy();

            mc2  = mc3.Copy();
            cost = mc2.InsertNote(5, 8, -2);
            Console.WriteLine(cost);
            cost = mc2.DeleteNote(2);
            Console.WriteLine(cost);
            cost = mc2.ReplaceNote(3, 8, 3);
            Console.WriteLine(cost);
            cost = mc2.ReplaceNote(1, 24, 1);
            Console.WriteLine(cost);

            mc3.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc3.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc3));
            Console.WriteLine();

            Console.WriteLine("(4)");
            mc2  = mc.Copy();
            cost = mc2.InsertNote(5, 8, -2);
            Console.WriteLine(cost);
            cost = mc2.DeleteNote(2);
            Console.WriteLine(cost);
            cost = mc2.ReplaceNote(3, 8, 3);
            Console.WriteLine(cost);
            cost = mc2.ReplaceNote(1, 24, 1);
            Console.WriteLine(cost);

            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine();

            Console.WriteLine("(5)");
            mc = new MelodicContour(0,
                                    new MelodicContourNote(8, 0),
                                    new MelodicContourNote(6, 0),
                                    new MelodicContourNote(2, -2),
                                    new MelodicContourNote(4, 0),
                                    new MelodicContourNote(8, 4),
                                    new MelodicContourNote(8, 3),
                                    new MelodicContourNote(8, 1),
                                    new MelodicContourNote(8, 0),
                                    new MelodicContourNote(4, 1),
                                    new MelodicContourNote(4, 0),
                                    new MelodicContourNote(4, -1));
            mc2 = new MelodicContour(0,
                                     new MelodicContourNote(8, -2),
                                     new MelodicContourNote(6, -2),
                                     new MelodicContourNote(2, -2),
                                     new MelodicContourNote(4, -2),
                                     new MelodicContourNote(8, 0),
                                     new MelodicContourNote(36, -1));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            mc2.Print();
            Console.WriteLine();
            mc.Print();
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine();

            Console.WriteLine("(6)");
            mc2 = new MelodicContour(0,
                                     new MelodicContourNote(4, -2),
                                     new MelodicContourNote(4, 0),
                                     new MelodicContourNote(4, 2),
                                     new MelodicContourNote(8, 5),
                                     new MelodicContourNote(12, 7),
                                     new MelodicContourNote(4, -1),
                                     new MelodicContourNote(4, 1),
                                     new MelodicContourNote(4, 3),
                                     new MelodicContourNote(8, 6),
                                     new MelodicContourNote(12, 5));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine();

            Console.WriteLine("(7)");
            mc2 = new MelodicContour(0,
                                     new MelodicContourNote(8, -1),
                                     new MelodicContourNote(6, -1),
                                     new MelodicContourNote(2, -3),
                                     new MelodicContourNote(4, -1),
                                     new MelodicContourNote(8, 3),
                                     new MelodicContourNote(8, 2),
                                     new MelodicContourNote(8, 0),
                                     new MelodicContourNote(8, -1),
                                     new MelodicContourNote(4, 0),
                                     new MelodicContourNote(4, -1),
                                     new MelodicContourNote(4, -3));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine("min: " + mc.Distance(mc2));
            Console.WriteLine();

            // In this example, `mc.DistanceWithDirection(mc2)` is differ from `mc2.DistanceWithDirection(mc)`.
            Console.WriteLine("(8)");
            mc = new MelodicContour(0);
            mc.InsertNote(0, 16, 0);
            mc.InsertNote(1, 16, -1);
            mc.InsertNote(2, 8, -2);
            mc.InsertNote(3, 8, -1);
            mc.InsertNote(4, 8, 0);
            mc.InsertNote(5, 8, -4);
            mc2 = new MelodicContour(0,
                                     new MelodicContourNote(4, -2),
                                     new MelodicContourNote(4, 0),
                                     new MelodicContourNote(4, 2),
                                     new MelodicContourNote(8, 5),
                                     new MelodicContourNote(12, 7),
                                     new MelodicContourNote(4, -1),
                                     new MelodicContourNote(4, 1),
                                     new MelodicContourNote(4, 3),
                                     new MelodicContourNote(8, 6),
                                     new MelodicContourNote(12, 5));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine("min: " + mc.Distance(mc2));
            Console.WriteLine();

            Console.WriteLine("(9)");
            mc = new MelodicContour(0,
                                    new MelodicContourNote(8, 0),
                                    new MelodicContourNote(8, 0));
            mc2 = new MelodicContour(4,
                                     new MelodicContourNote(4, 0),
                                     new MelodicContourNote(4, 1),
                                     new MelodicContourNote(4, 0));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine("min: " + mc.Distance(mc2));
            Console.WriteLine();

            // In this example, the optimal path must use two MoveNotes() operations.
            Console.WriteLine("(10)");
            mc = new MelodicContour(0,
                                    new MelodicContourNote(8, 0),
                                    new MelodicContourNote(8, 0),
                                    new MelodicContourNote(8, 0),
                                    new MelodicContourNote(8, 0));
            mc2 = new MelodicContour(0,
                                     new MelodicContourNote(12, 0),
                                     new MelodicContourNote(4, 1),
                                     new MelodicContourNote(4, 0),
                                     new MelodicContourNote(12, -1));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine("min: " + mc.Distance(mc2));
            Console.WriteLine();

            // In this example, the optimal path must use a DelayAndReplaceNotes() operation.
            Console.WriteLine("(11)");
            mc = new MelodicContour(8,
                                    new MelodicContourNote(8, 0),
                                    new MelodicContourNote(8, 0),
                                    new MelodicContourNote(8, 0));
            mc2 = new MelodicContour(0,
                                     new MelodicContourNote(16, 0),
                                     new MelodicContourNote(4, -1),
                                     new MelodicContourNote(12, -1));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine("min: " + mc.Distance(mc2));
            Console.WriteLine();

            Console.WriteLine("(12)");
            mc = new MelodicContour(0,
                                    new MelodicContourNote(16, 61),
                                    new MelodicContourNote(8, 62),
                                    new MelodicContourNote(8, 64),
                                    new MelodicContourNote(16, 66),
                                    new MelodicContourNote(16, 69));
            mc2 = new MelodicContour(0,
                                     new MelodicContourNote(16, 76),
                                     new MelodicContourNote(8, 73),
                                     new MelodicContourNote(8, 73),
                                     new MelodicContourNote(16, 73),
                                     new MelodicContourNote(16, 76));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine();

            Console.WriteLine("(13)");
            mc = new MelodicContour(0,
                                    new MelodicContourNote(8, 51),
                                    new MelodicContourNote(8, 54),
                                    new MelodicContourNote(8, 60),
                                    new MelodicContourNote(8, 54),
                                    new MelodicContourNote(8, 44),
                                    new MelodicContourNote(8, 51),
                                    new MelodicContourNote(8, 60),
                                    new MelodicContourNote(8, 51));
            mc2 = new MelodicContour(0,
                                     new MelodicContourNote(8, 61),
                                     new MelodicContourNote(8, 56),
                                     new MelodicContourNote(8, 50),
                                     new MelodicContourNote(8, 40),
                                     new MelodicContourNote(8, 37),
                                     new MelodicContourNote(8, 44),
                                     new MelodicContourNote(8, 53),
                                     new MelodicContourNote(8, 59));
            mc.Print();
            Console.WriteLine();
            mc2.Print();
            Console.WriteLine("distance: " + mc.DistanceWithDirection(mc2));
            Console.WriteLine("inverse distance: " + mc2.DistanceWithDirection(mc));
            Console.WriteLine();
        }
Esempio n. 2
0
        private void MelodicContourEditTest()
        {
            Console.WriteLine("MelodicContour Edit Test");
            MelodicContour mc   = new MelodicContour(0);
            int            cost = 0;

            cost += mc.InsertNote(mc.noteList.Count, new MelodicContourNote(16, 0));
            Console.WriteLine(cost);
            cost += mc.InsertNote(mc.noteList.Count, 16, -1);
            Console.WriteLine(cost);
            cost += mc.InsertNote(mc.noteList.Count, new MelodicContourNote(8, -2));
            Console.WriteLine(cost);
            cost += mc.InsertNote(mc.noteList.Count, 8, -1);
            Console.WriteLine(cost);
            cost += mc.InsertNote(mc.noteList.Count, new MelodicContourNote(8, 0));
            Console.WriteLine(cost);
            cost += mc.InsertNote(mc.noteList.Count, 8, -4);
            Console.WriteLine(cost);
            mc.Print();

            cost  = 0;
            cost += mc.ReplaceNote(5, new MelodicContourNote(8, 4));
            Console.WriteLine(cost);
            cost += mc.ReplaceNote(4, 8, 3);
            Console.WriteLine(cost);
            cost += mc.ReplaceNote(3, new MelodicContourNote(8, 0));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(1)");
            // 음표와 음표 사이에 삽입
            cost = mc.InsertNote(2, new MelodicContourNote(16, mc.GetNewClusterNumber(1)));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(2)");
            // 잘못된 인덱스에 삽입
            cost = mc.InsertNote(10, new MelodicContourNote(24, mc.GetNewClusterNumber(3)));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(3)");
            // 인덱스는 유지하고 길이를 바꾸는 교체 (맨 앞 음표라서 클러스터 순위 변경 비용이 없음)
            cost = mc.ReplaceNote(0, new MelodicContourNote(4, mc.GetNewClusterNumber(0)));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(4)");
            // 맨 앞에 삽입
            cost = mc.InsertNote(0, new MelodicContourNote(4, 1));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(5)");
            // 직전 음과 같은 음 높이를 갖는 음표 삽입
            cost = mc.InsertNote(1, new MelodicContourNote(4, 1));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(6)");
            // 없는 음표로 교체
            cost = mc.ReplaceNote(0, new MelodicContourNote(0, 0));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(7)");
            // 없는 음표를 교체 1
            cost = mc.ReplaceNote(-1, new MelodicContourNote(1, 3));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(8)");
            // 없는 음표를 교체 2
            cost = mc.ReplaceNote(10, new MelodicContourNote(1, 3));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(9)");
            // 같은 음표로 교체
            cost = mc.ReplaceNote(0, new MelodicContourNote(4, 1));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(10)");
            // 길이와 음 높이를 모두 바꾸도록 교체 1 (맨 앞 음표라서 클러스터 순위 변경 비용이 없음)
            cost = mc.ReplaceNote(0, new MelodicContourNote(1, 3));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(11)");
            // 길이와 음 높이를 모두 바꾸도록 교체 2
            cost = mc.ReplaceNote(3, new MelodicContourNote(15, mc.GetExistingClusterNumber(0)));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(12)");
            // 직후 음표와 길이가 같고 클러스터가 다르도록 교체 (앞에 위치한 음표라서 클러스터 순위 변경 비용이 없음)
            cost = mc.ReplaceNote(2, new MelodicContourNote(15, mc.GetExistingClusterNumber(1)));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(13)");
            // 음 높이 변화와 길이를 유지하고 클러스터 번호를 바꾸지만 클러스터 순위를 바꾸지 않도록 교체
            // (기존 클러스터가 사라지지 않음)
            cost = mc.ReplaceNote(4, 16, -1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(14)");
            // 음 높이 변화와 길이를 유지하면서 클러스터 번호를 바꾸지만 클러스터 순위를 바꾸지 않도록 교체
            // (기존 클러스터가 사라지면서 클러스터 개수 변경 비용 발생)
            cost = mc.ReplaceNote(4, 16, 1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(15)");
            // 음 높이 변화는 유지하면서 클러스터 순위만 다르도록 교체
            cost = mc.ReplaceNote(4, 16, 3);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(16)");
            // 중간에 있는 기존 음표 제거
            cost = mc.DeleteNote(4);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(17)");
            // 맨 끝의 기존 음표 제거
            cost = mc.DeleteNote(7);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(18)");
            // 맨 앞의 기존 음표 제거
            cost = mc.DeleteNote(0);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(19)");
            // 맨 처음 쉼표 길이 조정 1
            cost = mc.DelayNotes(8);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(20)");
            // 제거했던 위치에 새로운 음표 삽입
            cost = mc.InsertNote(0, 8, 1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(21)");
            // 직전 음표와 같은 음을 갖는 음표 제거
            cost = mc.DeleteNote(1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(22)");
            // 없는 음표 제거
            cost = mc.DeleteNote(22);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(23)");
            // 맨 처음 쉼표 길이 조정 2
            cost = mc.DelayNotes(4);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(24)");
            // 맨 처음 쉼표 길이를 잘못되게 조정
            cost = mc.DelayNotes(-1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(25)");
            // 맨 처음 쉼표 길이를 이전 상태와 같게 조정
            cost = mc.DelayNotes(4);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(26)");
            // 비용이 2가 되도록 연산 수행
            cost = mc.ReplaceNote(5, 8, -2);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(27)");
            // 맨 처음 쉼표 길이 조정 3
            cost = mc.DelayNotes(0);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(28)");
            // 연산 정보를 이용해 음표와 음표 사이에 삽입
            MelodicContour.OperationInfo op1 = new MelodicContour.OperationInfo(
                MelodicContour.OperationInfo.Type.Insert, 3, new MelodicContourNote(),
                new MelodicContourNote(2, mc.GetExistingClusterNumber(0)));
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(29)");
            // 연산 정보를 이용해 음표 제거
            MelodicContour.OperationInfo op2 = new MelodicContour.OperationInfo(
                MelodicContour.OperationInfo.Type.Delete, 2,
                new MelodicContourNote(15, mc.GetExistingClusterNumber(0)), new MelodicContourNote());
            cost = mc.PerformOperation(op2);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(30)");
            // 연산 정보를 이용해 음표 교체
            MelodicContour.OperationInfo op3 = new MelodicContour.OperationInfo(
                MelodicContour.OperationInfo.Type.Replace, 1,
                new MelodicContourNote(15, -2), new MelodicContourNote(16, 2));
            cost = mc.PerformOperation(op3);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(31)");
            // 연산 정보를 이용해 리듬 패턴의 맨 앞 쉼표 길이 조정
            MelodicContour.OperationInfo op4 = new MelodicContour.OperationInfo(0, 16);
            cost = mc.PerformOperation(op4);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(32)");
            // 쉼표 길이를 조정하는 연산의 역연산 수행
            cost = mc.PerformOperation(op4.Inverse());
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(33)");
            // 음표를 교체하는 연산의 역연산 수행
            cost = mc.PerformOperation(op3.Inverse());
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(34)");
            // 음표를 제거하는 연산의 역연산 수행
            cost = mc.PerformOperation(op2.Inverse());
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(35)");
            // 음표를 삽입하는 연산의 역연산 수행
            cost = mc.PerformOperation(op1.Inverse());
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(36)");
            // 상황에 맞지 않는 연산 정보 1
            op1 = new MelodicContour.OperationInfo(MelodicContour.OperationInfo.Type.Replace,
                                                   5, new MelodicContourNote(16, -2), new MelodicContourNote(16, -3));
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(37)");
            // 상황에 맞지 않는 연산 정보 2
            op1 = new MelodicContour.OperationInfo(MelodicContour.OperationInfo.Type.Delete,
                                                   5, new MelodicContourNote(16, -2), new MelodicContourNote());
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(38)");
            // 상황에 맞지 않는 연산 정보 3
            op1  = new MelodicContour.OperationInfo(4, 0);
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(39)");
            // 상황에 맞지 않는 연산 정보 4
            op1 = new MelodicContour.OperationInfo(MelodicContour.OperationInfo.Type.Delete,
                                                   5, new MelodicContourNote(8, -3), new MelodicContourNote());
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(40)");
            // 연속된 두 음표의 길이만 바꾸는 옮기기 연산 수행
            cost = mc.MoveNotes(3, new MelodicContourNote(4, -2), new MelodicContourNote(12, 0));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(41)");
            // 연속된 두 음표의 길이와 음 높이를 바꾸는 옮기기 연산 수행
            cost = mc.MoveNotes(1, new MelodicContourNote(20, -2), new MelodicContourNote(10, 1));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(42)");
            // 연산 전후로 멜로디 형태가 바뀌지 않는 옮기기 연산 수행
            cost = mc.MoveNotes(1, new MelodicContourNote(20, -2), new MelodicContourNote(10, 1));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(43)");
            // 마지막 음표를 앞 음표로 하는 옮기기 연산 수행
            cost = mc.MoveNotes(5, new MelodicContourNote(4, -2), new MelodicContourNote(4, 0));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(44)");
            // 없는 음표를 앞 음표로 하는 옮기기 연산 수행
            cost = mc.MoveNotes(8, new MelodicContourNote(4, -2), new MelodicContourNote(4, 0));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(45)");
            // 연산 정보를 이용해 연속된 두 음표의 길이와 음 높이를 바꾸는 옮기기 연산 수행
            op1 = new MelodicContour.OperationInfo(1, new MelodicContourNote(20, -2), new MelodicContourNote(10, 1),
                                                   new MelodicContourNote(15, 2), new MelodicContourNote(15, -3));
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(46)");
            // 45번 테스트케이스에서 수행했던 옮기기 연산의 역연산 수행
            cost = mc.PerformOperation(op1.Inverse());
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(47)");
            // 상황에 맞지 않는 연산 정보 5
            op1 = new MelodicContour.OperationInfo(1, new MelodicContourNote(20, -2), new MelodicContourNote(10, 0),
                                                   new MelodicContourNote(15, 2), new MelodicContourNote(15, -3));
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(48)");
            // 연산 전후로 두 음표의 길이의 합이 달라지는 옮기기 연산 수행
            op1 = new MelodicContour.OperationInfo(1, new MelodicContourNote(20, -2), new MelodicContourNote(10, 0),
                                                   new MelodicContourNote(16, -3), new MelodicContourNote(16, 0));
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(49)");
            // DelayAndReplace 연산 수행
            cost = mc.DelayAndReplaceNotes(4, new MelodicContourNote(4, 1));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(50)");
            // 연산 전후로 멜로디 형태가 바뀌지 않는 DelayAndReplace 연산 수행
            cost = mc.DelayAndReplaceNotes(4, new MelodicContourNote(4, 1));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(51)");
            // 연산 전후로 쉼표 및 음표의 길이의 합이 달라지는 DelayAndReplace 연산 수행
            cost = mc.DelayAndReplaceNotes(4, new MelodicContourNote(8, 1));
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(52)");
            // 연산 정보를 이용해 쉼표 및 음표의 길이와 음 높이를 바꾸는 옮기기 연산 수행
            op1 = new MelodicContour.OperationInfo(4, 0,
                                                   new MelodicContourNote(4, 1), new MelodicContourNote(8, 0));
            cost = mc.PerformOperation(op1);
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(53)");
            // 52번 테스트케이스에서 수행했던 DelayAndReplace 연산의 역연산 수행
            cost = mc.PerformOperation(op1.Inverse());
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(54)");
            // 상황에 맞지 않는 연산 정보 6
            cost = mc.PerformOperation(op1.Inverse());
            Console.WriteLine(cost);
            mc.Print();

            Console.WriteLine("(55)");
            // 빈 멜로디 형태에 DelayAndReplace 연산 수행
            mc   = new MelodicContour(16);
            cost = mc.DelayAndReplaceNotes(0, new MelodicContourNote(16, 0));
            Console.WriteLine(cost);
            mc.Print();
        }