listboxes passing values from each other - c#

I'm trying to multiply the values of 2 listboxes together and make their product appear at another list box I'm getting the results I need but the problem is when I rerun the loop using a command button the listbox removes the next instance of the first value calculated by ppc[i] * qty[i] but when I try to remove the the listBox4.Items.Remove(ppc[i] * qty[i]) it reprints the whole array again from first element to last element
string myString = textBox1.Text.ToString();
int index = listBox6.FindString(myString, -1);
int[] qty = new int[99];
int[] ppc = new int[99];
int[] gt1 = new int[99];
listBox3.Items.Add(listBox5.Items[index]);
listBox1.Items.Add(textBox2.Text.ToString());
if (index != -1)
{
listBox6.SetSelected(index, true);
listBox2.Items.Add(textBox1.Text); //name
}
listBox3.Items.Add(listBox5.Items[index]);
listBox3.Items.Remove(listBox5.Items[index]);
for (int i = 0; i != listBox2.Items.Count ; i++)
{
ppc[i] = Convert.ToInt32(listBox3.Items[i]);
qty[i] = Convert.ToInt32(listBox1.Items[i]);
listBox4.Items.Remove(ppc[i] * qty[i]);
listBox4.Items.Add((ppc[i] * qty[i]));
}

My understanding is that this loop works once, and then when it is re-run it is out of order. Are you making sure to clear listbox4 each time this loop is executed? Also since listBox2 isn't used, it is probably better not to use it for your loop bounds.
if(listBox1.Items.Count == listBox3.Items.Count)
{
int rowCount = listBox1.Items.Count;
listBox4.Items.Clear();
for (int i=0; i < rowCount; i++)
{
ppc[i] = Convert.ToInt32(listBox3.Items[i]);
qty[i] = Convert.ToInt32(listBox1.Items[i]);
listBox4.Items.Insert(i , (ppc[i] * qty[i]));
}
}

Related

Figure out max number of consecutive seats

I had an interviewer ask me to write a program in c# to figure out the max number of 4 members families that can sit consecutively in a venue, taking into account that the 4 members must be consecutively seated in one single row, with the following context:
N represents the number of rows availabe.
The Columns are labeled from the letter "A" to "K", purposely ommiting the letter "i" (in other words, {A,B,C,D,E,F,G,H,J,K})
M represents a list of reserved seats
Quick example:
N = 2
M = {"1A","2F","1C"}
Solution = 3
In the representation you can see that, with the reservations and the size given, only three families of 4 can be seated in a consecutive order.
How would you solve this? is it possible to not use for loops? (Linq solutions)
I got mixed up in the for loops when trying to deal with the reservations aray: My idea was to obtain all the reservations that a row has, but then I don't really know how to deal with the letters (Converting directly from letter to number is a no go because the missing "I") and you kinda need the letters to position the reserved sits anyway.
Any approach or insight on how to go about this problem would be nice.
Thanks in advance!
Here is another implementation.
I also tried to explain why certain things have been done.
Good luck.
private static int GetNumberOfAvailablePlacesForAFamilyOfFour(int numberOfRows, string[] reservedSeats)
{
// By just declaring the column names as a string of the characters
// we can query the column index by colulmnNames.IndexOf(char)
string columnNames = "ABCDEFGHJK";
// Here we transform the reserved seats to a matrix
// 1A 2F 1C becomes
// reservedSeatMatrix[0] = [0, 2] -> meaning row 1 and columns A and C, indexes 0 and 2
// reservedSeatMatrix[1] = [5] -> meaning row 2 and column F, index 5
List<List<int>> reservedSeatMatrix = new List<List<int>>();
for (int row = 0; row < numberOfRows; row++)
{
reservedSeatMatrix.Add(new List<int>());
}
foreach (string reservedSeat in reservedSeats)
{
int seatRow = Convert.ToInt32(reservedSeat.Substring(0, reservedSeat.Length - 1));
int seatColumn = columnNames.IndexOf(reservedSeat[reservedSeat.Length - 1]);
reservedSeatMatrix[seatRow - 1].Add(seatColumn);
}
// Then comes the evaluation.
// Which is simple enough to read.
int numberOfAvailablePlacesForAFamilyOfFour = 0;
for (int row = 0; row < numberOfRows; row++)
{
// Reset the number of consecutive seats at the beginning of a new row
int numberOfConsecutiveEmptySeats = 0;
for (int column = 0; column < columnNames.Length; column++)
{
if (reservedSeatMatrix[row].Contains(column))
{
// reset when a reserved seat is reached
numberOfConsecutiveEmptySeats = 0;
continue;
}
numberOfConsecutiveEmptySeats++;
if(numberOfConsecutiveEmptySeats == 4)
{
numberOfAvailablePlacesForAFamilyOfFour++;
numberOfConsecutiveEmptySeats = 0;
}
}
}
return numberOfAvailablePlacesForAFamilyOfFour;
}
static void Main(string[] args)
{
int familyPlans = GetNumberOfAvailablePlacesForAFamilyOfFour(2, new string[] { "1A", "2F", "1C" });
}
Good luck on your interview
As always, you will be asked how could you improve that? So you'd consider complexity stuff like O(N), O(wtf).
Underlying implementation would always need for or foreach. Just importantly, never do unnecessary in a loop. For example, if there's only 3 seats left in a row, you don't need to keep hunting on that row because it is not possible to find any.
This might help a bit:
var n = 2;
var m = new string[] { "1A", "2F", "1C" };
// We use 2 dimension bool array here. If it is memory constraint, we can use BitArray.
var seats = new bool[n, 10];
// If you just need the count, you don't need a list. This is for returning more information.
var results = new List<object>();
// Set reservations.
foreach (var r in m)
{
var row = r[0] - '1';
// If it's after 'H', then calculate index based on 'J'.
// 8 is index of J.
var col = r[1] > 'H' ? (8 + r[1] - 'J') : r[1] - 'A';
seats[row, col] = true;
}
// Now you should all reserved seats marked as true.
// This is O(N*M) where N is number of rows, M is number of columns.
for (int row = 0; row < n; row++)
{
int start = -1;
int length = 0;
for (int col = 0; col < 10; col++)
{
if (start < 0)
{
if (!seats[row, col])
{
// If there's no consecutive seats has started, and current seat is available, let's start!
start = col;
length = 1;
}
}
else
{
// If have started, check if we could have 4 seats.
if (!seats[row, col])
{
length++;
if (length == 4)
{
results.Add(new { row, start });
start = -1;
length = 0;
}
}
else
{
// // We won't be able to reach 4 seats, so reset
start = -1;
length = 0;
}
}
if (start < 0 && col > 6)
{
// We are on column H now (only have 3 seats left), and we do not have a consecutive sequence started yet,
// we won't be able to make it, so break and continue next row.
break;
}
}
}
var solution = results.Count;
LINQ, for and foreach are similar things. It is possible you could wrap the above into a custom iterator like:
class ConsecutiveEnumerator : IEnumerable
{
public IEnumerator GetEnumerator()
{
}
}
Then you could start using LINQ.
If you represent your matrix in simple for developers format, it will be easier. You can accomplish it either by dictionary or perform not so complex mapping by hand. In any case this will calculate count of free consecutive seats:
public static void Main(string[] args)
{
var count = 0;//total count
var N = 2; //rows
var M = 10; //columns
var familySize = 4;
var matrix = new []{Tuple.Create(0,0),Tuple.Create(1,5), Tuple.Create(0,2)}.OrderBy(x=> x.Item1).ThenBy(x=> x.Item2).GroupBy(x=> x.Item1, x=> x.Item2);
foreach(var row in matrix)
{
var prevColumn = -1;
var currColumn = 0;
var free = 0;
var div = 0;
//Instead of enumerating entire matrix, we just calculate intervals in between reserved seats.
//Then we divide them by family size to know how many families can be contained within
foreach(var column in row)
{
currColumn = column;
free = (currColumn - prevColumn - 1)/familySize;
count += free;
prevColumn = currColumn;
}
currColumn = M;
free = (currColumn - prevColumn - 1)/familySize;
count += free;
}
Console.WriteLine("Result: {0}", count);
}

Why is the index out of bounds of the array when I'm resizing the array?

Here's a small piece of the program I am working on. I am trying to manually resize the array by creating another array, copying all of the items from the first array into the second and then having the first array refer to the second.
RoundInfo[] rounds = new RoundInfo[10];
int numRounds = 0;
RoundInfo ri;
RoundInfo[] newRI;
public void AddRound(int height, int speed)
{
if (numRounds >= rounds.Length) // creates a new array of RI objects if numRounds is greater than rounds.Length
{
newRI = new RoundInfo[numRounds + 1];
// Console.WriteLine("numRounds: {0} length: {1}", numRounds, rounds.Length); // me checking if the AddRound correctly increments numRounds, it does.
//Console.WriteLine(newRI.Length);
for (int i = 0; i < newRI.Length; i++)
newRI[i] = rounds[i]; // *THE PROGRAM CRASHES HERE*
rounds = newRI;
ri = new RoundInfo(height, speed);
rounds[numRounds] = ri;
numRounds++;
}
if (numRounds < rounds.Length) // the program goes through this fine
{
ri = new RoundInfo(height, speed);
rounds[numRounds] = ri;
numRounds++;
}
}
I don't see why it crashes if the new array is longer.
because you're entering in first if when numRounds == rounds.Length.
where 10==rounds.Length(which is 10)
theng adding on
if (numRounds >= rounds.Length) // here you're having numRounds as 10
{
newRI = new RoundInfo[numRounds + 1]; //here you're adding + 1 will get newRI = new RoundInfo[11]
for (int i = 0; i < newRI.Length; i++)
newRI[i] = rounds[i]; // *THE PROGRAM CRASHES HERE*
// so in here your program will crash due to indexOutOfBOunds because newRI[11] = rounds[11];
//rounds[11] is not existing
rounds = newRI;
ri = new RoundInfo(height, speed);
rounds[numRounds] = ri;
numRounds++;
}
you may prevent this by not adding +1 on newRI
if (numRounds >= rounds.Length)
{
newRI = new RoundInfo[numRounds]; //remove +1 here
//etc codes
}
I don't know what is your intention in this part
// creates a new array of RI objects if numRounds is greater than rounds.Length
copying an array but exceeds previous array length is impossible. It seems you're trying to do (newArray[oldArray.Length + 1] == oldArray[oldArray.Length])
which you cannot do because it will really go out of bounds.
newArray[11] can't have oldArray[11] because it is not existing
what you may try is the length of oldArray, not the new
for (int i = 0; i < rounds.Length; i++)
newRI[i] = rounds[i];

Adding values to a list box from array WITH text

I'm adding values from a file to an array and then adding those values to a list box in a form. I have methods performing calculations and everything is working great, but I'd like to be able to use a loop and insert the year prior to the values I am inserting into the list box. Is there a way to use the .Add method and include a variable which will be changing in this? Something like populationListbox.Items.Add(i, value); if i is my loop counter? Code is below so I'd like first line in the list box to have the year I specify with my counter, followed by the population. Like this, "1950 - 151868". As of now it only displays the value 151868. Thanks!
const int SIZE = 41;
int[] pops = new int[SIZE];
int index = 0;
int greatestChange;
int leastChange;
int greatestYear;
int leastYear;
double averageChange;
StreamReader inputFile;
inputFile = File.OpenText("USPopulation.txt");
while (!inputFile.EndOfStream && index < pops.Length)
{
pops[index] = int.Parse(inputFile.ReadLine());
index++;
}
inputFile.Close();
foreach (int value in pops)
{
**populationListbox.Items.Add(value);**
}
greatestChange = greatestIncrease(pops) * 1000;
leastChange = leastIncrease(pops) * 1000;
averageChange = averageIncrease(pops) * 1000;
greatestYear = greatestIncreaseyear(pops);
leastYear = leastIncreaseyear(pops);
greatestIncreaselabel.Text = greatestChange.ToString("N0");
leastIncreaselabel.Text = leastChange.ToString("N0");
averageChangelabel.Text = averageChange.ToString("N0");
greatestIncreaseyearlabel.Text = greatestYear.ToString();
leastIncreaseyearlabel.Text = leastYear.ToString();
Like this?
int i = 1950;
foreach (int value in pops)
{
populationListbox.Items.Add(i.ToString() + " - " + value);
i++;
}
Your life will be a lot easier if you stop trying to program C# as if it were 1980s C and use the power of it's Framework:
var pops = File.ReadLines("USPopulation.txt").Select(int.Parse);
populationListbox.Items.AddRange(pops.Select((p,i) => $"{i} - {p}"));

How to write groups of numbers using Console.Write?

I'm very new to C# (And Stack Overflow, forgive me for any poor etiquette here), and I'm writing the game Mastermind in a console application. I'm trying to show a list of the user's guesses at the end of the game, and I know that using Console.WriteLine(); will just give me 30-odd lines off numbers which don't tell the user anything.
How can I alter my code so that the program displays 4 numbers in a group, at a time? For example:
1234
1234
1234
//Store numbers in a history list
ArrayList guesses = new ArrayList(); //This is the ArrayList
Console.WriteLine("Please enter your first guess.");
guess1 = Convert.ToInt32(Console.ReadLine());
guesses.Add(guess1);
foreach (int i in guesses)
{
Console.Write(i);
}
I assume that each element of your byte array is a single digit (0-9). If that assumption is invalid -- please let me know, I'll modify the code :)
Action<IEnumerable<int>> dump = null;
dump = items =>
{
if(items.Any())
{
var head = String.Join("", items.Take(4));
Console.WriteLine(head);
var tail = items.Skip(4);
dump(tail);
}
};
dump(guesses);
It looks like you're most of the way there, you have a console write that writes them all out without linebreaks. Next add an integer count and set it to zero. Increment it by one in the foreach loop. count % 4 == 0 will then be true for all counts that are a multiple of four. This means you can stick an if block there with a write-line to give you your groups of four.
List<int> endResult = new List<int>();
StringBuilder tempSb = new StringBuilder();
for(int i=0; i < groups.Count; i++)
{
if(i % 4 == 0) {
endResult.Add(int.Parse(sb.ToString()));
tempSb.Clear(); // remove what was already added
}
tempSb.Append(group[i]);
}
// check to make sure there aren't any stragglers left in
// the StringBuilder. Would happen if the count of groups is not a multiple of 4
if(groups.Count % 4 != 0) {
groups.Add(int.Parse(sb.ToString()));
}
This will give you a list of 4 digit ints and make sure you don't lose any if your the number of ints in your groups list is not a multiple of 4. Please note that I am continuing based on what you provided, so groups is the ArrayList of ints.
This is some thing I quickly put together:
Update:
ArrayList guesses = new ArrayList(); //This is the ArrayList
// Four or more
guesses.Add(1); guesses.Add(2);
guesses.Add(3);guesses.Add(4);
guesses.Add(5); guesses.Add(6); guesses.Add(7);guesses.Add(8); guesses.Add(9);
//Uncomment-Me for less than four inputs
//guesses.Add(1); guesses.Add(2);
int position = 0;
if (guesses.Count < 4)
{
for (int y = 0; y < guesses.Count; y++)
{
Console.Out.Write(guesses[y]);
}
}
else
{
for (int i = 1; i <= guesses.Count; i++)
{
if (i%4 == 0)
{
Console.Out.WriteLine(string.Format("{0}{1}{2}{3}", guesses[i - 4], guesses[i - 3],
guesses[i - 2], guesses[i - 1]));
position = i;
}
else
{
if (i == guesses.Count)
{
for (int j = position; j < i; j++)
{
Console.Out.Write(guesses[j]);
}
}
}
}
}

loop though a array then if and then output result?

i have a little problem, in the code below (C#) it loops thought the arrays, it then check if the user_id has a user_post greater than 50, it then write the user_id, the expected outcome is
12
13
but the actual output is
12
12
12
whats wrong with the code? I tried a standard for loop but could not get it right?
int[] user_id = new int[64];
int[] group_id = new int[64];
int[] user_post = new int[64];
//user 55
user_id[0] = 10;
group_id[0] = 8;
user_post[0] = 4;
//user56
user_id[1] = 11;
group_id[1] = 2;
user_post[1] = 15;
//user57
user_id[2] = 12;
group_id[2] = 2;
user_post[2] = 55;
//user58
user_id[3] = 13;
group_id[3] = 2;
user_post[3] = 56;
foreach (int i in group_id)
{
if (group_id[i] == 2)
if (user_post[i] > 50)
Console.WriteLine(Convert.ToString(user_id[i]));
}
Console.WriteLine("Press any key too continue...");
Console.ReadLine();
// continue...
Because you have an if statement that only checks for 2
if (group_id[i] == 2)
where as "i" is not a counter instead the element from the foreach loop.
and items at 2 & 3rd position have 2 group id so it alway ends like this:
if (group_id[8] == 2) //false
if (group_id[2] == 2) //true
if (group_id[2] == 2) //true
Instead of that vague code you should have your loop as this:
for(int i = 0 ; i< 64 ; i++)
{
if (group_id[i] == 2)
{
if (user_post[i] > 50)
Console.WriteLine(Convert.ToString(user_id[i]));
}
}
in your foreach statement, i takes on the values stored in your group_id array - 8, 2, 2, 2
In your if and output statements, your are using this value as an index into the arrays
So, your if statements end up doing this:
if(group_id[8])...
if(group_id[2])...
if(group_id[2])...
if(group_id[2])...
You are only examining elements 8 and 2 in your arrays.
Use a for loop to iterate through the array indexes
The for syntax is as follows:
for (int i = 0; // incremental variable
i < 100; // determining a limit
++i) // increment the variable
While foreach works like this:
foreach (var element // the element itself, not an index
in
elementCollection) // iterating through the collection
You're looping around the wrong array with the for each statement. You should loop using the regular for statement instead like this:
for (int i = 0;i < user_post.Length; i++)
{
if (user_post[i] > 50 && group_id[i] == 2)
{
Console.WriteLine(Convert.ToString(user_id[i]));
}
}
foreach (int i in group_id)
is wrong, you must use:
for(int i = 0; i < group_id.Length; i++)
because with the former you're using the values in group_id as indexes of your arrays.
BTW, I'd suggest you to create a class e.g. Info like:
class Info
{
public int GroupId {get; set;};
public int UserId {get; set;};
public int PostId {get; set;}
}
this would allow you to create one array only (i.e. Info[]) and avoid possible errors due to different lenghts of the 3 arrays...

Categories