본문으로 건너뛰기

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

모든 태그 보기

· 약 3분
karais89

Instructions

링크

Enough is enough! Alice and Bob were on a holiday. Both of them took many pictures of the places they've been, and now they want to show Charlie their entire collection. However, Charlie doesn't like this sessions, since the motive usually repeats. He isn't fond of seeing the Eiffel tower 40 times. He tells them that he will only sit during the session if they show the same motive at most N times. Luckily, Alice and Bob are able to encode the motive as a number. Can you help them to remove numbers such that their list contains each number only up to N times, without changing the order?

Task Given a list lst and a number N, create a new list that contains each number of lst at most N times without reordering. For example if N = 2, and the input is [1,2,3,1,2,1,2,3], you take [1,2,3,1,2], drop the next [1,2] since this would lead to 1 and 2 being in the result 3 times, and then take 3, which leads to [1,2,3,1,2,3].

Example

Kata.DeleteNth (new int[] {20,37,20,21}, 1) // return [20,37,21]
Kata.DeleteNth (new int[] {1,1,3,3,7,2,2,2,2}, 3) // return

My Solution

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

public class Kata {
public static int[] DeleteNth(int[] arr, int x) {
Dictionary<int, int> valCounts = new Dictionary<int, int>();
List<int> removeArrs = new List<int>();
for (int i = 0; i < arr.Length; i++)
{
if (valCounts.ContainsKey(arr[i]))
{
if (++valCounts[arr[i]] <= x)
{
removeArrs.Add(arr[i]);
}
}
else
{
valCounts[arr[i]] = 1;
removeArrs.Add(arr[i]);
}
}
return removeArrs.ToArray();
}
}
  • 여러번 반복하는걸 제거해 달라는 요구 사항.
  • Dictinary를 사용하여 해당 되는 키 값이 없으면 1 있으면 +1 해주어서 x보다 작을때만 리스트에 더해준 후 해당 리스트 반환
  • Linq를 사용하면 더 간단히 풀리겠지...

Best Practices

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

public class Kata {
public static int[] DeleteNth(int[] arr, int x) {
var result = new List<int>();
foreach(var item in arr) {
if(result.Count(i => i == item) < x)
result.Add(item);
}
return result.ToArray();
}
}
  • C# 문제는 거의 모두 linq를 사용하여 푼다고 보면 될 듯.
  • Linq중 Count 함수를 사용하여 해당되는 값이 몇개 있는지 반환한후 그것보다 작을시에만 더해주었다.
  • 확실히 내 해결책 보다 훨씬 간단하다.

· 약 1분
karais89

Instructions

링크

In this kata you will create a function that takes a list of non-negative integers and strings and returns a new list with the strings filtered out.

Example

ListFilterer.GetIntegersFromList(new List<object>(){1, 2, "a", "b"}) => {1, 2}
ListFilterer.GetIntegersFromList(new List<object>(){1, 2, "a", "b", 0, 15}) => {1, 2, 0, 15}
ListFilterer.GetIntegersFromList(new List<object>(){1, 2, "a", "b", "aasf", "1", "123", 231}) => {1, 2, 231}

My Solution

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

public class ListFilterer
{
public static IEnumerable<int> GetIntegersFromList(List<object> listOfItems)
{
List<int> newInts = new List<int>();
foreach (var item in listOfItems)
{
if (item is int)
{
newInts.Add((int)item);
}
}
return newInts;
}
}
  • c# 자료형 판단? 리플렉션을 사용해야 되나?
  • is 연산자로 가능?
  • newInts 말고 filterInts 정도로 네이밍 변경을 했으면 좋았겠다.

Best Practices

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

public class ListFilterer
{
public static IEnumerable<int> GetIntegersFromList(List<object> listOfItems)
{
return listOfItems.OfType<int>();
}
}

· 약 1분
karais89

Instructions

링크

It's pretty straightforward. Your goal is to create a function that removes the first and last characters of a string. You're given one parameter, the original string. You don't have to worry with strings with less than two characters.

My Solution

using System;

public class Kata
{
public static string Remove_char(string s)
{
// Your Code
return s.Substring(1, s.Length - 2);
}
}

Best Practices

using System;

public class Kata
{
public static string Remove_char(string s)
{
return s.Substring(1,(s.Length - 2));
}
}
  • 똑같은 방식으로 해결

· 약 2분
karais89

Instructions

링크

You are given an array strarr of strings and an integer k. Your task is to return the first longest string consisting of k consecutive strings taken in the array.

Example: longest_consec(["zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"], 2) --> "abigailtheta"

n being the length of the string array, if n = 0 or k > n or k <= 0 return "".

Note consecutive strings : follow one after another without an interruption

My Solution

using System;
using System.Collections.Generic;

public class LongestConsecutives
{
public static String LongestConsec(string[] strarr, int k)
{
// your code
if (strarr == null || strarr.Length == 0 ||
strarr.Length < k || k <= 0)
{
return string.Empty;
}

int maxLength = 0;
int longestIndex = 0;
for (int i = 0; i < strarr.Length; i++)
{
int length = 0;
for (int j = i; j < strarr.Length && j < i + k; j++)
{
length += strarr[j].Length;
}

if (length > maxLength)
{
maxLength = length;
longestIndex = i;
}

}
string str = "";
for (int i = longestIndex; i < longestIndex + k; i++)
{
str += strarr[i];
}
return str;
}
}
  • 영어 해석이 안되서 무슨 조건인지 정확히 모르겠다.
  • k개의 연속된 문자열 길이의 합이 가장 긴 문자열을 구하면 된다.
  • stringBuilder를 사용하는 부분은 일단 생략.

Best Practices 1

using System;
using System.Linq;
public class LongestConsecutives {
public static string LongestConsec(string[] s, int k){
return s.Length==0||s.Length<k||k<=0 ? ""
: Enumerable.Range(0,s.Length-k+1)
.Select(x=>string.Join("",s.Skip(x).Take(k)))
.OrderByDescending(x=>x.Length)
.First();
}
}
  • linq 사용

Best Practices 2

 public class LongestConsecutives
{
public static string LongestConsec(string[] strarr, int k)
{
if (k > strarr.Length || strarr.Length == 0 || k <= 0)
{
return string.Empty;
}

var currentStr = string.Empty;
for (var i = 0; i < strarr.Length; i++)
{
var str = string.Empty;
for (var j = i; j < k + i && j < strarr.Length; j++)
{
str += strarr[j];
}

if (currentStr.Length < str.Length)
{
currentStr = str;
}
}

return currentStr;
}
}
  • 논리는 거의 비슷한듯.

· 약 2분
karais89

Instructions

링크

Given an array of one's and zero's convert the equivalent binary value to an integer.

Eg: [0, 0, 0, 1] is treated as 0001 which is the binary representation of 1.

Examples:

Testing: [0, 0, 0, 1] ==> 1
Testing: [0, 0, 1, 0] ==> 2
Testing: [0, 1, 0, 1] ==> 5
Testing: [1, 0, 0, 1] ==> 9
Testing: [0, 0, 1, 0] ==> 2
Testing: [0, 1, 1, 0] ==> 6
Testing: [1, 1, 1, 1] ==> 15
Testing: [1, 0, 1, 1] ==> 11

However, the arrays can have varying lengths, not just limited to 4.

My Solution

using System;

namespace Solution
{
class Kata
{
public static int binaryArrayToNumber(int[] BinaryArray)
{
int sum = 0;
Array.Reverse(BinaryArray);
for (int i = 0; i < BinaryArray.Length; i++)
{
if (BinaryArray[i] == 1)
{
sum += (int)Math.Pow(2, i);
}
}
return sum;
}
}
}
  • 2진수를 10진수로 변경 하는 문제

  • array를 반대로 정렬해주고 2의 거듭제곱을 해주는 방식으로 해결 하였다,.

Best Practices

using System;
namespace Solution
{
class Kata
{
public static int binaryArrayToNumber(int[] BinaryArray)
{
return Convert.ToInt32(string.Join("", BinaryArray), 2);
}
}
}
  • 이게 가장 쉬운 해결책이긴 하네..
  • 그냥 binaryArray를 string 자체로 변경한후 스트링을 2진수 배열의 값을 기준으로 int값으로 변경 해주는 코드

· 약 7분
karais89

Instructions

링크

There is a war and nobody knows - the alphabet war! There are two groups of hostile letters. The tension between left side letters and right side letters was too high and the war began. The letters have discovered a new unit - a priest with Wo lo looooooo power.

Task Write a function that accepts fight string consists of only small letters and return who wins the fight. When the left side wins return Left side wins!, when the right side wins return Right side wins!, in other case return Let's fight again!.

The left side letters and their power:

 w - 4
p - 3
b - 2
s - 1
t - 0 (but it's priest with Wo lo loooooooo power)

The right side letters and their power:

 m - 4
q - 3
d - 2
z - 1
j - 0 (but it's priest with Wo lo loooooooo power)

The other letters don't have power and are only victims. The priest units t and j change the adjacent letters from hostile letters to friendly letters with the same power.

mtq => wtp
wjs => mjz

A letter with adjacent letters j and t is not converted i.e.:

tmj => tmj
jzt => jzt

The priests (j and t) do not convert the other priests ( jt => jt).

Example

AlphabetWar("z") //=> "z" => "Right side wins!"
AlphabetWar("tz") //=> "ts" => "Left side wins!"
AlphabetWar("jz") //=> "jz" => "Right side wins!"
AlphabetWar("zt") //=> "st" => "Left side wins!"
AlphabetWar("azt") //=> "ast" => "Left side wins!"
AlphabetWar("tzj") //=> "tzj" => "Right side wins!"

Alphabet war Collection

  • Alphabet war
  • Alphabet war - airstrike - letters massacre
  • Alphabet wars - reinforces massacre
  • Alphabet wars - nuclear strike
  • Alphabet war - Wo lo loooooo priests join the war

My Solution

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

public class Kata
{
public static readonly Dictionary<char, int> leftSideLetters = new Dictionary<char, int>()
{
{ 'w', 4 }, { 'p', 3 }, { 'b', 2 }, { 's', 1 }
};

public static readonly Dictionary<char, int> rightSideLetters = new Dictionary<char, int>()
{
{ 'm', 4 }, { 'q', 3 }, { 'd', 2 }, { 'z', 1 }
};

public static char RightToLeftLetter(char ch)
{
if (rightSideLetters.ContainsKey(ch))
{
int score = rightSideLetters[ch];
foreach (var left in leftSideLetters)
{
if (left.Value == score)
{
return left.Key;
}
}
}

return ch;
}

public static char LeftToRightLetter(char ch)
{
if (leftSideLetters.ContainsKey(ch))
{
int score = leftSideLetters[ch];
foreach (var right in rightSideLetters)
{
if (right.Value == score)
{
return right.Key;
}
}
}

return ch;
}

public static string AlphabetWar(string fight)
{
int leftScore = 0;
int rightScore = 0;

//Console.WriteLine("fight: " + fight);

StringBuilder convFight = new StringBuilder(fight);
// priest char check
for (int i = 0; i < convFight.Length; i++)
{
// left side priest
if (convFight[i] == 't')
{
bool isTwoLeftPriest = (i - 2 >= 0 && convFight[i - 2] == 'j');
if (!isTwoLeftPriest)
{
// left alpha change
if (i - 1 >= 0)
{
convFight[i - 1] = RightToLeftLetter(convFight[i - 1]);
}
}

bool isTwoRightPriest = (i + 2 <= convFight.Length - 1 && convFight[i + 2] == 'j');
if (!isTwoRightPriest)
{
// right alpha change
if (i + 1 <= convFight.Length - 1)
{
convFight[i + 1] = RightToLeftLetter(convFight[i + 1]);
}
}
}

// right side priest
if (convFight[i] == 'j')
{
bool isTwoLeftPriest = (i - 2 >= 0 && convFight[i - 2] == 't');
if (!isTwoLeftPriest)
{
// left alpha change
if (i - 1 >= 0)
{
convFight[i - 1] = LeftToRightLetter(convFight[i - 1]);
}
}

bool isTwoRightPriest = (i + 2 <= convFight.Length - 1 && convFight[i + 2] == 't');
if (!isTwoRightPriest)
{
// right alpha change
if (i + 1 <= convFight.Length - 1)
{
convFight[i + 1] = LeftToRightLetter(convFight[i + 1]);
}
}
}
}

// left and right score diff
for (int i = 0; i < convFight.Length; i++)
{
char ch = convFight[i];
if (leftSideLetters.ContainsKey(ch))
{
leftScore += leftSideLetters[ch];
}

if (rightSideLetters.ContainsKey(ch))
{
rightScore += rightSideLetters[ch];
}
}

if (leftScore > rightScore)
{
return "Left side wins!";
}
else if (leftScore < rightScore)
{
return "Right side wins!";
}
else
{
return "Let's fight again!";
}
}
}
  • 알파벳 전쟁 시리즈.
  • 각 알파벳 마다 점수가 있다.
  • t와 j는 상대 알파벳을 자기 알파벳 점수로 변경한다.
  • 2칸 옆의 priest를 비교하는 부분이 중복되는 부분과 쓸데없이 길어지는 부분이 있다.

Best Practices 1

using System.Collections.Generic;
public class Kata
{
public enum Side
{
LeftSide,
RightSide,
NoSide
}

public static string AlphabetWar(string fight)
{
int pointDiff = 0;
Dictionary<char, int> leftPowers = new Dictionary<char, int>(){
{'w',4},
{'p',3},
{'b',2},
{'s',1},
{'t',0}
};
Dictionary<char, int> rightPowers = new Dictionary<char, int>(){
{'m',4},
{'q',3},
{'d',2},
{'z',1},
{'j',0}
};

for (int i = 0; i < fight.Length; i++)
{
int value = 0;
Side n1Wooloo = Side.NoSide;
Side n2Wooloo = Side.NoSide;

if (leftPowers.TryGetValue(fight[i], out value))
{
if (value == 0) continue;

value *= -1;

findNeighborWooloos(i, leftPowers, rightPowers, fight, ref n1Wooloo, ref n2Wooloo);

if (n1Wooloo == Side.RightSide && n2Wooloo != Side.LeftSide || n2Wooloo == Side.RightSide && n1Wooloo != Side.LeftSide)
value *= -1;
}
else if (rightPowers.TryGetValue(fight[i], out value))
{
if (value == 0) continue;

findNeighborWooloos(i, leftPowers, rightPowers, fight, ref n1Wooloo, ref n2Wooloo);

if (n1Wooloo == Side.LeftSide && n2Wooloo != Side.RightSide || n2Wooloo == Side.LeftSide && n1Wooloo != Side.RightSide)
value *= -1;
}

pointDiff += value;
}

if (pointDiff > 0) { return "Right side wins!"; }
if (pointDiff < 0) { return "Left side wins!"; }
return "Let's fight again!";
}

public static void findNeighborWooloos(int i, Dictionary<char, int> leftPowers, Dictionary<char, int> rightPowers, string fight, ref Side n1Wooloo, ref Side n2Wooloo)
{
int tempVal;
if (i > 0)
{
if (leftPowers.TryGetValue(fight[i - 1], out tempVal))
{
if (tempVal == 0) n1Wooloo = Side.LeftSide;
}
else if (rightPowers.TryGetValue(fight[i - 1], out tempVal))
{
if (tempVal == 0) n1Wooloo = Side.RightSide;
}
}
if (i < fight.Length - 1)
{
if (leftPowers.TryGetValue(fight[i + 1], out tempVal))
{
if (tempVal == 0) n2Wooloo = Side.LeftSide;
}
else if (rightPowers.TryGetValue(fight[i + 1], out tempVal))
{
if (tempVal == 0) n2Wooloo = Side.RightSide;
}
}
}
}
  • 문자 자체를 변경 하는 작업을 하지 않는다.
  • 문자를 비교하고 옆이 priest일 경우 점수만 변경 해준다.

Best Practices 2

 using System.Linq;
using System.Text.RegularExpressions;
public class Kata
{
public static string AlphabetWar(string fight)
{
string power = "wpbs_zdqm";
fight = new Regex(@"(?<!t)[wpbs](?=j)|(?<=j)[wpbs](?!t)|(?<!j)[zdqm](?=t)|(?<=t)[zdqm](?!j)").Replace(fight, x => ""+ power[8 - power.IndexOf(x.Value)]);
int result = fight.Aggregate(0, (a, b) => a + (power.IndexOf(b) == -1 ? 0 : power.IndexOf(b) - 4)); //
return result == 0 ? "Let's fight again!" : $"{(result < 0 ? "Left":"Right")} side wins!";
}
}
  • 정규표현식을 사용하여 간단하게 해결

· 약 2분
karais89

Instructions

링크

Write a program that finds the summation of every number from 1 to num. The number will always be a positive integer greater than 0.

For example:

summation(2) -> 3
1 + 2

summation(8) -> 36
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8

My Solution

 using System;

public static class Kata
{
public static int summation(int num)
{
//Code here
int sum = 0;
for (int i = 0; i <= num; i++)
{
sum += i;
}
return sum;
}
}
  • 갑자기 1부터 n까지 더하는 문제가 나와서.. 일단 풀어봤다.
  • 이렇게 간단한 문제도 생각하는 방식이 여러개 구나.

Best Practices 1

using System;

public static class Kata
{
public static int summation(int num)
{
return num*(num+1)/2;
}
}
  • 더하는 방법 하면 딱 이걸 생각할 수도 있구나.
  • 가우스의 유명한 일화..

Best Practices 2

using System;
using System.Linq;

public static class Kata
{
public static int summation(int num)
{
return Enumerable.Range(1, num).Sum();
}
}

· 약 2분
karais89

Instructions

링크

Implement a method that accepts 3 integer values a, b, c. The method should return true if a triangle can be built with the sides of given length and false in any other case.

(In this case, all triangles must have surface greater than 0 to be accepted).

My Solution

using System;

public class Triangle
{
public static bool IsTriangle(int a, int b, int c)
{
int[] triangles = new int[3];

triangles[0] = a;
triangles[1] = b;
triangles[2] = c;

Array.Sort(triangles);

return triangles[0] + triangles[1] > triangles[2];
}
}
  • 삼각형의 성립 조건을 알아야 풀 수 있는 문제.
  • c가 가장 긴 변일때 a+b > c
  • Array.Sort

Best Practices

public class Triangle
{
public static bool IsTriangle(int a, int b, int c) =>
a > 0 && b > 0 && c > 0 && a + b > c && a + c > b && b + c > a;
}
  • 삼각형의 성립조건은 저게 맞는 것 같은데.
  • 어차피 모든 조건을 성립하면 삼각형의 성립 조건도 성립되기 때문에 상관없이 구현되어 있는 것 같다.

· 약 2분
karais89

Instructions

링크

ROT13 is a simple letter substitution cipher that replaces a letter with the letter 13 letters after it in the alphabet. ROT13 is an example of the Caesar cipher.

Create a function that takes a string and returns the string ciphered with Rot13. If there are numbers or special characters included in the string, they should be returned as they are. Only letters from the latin/english alphabet should be shifted, like in the original Rot13 "implementation".

Please note that using "encode" in Python is considered cheating.

My Solution

using System;
using System.Text;

public class Kata
{
public static string Rot13(string message)
{
// your code here
StringBuilder builder = new StringBuilder();
for (int i = 0; i < message.Length; i++)
{
char ch = message[i];
if (char.IsLetter(ch))
{
char a = 'a';
char z = 'z';

if (char.IsUpper(ch))
{
a = 'A';
z = 'Z';
}
ch += (char)13;
if (ch > z)
{
ch = (char)(a + ch - z - 1);
}
}
builder.Append((char)ch);
}

return builder.ToString();
}
}
  • 가끔씩 보면 문제 수준이 이해가 안가는 것들이 있다.
  • 일단 13 더해주고, 넘어가면 자동으로 a 부터 시작하는 식으로 구현 함.

Best Practices

using System;

public class Kata
{
public static string Rot13(string message)
{
string result = "";
foreach (var s in message)
{
if ((s >= 'a' && s <= 'm') || (s >= 'A' && s <= 'M'))
result += Convert.ToChar((s + 13)).ToString();
else if ((s >= 'n' && s <= 'z') || (s >= 'N' && s <= 'Z'))
result += Convert.ToChar((s - 13)).ToString();
else result += s;
}
return result;
}
}
  • 13이 딱 절반이라 더하고 빼기를 하면서 순환을 시켜준것 같다.

· 약 8분
karais89

Instructions

링크

This is the first of my "-nacci" series. If you like this kata, check out the zozonacci sequence too.

Task

  1. Mix -nacci sequences using a given pattern p.
  2. Return the first n elements of the mixed sequence.

Rules

  1. The pattern p is given as a list of strings (or array of symbols in Ruby) using the pattern mapping below (e. g. ['fib', 'pad', 'pel'] means take the next fibonacci, then the next padovan, then the next pell number and so on).
  2. When n is 0 or p is empty return an empty list.
  3. If the length of p is more than n repeat the pattern.

Examples

            0 1 2 3 4
----------+------------------
fibonacci:| 0, 1, 1, 2, 3 ...
padovan: | 1, 0, 0, 1, 0 ...
pell: | 0, 1, 2, 5, 12 ...

pattern = ['fib', 'pad', 'pel']
n = 6
# ['fib', 'pad', 'pel', 'fib', 'pad', 'pel']
# result = [fibonacci(0), padovan(0), pell(0), fibonacci(1), padovan(1), pell(1)]
result = [0, 1, 0, 1, 0, 1]

pattern = ['fib', 'fib', 'pel']
n = 6
# ['fib', 'fib', 'pel', 'fib', 'fib', 'pel']
# result = [fibonacci(0), fibonacci(1), pell(0), fibonacci(2), fibonacci(3), pell(1)]
result = [0, 1, 0, 1, 2, 1]

Sequences

  • fibonacci : 0, 1, 1, 2, 3 ...
  • padovan: 1, 0, 0, 1, 0 ...
  • jacobsthal: 0, 1, 1, 3, 5 ...
  • pell: 0, 1, 2, 5, 12 ...
  • tribonacci: 0, 0, 1, 1, 2 ...
  • tetranacci: 0, 0, 0, 1, 1 ...

Pattern mapping

  • 'fib' -> fibonacci
  • 'pad' -> padovan
  • 'jac' -> jacobstahl
  • 'pel' -> pell
  • 'tri' -> tribonacci
  • 'tet' -> tetranacci

If you like this kata, check out the zozonacci sequence.

My Solution

using System;
using System.Numerics;
using System.Collections.Generic;

namespace Solution
{
public static class Kata
{
// non-recursive
// Dynamic Programming
public static BigInteger Fibonacci(int n)
{
if (n < 2)
{
return n;
}

BigInteger[] arr = new BigInteger[n + 1];
arr[0] = 0;
arr[1] = 1;

for (int i = 2; i <= n; i++)
{
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr[n];
}

// a(n) = a(n-2) + a(n-3) with a(0)=1, a(1)=a(2)=0.
public static BigInteger Padovan(int n)
{
if (n == 0)
{
return 1;
}

if (n <= 2)
{
return 0;
}

BigInteger[] arr = new BigInteger[n + 1];
arr[0] = 1;
arr[1] = 0;
arr[2] = 0;

for (int i = 3; i <= n; i++)
{
arr[i] = arr[i - 2] + arr[i - 3];
}
return arr[n];
}

// a(n) = a(n-1) + 2*a(n-2), with a(0) = 0, a(1) = 1.
public static BigInteger Jacobstahl(int n)
{
if (n < 2)
{
return n;
}

BigInteger[] arr = new BigInteger[n + 1];
arr[0] = 0;
arr[1] = 1;

for (int i = 2; i <= n; i++)
{
arr[i] = arr[i - 1] + 2 * arr[i - 2];
}
return arr[n];
}

// a(0) = 0, a(1) = 1; for n > 1, a(n) = 2*a(n-1) + a(n-2).
public static BigInteger Pell(int n)
{
if (n < 2)
{
return n;
}

BigInteger[] arr = new BigInteger[n + 1];
arr[0] = 0;
arr[1] = 1;

for (int i = 2; i <= n; i++)
{
arr[i] = 2 * arr[i - 1] + arr[i - 2];
}
return arr[n];
}

// a(n) = a(n-1) + a(n-2) + a(n-3) with a(0)=a(1)=0, a(2)=1.
public static BigInteger Tribonacci(int n)
{
if (n == 0 || n == 1)
{
return 0;
}

if (n == 2)
{
return 1;
}

BigInteger[] arr = new BigInteger[n + 1];
arr[0] = 0;
arr[1] = 0;
arr[2] = 1;

for (int i = 3; i <= n; i++)
{
arr[i] = arr[i - 1] + arr[i - 2] + arr[i - 3];
}
return arr[n];
}

// a(n) = a(n-1) + a(n-2) + a(n-3) + a(n-4) with a(0)=a(1)=a(2)=0, a(3)=1.
public static BigInteger Tetranacci(int n)
{
if (n < 3)
{
return 0;
}

if (n == 3)
{
return 1;
}

BigInteger[] arr = new BigInteger[n + 1];
arr[0] = 0;
arr[1] = 0;
arr[2] = 0;
arr[3] = 1;

for (int i = 4; i <= n; i++)
{
arr[i] = arr[i - 1] + arr[i - 2] + arr[i - 3] + arr[i - 4];
}
return arr[n];
}

public static void ShowConsole(string head, Func<int, BigInteger> func, int n)
{
Console.Write(head + " : ");
for (int i = 0; i < n; i++)
{
Console.Write(" " + func(i));
}
Console.WriteLine();
}

public static BigInteger[] Mixbonacci(string[] pattern, int length)
{
/*
ShowConsole("fib", Fibonacci, 10);
ShowConsole("pad", Padovan, 10);
ShowConsole("jac", Jacobstahl, 10);
ShowConsole("pel", Pell, 10);
ShowConsole("tri", Tribonacci, 10);
ShowConsole("tet", Tetranacci, 10);
*/
if (length == 0 || pattern == null || pattern.Length == 0)
{
return new BigInteger[] {};
}

Dictionary<string, int> boancciCounts = new Dictionary<string, int>();
boancciCounts["fib"] = 0;
boancciCounts["pad"] = 0;
boancciCounts["jac"] = 0;
boancciCounts["pel"] = 0;
boancciCounts["tri"] = 0;
boancciCounts["tet"] = 0;

Dictionary<string, Func<int, BigInteger>> boancciFuncs = new Dictionary<string, Func<int, BigInteger>>();
boancciFuncs["fib"] = Fibonacci;
boancciFuncs["pad"] = Padovan;
boancciFuncs["jac"] = Jacobstahl;
boancciFuncs["pel"] = Pell;
boancciFuncs["tri"] = Tribonacci;
boancciFuncs["tet"] = Tetranacci;


BigInteger[] mixbonaccis = new BigInteger[length];
for (int i = 0; i < length; i++)
{
string key = pattern[i % pattern.Length];
mixbonaccis[i] = boancciFuncs[key](boancciCounts[key]++);
}

return mixbonaccis;
}
}
}
  • 여러가지 점화식이 있는 함수들로 수를 표현하면 되는 문제.
  • 여러가지 규칙의 함수들이 있다.
  • 사실 문제 자체는 재귀 함수를 사용하는 방식이 가장 풀기 쉬운 방식인데, 스택 문제와 퍼포먼스 문제 때문에 해당 방법은 사용하면 안되는 듯 하다.
  • Func 까지 써가면서 품..
  • 재귀함수가 아닌 다이나믹 프로그래밍 방식을 사용함 (배열 사용)
  • 쓸데없이 길어지는 느낌이 없지 않아 있다.

Best Practices

using System.Numerics;
using System.Collections.Generic;
namespace Solution
{
public static class Kata
{
private static readonly Dictionary<string, IEnumerable<BigInteger>> GeneratorMapping =
new Dictionary<string, IEnumerable<BigInteger>>() {
{"fib", FibonacciGenerator()},
{"pad", PadovanGenerator()},
{"jac", JacobstahlGenerator()},
{"tet", TetranacciGenerator()},
{"tri", TribonacciGenerator()},
{"pel", PellGenerator()}
};

public static BigInteger[] Mixbonacci(string[] pattern, int length)
{
if (pattern.Length == 0 || length == 0)
{
return new BigInteger[] { };
}

var res = new List<BigInteger>() { };
var gens = new Dictionary<string, IEnumerator<BigInteger>>();
var patLength = pattern.Length;

for (var i = 0; i < patLength; i++)
{
var v = pattern[i];
gens[v] = GeneratorMapping[v].GetEnumerator();
}

for (var i = 0; i < length; i++)
{
var gen = gens[pattern[i % patLength]];
gen.MoveNext();
res.Add(gen.Current);
}

return res.ToArray();

}

public static IEnumerable<BigInteger> FibonacciGenerator()
{
var a = new BigInteger(0);
var b = new BigInteger(1);
BigInteger x;
while (true)
{
yield return a;
x = a;
a = b;
b = x + a;
}
}

public static IEnumerable<BigInteger> PadovanGenerator()
{
var a = new BigInteger(1);
var b = new BigInteger(0);
var c = new BigInteger(0);
BigInteger x;
BigInteger y;
while (true)
{
yield return a;
x = a;
y = b;
a = b;
b = c;
c = x + y;
}
}

public static IEnumerable<BigInteger> JacobstahlGenerator()
{
var a = new BigInteger(0);
var b = new BigInteger(1);
BigInteger x;
while (true)
{
yield return a;
x = a;
a = b;
b = 2 * x + b;
}
}


public static IEnumerable<BigInteger> PellGenerator()
{
var a = new BigInteger(0);
var b = new BigInteger(1);
BigInteger x;
while (true)
{
yield return a;
x = a;
a = b;
b = x + 2 * b;
}
}

public static IEnumerable<BigInteger> TribonacciGenerator()
{
var a = new BigInteger(0);
var b = new BigInteger(0);
var c = new BigInteger(1);
BigInteger x, y, z;
while (true)
{
yield return a;
x = a; y = b; z = c;
a = b; b = c;
c = x + y + z;
}
}

public static IEnumerable<BigInteger> TetranacciGenerator()
{
var a = new BigInteger(0);
var b = new BigInteger(0);
var c = new BigInteger(0);
var d = new BigInteger(1);
BigInteger x, y, z, j;
while (true)
{
yield return a;
x = a; y = b; z = c; j = d;
a = b; b = c; c = d;
d = x + y + z + j;
}
}
}
}
  • IEnumerable 특성을 이용해서 해결.