C# Array Length Update - c#

I am solving the problem from this link: https://www.hackerrank.com/challenges/cut-the-sticks (I added the link for more details if my explanation wasn't enough or wasn't quite clear.)
The point here from the exercise that I in the first I give a (int) number of sticks that I will use in the operation. the second line I enter the sticks length. So I must find the smallest stick(k), then subtract it from the rest of the sticks, then make the program print the number of total sticks that I have cut. So if the stick was cut before or its original value is 0 I have to remove it and don't count it. Then this should repeat over to redefine the value of the k because the min array value will be changed because all the sticks are cutted.
Here is my code that I used:
int n = Convert.ToInt32(Console.ReadLine());
string[] userinput = Console.ReadLine().Split(' ');
int[] arr = new int[n];
arr = Array.ConvertAll(userinput, Int32.Parse);
for (int i = 0; i < n - 1; i++)
{
arr = arr.Where(s => s != '0').ToArray();
int k = arr.Min();
arr[i] -= k;
Console.WriteLine(arr.Length);
}
Console.ReadKey();
The problem is it keeps printing the n value, which is the array's original size, it doesn't modify after the removing of the 0. So how can I fix it to just print the number of cutted sticks and when the all sticks is 0 so break?
I'm sorry for my English and if my explanation is a bit hard, but I am just new to C#.

This is the working code as you expected and tested.
Note: I just reused all the variable names and naming conventions as you did which can be refactored further.
class Program
{
static void Main(string[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
string[] userinput = Console.ReadLine().Split(' ');
int[] arr = new int[n];
arr = Array.ConvertAll(userinput, Int32.Parse);
CutTheStick(arr);
Console.ReadKey();
}
private static void CutTheStick(int[] arr)
{
arr = arr.Where(s => s != 0).ToArray();
if (arr.Length > 0)
{
Console.WriteLine(arr.Length);
int k = arr.Min();
for (int i = 0; i < arr.Length; i++)
{
arr[i] -= k;
}
CutTheStick(arr);
}
}
}
If you had web/winForm based application, remove the static keyword accordingly.

There is an evident error in your code. The char '0' is not the integer 0. The automatic conversion between char and int allows this code to compile and run but you are not testing correctly your inputs
For example
int[] arr = new int[] {0,1,2,3,4};
if(arr[0] == '0')
Console.WriteLine("Is Zero");
will never print "Is Zero", while
int[] arr = new int[] {48,1,2,3,4};
if(arr[0] == '0')
Console.WriteLine("Is Zero");
will print "Is Zero" because the integer value of the char '0' is 48.
Now to give a solution to your problem I could post this code
int cutCount = 1;
int n = Convert.ToInt32(Console.ReadLine());
string[] userinput = Console.ReadLine().Split(' ');
int[] arr = Array.ConvertAll(userinput, Int32.Parse);
// Loop until we finish to empty the array
while (true)
{
// remove any zero present in the array
arr = arr.Where(s => s != 0).ToArray();
// If we don't have any more elements we have finished
if(arr.Length == 0)
break;
// find the lowest value
int k = arr.Min();
// Start a loop to subtract the lowest value to all elements
for (int i = 0; i < arr.Length; i++)
arr[i] -= k;
// Just some print to let us follow the evolution of the array elements
Console.WriteLine($"After cut {cutCount} the array length is {arr.Length}");
Console.Write("Array is composed of: ");
foreach(int x in arr)
Console.Write(x + " ");
Console.WriteLine();
}
Console.ReadLine();
But please study it carefully because otherwise my solution is no help for you in future programming tasks

Related

assigning numbers entered in a row to an array 3 6 23 12 4 a[0]=3 a[1]=6 a[2]=23 a[3]=12 a[4]=10

string[] n = Console.ReadLine().Split();
for (int i = 1; i <6; i++)
{
int[] a = long.Parse(n[i]);
}
If each number in a row separated with whitespace - you can use your Split more efficiently:
int[] array = Console.ReadLine().Split().Select(int.Parse).ToArray(); // Improved according to #Caius Jard comment
If need array of longs - replace int.Parse with long.Parse and declare variable as long[] array.
You need to add using System.Linq to get access to ToArray extension method.
EDIT.
Insprired by #Caius Jard, non-LINQ version:
// Read input line and split it by whitespace (default)
string[] values = Console.ReadLine().Split();
// Declare arrays for Int or Long values.
// Arrays sizes equals to size of array of input values
int[] arrayOfInts = new int[values.Length];
long[] arrayOfLongs = new long[values.Length];
// Iterate with for loop over amount of input values.
for (int i = 0; i < values.Length; i++)
{
// Convert trimmed input value to Int32
arrayOfInts[i] = int.Parse(values[i].Trim());
// Or to Int64
arrayOfLongs[i] = long.Parse(values[i].Trim());
}
int.Parse and long.Parse may be replaced with Convert.ToInt32 and Convert.ToInt64 if needed.
Please, don't use magic constants: i < 6. Here 6 doesn't necessary equal to n.Length.
You can put it as
string[] n = Console.ReadLine().Split();
List<int> list = new List<int>();
for (int i = 0; i < n.Length; ++i) {
if (int.TryParse(n[i], out int value))
list.Add(value);
else {
// Invalid item within user input, say "bla-bla-bla"
//TODO: either reject the input or ignore the item (here we ignore)
}
}
if (list.Count == a.Length) {
// We have exactly a.Length - 6 valid integer items
for (int i = 0; i < a.Length; ++i)
a[i] = list[i];
}
else {
//TODO: erroneous input: we have too few or too many items
}

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

How to Display an Array in C#?

so I'm new to coding and I've decided to learn C# with the whole Covid-19 going on, and I've run into a small problem if anybody can assist me.
I'm just writing a basic C# program to allow the user to input 5 numbers into an array and then display the array, but for some reason, I only display the number 5, not the whole array.
Please find my code: ( if anyone can make it easier for me please help me lol (: )
int[] numbers = new int[5];
int num = 0;
int i = 0;
Console.WriteLine("This porgram allows the user to input 5 numbers into an array");
Console.Write("--------------------------------------------------------------");
Console.WriteLine("\n");
for ( i = 0; i < numbers.Length; i ++)
{
Console.WriteLine("Please input number");
num = Convert.ToInt32(Console.ReadLine());
}
for (i = 0; i < numbers.Length; i++)
{
Console.ReadLine();
Console.WriteLine("Your array is: " , numbers );
}
Console.WriteLine();
// any help will be appreciated!
Two problems:
1) You haven't put the number coming in. After
num = Convert.ToInt32(Console.ReadLine());
put
numbers[i] = num;
Though in fact num is superfluous, so you could just have
numbers[i]= Convert.ToInt32(Console.ReadLine());
2) In the second loop you need to display the specific array element:
Console.WriteLine("Your array item is: " , numbers[i] );
Also, not sure what the ReadLine() in the second loop is for - just means the users has to hit return to see each number.
It's worth mentioning a few other issues in the code:
Variables should be declared as close as possible to where they are used. this i should be declared separately for each for loop - for(int i = 0; ... and num should be declared inside the loop (though as mentioned, it's redundant).
Be clear on the difference between Console.Write() and Console.WriteLine(). WriteLine() simply adds a \n to whatever is displayed. Thus it would be clearer (for the same output to have:
Console.WriteLine("--------------------------------------------------------------");
Console.WriteLine();
here is code:
it is the basic syntax of displaying an array.
public class Work
{
public static void Main()
{
int[] arr = new int[5];
int i;
Console.Write("\nRead & Print elements of an array:\n");
Console.Write("-----------------------------------------\n");
Console.Write("Input 5 elements in the array :\n");
for(i=0; i<5; i++)
{
Console.Write("element - {0} : ",i);
arr[i] = Convert.ToInt32(Console.ReadLine());
}
Console.Write("\nElements in array are: ");
for(i=0; i<5; i++)
{
Console.Write("{0} ", arr[i]);
}
Console.Write("\n");
}
}

Get sequence of random n numbers that add up to something but only from a specific set of numbers

What I need is:
e.g:
Sum should be equal to:
120 (user input)
Number of numbers/items:
80 (user input)
Range of numbers to be used in set(from):
0 (user input)
Range of numbers to be used in set(to):
4 (user input)
Output:
1,1,3,2,1,1,0,0,1,1,2,1,0,2,3,3,1,2,0,0,0,1,3,2,3,1,0,0,2,3,2,3,2,2,1,1,0,0,2,0,1,0,1,1,3,3,1,3,1,0,0,3,2,1,0,0,2,1,2,3,0,3,1,1,3,3,2,2,1,1,3,1,3,3,3,3,3,1,2,0
These are all numbers that are between 0 and 4, their sum is 120 and are 80 in total.
What i've done is:
static void Main(string[] args)
{
bool loopOn = true;
Program p = new Program();
Console.WriteLine("____________________________________________________________________________");
Console.WriteLine("");
Console.WriteLine("Sum should be equal to:");
int sum = int.Parse(Console.ReadLine());
Console.WriteLine("Number of items:");
int items = int.Parse(Console.ReadLine());
Console.WriteLine("Range(from):");
int from = int.Parse(Console.ReadLine());
Console.WriteLine("Range(to):");
int to = int.Parse(Console.ReadLine());
while (loopOn == true)
{
List<int> number_list = p.createNumberSet(items, from, to);
if (number_list.Sum() == sum)
{
loopOn = false;
Console.WriteLine("____________________________________________________________________________");
Console.WriteLine("Start");
number_list.ForEach(Console.WriteLine);
Console.WriteLine("Stop");
Console.WriteLine("____________________________________________________________________________");
}
}
Console.WriteLine("Press any key to exit....");
Console.ReadLine();
}
public List<int> createNumberSet(int itemNumber, int range_from, int range_to)
{
List<int> number_set = new List<int>();
Random r = new Random();
for (int i = 0; itemNumber > i; i++)
{
number_set.Add(r.Next(range_from, range_to));
}
return number_set;
}
But this seems extremely in-efficent and doesn't seem to work with a lot of other examples. Does anyone have a better way of doing this?
Well, I am a bit lazy right now, so this is just an idea
Keep the first part:
bool loopOn = true;
Program p = new Program();
Console.WriteLine("____________________________________________________________________________");
Console.WriteLine("");
Console.WriteLine("Sum should be equal to:");
int sum = int.Parse(Console.ReadLine());
Console.WriteLine("Number of items:");
int items = int.Parse(Console.ReadLine());
Console.WriteLine("Range(from):");
int from = int.Parse(Console.ReadLine());
Console.WriteLine("Range(to):");
int to = int.Parse(Console.ReadLine());
Now, first of all, check is a solution exists:
if (from * items > sum) {
// There is no solution, handle accordingly
}
Let's focus on the interesting part now:
First create the list of necessary items
int[] number_set = new int[items];
for(int i = 0; i < items; i++) {
number_set[i] = from;
}
Find the difference between the wanted sum and the current sum of the list
int left_to_add = sum - from * items;
int idx = 0;
Random r = new Random();
while(left_to_add > 0) {
int toAdd = 0;
if (left_to_add < range_to - range_from) {
toAdd = r.Next(1, left_to_add);
} else {
toAdd = r.Next(1, range_to - range_from);
}
left_to_add -= toAdd;
number_set[idx] += toAdd;
idx++;
}
What's left to do is, convert the array to a list and shuffle it.
(I forgot that you actually can access list items by index, so there is no need to use an array as I did here)
At the algorithm level, this is what I would try:
Determine the number of each element, n[0], n[1], n[2], n[3] in your example (i.e. number of 0, number of 1 ...) and then generate a simple sequence by concatenating n[0] "0", n[1] "1", n[2] "2" and n[3] "3". Finally, a random sequence is obtained by performing a random permutation on this simple sequence.
The problem is therefore to determine the n[i].
The first step is to determine the average values of these n[i]. It your example, it is simple, as we can take average n_av[i]=20 for all index i.
In a more general case, we have to insure that
sum_i n_av[i]*i = sum_target (120 here) (1)
knowing that
sum_i (n[i]) = n = 80 here. (2)
In the general case, there is no necessary one unique good solution. I will try to propose an example of solution here if you provide an example of a difficult scenario.
The second step consists in selecting some random n[i] values around these average values. One possibility is to generate rounded Gaussian variables: we already know the averages, we just need to determine the variances. One possibility is to consider the variance that we will get if we were generating directly the random values, i.e. by considering the variance of the corresponding binomial variable :
var = n p(1-p). Here p[i] = n_av[i]/n
The last step consists in adjusting the values of the n[i] such that the sum of the n[i] is equal to the target. This is simply obtained by slightly increasing or decreasing some n[i] values.

Why does my C# code does not work as intended (arrays transformation, newbie)

I'm trying to take array of numbers (0 or 1 only) and repeatedly transform it as follows:
first and last numbers are always 0;
all the other numbers are
derived from previous state of array: if array[n] and its two neighbours
(array[n-1], array[n] and array[n+1]) have the same value (three 0s or three 1s) then newarray[n] should be be 1, otherwise it should be 0 (that produces nice patterns).
For example, if the array size is 10 and it starts with all zeroes, then program should output this:
0000000000
0111111110
0011111100
0001111000
0100110010
0000000000
0111111110
...and so on
I wrote a code that should do this and it doesn't work as intended. It always does first transformation perfectly but then begins some wrong, asymmetric, crazy stuff:
0000000000
0111111110
0000000000
0101010100
0000000010
0101010000
What makes my code behave the way it does?
Here is the code:
namespace test
{
class Program
{
public static void Main(string[] args)
{
const int leng = 10; //length of array
int[] arrayone = new int[leng];
int[] arraytwo = new int[leng];
for (int i = 0; i<=leng-1; i++)
{
arrayone[i] = 0;
arraytwo[i] = 0;
} //making two arrays and filling them with zeroes
for (int i = 0; i<=leng-1; i++)
{
Console.Write(arrayone[i]);
}
Console.WriteLine(' '); //printing the first state of array
for (int st=1; st<=16; st++) //my main loop
{
arraytwo[0]=0;
arraytwo[leng - 1]=0; //making sure that first and last elements are zero. I'm not sure I need this since I fill both arrays with zeroes in the beginning. But it probably doesn't hurt?
for (int i = 1; i<=leng-2; i++) //calculating new states for elements from second to second-to-last
{
if (((arrayone[i-1]) + (arrayone[i]) + (arrayone[i+1]) == 0) | ((arrayone[i-1]) + (arrayone[i]) + (arrayone[i+1]) == 3) == true)
arraytwo[i] = 1;
else
arraytwo[i] = 0;
}
//by now arraytwo contains transformed version of arrayone
for (int i = 0; i<=leng-1; i++)
{
Console.Write(arraytwo[i]);
} //printing result
arrayone = arraytwo; //copying content of arraytwo to arrayone for the next round of transformation;
Console.WriteLine(' ');
}
Console.Write(" ");
Console.ReadKey(true);
}
}
}
Tweakable version: https://dotnetfiddle.net/8htp9N
As pointed out you're talking an object and working on it, at the end of that you're assigning the reference not the values. one way to combat that would be
for your line: arrayone = arraytwo;
change it to : arrayone = (int[])arraytwo.Clone();
this will copy the values - for integers this will be sufficient.
Please, notice how your current code is complex and thus diffcult to debug. Make it simpler, extract a method:
using System.Linq;
...
private static IEnumerable<int[]> Generate(int width) {
int[] item = new int[width];
while (true) {
yield return item.ToArray(); // .ToArray() - return a copy of the item
int[] next = new int[width];
for (int i = 1; i < item.Length - 1; ++i)
if (item[i - 1] == item[i] && item[i] == item[i + 1])
next[i] = 1;
item = next;
}
}
Then you can put
public static void Main(string[] args) {
var result = Generate(10) // each line of 10 items
.Take(7) // 7 lines
.Select(item => string.Concat(item));
Console.Write(string.Join(Environment.NewLine, result));
}
Outcome:
0000000000
0111111110
0011111100
0001111000
0100110010
0000000000
0111111110

Categories