Change this nested for loop to recursion [duplicate] - c#

This question already has an answer here:
Creating all possible arrays without nested for loops [closed]
(1 answer)
Closed 6 years ago.
I posted this similar, previous question, but I was not very clear.
I have the following code:
int N=4;
int[] myArray = new int[N];
for (int i1 = 1; i1 < N; i1++)
myArray[0]=i1;
for (int i2 = 1; i2 < N; i2++)
myArray[1]=i2;
for (int i3 = 1; i3 < N; i3++)
myArray[2]=i3;
for (int i4 = 1; i4 < N; i4++)
{
myArray[3]=i4;
foreach (var item in myArray)
Console.Write(item.ToString());
Console.Write(Environment.NewLine);
}
This outputs the following:
1111
1112
1113
1121
1122
1123
1131
....
3332
3333
Is there a simple way to change this nested for loop to recursion? I am not very skilled at programming, so the simpler, the better. I am not worried about how efficient the code is.
I, effectively, would like to be able to change the int N in my code to different numbers, without having to add or remove anything from my code.
EDIT
Here is what I have so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sandbox
{
class Program
{
static void Main(string[] args)
{
int class_length = 4;
int[] toric_class = Enumerable.Repeat(1, class_length).ToArray();
Recursion(toric_class, class_length, 1, 3);
Console.Read();
}
static void Recursion(int[] toric_class, int length, int number, int spot)
{
if (number < 4)
{
toric_class[spot] = number;
foreach (var item in toric_class)
{
Console.Write(item.ToString());
}
Console.Write(Environment.NewLine);
Recursion(toric_class, length, number + 1, spot);
}
}
}
}
This only outputs
1111
1112
1113
I am unsure of where to go from here.

public static void Set(int[] array, int index, int N)
{
if (index == N)
{
foreach (var item in array)
Console.Write(item.ToString());
Console.Write(Environment.NewLine);
return;
}
for (int i = 1; i < N; i++)
{
array[index] = i;
Set(array, index + 1, N);
}
}
And call it this way:
int N = 4;
int[] myArray = new int[N];
Set(myArray, 0, N);

If you want just to simplify and generalize the solition, you don't want any recursion:
// N - length of the array
// K - kind of radix; items of the array will be in [1..K] range
private static IEnumerable<int[]> Generator(int N = 4, int K = 3) {
int[] items = Enumerable
.Repeat(1, N)
.ToArray();
do {
yield return items.ToArray(); // .ToArray() : let's return a copy of the array
for (int i = N - 1; i >= 0; --i)
if (items[i] < K) {
items[i] += 1;
break;
}
else
items[i] = 1;
}
while (!items.All(item => item == 1));
}
Test
string test = string.Join(Environment.NewLine, Generator(4)
.Select(items => string.Concat(items)));
Console.Write(test);
Outcome:
1111
1112
1113
1121
1122
...
3321
3322
3323
3331
3332
3333

Related

Iterate over the same array from 2 different directions

I have this problem from school:
You get a list of N students and a list of grades for each student. Every student gets coins. A student which has bigger grade than his neighbours from list earns more coins than them. Find the coins which every student must recieve.
Input:
6
Ionel
Mihai
Elena
Maria
George
Irina
9
10
8
6
9
10
Output:
Ionel 1
Mihai 3
Elena 2
Maria 1
George 2
Irina 3
Here is my code:
static void Main()
{
int number = Convert.ToInt32(Console.ReadLine());
string[] studentsList = FillTheList(number);
int[] studentsGrades = ConvertList(FillTheList(number));
PrintResult(studentsList, CalculateCoins(studentsGrades, number));
}
static string[] FillTheList(int number)
{
string[] result = new string[number];
for (int i = 0; i < number; i++)
{
result[i] = Console.ReadLine();
}
return result;
}
static int[] ConvertList(string[] array)
{
int[] result = new int[array.Length];
for (int i = 0; i < array.Length; i++)
{
result[i] = Convert.ToInt32(array[i]);
}
return result;
}
static int[] GiveEachStudentCoins(int number)
{
int[] result = new int[number];
result[0] = 1;
return result;
}
static void CheckArray(int[] array, int[] theResult, int number, int counter)
{
int i = number;
int count = counter;
int[] result = theResult;
for (int j = 0; j < array.Length; j++)
{
if (array[i] < array[j])
{
result[j] += count;
}
else
{
break;
}
}
}
static int[] CalculateCoins(int[] array, int number)
{
int[] result = GiveEachStudentCoins(number);
const int count = 1;
for (int i = 1; i < array.Length; i++)
{
if (array[i - 1] < array[i])
{
result[i] += result[i - 1] + count;
}
else
{
result[i] += count;
CheckArray(array, result, i, count);
}
}
return result;
}
static void PrintResult(string[] array, int[] array2)
{
for (int i = 0; i < array.Length; i++)
{
array[i] += " " + array2[i];
}
foreach (string student in array)
{
Console.WriteLine(student);
}
}
It works for ascending and descending order of grades, and also for equal grades. But it doesn't work for mixed order. Here is the result I get:
Ionel 3
Mihai 4
Elena 2
Maria 1
George 2
Irina 3
My problem is on the CheckArray method I think, and I don't know how to change the logic for this thing to work.
We can access the neighboring elements while walking through the array in a for loop by subtracting or adding 1 to the index of the current item. Of course before we do this, we have to make sure that the neighbor we want to check actually exists (if i == 0 then we can't access index i - 1, and if i == array.Length - 1, then we can't access index i + 1).
Given this knowledge, we can follow a simple formula, just as if we were doing it "by hand" on a piece of paper:
Start all values in the coins array with 1
Loop through each item in the input array.
If there's an item to the left and it's smaller than this item, then set the corresponding coins item to be one more than the coins item to it's left
If there's an item to the right and it's smaller than this item, and if the corresponding coins item is equal to the coins item to its right, then increment this item by 1
If we incremented this item after comparing to the right, then we need to re-check the item to the left and increment it if necessary (based on the corresponding values in the items array).
If that didn't make complete sense, try it on paper and it may be more obvious. Otherwise, hopefully this code sample will help:
public static int[] GetCoins(int[] input)
{
int[] coins = new int[input.Length];
// Initialize coins array with all '1's (similar to 'GiveEachStudentCoins')
for (int i = 0; i < coins.Length; i++)
{
coins[i] = 1;
}
// Examine the neighbors of each item in the array
for (int i = 0; i < input.Length; i++)
{
// Check left neighbor (if there is one)
if (i > 0 && (input[i] > input[i - 1]))
{
if (coins[i] <= coins[i - 1])
{
coins[i] = coins[i - 1] + 1;
}
}
// Check right neighbor (if there is one)
if (i < input.Length - 1 && input[i] > input[i + 1])
{
if (coins[i] == coins[i + 1])
{
coins[i]++;
// Recheck left since we incremented this one
if (i > 0 && input[i - 1] > input[i])
{
coins[i - 1]++;
}
}
}
}
return coins;
}
Here's some sample code that can be used for testing, so you don't have to manually enter numbers into the console each time (this requires adding using System.Linq to the top of the file):
public static void Main(string[] args)
{
// Populate the grades you want to test here
int[] studentsGrades = {9, 10, 8, 6, 9, 10};
// Student names are automatically generated
string[] studentsList = Enumerable.Range(1, studentsGrades.Length)
.Select(i => $"Student #{i} grade: {studentsGrades[i - 1]}\tcoins: ")
.ToArray();
// Call the new method to get the coins array
int[] coins = GetCoins(studentsGrades);
// Show the results
PrintResult(studentsList, coins);
Console.WriteLine("Done! Press any key to exit...");
Console.ReadKey();
}

HeapSort Algorythm from txt file to list of arrays doesn't Sort the numbers

So I have to make HeapSort Algorythm for University using pseudocode I was given (only for heapsort). And I have to use input and output file. But for now I have only made input file which is working fine since it loads the txt file and writes down all the numbers in Console. So the problem is that after adding sorting methods to Main nothing changes. Also I decided to make a test for every method and all of them writes down my numbers once and that is it. I am not really good with sorting so it is hard for me to find the issue. Also because it is from pseudocode I had to use and no the code I could do for myself. So Do You know what cause thats issue that the sorting doesn't occure?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;
using System.IO;
using System.Windows.Forms;
namespace Zad4
{
class Program
{
void Heapify(List<int> array, int i, int n)
{
int largest, temp;
int parent = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && array[left] > array[parent])
{
largest = left;
}
else
{
largest = parent;
}
if (right < n && array[right] > array[largest])
{
largest = right;
}
if (largest != i)
{
temp = array[i];
array[i] = array[largest];
array[largest] = temp;
Heapify(array, largest, n);
}
}
void BuildHeap(List<int> array, int n)
{
int i;
for (i = (n - 1) / 2; i >= 0; i--)
{
Heapify(array, i, n);
}
}
void HeapSort(List<int> array, int n)
{
int i, temp;
for (i = n - 1; i >= 0; i--)
{
temp = array[0];
array[0] = array[n - 1];
array[n - 1] = temp;
n = n - 1;
Heapify(array, 0, n);
Console.WriteLine(string.Join(" ", array));
}
}
static void Main(string[] args)
{
int n = 0;
Program A = new Program();
StreamReader myFile =
new StreamReader("C:\\Users\\dawid\\Desktop\\C#\\Heapsort\\dane.txt");
string myString = myFile.ReadToEnd();
myFile.Close();
char rc = (char)10;
String[] listLines = myString.Split(rc);
List<List<int>> listArrays = new List<List<int>>();
for (int i = 0; i < listLines.Length; i++)
{
List<int> array = new List<int>();
String[] listInts = listLines[i].Split(' ');
for (int j = 0; j < listInts.Length; j++)
{
if (listInts[j] != "\r")
{
array.Add(Convert.ToInt32(listInts[j]));
}
}
listArrays.Add(array);
A.BuildHeap(array, n);
A.HeapSort(array, n);
}
foreach (List<int> array in listArrays)
{
foreach (int i in array)
{
Console.WriteLine(string.Join(" ", array));
}
}
Console.WriteLine();
Console.ReadLine();
}
}
}
So the solution I found is just changing the way I read my txt file and the most important one was bad use of my methods. So that is how it looks now and it sorting well. Maybe I shouldn't ask a question since I got an answer on my own. But well. There You go:
static void Main(string[] args)
{
Program A = new Program();
string[] array = System.IO.File.ReadAllLines(#"C:\Users\dawid\Desktop\C#\Heapsort\dane.txt");
int[] arrayInt = Array.ConvertAll(array, int.Parse);
A.BuildHeap(arrayInt, arrayInt.Length);
A.HeapSort(arrayInt, arrayInt.Length);
Console.WriteLine(string.Join(" ", arrayInt));
Console.ReadLine();
}

How can define a 26x2 array and then use LINQ on its rows?

Grrrr I have C# and multidimensional arrays. For some reason, coming from a C/C++ background, they really annoy me.
So when I run
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution
{
static void Main(String[] args)
{
int T = Int32.Parse(Console.ReadLine());
for(int t = 0; t < T; ++t)
{
string str = Console.ReadLine();
if(str.Length % 2 == 1)
{
Console.WriteLine(-1);
continue;
}
int n = str.Length / 2;
// determine how many replacements s1 needs to be an anagram of s2
string s1 = str.Substring(0, n);
string s2 = str.Substring(n, n);
int[][] counter = new int[26][2];
int ascii_a = (int)'a';
for(int i = 0; i < n; ++i)
{
counter[(int)s1[i] - ascii_a][0] += 1;
counter[(int)s2[i] - ascii_a][1] += 1;
}
int count = counter.Select((pair => Math.Abs(pair[0] - pair[1]))).Sum();
Console.WriteLine(count);
}
}
}
I get
solution.cs(22,42): error CS0029: Cannot implicitly convert type int'
toint[][]' Compilation failed: 1 error(s), 0 warnings
No idea why.
I can change it to
int[,] counter = new int[26,2];
int ascii_a = (int)'a';
for(int i = 0; i < n; ++i)
{
counter[(int)s1[i] - ascii_a, 0] += 1;
counter[(int)s2[i] - ascii_a, 1] += 1;
}
int count = counter.Select((pair => Math.Abs(pair[0] - pair[1]))).Sum();
but then, of course, my LINQ statement breaks.
If you change
int[][] counter = new int[26][2];
to
int[][] counter = new int[26][];
for (int i = 0; i < counter.Length; i++)
counter[i] = new int[2];
code compiles. You can test the rest as you like. As you haven't provided necessary input in OP.
You can't define jagged array like that:
int[][] counter = new int[26][2];
I recommend reading on jagged arrays:
https://msdn.microsoft.com/en-us/library/2s05feca.aspx
https://msdn.microsoft.com/en-us/library/2yd9wwz4.aspx
In your case I'd suggest using not jagged, but multi-dimentional array:
var counter = new int[26,2];
What you are using here is a jagged array, and you can't new one like that:
int[][] counter = new int[26][2];
You have to declare the inner array separately :
int[][] counter = new int[26][];
for (int i = 0; i < 26; i++)
{
counter[i] = new int[2];
}
Alternatively, as #IvanStoev suggested, you can also use a LINQ one liner:
var counter = Enumerable.Range(0, 26).Select(_ => new int[2]).ToArray();
You can also use a 2-dimensional array, such as this one :
// notice there is only one bracket
int[,] counter = new int[26,2];
int ascii_a = (int)'a';
for(int i = 0; i < n; ++i)
{
counter[(int)s1[i] - ascii_a, 0] += 1;
counter[(int)s2[i] - ascii_a, 1] += 1;
}
// and, you will need to update your query,
// as linq would implicitly flatten the array
var count = Enumerable.Range(0, 26)
.Select(x => counter[x, 0] - counter[x, 1])
.Sum();
I would suggest defining a Counter struct then use an array of those instead of a multi-dimensional array.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution
{
struct Counter
{
public int c1;
public int c2;
}
static void Main(String[] args)
{
int T = Int32.Parse(Console.ReadLine());
for (int t = 0; t < T; ++t)
{
string str = Console.ReadLine();
if (str.Length % 2 == 1)
{
Console.WriteLine(-1);
continue;
}
int n = str.Length / 2;
// determine how many replacements s1 needs to be an anagram of s2
string s1 = str.Substring(0, n);
string s2 = str.Substring(n, n);
Counter[] counter = new Counter[26];
int ascii_a = (int)'a';
for (int i = 0; i < n; ++i)
{
counter[(int)s1[i] - ascii_a].c1 += 1;
counter[(int)s2[i] - ascii_a].c2 += 1;
}
int count = counter.Select((pair => Math.Abs(pair.c1 - pair.c2))).Sum();
Console.WriteLine(count);
}
}
}

C# 2D Array calling it another class through obj.method();

Write a Java class that has a static method named count that accepts a 2D-Array of integers and a target integer value as parameters and returns the number of occurrences of the target value in the array. For example, if a variable named list refers to an array containing values {{3,5,7,94}{5,6,3,50}} then the call of count(list, 3) should return 2 because there are 2 occurrences of the value 3 in the array.
Here is my coding and it's not giving me proper output
P.S :-I have been told to take count method as public not static
class java
{
public int count(int [,] list,int n)
{
int c = 0;
for (int i = 0; i <list.Length; i++)
{
for (int j = 0; j < list.Length; j++)
{
if (list[i, j] == n)
{
c++;
}
}
}
return c;
}
class Program
{
static void Main(string[] args)
{
java jv = new java();
int[,] arr = { { 3, 5, 7, 94 }, {5, 6, 3, 50 } };
int k=0;
jv.count(arr,k);
}
}
Iterating Multi-Dimensional arrays requires you to iterate each dimension with it's own Length, which means i and j should be 0-3 and 0-1 respectively.
as can be seen in the picture but for a different dimensioned array:
GetLength(0) would return 4.
GetLength(1) would return 3.
What you are doing is iterating them when i = (0 to Length) over j = (0 to Length) when Length = Height * Width = 8 in your case which means 8 over 8.
So your count() method should look like that:
public int count(int[,] list,int n)
{
int c = 0;
for (int i = 0; i < list.GetLength(0); i++)
{
for (int j = 0; j < list.GetLength(1); j++)
{
if (list[i, j] == n)
{
c++;
}
}
}
return c;
}
if you would like to iterate the array as an array of arrays instead of getting things complicated with "Which dimension am I iterating now?" you can use Jagged Arrays (Of course there are more things to consider about it), this will allow you to replace the whole method with this one short Linq:
public int count(int[][] list,int n)
{
return list.SelectMany(x => x).Count(x => x == n);
}
or:
public int count(int[][] list, int n)
{
return list.Sum(x => x.Count(y => y == n));
}
Note the i against j in inner for.
And do use i <list.GetLength(0) and j < list.GetLength(1) against list.Length
class java
{
public int count(int [,] list,int n)
{
int c = 0;
for (int i = 0; i < list.GetLength(0); i++)
{
for (int j = 0; j < list.GetLength(1); j++)
{
if (list[i, j] == n)
{
c++;
}
}
}
return c;
}
class Program
{
static void Main(string[] args)
{
java jv = new java();
int[,] arr = { {3,5,7,94 }, {5,6,3,50 } };
int k=5;
Console.WriteLine(jv.count(arr,k));
}
}
Since Array has implemented IEnumerable you can simply use foreach loop here (feel free to change static to instance method) :
public static int count(int[,] list, int n)
{
int c = 0;
foreach (var item in list) if (item == n) c++;
return c;
}
Usage:
static void Main()
{
var r = count(new int[,]{
{
5, 8, 7, 8
},
{
0, 8, 9, 3
}}, 8);
Console.WriteLine(r);
output : 3
P.S.
Generally if possible, it is best to use a for loop as it is faster than foreach but in these case i like that if you use foreach you don't have nested for loops nor GetLength(x) calls it's just one line of code and it has almost same performance...
Your error is in this line:
for (int j = 0; i < list.Length; j++)
It should be
for (int j = 0; j < list.Length; j++)

Most efficient way to find the smallest index where its value minus the value of a previous index is smaller than a given x?

I have five long integers p, q, s, m and x. An array numbers[] is created by the following formula.
numbers[0] = s;
for(int i=1; i<numbers.Length;i++){
numbers[i] = (p * numbers[i-1] + q) % m;
}
The first value of numbers (numbers[0]) is s.
What is the most efficient way to find index j where i < j and |numbers[j] - numbers[i]| <= x or |numbers[j] - numbers[i]| >= m-x.
For instance, in a case where p = 3, q= 7, s= 1, m= 29 en x= 1 the array will be:
numbers[0] = 1, numbers[1] = 10, numbers[2] = 8 and numbers[3] = 2.
In this case index j would be 3, because numbers[3] - numbers[0]<=x, because x is 1.
I thought about using something such as a variant of counting sort or radix sort but I can't get anything to work.
As i < j, then you need to grant that numbers has a length of at least 2.
You could do two nested loops, the outer one ranging from j = 1 to numbers.Length - 1 (granting the possible solution to be the smallest j) to i = 0 to i < j.
Then you compare both positions according your specs. If true, return j. If it finishes both loops, then there is no solution.
Edit: Code Sample
public int GetSmallestIndex(long[] numbers, long x, long m)
{
if (numbers.Length >= 2)
{
for (int j = 1; j < numbers.Length; j++)
{
for (int i = 0; i < j; i++)
{
long diff = Math.Abs(numbers[j] - numbers[i]);
if (diff <= x || diff >= m - x)
return j;
}
}
}
return -1; //If no solution is found, return -1 as convention
}
The only way to find out if something is more efficient is to benchmark it by using the StopWatch in System.Diagnostics.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
var stopWatch = new Stopwatch();
stopWatch.Start();
const long x = 1;
var numbers = new long[] {3, 7, 1, 29};
var theSmallestIndex = SmallestIndex(x, numbers);
stopWatch.Stop();
Console.WriteLine("Elapsed Time: {0}", stopWatch.Elapsed);
Console.WriteLine("Smallest Index: {0}", theSmallestIndex);
Console.ReadKey();
}
public static long SmallestIndex(long x, long[] numbers)
{
var values = ValuesMinusTheValueOfPreviousIndex(x, numbers.ToList());
var smallest = values.Values.OrderBy(n => n).FirstOrDefault();
var result = values.Where(n => n.Value.Equals(smallest));
return result.FirstOrDefault().Key;
}
public static Dictionary<int, long> ValuesMinusTheValueOfPreviousIndex(long x, List<long> numbers)
{
var results = new Dictionary<int, long>();
foreach (var number in numbers)
{
var index = numbers.IndexOf(number);
var previousNumber = index > 0 ? numbers.ElementAt(index - 1) : 0;
var result = number - previousNumber;
results.Add(index, result);
}
return results;
}
}
}
EDIT: Added Math.Abs as you requested in the comments
long p = 3, q = 7, s = 1, m = 29, x = 1;
long[] numbers = new long[10];
numbers[0] = s;
for (int i = 1; i < numbers.Length; i++)
{
numbers[i] = (p * numbers[i - 1] + q) % m;
}
// Find the smallest index j in numbers, where i < j &&
// (numbers[j] - numbers[i] <= x || numbers[j] - numbers[i] >= m-x)
int smallestIndex = 0;
long comparison;
for (int j = 1; j < numbers.Length; j++)
{
for (int i = 0; i < j; i++)
{
comparison = Math.Abs(numbers[j] - numbers[i]);
if (comparison <= x || comparison >= m - x)
{
smallestIndex = j;
break;
}
}
if (smallestIndex != 0) break;
}
if (smallestIndex == 0)
{
// No result matches the conditions
}
else
{
// j is the smallest index matching the conditions
// Before using Abs, in the example j is 2, because 8 - 10 = -2, lesser than x
// Now using absolute values, In the example j is 3
}

Categories

Resources