본문으로 건너뛰기

· 약 3분
karais89

Instructions

Given two arrays a and b write a function comp(a, b) (compSame(a, b) in Clojure) that checks whether the two arrays have the "same" elements, with the same multiplicities. "Same" means, here, that the elements in b are the elements in a squared, regardless of the order.

Examples Valid arrays

a = [121, 144, 19, 161, 19, 144, 19, 11]
b = [121, 14641, 20736, 361, 25921, 361, 20736, 361]

comp(a, b) returns true because in b 121 is the square of 11, 14641 is the square of 121, 20736 the square of 144, 361 the square of 19, 25921 the square of 161, and so on. It gets obvious if we write b's elements in terms of squares:

a = [121, 144, 19, 161, 19, 144, 19, 11]
b = [11*11, 121*121, 144*144, 19*19, 161*161, 19*19, 144*144, 19*19]

Invalid arrays If we change the first number to something else, comp may not return true anymore:

a = [121, 144, 19, 161, 19, 144, 19, 11]
b = [132, 14641, 20736, 361, 25921, 361, 20736, 361]

comp(a,b) returns false because in b 132 is not the square of any number of a.

a = [121, 144, 19, 161, 19, 144, 19, 11]
b = [121, 14641, 20736, 36100, 25921, 361, 20736, 361]

comp(a,b) returns false because in b 36100 is not the square of any number of a.

Remarks a or b might be [] (all languages except R, Shell). a or b might be nil or null or None or nothing (except in Haskell, Elixir, C++, Rust, R, Shell).

If a or b are nil (or null or None), the problem doesn't make sense so return false.

If a or b are empty the result is evident by itself.

My Solution

using System;
using System.Collections.Generic;

class AreTheySame
{
public static bool comp(int[] a, int[] b)
{
if (a == null || b == null)
{
return false;
}

if (a.Length != b.Length)
{
return false;
}

List<int> bList = new List<int>(b);
for (int i = 0; i < a.Length; i++)
{
int mulVal = a[i] * a[i];
for (int j = 0; j < bList.Count; j++)
{
if (bList[j] == mulVal)
{
bList.RemoveAt(j);
break;
}
}
}

return bList.Count == 0;
}
}

b 배열을 리스트로 만든 후 값이 일치할 경우 bList에서 값을 제거해주는 방식. 맨 마지막에 bList에 크기가 0이면 a와 모두 일치하다고 판단하고 true를 리턴해주고 아니면 모두 일치하지는 않으므로 false를 리턴해준다.

if (a.Length != b.Length)
{
return false;
}

이 부분은 필요 없어도 동작 할듯.

Best Practices

using System;
using System.Linq;

class AreTheySame
{
public static bool comp(int[] a, int[] b)
{
if ((a == null) || (b == null)){
return false;
}

int[] copy = a.Select(x => x * x).ToArray();
Array.Sort(copy);
Array.Sort(b);

return copy.SequenceEqual(b);
}
}

Linq를 사용하였다. 각 값을 제곱한 배열을 만든 후 배열의 값을 모두 정렬 시킨 후 (Select) 일치하는지 확인하는 함수(SequenceEqual)를 사용하여 해결 하였다.

· 약 3분
karais89

Instructions

The new "Avengers" movie has just been released! There are a lot of people at the cinema box office standing in a huge line. Each of them has a single 100, 50 or 25 dollars bill. An "Avengers" ticket costs 25 dollars.

Vasya is currently working as a clerk. He wants to sell a ticket to every single person in this line.

Can Vasya sell a ticket to each person and give the change if he initially has no money and sells the tickets strictly in the order people follow in the line?

Return YES, if Vasya can sell a ticket to each person and give the change with the bills he has at hand at that moment. Otherwise return NO.

Line.Tickets(new int[] {25, 25, 50}) // => YES
Line.Tickets(new int[] {25, 100}) // => NO. Vasya will not have enough money to give change to 100 dollars
Line.Tickets(new int[] {25, 25, 50, 50, 100}) // => NO. Vasya will not have the right bills to give 75 dollars of change (you can't make two bills of 25 from one of 50)

My Solution

using System;

public class Line
{
public static string Tickets(int[] peopleInLine)
{
int[] bills = new int[3];
for (int i = 0; i < peopleInLine.Length; i++)
{
int bill = peopleInLine[i];
if (bill == 25)
{
bills[0]++;
continue;
}

if (bill == 50)
{
bills[1]++;
if (bills[0] <= 0)
{
return "NO";
}
bills[0]--;
}
else if (peopleInLine[i] == 100)
{
bills[2]++;
if (bills[0] <= 0 || bills[1] <= 0)
{
return "NO";
}
bills[0]--;
bills[1]--;
}
}
return "YES";
}
}

문제 해결은 했는데 오류가 있다. 테스트 케이스에서 통과를 한 경우 인듯.. 100 달러를 냈을때 25달러 3개가 있는 경우에 대한 if문이 없다. 결국 이건 잘못된 코드 인듯 하다.

Best Practices

using System;

public class Line
{
public static string Tickets(int[] peopleInLine)
{
int twentyFives = 0, fifties = 0;

foreach (var bill in peopleInLine)
{
switch (bill)
{
case 25:
++twentyFives;
break;
case 50:
--twentyFives;
++fifties;
break;
case 100:
if (fifties == 0)
{
twentyFives -= 3;
}
else
{
--twentyFives;
--fifties;
}
break;
}

if (twentyFives < 0 || fifties < 0)
{
return "NO";
}
}

return "YES";
}
}

확실히 이 방법이 가장 깔끔한 방법인듯..

· 약 4분
karais89

Instructions

A bookseller has lots of books classified in 26 categories labeled A, B, ... Z. Each book has a code c of 3, 4, 5 or more capitals letters. The 1st letter of a code is the capital letter of the book category. In the bookseller's stocklist each code c is followed by a space and by a positive integer n (int n >= 0) which indicates the quantity of books of this code in stock.

For example an extract of one of the stocklists could be:

L = {"ABART 20", "CDXEF 50", "BKWRK 25", "BTSQZ 89", "DRTYM 60"}.

or

L = ["ABART 20", "CDXEF 50", "BKWRK 25", "BTSQZ 89", "DRTYM 60"] or ....

You will be given a stocklist (e.g. : L) and a list of categories in capital letters e.g :

  M = {"A", "B", "C", "W"}

or

  M = ["A", "B", "C", "W"] or ...

and your task is to find all the books of L with codes belonging to each category of M and to sum their quantity according to each category.

For the lists L and M of example you have to return the string (in Haskell/Clojure a list of pairs):

  (A : 20) - (B : 114) - (C : 50) - (W : 0)

where A, B, C, W are the categories, 20 is the sum of the unique book of category A, 114 the sum corresponding to "BKWRK" and "BTSQZ", 50 corresponding to "CDXEF" and 0 to category 'W' since there are no code beginning with W.

If L or M are empty return string is "" (Clojure should return an empty array instead).

Note: In the result codes and their values are in the same order as in M.

My Solution

using System;
using System.Collections.Generic;
public class StockList {
public static string stockSummary(String[] lstOfArt, String[] lstOf1stLetter) {
if (lstOfArt == null || lstOfArt.Length == 0 || lstOf1stLetter == null || lstOf1stLetter.Length == 0)
{
return string.Empty;
}
Dictionary<string, int> letterDic = new Dictionary<string, int>();
for (int i = 0; i < lstOf1stLetter.Length; i++)
{
for (int j = 0; j < lstOfArt.Length; j++)
{
if (lstOfArt[j].Substring(0, 1) == lstOf1stLetter[i])
{
if (letterDic.ContainsKey(lstOf1stLetter[i]))
{
letterDic[lstOf1stLetter[i]] += int.Parse(lstOfArt[j].Split()[1]);
}
else
{
letterDic[lstOf1stLetter[i]] = int.Parse(lstOfArt[j].Split()[1]);
}
}
}
}
string summary = string.Empty;
for (int i = 0; i < lstOf1stLetter.Length; i++)
{
if (letterDic.ContainsKey(lstOf1stLetter[i]))
{
summary += $"({lstOf1stLetter[i]} : {letterDic[lstOf1stLetter[i]]}) - ";
}
else
{
summary += $"({lstOf1stLetter[i]} : 0) - ";
}
}
summary = summary.Substring(0, summary.Length - 3);
return summary;
}
}

딕셔너리를 사용하여 합을 저장해서 풀어야지 라는 생각을 했다가 쓸데 없이 복잡해 진 것 같다.

생각해보니 굳이 딕셔너리를 안써도 되는 문제 였다..

" - " 기호를 제거하는 코드도 쓸데없이 지저분하다.

Best Practices 1

using System.Linq;

public class StockList {
public static string stockSummary(string[] lstOfArt, string[] lstOf1stLetter) {
if (!lstOfArt.Any()) return "";
return string.Join(" - ",
lstOf1stLetter.Select(c => string.Format("({0} : {1})", c,
lstOfArt.Where(a => a[0] == c[0]).Sum(a => int.Parse(a.Split(' ')[1])))));
}
}

Linq를 사용하면 언제나 코드가 짧아진다.

Best Practices 2

using System;
public class StockList {
public static string stockSummary(String[] lstOfArt, String[] lstOf1stLetter) {
if (lstOfArt.Length == 0) {
return "";
}
string result = "";
foreach (string m in lstOf1stLetter) {
int tot = 0;
foreach (string l in lstOfArt) {
if (l[0] == m[0]) {
tot += int.Parse(l.Split(' ')[1]);
}
}
if (!String.IsNullOrEmpty(result)) {
result += " - ";
}
result += "(" + m + " : " + tot + ")";
}
return result;
}
}

이렇게 풀면 되는 거였는데.. 너무 돌아간듯. " - " 붙이는 방식은 다시 생각 해보자.

· 약 2분
karais89

Instructions

Your task is to make function, which returns the sum of a sequence of integers.

The sequence is defined by 3 non-negative values: begin, end, step.

If begin value is greater than the end, function should returns 0

Examples

SequenceSum (2,2,2); // => 2
SequenceSum (2,6,2); // => 12 -> 2 + 4 + 6
SequenceSum (1,5,1); // => 15 -> 1 + 2 + 3 + 4 + 5
SequenceSum (1,5,3); // => 5 -> 1 + 4
This is the first kata in the series:

1) Sum of a sequence (this kata) 2) Sum of a Sequence [Hard-Core Version]

My Solution

public static class Kata 
{
public static int SequenceSum(int start, int end, int step)
{
int sum = 0;
for (int i = start; i <= end; i += step)
{
sum += i;
}
return sum;
}
}

기본적인 for문의 사용 방법만 알면 풀 수 있는 문제.

Best Practices 1

public static class Kata
{
public static int SequenceSum(int start, int end, int step)
{
int sum = 0;

for ( int i = start; i <= end; i += step)
{
sum += i;
}

return sum;
}
}

답은 일치 한다.

Best Practices 2

public static class Kata
{
public static int SequenceSum(int start, int end, int step)
{
return start == end ? end : start > end ? 0 : SequenceSum(start + step, end, step) + start;
}
}

표 자체는 많이 받지 못한 해답인데. 재귀 함수를 사용하여 푸는 방식을 사용 하였다.

· 약 7분
karais89

book image

기간

2일

목적

게임 프로그래머로 산다는 것.

게임 프로그래머의 5인의 이야기를 책으로 만날 수 있다.

현업에 종사하는 사람으로써 이 책을 안 보고 넘어 갈 수 없었다.

리뷰

게임을 만드는 사람들의 이야기다. "나는 이렇게 살고 있는데, 여러분은 어떻습니까?"라고 동료로서 선배로서 그들의 진솔한 이야기를 들려준다.

책의 특징

  • 게임 업계에 종사하는 5인의 이야기를 담고 있다.
  • 2016년 출판된 책이라 비교적 최신의 내용을 담고 있다.
  • 전문적인 내용 보다는 자신의 경험담 및 가치관에 대한 이야기라 쉽게 읽을 수 있다.
  • 업계에 오랫동안 종사하는 분들의 이야기라 앞으로의 나아갈 방향을 생각하게 만든다. (40~50대때의 나는 과연 어떤 모습일까?)
  • 각 챕터마다 수록되어 있는 각자의 인터뷰가 상당히 인상적이었다.

나의 결론

  • 나만의 게임을 만들자. (사이드 프로젝트, 토이 프로젝트, 펫 프로젝트 등등)
  • 수학, 영어는 매우 중요하다. (꾸준한 공부가 필요하다)
  • 자료구조, 알고리즘, 디자인 패턴, 소프트웨어 공학등의 기초가 중요하다.
  • 3D 그래픽스 개념 (DirectX, OpenGL)을 알면 개발이 쉬워진다.
  • 블로그는 꾸준히 하자.

책 내용 정리

김성완 (인디 개발자 인디라 운영)

  • 늙는것을 두려 하지 말고 매일매일 신나게 살았으면 한다.
  • 프로그래머는 절대로 꼰대가 되면 안 되는 것이다
  • 작은 것만 가지고도 용감하게 새로운 시도를 할 수 있고 그런 새로운 추구에 더 큰 박수를 보내는 이들이 바로 인디 게임 개발자들이다
  • 일주일에 하나씩 게임 만들기 http://goo.gl/POA5CA
  • 새로운 것을 두려워하지 않는 호기심과 나이에 상관없는 피터팬 정신이 필요합니다

정재원 (해외 취업 개발자)

  • 프로그래머를 움직이는 것은 최종 상품인 게임 보다도 기술에 대한 열정인 경우가 많다
  • 강요된 야근은 결국에는 더 큰 눈덩이가 되어 돌아오기 쉽다.
  • 프로그래밍의 근본이 수학이라고 믿는다
  • 프로그래밍 언어는 영어이다
  • 개발자로서 영어는 필수이다
  • 프로그래머 라도 사람들과의 의사소통이 중요하다
  • 글쓰기 실력을 늘리는 가장 효율적인 방법은 많은 글을 써 보는 것이다 블로그 글도 좋고 회사에서 요구하는 문서도 좋다
  • 읽기 쉽고 간결한 코드가 좋다
  • 실력 향상에는 의도적 공부가 필수다
    • 새로운 언어를 배우는 것
    • 개인 프로젝트를 하는 것
  • 지식 공유
    • 사내 컨퍼런스
    • 블로그
  • 오픈소스 라이브러리 제작
  • 프로는 자신의 결과물에 책임을지는 사람이다

이국현 (서버 개발자)

  • 연극의 화려한 무대는 클라이언트이고 무대뒤에 분주한 스텝들의 모습은 서버의 모습같이 느껴진다
  • 게임이라는 컨텐츠를 소비하는 사람이 되기 보다는 컨텐츠를 만드는 사람으로서의 역할에 더 충실해야 한다
  • 프로그래머는 몇 십만 원짜리 컴퓨터 한 대만 있으면 전 세계의 모든 기술을 습득할 수 있다

김상천 (50대 개발자)

  • 게임 엔진을 한 번 만들어 보라고 권하고 싶습니다 개발자로 성장하는데 많은 도움이 된다고 생각 합니다
  • 자기 관리에 대한 생각 프로젝트의 규모가 커지면서 소프트웨어 공학의 필요성을 느꼈다.
  • 외부의 많은 공개 소프트웨어를 열심히 분석했다.
  • 최신 OS에 대한 감각을 익힌다.

김용준 (해골책 저자)

  • 현재 국내에서는 대부분의 회사들이 상용엔진을 통해서 게임을 개발하고 있다.
  • 최근이 개발 추세는 엔진을 만드는 능력보다는 엔진을 잘 사용하는 쪽으로 초점이 맞춰지고 있다.
  • c언어는 해커를 위한 언어다. 컴퓨터에 대한 거의 무한대에 가까운 권한을 주면서, 프로그램에 문제가 생겼을 경우에 대한 무한대의 책임도 프로그래머에게 준다.
  • 3D 그래픽스의 기초 원리에 더 많은 이해가 필요한 것이다.
  • 수학(선형대수), 자료구조, 알고리즘

최영준 (강사)

  • 게임은 결국 수학 (삼각함수, 방정식에 대한 이해, 벡터, 행렬)
  • 엉덩이로 하는 공부 (기본적 물리 지식, 어느정도의 영어 독해 능력)
  • C/C++, API, 게임수학, DirectX, 엔진 프로그래밍에 순서로 골자를 잡고 디자인 패턴, 자료구조, 알고리즘 등의 살을 붙여나가는 공부 방식을 추천한다.

평점 및 한줄평

게임 프로그래머로서 게임 프로그래머의 이야기를 들을 수 있는 단비와 같은 책

4.5/5

· 약 3분
karais89

Instructions

In mathematics, the factorial of a non-negative integer n, denoted by n!, is the product of all positive integers less than or equal to n. For example: 5! = 5 4 3 2 1 = 120. By convention the value of 0! is 1.

Write a function to calculate factorial for a given input. If input is below 0 or above 12 throw an exception of type

ArgumentOutOfRangeException (C#) or IllegalArgumentException (Java) or RangeException (PHP) or throw a RangeError (JavaScript).

More details about factorial can be found here: http://en.wikipedia.org/wiki/Factorial

My Solution

using System;

public static class Kata
{
public static int Factorial(int n)
{
if (n < 0 || n > 12)
throw new ArgumentOutOfRangeException("invalid value");

int sum = 1;
for (int i = 1; i <= n; i++)
{
sum *= i;
}
return sum;
}
}

팩토리얼 문제. 예외를 발생시키는 코드는 사실 잘 사용하지 않아서.. 예외 발생 부분은 찾아봤다.

Best Practices 1

using System;

public static class Kata
{
public static int Factorial(int n)
{
if(n < 0 || n > 12)
throw new ArgumentOutOfRangeException();
return n > 0 ? n * Factorial(n - 1) : 1;
}
}

재귀 함수 사용. 재귀 함수 부분도 생각해 보았는데.. 속된말로 스택 뽕빨 난다..란 말이 있어서 그냥 시도 조차 안했다. 사실 문제에서는 12개 까지의 값을 제한 하기 때문에 어떻게 본다면 이게 가장 좋은 코드 일 수도 있을 것 같다.

Best Practices 2

using System;
using System.Linq;

public static class Kata
{
public static int Factorial(int n)
{
if(n < 0 || n > 12) throw new ArgumentOutOfRangeException();

return Enumerable.Range(1, n).Aggregate(1, (x,y) => x * y);
}
}

Aggregate란 메서드는 처음 봄.

확인해보니 누산기에 값을 누적해준다고 생각하면 될 듯.

1부터 시작해서 n까지의 값을 누적해서 계속 곱해준다고 생각하면 될듯.

https://docs.microsoft.com/ko-kr/dotnet/api/system.linq.enumerable.aggregate?view=netframework-4.7.2

· 약 3분
karais89

Instructions

You probably know the "like" system from Facebook and other pages. People can "like" blog posts, pictures or other items. We want to create the text that should be displayed next to such an item.

Implement a function likes :: [String] -> String, which must take in input array, containing the names of people who like an item. It must return the display text as shown in the examples:

Kata.Likes(new string[0]) => "no one likes this"
Kata.Likes(new string[] {"Peter"}) => "Peter likes this"
Kata.Likes(new string[] {"Jacob", "Alex"}) => "Jacob and Alex like this"
Kata.Likes(new string[] {"Max", "John", "Mark"}) => "Max, John and Mark like this"
Kata.Likes(new string[] {"Alex", "Jacob", "Mark", "Max"}) => "Alex, Jacob and 2 others like this"

For 4 or more names, the number in and 2 others simply increases.

My Solution

using System;

public static class Kata
{
public static string Likes(string[] name)
{
if (name == null || name.Length == 0)
{
return "no one likes this";
}
else if (name.Length == 1)
{
return $"{name[0]} likes this";
}
else if (name.Length == 2)
{
return $"{name[0]} and {name[1]} like this";
}
else if (name.Length == 3)
{
return $"{name[0]}, {name[1]} and {name[2]} like this";
}
return $"{name[0]}, {name[1]} and {name.Length-2} others like this";
}
}

풀면서 이런 해결 방법 밖에 없나? 라는 생각을 했는데.. 다른 방법은 없나 보다.

결국엔 if else 다.. 원래는 string.Format을 사용하려다가..

그냥 $ 표현을 사용 하였다.

$ 기호는 C# 6.0에서 추가된 문자열 보간 (Interpolated Strings) 이다.

Best Practices

public static class Kata
{
public static string Likes(string[] names)
{
switch (names.Length)
{
case 0: return "no one likes this"; // :(
case 1: return $"{names[0]} likes this";
case 2: return $"{names[0]} and {names[1]} like this";
case 3: return $"{names[0]}, {names[1]} and {names[2]} like this";
default: return $"{names[0]}, {names[1]} and {names.Length - 2} others like this";
}
}
}

if와 switch의 차이 정도.. 나의 코드에서는 names가 null이 아니라는 보장이 없어서, null 검사를 해줬었는데 여기서는 그런 null 체크 코드는 없다.

· 약 2분
karais89

Instructions

Given a string of digits, you should replace any digit below 5 with '0' and any digit 5 and above with '1'. Return the resulting string.

My Solution

public class Kata
{
public static string FakeBin(string x)
{
string copyX = "";
for (int i = 0; i < x.Length; i++)
{
if (x[i] < '5')
copyX += '0';
else
copyX += '1';
}
return copyX;
}
}

처음에 문제 자체를 이해를 못해서, 테스트 코드를 보고 이해 한 후 해결 하였다.

해결하고 보니 string을 for문에서 계속 더해주는 문제가 있네..

StringBuilder을 쓸걸 그랬다..

그리고 비교 자체를 문자열 자체로 비교한게 문제가 있지 않을까 싶었는데.. 그냥 다들 그렇게 하네..

Best Practices 1

using System.Linq;

public class Kata
{
public static string FakeBin(string x)
{
return string.Concat(x.Select(a => a < '5' ? "0" : "1"));
}
}

Linq를 사용하여 해결 하였다.

Best Practices 2

using System.Text;
public class Kata
{
public static string FakeBin(string x)
{
StringBuilder builder = new StringBuilder();

foreach (char t in x)
{
builder.Append( t >= '5' ? '1' : '0' );
}

return builder.ToString();
}
}

builder를 사용하였다. 그리고 for 대신 foreach 사용.

· 약 3분
karais89

Instructions

There is an array with some numbers. All numbers are equal except for one. Try to find it!

findUniq([ 1, 1, 1, 2, 1, 1 ]) === 2
findUniq([ 0, 0, 0.55, 0, 0 ]) === 0.55

It’s guaranteed that array contains more than 3 numbers.

The tests contain some very huge arrays, so think about performance.

This is the first kata in series:

  1. Find the unique number (this kata)
  2. Find the unique string
  3. Find The Unique

My Solution

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

public class Kata
{
public static int GetUnique(IEnumerable<int> numbers)
{
int count = -1;
int firstNum = 0;
int diffCount = 0;
int findNum = 0;
foreach (int num in numbers)
{
if (++count == 0)
{
firstNum = num;
continue;
}

if (num == firstNum)
continue;


diffCount++;
findNum = num;
}

if (diffCount == 1)
return findNum;
else
return firstNum;
}
}
  • 배열의 개수는 3개 이상이 보증된다.
  • 원소 중 1개를 제외하고는 모든 수가 똑같다. 다른 수를 리턴해야 된다.
  • IEnumerable로 받아서 foreach문으로 루프를 돌렸다.
  • 첫번째 원소의 숫자를 기준으로 비교를 함.

풀이 방법

  1. 첫번째 원소와 다른 숫자가 1개 이상 존재시(diffCount가 1이상)에는 첫번째 원소가 유일한 수
  2. 첫번째 원소와 다른 숫자가 1개 이면 findNum으로 대입된 숫자가 유일한 수 이다.

좋은 방법 같지는 않다.

Best Practices 1

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

public class Kata
{
public static int GetUnique(IEnumerable<int> numbers)
{
return numbers.GroupBy(x=>x).Single(x=> x.Count() == 1).Key;
}
}

Linq를 사용하면 한 줄이면 풀수 있는 문제..

Best Practices 2

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

public class Kata
{
public static int GetUnique(IEnumerable<int> numbers)
{
int[] numArray = numbers.ToArray();

int prevNum = numbers.First();
for (int i = 0; i < numArray.Length - 1; i++)
{
if (numArray[i] != prevNum){
if(numArray[i+1] == numArray[i])
return prevNum;
else
return numArray[i];
}
}

return 0;
}
}

ToArray 함수의 경우 메모리 많은 양의 메모리를 사용한다고 한다. 문제에서는 아주 큰 배열도 가능하게 처리해달라고 하여 해당 답안은 적절치 않다고 한다.

· 약 3분
karais89

Instructions

The museum of incredible dull things

The museum of incredible dull things wants to get rid of some exhibitions. Miriam, the interior architect, comes up with a plan to remove the most boring exhibitions. She gives them a rating, and then removes the one with the lowest rating.

However, just as she finished rating all exhibitions, she's off to an important fair, so she asks you to write a program that tells her the ratings of the items after one removed the lowest one. Fair enough.

Task

Given an array of integers, remove the smallest value. Do not mutate the original array/list. If there are multiple elements with the same value, remove the one with a lower index. If you get an empty array/list, return an empty array/list.

Don't change the order of the elements that are left.

Remover.RemoveSmallest(new List<int>{1,2,3,4,5}) = new List<int>{2,3,4,5}
Remover.RemoveSmallest(new List<int>{5,3,2,1,4}) = new List<int>{5,3,2,4}
Remover.RemoveSmallest(new List<int>{2,2,1,2,1}) = new List<int>{2,2,2,1}

My Solution

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

public class Remover
{
public static List<int> RemoveSmallest(List<int> numbers)
{
// Good Luck!
if (numbers == null || numbers.Count == 0)
{
return new List<int>() { };
}

int minVal = int.MaxValue;
int minIndex = 0;
for (int i = 0; i < numbers.Count; i++)
{
if (minVal > numbers[i])
{
minVal = numbers[i];
minIndex = i;
}
}

List<int> removeSmallests = new List<int>(numbers);
removeSmallests.RemoveAt(minIndex);
return removeSmallests;
}
}

문제 자체는 전달 받은 리스트의 값 변경 없이 최소 값을 뺀 리스트를 반환하는 문제이다.

전달 받은 리스트에서 최소값을 구하고, 그 리스트를 복사한후 최소값을 구한 인덱스를 빼준후 반환해 주는 식으로 구했다.

Best Practices

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

public class Remover
{
public static List<int> RemoveSmallest(List<int> numbers)
{
numbers.Remove(numbers.DefaultIfEmpty().Min());
return numbers;
}
}

Linq를 사용하여 해결 하였다. 하지만 목록을 복제하지는 않아서, 문제에서 요구하는 완벽한 해결 방법은 아닌거 같다.

DefaultIfEmpty

  • IEnumerable<T>의 요소를 반환하거나, 시퀀스가 비어 있으면 기본값이 할당된 singleton 컬렉션을 반환합니다

DefaultIfEmpty 메서드는 객체 자체가 null 일때의 예외 처리도 함께 되어 있다.

public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, TSource defaultValue)
{
if (source == null)
throw Error.ArgumentNull(nameof (source));
return Enumerable.DefaultIfEmptyIterator<TSource>(source, defaultValue);
}