Related
Task - Implement the Shift method using for statements, array indices and Array.Copy method for copying array elements. The method has two arguments. The source arguments has the array of integers to shift and return. Do not create a new array. The iterations argument has the array of integers. Each value in the iterations array is a shift instruction that tells the number of shift iterations. The odd elements (an element with odd index) tells the number of right shift iterations. The even elements (an element with even index or zero index) tells the number of left shift iterations. The first and the last elements in the source array should be wrapped to the other side of the array.
I have a problem with copying the elements more than one times.
My solution so far:
public static int[] Shift(int[]? source, int[]? iterations)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (iterations == null)
{
throw new ArgumentNullException(nameof(iterations));
}
if (source == Array.Empty<int>())
{
throw new ArgumentNullException(nameof(source));
}
foreach (var currentIteration in iterations)
{
if (currentIteration == 0)
{
break;
}
else if (currentIteration % 2 == 0)
{
for (int i = 0; i < currentIteration; i++)
{
var temp = source[0];
Array.Copy(source, 0, source, 1, source.Length - 1);
source[source.Length - 1] = temp;
}
}
else
{
for (int i = 0; i < currentIteration; i++)
{
var temp = source[source.Length - 1];
Array.Copy(source, 1, source, 0, source.Length - 1);
source[0] = temp;
}
}
}
return source;
}
There are unit tests, which can be helpful in finding a solution.
[TestCase(new[] { 1 }, new[] { 2, 2 }, ExpectedResult = new[] { 1 })]
[TestCase(new[] { 1 }, new[] { 2, 3 }, ExpectedResult = new[] { 1 })]
[TestCase(new[] { 1 }, new[] { 2, 4 }, ExpectedResult = new[] { 1 })]
[TestCase(new[] { 1, 2 }, new int[] { }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 0 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 1 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 2 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 3 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 4 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 0, 1 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 0, 2 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 0, 3 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 0, 4 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 1, 1 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 1, 2 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 1, 3 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 1, 4 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 2, 1 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 2, 2 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 2, 3 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 2, 4 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 3, 1 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 3, 2 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 3, 3 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 3, 4 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 4, 1 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 4, 2 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 4, 3 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 4, 4 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new int[] { }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 0 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 0, 0 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 0, 0, 0 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1 }, ExpectedResult = new[] { 2, 3, 4, 5, 1 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 0, 1 }, ExpectedResult = new[] { 5, 1, 2, 3, 4 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 1 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 1, 1 }, ExpectedResult = new[] { 2, 3, 4, 5, 1 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 1, 1, 1 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 2 }, ExpectedResult = new[] { 5, 1, 2, 3, 4 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 2, 1 }, ExpectedResult = new[] { 2, 3, 4, 5, 1 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 2, 3 }, ExpectedResult = new[] { 3, 4, 5, 1, 2 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 2, 3, 4 }, ExpectedResult = new[] { 4, 5, 1, 2, 3 })]
public int[] Shift_SourceAndIterationsAreNotNull_ReturnsArrayWithShiftedElements(int[] source, int[] iterations)
{
return Shifter.Shift(source, iterations);
}
I would be grateful, if someone can help me, or explain how to find the best code for this.
Based on the discription the direction of movement is indicated via iterations elemente index NOT value as you made in your original code.
you made some logical errors within your original method:
if odd index you should move right(based on description) not left.
if even index you should move left(based on description) not right.
The method below have comments regarding lines you have issues in,
hopefully it would achieve your task.
public static int[] Shift(int[]? source, int[]? iterations)
{
if (source == null || iterations == null || source == Array.Empty<int>())
throw new ArgumentNullException(nameof(source));
// use for loop instead of foreach due to ease access of index of each element
// i => iteration index
for (int i = 0; i < iterations.Length; i++)
{
//----------------------------------------
// you have to check the state(odd or even) of each iteration index and not the iteration value itself.
//----------------------------------------
// if no movments to do contineu to next loop iteration
if (iterations[i] == 0)
continue;
// if even index
if (i % 2 == 0)
{
for (int j = 0; j < iterations[i]; j++)
{
var temp = source[0];
// Array.Copy(source, 0, source, 1, source.Length - 1);
// Note you passed reversed arguments
Array.Copy(source, 1, source, 0, source.Length - 1);
source[source.Length - 1] = temp;
}
}
// if odd index
else
{
for (int j = 0; j < iterations[i]; j++)
{
var temp = source[source.Length - 1];
// Array.Copy(source, 1, source, 0, source.Length - 1);
// Note you passed reversed arguments
Array.Copy(source, 0, source, 1, source.Length - 1);
source[0] = temp;
}
}
}
return source;
}
}
I am trying to solve the concept of filling every item in a list until every item has reached a ceiling. Once every item has reached a ceiling/limit any remaining excess values is then distributed once more starting from the first item of the list. Examples after the current breakdown.
I believe I have a solution for the first component of the problem, distributing values - however I am unsure of the solution to dealing with excess values.
A detailed example:
I have a list of boxes (10 boxes) and a value of 33 products, I
want to distribute the products one at a time across these boxes until
a limit ceiling for each box is set (5 products). Every box must be
filled to 5 before I pick my first box again and start one at a time
to add the remaining excess.
In the table below, init is the pre-existing values stored in each box. The next columns show distribution across the boxes for values of 25,33, and finally 40. In 40 you can see more clearly how priority of filling in the emptiest boxes preceeds eventually filling every other box in.
init
25
33
40
2
4
5
6
1
3
5
6
2
4
5
5
0
2
4
5
-1
1
3
5
2
4
5
5
3
5
5
5
0
2
4
5
2
4
5
5
1
3
4
5
My current logic is this:
class Box
{
public float amount;
}
public static void Init()
{
// Create a list of boxes.
List<Box> boxes = new List<Box>
{
// Add boxes to the list.
new Box() { amount = 2 },
new Box() { amount = 1 },
new Box() { amount = 2 },
new Box() { amount = 0 },
new Box() { amount = -1 },
new Box() { amount = 2 },
new Box() { amount = 3 },
new Box() { amount = 0 },
new Box() { amount = 2 },
new Box() { amount = 1 }
};
Distribute(boxes, 25, 2);
}
static void Distribute(List<Box> boxes, float totalValue, float maxDistribution)
{
float ceiling = 5; //The "soft limit" for each box.
List<Box> currentBoxes = boxes;
List<Box> criticalBoxes = new List<Box>();
int distribution = (int)(totalValue / maxDistribution); //amount of times needed for even distribution.
int currentBoxIndex = 0;
for (int i = 0; i < distribution; i++)
{
//If we have room, add distribution, else move to a "at capacity list"
if (currentBoxes[currentBoxIndex].amount + maxDistribution < ceiling)
{
currentBoxes[currentBoxIndex].amount += maxDistribution; //Distribute the maximum allowed per loop
} else
{
criticalBoxes.Add(currentBoxes[currentBoxIndex]);
currentBoxes.RemoveAt(currentBoxIndex);
}
//Status of loop.
if(currentBoxIndex == currentBoxes.Count)
{
currentBoxIndex = 0;
} else
{
currentBoxIndex++;
}
}
}
It seems binary; either the amount you have to distribute will completely fill boxes (with/out overspill) or it won't. If it will, then start from them all full and distribute the overspill, otherwise, distribute to a cap
int distrib = 40;
int cap = 5;
int space = boxes.Sum(b => cap - b.Amount);
int overspill = distrib - space;
if(overspill >= 0){
boxes.ForEach(b => b.Amount = cap + overspill / boxes.Count);
distrib = overspill % boxes.Count;
cap = int.MaxValue;
}
for(int x= 0; x < distrib;){
var b = boxes[x%boxes.Count];
if(b.Amount >= cap)
continue;
boxes[x%boxes.Count].Amount++;
x++;
}
If instead you want a logic of prioritizing the emptiest boxes, it gets simpler with MinBy (.net6 or MoreLinq)
int distrib = 25;
while(distrib-- > 0)
boxes.MinBy(b => b.Amount).Amount++;
In older .net that's boxes.First(b => b.Amount == boxes.Min(b2 => b2.Amount) ).Amount++;
There's plenty of scope for optimizing and tweaking this, but how much it's worth the effort depends on how much of a hot spot it is
I think this is close:
List<Box> boxes = new List<Box>
{
// Add boxes to the list.
new Box() { amount = 2 },
new Box() { amount = 1 },
new Box() { amount = 2 },
new Box() { amount = 0 },
new Box() { amount = -1 },
new Box() { amount = 2 },
new Box() { amount = 3 },
new Box() { amount = 0 },
new Box() { amount = 2 },
new Box() { amount = 1 }
};
Console.WriteLine(String.Join(", ", boxes.Select(b => b.amount)));
var sorted = boxes.OrderBy(b => b.amount < 5f ? int.MinValue : b.amount).ToList();
while (boxes.Sum(b => b.amount) < 52f)
{
var box = sorted.First();
sorted.RemoveAt(0);
box.amount += 1.0f;
sorted = sorted.Append(box).OrderBy(b => b.amount < 5f ? int.MinValue : b.amount).ToList();
Console.WriteLine(String.Join(", ", boxes.Select(b => b.amount)));
}
That gives me:
2, 1, 2, 0, -1, 2, 3, 0, 2, 1
3, 1, 2, 0, -1, 2, 3, 0, 2, 1
3, 2, 2, 0, -1, 2, 3, 0, 2, 1
3, 2, 3, 0, -1, 2, 3, 0, 2, 1
3, 2, 3, 1, -1, 2, 3, 0, 2, 1
3, 2, 3, 1, 0, 2, 3, 0, 2, 1
3, 2, 3, 1, 0, 3, 3, 0, 2, 1
3, 2, 3, 1, 0, 3, 4, 0, 2, 1
3, 2, 3, 1, 0, 3, 4, 1, 2, 1
3, 2, 3, 1, 0, 3, 4, 1, 3, 1
3, 2, 3, 1, 0, 3, 4, 1, 3, 2
4, 2, 3, 1, 0, 3, 4, 1, 3, 2
4, 3, 3, 1, 0, 3, 4, 1, 3, 2
4, 3, 4, 1, 0, 3, 4, 1, 3, 2
4, 3, 4, 2, 0, 3, 4, 1, 3, 2
4, 3, 4, 2, 1, 3, 4, 1, 3, 2
4, 3, 4, 2, 1, 4, 4, 1, 3, 2
4, 3, 4, 2, 1, 4, 5, 1, 3, 2
4, 3, 4, 2, 1, 4, 5, 2, 3, 2
4, 3, 4, 2, 1, 4, 5, 2, 4, 2
4, 3, 4, 2, 1, 4, 5, 2, 4, 3
5, 3, 4, 2, 1, 4, 5, 2, 4, 3
5, 4, 4, 2, 1, 4, 5, 2, 4, 3
5, 4, 5, 2, 1, 4, 5, 2, 4, 3
5, 4, 5, 3, 1, 4, 5, 2, 4, 3
5, 4, 5, 3, 2, 4, 5, 2, 4, 3
5, 4, 5, 3, 2, 5, 5, 2, 4, 3
5, 4, 5, 3, 2, 5, 5, 3, 4, 3
5, 4, 5, 3, 2, 5, 5, 3, 5, 3
5, 4, 5, 3, 2, 5, 5, 3, 5, 4
5, 5, 5, 3, 2, 5, 5, 3, 5, 4
5, 5, 5, 4, 2, 5, 5, 3, 5, 4
5, 5, 5, 4, 3, 5, 5, 3, 5, 4
5, 5, 5, 4, 3, 5, 5, 4, 5, 4
5, 5, 5, 4, 3, 5, 5, 4, 5, 5
5, 5, 5, 5, 3, 5, 5, 4, 5, 5
5, 5, 5, 5, 4, 5, 5, 4, 5, 5
5, 5, 5, 5, 4, 5, 5, 5, 5, 5
5, 5, 5, 5, 5, 5, 5, 5, 5, 5
5, 5, 5, 5, 5, 5, 6, 5, 5, 5
6, 5, 5, 5, 5, 5, 6, 5, 5, 5
I declared some array then got an error thath said "Unexpected symbol '{' ".
int[] array ;
void Start () {
if (level == 1) {
array = { 1, 2, 3, 4, 5}; //error here
}else if (level == 2) {
array = { 1, 2, 3, 4, 5, 6, 7}; //error here
}else if (level == 3) {
array = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
}
}
I change above code to this
array [0] = 1;
array [1] = 2;
...
but i want a simpler one like the first code, how?
You can only use the above syntax at the time of declaration, you can't use it later.
If you want to use something similar than you can do:
array = new[] { 1, 2, 3, 4, 5};
or
array = new int[] { 1, 2, 3, 4, 5};
But, at the time of declaration you can do:
int[] array = { 1, 2, 3, 4, 5 }; //this should compile fine
You could use something like below :
array =new int[] { 1, 2, 3, 4, 5};
For initializing array
NUnit has various ways to test collections against each other with CollectionAssert and Collection Constraints. But I do not see a way to test if one IEnumerable is a subsequence of another, i.e. it is subset with elements in the same order as in the superset.
Am I overlooking something, or do I need to implement this myself?
EDIT: This is the kind of test I have in mind
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 3, 4, 5, 6 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 4, 5 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3, 5 })] // PASS
public void TestSubsequnce(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
AssertSubsequence(subsequence, supersequence, Comparer<int>.Default);
}
It's not the most efficient algorithm with worst case of O(n log(n)), but here's how you can do it
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 3, 4, 5, 6 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 4, 5 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3, 5 })] // PASS
public void TestSubsequnce(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
AssertSubsequenceWithGaps(subsequence, supersequence);
}
public static void AssertSubsequenceWithGaps(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
// iterating multiple times, cast sequences to List
var listSub = subsequence.ToList();
var listSuper = supersequence.ToList();
int expected = listSub.Count;
int innerPointer = 0;
int actual = 0;
for (int i = 0; i < listSub.Count; i++)
{
for ( /* start from where we left before */; innerPointer < listSuper.Count; innerPointer++)
{
var valueSub = listSub[i];
var valueSuper = listSuper[innerPointer];
if (valueSub == valueSuper)
{
actual++;
break;
}
}
}
Assert.AreEqual(expected, actual);
}
Since there does not seem to be an out-of-the-box solution, here is what I came up with in the mean time.
private static void AssertSubsequence<T>(IEnumerable<T> subsequence, IEnumerable<T> superSequence, IComparer<T> comparer)
{
var superEnumerator = superSequence.GetEnumerator();
foreach (var subElement in subsequence)
{
if (!superEnumerator.MoveNext())
{
Assert.Fail("Expected a subsequence, but there is no match for {0} from the proposed subsequence.", subElement);
}
while (comparer.Compare(subElement, superEnumerator.Current) != 0)
{
if (!superEnumerator.MoveNext())
{
Assert.Fail("Expected a subsequence, but there is no match for {0} from the proposed subsequence", subElement);
}
}
}
}
I have a simple code in C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyProject
{
public static class Class1
{
public static int[] Iparray = new int { 12, 9, 4, 99, 120, 1, 3, 10 };
}
}
however on (Ctrl+Shift+B) the error displayed is
Cannot initialize type 'int' with a collection initializer because it does not implement 'System.Collections.IEnumerable'
I am using vs 2010 and
and .NET framework 4
Thank you All
You're missing brackets. Like this:
int[] a = new int[] { 1, 2, 3 };
You have three ways to define an int array:
public static int[] Iparray = { 12, 9, 4, 99, 120, 1, 3, 10 };
public static int[] Iparray = new[] { 12, 9, 4, 99, 120, 1, 3, 10 };
public static int[] Iparray = new int[] { 12, 9, 4, 99, 120, 1, 3, 10 };
new int[] { 12, 9, 4, 99, 120, 1, 3, 10 };
You just missed square brackets;
namespace MyProject
{
public static class Class1
{
public static int[] Iparray = new int[] { 12, 9, 4, 99, 120, 1, 3, 10 };
}
}
Arrays (C# Programming Guide)
Single-Dimensional Arrays (C# Programming Guide)
Alternative ways of declaring an int array;
int[] Iparray = { 12, 9, 4, 99, 120, 1, 3, 10 };
int[] Iparray = new[] { 12, 9, 4, 99, 120, 1, 3, 10 };
int[] values = new int[] { 1, 2, 3 };
or this:
int[] values = new int[3];
values[0] = 1;
values[1] = 2;
values[2] = 3;
and have a look on this http://msdn.microsoft.com/en-us/library/aa288453(v=vs.71).aspx
Add [] to your code
public static int[] Iparray = new int[] { 12, 9, 4, 99, 120, 1, 3, 10 };
Try this:-
public static int[] a = new int[] {12, 9, 4, 99, 120, 1, 3, 10 };
instead of
public static int[] Iparray = new int { 12, 9, 4, 99, 120, 1, 3, 10 };