C# Recursive Permutation is Possible? (beginner) - c#

Hi guys im trying to learn permutation and recurtion. And im looking for a way how can i use bought at the same time.
MAIN:
namespace Recursive_Permutation
{
class Program
{
static void Main(string[] args)
{
int[] array = new int[5] { 0, 0, 0, 0, 0 };
CalPermutations CP = new CalPermutations();
CP.Run(array, array.Length-1);
}
}
}
Here is my Simple code:
namespace Recursive_Permutation
{
public class CalPermutations
{
public int Run(int[] array,int indexer)
{
if (indexer > array.Length)
{
return 1;
}
else
{
for (int i = 0; i <= array.Length; i++)
{
array[indexer] = i;
Display(array);
}
Run(array, indexer-1);
}
return indexer;
}
public void Display(int[] array)
{
foreach (int num in array)
{
Console.Write(num);
}
Console.WriteLine();
}
}
}
And here is the Output of the program:
Question:
it might be simple to other but im kind of confuse now in how can i manipulate it that it still count the first digit (position [0]) 1 to 5 and go next position and (position 1) and add 1 and go back to [0] and start count again till it reaches 5.
i hope that my explanation is understandable.. thx.

I put together this simpler example of using recursion and permutation. It uses strings internally, but produces the same result.
Its for proof of concept only, since nobody will us recursion for this simple stuff in a professional environment. Recursion can have a big memory impact, but makes describing some problems in a simple way possible.
If I had to choose between iterative and recursive solutions, I would take the iterative one most of the time.
// Main entrance
public void DoStuff()
{
// define variations
List<string> possibilities = new List<string>() { "0", "1", "2", "3", "4", "5" };
// resultlist, will be filled later
List<string> permutations = new List<string>();
// how many values will be taken from the possibilities
int digits = 5;
//do the work
Permute(permutations, possibilities, digits, "");
// display the work
foreach (var item in permutations)
{
Console.WriteLine(item);
}
}
/// <summary>
/// generates a List of permuted strings
/// </summary>
/// <param name="permutations">resultlist</param>
/// <param name="possibilities">possible values of the digit</param>
/// <param name="digitsLeft">how many digits shall be appended</param>
/// <param name="current">the current value of the unfinished result</param>
private void Permute(List<string> permutations, List<string> possibilities, int digitsLeft, string current)
{
// uncomment to see how it works in detail
//Console.WriteLine("step:"+current);
// most important: define Stop conditions for the recursion
// safety stop
if (digitsLeft < 0)
{// end of digits :), normally we never end up here
return;
}
// normal stop
if (digitsLeft == 0)
{// normal endpoint, add the found permutation to the resultlist
permutations.Add(current);
return;
}
// now prepare the recursion, try each possibility
foreach (var item in possibilities)
{
// digitsLeft need to be decreased, since we add a concrete digit to the current value (current+item)
// important: (current + item) generates a new string in memory, the old values won't be touched, permutations possibilities are references, so no memory impact here
Permute(permutations, possibilities, digitsLeft - 1, current + item);
}
}

Update: added comments on each method as per comment.
public class Program
{
public static void Main(string[] args)
{
int[] array = new int[] { 0, 0, 0, 0, 0};
CalPermutations CP = new CalPermutations();
CP.Run(array, 0);
}
}
public class CalPermutations
{
// Prints all the permutations of array, starting at the specified index.
public void Run(int[] array, int indexer)
{
if (indexer < 0 || indexer >= array.Length)
return;
// Keep [0, indexer] combination constant, change combination on right i.e. (indexer, Array.length).
Run(array, indexer+1);
// All the elements on right have finished, increment current element.
array[indexer]++;
// Check if current combination is STILL valid.
if(array[indexer] <= array.Length)
{
// since current combination is still valid, display it, and execute the process again on the new combination.
Display(array);
Run(array, indexer);
}
else
{
// Since current element is out of range, reset it.
array[indexer] = 1;
}
}
// Prints all the elements in array.
public void Display(int[] array)
{
foreach (int num in array)
Console.Write(num);
Console.WriteLine();
}
}

Related

Test method in Console c#

I want to test a binary search in console app. I've populalated my array. I have no errors. Code runs... I'm not sure what lines of code I need to test this.
Here is my code..
internal class Program
{
static void Main(string[] args)
{
//Initialise array
int[] arr = { 800, 11, 50, 771, 649, 770, 240, 9 };
int key = 0;
Program.BinarySearchDisplay(arr, key);
}
//Binary Search Method
public static object BinarySearchDisplay(int[] arr, int key)
{
int minNum = 0;
int maxNum = arr.Length - 1;
while (minNum <= maxNum)
{
int mid = (minNum + maxNum) / 2;
if (key == arr[mid])
{
return ++mid;
}
else if (key < arr[mid])
{
maxNum = mid - 1;
}
else
{
minNum = mid + 1;
}
}
return "None";
}
}
}
A couple of things of note here. Although technically correct, it is not a good idea to return values of different types from a function. C# being statically typed provides the opportunity to expect certain return types that are used to check the code doesn't contain errors at compile type.
A function needs to return a value, and so you need to assign this value to a variable. This is an example of how to do this for a function called Fun()
int x = Fun(a,b,c);
Here is one way to achieve what you are trying to do. Have a function that returns a value if successful or flag when it does not succeed. Return a bool type indicating success, and include an out parameter that gets assigned a value before the function exits.
Notice that you store the results of the function in a variable found of type bool and then act accordingly using an if(found) statement
class Program
{
static void Main(string[] args)
{
//Initialise array
int[] arr = { 800, 11, 50, 771, 649, 770, 240, 9 };
int key = 50;
Console.WriteLine($"Array: {string.Join(",", arr)}");
Console.WriteLine($"Key: {key}");
// call the function an store the results in a variable
bool found = BinarySearchDisplay(arr, key, out int index);
if (found)
{
Console.WriteLine($"Found arr[{index}] = {arr[index]}");
}
else
{
Console.WriteLine("Not Found.");
}
}
/// <summary>
/// Binary Search Method.
/// </summary>
/// <param name="arr">The array of values.</param>
/// <param name="key">The key to search for.</param>
/// <param name="index">The array index if key was found, -1 otherwise.</param>
/// <returns>true if key found, false otherwise.</returns>
public static bool BinarySearchDisplay(int[] arr, int key, out int index)
{
int minIndex = 0;
int maxIndex = arr.Length - 1;
index = -1;
while (minIndex <= maxIndex)
{
index = (minIndex + maxIndex) / 2;
if (key == arr[index])
{
return true;
}
else if (key < arr[index])
{
maxIndex = index - 1;
}
else
{
minIndex = index + 1;
}
}
return false;
}
}
Note that Program.BinarySearchDisplay() is replaced by just BinarySearchDisplay(). This is because the function is within the same class Program and there is no need to fully qualify its name.
The result of the above code is
Array: 800,11,50,771,649,770,240,9
Key: 50
Found arr[2] = 50
I think there was an error in the op code in return ++mid; as the next index value is returned. Maybe this was done because indexing is 0-based, and the op wanted a 1-based result. But mixing the two styles is dangerous and will lead to bugs.
This is a similar pattern to bool int.TryParse(string, out int) to convert a string to a number if possible, or return false otherwise.
if(int.TryParse("1150", out int x))
{
// x holds the value 1150
}

How to optimize a loops going through arrays?

I've been going though www.testdome.com to test my skills and opened a list of public questions. One of the practice questions was:
Implement function CountNumbers that accepts a sorted array of
integers and counts the number of array elements that are less than
the parameter lessThan.
For example, SortedSearch.CountNumbers(new int[] { 1, 3, 5, 7 }, 4)
should return 2 because there are two array elements less than 4.
And my answer was:
using System;
public class SortedSearch
{
public static int CountNumbers(int[] sortedArray, int lessThan)
{
int count = 0;
int l = sortedArray.Length;
for (int i = 0; i < l; i++) {
if (sortedArray [i] < lessThan)
count++;
}
return count;
}
public static void Main(string[] args)
{
Console.WriteLine(SortedSearch.CountNumbers(new int[] { 1, 3, 5, 7 }, 4));
}
}
It seems that I've failed on two counts:
Performance test when sortedArray contains lessThan: Time limit exceeded
and
Performance test when sortedArray doesn't contain lessThan: Time limit exceeded
To be honest I'm not sure what to optimize there? Maybe I'm using a wrong method and there is a similar way to speed up the calculation?
If someone could point out my mistake or explain what I'm going wrong, I'd really appreciate it!
Because the array is sorted, you can stop counting as soon as you reach or exceed the lessThan parameter.
else break would probably do it.
Does it have to be really a loop? You could do Lambda exp for that
public static int CountNumbers(int[] sortedArray, int lessThan)
{
return sortedArray.ToList().Where(x=>x < lessThan).Count();
}
Harold's answer and approach is spot on.
Find below another code sample in case you're practicing for technical interviews. It handles cases when the array is null or empty, when lessThan is presented in the array (including duplicates), etc.
private static int CountNumbers(int[] sortedArray, int lessThan)
{
if (sortedArray == null)
{
throw new ArgumentNullException("Sorted array cannot be null.");
}
if (sortedArray.Length == 0)
{
throw new ArgumentException("Sorted array cannot be empty.");
}
int start = 0;
int end = sortedArray.Length;
int middle = int.MinValue;
while (start < end)
{
middle = (start + end) / 2;
if (sortedArray[middle] == lessThan)
{
break; // Found the "lessThan" number in the array, we can stop and move left
}
else if (sortedArray[middle] < lessThan)
{
start = middle + 1;
}
else
{
end = middle - 1;
}
}
// Adjust the middle pointer based on the "current" and "lessThan" numbers in the sorted array
while (middle >= 0 && sortedArray[middle] >= lessThan)
{
middle--;
}
// +1 because middle is calculated through 0-based (e.g. start)
return middle + 1;
}

Permutation recursion C#

I have this function that call itself to find all the possible combination with the array of int. The problem is that the program calculate the first combination and then, when the recursion continues, the List of combination still contains that value and i don't understand why.
public static void Permutation(List<int> items, int h, List<int> actualCombination)
{
if (h == actualCombination.Count)
{
results[results.Count] = actualCombination;
}
else
{
for (int i = 0; i < items.Count; i++)
{
actualCombination.Add(items[i]);
List<int> temp = new List<int>(items);
temp.Remove(items[i]);
Permutation(temp, h, actualCombination);
}
return;
}
}
after that, i call the function in main. In my case the second parameter specify the combination length."Results" is a Dictionary composed by int as key and List as value that is used to save all the combination.
static void Main(string[] args)
{
Permutation(new List<int> { 1, 2, 3 }, 3, new List<int>());
Console.ReadKey();
}
I solved the problem by copying the List before of the function add.

Writing a removeLast method

Situation:
I'm new to c# and currently learning the ropes whilst also polishing up on my data structures, I decided to make a class that'd perform multiple functions to a linear array, since It was suggested to me that I should start with linear arrays then work on a circular one.
The methods my class currently provides are:
adding an item to the front-most position of the array,
adding an item to the back-most position of the array,
removing the first item in the array,
removing the last item in the array, //todo
clearing the current array list of it's values,
displaying the array list contents to the user.
Problem:
I'm having difficulty constructing a method that removes the last item of the array, I've looked online and the pre-writen methods seem complex and I can't get my head around them due to my in-experience. I realize it must be easy for others to write a method like this, but I'm truly stumped.
I'd like to learn how to write a method that removes the last value in the array, in the most simpliest to understand way. Here is my current code for my LinearArrayList class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace arraydatastructuresactual
{
public class LinearArrayList
{
private int count; //how many numbers currently stored
private int[] values; //array to hold values entered into list
//constructors
/// <summary>
/// //creates a linear array that can hold max values
/// </summary>
/// <param name="max"></param>
public LinearArrayList(int max)
{
count = 0;
values = new int[max]; //makes the linear array as big as the max value
}
/// <summary>
/// //default constructor sets capacity to 10
/// </summary>
public LinearArrayList()
{
count = 0;
values = new int[10];
}
/// <summary>
/// returns true if list is empty
/// otherwise turns false
/// </summary>
/// <returns>true if empty otherwise false</returns>
public bool isEmpty()
{
return (count == 0);
}
/// <summary>
/// returns true if list is full
/// otherwise turns false
/// </summary>
/// <returns>true if full otherwise false</returns>
public bool isFull()
{
return (values.Length <= count);
}
/// <summary>
/// if not full adds value to the end of list
/// throws exception if list is fulll
/// </summary>
/// <param name="value">value to add to end of list</param>
public void addLast(int value) //adds an item to the last position in the array.
{
if (isFull())
{
throw new Exception("List Full");
}
else
{
values[count++] = value;
}
}
public void addFirst(int value) //Adds an item to the first position in the array.
{
if (isFull())
{
throw new Exception("List Full");
}
else
{
for (int i = count; i > 0; i--)
{
values[i] = values[i--];
}
values[0] = value;
count++;
}
}
public int removeFirst() //removes the first item from the array
{
if (isEmpty())
throw new Exception("List is Empty");
int value = values[0];
count--;
for (int i = 0; i < count; i++)
{
values[i] = values[i + 1];
}
return value;
}
public int removeLast() //todo //removes the last item from the array
{
if (isEmpty())
throw new Exception("List is Empty");
int value = values[0];
count--;
for (int i = count; i < count; i++)
{
values[i] = values[i + 1];
}
return value;
}
public void displayUI()//displays contents of list
{
}
public void destroy() //Empties The List
{
}
}
}
If someone could share their experience on how I'd go about achieving this, then many thanks, I tried to repurpose my removeFirst method but I messed up, tried to do this a few times and I'm completely stumped now.
You just need to write
public int removeLast()
{
if (isEmpty())
throw new Exception("List is Empty");
count--;
return values[count];
}
this will return the last item in the values array WITHOUT changing its size but decrementing the variable that keeps track of the item actually inserted in the array.
Notice that I don't try to change the value in the location pointed by the count variable. It is still there until you overwrite it adding another value
So you could still write this
// Creates an array with space for 10 ints
LinearArrayList la = new LinearArrayList();
la.addLast(34);
la.addLast(23);
la.addLast(56);
la.addLast(467);
la.addLast(43);
la.addLast(666);
la.addLast(7989);
la.addLast(82);
la.addLast(569);
la.addLast(100);
int value = la.removeLast();
// This will work because you still have a slot free in the 10 ints array
la.addLast(1110);
// While this will fail because the array has now all slots filled
la.addLast(9435);
An alternative to Sybren's answer:
int lastValue = values[values.Length - 1];
int[] newValues = new int[values.Length - 1];
Array.Copy(values, newValues, newValues.Length);
values = newValues;
return lastValue;
or
int lastValue = values[values.Length - 1];
Array.Resize(values, values.Length - 1);
return lastValue;
If you don't want to use any existing methods of Array class, you can also:
int lastValue = values[values.Length - 1];
int[] newValues = new int[values.Length - 1];
for (int i = 0; i < newValues.Length; i++)
{
newValues[i] = values[i];
}
values = newValues;
return lastValue;
Edit
Forget this, do what #Steve said.
Here's a way to do it. You're converting your array to a list, getting the last element from the list, removing the last element from the list, and convert it back to an array.
var numbersList = values.ToList();
var last = numbersList.Last();
numbersList.Remove(last);
values = numbersList.ToArray();
return last;

Roulette Wheel weakness in random number selection

I'm working on a roulette wheel class, it should function more or less like a regular roulette wheel where certain numbers can take up a larger portion of the roulette wheel and thus have a higher probability of being chosen.
So far it has passed the more basic unit tests, that is, programatically it works, I can create a roulette wheel and fill it with a bunch of generic values and it will do just that.
However when it comes to my probability testing, I decided to try it out as a 6-sided die, after 10,000,000 trials it should generate an average die roll of about 3,5 unfortunately it doesn't even come close to that the average after 10,000,000 trials is about 2,9 so I am guessing there is a weakness in my number selection somewhere? I have posted unit tests and actual code below:
public class RouletteNumber<T>
{
public readonly T Number;
public readonly int Size;
public RouletteNumber(T number, int size)
{
this.Number = number;
this.Size = size;
}
public static RouletteNumber<T>[] CreateRange(Tuple<T, int>[] entries)
{
var rouletteNumbers = new RouletteNumber<T>[entries.Length];
for (int i = 0; i < entries.Length; i++)
{
rouletteNumbers[i] = new RouletteNumber<T>(entries[i].Item1, entries[i].Item2);
}
return rouletteNumbers;
}
}
public class RouletteWheel<T>
{
private int size;
private RouletteNumber<T>[] numbers;
private Random rng;
public RouletteWheel(params RouletteNumber<T>[] rouletteNumbers)
{
size = rouletteNumbers.Length;
numbers = rouletteNumbers;
rng = new Random();
//Check if the roulette number sizes match the size of the wheel
if (numbers.Sum(n => n.Size) != size)
{
throw new Exception("The roulette number sections are larger or smaller than the size of the wheel!");
}
}
public T Spin()
{
// Keep spinning until we've returned a number
while (true)
{
foreach (var entry in numbers)
{
if (entry.Size > rng.Next(size))
{
return entry.Number;
}
}
}
}
}
[TestMethod]
public void DiceRouletteWheelTest()
{
double expected = 3.50;
var entries = new Tuple<int, int>[]
{
Tuple.Create(1, 1),
Tuple.Create(2, 1),
Tuple.Create(3, 1),
Tuple.Create(4, 1),
Tuple.Create(5, 1),
Tuple.Create(6, 1)
};
var rouletteWheel = new RouletteWheel<int>(RouletteNumber<int>.CreateRange(entries));
var results = new List<int>();
for (int i = 0; i < 10000000; i++)
{
results.Add(rouletteWheel.Spin());
}
double actual = results.Average();
Assert.AreEqual(expected, actual);
}
}
When you call Random.Next(n) it generates a random number between 0 and n-1, not between 0 and n.
Did you account for that?
In fact for a 6-sided die, you would want to call Random.Next(1, 7)
Maybe i'm not understanding it correctly but I'm guessing the problem lies here :
while (true)
{
foreach (var entry in numbers)
{
if (entry.Size > rng.Next(size))
{
return entry.Number;
}
}
}
You're calculating the rng.Next each time you do the if check.
So the first number has a 1 in 6 chance of being taken. Number 2(the next entry in numbers) then has a 2 in 6 chance of being taken(a new number is rendered between 1 and 6). But since you always start from the first you will eventually have more lower numbers.
I also don't see the need for the while(true) in a normal random generator.
I'm guessing this could would work and look like your current code :
var rndValue = rng.Next(size);
foreach (var entry in numbers)
{
if (entry.Size > rndValue)
{
return entry.Number;
}
}

Categories

Resources