본문으로 건너뛰기

"kata" 태그로 연결된 63개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 2분
karais89

Instructions

Given a node object representing a binary tree:

Node:
value: <int>,
left: <Node> or null,
right: <Node> or null

Node:
value: <int>,
left: <Node> or null,
right: <Node> or null

struct node
{
int value;
node* left;
node* right;
}

public class Node
{
public int Value;
public Node Left;
public Node Right;

public Node(int value, Node left = null, Node right = null)
{
Value = value;
Left = left;
Right = right;
}
}

write a function that returns the sum of all values, including the root. Absence of a node will be indicated with a null value.

10
| \
1 2
=> 13

1
| \
0 0
\
2
=> 3

My Solution

using System;
using System.Collections.Generic;

public static class Kata
{
public static int SumTree(Node root)
{
return RecusiveTree(root);
}

public static int RecusiveTree(Node root)
{
if (root == null)
{
return 0;
}

if (root.Left == null && root.Right == null)
{
return root.Value;
}

if (root.Left != null && root.Right != null)
{
return root.Value + RecusiveTree(root.Left) + RecusiveTree(root.Right);
}
else if (root.Right != null)
{
return root.Value + RecusiveTree(root.Right);
}
else if (root.Left != null)
{
return root.Value + RecusiveTree(root.Left);
}
return 0;
}
}

전체 트리의 합 구하는 문제

트리의 합은 재귀 호출 밖에 없나?? 라는 생각을 하면서 재귀 호출을 사용하여 구하였다..

Best Practices

using System;

public static class Kata
{
public static int SumTree(Node root)
{
return root == null ? 0 : root.Value + SumTree(root.Left) + SumTree(root.Right);
}
}

재귀 호출을 사용하여 해결 한줄로 짤 수 있는 코드 였구나..

쓸데 없는 비교 검사문등을 집어 넣어서, 코드가 길어 졌다. 반성 하자.

재귀 호출을 사용하지 않고 해결하는 방법

public static void preTraverseNoRec(Node root){
Stack<Node> stack = new Stack<eNode>();
stack.push(root);
while(stack.size()!=0) {
Node node = stack.pop();
System.out.println(node.data);
if(node.right != null) stack.push(node.right);
if(node.left != null) stack.push(node.left);
}
}

· 약 3분
karais89

Instructions

In this kata you parse RGB colors represented by strings. The formats are primarily used in HTML and CSS. Your task is to implement a function which takes a color as a string and returns the parsed color as a map (see Examples).

Input: The input string represents one of the following:

  • 6-digit hexadecimal - "#RRGGBB" e.g. "#012345", "#789abc", "#FFA077" Each pair of digits represents a value of the channel in hexadecimal: 00 to FF
  • 3-digit hexadecimal - "#RGB" e.g. "#012", "#aaa", "#F5A" Each digit represents a value 0 to F which translates to 2-digit hexadecimal: 0->00, 1->11, 2->22, and so on.
  • Preset color name e.g. "red", "BLUE", "LimeGreen" You have to use the predefined map PRESET_COLORS (JavaScript, Python, Ruby), presetColors (Java, C#, Haskell), or preset-colors (Clojure). The keys are the names of preset colors in lower-case and the values are the corresponding colors in 6-digit hexadecimal (same as 1. "#RRGGBB").
Parse("#80FFA0") === new RGB(128, 255, 160))
Parse("#3B7") === new RGB( 51, 187, 119))
Parse("LimeGreen") === new RGB( 50, 205, 50))

// RGB struct is defined as follows:
struct RGB
{
public byte r, g, b;
public RGB(byte r, byte g, byte b);
}

My Solution

using System;
using System.Collections.Generic;

class HtmlColorParser
{
private readonly IDictionary<string, string> presetColors;

public HtmlColorParser(IDictionary<string, string> presetColors)
{
this.presetColors = presetColors;
}

public RGB Parse(string color)
{
string sixDigit = color;
if (color.Substring(0, 1) == "#")
{
if (color.Length == 4)
{
string r = color.Substring(1, 1);
string g = color.Substring(2, 1);
string b = color.Substring(3, 1);

sixDigit = $"#{r}{r}{g}{g}{b}{b}";
}
}
else
{
string colorLow = color.ToLower();
sixDigit = presetColors[colorLow];
}

byte[] rgb = new byte[3];
for (int i = 0; i < rgb.Length; i++)
{
string hex = sixDigit.Substring((i*2) + 1, 2);
rgb[i] = Convert.ToByte(hex, 16);
}

return new RGB(rgb[0], rgb[1], rgb[2]);
}
}

3-digit일때 굳이 Substring으로 변환 하나하나 받아와서 사용하지 않고, 바로 인덱스에 접근하면 되는데.. 쓸데 없는 짓을 했네..

Best Practices

using System;
using System.Collections.Generic;

class HtmlColorParser
{
private readonly IDictionary<string, string> presetColors;

public HtmlColorParser(IDictionary<string, string> presetColors)
{
this.presetColors = presetColors;
}

public RGB Parse(string color)
{
color = color.ToLower();
string hex;

if (presetColors.ContainsKey(color))
hex = presetColors[color];
else if (color.Length == 4)
hex = string.Format("#{0}{0}{1}{1}{2}{2}", color[1], color[2], color[3]);
else
hex = color;

var n = Convert.ToInt32(hex.Substring(1), 16);
return new RGB((byte)((n >> 16) & 0xFF), (byte)((n >> 8) & 0xFF), (byte)(n & 0xFF));
}
}

제일 높은 표이긴 한데 표 자체가 2개 밖에 없어서 추가 검증이 필요하다. 지금 문제 푸는게 최신 문제 위주로 문제가 주어지나 싶다..

16진수를 RGB 값으로 변환할때 여기서는 그냥 바로 스트링값 전부를 int로 변환했다. 그리고 비트 연산자와 & 연산자를 사용하여 각 값들을 추출해서 사용 함. 이 부분을 좀 볼 필요가 있을 듯하다.

· 약 4분
karais89

Instructions

Longest Palindrome

Find the length of the longest substring in the given string s that is the same in reverse.

As an example, if the input was “I like racecars that go fast”, the substring (racecar) length would be 7.

If the length of the input string is 0, the return value must be 0.

"a" -> 1
"aab" -> 2
"abcde" -> 1
"zzbaabcd" -> 4
"" -> 0

My Solution

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

public class Kata
{
public static string ReverseString(string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}

public static int GetLongestPalindrome(string str)
{
//your code :)
if (str == null || str.Length == 0)
{
return 0;
}

// 맨 처음 글자와 맨 마지막 글자가 일치하고, 점 점 차이를 좁히면서 모두 일치하면 회문이다?
// 아니면 그냥 처음문자를 뒤집은것과 일치하면 회문?
int longestVal = 0;

// 회문 판단
for (int i = 0; i < str.Length; i++)
{
char ch = str[i];
for (int j = str.Length - 1; j >= i; j--)
{
if (ch != str[j])
{
continue;
}

string subStr = str.Substring(i, j-i+1);
if (subStr == ReverseString(subStr))
{
if (longestVal < subStr.Length)
{
longestVal = subStr.Length;
}
}
}
}

return longestVal;
}
}

회문 판단 알고리즘

내 해결책은 먼저 첫번째 문자 부터 판단하여, 가장 마지막 문자에서부터 문자가 같은지 판단한다. 만약 문자가 같으면 회문이 될 가능성이 있는 문장이므로, ReverseString으로 문자를 뒤짚어도 같은 문자열인지 판단할 후 있다.

Best Practices 1

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

public class Kata
{
public static int GetLongestPalindrome(string str)
{
//Case String is Null or Empty
if (string.IsNullOrEmpty(str)) return 0;
//Variable to store the length of the longest reversible word
int longest = 0;
//Array with all the subtrings in the string passed to the function
string [] subStrs = GetSubstrings(str);
//For each string in the array verify if it is reversible and if it is,
//compare its length with longest
foreach (string s in subStrs)
longest = IsReversible(s) && s.Length > longest ? s.Length :
longest;
return longest;
}

//Function that verifies if a word is reversible
public static bool IsReversible(string word)
{
char [] temp = word.ToCharArray();
Array.Reverse(temp);
string revWord = new string (temp);
//Console.WriteLine(word + " " + revWord);
return (revWord != word) ? false : true;
}

//Function that gets an array of all the substrings in a string
public static string [] GetSubstrings(string word)
{
int count = 0;
int length = word.Length;
List<string> Substrs = new List<string>();
for (int i = 0; i < word.Length; i++)
{
Substrs.Add(word.Substring(i));
for (int j = 1; j < length; j++)
{
Substrs.Add(word.Substring(i,j));
}
length--;
}
return Substrs.ToArray();
}
}

표 3개를 획득한 답안이다.

Best Practices 2

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

public class Kata
{
public static bool IsPalindrome(string str)
{
var arr = str.ToCharArray();
Array.Reverse(arr);
var reversed = new string(arr);
return str == reversed;
}

public static int GetLongestPalindrome(string str)
{
if (str == null)
return 0;

int max = 0;
for (int i = 0; i < str.Length; ++i)
for (int j = i; j < str.Length; ++j)
if (IsPalindrome(str.Substring(i, j - i + 1)))
max = Math.Max(max, j - i + 1);

return max;
}
}

이게 더 깔끔한 방법 인듯 하다.

· 약 4분
karais89

Instructions

The prime numbers are not regularly spaced. For example from 2 to 3 the step is 1. From 3 to 5 the step is 2. From 7 to 11 it is 4. Between 2 and 50 we have the following pairs of 2-steps primes:

3, 5 - 5, 7, - 11, 13, - 17, 19, - 29, 31, - 41, 43

We will write a function step with parameters:

  • g (integer >= 2) which indicates the step we are looking for,
  • m (integer >= 2) which gives the start of the search (m inclusive),
  • n (integer >= m) which gives the end of the search (n inclusive)

In the example above step(2, 2, 50) will return [3, 5] which is the first pair between 2 and 50 with a 2-steps.

So this function should return the first pair of the two prime numbers spaced with a step of g between the limits m, n if these g-steps prime numbers exist otherwise nil or null or None or Nothing or [] or "0, 0" or {0, 0} (depending on the language).

Examples:

step(2, 5, 7) --> [5, 7] or (5, 7) or {5, 7} or "5 7"

step(2, 5, 5) --> nil or ... or [] in Ocaml or {0, 0} in C++

step(4, 130, 200) --> [163, 167] or (163, 167) or {163, 167}

See more examples for your language in "RUN" Remarks: ([193, 197] is also such a 2-steps primes between 130 and 200 but it's not the first pair).

step(6, 100, 110) --> [101, 107] though there is a prime between 101 and 107 which is 103; the pair 101-103 is a 2-step.

Notes: The idea of "step" is close to that of "gap" but it is not exactly the same. For those interested they can have a look at http://mathworld.wolfram.com/PrimeGaps.html.

A "gap" is more restrictive: there must be no primes in between (101-107 is a "step" but not a "gap". Next kata will be about "gaps":-).

For Go: nil slice is expected when there are no step between m and n. Example: step(2,4900,4919) --> nil

FUNDAMENTALSNUMBERS

Poweredby qualified Solution:

class StepInPrimes { public static long[] Step(int g, long m, long n) { // your code } } Sample Tests:

using System; using NUnit.Framework;

[TestFixture] public static class StepInPrimesTests {

[Test] public static void test1() {

My Solution

using System;
using System.Text;
public class Kata
{
public static string[] TowerBuilder(int nFloors)
{
string[] towers = new string[nFloors];
int totalCnt = nFloors * 2 - 1;
for (int i = 0; i < nFloors; i++)
{
int spaceCnt = (nFloors - 1 - i) * 2;
int starCnt = totalCnt - spaceCnt;
towers[i] = MakeTowerStr(spaceCnt, starCnt);
}
return towers;
}
private static string MakeTowerStr(int spaceCnt, int starCnt)
{
int halfSpaceCnt = spaceCnt / 2;
StringBuilder sb = new StringBuilder();
// before space
for (int i = 0; i < halfSpaceCnt; i++)
{
sb.Append(" ");
}
// star
for (int i = 0; i < starCnt; i++)
{
sb.Append("*");
}
// after space
for (int i = 0; i < halfSpaceCnt; i++)
{
sb.Append(" ");
}
return sb.ToString();
}
}

학부때 많이 했던 별 찍기 문제.

Best Practices

public class Kata
{
public static string[] TowerBuilder(int nFloors)
{
var result = new string[nFloors];
for(int i=0;i<nFloors;i++)
result[i] = string.Concat(new string(' ',nFloors - i - 1),
new string('*',i * 2 + 1),
new string(' ',nFloors - i - 1));
return result;
}
}

Concat 및 new String의 2번째 인자를 사용하여 깔끔하게 풀었다. String 2번째 인자가 반복할 개수를 받을 수 있는걸 몰라서 괜히 어렵게 풀었다. 문제를 풀때 msdn 한번씩 뒤져보는것도 좋을 수 있겠다.

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

// Create a string that consists of a character repeated 20 times.
string string2 = new string('c', 20);

· 약 5분
karais89

Instructions

The prime numbers are not regularly spaced. For example from 2 to 3 the step is 1. From 3 to 5 the step is 2. From 7 to 11 it is 4. Between 2 and 50 we have the following pairs of 2-steps primes:

3, 5 - 5, 7, - 11, 13, - 17, 19, - 29, 31, - 41, 43

We will write a function step with parameters:

  • g (integer >= 2) which indicates the step we are looking for,
  • m (integer >= 2) which gives the start of the search (m inclusive),
  • n (integer >= m) which gives the end of the search (n inclusive)

In the example above step(2, 2, 50) will return [3, 5] which is the first pair between 2 and 50 with a 2-steps.

So this function should return the first pair of the two prime numbers spaced with a step of g between the limits m, n if these g-steps prime numbers exist otherwise nil or null or None or Nothing or [] or "0, 0" or {0, 0} (depending on the language).

Examples:

step(2, 5, 7) --> [5, 7] or (5, 7) or {5, 7} or "5 7"

step(2, 5, 5) --> nil or ... or [] in Ocaml or {0, 0} in C++

step(4, 130, 200) --> [163, 167] or (163, 167) or {163, 167}

See more examples for your language in "RUN" Remarks: ([193, 197] is also such a 2-steps primes between 130 and 200 but it's not the first pair).

step(6, 100, 110) --> [101, 107] though there is a prime between 101 and 107 which is 103; the pair 101-103 is a 2-step.

Notes: The idea of "step" is close to that of "gap" but it is not exactly the same. For those interested they can have a look at http://mathworld.wolfram.com/PrimeGaps.html.

A "gap" is more restrictive: there must be no primes in between (101-107 is a "step" but not a "gap". Next kata will be about "gaps":-).

For Go: nil slice is expected when there are no step between m and n. Example: step(2,4900,4919) --> nil

My Solution

using System;
using System.Collections.Generic;

class StepInPrimes
{
public static List<long> GetPrimeList(long start, long end)
{
long[] arr = new long[end+1];
for (long i = 0; i < arr.Length; i++)
{
arr[i] = i;
}

for (long i = 2; i < arr.Length; i++)
{
// 이미 체크된 수의 배수는 확인하지 않는다
if (arr[i] == 0)
{
continue;
}

// i를 제외한 i의 배수들은 0으로 체크
for (long j = i + i; j < arr.Length; j += i)
{
arr[j] = 0;
}
}

List<long> newList = new List<long>(arr);
newList.RemoveAll(item => item == 0);
newList.RemoveAll(item => item == 1);
newList.RemoveAll(item => item < start);

return newList;
}

public static long[] Step(int g, long m, long n)
{
List<long> primeNumbers = GetPrimeList(m, n);
for (int i = 0; i < primeNumbers.Count; i++)
{
for (int j = i+1; j < primeNumbers.Count; j++)
{
if (primeNumbers[j] - primeNumbers[i] == g)
{
return new long[] { primeNumbers[i], primeNumbers[j] };
}
}
}

return null;
}
}

처음에 그냥 소수를 그냥 구하는 식으로 해서 문제를 풀려고 했는데 타임아웃이 걸려서 결국 다른 방법으로 문제를 풀어야 했다. 사실 소수를 찾는 방법 중 가장 유명한 에라토스테네스의 체를 이미 알고 있었기 때문에 해당 방법을 찾아서 문제를 풀었다.

Best Practices

using System;
class StepInPrimes
{
public static long[] Step(int g, long m, long n)
{
for (long i = m; i <= n; i++)
{
if (isPrime(i))
{
if (isPrime(i + g) && (i + g) <= n)
{
return new long[2] { i, i + g };
}
}
}
return null;
}

public static bool isPrime(long number)
{
if (number == 1) return false;
if (number == 2) return true;

if (number % 2 == 0) return false; //Even number

for (int i = 3; i <= Math.Ceiling(Math.Sqrt(number)); i += 2)
{
if (number % i == 0) return false;
}
return true;
}
}

제일 높은 표를 받은 해결책이긴 한데 표 자체가 4개 밖에 없어서 추가 검증이 필요하다. 에라토스테네스의 체의 공식을 C#에서 적용하는 다른 소스등을 참고하는게 도움이 될 듯하다. 결국 문제의 핵심은 소수를 구하는 것이다.

아래는 스택 오버플로우에서 찾은 소수 인지 판단하는 함수

https://stackoverflow.com/questions/15743192/check-if-number-is-prime-number

public static bool IsPrime(int number)
{
if (number <= 1) return false;
if (number == 2) return true;
if (number % 2 == 0) return false;

var boundary = (int)Math.Floor(Math.Sqrt(number));

for (int i = 3; i <= boundary; i+=2)
if (number % i == 0)
return false;

return true;
}

· 약 2분
karais89

Instructions

You are given two arrays a1 and a2 of strings. Each string is composed with letters from a to z. Let x be any string in the first array and y be any string in the second array.

Find max(abs(length(x) − length(y)))

If a1 and/or a2 are empty return -1 in each language except in Haskell (F#) where you will return Nothing (None).

Example:

a1 = ["hoqq", "bbllkw", "oox", "ejjuyyy", "plmiis", "xxxzgpsssa", "xxwwkktt", "znnnnfqknaz", "qqquuhii", "dvvvwz"]
a2 = ["cccooommaaqqoxii", "gggqaffhhh", "tttoowwwmmww"]
mxdiflg(a1, a2) --> 13

Bash note:

  • input : 2 strings with substrings separated by ,
  • output: number as a string

My Solution

using System;

public class MaxDiffLength
{

public static int Mxdiflg(string[] a1, string[] a2)
{
if (a1 == null || a1.Length == 0 || a2 == null || a2.Length == 0)
return -1;

int maxVal = int.MinValue;
for (int i = 0; i < a1.Length; i++)
{
for (int j = 0; j < a2.Length; j++)
{
int diff = Math.Abs(a1[i].Length - a2[j].Length);
if (diff > maxVal)
maxVal = diff;
}
}

return maxVal;
}
}

두 배열의 길이의 값 차이 중 가장 큰 값을 구하는 문제

Best Practices

using System;
using System.Linq;

public class MaxDiffLength
{

public static int Mxdiflg(string[] a1, string[] a2)
{
if(a1.Length <= 0 || a2.Length <= 0)
return -1;
var first = Math.Abs(a1.Max(x => x.Length) - a2.Min(x => x.Length));
var second = Math.Abs(a2.Max(x => x.Length) - a1.Min(x => x.Length));
return Math.Max(first, second);
}
}

Linq 사용

a1 최대값 - a2 최소값 혹은 a2 최대값 - a1 최소값 중에 가장 큰 값 반환

· 약 2분
karais89

Instructions

In John's car the GPS records every s seconds the distance travelled from an origin (distances are measured in an arbitrary but consistent unit). For example, below is part of a record with s = 15:

x = [0.0, 0.19, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25]

The sections are:

0.0-0.19, 0.19-0.5, 0.5-0.75, 0.75-1.0, 1.0-1.25, 1.25-1.50, 1.5-1.75, 1.75-2.0, 2.0-2.25

We can calculate John's average hourly speed on every section and we get:

[45.6, 74.4, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0]

Given s and x the task is to return as an integer the floor of the maximum average speed per hour obtained on the sections of x. If x length is less than or equal to 1 return 0 since the car didn't move.

Example: with the above data your function gps(s, x)should return 74

Note With floats it can happen that results depends on the operations order. To calculate hourly speed you can use:

(3600 * delta_distance) / s.

My Solution

using System;

public class GpsSpeed {

public static int Gps(int s, double[] x) {
if (x == null || x.Length <= 1)
return 0;

// your code
double max = double.MinValue;
for (int i = 0; i < x.Length; i++)
{
if (i+1 < x.Length)
{
double distance = x[i+1] - x[i];
double speed = ((3600*distance) / s);
if (max < speed)
{
max = speed;
}
}
}
return (int)(max);
}
}

처음에 문제를 잘못 이해해서 다른 방법으로 풀었다.

Best Practices

using System;
using System.Linq;

public class GpsSpeed
{
public static int Gps(int s, double[] x)
{
if(x.Length > 2)
{
var averageSpeeds = x.Skip(1).Select((distance, index) => ((distance - x[index]) / s) * 3600);
return Convert.ToInt32(Math.Floor(averageSpeeds.Max()));
}

return 0;
}
}

Linq 사용

Skip : 무시할 개수

· 약 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;
}
}

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