SF Developer
SF Developer

Reputation: 5384

C# Recursion to get the proper count

OK so today is one of those days that my mind cannot work properly.
I cannot make this to work (:

class Program
{
    static private List<KeyValuePair<int, double>> _list;
    static protected List<KeyValuePair<int, double>> list
    {
        get
        {
            if (_list == null)
            {
                _list = new List<KeyValuePair<int, double>>();

                _list.Add(new KeyValuePair<int, double>(1, 11.60));                                        
                _list.Add(new KeyValuePair<int, double>(2, 11.20));
                _list.Add(new KeyValuePair<int, double>(3, 13.00));
                _list.Add(new KeyValuePair<int, double>(4, 13.60));
                _list.Add(new KeyValuePair<int, double>(5, 15.90));
                _list.Add(new KeyValuePair<int, double>(6, 16.10));
                _list.Add(new KeyValuePair<int, double>(7, 19.10));
                _list.Add(new KeyValuePair<int, double>(8, 19.10));
                _list.Add(new KeyValuePair<int, double>(9, 19.10));
                _list.Add(new KeyValuePair<int, double>(10, 21.00));
                _list.Add(new KeyValuePair<int, double>(11, 23.00));
            }

            return _list;
        }
    }

    static void Main(string[] args)
    {
        Program p = new Program();

        int value = 27;
        double d = p.GetCost(value);
    }

    public double GetCost(int tot)
    {
        double cost = 0;
        if (tot < 1)
            return list[tot-1].Value;

        cost += GetCost(tot - list.Count);
        return cost;
    }        
}

So conceptually, I need to set that recursion GETCOST procedure to work properly so that it will call itself and get the RIGHT value (the second column) from the LIST and add it to the recursive caller.

EXPECTED RESULTS

if the "value" is 8 the total should be $19.10 $19.10 from KeyParValue(8 - 19.10)

if the "value" is 12 the total should be $36.60 $23 + 11.60 from KeyParValue(11 - 23.00) + KeyParValue(1 - 13.60)

if the "value" is 27 the total should be $61.90
$23 + $23 + $15.90; from KeyParValue(11 - 23.00) + KeyParValue(11 - 23.00) + KeyParValue(5 - 15.90)

Thanks advanced, F.

Upvotes: 1

Views: 1202

Answers (5)

Sascha
Sascha

Reputation: 10347

Maybe you want something like this:

public static double GetCost ( int tot ) {
  double  cost = 0;
  if ( tot > list.Count () )
    cost += ( (int)tot / list.Count () ) * list[list.Count () - 1].Value; // add n times the max value
  if ( tot % list.Count () > 0 )
    cost += list[( tot % list.Count () ) - 1].Value; // should add the remainder
  return cost;
}

Checked now in Visual Studio. Your second example is off by two. It should be 34.60 ( 23.00 + 11.60 = 34.60 ). As Jon has pointed out, there is an issue with 0. Maybe throw an ArgumentException or return zero, whatever fits your needs.

Edit: From your comment on Jon's answer I think that the list isn't ordered as in your sample. That means, calculating the total must be based on the key and not the index. A first shot ( giving you the expected results):

public static double GetCost ( int tot ) {
  int maxKey = list.Aggregate ( ( current, next ) => next.Key > current.Key ? next : current ).Key;
  double cost = 0;

  if ( tot > maxKey )
    cost += ( (int)tot / maxKey ) * list.Where ( kvp => kvp.Key == maxKey ).First ().Value; // add n times the max value
  if ( tot % maxKey > 0 )
    cost += list.Where ( kvp => kvp.Key == tot % maxKey ).First ().Value; // should add the remainder
  return cost;
}

Doesn't look that different. This function assumes all keys between one and maxKey do exist. If not, it will fail for the cases a required key is missing.

Upvotes: 0

Paul Walls
Paul Walls

Reputation: 6054

You don't need recursion or loops...

public double GetCost( int tot )
{
    int multipliers;
    int count;
    double cost;
    var dictionary = list.ToDictionary( kvp => kvp.Key, kvp => kvp.Value );

    count = list.Count;
    multipliers = tot / count;
    cost = multipliers * dictionary[count];
    tot %= count;
    if ( dictionary.ContainsKey( tot ) )
    {
        cost += dictionary[tot];
    }
    return cost;
}

Edit: Fixed the "tot==0 issue".

Upvotes: 0

Druegor
Druegor

Reputation: 389

I'd go with something like the following and remove the recursion. However, since the question was about recursion I've included the recursion logic as well. Really it just your list that is causing logic issues.

class Program
{
    private static Dictionary<int, double> _dollarValues;
    protected static Dictionary<int, double> DollarValues
    {
        get
        {
            if (_dollarValues == null)
            {
                _dollarValues = new Dictionary<int, double>();

                _dollarValues.Add(1, 11.60);
                _dollarValues.Add(2, 11.20);
                _dollarValues.Add(3, 13.00);
                _dollarValues.Add(4, 13.60);
                _dollarValues.Add(5, 15.90);
                _dollarValues.Add(6, 16.10);
                _dollarValues.Add(7, 19.10);
                _dollarValues.Add(8, 19.10);
                _dollarValues.Add(9, 19.10);
                _dollarValues.Add(10, 21.00);
                _dollarValues.Add(11, 23.00);
            }

            return _dollarValues;
        }
    }

    private static int _maxKey = 0;

    private static void Main(string[] args)
    {
        _maxKey = DollarValues.Max(key => key.Key);
        int value = 27;
        double cost = 0; //GetCost(value); If I wanted to use recursion instead.
        while(value > 0)
        {
            int key = value >= _maxKey ? _maxKey : value;
            cost += DollarValues[key];
            value -= key;
        }
    }
            //Recursion if I had to
    public static double GetCost(int value)
    {
        double cost = 0;
        cost += 
                       value >= _maxKey ? 
                              DollarValues[_maxKey] + GetCost(value - _maxKey) 
                              : DollarValues[value];
        return cost;
    }
}

Upvotes: 0

Jan
Jan

Reputation: 16038

This will return what you described in yout expected result section. But it feels like the thing you really want to achieve is something different.

public double GetCost(int tot)
{
    double cost = 0;
    while(tot > 0) {
        cost += tot >= 11 
                ? list[11] 
                : list[tot];
        tot -= tot % 11;
    }
    return cost;
}      

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1503290

This is problematic to start with:

if (tot < 1)
    return list[tot-1].Value;

If tot is less than 1, then tot - 1 is less than zero, and list[tot - 1] will throw an exception.

Do you actually want:

if (tot < 1)
    return list[tot].Value - 1;

? That's still only going to work if tot is 0, mind you...

It's not really clear to me what your code is meant to achieve in the first place - but I strongly suspect it would be clearer without using recursion. Perhaps you could describe what you're trying to do?

Upvotes: 2

Related Questions