private ConversionPath GetShortestPath(ToConvert toConvert, List <ExchangeRate> exchangeRates) { // keys are currencies, values are for the chained calculations // first node: <initial currency, amount> // other nodes: <currency, exchange rate> var firstNode = new KeyValuePair <string, float>(toConvert.InitialCurrency, toConvert.Amount); // init with a first path with the currency to convert from var possibilities = new List <ConversionPath> { new ConversionPath { Nodes = new List <KeyValuePair <string, float> > { firstNode } } }; while (exchangeRates.Any()) { foreach (var possibility in possibilities.ToList()) { var lastNode = possibility.Nodes.Last(); var matchingRates = exchangeRates .Where(e => lastNode.Key == e.InitialCurrency || lastNode.Key == e.TargetCurrency) .ToList(); if (matchingRates.Any()) { possibilities = AddPathsFromMatches(possibilities, possibility, matchingRates); var shortest = possibilities.FirstOrDefault(p => p.Nodes.Last().Key == toConvert.TargetCurrency); // found the shortest path if (shortest != null) { return(shortest); } exchangeRates.RemoveAll(e => matchingRates.Contains(e)); } else { // no match, useless path possibilities.Remove(possibility); // remaining exchange rates but no path to solution if (!possibilities.Any()) { return(null); } break; } } } // empty list but no solution found return(null); }
public void Run(string filePath) { if (!File.Exists(filePath)) { Console.Error.WriteLine("File path doesn't exist"); Environment.Exit(1); } var lines = File.ReadLines(filePath).ToList(); try { var instructions = ExchangeRatesTableParser.GetConversionInstructions(lines[0], lines[1]); ToConvert toConvert = instructions.Item1; int exchangeRatesCount = instructions.Item2; var exchangeRates = ExchangeRatesTableParser.ParseRates(lines, exchangeRatesCount); ConversionPath shortestPath = GetShortestPath(toConvert, exchangeRates.ToList()); if (shortestPath == null) { Console.Error.WriteLine("Incorrect file: no solution"); Environment.Exit(1); } Console.WriteLine(Math.Round(ConvertCurrency(shortestPath))); } catch (IndexOutOfRangeException) { Console.Error.WriteLine("Incorrect file: doesn't respect the exchange rates format"); Environment.Exit(1); } catch (FormatException) { Console.Error.WriteLine("Incorrect file: number of lines not provided"); Environment.Exit(1); } catch (IncorrectRateCountException) { Console.Error.WriteLine("Incorrect file: expected number of exchange rates differs from content"); return; } }
public static Tuple <ToConvert, int> GetConversionInstructions(string request, string exchangeRateCount) { string[] requestData = request.Split(';'); if (requestData.Length != 3) { throw new IndexOutOfRangeException(); } else { ToConvert toConvert = new ToConvert { InitialCurrency = requestData[0], Amount = Convert.ToInt32(requestData[1]), TargetCurrency = requestData[2] }; int count = Convert.ToInt32(exchangeRateCount); return(Tuple.Create(toConvert, count)); } }
private static IEnumerable <object> GetImpls() { var sourceType = typeof(TSource); var destinationType = typeof(TDestination); // Custom foreach (var factory in InternalConvert.factories) { yield return(factory.GetConverter(sourceType, destinationType)); } // Basic yield return(BasicConvert.Instance); // Implicit if (sourceType == destinationType) { yield return(new EqualsConvert <TSource>()); } // Implicit if (Nullable.GetUnderlyingType(destinationType) == sourceType) { yield return(Activator.CreateInstance(typeof(StructToNullableConvert <>).MakeGenericType(sourceType))); } // Explicit if (Nullable.GetUnderlyingType(sourceType) == destinationType) { yield return(Activator.CreateInstance(typeof(NullableToStructConvert <>).MakeGenericType(destinationType))); } // Custom if (destinationType == typeof(string)) { yield return(new ToStringConvert <TSource>()); } // Implicit if (destinationType.IsAssignableFrom(sourceType)) { yield return(Activator.CreateInstance(typeof(AssignableConvert <,>).MakeGenericType(sourceType, destinationType))); } // Custom if (sourceType == typeof(DBNull)) { yield return(new FromDBNullConvert <TDestination>()); } // Custom if (destinationType == typeof(DBNull)) { yield return(new ToDBNullConvert <TSource>()); } // Implicit & XConvert { if (Nullable.GetUnderlyingType(sourceType) is Type underlyingType && underlyingType != sourceType) { yield return(Activator.CreateInstance(typeof(NullableToValueConvert <,>).MakeGenericType(underlyingType, destinationType))); } } // XConvert & Implicit { if (Nullable.GetUnderlyingType(destinationType) is Type underlyingType && underlyingType != destinationType) { yield return(Activator.CreateInstance(typeof(ValueToNullableConvert <,>).MakeGenericType(sourceType, underlyingType))); } } // Custom if (sourceType == typeof(string) && destinationType.IsEnum) { yield return(Activator.CreateInstance(typeof(ParseEnum <>).MakeGenericType(destinationType))); } // Implicit if (ImplicitConvert.TryGetMathod(sourceType, destinationType, out var method)) { yield return(BaseDynamicConvert.CreateInstanceByIL <TSource, TDestination>(method)); } // Explicit if (ExplicitConvert.TryGetMathod(sourceType, destinationType, out method)) { yield return(BaseDynamicConvert.CreateInstanceByIL <TSource, TDestination>(method)); } // Custom if (ParseConvert.TryGetMathod(sourceType, destinationType, out method)) { yield return(BaseDynamicConvert.CreateInstanceByIL <TSource, TDestination>(method)); } // Custom if (ToConvert.TryGetMathod(sourceType, destinationType, out method)) { yield return(BaseDynamicConvert.CreateInstanceByIL <TSource, TDestination>(method)); } // Custom if (ConstructorConvert.TryGetMathod(sourceType, destinationType, out var constructor)) { yield return(BaseDynamicConvert.CreateInstanceByIL <TSource, TDestination>(constructor)); } // Explicit if (sourceType.IsAssignableFrom(destinationType)) { yield return(Activator.CreateInstance(typeof(BaseConvert <,>).MakeGenericType(sourceType, destinationType))); } // Error yield return(new ForceConvert <TSource, TDestination>()); }