using System.Collections;
using System.Collections.Generic;
public int LargestPerimeter(int[] nums)
for (int i = nums.Length - 1; i > 1; i--)
if (nums[i] < nums[i - 1] + nums[i - 2])
return nums[i] + nums[i - 1] + nums[i - 2];
public static void Main()
var solution = new Solution();
Case.SetResultGenerator(solution.LargestPerimeter);
"[2,1,2]".ParseArray<int>(),
"[1,2,1,10]".ParseArray<int>(),
public TreeNode(int val=0, TreeNode left=null, TreeNode right=null)
public override string ToString()
public static string Serialize(TreeNode root)
var sb = new StringBuilder();
var queue = new Queue<TreeNode>();
var node = queue.Dequeue();
sb.Append(node.val.ToString() + ",");
queue.Enqueue(node.left);
queue.Enqueue(node.right);
if (sb[sb.Length - 1] == ',')
sb.Remove(sb.Length - 1, 1);
public static TreeNode Deserialize(string treeString)
if (string.IsNullOrEmpty(treeString))
treeString = treeString.Trim(new [] {'[', ']'});
if (string.IsNullOrEmpty(treeString))
var vals = new Queue<string>(treeString.Split(','));
if (vals.Count == 0 || vals.Peek() == "null")
var queue = new Queue<TreeNode>();
var root = new TreeNode(int.Parse(vals.Dequeue()));
while (queue.Count != 0 && vals.Count > 1)
var node = queue.Dequeue();
var left = vals.Dequeue();
var right = vals.Dequeue();
node.left = new TreeNode(int.Parse(left));
queue.Enqueue(node.left);
node.right = new TreeNode(int.Parse(right));
queue.Enqueue(node.right);
public static class TreeNodeExtensions
public static string Serialize(this TreeNode root)
return TreeNode.Serialize(root);
public static TreeNode DeserializeTreeNode(this string treeString)
return TreeNode.Deserialize(treeString);
public static class Extensions
public static IList<T> ToIList<T>(this IList<T> list)
public static T[][] ParseMatrix<T>(
this string matrixString,
bool ignoreQuotes = true)
return matrixString.ParseList<T>(addEmpty, ignoreQuotes).Select(x => x.ToArray()).ToArray();
public static IList<IList<T>> ParseList<T>(
bool ignoreQuotes = true)
var result = new List<IList<T>>();
if (listString.StartsWith("[["))
listString = listString.Substring(1, listString.Length - 1);
if (listString.EndsWith("]]"))
listString = listString.Substring(0, listString.Length - 1);
var current = new List<T>();
var currentItem = string.Empty;
for (int i = 0; i < listString.Length; i++)
if (listString[i] == '[')
currentItem = string.Empty;
if (listString[i] == ']')
if (!string.IsNullOrEmpty(currentItem) || addEmpty)
current.Add((T)Convert.ChangeType(currentItem, typeof(T)));
currentItem = string.Empty;
if (listString[i] == ' ' || (ignoreQuotes && listString[i] == '"'))
if (listString[i] == ',')
if (!string.IsNullOrEmpty(currentItem) || addEmpty)
current.Add((T)Convert.ChangeType(currentItem, typeof(T)));
currentItem = string.Empty;
currentItem += listString[i];
public static T[] ParseArray<T>(this string arrayString, char delimiter = ',', bool removeQuotes = true)
arrayString = removeQuotes ? arrayString.Replace("\"", "") : arrayString;
arrayString = arrayString.Trim(new [] {'[', ']'});
var split = arrayString.Split(delimiter);
return split.Select(x => (T)Convert.ChangeType(x, typeof(T))).ToArray();
public static void Print(this object obj)
Console.WriteLine(obj.TryGetObjectString());
public static string TryGetObjectString(this object input)
if (input is not IEnumerable someEnumerable || input is string)
if (!(input.GetType().Name.Contains(nameof(ValueTuple))))
someEnumerable = input.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Select(x => x.GetValue(input)) as IEnumerable;
foreach (var item in someEnumerable)
result += TryGetObjectString(item);
public static T[] SubArray<T>(this T[] data, int index, int length)
T[] result = new T[length];
Array.Copy(data, index, result, 0, length);
public static Case<TInput, TResult> CreateCase<TInput, TResult>(TInput input, TResult expectedResult)
return new Case<TInput, TResult>(input, expectedResult);
public static void SetResultGenerator(Delegate @delegate)
var returnType = @delegate.Method.ReturnType;
if (returnType == typeof(void))
throw new InvalidOperationException("Delegate with return type 'void' is not supported.");
var parameters = @delegate.Method.GetParameters();
if (parameters.Count() != 1)
throw new InvalidOperationException("Only one input parameter can be handeled. Use a tuple and an anonymous func if you need more than one.");
var inputType = parameters.First().ParameterType;
var setResultGeneratorMethod =
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.First(m => m.IsGenericMethod && m.Name == nameof(Case.SetResultGenerator));
var genericSetResultGeneratorMethod = setResultGeneratorMethod.MakeGenericMethod(inputType, returnType);
.GetMethod(nameof(CastResultGenerator), BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(inputType, returnType)
.Invoke(null, new object[] { @delegate });
genericSetResultGeneratorMethod.Invoke(null, new object[] { convertedDelegate });
public static void SetResultGenerator<TInput, TResult>(Func<TInput, TResult> resultGenerator)
Case<TInput, TResult>.ResultGenerator = resultGenerator;
public static void SetResultChecker<TInput, TResult>(Func<Case<TInput, TResult>, bool> resultChecker)
Case<TInput, TResult>.ResultChecker = resultChecker;
private static Func<TInput, TResult> CastResultGenerator<TInput, TResult>(Delegate @delegate)
var castedDelegate = (Func<TInput, TResult>)@delegate;
private static Func<TInput, TResult, bool> CastResultChecker<TInput, TResult>(Delegate @delegate)
var castedDelegate = (Func<TInput, TResult, bool>)@delegate;
public class Case<TInput, TResult>
public static Func<TInput, TResult> ResultGenerator { get; set; }
public static Func<Case<TInput, TResult>, bool> ResultChecker { get; set; }
public string InputString { get; set; }
public TInput Input { get; set; }
public TResult ExpectedResult { get; set; }
public TResult ActualResult { get; set; }
public bool Passed { get; set; }
Case.SetResultChecker<TInput, TResult>(c => c.ActualResult.Equals(c.ExpectedResult));
public Case(TInput input, TResult expectedResult)
ExpectedResult = expectedResult;
public Case<TInput, TResult> GenerateResult()
ActualResult = ResultGenerator(Input);
public bool ResultAsExpected()
return ResultChecker(this);
public Case<TInput, TResult> Run()
Passed = ResultAsExpected();
public Case<TInput, TResult> PrintResult()
$"Test {(Passed ? "passed" : "failed" )}.".Print();
$"Input: {Input.TryGetObjectString()}".Print();
$"Result: {ActualResult.TryGetObjectString()}".Print();
$"Expected: {ExpectedResult.TryGetObjectString()}".Print();