Different value for every int variable - c#

I have a five int variables:
int firstSequence;
int secondSequence;
int thirdSequence;
int fourthSequence;
int fifthSequence;
Every of these variable could have value from 1-5. How to check in the most efficient way, if every of these variable has unique value? I mean only one can have value = 1 etc.
private bool IsOrderCorrect()
{
if(firstSequence != secondSequence && ...)
}

Simply put them into an array then use Distinct:
new [] {
firstSequence,
secondSequence,
thirdSequence,
fourthSequence,
fifthSequence
}.Distinct().Count() == 5;

You could try
( (1 << firstSequence)
| (1 << secondSequence)
| (1 << thirdSequence)
| (1 << fourthSequence)
| (1 << fifthSequence))
== (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);

Here you go
List<int> uniqueCheck = new List<int>() { firstSequence, secondSequence, thirdSequence, fourthSequence, fifthSequence };
if(uniqueCheck.Distinct().Count() == uniqueCheck.Count())
{
//they are unique
}

I don't think that is the most efficient way.
The most efficient way would be to sum them and make sure the sum equals 15.
Testing this on my machine a 1000000 times results in the .Distinct().Count() == 5 method taking 244.77 milliseconds.
Doing the same thing but using .Sum() == 15 takes 54.92 so the sum method is more efficient.
Having said this, using Distinct().Count(), will generalise to more cases however the op asked for the most efficient way.
EDIT:
Sorry, I was rushing when I typed the original so it was flawed. My general method remains the same but instead of summing the numbers, you should sum the squares, which I believe should equal 55 and should only sum to 55 if the numbers are distint.
Testing with the sum of squares takes 139 milliseconds which is still faster than .Distinct().Count() == 5
So my answer should be updated to .Select(x => x*x).Sum() == 55

If they were in an array it would be very easy
int[] numbers = new int[] {1,2,3,4,5};
for (int i = 0; i < numbers.Length; i++)
{
for (int j = 0; j!= i && j < numbers.Length; j++)
{
if (numbers[i] == numbers[j]) {
// you know what to do
}
}
}

Related

Algorithm to get which values make sum of a given number from array

I don't know to search or google it so I ask it here.
I have an array of integers with fixed size and exactly with this logic.
sample [1,2,4,8,16,32]
Now I am given a number for example 26. And I shall find the numbers whose sum will make this number, in this case is [2,8,16]
for a number of 20 it will be [4,16]
for 40 it is [8,32]
and for 63 it is all of these numbers [1,2,4,8,16,32]
What is the proper algorithm for that?
I know strictly that there is always this continuation that the number is double of the previous value.
as well as only the numbers from the given array will sum up to the given number and each number will be used only for once or none
If it will be in C# method that takes array of ints and an int value and returns the array of ints that contains the ints that sum up this number from the given array will be preferred.
Thank you
As you can see, the number are base-2, which means you can easily use shift.
You could try this:
private IEnumerable<int> FindBits(int value)
{
// check for bits.
for (int i = 0; i < 32; i++)
{
// shift 1 by i
var bitVal = 1 << i; // you could use (int)Math.Pow(2, i); instead
// check if the value contains that bit.
if ((value & bitVal) == bitVal)
// yep, it did.
yield return bitVal;
}
}
This method will check what bits are set and return them as an ienumerable. (which can be converted to an array of list)
Usage:
// find the bits.
var res = FindBits(40).ToArray();
// format it using the string.join
var str = $"[{string.Join(",", res)}]";
// present the results
Console.WriteLine(str);
Results in [8,32]
Extra info:
counter
00000001 = 1 = 1 << 0
00000010 = 2 = 1 << 1
00000100 = 4 = 1 << 2
00001000 = 8 = 1 << 3
00010000 = 16 = 1 << 4
00100000 = 32 = 1 << 5
01000000 = 64 = 1 << 6
10000000 = 128 = 1 << 7
Instead of writing all combinations you make a for loop which does the counter.
Some extra non-sense:
If you like lambda's, you could replace the FindBits with this:
private Func<int, IEnumerable<int>> FindBits = (int value) => Enumerable
.Range(0, 31)
.Select(i => 2 << i).Where(i => (value & i) == i);
But it's better to keep it simpel/readable.
First you should notice that
( 1 2 4 8 16 ... ) = (2^0 2^1 2^2 2^3 2^4 ... )
And that this is the same as finding a binary encoding for a decimal number. What you are looking for is an algorithm to transform a decimal or base 10 number to a binary or base 2 number.
The algorithm is pretty simple:
public List<int> dec_to_bin(int num)
{
List<int> return_list = new List<int>();
int index = 0;
int remainder = num;
int bit = 0;
while (remainder > 0)
{
bit = remainder % 2;
if (bit == 1 )
{
return_list.Add((int)Math.Pow(2, index));
}
remainder = remainder / 2;
index = index + 1;
}
return return_list;
}
There is a better way however that just uses the underlying encoding of the number which is already binary.
public List<int> dec_to_bin(int num)
{
List<int> return_list = new List<int>();
int value = 1;
while( value < num )
{
if( (value & num) == value )
{
return_list.Add(value);
}
value = value * 2;
}
return return_list;
}
Another way to state your requirement is "What are the unique powers of 2 that sum to a given integer?" Since computers work with powers of 2 natively, there are built-in goodies in most languages to do this very succinctly.
As a bonus, you can use existing .Net types and methods to eliminate the need to write your own loops.
Here's one approach:
IEnumerable<int> GetCompositePowersOf2(int input) =>
//convert to enumerable of bools, one for each bit in the
//input value (true=1, false=0)
new BitArray(new[] { input }).Cast<bool>()
// get power of 2 corresponding to the position in the enumerable
// for each true value, gets 0 for false values.
.Select((isOne, pos) => isOne ? (1 << pos) : 0)
//filter out the 0 values
.Where(pow => pow > 0);
I don't quite get the " takes array of ints " part, since this creation of sums only works with numbers that are the power of 2.
private int[] count (int num)
{
int factor = 0;
List<int> facts = new List<int>();
while (num > 0)
{
int counter = 0;
int div = num;
int remainder = 0;
while (remainder == 0)
{
remainder = div % 2;
div = div / 2;
counter++;
}
factor = 1;
for (int i = 1; i < counter; i++)
factor *= 2;
num = num - factor;
facts.Add(factor);
}
return (facts.ToArray());
}

Convert binary number 5 into list of intergers (4,1)

I have a configuration value expressed as a binary number to allow several options within the same value.
E.g. the value of 5 would be "101" or both 4 and 1.
Does anyone know of the best/fastest way to "input" the value '5' and get a list of {1,4} back?
If you want to get powers of 2 which the value consists of:
int value = 5;
var addendums = Enumerable.Range(0, sizeof(int) * 8 - 1)
.Select(i => (1 << i) & value)
.Where(x => x != 0)
.ToList();
Result:
[ 1, 4 ]
Note that if you want to have addendums in descending order, you can apply Reverse() after filtering sequence.
TL;DR The first step generates integer values which correspond to bit positions in integer value 0, 1, 2, ..., 31. Max index is a number of bits in Int32 value - 1 (because we need the index of the bit).
Next step selects a result of bitwise AND operation of the 1 shifted to the corresponding index (same as the power of 2) with the value itself (only first 4 bits shown here):
i 1<<i value (1<<i) & value
Binary Binary Binary Decimal
0 0001 0101 0001 1
1 0010 0101 0000 0
2 0100 0101 0100 4
3 1000 0101 0000 0
...
All you have to do after this step - filter out zeroes.
Some bit shifting and & later...
int n = 5+32;
var lst = new List<int>();
int i = 1;
while (n > 0)
{
if ((n & i) == i)
{
lst.Add(i);
n &= ~i;
}
i <<= 1; // equivalent to i *= 2
}
A little more esoteric, with the use of xor (^):
if (n != 0)
{
while (true)
{
if ((n & i) != 0)
{
lst.Add(i);
n ^= i;
if (n == 0)
{
break;
}
}
i <<= 1; // equivalent to i *= 2
}
}
I have made this little sample. Here you obtain from an integer its value as a sum of its powers of two. Thosw powers should be your input options
class Program
{
static void Main(string[] args)
{
var input = 5;
var options = new List<uint>();
for (uint currentPow = 1; currentPow != 0; currentPow <<= 1)
if ((currentPow & input) != 0)
options.Add(currentPow);
foreach (var option in options)
Console.WriteLine(option);
Console.ReadLine();
}
}
And the output is: 1 4
EDIT>>> In fact this does the same as #Sergey Berezovskiy answer but without LINQ
Hope it helps
The naive approach:
int originalInput = 42;
int input = originalInput;
// Generate binary numbers
var binaryNumbers = Enumerable.Range(0, 31).Select(n => (int)Math.Pow(2, n)).ToArray();
// Largest first
Array.Reverse(binaryNumbers);
var result = new List<int>();
foreach (var bin in binaryNumbers)
{
if (input >= bin)
{
result.Add(bin);
input -= bin;
}
}
Console.WriteLine($"{originalInput} decomposed: " + string.Join(" ", result));
Generate a range of power-of-two numbers, ranging from 2^31 (1073741824) to 2^0 (1), then check whether the input is equal to or larger than those numbers, and if so, add that number to the result list and subtract it from the input.
Now that that's all written out, see how Sergey's answer greatly reduces the code required by some Linq and bitshifting magic.
A hybrid solution, inspired by combining both answers:
var input = 42;
var output = Enumerable.Range(0, 31)
.Select(n => (int)Math.Pow(2, n))
.Where(p => (p & input) > 0);
Console.WriteLine($"{input} decomposed: " + string.Join(" ", output));
A maybe more traditional and easy to understand solution. You convert the number into a string binary representation, and then analyze each character to extract the corresponding decimal representations of each bit at 1.
int number = 5;
string binaryRep = Convert.ToString(number, 2);
List<int> myList = new List<int>();
int pow = 0;
for(int i = binaryRep.Count() - 1; i >= 0; i--)
{
if(binaryRep[i] == '1')
{
myList.Add((int)Math.Pow(2, pow));
}
pow++;
}
Short and fast:
int input = 5;
var list = new List<int>();
for (int i = 1, j = input; i <= j; i *= 2, input >>= 1){
if ((input & 1) == 1)
list.Add(i);
}
To show binary representation use
int value = 7;
var binary = Convert.ToString(value, 2);
To see binary numbers:
private int[] ToBinaryNumbers(int value)
{
var binary = Convert.ToString(value, 2).Reverse();
int ix = 0;
return binary.Select(x => { var res = x == '1' ? (int?)Math.Pow(2, ix) : (int?)null; ix++; return res; }).Where(x => x.HasValue).Select(x => x.Value).ToArray();
}
This will give you 1,2,4 for 7 or 1,8 for 9

Can somebody explains what happens in this algorithm to check if its a pandigital?

I know that the << operand shifts the left value of the operand with the value on the right with bits. So 1 << 2 would give 4. And the | operand copies a bit if it exists in either value. But I simply can't get my head around the code.
private static bool isPandigital(long n)
{
int digits = 0;
int count = 0;
int tmp;
while (n > 0)
{
tmp = digits;
digits = digits | 1 << (int)((n % 10) - 1);
if (tmp == digits)
{
return false;
}
count++;
n /= 10;
}
return digits == (1 << count) - 1;
}
Why does it say 1 << in line 8? And why is the module - 1?
On top of that I don't know what is happening on the last line when the value is returned. Help would be greatly apreciated. Thanks very much!
Doing
digits = digits | 1 << (int)((n % 10) - 1);
is the same thing as
long temp1 = n % 10; //Divide the number by 10 and get the remainder
long temp2 = temp1 - 1; //Subtract 1 from the remainder.
int temp3 = (int)temp2; //cast the subtracted value to int
int temp4 = 1 << temp3; //left shift 1 to the casted value. This is the same as saying "two to the power of the value of temp3"
int temp5 = digits | temp4; //bitwise or together the values of digits and that leftshifted number.
digits = temp5; //Assign the or'ed value back to digits.
The last line
return digits == (1 << count) - 1;
is just doing the same thing as
int temp1 = 1 << count; //left shift 1 `count` times, this is the same as saying "two to the power of the value of count"
int temp2 = temp1 - 1; //Subtract 1 from the leftshifted number.
bool temp3 = digits == temp2; //test to see if digits equals temp2
return temp3;
I don't know what "pandigital" means, but this break apart can help you understand what is happening.
If pandigital means "contains all possible digits for the given radix"
https://en.wikipedia.org/wiki/Pandigital_number
and the radix == 10, why not just check if the number contains all possible 0..9 digits:
private static bool isPandigital(long n) {
// I assume negative numbers cannot be pandigital;
// if they can, put n = Math.Abs(n);
if (n < 1023456789) // smallest pandigital
return false;
int[] digits = new int[10];
for (; n > 0; n /= 10)
digits[n % 10] += 1;
return digits.All(item => item > 0);
}
Edit: In case of bit array (each bit in digits represent a digit) implementation:
private static bool isPandigital(long n) {
// negative numbers can't be pandigital
if (n < 1023456789) // smallest pandigital
return false;
int digits = 0;
for (; n > 0; n /= 10)
digits |= (1 << (int)(n % 10));
// 0b1111111111
return digits == 1023;
}
I think the writer of the method attempted to do this:
static bool IsPandigital(long n) {
int digits = 0;
while (n > 0) {
//set the bit corresponding to the last digit of n to 1 (true)
digits |= 1 << (int)(n % 10);
//remove the last digit of n
n /= 10;
}
//digits must be equal to 1111111111 (in binary)
return digits == (1 << 10) - 1;
}
The << operator is not that difficult. You just have to think in binary.
1 << 0 is simply a 1 shifted zero places, so 1
1 << 1 is 10
1 << 2 is 100, etc
If you encounter a 2 and a 5 and you 'or' them together you will have 100100.
This means if you encounter all 10 digits, the end result will be ten 1's.
In the return statement, we check if digits equals ten 1's.
1 << 10 means a 10000000000. If you substract 1, you get 1111111111
All this in binary, of course.
He may have had a different definition of pandigital, or just a different requirement. If, for example zeroes are not allowed, you can simply change the last line to: digits == (1 << 10) - 2;

Every possible combination of X split into N stacks

I am sure this problem has a formal name, and knowing that name would probably help me find the solution, but I don't know it, and wording the problem for Google keeps pointing me to the Knapsack Problem, which isn't the same thing.
I want to take some value X and find every possible combination of splitting that value into N stacks of whole integers.
In case my wording is confusing, here is an example of X = 4, N = 3
Stack -> 1 | 2 | 3 |
----------------------
#1-----> 4 | 0 | 0 |
----------------------
#2-----> 3 | 1 | 0 |
----------------------
#3-----> 2 | 1 | 1 |
----------------------
#4-----> 2 | 2 | 0 |
Duplication is acceptable, since its easy to remove, but ideally it would not be calculated. An algorithm for solving the problem would be perfect, but even finding out of the problem has a name would make research easier. Thanks.
These are in fact integer partitions as a deleted answer remarks. Using Mathematica:
IntegerPartitions[4, 3] // PadRight //Grid
Output:
4 0 0
3 1 0
2 2 0
2 1 1
I could not find a C# implementation but here are a couple of related questions:
Elegant Python code for Integer Partitioning
Integer Partition in Java
Algorithm for generating integer partitions
Google hits:
Integer Partition Algorithm by Jerome Kelleher
Integer Partition Algorithm by Daniel Scocco
Fast Algorithms for Generating Integer Partitions (PDF) (looks heavy-duty)
Stony Brook Algorithm Repository - Partitions
This seems to do the trick:
vector<vector<int> > partitions(int X, int N, int Y)
{
vector<vector<int> > v;
if(X<=1 || N==1)
{
if(X<=Y)
{
v.resize(1);
v[0].push_back(X);
}
return v;
}
for(int y=min(X, Y); y>=1; y--)
{
vector<vector<int> > w = partitions(X-y, N-1, y);
for(int i=0; i<w.size(); i++)
{
w[i].push_back(y);
v.push_back(w[i]);
}
}
return v;
}
int main()
{
vector<vector<int> > v = partitions(5, 3, 5);
int i;
for(i=0; i<v.size(); i++)
{
int x;
for(x=0; x<v[i].size(); x++)
printf("%d ", v[i][x]);
printf("\n");
}
return 0;
}
This is user434507's answer in C#:
class Program
{
static void Main(string[] args)
{
var v = Partitions(5, 3, 5);
for (int i = 0; i < v.Count; i++)
{
for (int x = 0; x < v[i].Count; x++)
Console.Write(v[i][x] + " ");
Console.WriteLine();
}
}
static private List<List<int>> Partitions(int total, int stacks, int max)
{
List<List<int>> partitions = new List<List<int>>();
if (total <= 1 || stacks == 1)
{
if (total <= max)
{
partitions.Add(new List<int>());
partitions[0].Add(total);
}
return partitions;
}
for (int y = Math.Min(total, max); y >= 1; y--)
{
var w = Partitions(total - y, stacks - 1, y);
for (int i = 0; i < w.Count; i++)
{
w[i].Add(y);
partitions.Add(w[i]);
}
}
return partitions;
}
}

How can I quickly tell if a list contains a list?

There are multiple related questions, but I'm looking for a solution specific to my case. There is an array of (usually) 14 integers, each in the range of 1 to 34. How can I quickly tell if each int in a specific, static list appears at least once in this array?
For reference, I'm currently using this code, which was written to resemble the spec as closely as possible, so it can certainly be improved vastly:
if (array.Count < 13) {
return;
}
var required = new int[] {
0*9 + 1,
0*9 + 9,
1*9 + 1,
1*9 + 9,
2*9 + 1,
2*9 + 9,
3*9 + 1,
3*9 + 2,
3*9 + 3,
3*9 + 4,
3*9 + 5,
3*9 + 6,
3*9 + 7,
};
IsThirteenOrphans = !required.Except (array).Any ();
The required list is not dynamic, i.e. it will always be the same during runtime. Using Linq is optional, the main aspect is performance.
Edit:
The input array is not sorted.
Input values may appear multiple times.
The input array will contain at least 14 items, i.e. 1 more than the required array.
There is only 1 required array and it is static.
The values in required are distinct.
You may assume that a histogram is cheap to create.
Update: I am also interested in a solution for a sorted input array.
Idea 1
If you need to compare with several required lists then you might sort the input list and then simply compare it by iterating. But sorting is of course not too fast, but not too slow either. But if you compare with several required lists the overhead of sorting might be amortized quickly.
Once the array is sorted comparing is trivial:
for(int i = 0; i < 14; i++)
if(arr[i] != required[i]) return false;
return true;
Idea 2
Or if the 14 integers are distinct/unique you can simply make required a HashSet and do
input.Count(i => required.Contains(i)) == 14
But I don't know without actually testing it if that's faster than sorting.
Idea 3
Calculate a quick hash which is invariant under permutations over the 14 ints and compare it to the known value of require. Only if the hash matches do the more expensive comparison.
//Prepare/precalculated
int[] hashes = new int[34];
Random random = new Random();
for(int i = 0; i < 34; i++)
hashes[i] = random.NextInt();
//On each list
int HashInts(int[] ints)
{
int result = 0;
foreach(int i in ints)
result += hashes[i - 1];
return result;
}
A wise choice of values for hashes might improve it a bit, but random values should be fine.
Idea 4
Create a Histogram:
int[] CreateHistogram(int[] ints)
{
int[] counts = new int[34];
foreach(int i in ints)
{
counts[i - 1]++;
}
return counts;
}
You can avoid the array creating by reusing an existing array if performance is really important.
If you have a 34+ bit integral type available, and C style bit operations, then you could compute such an integer V from the variable list (if the list is v[0], v[1], ... then V is (1 << v[0]) | (1 << v[1]) ... where 1 is of the same type as V) and have a predefined such integer S for the static list, computed analogously. The test to see if the static list is contained in the variable list is then (S & ~V) == 0.
One possibility is to change the way that you store the data. Since the range of possible values is limited to 1-34, instead of storing a list of numbers, you could store the counts of each number present:
int[] counts = new int[34];
If your list has one 1 and two 3s, then counts[0] == 1 && counts[2] = 2 (you could alternately use 1-based indexing if that makes things faster (fewer subtractions.))
Now to evaluate that each int in a list appears at least once, you simply index into the array sequentially for each x and verify that all counts[x] > 0. There will be overhead associated with transforming the data from the counts form to the list form, but that's only a problem if you also frequently need to view the data in the list form. Another advantage to this storage format is that adding/removing to counts will never involve more than a single array element; in the list form, removing an element in the middle of the list entails a copy of multiple elements.
If you want fast way you shouldn't use linq, If a given list items all are bellow 35 you can remove if (lst[i] < 35)
The bellow answer traverse list at most one time, and acts like counting sort:
public bool FindExactMatch(int[] array, List<int> lst)
{
bool[] a34 = new bool[35];
foreach(var item in array)
{
a34[item] = true;
}
int exact = 0;
for (int i = 0; i < lst.Count; i++)
{
if (a34[lst[i]])
{
exact++;
if (exact == array.Length) return true;
a34[lst[i]] = false;
}
}
return false;
}
for sorted list if list size is big you can do lst.BinarySearch(array[i]) which takes 14 * log(n) * c1 at most, and I think it's efficient enough also if you implement it may be become faster, and I didn't test binary search with my own implementation, but Min, Max, Sort in linq is slower than (between 4 and 10 time) your own (good) implementation.
And if sorted list size is small i prefer to use algorithm like above because constant c1 is small in above algorithm and may be larger in binary search algorithm.
This looks like a good candidate for bitwise operations, since the values in required are distinct, static, and between 1 and 34. Instead of saving required as an array, save it as a const ulong. In your arrays to check, create a new ulong populated by left-shift each value and bitwise or.
const ulong comparator = (1UL << 1) | (1UL << 9) | (1UL << 10) | (1UL << 18) | (1UL << 19) | (1UL << 27) | (1UL << 28) | (1UL << 29) | (1UL << 30) | (1UL << 31) | (1UL << 32) | (1UL << 33) | (1UL << 34);
public static bool ContainsDistinct13Values(int[] array)
{
ulong word = 0;
foreach (int i in array)
{
word |= (1UL << i);
}
return word == comparator;
}
Edit:
So I understood your question and probably have some nice over-complicated solution. Another question is, how good performance it has.
static void Main(string[] args)
{
var required = new int[]
{
0*9 + 1,
0*9 + 9,
1*9 + 1,
1*9 + 9,
2*9 + 1,
2*9 + 9,
3*9 + 1,
3*9 + 2,
3*9 + 3,
3*9 + 4,
3*9 + 5,
3*9 + 6,
3*9 + 7,
};
precomputed = required.Select((x, i) => new { Value = x, Offset = (UInt16)(1 << i) }).ToDictionary(x => x.Value, x => x.Offset);
for (int i = 0; i < required.Length; i++)
{
precomputedResult |= (UInt16)(1 << i);
}
int[] array = new int[34]; // your array goes here..
Console.WriteLine(ContainsList(array));
Console.ReadKey();
}
// precompute dictionary
private static Dictionary<int, UInt16> precomputed;
// precomputed result
private static UInt16 precomputedResult = 0;
public static bool ContainsList(int[] values)
{
UInt16 result = 0;
for (int i = 0; i < values.Length; i++)
{
UInt16 v;
if (precomputed.TryGetValue(values[i], out v))
result |= v;
}
return result == precomputedResult;
}
You could easily loop through the items and find out is there any item missing. By your example i understand you just wanted to know if there is any item from required is missing in array. so you could write
bool notContains = false;
foreach (var iddd in required)
{
foreach (var ar in array)
{
if (iddd == ar) notContains=true;
}
if (notContains == false) break;
}
This is lot faster than your approach. Check out the below code with timer added. Your approach took 5 ms, but the new one take 0 ms
System.Diagnostics.Stopwatch aTimer = new System.Diagnostics.Stopwatch();
aTimer.Start();
var IsThirteenOrphans = !required.Except(array).Any();
aTimer.Stop();
System.Diagnostics.Stopwatch bTimer = new System.Diagnostics.Stopwatch();
bTimer.Start();
bool notContains = false;
foreach (var iddd in required)
{
foreach (var ar in array)
{
if (iddd == ar) notContains=true;
}
if (notContains == false) break;
}
bTimer.Stop();

Categories