How to add values to specific column in 2D arrays? - c#

I suppose to fill the value each time the user try to make an appointment. There is Two type of Appointment: Appointment a and Appointment b. Each appointment can make it only 4 a day. So, my dimensional would have two columns for types of appointment and 4 rows for 4 appointments. I just tried if the user types only "a".
If the user types "a" for the first time, my 2D array will look like:
1111
1000
If the user types "a" for the second time, the 2D array will look like:
1111
1200
And so on... So finally the 2D array will look like:
1111
1234
int[,] slots = new int[4,2];
string appt_type;
string choice = "Y";
while (choice == "Y")
{
Console.WriteLine("Please enter a or b");
appt_type = Console.ReadLine();
if (appt_type == "a")
{
for (int i=0; i<slots.GetLength(0); i++)
{
for (int j=0; j<slots.GetLength(1); j++)
{
slots[i,0] = 1;
slots[i,j] = i+1;
}
}
int q = 0;
foreach (int i in slots)
{
if ((q%2) == 1)
Console.WriteLine(i + " ");
else
Console.Write(i + " ");
q++;
}
}
}
My final output is what I expect it. However, I want to fill each of the second column each time the user enters "a".
First enters "a"
1111 1000
Second time enters "a"
1111 1200
Third time enters "a"
1111 1230
Fourth time enters "a"
1111 1234

First of all,your for loop isn't as you want it,because before the user inputs "a" or "b" you already initialized in the for loop inside for loop,the array as it should be in the end.After the for loops the array is 1111 1234.
You can create a counter variable to count the number of times the user had entered "a" each time that you get the input.In this specific case there is a connection between the row of the array,and the amount of "a"'s the user has entered so I initialized the counter with 0 even though it value goes up only if you enter "a" again.The amount of "a"'s the user has entered-1 because it is 1 for sure after it gets into the forloop,so thats why you can also set it as the element of the array that you wanted to change.
Additionally,you can use while(true) instead of creating a variable and leave it the same.
Its pretty much like this:(Tried to use your way printing it)
int[,] slots = new int[4, 2];
string appt_type;
int counter = 0;//counts how many times the user had enter the letter "a"
while (true)
{
Console.WriteLine("Please enter a or b");
appt_type = Console.ReadLine();
if (appt_type == "a")
{
counter++;
for (int i = 0; i < slots.GetLength(0); i++)
{
for (int j = 0; j < slots.GetLength(1); j++)
{
slots[i, 0] = 1;
slots[counter - 1,1 ] = counter;//note:all of the elements that you want to change are in column 1 of the array
}
}
int q = 1;//the position of i in the array
foreach (int i in slots)
{
if(q%2!=1)
Console.WriteLine(i+" " );
else
Console.Write(i);
q++;
}

In order for your code to allow the user to input his/her choice and make the code do something based on that choice, you need to check the element's value if it is 0 or something else and then do something based on that value. Here is a quick untested fix, but you can get the gist:
for (int i=0; i<slots.GetLength(0); i++)
{
for (int j=0; j<slots.GetLength(1); j++)
{
if (slots[i,j] == 0)
{
slots[i,j] = i+1;
break;
}
}
}
I think your code can still be improved in a lot more ways. Here are my suggestions:
Break apart your code in methods to make it easier to read.
Separate the routines when A is selected, when B is selected, and
when slots is displayed.
It is clear that upon selecting choice A, the first column of the
array is set to 1111 and does not change up to the end, so set it
once and forget about going through it by checking if the first
element of the column is equal to 1.
You don't have to go through all of the elements in the second column
just to set the value. Just check for the first 0 that you encounter
and set it to the current index + 1.
Use break to get out of loops easily and eliminate the curly braces to
make the code look a bit cleaner.
Ignore the case when comparing strings, because a != A.
Here is a suggested and tested refactor. Add a break point on while(true), make it run in debug mode, and see how the code flows on every user input:
class Program
{
static void Main(string[] args)
{
var slots = new int[4, 2];
while (true)
{
Console.Write("Do you want to proceed? [Y/N]");
var choice = Console.ReadLine();
if (!choice.Equals("y", StringComparison.CurrentCultureIgnoreCase))
break;
Console.WriteLine("Please enter a or b: ");
var appt_type = Console.ReadLine();
if (appt_type.Equals("a", StringComparison.CurrentCultureIgnoreCase))
slots = AssignScheduleA(slots);
else if (appt_type.Equals("b", StringComparison.CurrentCultureIgnoreCase))
AssignScheduleB(slots);
DisplaySlotsValue(slots);
}
}
private static int[,] AssignScheduleA(int[,] slots)
{
if (slots[0,0] != 1)
{
for(int idx1 = 0; idx1 < slots.GetLength(0); idx1++)
slots[idx1, 0] = 1;
}
for(int idx2 = 0; idx2 < slots.GetLength(0); idx2++)
{
if (slots[idx2, 1] == 0)
{
slots[idx2, 1] = idx2 + 1;
break;
}
}
return slots;
}
private static void AssignScheduleB(int[,] slots)
{
throw new NotImplementedException();
}
private static void DisplaySlotsValue(int[,] slots)
{
for (int idx1 = 0; idx1 < slots.GetLength(0); idx1++)
Console.Write(slots[idx1, 0]);
Console.WriteLine();
for (int idx2 = 0; idx2 < slots.GetLength(0); idx2++)
Console.Write(slots[idx2, 1]);
Console.WriteLine();
}
}
If you go over this while on debug mode, you will understand how the code will let the user make a choice every time and fill in the array based on the choice. This code can still be improved and that can be something that you do as you learn more about C#. Happy coding!

Related

Creating an Integer range for input into int variable

So i have a project where i need to store 8 integers, between 1-10, and recall them into a histogram
The histogram is made up of the character * only. (forgive bad formatting, this is my first post)
The program works, but i think my if statements for int restriction (1-10) could be simplified.
My goal is to achieve this output with as little code as possible
The whole code, and nothing but the code (and comments)
Console.WriteLine("Hello and Welcome!\nEnter 8 values between 1 and 10\n*Press Any Key to continue*");
Console.ReadKey();
//create list to store values
List<int> values = new List<int>();
//loop to collect values
for (int i = 1; i < 9; i++)
{
//label for data validation start point
retry:
Console.WriteLine("Please Enter Value " + i, "Between 1 - 10");
//variable assigned to user input
value = Console.ReadLine();
//Convert string to integer
if (!int.TryParse(value, out validValue))
{
Console.WriteLine("~Incorrect Data Input~"); goto retry; };
if (validValue < 1) { Console.WriteLine("~Incorrect Data Input~"); goto retry; };
if (validValue > 10) { Console.WriteLine("~Incorrect Data Input~"); goto retry; };
values.Add(validValue);
}
for (int i = 0; i < 8; i++ )
{
Console.WriteLine();
for(int id = 0; id < values[i]; id++)
Console.Write("*");
}
Console.ReadKey();
This is the area im thinking could be cleaner
if (validValue < 1) { Console.WriteLine("~Incorrect Data Input~"); goto retry; };
if (validValue > 10) { Console.WriteLine("~Incorrect Data Input~"); goto retry; };
Im open to any suggestions as to how i could clean this or any part of the project up.
There is a more difficult aspect to this project, like a do this if you want to show off kind of thing, where i would need the histogram to be displayed vertically.
I figure this would be done with 2d arrays? i havent really got a clue other than needing 80 spaces and *'s in the right spaces lol.
Ive only been coding for a month or so and it being learner based, any help or suggestions would be welcomed
Thank you
Chris
Here's a sample of how you could reconstruct your logic with a couple of pointers.
Console.WriteLine("Hello and Welcome!\nEnter 8 values between 1 and 10\n*Press Any Key to continue*");
Console.ReadKey();
//create list to store values
List<int> values = new List<int>();
//loop to collect values (no need to run from 1 - 9; 0 - 8 works fine.)
for (int i = 0; i < 8; i++)
{
//label for data validation start point
int validValue = 0;
//Use a while loop instead of a goto
while (validValue == 0)
{
Console.WriteLine("Please Enter Value " + i, "Between 1 - 10");
//variable assigned to user input
var value = Console.ReadLine();
//Convert string to integer
//If the first question in the predicate fails, it won't go on to ask the other questions
if (int.TryParse(value, out validValue) && validValue > 0 && validValue < 10)
{
values.Add(validValue);
}
else
{
Console.WriteLine("~Incorrect Data Input~");
}
//If the code reaches this point and validValue hasn't been changed, it'll be 0 and the loop will run again
}
}
for (int i = 0; i < 8; i++)
{
Console.WriteLine();
for (int id = 0; id < values[i]; id++)
Console.Write("*");
}
Console.ReadKey();

Fibonnacci sequence using Arrays and For Loops

This program is to create a wave like structure using C# with the fibonnaci sequence and arrays. With the number of the sequence being at the end and asterisks equaling what number is on the current line in front. This is all done using the For loops and having the upper limiter done by the Array, I solve that limiter problem by using the .Length aspect of Arrays but I don't grasp the concept of how to properly use the array within this sequence.
This first part of code I have the sequence building up using my array with 12 index as I only need the 11 first fibonacci sequences.
The problem I am running into is within the second part of the code.
class Program
{
static void Main(string[] args)
{
int a = 0, b = 1;
int[] fibArray = new int[12];
fibArray[0] = 0;
fibArray[1] = 1;
Console.WriteLine("0");
Console.WriteLine("*1");
for (int i = 3; i <= fibArray.Length; i++)
{
fibArray[i] = a + b;
a = b;
b = fibArray[i];
for(int y = 1; y <= fibArray[i]; y++)
{
Console.Write("*");
}
Console.Write("" + fibArray[i]);
Console.WriteLine();
}
With this second part of code I am unable to get it to register and output the sequence. Mostly I am unsure of how to properly set up my array to ensure that the fibonacci sequence is able to go reverse as well. I understand the sequence is typically f(n)=f(n-1)+f(n-2), I cannot wrap my head around how to properly use arrays in this context.
for (int p = fibArray[11]; p >= fibArray.Length; p--)
{
for (int k = 1; k <= p; k++)
{
Console.Write("*");
}
Console.Write(""+ b);
Console.WriteLine();
}
}
}
}
Sorry for ranting, just trying to explain the code as a whole but to give a sum of what I am asking about.
It would be how to use the Arrays, what I did wrong with my current code, and what aspect I could use to control the loops using the Array itself.
To give an overall example of the desired output it would be like so:
0
*1
*1
**2
***3
***3
**2
*1
*1
0
Some things to note about your original code. You manually set the first two values in the sequence at elements 0 and 1, but then skipped over element 2 and started from element 3. Your loop was including the length of the array as valid index when it should start at (array length - 1) since arrays are zero based in .Net.
You can output the correct length of asterisks by using this string constructor.
I'd separate the generation of the sequence from the output:
static void Main(string[] args)
{
// building the Fibonacci sequence (no output at this time)
int[] fibArray = new int[12];
for (int i = 0; i < fibArray.Length; i++)
{
switch (i)
{
case 0:
fibArray[i] = 0;
break;
case 1:
fibArray[i] = 1;
break;
default:
fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
break;
}
}
// increasing curve
for (int i = 0; i < fibArray.Length; i++)
{
Console.WriteLine(new String('*', fibArray[i]) + fibArray[i].ToString());
}
// decreasing curve
for (int i = (fibArray.Length-1); i >= 0; i--)
{
Console.WriteLine(new String('*', fibArray[i]) + fibArray[i].ToString());
}
Console.WriteLine();
Console.Write("Press Enter to Quit");
Console.ReadLine();
}
Output:
0
*1
*1
**2
***3
*****5
********8
*************13
*********************21
**********************************34
*******************************************************55
*****************************************************************************************89
*****************************************************************************************89
*******************************************************55
**********************************34
*********************21
*************13
********8
*****5
***3
**2
*1
*1
0
Press Enter to Quit

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);
}

int list won't display in console application

I come from a C++ background creating basic 2D games with it, but I am trying to teach myself C# to a point to where I can get the most basic of jobs using it. I am not in school but I am following the Problems on ProjectEuler.net.
The problem question is commented into the code. I can't tell whether I solved it or not because I can't get the numbers to display from a list into the console application.
I've tried writing to console directly from the variable value with Console.WriteLine but I'm not having any luck. I've also tried converting all int list values to a string value and displaying them but that also didn't work.
I'm not looking for the answer to number 4 just looking to display the list so I can find the answer on my own.
Why can't I get the list to write to the Console?
Any help is appreciated!
static void Main(string[] args)
{
/* A palindromic number reads the same both ways.
* The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers. */
// 100 x 100 = 10000
// 999 x 999 = 998001
List<int> palindromeContainer = new List<int>();
int Increment = 2;
int Holder = 0;
for (int i = 100; i <= 999; ++i)
{
int j = i;
while (j <= 999)
{
do
{ Holder = i * j; // Gets all Possible Combinations of i * j
if ((Holder % Increment) != 0) // Checks for Prime Numbers
{
++Increment;
}
else if (Increment == Holder - 1 && Holder % Increment != 0 )
{
palindromeContainer.Add(Holder);
Increment = 2;
break;
}
else if (Increment == Holder - 1 && Holder % Increment == 0)
{
Increment = 2;
break;
}
} while (Increment < Holder);
++j;
}
}
palindromeContainer.Sort();
foreach (int line in palindromeContainer)
{
Console.WriteLine(line); // Display all items in list
}
Firstly comment out your loop logic and test without:
List<int> palindromeContainer = new List<int>();
palindromeContainer.Add(2);
palindromeContainer.Add(1);
palindromeContainer.Sort();
foreach (int line in palindromeContainer)
{
Console.WriteLine(line); // Display all items in list
}
Console.ReadLine();
This will output to the console. Then you will know this is working and console output is not the problem.

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]);
}
}
}
}
}

Categories