Extract all sequential subsets from a given set [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
I need to get sequential subsets (self-made terminology) for a given set. For instance, if my set is {1,5,8,25}, the output should be:
{1}
{5}
{8}
{25}
{1,5}
{5,8}
{8,25}
{1,5,8}
{5,8,25}
{1,5,8,25}
I tried implementing the same in C# lists using iterative approach but found the time complexity to be high. Can anyone help me with this?
As per comments, here is my approach which is similar to the posted answer:
public static void Main(string[] args)
{
List<int> input = new List<int>() { 0, 1, 2, 3 };
var output = GetSubset(input);
foreach (var element in output)
{
Console.Write("{ ");
foreach (int e in element)
{
Console.Write(e + " ");
}
Console.Write("}");
Console.WriteLine();
}
Console.ReadKey();
}
private static List<List<int>> GetSubset(List<int> arr)
{
List<List<int>> sets = new List<List<int>>();
var length = arr.Count;
// No of element on each set
for (int k = 1; k <= length; k++)
{
for (int i = 0; i <= length - k; i++)
{
List<int> set = new List<int>();
for (int j = i; j < (i + k); j++)
{
set.Add(arr[j]);
}
sets.Add(set);
}
}
return sets;
}
As correctly pointed out, the time complexity is O(n^3). Is there a better approach towards same.

This should sort you out if it's fast enough:
IEnumerable<int[]> GetSequentialSubsets(int[] data)
{
Array.Sort(data);
//The number of elements to add to each returned array
for (int m = 1; m <= arr.Length; m++)
{
//The starting index in int[] data of the current array
for (int i = 0; i <= arr.Length - m; i++)
{
var element = new int[m];
//Adding data to the current array
for (int j = i; j < i + m; j++)
{
element[j - i] = arr[j];
}
yield return element;
}
}
}
Note that I sort the array, just in case you throw in something unsorted. But if you don't care about incrementing elements and just want the elements to be sequential, you should leave that part out. I didn't find that part of your question entirely clear. You can test it like this:
var arr = new[] { 1, 5, 8, 25 };
var res = GetSequentialSubsets(arr);
foreach (var element in res)
{
foreach (int e in element)
{
Console.Write(e + " ");
}
Console.WriteLine();
}
The complexity must be the number of indices we iterate over which is equal to
n * (n + 1) * (n + 2) / 6
so O(n³).
N.B. The number of indices is the sum of i * (n + 1 - i) from i = 1 to i = n. WolframAlpha then gives the result above.

Related

Cannot convert to icomparer array.sort C# [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 months ago.
Improve this question
It gives a 1503 error, but I can’t fix it. It gives an error from Array.Sort(
valuePerWeight, weights, values); in the values variable. How can I fix it? I tried to write values in front of weights but it doesn’t work
class Program
{
static void Main(string[] args)
{
int[] data = ReadDataFromFile("items.txt");
int capacity = data[0];
int[] weights = new int[data.Length - 1];
int[] values = new int[data.Length - 1];
for (int i = 1; i < data.Length; i++)
{
weights[i - 1] = data[i];
values[i - 1] = data[++i];
}
int[] selectedItems = GreedyKnapsack(capacity, weights, values);
int totalValue = 0;
Console.WriteLine("Selected items:");
for (int i = 0; i < selectedItems.Length; i++)
{
if (selectedItems[i] == 1)
{
Console.WriteLine($"Weight: {weights[i]}, Value: {values[i]}");
totalValue += values[i];
}
}
Console.WriteLine($"Total value: {totalValue}");
}
it gives an error in array.sort
static int[] GreedyKnapsack(int capacity, int[] weights, int[] values)
{
int n = weights.Length;
int[] selected = new int[n];
double[] valuePerWeight = new double[n];
for (int i = 0; i < n; i++)
{
valuePerWeight[i] = (double)values[i] / weights[i];
}
Array.Sort(
valuePerWeight, weights, values);
int weight = 0;
for (int i = n - 1; i >= 0; i--)
{
if (weight + weights[i] <= capacity)
{
selected[i] = 1;
weight += weights[i];
}
}
return selected;
}
}
}
You are getting CS1503 because you are passing an array of int Values when you should be passing an IComparer<int>.
From you question, it´s not clear what's the objective of your method.
If you want to sort valuePerWeight, weights and values, you can just sort them seperately:
Array.Sort(valuePerWeight)
Array.Sort(weights)
Array.Sort(values)

I would like to know the different solutions, I am attaching my solution thanks [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
They believe that this solution is fine, I have not been programming for a long time, I have been about 1 month, my question is what other ways I opened to solve the following problem, I attach my solution.
Sample Input 1 2 3 4 5
Sample Output 10 14
The numbers are 1,2,3,4, and 5.
Calculate the following sums using four of the five integers: Sum everything except 1,the sum is 2+3+4+5=14. Sum everything except 2,the sum is 1+3+4+5=13. Sum everything except 3,the sum is 1+2+4+5=12. Sum everything except 4,the sum is 1+2+3+5=11. Sum everything except 5,the sum is 1+2+3+4=10.
Code:
static void Main(string[] args)
{
int[] arr = new int[] { 1, 2, 3, 4, 5 };
miniMaxSum(arr);
}
static void miniMaxSum(int[] arr)
{
List<int> arr2 = new List<int>();
int sum = 0,mn,mx;
int sum2 = 0;
int sum3 = 0;
int sum4 = 0;
int sum5 = 0;
for (int i = 0; i < arr.Length; i++)
{
if(i != 0)
{
sum = sum + arr[i];
}
if (i != 1)
{
sum2 = sum2 + arr[i];
}
if (i!= 2)
{
sum3 = sum3 + arr[i];
}
if (i != 3)
{
sum4 = sum4 + arr[i];
}
if (i != 4)
{
sum5 = sum5 + arr[i];
}
}
arr2.Add(sum);
arr2.Add(sum2);
arr2.Add(sum3);
arr2.Add(sum4);
arr2.Add(sum5);
mx = arr2[0];
mn = arr2[0];
for (int j = 0; j < arr2.Count; j++)
{
if (arr2[j] > mx)
{
mx = arr2[j];
}
if(arr2[j] < mn)
{
mn = arr2[j];
}
}
Console.Write(mn + " ");
Console.Write(mx);
}
For this one you can take a look at Statistics' Combination Formula, which gets all the possible r elements out of n elements, C(n, r).
This is the method to get all the possible combinations:
static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) => elements.Skip(i + 1)
.Combinations(k - 1)
.Select(c => (new[] { e }).Concat(c)));
}
First I'm gonna try using it in your case. You have the array like so.
int[] arr = new int[] { 1, 2, 3, 4, 5 };
Then you want to sum every 4 numbers in your array, like 1,2,3,4 ; 1,2,4,5 ; 1,2,3,5 ; ... etc. So you can use the method above with a Linq method called Sum().
foreach(IEnumerable<int> result in arr.Combinations(4))
{
Console.WriteLine(result.Sum());
}
Also, if you want to sum every 3 element instead, like 1,2,3 ; 3,4,5 ; 1,2,5 ; ... etc, you only need to change the parameter k in the method Combinations:
foreach(IEnumerable<int> result in arr.Combinations(3))
{
Console.WriteLine(result.Sum());
}
Last but not least, the above method that I provided is an extension methods, so be sure to put it in a static class, and don't forget to add a reference to System.Linq.
I'm going to take a slightly different approach from the other two answers that are currently posted. I'm going to slowly improve your solution one step at a time. I'm going to avoid LINQ; don't get me wrong LINQ is cool and you should definitely learn it, but it's useful to know what is going on inside. For more about LINQ see #General's answer above.
The first thing I would notice is that your solution only works when there are five elements in the array. The first version I am going to show you is one that removes this limitation.
But before I do that I want to write two helper functions that will come in handy: Max and Min. These functions take an array and return the maximum element and minimum element respectively.
static int Min(int[] arr)
{
int min = int.MaxValue;
foreach (var val in arr)
{
min = Math.Min(min, val);
}
return min;
}
static int Max(int[] arr)
{
int max = int.MinValue;
foreach (var val in arr)
{
max = Math.Max(max, val);
}
return max;
}
With these in hand we can write a version of your function that will handle an array of any size.
/// Adds capability to work with arrays longer the 5 elements.
static void MinMaxSum1(int[] arr)
{
// This array will hold the sums obtained if
// the corresponding element in the input
// array was left out of the sum.
// So sums[0] is the sum if the zeroth element
// is left out.
int[] sums = new int[arr.Length];
// skip is the index of the element we'll leave out
// of the sum
for (int skip = 0; skip < arr.Length; skip++)
{
int sum = 0;
for (int current = 0; current < arr.Length; current++)
{
if (current != skip)
{
sum += arr[current];
}
}
sums[skip] = sum;
Console.WriteLine($"MinMaxSum1: arr[{skip}] = {arr[skip]} sums[{skip}] = {sum}");
}
int min = Min(sums);
int max = Max(sums);
Console.WriteLine($"MinMaxSum1: min={min} max={max}");
Console.WriteLine("================================");
}
It's worthwhile to take a moment and consider how many operations this will do if the array has n elements. The inner loop will do n-1 additions and the outer loop will cause this to run n times, so roughly n2 additions, the Min and Max methods perform n comparisons each. So roughly n2 + 2n operations.
Can we do better?
Well, yes, we can. If you look at the output you may realize that arr[i] + sum[i] == 15. This makes sense there are two ways to get the answer:
add the elements skipping the one you want to leave out
add all the elements and subtract the one you want to leave out.
Notice the sum of all the elements is not going to change!
So if we have a helper function Sum that sums all the elements in the array we can write:
static void MinMaxSum2(int[] arr)
{
int sum = Sum(arr);
int[] sums = new int[arr.Length];
for (int i = 0; i < sums.Length; ++i)
{
sums[i] = sum - arr[i];
Console.WriteLine($"MinMaxSum2: arr[{i}] = {arr[i]} sums[{i}] = {sums[i]}");
}
int min = Min(sums);
int max = Max(sums);
Console.WriteLine($"MinMaxSum2: min={min} max={max}");
Console.WriteLine("================================");
}
This goes through the array once to compute the sum performing n additions, another time to compute the sums array performing n subtractions and the Min and Max routines perform n comparisons each, so about 4n operations in total.
Can we do better?
Again yes, but this time we need to look at part of your solution that was not mentioned in the question text. It looks like you only need the min and max partial sums. From the implementation above I hope you can see that the min will occur for sum - Max(arr) and the max will occur for sum - Min(arr).
This leads to this implementation:
static void MinMaxSum3(int[] arr)
{
int min = Min(arr);
int max = Max(arr);
int sum = Sum(arr);
Console.WriteLine($"MinMaxSum3: min sum = {sum - max}");
Console.WriteLine($"MinMaxSum3: max sum = {sum - min}");
Console.WriteLine("================================");
}
You can find all these versions, along with the implementation of Sum and one bonus implementation on .NET Fiddle
The description doesn't match the output. However, assuming the description is correct
Calculate the following sums using four of the five integers:
Sum everything except 1, the sum is 2+3+4+5=14.
Sum everything except 2,the sum is 1+3+4+5=13.
Sum everything except 3,the sum is 1+2+4+5=12.
Sum everything except 4,the sum is 1+2+3+5=11.
Sum everything except 5,the sum is 1+2+3+4=10.
You can do the following
You can just use 2 loops
var arr = new[] { 1, 2, 3, 4, 5 };
for (var i = 0; i < arr.GetLength(0);i++)
{
var sum = 0;
for (var j = 0; j < arr.GetLength(0); j++)
if (i != j)
sum += arr[j];
Console.WriteLine(sum);
}
Output
14
13
12
11
10
Or if you like Linq Chain Methods
for (var i = 0; i < arr.GetLength(0);i++)
{
var sum = arr.Where((x, j) => i != j ).Sum();
Console.WriteLine(sum);
}
Or you if hate for loops with a passion
var results = Enumerable.Range(0, arr.GetLength(0))
.Select(i => arr
.Where((x, j) => i != j)
.Sum());
Console.WriteLine(string.Join(Environment.NewLine, results));
Or if Extension Methods are your thing
public static IEnumerable<IEnumerable<T>> FunkyIterator<T>(this T[] source)
=> Enumerable.Range(0, source.GetLength(0))
.Select(i => source.Where((x, j) => i != j));
...
foreach (var iterations in arr.FunkyIterator())
Console.WriteLine(iterations.Sum());
How about this approach?
int[] arr = new int[] { 1, 2, 3, 4, 5 };
var total = arr.Sum();
List<int> sums = new List<int>();
foreach(int i in arr) {
sums.Add(total - i);
}
var min = sums.Min();
var max = sums.Max();
Console.WriteLine("min = " + min);
Console.WriteLine("max = " + max);
Or, if you don't want to use any LINQ:
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int total = 0;
foreach(int i in arr) {
total += i;
}
int min = 0, max = 0;
for(int i=0; i<arr.Length; i++) {
int sum = total - arr[i];
if (i == 0) {
min = sum;
max = sum;
}
else {
if (sum < min) {
min = sum;
}
if (sum > max) {
max = sum;
}
}
}
Console.WriteLine("min = " + min);
Console.WriteLine("max = " + max);

Sort an array of 0s, 1s and 2s (Further optimization) [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 years ago.
Improve this question
Below is a very simple code which sorts array of 0s, 1s and 2s. I believe it's time complexity is O(N), right? How can this algo be further improved to bring down time complexity to O(logN) or so?
//Input: 0 2 1 2 0
//Output: 0 0 1 2 2
public static int[] SortArray012(int[] array)
{
Dictionary<int, int> result = new Dictionary<int, int>(3);
int[] sortedResult = new int[array.Length];
int i = 0;
foreach(int no in array)
{
if (result.ContainsKey(no))
result[no]++;
else
result.Add(no, 1);
}
for (; i < result[0]; i++)
sortedResult[i] = 0;
for (; i < result[0] + result[1]; i++)
sortedResult[i] = 1;
for (; i < result[0] + result[1] + result[2]; i++)
sortedResult[i] = 2;
return sortedResult;
}
This is an example of counting sort. While there is no way to my knowledge to lower the asymptotic complexity you can focus on reducing the constants. For example there is no need to construct a dictionary, an array will do. If we are guaranteed that we will only see 1,2 and 0 then there is no need for the if statement. We can also generate our result with two for loops instead of three
int[] test = {1,1,0,2,1,0};
int[] count = {0,0,0};
int[] result = new int[test.Length];
foreach(int no in test){
count[no]++;
}
int i = 0;
int k = 0;
foreach(int c in count){
for(int j = 0; j < c; j++){
result[k++] = i;
}
i++;
}

Returning a list of even fibonacci numbers in C# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am working my way through Problem 2 on the Project Euler page
Each new term in the Fibonacci sequence is generated by adding the
previous two terms. By starting with 1 and 2, the first 10 terms will
be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... By considering the terms in
the Fibonacci sequence whose values do not exceed four million, find
the sum of the even-valued terms.
Before I sum all of the even numbers, I want to generate a list of them.
I have created the following methods:
static List<int> Fibonacci(int n)
{
int a = 0;
int b = 1;
var list = new List<int>();
for (int i = 0; i < n; i++)
{
int temp = a;
a = b;
b = temp + b;
list.Add(a);
}
return list;
}
static List<int> ListEvenFibonacci(int n)
{
var list = Fibonacci(n);
var evenList = new List<int>();
for (int i = 0; i < list.Count; i++)
{
if (IsEvan(list.ElementAt(i)))
{
evenList.Add(i);
}
}
return evenList;
}
static bool IsEvan(int n)
{
if (n % 2 == 0)
{
return true;
}
else
{
return false;
}
}
And in my main function I am printing out the even list of numbers to make sure it works like so:
static void Main(string[] args)
{
var List = ListEvenFibonacci(15);
for (int i = 0; i < List.Count; i++)
{
Console.WriteLine(List[i]);
}
}
however, the output I am getting is not correct:
2
5
8
11
14
I suggest implementing a generator and then, with a help of Linq perform the query:
private static IEnumerable<long> Fibo(long first, long second) {
long prior = first;
long last = second;
yield return prior;
yield return last;
while (true) {
long next = prior + last;
yield return next;
prior = last;
last = next;
}
}
...
long result = Fibo(1, 2)
//.Where((value, index) => index % 2 == 0) // if we want even indexes (zero based!)
.Where(value => value % 2 == 0) // if we want even values
.TakeWhile(value => value <= 4000000) // items not exceed 4e6
.Sum();
Console.Write(result);
Outcome: 4613732
You're adding an iteration variable, not the list element itself.
evenList.Add(i);
Should be
evenList.Add(list[i]);
Don't save index of even number. Save the number at index like this.
for (int i = 0; i < list.Count; i++)
{
if (IsEvan(list.ElementAt(i)))
evenList.Add(list.ElementAt(i));
}
For sum of even values
int sum = 0;
for (int i = 0; i < List.Count; i++)
sum += List[i];
Console.WriteLine(sum); // this will print sum of even number.

How do I get rid of circular numbers in my list

Okay, I know that this code is crude, and all around a messy, but I am no programmer, so bear with me. I have this code that lists a bunch of numbers, but I want it to not list any circular copies of the numbers.
For example, if the number 111262 is on my list, I don't want 112621, 126211, 262111, 621112, or 211126 to be listed.
Sorry, that number cannot be on the list.
For a true example, if the number 111252 is on my list, I don't want 112521, 125211, 252111, 521112, or 211125 to be listed.
Any help is appreciated!
namespace Toric_Classes
{
class Program
{
static void Main(string[] args)
{
int number_of_perms=0;
bool badsubsum1;
bool badsubsum2;
int subsum1 = 0;
int subsum2 = 0;
int sum = 0;
int class_length=6;
int[] toric_class=new int[class_length];
// The nested for loops scroll through every possible number of length class_length, where each digit can have a value of 1,2,..., or class_length-1
// Each number is looked at as an array, and is not stored anywhere, only printed if it satisfies certain conditions
for(int i1=1; i1<class_length; i1++)
{
toric_class[0] = i1;
for (int i2 = 1; i2 < class_length; i2++)
{
toric_class[1] = i2;
for (int i3 = 1; i3 < class_length; i3++)
{
toric_class[2] = i3;
for (int i4 = 1; i4 < class_length; i4++)
{
toric_class[3] = i4;
for (int i5 = 1; i5 < class_length; i5++)
{
toric_class[4] = i5;
for (int i6 = 1; i6 < class_length; i6++)
{
badsubsum1 = false;
badsubsum2 = false;
toric_class[5] = i6;
// Find the value of the sum of the digits of our array.
// We only want numbers that have a total digit sum being a multiple of class_length
for (int k = 0; k < class_length; k++)
{
sum += toric_class[k];
}
// The follwong two nested loops find the value of every contiguous subsum of our number, but not the total subsum.
// We *do not* want any subsum to be a multiple of class_length.
// That is, if our number is, say, 121342, we want to find 1+2, 1+2+1, 1+2+1+3, 1+2+1+3+4, 2+1, 2+1+3, 2+1+3+4, 2+1+3+4+2, 1+3, 1+3+4, 1+3+4+2, 3+4, 3+4+2, and 4+2
// The following checks 1+2, 1+2+1, 1+2+1+3, 1+2+1+3+4, 2+1, 2+1+3, 2+1+3+4, 1+3, 1+3+4, and 3+4
for (int i = 0; i < class_length - 1; i++)
{
for (int j = i + 1; j < class_length - 1; j++)
{
for (int k = i; k < j; k++)
{
subsum1 += toric_class[k];
}
if (subsum1 % class_length == 0)
{
badsubsum1 = true;
break;
}
subsum1 = 0;
}
}
// The following checks 2+1, 2+1+3, 2+1+3+4, 2+1+3+4+2, 1+3, 1+3+4, 1+3+4+2, 3+4, 3+4+2, and 4+2
for (int i = 1; i < class_length; i++)
{
for (int j = i + 1; j < class_length; j++)
{
for (int k = i; k < j; k++)
{
subsum2 += toric_class[k];
}
if (subsum2 % class_length == 0)
{
badsubsum2 = true;
break;
}
subsum2 = 0;
}
}
// We only want numbers that satisfies the following conditions
if (sum % class_length == 0 && badsubsum1 == false && badsubsum2 == false)
{
foreach (var item in toric_class)
{
Console.Write(item.ToString());
}
Console.Write(Environment.NewLine);
number_of_perms++;
}
sum = 0;
subsum1 = 0;
subsum2 = 0;
}
}
}
}
}
}
Console.WriteLine("Number of Permuatations: "+number_of_perms);
Console.Read();
}
}
}
EDIT
To clarify, I am creating a list of all numbers with length n that satisfy certain conditions. Consider the number d1d2...dn, where each di is a digit of our number. Each di may have value 1,2,...,n. Our number is in the list if it satisfies the following
The sum of all the digits is a multiple of n, that is,
d1+d2+...+dn = 0 mod n
Every contiguous subsum of the digits is not a multiple of n, aside from the total sum, that is, if i !=1 and j != n, then
di+d(i+1)+...+dj != 0 mod n
I should mention again that a "number" does not strictly use the numbers 0-9 in its digits. It may take any value between 1 and n. In my code, I am using the case where n=6.
The code works by creating an array of length class_length (in the code above, I use class_length=6). We first have 6 nested for loops that simply assign values to the array toric_class. The first for assigns toric_class[0], the second for assigns toric_class[1], and so on. In the first go around, we are generating the array 111111, then 111112, up to 111115, then 111121, etc. So essentially, we are looking at all heximal numbers that do not include 0. Once we reach our sixth value in our array, we check the array toric_class and check its values to ensure that it satisfies the above conditions. If it does, we simply print the array in a line, and move on.
Here is my easy and inefficient way that should work with minimal changes to your code. It requires shared string list var strList = new List<string>(); to store the used numbers. Then this part:
foreach (var item in toric_class)
{
Console.Write(item.ToString());
}
Console.Write(Environment.NewLine);
number_of_perms++;
becomes something like this:
string strItem = " " + string.Join(" ", toric_class) + " "; // Example: int[] {1, 12, 123} becomes " 1 12 123 "
if (!strList.Any(str => str.Contains(strItem))) // Example: if " 1 12 123 1 12 123 " contains " 1 12 123 "
{
Console.WriteLine(strItem);
strItem += strItem.Substring(1); // double the string, but keep only one space between them
strList.Add(strItem);
}
number_of_perms++; // not sure if this should be in the if statement
The idea is that for example the string " 1 1 1 2 5 2 1 1 1 2 5 2 " contains all circular copies of the numbers {1, 1, 1, 2, 5, 2}. I used string as a lazy way to check if array contains sub-array, but you can use similar approach to store copy of the used numbers in a list of arrays new List<int[]>() and check if any of the arrays in the list is circular copy of the current array, or even better HashSet<int[]>() approach similar to #slavanap's answer.
The first version of my answer was the easiest, but it works only with array of single digit items.
List is almost the same as array (new List<string>() instead of new string[]), but makes it much easier and efficient to add items to it. For example {1,2}.Add(3) becomes {1,2,3}.
str => str.Contains(strItem) is shortcut for a function that accepts parameter str and returns the result of str.Contains(strItem). That "function" is then passed to the .Any LINQ extension, so
strList.Any(str => str.Contains(strItem))
is shortcut for something like this:
foreach(string str in strList)
{
if (str.Contains(strItem))
{
return true;
}
}
return false;
The following method:
private static List<int> GetCircularEquivalents(int value)
{
var circularList = new List<int>();
var valueString = value.ToString();
var length = valueString.Length - 1;
for (var i = 0; i < length; i++)
{
valueString = valueString.Substring(1, length) + valueString.Substring(0, 1);
circularList.Add(int.Parse(valueString));
}
return circularList;
}
will return a list of the circular numbers derived from the input value. Using your example, this method can be called like this:
var circularList = GetCircularEquivalents(111262);
var dirtyList = new List<int> { 1, 112621, 2, 126211, 3, 262111, 4, 621112, 5, 211126, 6 };
var cleanList = dirtyList.Except(circularList).ToList();
which would result in a cleanList made up of the numbers 1 through 6, i.e. the dirtyList with all the circular numbers derived from 111262 removed.
That's where OOP really benefits. Comments inlined.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3 {
struct MyInt : IEquatable<MyInt> {
private int _value;
public MyInt(int value) {
_value = value;
}
// make it look like int
static public implicit operator MyInt(int value) {
return new MyInt(value);
}
public static explicit operator int(MyInt instance) {
return instance._value;
}
// main difference in these 3 methods
private int GetDigitsNum() {
int temp, res;
for (res = 0, temp = Math.Abs(_value); temp > 0; ++res, temp /= 10);
return res;
}
public bool Equals(MyInt other) {
int digits = other.GetDigitsNum();
if (digits != this.GetDigitsNum())
return false;
int temp = other._value;
// prepare mul used in shifts
int mul = 1;
for (int i = 0; i < digits - 1; ++i)
mul *= 10;
// compare
for (int i = 0; i < digits; ++i) {
if (temp == _value)
return true;
// ROR
int t = temp % 10;
temp = temp / 10 + t * mul;
}
return false;
}
public override int GetHashCode() {
// hash code must be equal for "equal" items,
// that's why use a sum of digits.
int sum = 0;
for (int temp = _value; temp > 0; temp /= 10)
sum += temp % 10;
return sum;
}
// be consistent
public override bool Equals(object obj) {
return (obj is MyInt) ? Equals((MyInt)obj) : false;
}
public override string ToString() {
return _value.ToString();
}
}
class Program {
static void Main(string[] args) {
List<MyInt> list = new List<MyInt> { 112621, 126211, 262111, 621112, 211126 };
// make a set of unique items from list
HashSet<MyInt> set = new HashSet<MyInt>(list);
// print that set
foreach(int item in set)
Console.WriteLine(item);
}
}
}
Output:
112621

Categories