Suppose you have one million consecutive integer numbers.
Return all possible values of a,b and c such that
a+b+c<=d.
d will be provided to you.
ex: if the numbers are 1,2,3,4,5,6,7
and d=7
[1,2,3]
[1,2,4]
[1,2,3] will be same as [1,3,2] and [3,2,1]...
Because one million is too big, in the example I adopted 1000 as an example. Also for the convenience, I used 1 to 1000 as the data set.
Suppose
`a<b<c`
Thus 3*a<1000==> a<333.33, so I extract a from 1 to 333.
static void Main(string[] args)
{
int d = 519;
var setA = Enumerable.Range(1, 333);
IEnumerable<int> value = Enumerable.Range(1, 1000);
var result = (from a in setA
from b in value
from c in value
where a!=b && a!=c && b!=c && a + b + c <= d
select new {a,b,c}).ToList().Distinct().ToList();
foreach (var item in result)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
It is slow and throw an System.OutOfMemoryException exception.....
Narrowing down a to 1...333 is a good idea. You can further improve your code though by using the fact that a < b < c, so b,c in Enumerable.Range(1, 1000) is suboptimal.
You can define lower bounds and upper bounds for b and c depending on the given numbers a and b respectively:
a < b => b >= a + 1, b in Enumerable.Range(a + 1, ...)
b < c => c must be in Enumerable.Range(b + 1, ...)
Furthermore you can define bounds for a and b like that:
Since b >= a + 1 and a + b + c <= total, a + (a + 1) + ((a + 1) + 1) <= total must hold true also. That is, a < total / 3 is not sufficient. It is a <= (total - 3) / 3
Similarly a + b + (b + 1) <= total, that is, b <= (total - a - 1) / 2
And of course, a + b + c <= total translates to c <= total - a - b
You can make use of that by nesting the iterations and using SelectMany to flatten the result list:
var result = Enumerable.Range(1, (total - dba - dca) / 3)
.SelectMany(
a => Enumerable.Range(a + 1, (total - a - dcb) / 2 - a)
.SelectMany(
b => Enumerable.Range(b + 1, (total - a - b) - b)
.Select(c => new { a, b, c })));
As for your performance and out-of-memory issue:
Remove the ToList() from your LINQ query. It causes all results to be loaded into memory before you start processing them. Since you only want to print out the tuples, you don't need to load all of them into memory. This is the big strengh of LINQ - it just returns an enumerator without actually calculating the result. If you remove the ToList() from the LINQ query, the for-each loop will calculate one result per iteration, print it out, and forget it again.
As an explanatory answer to your comments:
The implementation of Enumerable.Range looks like this:
private static IEnumerable<int> RangeIterator(int start, int count)
{
for (int i = 0; i < count; ++i)
yield return start + i;
}
Implementation of SelectMany:
private static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
{
foreach (TSource source1 in source)
{
foreach (TResult result in selector(source1))
yield return result;
}
}
So for example,
foreach (var item in Enumerable.Range(1, 10).SelectMany(n => Enumerable.Range(1, n)))
{ /* do something */ }
conceptually translates to:
for (int i = 0; i < 10; ++i)
{
var n = 1 + i;
for (int j = 0; j < n; ++j)
{
var result = 1 + j;
/* do something */ // <- processes the current result and forgets it again
}
}
However, when you add ToList:
foreach (var item in Enumerable.Range(1, 10).SelectMany(n => Enumerable.Range(1, n)).ToList())
{ /* do something */ }
this translates to:
var list = new List<int>();
for (int i = 0; i < 10; ++i)
{
var n = 1 + i;
for (int j = 0; j < n; ++j)
{
var item = 1 + j;
list.Add(item); // <- puts the current result in a list
}
}
// list content: 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6...
foreach (var item in list)
{ /* do something */ }
You can play with the index and your selection for each of the for loops, assuming the input is sorted. The first one should be one third of the main array, second loop should be not more than half but starting from the index of the first loop. something like this:
const int totalElements = 1000;
const int target = 1000;
var value = Enumerable.Range(1, totalElements).OrderBy(dd => dd).ToList();
var sw = new Stopwatch();
var result = new List<int[]>();
sw.Start();
for (int i = 0; i < value.Count / 3; i++)
{
var a = value[i];
for (int j = i + 1; j < value.Count / 2; j++)
{
var b = value[j];
for (int k = j + 1; k < value.Count; k++)
{
var c = value[k];
if (a + b + c <= target)
{
var newR = new[] { a, b, c };
result.Add(newR);
}
}
}
}
sw.Stop();
Console.WriteLine("Time Taken: " + sw.Elapsed.TotalSeconds);
Console.WriteLine("Total result count: " + result2.Count);
For 1000 it's taking 4.9 seconds on my lousy machine, where as the LINQ is throwing outofmemory exception. On top of that you have to add some sort of equality comparison in the LINQ otherwise you'll get results like 1+2+3 and 3+2+1, and using the index only you get rid of that.
You can also adjust the range by doing something like this:
for (int i = 0; i < value.Count / 3; i++)
{
var a = value[i];
var index = value.IndexOf(target - a) + 1;
for (int j = i + 1; j < index; j++)
{
var b = value[j];
var remainingIndex = value.IndexOf(target - (a + b)) + 1;
for (int k = j + 1; k < remainingIndex; k++)
{
var c = value[k];
if (a + b + c <= target)
{
var newR = new[] { a, b, c };
result.Add(newR);
}
}
}
}
It might be better if the values are sequential like this example and you can find the index easily. If that's not the case you have to find the index by Binary Search but it'll probably be similar performance anyway.
I suggest to store the numbers in a SortedSet Class. You can the do the following (pseudocode):
For each n in GetViewBetween (1, d)
For each m in GetViewBetween (n+1, d-n)
For each k in GetViewBetween (m+1, d-n-m)
Store or print or callback or return with continuation the Tuple object with n, m, k
Loop
Loop
Loop
I would suggest you a geometry representation: Imagine, that your 'd' is sum of triangle borders. Thuse, you need to find all triangles that fit. In your code you double variants: (a+b+c) = (b+c+a), for example. But if you make 3 loops for each triangle side, then it would be faster.
Related
Given an array of n integers and a number, d, perform left rotations on the array. Then print the updated array as a single line of space-separated integers.
Sample Input:
5 4
1 2 3 4 5
The first line contains two space-separated integers denoting the respective values of n (the number of integers) and d (the number of left rotations you must perform).
The second line contains n space-separated integers describing the respective elements of the array's initial state.
Sample Output:
5 1 2 3 4
static void Main(String[] args)
{
string[] arr_temp = Console.ReadLine().Split(' ');
int n = Int32.Parse(arr_temp[0]);
int d = Int32.Parse(arr_temp[1]);
string[] arr = Console.ReadLine().Split(' ');
string[] ans = new string[n];
for (int i = 0; i < n; ++i)
{
ans[(i + n - d) % n] = arr[i];
}
for (int j = 0; j < n; ++j)
{
Console.Write(ans[j] + " ");
}
}
How to use less memory to solve this problem?
This will use less memory in most cases as the second array is only as big as the shift.
public static void Main(string[] args)
{
int[] n = { 1, 2, 3, 4, 5 };
LeftShiftArray(n, 4);
Console.WriteLine(String.Join(",", n));
}
public static void LeftShiftArray<T>(T[] arr, int shift)
{
shift = shift % arr.Length;
T[] buffer = new T[shift];
Array.Copy(arr, buffer, shift);
Array.Copy(arr, shift, arr, 0, arr.Length - shift);
Array.Copy(buffer, 0, arr, arr.Length - shift, shift);
}
This problem can get a bit tricky but also has a simple solution if one is familiar with Queues and Stacks.
All I have to do is define a Queue (which will contain the given array) and a Stack.
Next, I just have to Push the Dequeued index to the stack and Enqueue the Popped index in the Queue and finally return the Queue.
Sounds confusing? Check the code below:
static int[] rotLeft(int[] a, int d) {
Queue<int> queue = new Queue<int>(a);
Stack<int> stack = new Stack<int>();
while(d > 0)
{
stack.Push(queue.Dequeue());
queue.Enqueue(stack.Pop());
d--;
}
return queue.ToArray();
}
Do you really need to physically move anything? If not, you could just shift the index instead.
Actually you asked 2 questions:
How to efficiently rotate an array?
and
How to use less memory to solve this problem?
Usually efficiency and low memory usage are mutually exclusive. So I'm going to answer your second question, still providing the most efficient implementation under that memory constraint.
The following method can be used for both left (passing negative count) or right (passing positive count) rotation. It uses O(1) space (single element) and O(n * min(d, n - d)) array element copy operations (O(min(d, n - d)) array block copy operations). In the worst case scenario it performs O(n / 2) block copy operations.
The algorithm is utilizing the fact that
rotate_left(n, d) == rotate_right(n, n - d)
Here it is:
public static class Algorithms
{
public static void Rotate<T>(this T[] array, int count)
{
if (array == null || array.Length < 2) return;
count %= array.Length;
if (count == 0) return;
int left = count < 0 ? -count : array.Length + count;
int right = count > 0 ? count : array.Length - count;
if (left <= right)
{
for (int i = 0; i < left; i++)
{
var temp = array[0];
Array.Copy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = temp;
}
}
else
{
for (int i = 0; i < right; i++)
{
var temp = array[array.Length - 1];
Array.Copy(array, 0, array, 1, array.Length - 1);
array[0] = temp;
}
}
}
}
Sample usage like in your example:
var array = Enumerable.Range(1, 5).ToArray(); // { 1, 2, 3, 4, 5 }
array.Rotate(-4); // { 5, 1, 2, 3, 4 }
Isn't using IEnumerables better? Since It won't perform all of those maths, won't allocate that many arrays, etc
public static int[] Rotate(int[] elements, int numberOfRotations)
{
IEnumerable<int> newEnd = elements.Take(numberOfRotations);
IEnumerable<int> newBegin = elements.Skip(numberOfRotations);
return newBegin.Union(newEnd).ToArray();
}
IF you don't actually need to return an array, you can even remove the .ToArray() and return an IEnumerable
Usage:
void Main()
{
int[] n = { 1, 2, 3, 4, 5 };
int d = 4;
int[] rotated = Rotate(n,d);
Console.WriteLine(String.Join(" ", rotated));
}
I have also tried this and below is my approach...
Thank you
public static int[] RotationOfArray(int[] A, int k)
{
if (A == null || A.Length==0)
return null;
int[] result =new int[A.Length];
int arrayLength=A.Length;
int moveBy = k % arrayLength;
for (int i = 0; i < arrayLength; i++)
{
int tmp = i + moveBy;
if (tmp > arrayLength-1)
{
tmp = + (tmp - arrayLength);
}
result[tmp] = A[i];
}
return result;
}
I have tried to used stack and queue in C# to achieve the output as follows:
public int[] rotateArray(int[] A, int rotate)
{
Queue<int> q = new Queue<int>(A);
Stack<int> s;
while (rotate > 0)
{
s = new Stack<int>(q);
int x = s.Pop();
s = new Stack<int>(s);
s.Push(x);
q = new Queue<int>(s);
rotate--;
}
return q.ToArray();
}
I've solve the challange from Hackerrank by following code. Hope it helps.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace ConsoleApp1
{
class ArrayLeftRotationSolver
{
TextWriter mTextWriter;
public ArrayLeftRotationSolver()
{
mTextWriter = new StreamWriter(#System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
}
public void Solve()
{
string[] nd = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nd[0]);
int d = Convert.ToInt32(nd[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] result = rotLeft(a, d);
mTextWriter.WriteLine(string.Join(" ", result));
mTextWriter.Flush();
mTextWriter.Close();
}
private int[] rotLeft(int[] arr, int shift)
{
int n = arr.Length;
shift %= n;
int[] vec = new int[n];
for (int i = 0; i < n; i++)
{
vec[(n + i - shift) % n] = arr[i];
}
return vec;
}
static void Main(string[] args)
{
ArrayLeftRotationSolver solver = new ArrayLeftRotationSolver();
solver.Solve();
}
}
}
Hope this helps.
public static int[] leftrotation(int[] arr, int d)
{
int[] newarr = new int[arr.Length];
var n = arr.Length;
bool isswapped = false;
for (int i = 0; i < n; i++)
{
int index = Math.Abs((i) -d);
if(index == 0)
{
isswapped = true;
}
if (!isswapped)
{
int finalindex = (n) - index;
newarr[finalindex] = arr[i];
}
else
{
newarr[index] = arr[i];
}
}
return newarr;
}
Take the Item at position 0 and add it at the end. remove the item at position 0. repeat n times.
List<int> iList = new List<int>();
private void shift(int n)
{
for (int i = 0; i < n; i++)
{
iList.Add(iList[0]);
iList.RemoveAt(0);
}
}
An old question, but I thought I'd add another possible solution using just one intermediate array (really, 2 if you include the LINQ Take expression). This code rotates to right rather than left, but may be useful nonetheless.
public static Int32[] ArrayRightRotation(Int32[] A, Int32 k)
{
if (A == null)
{
return A;
}
if (!A.Any())
{
return A;
}
if (k % A.Length == 0)
{
return A;
}
if (A.Length == 1)
{
return A;
}
if (A.Distinct().Count() == 1)
{
return A;
}
for (var i = 0; i < k; i++)
{
var intermediateArray = new List<Int32> {A.Last()};
intermediateArray.AddRange(A.Take(A.Length - 1).ToList());
A = intermediateArray.ToArray();
}
return A;
}
O(1) space, O(n) time solution
I think in theory this is as optimal as it gets, since it makes a.Length in-place swaps and 1 temp variable swap per inner loop.
However I suspect O(d) space solutions would be faster in real life due to less code branching (fewer CPU command pipeline resets) and cache locality (mostly sequential access vs in d element steps).
static int[] RotateInplaceLeft(int[] a, int d)
{
var swapCount = 0;
//get canonical/actual d
d = d % a.Length;
if(d < 0) d += a.Length;
if(d == 0) return a;
for (var i = 0; swapCount < a.Length; i++) //we're done after a.Length swaps
{
var dstIdx = i; //we need this becasue of ~this: https://youtu.be/lJ3CD9M3nEQ?t=251
var first = a[i]; //save first element in this group
for (var j = 0; j < a.Length; j++)
{
var srcIdx = (dstIdx + d) % a.Length;
if(srcIdx == i)// circled around
{
a[dstIdx] = first;
swapCount++;
break; //hence we're done with this group
}
a[dstIdx] = a[srcIdx];
dstIdx = srcIdx;
swapCount++;
}
}
return a;
}
If you take a look at constrains you will see that d <= n (number of rotations <= number of elements in array). Because of that this can be solved in 1 line.
static int[] rotLeft(int[] a, int d)
{
return a.Skip(d).Concat(a.Take(d)).ToArray();
}
// using the same same array, and only one temp variable
// shifting everything several times by one
// works, simple, but slow
public static int[] ArrayRotateLeftCyclical(int[] a, int shift)
{
var length = a.Length;
for (int j = 0; j < shift; j++)
{
int t = a[0];
for (int i = 0; i < length; i++)
{
if (i == length - 1)
a[i] = t;
else
a[i] = a[i + 1];
}
}
return a;
}
Let's say if I have a array of integer 'Arr'. To rotate the array 'n' you can do as follows:
static int[] leftRotation(int[] Arr, int n)
{
int tempVariable = 0;
Queue<int> TempQueue = new Queue<int>(a);
for(int i=1;i<=d;i++)
{
tempVariable = TempQueue.Dequeue();
TempQueue.Enqueue(t);
}
return TempQueue.ToArray();`
}
Let me know if any comments. Thanks!
This is my attempt. It is easy, but for some reason it timed out on big chunks of data:
int arrayLength = arr.Length;
int tmpCell = 0;
for (int rotation = 1; rotation <= d; rotation++)
{
for (int i = 0; i < arrayLength; i++)
{
if (arr[i] < arrayElementMinValue || arr[i] > arrayElementMaxValue)
{
throw new ArgumentException($"Array element needs to be between {arrayElementMinValue} and {arrayElementMaxValue}");
}
if (i == 0)
{
tmpCell = arr[0];
arr[0] = arr[1];
}
else if (i == arrayLength - 1)
{
arr[arrayLength - 1] = tmpCell;
}
else
{
arr[i] = arr[i + 1];
}
}
}
what about this?
public static void RotateArrayAndPrint(int[] n, int rotate)
{
for (int i = 1; i <= n.Length; i++)
{
var arrIndex = (i + rotate) > n.Length ? n.Length - (i + rotate) : (i + rotate);
arrIndex = arrIndex < 0 ? arrIndex * -1 : arrIndex;
var output = n[arrIndex-1];
Console.Write(output + " ");
}
}
It's very straight forward answer.
Main thing is how you choose the start index.
public static List<int> rotateLeft(int d, List<int> arr) {
int n = arr.Count;
List<int> t = new List<int>();
int h = d;
for (int j = 0; j < n; j++)
{
if ((j + d) % n == 0)
{
h = 0;
}
t.Add(arr[h]);
h++;
}
return t;
}
using this code, I have successfully submitted to hacker rank problem,
// fast and beautiful method
// reusing the same array
// using small temp array to store replaced values when unavoidable
// a - array, s - shift
public static int[] ArrayRotateLeftWithSmallTempArray(int[] a, int s)
{
var l = a.Length;
var t = new int[s]; // temp array with size s = shift
for (int i = 0; i < l; i++)
{
// save cells which will be replaced by shift
if (i < s)
t[i] = a[i];
if (i + s < l)
a[i] = a[i + s];
else
a[i] = t[i + s - l];
}
return a;
}
https://github.com/sam-klok/ArraysRotation
public static void Rotate(int[] arr, int steps)
{
for (int i = 0; i < steps; i++)
{
int previousValue = arr[arr.Length - 1];
for (int j = 0; j < arr.Length; j++)
{
int currentValue = arr[j];
arr[j] = previousValue;
previousValue = currentValue;
}
}
}
Here is an in-place Rotate implementation of a trick posted by גלעד ברקן in another question. The trick is:
Example, k = 3:
1234567
First reverse in place each of the two sections delineated by n-k:
4321 765
Now reverse the whole array:
5671234
My implementation, based on the Array.Reverse method:
/// <summary>
/// Rotate left for negative k. Rotate right for positive k.
/// </summary>
public static void Rotate<T>(T[] array, int k)
{
ArgumentNullException.ThrowIfNull(array);
k = k % array.Length;
if (k < 0) k += array.Length;
if (k == 0) return;
Debug.Assert(k > 0);
Debug.Assert(k < array.Length);
Array.Reverse(array, 0, array.Length - k);
Array.Reverse(array, array.Length - k, k);
Array.Reverse(array);
}
Live demo.
Output:
Array: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
Rotate(5)
Array: 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7
Rotate(-2)
Array: 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9
I have problem with solution in this example Say Me Please Operations(codeKata):
You have a string with N numbers, every 2 numbers after an operation(?) return next number in this string.
Write a function who return new string with respective operations :
1)addition,
2)subtraction,
3)multiplication,
4)division.
example: for string stringNumbers = "9 4 5 20 25"
your function must return:
"subtraction, multiplication, addition"
because,
9 - 4 = 5 - substraction,
4 * 5 = 20 - multiplication,
5 + 20 = 25 - addition,
My Code:
int x = 0,add = 0, multi = 0, sub = 0, divi = 0, z = 0;
var v = stringNumbers.Split(' ').ToArray();
string s = "";
if (v.Length >= 3)
{
for (int i = 0; i < v.Length; i++)
for (int j = i + 1; j < v.Length; j++)
for (int k = j + 1; k < v.Length; k++)
{
Console.WriteLine(k);
x = int.Parse(v[i]);
z = int.Parse(v[j]);
add = x + z;
multi = x * z;
sub = x - z;
divi = x / z;
if (add == int.Parse(v[k]))
{
s += "addition, ";
}
else if (sub == int.Parse(v[k]))
{
s += "subtraction, ";
}
else if (multi == int.Parse(v[k]))
{
s += "multiplication, ";
}
else if (divi == int.Parse(v[k]))
{
if (int.Parse(v[i]) != 0)
s += "division, ";
}
else
{
break;
}
}
}
else
return "";
s = s.Remove(s.Length - 2, 2);
return s;
I passed sample test, but no this one.I dont know where is issue.
Thanks for help!
This is my third post sorry for the mistakes.
Something like this is a lot simpler and will accomplish the same without the layers of loops you are using:
public static string ProcessOperations(string numbers)
{
string[] numberArray;
string returnValue = string.Empty;
numberArray = numbers.Split(' ');
for (int i = 0; i < numberArray.Length - 2; i++)
{
if (int.TryParse(numberArray[i], out int a) &&
int.TryParse(numberArray[i + 1], out int b) &&
int.TryParse(numberArray[i + 2], out int c))
{
if (a + b == c)
returnValue += "addition, ";
else if (a - b == c)
returnValue += "subtraction, ";
else if (a * b == c)
returnValue += "multiplication, ";
else if (a / b == c)
returnValue += "division, ";
}
}
returnValue = returnValue.TrimEnd(new[] { ',', ' ' });
return returnValue;
}
Testing with the only value you supplied:
?ProcessOperations("9 4 5 20 25");
subtraction, multiplication, addition
This uses a single loop that operates up until the end position - 2. It then parses the items at position i, i + 1, and i + 2 (into a, b, and c). Following that, it checks which arithmatic operation is used to calculate c from a and b.
There's a TrimEnd just before the return to remove any spurious commas and spaces.
Notes: There's no error checking is no arithmatic operation will give the result. The division is integer division so will not work with floating point numbers.
Let's say v.length is 5.
You want to execute the following loops passes:
i=0, j=1, k=2
i=1, j=2, k=3
i=2, j=3, k=4
But that's not what you're doing. You have j and k change semi-independently of i.
i=0, j=1, k=2
i=0, j=1, k=3
i=0, j=1, k=4
i=0, j=2, k=3
i=0, j=2, k=4
i=0, j=3, k=4
i=1, j=2, k=3
i=1, j=2, k=4
i=1, j=3, k=4
i=2, j=3, k=4
To get the desired outcome, you should only have one loop. You can derive the other values from the loop variable.
You could derive j and k from i as follows:
for (int i = 0; i < v.Length - 2; ++i) {
int j = i + 1;
int k = i + 2;
...
}
Or you could could derive i and j from k as follows:
for (int k = 2; k < v.Length; ++k) {
int i = k - 2;
int j = k - 1;
...
}
Either way, the if (v.Length >= 3) check is useless. The for already performs an equivalent check. I also recommend parsing the elements of v once each (before the main loop) rather than parsing them repeatedly.
Hi all i am solving a problem that says :
Given a set S = {1, 2, 3, ... N}. Find two integers A and B where (A < B), from set S such that the value of A&B, where '&' is bitwise AND, is the maximum possible number less than a given integer K.
Sample Input1 : 5 2, (where n = 5, k = 2) => Output : 1,
Sample Input2 : 8 5, (where n = 8, k = 5) => Output : 4
I wrote the code and this seems to be working fine. But I am looking for more optimized solution. I am currently using two while loops, which I am not sure could be reduced to one single while or for loop. Below is my function :
static void Main(String[] args)
{
string[] tokens_n = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(tokens_n[0]);
int k = Convert.ToInt32(tokens_n[1]);
int i = 1, maxDiff = 0;
while (i < n)
{
int j = i + 1;
while (j <= n)
{
int diff = i & j;
if (diff < k)
{
if (diff > maxDiff)
{
maxDiff = diff;
}
}
j++;
}
i++;
}
Console.WriteLine(maxDiff);
}
I found a solution here but that problem seems to be about finding maximum difference in two arbitrary numbers in a list, whereas i need to loop for all the combinations to find the Bitwise AND value and then compare it.
int maxAnd = INT_MIN;
for(int i = 1; i < k; i++) {
for(int j = i + 1; j <= n; j++) {
int currentAnd = i & j;
if (currentAnd > maxAnd)
maxAnd = currentAnd;
}
}
cout << maxAnd << endl;
This might be not more optimized from efficiency perspective, but somewhat more readable.
var list = new[] {1, 2, 3, 4, 5};
var k = 2;
var combinations =
from item1 in list
from item2 in list
where
(item1 < item2) &&
(item1 & item2) < k
orderby item1 & item2 descending
select new {item1, item2};
Console
.WriteLine(combinations.First());
Turns out the solution can be drastically simplified (in terms of what we check, rather than readability). So, rather than providing ways to improve the code - I can offer a new solution to the original requirement
void Main()
{
var n = 2;
var k = 2;
//Best solution is for k - 1 (that is, B = k - 1, and then we check all possible As)
for (var i = k - 1; i > 0; i--)
{
int j;
int index = 1;
//The only possible A is when
//1. j <= n
//2. j contains all the same bits as i since we identify that `i` is the possible solution,
// and we are using bit-wise AND, we
//So, here were looping while the number is the same as i, continually flipping bits on
//Since we're shifting bits in, we can assume the first value != i is a solution, as we only care about j becoming too large
while ((j = (i | index)) == i && j <= n)
index = (index << 1) | 1;
// If j <= n, and it contains all the bits of i, and i <= k - 1, then we have a solution
if (j <= n)
{
Console.WriteLine($"i = {i}, j = {j}, Solution = {i & j}");
return;
}
}
if (n < 2 || k < 1)
Console.WriteLine("No solution");
else
Console.WriteLine($"i = 1, j = 2, Solution = 0");
}
This approach lets us solve inputs such as:
var n = 24827492;
var k = 2384972;
Almost as quickly as we can for low values.
I wrote an algorithm to find length of longest increasing sequence in an array.
The algorithm has an array m which will contain the sequence but in some conditions, it doesn't contain the exact sequence. So in such case, I record the index and value which needs to be changed.
This algorithm is n(log n)
Now, to find the actual sequence, I loop through the array m and replace the value recorded in another array. Will my algorithm now still have the complexity if n(log n) ?
Below is the code in C#:
int[] b = { 1, 8, 5, 3, 7, 2, 9 };
int k = 1;
int i = 1;
int N = b.Length;
List<int> m = new List<int>();
int[] lup = new int[b.Length];
m.Add(0);
m.Add(b[0]);
lup[0] = 0;
while (i < N)
{
if (b[i] >= m[k])
{
k = k + 1;
m.Add(b[i]);
}
else
{
if (b[i] < m[1])
{
m[1] = b[i];
}
else
{
int j;
j = Binary_Search(m, b[i], m.Count - 1);
//if the item to be replaced was not the last element, record it
if (m[j] > b[i] && j != k)
{
lup[j] = m[j];
}
m[j] = b[i];
}
}
i = i + 1;
}
Console.WriteLine("The Input Sequence is : " + string.Join("\t", b));
Console.WriteLine("Length of Longest Up Sequence is : " + k.ToString());
List<int> result = new List<int>();
// create result based on m and lup
//DOES THIS LOOP EFFECT PERFORMANCE??
for(int x = 1; x < m.Count; x++)
{
if (lup[x] == 0)
{
result.Add(m[x]);
}
else
{
result.Add(lup[x]);
}
}
Your intuition is correct. Adding this loop is n*(log(n)+1) so it's still n*log(n).
How could I iterate through each combination of two elements in a HashSet once?
foreach (var elt1 in hashSet) {
foreach (var elt2 in hashSet) {
...
}
}
This would iterate the combinations of two but would iterate each combination TWICE. I'd like to do it once.
I think it's easy to do in Python. Is there any way to do it in C#?
Sample:
input hashSet: { 1, 2, 3, 4 }
iterate through: (1,2), (1,3), (1,4), (2,3), (2,4), (3,4)
There is no built-in method to do this in C#. Since HashSet<T> is not indexed *, you cannot do it with two loops either.
If this is a one-time deal, the simplest solution is to make two nested loops on the results of ToList() or ToArray(), like this:
var items = hashSet.ToList();
for (var i = 0 ; i != items.Count ; i++) {
var a = items[i];
for (var j = i+1 ; j != items.Count ; j++) {
var b = items[i];
}
}
If you are looking for something reusable, make an extension method on IEnumerable<T> that produces all pairs:
static IEnumerable<Tuple<T,T>> MakeAllPairs<T>(this IEnumerable<T> data) {
var items = data.ToList();
for (var i = 0 ; i != items.Count ; i++) {
var a = items[i];
for (var j = i+1 ; j != items.Count ; j++) {
var b = items[i];
yield return Tuple.Create(a, b);
}
}
}
Now you can iterate your pairs in a single loop:
foreach (var pair in hashSet.MakeAllPairs()) {
Console.WriteLine("{0} {1}", pair.Item1, pair.Item2);
}
* Technically, you could use ElementAt<T>(int) extension from Enumerable, but that would be very slow on large sets.
I misread the question originally. This is a new answer
This is what you want (if working index-based is an option). Explanation is below
string[] myArray = GetArray();
for (int i = 0; i < myArray.Length - 1; i++)
{
var element1 = myArray[i];
for(int j = i + 1; j < myArray.Length; j++)
{
var element2 = myArray[j];
Console.WriteLine("{0} {1}", element1, element2);
}
}
Explanation: Assume the following array:
Apple, Banana, Coconut, Zucchini
When i = 0 (Apple), j will be 1 (Banana), then 2 (Coconut), then 3 (Zucchini)
When i = 1 (Banana), j will be 2 (Coconut), then 3 (Zucchini).
And so on...
Basically, you are making sure element j is always ahead of element i. This means you've effectively removed half of the possibilities (where j would be before i), which is what you wanted.
Note: if you want to use sets of equal elements (Apple + Apple), the second for loop needs to change to:
for(int j = i; j < myArray.Length; j++) //notice j = i instead of i + 1
You can work with indexes directly on the HashSet.
Try this:
int int1, int2;
HashSet<int> hs = new HashSet<int>();
hs.Add(1);
hs.Add(2);
hs.Add(3);
for (int i = 0; i < hs.Count-1; i++) {
int1 = hs.ElementAt<int>(i);
for (int j = i + 1; j < hs.Count; j++)
{
int2 = hs.ElementAt<int>(j);
}
}
To return all permutations (viz (1,2) and (2,1)), you can cross join the set with itself using SelectMany:
var hashSet = new HashSet<int>{1,2,3,4,5,6,7,8};
foreach (var elt in hashSet.SelectMany(
x => hashSet.Select(y => new Tuple<int, int>(x, y))))
{
Debug.WriteLine("{0}-{1}", elt.Item1, elt.Item2);
}
Edit: If you just want the unique combinations (viz (1,2) but not (2,1)) then just add a filter only larger values during the cross join:
var hashSet = new HashSet<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
foreach (var elt in hashSet.SelectMany(
x => hashSet.Where(y => y >= x)
.Select(y => new Tuple<int, int>(x, y))))
{
Debug.WriteLine("{0}-{1}", elt.Item1, elt.Item2);
}