C# - Sum integer in Array using recursive - c#

So i'm currently trying to calculate the sum of all bags in the array using a recursive method. I'm sure it's easy, but I can't seem to get my head around it. Any assistance would be appreciated! - Cheers.
class Program
{
static void Main(string[] args)
{
List<Bag> bags = new List<Bag>();
bags.Add(new Bag("Blue", 25));
bags.Add(new Bag("Red", 35));
bags.Add(new Bag("White", 30));
int totalVolume = CalcTotalVolume(bags);
Console.WriteLine("Total volume of bags: {0}", totalVolume);
}
static int CalcTotalVolume(List<Bag> bagList)
{
//resursive method
//1. base case is when the list is empty
if (bagList.Count == 0)
{
return 0;
}
else
{
List<int> subList = bagList.GetRange(1, bagList.Volume - 1);
int subTotal = CalcTotalVolume(subList);
int total = bagList[1] + subTotal;
return total;
}
}
}//end of class Program
class Bag
{
public string Colour { get; set; }
public int Volume { get; set; }
public Bag(string co, int vo)
{
Colour = co;
Volume = vo;
}
}

Obviously a loop is a lot more efficient, but just for a kata, this is sort of interesting...
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<Bag> bags = new List<Bag>();
bags.Add(new Bag("Blue", 25));
bags.Add(new Bag("Red", 35));
bags.Add(new Bag("White", 30));
int totalVolume = CalcTotalVolume(bags);
Console.WriteLine("Total volume of bags: {0}", totalVolume);
Console.ReadKey(true);
}
static int CalcTotalVolume(IEnumerable<Bag> bags)
{
//resursive method
//1. base case is when the list is empty
var bag = bags.FirstOrDefault();
if (bag == null) return 0;
var subList = bags.Skip(1);
return bag.Volume + CalcTotalVolume(subList);
}
}
class Bag
{
public string Colour { get; set; }
public int Volume { get; set; }
public Bag(string co, int vo)
{
Colour = co;
Volume = vo;
}
}
}

It would be interesting to know what kind of recursion you want. For example, the following also uses a recursive method but it amounts to a simple summing loop:
class Bag
{
public string Colour { get; }
public int Volume { get; }
public Bag(string c, int v)
{
Colour = c;
Volume = v;
}
}
class Program
{
static int CalcTotalVolumeIdx(List<Bag> bags, int i, int sum)
{
return (i >= bags.Count) ? sum :
CalcTotalVolumeIdx(bags, i + 1, sum + bags[i].Volume);
}
static int CalcTotalVolume(List<Bag> bags)
{
return CalcTotalVolumeIdx(bags, 0, 0);
}
static void Main(string[] args)
{
List<Bag> bags = new List<Bag>();
bags.Add(new Bag("Blue", 25));
bags.Add(new Bag("Red", 35));
bags.Add(new Bag("White", 30));
int totalVolume = CalcTotalVolume(bags);
Console.WriteLine("Total volume of bags: {0}", totalVolume);
}
}
As a side note, F# would actually compile the function CalcTotalVolumeIdx() into a while loop since this type of recursion is a well-known pattern that can be efficiently converted.
Edited to reflect Brian's comment. Thank you!

Related

SortedDictionary key Object duplicate Problem

I have a SortedDictionary with Object as key, which implements the IComparable interface,
but the result is not correct.
here is the code
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace TestApp {
public class Program
{
public class UserPrice : IComparable<UserPrice>
{
public string Wxid { get; set; }
public int Num { get; set; }
public int Price{ get; set; }
public DateTime PriceTime { get; set; }
public int CompareTo(UserPrice other)
{
if (Wxid == other.Wxid)
{
return 0;
}
if (Price != other.Price)
{
return other.Price.CompareTo(Price);
}
return PriceTime.CompareTo(other.PriceTime);
}
public override string ToString()
{
return String.Format("wxid={0}, num={1}, price={2}, priceTime={3}", Wxid, Num, Price, PriceTime);
}
}
private SortedDictionary<UserPrice, int> sortedPriceDict = new SortedDictionary<UserPrice, int>();
private BlockingCollection<UserPrice> chan = new BlockingCollection<UserPrice>();
private void MockMessage()
{
sortedPriceDict = new SortedDictionary<UserPrice, int>();
var task = Task.Run((Action)MockRecvMsg);
for (var i = 0; i < 10; i++)
{
var j = i;
Task.Run(() => MockSendMsg(j));
}
task.Wait();
}
private void MockRecvMsg()
{
while (true)
{
var p = chan.Take();
sortedPriceDict[p] = 1;
//Console.WriteLine(sortedPriceDict.Count + "," + p);
if(sortedPriceDict.Count > 10)
{
break;
}
}
foreach(var up in sortedPriceDict){
Console.WriteLine(up);
}
}
private async void MockSendMsg(int i)
{
var wxId = String.Format("user_{0}", i);
var rand = new Random();
var basePrice = 320;
while(true)
{
var up = new UserPrice();
up.Wxid = wxId;
up.Price = rand.Next(basePrice, basePrice + 100) * 100;
up.Num = rand.Next(1, 10);
up.PriceTime = DateTime.Now;
//Console.WriteLine(up);
chan.Add(up);
await Task.Delay(rand.Next(1, 5) * 1000);
}
}
public static void Main()
{
var main = new Program();
main.MockMessage();
}
}
}
I want to sort by [Price desc, PriceTime asc], user price with the same Wxid should by unique in the SortedDictionary, I start 10 Tasks to produce messages from 10 users, and 1 consumer to save the messages into the sortedDictionary, but after run for a while, the program will stop, because the dictionary's count is > 10, so what's wrong with my code ? Do I miss anything?

Array not returning max value

This is homework, but a small portion...
I'm trying to return the largest number in an array using arr.MAX(); , but I keep on getting zero.
After debugging, I can see that values are being stored (from the user) yet it still returns zero.
The method in question is at the bottom.
Class ElectionUI
{
public void candidateInfo()
{
do
{
for (int i = 0; i < theElection.CandidateNames.Length; i++)
{
Console.Write("Please enter the name for Candidate #" + (i +
1) + ": ");
theElection.CandidateNames[i] = Console.ReadLine();
Console.Write("Please enter the number of votes for: {0}: ",
theElection.CandidateNames[i]);
theElection.NumVotes[i] = int.Parse(Console.ReadLine());
Console.WriteLine("");
}
} while (theElection.NumVotes.Length < 5);
}
}
Class Election
{
private string[] candidateNames = new string[5];
private int[] numVotes = new int[5];
//get/set Candidate Names
public string[] CandidateNames
{
get { return candidateNames; }
set { candidateNames = value; }
}
//Get/Set Candidate votes
public int[] NumVotes
{
get { return numVotes; }
set { numVotes = value; }
}
public void findWinner()
{
int max = NumVotes.Max();
for (var i = 0; i < numVotes.Length; i++)
{
if (NumVotes[i] > max)
{
max = NumVotes[i];
}
}
Console.WriteLine(max);
}
}
from the code its not clear, how you are initializing you election class instance, and how you are calling findWinner method. And yes your Do-While looping doing nothing. Because you already set the name array length as 5 so it will run the for loop once and then it will exit. even if you remove your do-while you will get the same output.
check the fiddle your code is working fine. I just assume you are creating instance of Election and then passing it to ElectionUI class to use it.
https://dotnetfiddle.net/oiVK9g
using System;
using System.Linq;
public class Program
{
public static void Main()
{
var ele = new Election();
var ui = new ElectionUI(ele);
ui.candidateInfo();
ele.findWinner();
}
}
class ElectionUI
{
Election theElection;
public ElectionUI(Election obj)
{
theElection = obj;
}
public void candidateInfo()
{
do
{
for (int i = 0; i < theElection.CandidateNames.Length; i++)
{
Console.Write("Please enter the name for Candidate #" + (i +
1) + ": ");
theElection.CandidateNames[i] = Console.ReadLine();
Console.Write("Please enter the number of votes for: {0}: ",
theElection.CandidateNames[i]);
theElection.NumVotes[i] = int.Parse(Console.ReadLine());
Console.WriteLine("");
}
} while (theElection.NumVotes.Length < 5);
}
}
class Election
{
private string[] candidateNames = new string[5];
private int[] numVotes = new int[5];
//get/set Candidate Names
public string[] CandidateNames
{
get { return candidateNames; }
set { candidateNames = value; }
}
//Get/Set Candidate votes
public int[] NumVotes
{
get { return numVotes; }
set { numVotes = value; }
}
public void findWinner()
{
int max = NumVotes.Max();
Console.WriteLine(max);
}
}
I think that you wanted to return the candidate name of who won, right?
Using your code you should change the findWinner method to:
public void findWinner()
{
int max = NumVotes.Max();
string winnerName = null;
for (var i = 0; i < numVotes.Length; i++) {
if (NumVotes[i] = max) {
winnerName = CandidateNames[i];
}
}
Console.WriteLine(winnerName);
}
You need to initialize the local variable max with Int32.MinValue. That way any value encountered will replace it.

adding objects in a list, am i doing it right?

namespace ConsoleApplication13
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("how many footballs would you want?");
int amount = int.Parse(Console.ReadLine());
List<football> ballist = new List<football>();
for (int i = 0; i < amount; i++)
{
Console.WriteLine("how much should football {0} weigh?", i+1);
int weight = int.Parse(Console.ReadLine());
ballist.Add(new football(weight));
}
Console.WriteLine("amount of footballs is {0}", amount);
ballist.ForEach(s => Console.WriteLine(s.GetWeight()));
Console.ReadLine();
}
}
class football
{
private int weight = 0;
public int GetWeight()
{
return weight;
}
public football(int weigh)
{
weight = weigh;
}
}
}
adding objects in a list, am i doing it right?
A possible alternative is to let user input all the weights in one go and generate the list:
Console.WriteLine("please, input footballs' weights separated by comma");
String input = Console.ReadLine();
List<football> ballist = input
.Split(',')
.Select(item => new football(int.Parse(item)))
.ToList();
Some suggestions on Football class
// We usually start classes with capital letter
class Football {
private int m_Weight;
// C# is not Java, so use properties, which are more readable
public int Weight {
get {
return m_Weight;
}
private set {
// validate input
if (value <= 0)
throw new ArgumentOutOfRangeException("value");
m_Weight = value;
}
}
// "weight" - let argument correspond to property
public football(int weight) {
Weight = weight;
}
}
The adding to the list is right. I would recomend you to use property for the Weight.
class football
{
public int weight { get; set; }
}
If you dont want to have any code on the get/set.
public int _weight;
public int weight
{
get
{
//Your Code here
return _weight;
}
set
{
//And Here
_weight = value;
}
}

How to fix a StackOverflow exception in Get/Set?

Bear in mind that this is my first day of learning C#; this is also my first compiled language, so I am absolutely not used to the concept of 'types'. I am coming from Python.
It seems strongly typed languages are an order of magnitude more difficult than Python... v_v'
I get a StackOverflow exception, but I don't know why:
static void Main(string[] args)
{
Dictionary<string, int> init = new Dictionary<string,int>();
init["stepId"] = 250;
init["offset"] = 13;
init["inc"] = 113;
init["danger"] = 0;
StepGenerator gen = new StepGenerator(init);
Console.Write("Next: {0}", gen.Step["stepId"]);
Console.Read();
The error is seemingly here:
public Dictionary<string, int> Step
{
get { return Step; }
set
{
Dictionary<string, int> step = value;
// It complains about this line, and suggests an infinite recursion.
step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
step["limit"] = genDangerLimit(step["rnd"]);
step["enc"] = genEnc(step["danger"], step["limit"]);
Step = step;
}
Full:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace rePlanner
{
public class StepGenerator
{
// snipped array size:
private static readonly int[] rnlut = new int[] {0xB1}
enum Input
{
B,
G,
};
enum Encounter
{
No,
Yes,
}
enum Type
{
Run,
Walk,
Stutter,
Unit,
}
public Dictionary<string, int> Step
{
get { return Step; }
set
{
Dictionary<string, int> step = value;
step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
step["limit"] = genDangerLimit(step["rnd"]);
step["enc"] = genEnc(step["danger"], step["limit"]);
Step = step;
}
}
internal int stepId {get; set;}
internal int offset { get; set;}
internal int danger { get; set; }
internal int rnd { get; set; }
internal int dangerLimit { get; set; }
internal int enc { get; set; }
internal int type { get; set; }
internal int units { get; set; }
public int input { get; set; }
// Constructor.
public StepGenerator(Dictionary<string, int> step)
{
this.Step = step;
}
private int genStepId(int oldStepId)
{
return (oldStepId + 2) & 0xFF;
}
private int genOffset(int oldOffset, int stepId)
{
if (stepId == 0)
{
int offset = (oldOffset + 13) & 0xFF;
}
else
{
offset = oldOffset;
}
return offset;
}
private int genDanger(int oldDanger, int oldInc)
{
danger = oldDanger;
danger += oldInc;
if (danger > 65535)
{
danger = oldInc;
}
return danger;
}
private int genRnd(int rnlut, int offset)
{
return (rnlut - offset) & 0xFF;
}
private int genDangerLimit(int rnd)
{
return ((rnd + 1) * 256);
}
private int genEnc(int danger, int dangerLimit)
{
if(danger > dangerLimit)
{
return (int)Encounter.Yes;
}
return (int)Encounter.No;
}
public Dictionary<string, int> next()
{
Dictionary<string, int> step = this.Step;
step["stepId"] = genStepId(this.Step["stepId"]);
step["offset"] = genOffset(this.Step["offset"], this.Step["stepId"]);
step["danger"] = genDanger(this.Step["danger"], this.Step["inc"]);
step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
step["limit"] = genDangerLimit(step["rnd"]);
step["enc"] = genEnc(step["danger"], step["limit"]);
this.Step = step;
return step;
}
}
}
You're calling the setter on Step repeatedly with with line
Step = step;
This causes infinite recursion.
I think that you need to make your Step property the getter and setter for a private step member variable. First of all, remove
Dictionary<string, int> step = value;
from the Step setter. Make step a private member variable of StepGenerator:
private Dictionary<string, int> step;
Change your Step property to be:
public Dictionary<string, int> Step
{
get { return this.step; }
set
{
this.step = value;
this.step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
this.step["limit"] = genDangerLimit(step["rnd"]);
this.step["enc"] = genEnc(step["danger"], step["limit"]);
}
}

Refer variable from different class

using System;
namespace Matrix_Algebra
{
public struct S_Matrix_size
{
public int size_R, size_C;
public S_Matrix_size(int r, int c)
{
this.size_R = r;
this.size_C = c;
}
}
public class C_Matrix_entries
{
public C_Matrix_entries()
{
int r, c;
Console.WriteLine("Enter number of rows and columns ");
r = Convert.ToInt32(Console.ReadLine());
c = Convert.ToInt32(Console.ReadLine());
S_Matrix_size size = new S_Matrix_size(r,c);
double[,] entry = new double [size.size_R,size.size_C];
Console.WriteLine("Enter the entries from first row [left to right] to the last row ");
for (int i = 0; i<size.size_R; i++)
{
Console.WriteLine("Enter the {0} row", i + 1);
for (int j = 0; j<size.size_C;j++)
{
entry[i, j] = Convert.ToDouble(Console.ReadLine());
}
}
}
}
}
namespace Row_Reduce_Algebra
{
using Matrix_Algebra;
public class TEST
{
static void Main()
{
C_Matrix_entries matrix_no1 = new C_Matrix_entries();
for (int i = 0; i < **matrix_no1.size**; i++)
{
}
}
}
}
As the title says, I'm trying to access a variable from a class instance, but don't know how to do it properly.
You can't access matrix_no1.size because size is inaccessible.
Add a public property to your C_Matrix_entries class, and reference it in Main().
public class C_Matrix_entries
{
public S_Matrix_size size { get; private set; }
public C_Matrix_entries()
{
...
size = new S_Matrix_size(r,c);
As #GrantWinney rightfully pointed out (as I was shaping up a working reply for you), you cannot access matrix_no1.size because it is inaccessible. (It is also out of scope being that matrix_no1 is a local variable declared in the default C_Matrix_entries constructor.)
Based on your code, here is an end-to-end working example of how to fix the problem using a somewhat different public property added to C_Matrix_entries. Beyond the flavor of the new S_Matrix_size public property you add to C_Matrix_entries (i.e. Grant Winney's will work too), you will need to compute the product of its size_R and size_C properties in your loop's setup.
using System;
namespace Matrix_Algebra
{
public struct S_Matrix_size
{
public int size_R, size_C;
public S_Matrix_size(int r, int c)
{
this.size_R = r;
this.size_C = c;
}
}
public class C_Matrix_entries
{
private S_Matrix_size _size;
public C_Matrix_entries()
{
int r, c;
Console.WriteLine("Enter number of rows and columns ");
r = Convert.ToInt32(Console.ReadLine());
c = Convert.ToInt32(Console.ReadLine());
_size = new S_Matrix_size(r,c);
double[,] entry = new double [_size.size_R,_size.size_C];
Console.WriteLine("Enter the entries from first row [left to right] to the last row ");
for (int i = 0; i<_size.size_R; i++)
{
Console.WriteLine("Enter the {0} row", i + 1);
for (int j = 0; j<_size.size_C;j++)
{
entry[i, j] = Convert.ToDouble(Console.ReadLine());
}
}
}
public S_Matrix_size Size { get { return _size; } }
}
}
namespace Row_Reduce_Algebra
{
using Matrix_Algebra;
public class TEST
{
static void Main()
{
C_Matrix_entries matrix_no1 = new C_Matrix_entries();
for (int i = 0; i < matrix_no1.Size.size_R * matrix_no1.Size.size_C; i++)
{
// TODO: something useful
Console.WriteLine(i); // FORNOW
}
}
}
}

Categories

Resources