Place all distinct elements of the array to the left in C# - c#

I'm trying to write a programme that places all distinct elements of an array to the left of the same array, and all other (non-distinct) elements right after in whatever order. The time complexity must be O(n log n), i.e. using sorting and no additional array must be created. I made an attempt to print the distinct elements with the following code:
using System;
using System.Diagnostics;
public class Program
{
public static void Main()
{
int []arr = {1, 1, 6, 5, 4, 3, 4, 6, 1, 7, 2, 1, 4, 9};
allDistinct(arr);
}
public static void allDistinct(int[] x)
{
int n = x.Length;
Trace.Assert(n>0);
Array.Sort(x); //O(n log n)
for (int i = 0; i < n; i++)
{
// Move the index ahead while
// there are duplicates
while (i < n - 1 && x[i] == x[i + 1])
i++;
}
Console.WriteLine(x[i]);
}
}
However, I'd like my function to be of the form
public static int[] allDistinct(int[] x)
and then use the auxiliary function to print the array in the Main()
printArray(allDistinct(arr));
where
public static void printArray(int[] array)
{
for(int i=0; i<array.Length; ++i)
{
Console.Write("" + array[i] + " ");
}
Console.WriteLine("");
}
I made an attempt using the swap function, but I didn't succeed to get what I wanted, i.e. given the array
1 1 6 5 4 3 4 6 1 7 2 1 4 9
my output should be
1 2 3 4 5 6 7 9 + (duble elements in whatever order, e.g. 1 1 1 4 4 6)
thanks for your advise

I got a fully working example:
using System.IO;
using System;
class Program
{
static void Main()
{
int[] array = {1, 1, 6, 5, 4, 3, 4, 6, 1, 7, 2, 1, 4, 9};
allDistinct(array);
}
static int[] allDistinct(int[] array)
{
Array.Sort(array);
printArray(array); // first step monitoring
int n = array.Length;
// iterate through array
for(int i=0;i<n-1;i++)
{
// bubble push duplicates to the back
while(array[i] == array[i+1])
{
for(int j=i+1;j<n-1;j++)
{
array[j] = array[j+1];
}
array[n-1] = array[i];
n--;
}
printArray(array); // loop steps monitoring
}
return array;
}
static void printArray(int[] array)
{
Console.WriteLine(string.Join(" ", array));
}
}
This yields this output:
1 1 1 1 2 3 4 4 4 5 6 6 7 9
1 2 3 4 4 4 5 6 6 7 9 1 1 1
1 2 3 4 4 4 5 6 6 7 9 1 1 1
1 2 3 4 4 4 5 6 6 7 9 1 1 1
1 2 3 4 5 6 6 7 9 4 4 1 1 1
1 2 3 4 5 6 6 7 9 4 4 1 1 1
1 2 3 4 5 6 7 9 6 4 4 1 1 1
1 2 3 4 5 6 7 9 6 4 4 1 1 1
Note that this will change the order of the original array and return it, as arrays can't be passed by value in C#.
Edit:
About the bubble-push, you could instead count the number of duplicates and push harder:
static int[] allDistinct2(int[] array)
{
Array.Sort(array);
printArray(array);
int n = array.Length;
for(int i=0;i<n;i++)
{
int countDup = 0;
int iValue = array[i];
// Count the number of duplicates
for(int j=i+1;j<n && array[j] == iValue;j++)
{
countDup++;
}
Console.WriteLine("// " + countDup + " time(s) the value " + iValue);
if(countDup > 0)
{
for(int j=i+1;j<n-countDup;j++)
{
array[j] = array[j+countDup];
}
for(int j=n-countDup;j<n;j++)
{
array[j] = iValue;
}
}
n-=countDup;
printArray(array);
}
return array;
}
This yields:
1 1 1 1 2 3 4 4 4 5 6 6 7 9
// 3 time(s) the value 1
1 2 3 4 4 4 5 6 6 7 9 1 1 1
// 0 time(s) the value 2
1 2 3 4 4 4 5 6 6 7 9 1 1 1
// 0 time(s) the value 3
1 2 3 4 4 4 5 6 6 7 9 1 1 1
// 2 time(s) the value 4
1 2 3 4 5 6 6 7 9 4 4 1 1 1
// 0 time(s) the value 5
1 2 3 4 5 6 6 7 9 4 4 1 1 1
// 1 time(s) the value 6
1 2 3 4 5 6 7 9 6 4 4 1 1 1
// 0 time(s) the value 7
1 2 3 4 5 6 7 9 6 4 4 1 1 1
// 0 time(s) the value 9
1 2 3 4 5 6 7 9 6 4 4 1 1 1
Updated coding-ground link

places all distinct elements of an array to the left of the same array
I don't see any requirement for the resultset to be sorted. The only requirement is that the elements be arranged so that all duplicates come later than all distinct values.
If the resultset need not be sorted, there is no reason to call Array.Sort() (which is sort of cheating really); we can write our own solution that collates the numbers ourselves.
This algorithm flips the problem by starting at the end and looking for duplicates. When one is found, it is swapped into place, and the upper boundary of the array is moved downward. If the element at the end has no duplicates, we swap it with first element, and adjust the lower boundary upward so we don't look at it again.
public class Program
{
public static int[] DistinctFirst(int[] arr)
{
var lbound = 0;
var ubound = arr.GetUpperBound(0);
var i = ubound;
while ( i>lbound )
{
var k = i;
for (int j=i-1; j>=lbound; j--)
{
if (arr[j] == arr[i])
{
Swap(ref arr[j], ref arr[i-1]);
i--;
}
}
if (k == i)
{
Swap(ref arr[i], ref arr[lbound]);
lbound++;
}
else
{
i--;
}
}
return arr;
}
public static void Swap(ref int a, ref int b)
{
int c = a;
a = b;
b = c;
}
public static void Main()
{
int[] arr = {1, 1, 6, 5, 4, 3, 4, 6, 1, 7, 2, 1, 4, 9};
int[] result = DistinctFirst(arr);
foreach (var i in result)
{
Console.WriteLine(i);
}
}
}
Output:
9
7
2
3
5
4
4
4
6
6
1
1
1
1
Code on DotNetFiddle

You can easily solve this problem using O(N) extra space and O(nlogn) time.
here is my python solution : the idea behind my solution is first sort the arr also keep distinct element in map or dict now you just need to apply a logic which you can easily find in gfg shifting all zero one side like wise here we have to shift distinct element one side:
arr = [1 ,1, 6, 5 ,4, 3, 4, 6, 1, 7, 2, 1, 4, 9]``
mp={}
for i in range(len(arr)):
if arr[i] not in mp:
mp[arr[i]]=1
arr.sort()
j = 0
for i in range(len(arr)):
if arr[i] in mp and mp[arr[i]]!=0:
mp[arr[i]]-=1
arr[i],arr[j]=arr[j],arr[i]
j+=1
print(arr)

Related

C# Soft Number By Difference From Input

I have the following code. Please help me get my desired output. I have a list of numbers then I have input value which is 4. I want that my list will be sorted based on 0 difference first then the rest will be ascending. For example in my list there are 4s. My input is 4 so I want to sort those numbers where number item - input value=0 (4-4=0).
C#
static void Main(string[] args)
{
var numbers = new List<int> { 1, 2, 3, 4, 4, 5, 6, 7, 4, 8, 1, 4 };
var sortedNumbers = numbers.OrderBy(x => x - 4 == 0);
foreach (var item in sortedNumbers)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
OUTPUT
1
2
3
5
6
7
8
1
4
4
4
4
Desired Output
4
4
4
4
1
1
2
3
5
6
7
8
Instead of numbers.OrderBy(x => x - 4 == 0) you need to use OrderByDescending, because true is "more" than false and you want them first. You also want to sort the rest by their value:
var sortedNumbers = numbers.OrderByDescending(x => x == 4).ThenBy(x => x);
If you can't remember if you need to use OrderBy or OrderByDescending use:
var sortedNumbers = numbers.OrderBy(x => x == 4 ? 0 : 1).ThenBy(x => x);
You can achieve your desired output by using a ternary expression inside the OrderBy lambda :
static void Main(string[] args)
{
var numbers = new List<int> { 1, 2, 3, 4, 4, 5, 6, 7, 4, 8, 1, 4 };
var sortedNumbers = numbers.OrderBy(x => x==4? int.MinValue: x);
foreach (var item in sortedNumbers)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
output :
4
4
4
4
1
1
2
3
5
6
7
8
Edit : in case you have zero or negative number in your list, your number will be order as follow : first, exact match, then ascending. For example : { -1, 0, 0, -12, 1, 2, 3, 4, 4, 5, 6, 7, 4, 8, 1, 4 }
the result will be the following :
4
4
4
4
-12
-1
0
0
1
1
2
3
5
6
7
8

Copy a small 2d array into a larger 2d array that has a buffer to the left and top

I want to place the contents of a 2d array of ints into a larger 2d array of ints which has a buffer of 1 column to the left and 2 rows at the top. The width and height of both arrays can vary, but the content will always be large enough to exactly fit the larger array.
larger array: (9 is just a filler value)
9 9 9 9 9 9 9
9 9 9 9 9 9 9
9 0 0 0 0 0 0
9 0 0 0 0 0 0
9 0 0 0 0 0 0
9 0 0 0 0 0 0
content to copy: (will be full of random numbers)
3 1 2 3 3 5
6 7 5 5 6 5
2 1 3 5 2 2
1 3 5 2 2 5
expected output:
9 9 9 9 9 9 9
9 9 9 9 9 9 9
9 3 1 2 3 3 5
9 6 7 5 5 6 5
9 2 1 3 5 2 2
9 1 3 5 2 2 5
int[,] contentToCopy = { //5x6
{0,0,0,0,0,0},
{0,1,1,1,1,0},
{0,1,1,1,1,0},
{0,1,1,1,1,0},
{0,0,0,0,0,0}
};
int[,] arr = new int[7, 7];
for (int x = 0; x < contentToCopy.GetLength(0); x++)
{
for (int y = 0; y < contentToCopy.GetLength(1); y++)
{
arr[x + 2, y + 1] = contentToCopy[x, y];
}
}

Optimum Cutting of Rod with Length n into any of 3 possibly 4 sizes

I am not sure if I am in the correct area on stack - so my apologies first ..
I need to know how I can calculate all possible combinations (for 3 different fixed lengths) that can fit into a Rod of n length.
So for example if I have 3 fixed lengths of 8, 10, 12 and a Rod of variable Length n say 50'; I want to know all the possible cuts that I can make.
Using Microsoft Solver Foundation:
const int rodLength = 50;
const int lengthA = 8, lengthB = 10, lengthC = 12;
var solver = SolverContext.GetContext();
var model = solver.CreateModel();
var decisionA = new Decision(Domain.IntegerNonnegative, "A");
model.AddDecision(decisionA);
var decisionB = new Decision(Domain.IntegerNonnegative, "B");
model.AddDecision(decisionB);
var decisionC = new Decision(Domain.IntegerNonnegative, "C");
model.AddDecision(decisionC);
model.AddGoal("Goal", GoalKind.Minimize,
rodLength - (decisionA * lengthA) - (decisionB * lengthB) - (decisionC * lengthC));
int maxItems = (rodLength / new [] { lengthA, lengthB, lengthC }.Min());
model.AddConstraint("MaxItems", decisionA + decisionB + decisionC < maxItems);
var solution = solver.Solve();
Console.WriteLine("A " + decisionA.GetDouble());
Console.WriteLine("B " + decisionB.GetDouble());
Console.WriteLine("C " + decisionC.GetDouble());
where we trying to minimize the difference between the rod length and the sum of the items constraining the number of items (in your case max 50 / 8 = 6 items).
Here is sample of code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication104
{
class Program
{
static void Main(string[] args)
{
string max = "111111";
int size = 50;
List<List<int>> numbers = CountModThree(max,size);
Print(numbers);
Console.ReadLine();
}
static List<List<int>> CountModThree(string max,int size)
{
List<List<int>> results = new List<List<int>>();
List<int> newMod3 = new List<int>() {0};
while(true)
{
int length = newMod3.Select(x => x == 0 ? 8 : x == 1 ? 10 : 12).Sum();
if (length <= size) results.Add(newMod3);
if (string.Join("", newMod3) == max) break;
newMod3 = AddOne(newMod3);
}
return results;
}
static List<int> AddOne(List<int> number)
{
List<int> newNumber = new List<int>();
newNumber.AddRange(number);
int carry = 1;
for (int i = number.Count - 1; i >= 0; i--)
{
int digit = newNumber[i] + carry;
if (digit == 3)
{
newNumber[i] = 0;
carry = 1;
}
else
{
newNumber[i] = digit;
carry = 0;
break;
}
}
if (carry == 1) newNumber.Insert(0, 0);
return newNumber;
}
static void Print(List<List<int>> numbers)
{
foreach(List<int> number in numbers)
{
Console.WriteLine("string : '{0}', Total Length : '{1}, Number 8ft sections : '{2}', Number 10ft sections : '{3}', Number 12ft sections : '{4}'",
string.Join("", number),
number.Select(x => x == 0 ? 8 : x == 1 ? 10 : 12).Sum(),
number.Where(x => x == 0).Count(),
number.Where(x => x == 1).Count(),
number.Where(x => x == 2).Count()
);
}
}
}
}
You want to get all partitions of n into predefined integer pieces. Simple approach is using recursion.
Python code gives all possible solutions, ignoring summands order due to last index usage. So 8 8 8 8 8 10 and 8 8 10 8 8 8 variants are considered the same. If you need to distinguish them, just remove last argument and start loop from 0.
def solution(sum, lst, last, sol):
if sum == 0:
print(sol)
return
for i in range(last, len(lst)):
if lst[i] <= sum:
solution(sum - lst[i], lst, i, sol + " " + str(lst[i]))
return
solution(50, [8,10,12], 0, "")
8 8 8 8 8 10
8 8 10 12 12
8 10 10 10 12
10 10 10 10 10
If you need also solutions with smaller overall length (if n is unreachable) - remember solutions with small rest of sum, then use ones with the smallest rest. Quick-made example:
dict = [[] for i in range(10)]
def solution(sum, lst, last, sol):
if sum == 0:
print(sol)
return
if sum < 10:
dict[sum].append(sol)
for i in range(last, len(lst)):
if lst[i] <= sum:
solution(sum - lst[i], lst, i, sol + " " + str(lst[i]))
return
solution(50, [5, 13 , 21], 0, "")
for i in range(1, len(dict)):
if len(dict[i]) > 0:
print(dict[i])
break
5 5 5 5 5 5 5 5 5 5 #exact
[' 5 5 5 13 21', ' 5 5 13 13 13'] #inexact but close
There is also non-recursive method: make table A[0..n] and fill it with items (note that table might be huge!)
def tablecuts(sum, lst):
cuts = [[] for i in range(sum+1)]
cuts[0].append('*')
for item in lst:
for i in range(0, sum - item + 1):
if len(cuts[i]) > 0:
for j in cuts[i]:
cuts[i+item].append(j+" " + str(item))
for i in range(len(cuts)):
print(i, cuts[i])
tablecuts(13, [2,5,7])
0 ['*']
1 []
2 ['* 2']
3 []
4 ['* 2 2']
5 ['* 5']
6 ['* 2 2 2']
7 ['* 2 5', '* 7']
8 ['* 2 2 2 2']
9 ['* 2 2 5', '* 2 7']
10 ['* 2 2 2 2 2', '* 5 5']
11 ['* 2 2 2 5', '* 2 2 7']
12 ['* 2 2 2 2 2 2', '* 2 5 5', '* 5 7']
13 ['* 2 2 2 2 5', '* 2 2 2 7']

How to transpose a 2D array with random length on each row?

I have a 2D array
var arr= new List<double[]>();
content:
1 2 3
4 3 7
7 8 9 10
11
I want to transpose it like a matrix to:
1 4 7 11
2 3 8
3 7 9
10
then move 10 to first like :
1 4 7 11
2 3 8
3 7 9
10
How do I do this in a efficient way?
Since we have to loop through all arrays 'vertically' anyway, I seriously doubt that it can be much more efficient then nested for's
You could find a longest array and use Linq .Where and .Select with overload that accepts index:
var arr = new List<double[]>();
arr.Add(new double[] { 1, 2, 3});
arr.Add(new double[] { 4, 3, 7 });
arr.Add(new double[] { 7, 8, 9, 10 });
arr.Add(new double[] { 11 });
var longestArr = arr.OrderByDescending(a => a.Length).First();
var result = longestArr.Select((_, i) => arr.Where(a => a.Length > i).Select(a => a[i]).ToArray()).ToList();
foreach (var _ in result)
{
foreach (var element in _)
{
Console.Write(element + " ");
}
Console.WriteLine();
}
Or do the same with good old for loop:
var longestArrLength = arr.Max(a => a.Length);
var result2 = new List<double[]>(arr.Count);
for (int i = 0; i < longestArrLength; i++)
{
result2.Add(arr.Where(a => a.Length > i).Select(a => a[i]).ToArray());
}
Output for both is:
1 4 7 11
2 3 8
3 7 9
10
Here is a DotNetFiddle

reorder List starting at given position

List:
List<int> list1 = new List<int>(){ 0, 1, 2, 3, 4, 5, 6 };
let's say we want to reorder it. The beginning should be at number "2"
// 2,3,4,5,6,0,1
or at number 5
// 5,6,0,1,2,3,4
how do you do it with C#?
the reason: Imagine that you have an index of a given number in the List (number 3, index 3). You want to get the second number from the right - it'll be 5.
Unfortunately, if the starting number is at the end of the List (numbers 5 and 6) - out of range exception will be thrown, because there's no 7 and 8!
The idea is to reorder the List!
We enter Nr. 5 - we get 0 (5,6,0).
We enter Nr. 6 - we get 1 (6,0,1), etc.
or maybe there is some other (read - better) way to solve this problem?
The better way to do it is to use the mod operator %. This gives you the remainder when you divide an int by another int. The way this works is something like this:
int nextIndex = (currentIndex + offset) % length;
So, if your current index is 5, your offset is 2 and your length is 6 then:
5 + 2 = 7
7 / 6 = 1 remainder 1 (or 7 mod 6 = 1)
therefore nextIndex = 1
A little Linq can do this pretty easily:
List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 });
var numToStart = 4;
//reorderedList will be {4,5,6,0,1,2,3}
var reorderedList = list1.Skip(numToStart).Concat(list1.Take(numToStart));
You don't need to reorder the list. You could get the number with the following function:
int GetNumber(List<int> list, int fromValue, int index)
{
return list[(list.IndexOf(fromValue) + index) % list.Count()];
}
You could call the function like this:
List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 });
int number = GetNumber(list1, 5, 2); // number = 0

Categories

Resources