HW2 GetFigureTypeFromName LINQ

public enum FigureType { Triangle, Square, Rectangle, Parallelogram, Rhombus, Trapezoid, Circle }

class Program
{
static Dictionary<string, FigureType> figureNameDic = new Dictionary<string, FigureType>();
static void SetFigureNameDictionary()
{
figureNameDic.Add(“삼각형”, FigureType.Triangle);
figureNameDic.Add(“Triangle”, FigureType.Triangle);
figureNameDic.Add(“TRIANGLE”, FigureType.Triangle);
figureNameDic.Add(“정사각형”, FigureType.Square);
figureNameDic.Add(“Square”, FigureType.Square);
figureNameDic.Add(“SQUARE”, FigureType.Square);
figureNameDic.Add(“직사각형”, FigureType.Rectangle);
figureNameDic.Add(“Rectangle”, FigureType.Rectangle);
figureNameDic.Add(“RECTANGLE”, FigureType.Rectangle);
figureNameDic.Add(“평행사변형”, FigureType.Parallelogram);
figureNameDic.Add(“Parallelogram”, FigureType.Parallelogram);
figureNameDic.Add(“PARALLELOGRAM”, FigureType.Parallelogram);
figureNameDic.Add(“마름모꼴”, FigureType.Rhombus);
figureNameDic.Add(“Rhombus”, FigureType.Rhombus);
figureNameDic.Add(“RHOMBUS”, FigureType.Rhombus);
figureNameDic.Add(“사다리꼴”, FigureType.Trapezoid);
figureNameDic.Add(“Trapezoid”, FigureType.Trapezoid);
figureNameDic.Add(“TRAPEZOID”, FigureType.Trapezoid);
figureNameDic.Add(“원”, FigureType.Circle);
figureNameDic.Add(“Circle”, FigureType.Circle);
figureNameDic.Add(“CIRCLE”, FigureType.Circle);
}

static FigureType? GetFigureTypeFromName(string str)
{
return figureNameDic.Where(x => x.Key.Contains(str)).Select(x => (FigureType?)x.Value).FirstOrDefault(); // FirstOrDefault returns the default value of a type if no item matches the predicate.
}

// 도형(Figure) 입력
static FigureType? GetInputFigure()
{
FigureType? inputFigure = null;
do
{
Console.Write(“도형의 종류를 입력해주세요(삼각형/정사각형/직사각형/평행사변형/마름모꼴/사다리꼴/원 등등 또는 Triangle/Square/Rectangle): “);
string str = Console.ReadLine();
inputFigure = GetFigureTypeFromName(str); // 입력된 도형에 따라서 enum 도형(Figure) 얻기
Console.WriteLine(“사용자 입력:{0} enum 도형:{1}”, str, inputFigure);
} while (inputFigure == null);
return inputFigure;
}

static void Main(string[] args)
{
SetFigureNameDictionary();
do
{
FigureType? inputFigure = GetInputFigure();
Console.WriteLine(“FigureType={0}”, inputFigure);
Console.WriteLine(“프로그램을 종료하려면 ESCAPE 키를 누르세요. 다시 계산하려면 ENTER 키를 누르세요.”);
} while (Console.ReadKey().Key != ConsoleKey.Escape);
}
}

Array.ConvertAll

https://msdn.microsoft.com/ko-kr/library/kt456a2y(v=vs.110).aspx

public delegate TOutput Converter<in TInput, out TOutput>(
TInput input
)

 static System.Drawing.Point Point2DrawingPoint(Point p)
{
     return (System.Drawing.Point)p;
}

static void Main(string[] args)
{

List<Point> Vertices = new List<Point>()
{
new Point() { X = 400, Y = 10 },
new Point() { X = 300, Y = 210 },
new Point() { X = 500, Y = 210 }
};

// 1. Lambda expression
System.Drawing.Point[] points1 = Array.ConvertAll(Vertices.ToArray(), x => (System.Drawing.Point)x); // Use with Point.cs type conversion operator overload

// 2. Anonymous method
System.Drawing.Point[] points2 = Array.ConvertAll(Vertices.ToArray(), delegate(Point x) { return (System.Drawing.Point)x; });

// 3. Delegate (Converter<TInput, TOutput>)
System.Drawing.Point[] points3 = Array.ConvertAll(Vertices.ToArray(), new Converter<Point, System.Drawing.Point>(Point2DrawingPoint));

foreach (var v in Vertices)
Console.WriteLine(v);
foreach (var p in points1)
Console.WriteLine(p);
foreach (var p in points2)
Console.WriteLine(p);
foreach (var p in points3)
Console.WriteLine(p);

}

LINQ

    class Category
    {
        public string Name { get; set; }
        public int ID { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // The Three Parts of a LINQ Query:
            //  1. Data source.
            int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

            // 2. Query creation.
            // numQuery is an IEnumerable<int>
            var numQuery =
                from num in numbers
                where (num % 2) == 0
                select num;

            // 3. Query execution.
            foreach (int num in numQuery)
            {
                Console.Write(“{0,1} “, num);
            }
            Console.WriteLine();

            // LIST
            List<Person> pList = new List<Person>();
            pList.Add(new Person(“둘리”, 1, “123-4568-9012”, “대한민국”));
            pList.Add(new Person(“희동이”, 3, “000-0000-0000”, “서울”));
            pList.Add(new Person(“고길동”, 2, “000-0000-0000”, “서울”));
            pList.Add(new Person(“도우너”, 5, “000-0000-0000”, “온따빠야별”));
            pList.Add(new Person(“또치”, 4, “000-0000-0000”, “미국”));
            pList.Insert(2, new Person(“마이콜”, 6, “000-0000-0000”, “서울”));

            // query syntax

            IEnumerable<Person> seoulQuery =
                from per in pList
                where per.Address == “서울”
                select per;

            foreach (var per in seoulQuery)
            {
                Console.WriteLine(per.Name + “, ” + per.ID);
            }
            Console.WriteLine();

            // query syntax
            IEnumerable<Person> personQuery =
                from p in pList
                where (p.ID < 2) || (p.Address == “서울”)
                orderby p.Name ascending
                select p;

            foreach (var p in personQuery)
            {
                Console.WriteLine(p.Name + “, ” + p.ID);
            }
            Console.WriteLine();

            // method syntax
            IEnumerable<Person> personQuery2 = pList.Where(p => (p.ID < 2) || (p.Address == “서울”)).OrderBy(p => p);
            foreach (var p in personQuery2)
            {
                Console.WriteLine(p.Name + “, ” + p.ID);
            }
            Console.WriteLine();

            // JOIN
            List<Category> categories = new List<Category>()
            {
                new Category() { Name=”서울”, ID=1 },
                new Category() { Name=”대한민국”, ID=2 },
                new Category() { Name=”미국”, ID=3 },
                new Category() { Name=”온따빠야별”, ID=4 },
            };

            var query = from p in pList
                        join cat in categories on p.Address equals cat.Name
                        select new
                        {
                            p.Name,
                            p.Address,
                            cat.ID
                        };
            Console.WriteLine(“Join Query”);
            foreach (var q in query)
            {
                Console.WriteLine(q.Name + “, ” + q.Address + “, ” + q.ID);
            }
            Console.WriteLine();
        }
    }

 

 

// 결과

0 2 4 6
희동이, 3
마이콜, 6
고길동, 2

고길동, 2
둘리, 1
마이콜, 6
희동이, 3

고길동, 2
둘리, 1
마이콜, 6
희동이, 3

Join Query
둘리, 대한민국, 2
희동이, 서울, 1
마이콜, 서울, 1
고길동, 서울, 1
도우너, 온따빠야별, 4
또치, 미국, 3

COLLECTION, INTERFACE, DELEGATE

1. Collection 
서로 밀접하게 관련된 데이터를 그룹화하여 좀 더 효율적으로 처리할 수 있게 한 특수한 클래스 혹은 구조체이다.

 

2. Collection과 Interface
모든 닷넷 컬렉션은 ICollection<T> 인터페이스는 구현한다. 
IList<T> 인터페이스는 인덱스를 사용하여 요소에 개별적으로 접근할 수 있는 컬렉션을 정의한다.
-T this [int index] { get; set; } //지정한 인덱스에 있는 요소를 가져오거나 설정
-int IndexOf(T item) //IList에서 특정 항목의 인덱스를 확인
-void Insert(int index, T item) //항목을 IList의 지정한 인덱스에 삽입
-void RemoveAt(int index) //지정한 인덱스에서 IList 항목을 제거

 

3. Collection과 Method와 Delegate
// Person 클래스
public class Person
{
private readonly string _name;

 

public string Name
{
get { return _name; }
}

 

private readonly int _age;

 

public int Age
{
get { return _age; }
}

 

public Person(string name, int age)
{
_name = name;
_age = age;
}

 

public override string ToString()
{
return string.Format(“이름 : {0}\t나이 : {1}”, _name, _age);
}
}

 

// List<T> 컬렉션에 Person 객체를 담는다
private static void Main(string[] args)
{
List<Person> aList = new List<Person>();
aList.Add(new Person(“둘리”, 1000));
aList.Add(new Person(“희동이”, 3));
aList.Add(new Person(“고길동”, 40));
}

 

// aList에 포함된 세 사람이 모두 10세 이상인지를 확인한다 => 둘리와 고길동만 만족함
private static void Main(string[] args)
{
List<Person> aList = new List<Person>();
aList.Add(new Person(“둘리”, 1000));
aList.Add(new Person(“희동이”, 3));
aList.Add(new Person(“고길동”, 40));

 

bool result = true;
foreach (Person p in aList)
{
if (p.Age < 10)
{
result = false;
break;
}
}
}

 

// aList에 포함된 세 사람이 모두 이름이 두 글자인지를 확인한다 => 둘리만 만족함
private static void Main(string[] args)
{
List<Person> aList = new List<Person>();
aList.Add(new Person(“둘리”, 1000));
aList.Add(new Person(“희동이”, 3));
aList.Add(new Person(“고길동”, 40));

 

bool result = true;
foreach (Person p in aList)
{
if (p.Name.Length != 2)
{
result = false;
break;
}
}
}

 

// 위의 두 코드가 나이가 10세이상인지 또는 이름이 두 글자인지 조건을 만족하는지를 확인하는 부분이 반복
// List<T> 컬렉션의 TrueForAll 메소드는 조건을 만족하는 메소드가 존재한다면 true반환
public delegate bool Predicate<T>(T item);

 

public class List<T> : …
{

 

public bool TrueForAll(Predicate<T> match)
{
bool result = true;
foreach (T item in this)
{
if (match(item) == false)
{
result = false;
break;
}
}
}
}

 

private static void Main(string[] args)
{
List<Person> aList = new List<Person>();
aList.Add(new Person(“둘리”, 1000));
aList.Add(new Person(“희동이”, 3));
aList.Add(new Person(“고길동”, 40));

 

// 10살 이상인지를 검사
bool result1 = aList.TrueForAll(IsGreaterThanTen);

 

// 무명 대리자를 사용하여 이름이 두 글자인지 검사
bool result2 = aList.TrueForAll(delegate(Person p)
{ return p.Name.Length == 2; });
}

 

private static bool IsGreaterThanTen(Person p)
{
return p.Age >= 10;
}

4. List<T> 컬랙션 클래스의 메소드와 헬퍼 대리자

 

public List<TOutput> ConvertAll<TOutput> (Converter<T, TOutput> converter)
-리스트 객체의 각 원소를 TOutput 형으로 변환하여 리스트로 반환

 

public bool Exists(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 원소가 있는지 여부를 반환

 

public T Find(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 첫번째 원소를 반환

 

public List<T> FindAll(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 모든 원소를 리스트로 반환

 

public int FindIndex(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 첫번째 원소의 인덱스를 반환

 

public int FindLastIndex(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 마지막 원소의 인덱스를 반환

 

public void ForEach(Action<T> action)
-리스트에 있는 모든 원소에 대해 action을 수행

 

public bool TrueForAll(Predicate<T> match)
-리스트에 있는 모든 원소가 match 조건을 만족하는 지 여부를 반환

 

<<대리자(Delegate)>>

 

public delegate void Action<T>(T object)
-T 형의 매개변수를 하나 받고 반환값이 없는 메소드

 

public delegate TOutput Converter<TInput, TOutput>(TInput input)
-TInput 형의 매개변수를 받고 이를 TOutput 형으로 변환하여 반환하는 메소드

 

public delegate bool Predicate<T>(T object)
-T 형의 매개변수를 받아 그것이 특정 조건을 만족하는지를 반환하는 메소드

 

public delegate int Comparison<T>(T x, T y)
-x, y 두 객체를 비교하는 메소드로 x가 y보다 작으면 음수, 같으면 0, 크면 양수를 반환하는 메소드

 

5. List<T>의 Sort 메소드
public void Sort()
public void Sort(Comparison<T> comparison)
public void Sort(IComparer<T> comparer)
public void Sort(int index, int count, IComparer<T> comparer)

 

-public void Sort()
즉, 매개변수가 없는 Sort 메서드(void Sort())는 List<T>의 원소인 객체와 계약을 맺었는데, 
그 계약의 내용은 List<T>의 원소인 객체는 int CompareTo(T other)와 같은 메서드를 가지고 있다는 것입니다. 
따라서 실제 List<T>의 원소의 객체가 무엇이든지 간에 Sort 메서드는 그 객체의 CompareTo 메서드를 호출하면 정렬을 수행할 수 있다.
List<T>의 원소인 객체는 int CompareTo(T other)를 구현하여야 한다. 
즉, Person이 int CompareTo(Person other) 메소드에 이름 순으로 구현하여야 계약이 성립한다.

 

public class Person : IComparable<Person>
{
….

// Sort
public int CompareTo(Person other)
{
return this.Name.CompareTo(other.Name);
}
}

 

private static void Main(string[] args)
{
List<Person> aList = new List<Person>();
aList.Add(new Person(“둘리”, 1000));
aList.Add(new Person(“희동이”, 3));
aList.Add(new Person(“고길동”, 40));

 

// 이름순으로 정렬
aList.Sort();
}

-public void Sort(Comparison<T> comparison)
이번에는 이름이 아니라 나이 순으로 정렬을 하는 경우, 
int CompareTo(Person other) 내부 구현을 이름이 아니라 나이를 기준으로 정렬하도록 수정한다.
이 경우 동적으로 Sort를 다르게 할수없는 문제가 있으므로, 
List<T>의 원소를 비교 가능한 객체라고 전제 하는 것이 아니라, 
Sort 메서드의 매개 변수로 아예 List<T>의 원소들을 비교하는 메서드를 전달하는 것입니다.

public delegate int Comparison<T>(T x, T y)
Comparison 대리자의 의미는 x가 y보다 작으면 음수, 같으면 0, 크면 양수를 반환한다는 것이다.

public static int ComparePersonByName(Person x, Person y)
{
return x.Name.CompareTo(y.Name);
}

public static int ComparePersonByAge(Person x, Person y)
{
return x.Age.CompareTo(y.Age);
}

 

private static void Main(string[] args)
{
List<Person> aList = new List<Person>();
aList.Add(new Person(“둘리”, 1000));
aList.Add(new Person(“희동이”, 3));
aList.Add(new Person(“고길동”, 40));

 

// 이름순으로 정렬
aList.Sort(ComparePersonByName);
// 나이순으로 정렬
aList.Sort(ComparePersonByAge);
}

-public void Sort(IComparer<T> comparer)
Sort가 IComparer<T> 인터페이스를 매개변수로 받아 처리할 수 있다.
int Compare(T x, T y)

public class PersonNameComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x.Name.CompareTo(y.Name);
}
}

 

public class PersonAgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x.Age.CompareTo(y.Age);
}
}

 

private static void Main(string[] args)
{
List<Person> aList = new List<Person>();
aList.Add(new Person(“둘리”, 1000));
aList.Add(new Person(“희동이”, 3));
aList.Add(new Person(“고길동”, 40));

 

// 이름순으로 정렬
aList.Sort(new PersonNameComparer());
// 나이순으로 정렬
aList.Sort(new PersonAgeComparer());

 

foreach(Person p in aList)
Console.WriteLine(p); // Person의 ToString 호출
}

C# Collection Interface Delegate

CollectionInterfaceDelegateFileIOTest

http://msdn.microsoft.com/en-us/library/system.collections.generic(v=VS.80).aspx

Collections (예로, List, ArrayList, Hashtable등)은 ICollection<T> 인터페이스를 구현한다.
List 클래스의 경우는 IList<T> 인터페이스를 또한 구현한다.

List<T> 컬랙션 클래스의 메소드 (예를 들어, Exists, Find, TrueForAll 등)는 특정 헬퍼대리자 (예를 들어, delegate void Action<T>, delegate bool Predicate<T> 등과 같은)를 사용하여, 중복되는 코드를 간결하게 만들수있다.

HW3

단국대학교 멀티미디어공학전공 HCI프로그래밍2 (2015년 가을학기) 실습

날짜: 2015년 10월 30일

 

– 실습번호 : lab-03 (Due by 11/17)

– 실습제목 : collections, class, FileIO, LINQ

– 실습요약 : 평면 도형의 점들 입력 값으로 도형 판별하기 및 영역과 둘레 계산하기 및 쿼리

– 준비자료 : https://www.mathsisfun.com/geometry/quadrilaterals-interactive.html

 

– 실습문제

public enum FigureType // FigureType 판별
{
Triangle,
EquilateralTriangle,
IsoscelesTriangle,
ScaleneTriangle,
Quadrilateral,
Square,
Rectangle,
Parallelogram,
Rhombus,
Trapezoid,
None
}

 

  1. Point 클래스를 작성한다.

+ public int X { get;  set; }

+ public int Y { get;  set; }

+ public static implicit operator System.Drawing.Point(Point p) {

Return new System.Drawing.Point(p.x, p.y);

}

 

  1. Figure 추상클래스를 상속 받아 Triangle, Quadrilateral 클래스를 작성한다.

public class FigureTypeResolver : JavaScriptTypeResolver // JSON serialization & deserialization
{
public override Type ResolveType(string id)
{
return Type.GetType(id);
}

public override string ResolveTypeId(Type type)
{
if (type == null)
{
throw new ArgumentNullException(“type”);
}

return type.FullName;
}
}

public class FigureBound // TopLeft Point(X,Y) & Width & Height
{
public int X
{
set;
get;
}

public int Y
{
set;
get;
}

public int Width
{
set;
get;
}

public int Height
{
set;
get;
}

public FigureBound() : this (0, 0, 10, 10)
{
}

public FigureBound(int x, int y, int width, int height)
{
Set(x, y, width, height);
}

public void Set(int x, int y, int width, int height)
{
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
}
public override string ToString() { return (String.Format(“({0}, {1}, {2}, {3})”, X, Y, Width, Height)); } // ToString method override
}

public abstract class Figure // Figure 추상 클래스
{
public ConsoleColor Color
{
get;
set;
}

protected List<Point> vertices = null;
public List<Point> Vertices // Use Point.cs (Not System.Drawing.Point) for JSON
{
get
{
return vertices;
}
set
{
vertices = value;
UpdateBounds(); // 새 정점에 따른 바운딩박스 계산
UpdateSides(); // 새 정점에 따른 변들 계산
UpdateAngles(); // 새 정점에 따른 내각들 계산
}
}

public FigureBound Bounds = new FigureBound(); // 바운딩박스

public List<double> Sides // 변
{
get;
set;
}

public List<double> Angles // 내각 (radian)
{
get;
set;
}

public abstract void UpdateBounds();
public abstract void UpdateSides();
public abstract void UpdateAngles();

public void Draw(Graphics g) { // 도형 그리기

Brush b = new

SolidBrush(System.Drawing.Color.FromName(this.Color.ToString())));

System.Drawing.Point[] points = Array.ConvertAll(Vertices.ToArray(),

x => (System.Drawing.Point)x);

g.FillPolygon(b, points);

}

}

 

  1. FigureCalculator 클래스는 도형의 점들 입력 값으로부터 도형의 판별 및 도형의 면적과 둘레 계산을 담당한다.

+ public void GetUserInputFigure() // 사용자로부터 도형의 점을 입력 (3점과 4점만 입력 받도록 함) (optional)

+ public FigureType GetFigureType() // 무슨 도형인지 판별 (정삼각형, 이등변삼각형, 부등변삼각형 또는 정사각형, 직사각형, 평행사변형, 마름모, 사다리꼴 등)

+ public double Area(FigureType type, Figure figure) // 도형의 면적 계산

+ public double Perimeter(FigureType type, Figure figure) // 도형의 둘레 계산

 

  1. FigureManager 클래스는 File IO 입출력을 담당한다.

+ JSON을 이용한 파일 입출력 (JSON 형태로 저장한 도형의 리스트를 figureList에 import & 사용자가 추가로 입력한 도형의 정보를 포함하는 figureList를 파일로 export)

 

  1. FigureManager클래스 또는 Program 클래스의 Main 함수에서 본인이 더 테스트해보고 싶은 Method를 추가하라. 디렉토리에 여러 개의 데이터를 읽어서, 여러 가지 방법으로 정렬 및 LINQ 쿼리를 한 후 새로운 파일에 저장한다. 등등. 실행 화면과 코드를 첨부하시오.

+ List<Figure> figureList = new List<Figure>(); // 도형의 리스트

// LINQ를 이용하여 리스트에서 사다리꼴(Trapezoid)만 List로 추출

– public IList<Figure> GetTrapezoid () { // 내부구현 필요 – LINQ ToList() 사용 }

// LINQ를 이용하여 리스트에서 지정한 영역 값보다 작은 도형만 List로 추출

– public IList<Figure> GetFigureAreaLessThan(double area) { // 내부구현 필요 – LINQ ToList() 사용 }

 

HashCode

MSDN says:

A hash code is a numeric value that is used to identify an object during equality testing. It can also serve as an index for an object in a collection.

The GetHashCode method is suitable for use in hashing algorithms and data structures such as a hash table.

The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes.

The GetHashCode method can be overridden by a derived type. Value types must override this method to provide a hash function that is appropriate for that type and to provide a useful distribution in a hash table. For uniqueness, the hash code must be based on the value of an instance field or property instead of a static field or property.

Objects used as a key in a Hashtable object must also override the GetHashCode method because those objects must generate their own hash code. If an object used as a key does not provide a useful implementation of GetHashCode, you can specify a hash code provider when the Hashtable object is constructed. Prior to the .NET Framework version 2.0, the hash code provider was based on the System.Collections.IHashCodeProvider interface. Starting with version 2.0, the hash code provider is based on the System.Collections.IEqualityComparer interface.

Basically, hash codes exist to make hashtables possible.
Two equal objects are guaranteed to have equal hashcodes.
Two unequal objects are not guaranteed to have unequal hashcodes (that’s called a collision).