i have made a 2D array in c#. I want have a method to fill in some numbers and a method to print it. But this doesnt work. Since it is for school. The static void main cant be changed. Can anyone help me? the if statement is true and will say invalid number of arguments here is some code:
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("invalid number of arguments!");
Console.WriteLine("usage: assignment[1-3] <nr of rows> <nr of columns>");
return;
}
int numberOfRows = int.Parse(args[0]);
int numberOfColumns = int.Parse(args[1]);
Program myProgram = new Program();
myProgram.Start(numberOfRows, numberOfColumns);
}
void Start(int numberOfRows, int numberOfColumns)
{
int[,] matrix = new int[numberOfRows, numberOfColumns];
InitMatrix2D(matrix);
DisplayMatrix(matrix);
}
void InitMatrix2D(int[,] matrix)
{
int numberPlusOne = 1;
for (int rows = 0; rows < matrix.GetLength(0); rows++)
{
for (int columns = 0; columns < matrix.GetLength(1); columns++)
{
matrix[rows, columns] = numberPlusOne++; // telkens vullen met +1
}
}
}
void DisplayMatrix(int[,] matrix)
{
for (int rows = 0; rows < matrix.GetLength(0); rows++)
{
for (int columns = 0; columns < matrix.GetLength(1); columns++)
{
Console.Write($"{matrix[rows, columns]}");
}
}
}
The if statement is true.
It may not be obvious, but the array of strings passed to Main(string[] args) — args — are the arguments passed to the program on the command line, aptly called command line arguments. If you start a C# program named, say, myprog from a Console window with myprog 1 2 3, the operating system and .net runtime see to it that args will have (typically) four elements, namely "myprog", "1", "2" and "3". Perhaps the first one is missing and it's only "1", "2" and "3"; that seems to be the case when I try it on Windows 10 and .net 5.0.
You have probably never started your (or maybe any) program from the command line, hence your confusion.
In order to start a custom program which is not in the program search path from the Console, you need to know where it is because you either cd there or type the entire path name. The program may not be easy to find if you work with an IDE like Visual Studio.1
But Visual Studio allows you to pass arguments to the program via the project's properties dialog. Right-click the project, click Properties at the bottom, choose "Debug" on the left and enter two numbers in the "Application arguments" text box. Then hit F5 if you have a Debug build configuration active.
As an aside:
It is customary to return from Main with a non-zero value if the program encounters an error. That return value is used as the exit status of the program, which can be inspected by the caller. The wrong number of arguments is a very basic error condition that should be diagnosable: A script may choose not to continue when a critical step in a processing chain failed. It would be better to declare Main to return int. That way you can return non-zero when an error is encountered. Since you cannot change Main, this is perhaps a note to your teacher (who will likely answer that he doesn't want to complicate matters ;-) ).
It is customary to make error output on standard error, not on standard out. The reason is that a caller may parse the standard output (perhaps output from a chain of programs, not only yours!) and would be confused by unexpected text in the standard output. It would be better to write Console.Error.WriteLine("invalid number of arguments!");.
1 You can right-click the editor tab of a source file in Visual Studio and click "open containing folder"; somewhere below that project folder is an exe file, simply search *.exe in the explorer that opened. Right-click the entry with your exe and choose "open file location", then shift-right-click that folder and choose "open cmd window here", or the powershell equivalent.
Whew.
Now, if your program is named program.exe, type program 5 7 or whatever values you desire, and it should work.
Here are two different ways to display a matrix
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
16,17,18,19,20
21,22,23,24,25
26,27,28,29,30
31,32,33,34,35
| 1 2 3 4 5|
| 6 7 8 9 10|
| 11 12 13 14 15|
| 16 17 18 19 20|
| 21 22 23 24 25|
| 26 27 28 29 30|
| 31 32 33 34 35|
The first way is like a CSV file, with comma-separated values for each row. It is still human-readable but primarily targeted toward file operations.
The second way is arranged in a table/grid which far more human-readable, but less readable by computers.
The code to generate the above two styles is declared using extension methods, DisplayDelimited() and DisplayTable()
public static class DisplayExtensions
{
public static string DisplayDelimited<T>(this T[,] matrix, string columnSeparator = ",")
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
if (j > 0)
{
sb.Append(columnSeparator);
}
sb.Append(matrix[i, j]);
}
sb.AppendLine();
}
return sb.ToString();
}
public static string DisplayTable<T>(this T[,] matrix, int columnWidth = 8, string bracketSymbol = "|")
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < matrix.GetLength(0); i++)
{
sb.Append(bracketSymbol);
for (int j = 0; j < matrix.GetLength(1); j++)
{
if (j > 0)
{
sb.Append(" ");
}
sb.Append(matrix[i, j].ToString().PadLeft(columnWidth));
}
sb.AppendLine(bracketSymbol);
}
return sb.ToString();
}
}
class Program
{
static void Main(string[] args)
{
int value = 0;
int[,] matrix = new int[7, 5];
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 5; j++)
{
matrix[i, j] = ++value;
}
}
Console.WriteLine(matrix.DisplayDelimited());
Console.WriteLine(matrix.DisplayTable());
}
}
Related
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!
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.
Well I'm trying to write a program in which if you add for example 3 integers in the array, let's say 3 2 1, it will add them again after it so it becomes 321 321.
Here is the code I need to fix. And sorry for the stupid question I am a beginner with arrays.
I get this error
Index was outside the bounds of the array
My code:
using System;
public class Program
{
public static void Main()
{
int arraylength = int.Parse(Console.ReadLine());
int[] array = new int[arraylength];
for (int i = 0; i < arraylength + 1 / 2; i++)
{
int typed = int.Parse(Console.ReadLine());
array[i] = typed;
if (i == arraylength / 2)
{
for (int a = arraylength + 1 / 2; a < arraylength + 1; a++)
{
array[a] = typed;
}
}
}
}
}
Array indices in C# start at 0 and end at length - 1. You need to remove the + 1 from each of your for loop conditions:
for (int i = 0; i < arraylenght / 2; i++)
and
for (int a = (arraylenght + 1) / 2; a < arraylenght; a++)
I also suggest that you change arraylenght to arraylength. Since you probably autocompleted this every time you used it, the misspelling occurs consistently throughout your code and the compiler is satisfied. However, misspellings make it difficult for humans to read your code.
p.s. Your code doesn't do what you think it does. I suggest you step away from the computer for a moment and write in words what you are trying to accomplish. Describe each step of your solution in as much detail as you can. Then look at how your words match with the code you wrote. You will probably find that you do not need nested loops.
I have an application whose entry point is like
static void Main(String[] args)
{
int T = Int32.Parse(Console.ReadLine());
for (int t = 0; t < T; ++t)
{
int[] line = Array.ConvertAll(Console.ReadLine().Split(' '), Int32.Parse);
int N = line[0], M = line[1];
char[,] matrix = new char[M, N];
for (int i = 0; i < N; ++i)
{
char[] row = Console.ReadLine().Where(c => c != ' ').ToArray();
for (int j = 0; j < M; ++j)
matrix[j, i] = row[j];
}
int K = Int32.Parse(Console.ReadLine());
var ff = new ForbiddenForest(matrix);
Console.WriteLine(K == ff.OptimalMoveNumbers ? "Impressed" : "Oops!");
}
}
and I have test input like
3
2 3
*.M
.X.
1
4 11
.X.X......X
.X*.X.XXX.X
.XX.X.XM...
......XXXX.
3
4 11
.X.X......X
.X*.X.XXX.X
.XX.X.XM...
......XXXX.
4
which I need to debug and which I don't want to manually type in to the console line-by-line. What would be the easiest way to feed this in to the program? Is there a way of writing batch file that would run ThisProgram.exe and feed it my test input?
Assuming you use Visual Studio as your development IDE:
You can feed input to your application for Debug purposes by putting these input in Project Properties > Debug > Command line arguments.
You can loop through a file with the for-loop in batch:
for /f "delims=" %%g in (yourInputFile.txt) do (
ThisProgram.exe %%g
)
Also make sure, yourInputFile.txt is placed in the same directory as the batchfile and ThisProgram.exe . If they are not in the same directory you will have to change the directory using cd path\to\files
For my program, I've prompted the user to put 20 names into an array (the array size is 5 for testing for now), this array is then sent to a text document. I need to make it so that it will randomly pick a name from the list and display it (which I have done). But I now need to make it increase the chances of a name being picked, how would I go about doing this?
Eg. I want to increase the chances of the name 'Jim' being picked from the array.
class Programt
{
static void readFile()
{
}
static void Main(string[] args)
{
string winner;
string file = #"C:\names.txt";
string[] classNames = new string[5];
Random RandString = new Random();
Console.ForegroundColor = ConsoleColor.White;
if (File.Exists(file))
{
Console.WriteLine("Names in the text document are: ");
foreach (var displayFile in File.ReadAllLines(file))
Console.WriteLine(displayFile);
Console.ReadKey();
}
else
{
Console.WriteLine("Please enter 5 names:");
for (int i = 0; i < 5; i++)
classNames[i] = Console.ReadLine();
File.Create(file).Close();
File.WriteAllLines(file, classNames);
Console.WriteLine("Writing names to file...");
winner = classNames[RandString.Next(0, classNames.Length)];
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\nThe winner of the randomiser is: {0} Congratulations! ", winner);
Thread.Sleep(3000);
Console.Write("Completed");
Thread.Sleep(1000);
}
}
}
There's two ways of doing this. You can either produce a RNG with a normal distribution targeting one number.
Or the simpler way is a translational step. Generate in the range 0-100 and then produce code which translates to the answer in a biased way e.g.
0-5 : Answer 1
6-10: Answer 2
11-90: Answer 3
91-95: Answer 4
96-100: Answer 5
This gives an 80% chance of picking Answer 3, the others only get a 5% chance
So where you currently have RandString.Next(0, classNames.Length) you can replace that with a function something like GetBiasedIndex(0, classNames.Length, 3)
The function would look something like this (with test code):
public Form1()
{
InitializeComponent();
int[] results = new int[5];
Random RandString = new Random();
for (int i = 0; i < 1000; i++)
{
var output = GetBiasedIndex(RandString, 0, 4, 3);
results[output]++;
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 5; i++)
{
builder.AppendLine(results[i].ToString());
}
label1.Text = builder.ToString();
}
private int GetBiasedIndex(Random rng, int start, int end, int target)
{
//Number between 0 and 100 (Helps to think percentage)
var check = rng.Next(0, 100);
//There's a few ways to do this next bit, but I'll try to keep it simple
//Allocate x% to the target and split the remaining y% among all the others
int x = 80;//80% chance of target
int remaining = 100 - x;//20% chance of something else
//Take the check for the target out of the last x% (we can take it out of any x% chunk but this makes it simpler
if (check > (100 - x))
{
return target;
}
else
{
//20% left if there's 4 names remaining that's 5% each
var perOther = (100 - x) / ((end - start) - 1);
//result is now in the range 0..4
var result = check / perOther;
//avoid hitting the target in this section
if (result >= target)
{
//adjust the index we are returning since we have already accounted for the target
result++;
}
//return the index;
return result;
}
}
and the output:
52
68
55
786
39
If you're going to call this function repeatedly you'll need to pass in the instance of the RNG so that you don't reset the seed each call.
If you want to target a name instead of an index you just need to look up that name first and have an else condition for when that name isn't found