How to write groups of numbers using Console.Write? - c#

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

Related

How do you store the index position of a repeated keyword and store it in an array?

I want to make a program that finds how many times a key word has been repeated (i.e. "the") and then store the index position in a array. At the moment, my code only store's the first time it reads "the" in the string sentence. How do you make it that it stores the index position of the first time it reads "the" and the second?
It outputs on the console:
11
0
My current code:
string sentence = "John likes the snow and the winter.";
string keyWord = "the";
var test = sentence.Split(new char[] { ' ', '.' });
var count = Array.FindAll(test, s => s.Equals(keyWord.Trim())).Length;
int[] arr = new int[count];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = sentence.IndexOf("the", i);
i++;
}
foreach (int num in arr)
{
Console.WriteLine(num);
}
Console.ReadLine();
Second result (0) is there because of unnecessary i++ in the for loop. Because of that, you are entering the loop only once. To achieve what you want you could try code like below (please take a closer look at body of the for loop:
string sentence = "John likes the snow and the winter.";
            string keyWord = "the";
            var test = sentence.Split(new char[] { ' ', '.' });
            var count = Array.FindAll(test, s => s.Equals(keyWord.Trim())).Length;
            int[] arr = new int[count];
            int lastIndex = 0;
            for (int i = 0; i < arr.Length; i++)
            {
                lastIndex = sentence.IndexOf("the", lastIndex + keyWord.Length); //We are adding length of the `keyWord`, because we want to skip word we already found.
                arr[i] = lastIndex;
            }
            foreach (int num in arr)
            {
                Console.WriteLine(num);
            }
            
            Console.ReadLine();
I hope it makes sense.
There are two problems that I see with your code. First, you're incrementing i twice, so it will only ever get half the items. Second, you're passing i as the second parameter to IndexOf (which represents the starting index for the search). Instead, you should be starting the search after the previous found instance by passing in the index of the last instance found plus its length.
Here's a fixed example of the for loop:
for (int i = 0; i < arr.Length; i++)
{
arr[i] = sentence.IndexOf(keyword, i == 0 ? 0 : arr[i - 1] + keyword.Length);
}
Also, your code could be simplified a little if you use a List<int> instead of an int[] to store the indexes, because with List you don't need to know the count ahead of time:
string sentence = "John likes the snow and the winter.";
string keyWord = "the";
var indexes = new List<int>();
var index = 0;
while (true)
{
index = sentence.IndexOf(keyWord, index); // Find the next index of the keyword
if (index < 0) break; // If we didn't find it, exit the loop
indexes.Add(index++); // Otherwise, add the index to our list
}
foreach (int num in indexes)
{
Console.WriteLine(num);
}

Increasing sequence in one dimensional array

You're given an array of integers,in case if you see subsequence in which each following bigger than the previous on one(2 3 4 5) you have to rewrite this subsequence in the resulting array like this 2 - 5 and then the rest of the array. So in general what is expected when you have 1 2 3 5 8 10 11 12 13 14 15 the output should be something like 1-3 5 8 10-15.
I have my own idea but can't really implement it so all I managed to do is:
static void CompactArray(int[] arr)
{
int[] newArr = new int[arr.length];
int l = 0;
for (int i = 0,k=1; i <arr.length ; i+=k,k=1) {
if(arr[i+1]==arr[i]+1)
{
int j = i;
while (arr[j+1]==arr[j]+1)
{
j++;
k++;
}
if (k>1)
{
}
}
else if(k==1)
{
newArr[i] = arr[i];
}
}
In short here I walk through the array and checking if next element is sum of one and previous array element and if so I'm starting to walk as long as condition is true and after that i just rewriting elements under indices and then move to the next.
I expect that people will help me to develop my own solution by giving me suggestions instead of throwing their own based on the tools which language provides because I had that situation on the russian forum and it didn't help me, and also I hope that my explanation is clear because eng isn't my native language so sorry for possible mistakes.
If I understand the problem correctly, you just need to print the result on the screen, so I'd start with declaring the variable which will hold our result string.
var result = string.Empty
Not using other array to store the state will help us keep the code clean and much more readable.
Let's now focus on the main logic. We'd like to loop over the array.
for (int i = 0; i < array.Length; i++)
{
// Let's store the initial index of current iteration.
var beginningIndex = i;
// Jump to the next element, as long as:
// - it exists (i + 1 < array.Length)
// - and it is greater from current element by 1 (array[i] == array[i+1] - 1)
while (i + 1 < array.Length && array[i] == array[i+1] - 1)
{
i++;
}
// If the current element is the same as the one we started with, add it to the result string.
if (i == beginningIndex)
{
result += $"{array[i]} ";
}
// If it is different element, add the range from beginning element to the one we ended with.
else
{
result += $"{array[beginningIndex]}-{array[i]} ";
}
}
All that's left is printing the result:
Console.WriteLine(result)
Combining it all together would make the whole function look like:
static void CompactArray(int[] array)
{
var result = string.Empty;
for (int i = 0; i < array.Length; i++)
{
var beginningIndex = i;
while (i + 1 < array.Length && array[i] == array[i+1] - 1)
{
i++;
}
if (i == beginningIndex)
{
result += $"{array[i]} ";
}
else
{
result += $"{array[beginningIndex]}-{array[i]} ";
}
}
Console.WriteLine(result);
}

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.

When arrays go awry?

I'm trying to learn C# by solving mathematical problems. For example, I'm working on finding the sum of factors of 3 or 5 in the first 1000 positive numbers. I have the basic shell of the code laid out, but it isn't behaving how I'm expecting it to.
Right now, instead of getting a single output of 23, I am instead getting 1,1,3,3,5,5,7,7,9,9. I imagine I messed up the truncate function somehow. Its a bloody mess, but its the only way I can think of checking for factors. Second, I think that the output is writing during the loop, instead of patiently waiting for the for() loop to finish.
using System;
namespace Problem1
{
class Problem1
{
public static void Main()
{
//create a 1000 number array
int[] numberPool = new int[10];
//use for loop to assign the first 1000 positive numbers to the array
for (int i = 0; i < numberPool.Length; i++)
{
numberPool[i] = i + 1;
}
//check for factors of 3 or 5 using if/then statment
foreach (int i in numberPool)
if ((i / 3) == Math.Truncate((((decimal)(i / 3)))) || ((i / 5) == Math.Truncate(((decimal)(i / 5)))))
{
numberPool[i] = i;
}
else
{
numberPool[i] = 0;
}
//throw the 0s and factors together and get the sum!
int sum = 0;
for (int x = 0;x < numberPool.Length;x++)
{
sum = sum + numberPool[x];
}
Console.WriteLine(sum);
Console.ReadLine();
//uncomment above if running in vbs
}
}
}
The foreach loop has a few errors.
If you want to modify the array you are looping through use a for loop. Also, use modulus when checking remainders.
for (int i = 0; i < numberPool.Length; i++)
{
if (numberPool[i] % 3 == 0 || numberPool[i] % 5 == 0)
{
// Do nothing
}
else
{
numberPool[i] = 0;
}
}
Modulus (%) will give the remainder when dividing two integers.
Another useful shortcut, variable = variable + x can be replaced with variable += x
Please note that there are more concise ways of doing this but since you are learning the language I will leave that for you to find.
#kailanjian gave some great advice for you but here is another way your initial logic can be simplified for understanding:
//the sum of factors
int sum = 0;
//the maximum number we will test for
int maxNum = 1000;
//iterate from 1 to our max number
for (int i = 1; i <= maxNum; i++)
{
//the number is a factor of 3 or 5
if (i % 3 == 0 || i % 5 == 0)
{
sum += i;
}
}
//output our sum
Console.WriteLine(sum);
You also stated:
Second, I think that the output is writing during the loop, instead of patiently waiting for the for() loop to finish.
Your program logic will execute in the order that you list it and won't move on to the next given command until it is complete with the last. So your sum output will only be printed once it has completed our for loop iteration.

Categories