Lets suppose we have two integer arrays, for example:
var A = new int[] {1, 4, 6, 12, 44};
var B = new int[] {2, 4, 6, 44, 45};
The problem is to describe a transition steps as:
Starting with the array A and continue as following:
STEP 1 : remove index = 0 // result = {4, 6, 12, 44}
STEP 2 : insert index = 0 value = 2 // result = {2, 4, 6, 12, 44}
STEP 3 : remove index = 3 // result = {2, 4, 6, 44}
STEP 4 : insert index = 4 value = 45 // result = {2, 4, 6, 44, 45}
And we now have the array B
My Question is: How can I design this algorithm in any programming language or pseudocode that generates these steps programatically for given array A and B?
common step structure is like :
STEP N : insert/remove index = i [value = v]
Of course removing all elements from A then inserting all elements from B is a solution and like that maybe there will be more than 1 solutions for given A and B, but I am looking for the transition with the fewest steps.
There is the concept of the Levenshtein distance. It is used for comparing two strings (however you can also apply the same principle to integer arrays): minimal number of edits to change one string into another, where one edit is either a deletion, an insertion or a substitution.
The problem can be efficiently solved using dynamic programming. The wiki article shows such an approach.
You can use the same approach for your problem. But since in your case you are not allowed to substitute an element (only remove and insert operations), you can even simplify the the recursion a (tiny) bit:
def edit_distance(s, len_s, t, len_t):
if len_s == 0:
return len_t
if len_t == 0:
return len_s
if s[len_s-1] == t[len_t-1]:
return edit_distance(s, len_s-1, t, len_t-1)
else:
return min(edit_distance(s, len_s-1, t, len_t) + 1,
edit_distance(s, len_s, t, len_t-1) + 1)
The code above is without dynamic programming. To make it efficient, you need to add it.
Also, the code will only compute the number of steps. If you also want to list the steps, you have to store the complete table and backtrack the solution.
Time and memory complexity of the approach: O(len_s * len_t).
Here is an example using your two arrays [1, 4, 6, 12, 44] and [2, 4, 6, 44, 45]. Here is a table that you would get if you apply dynamic programming (e.g. with a bottom first approach) for each of the possible prefix-combination of the strings.
0 1 2 3 4 5
1 2 3 4 5 6
2 3 2 3 4 5
3 4 3 2 3 4
4 5 4 3 4 5
5 6 5 4 3 4
At the bottom right we see that 4 is the optimal number of steps to make both array equal. Now we can backtrack and look at the recursive formula again. Since the last two elements are not equal, it has to be an insert/remove operation. We can see in the table the optimal number of steps for [1, 4, 6, 12], [2, 4, 6, 44, 45] is 5, and for [1, 4, 6, 12, 44], [2, 4, 6, 44] is 3. So the optimal thing here is to remove the last element of the second array, or in other words to insert 45 in the first one.
Now we can thing about the last step that resulted in [1, 4, 6, 12, 44], [2, 4, 6, 44]. Since the last elements are equal, the step is clear. We leave both of them and perform no insert or remove operation.
So what was the last step in [1, 4, 6, 12], [2, 4, 6]? The table shows that the optimal value 3 originated from the position [1, 4, 6], [2, 4, 6], which means a removing 12 in the first array.
And so on.
Interestingly there can be multiple optimal solutions. Here I show you one possible path (which corresponds exactly to your solution):
0-1 2 3 4 5
|
1 2 3 4 5 6
\
2 3 2 3 4 5
\
3 4 3 2 3 4
|
4 5 4 3 4 5
\
5 6 5 4 3-4
Related
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 2 years ago.
Improve this question
I have a List as follows:
{1, 7, 4, 9, 5}
And I need a sorted List as {1, 4, 5, 7, 9}
I want to find the number of elements swapped to get this sorted list.
After 1st Move: {1, 4, 7, 9, 5}
After 2nd Move: {1, 4, 5, 7, 9}
Answer here would be: 2 Moves
Which is the optimum way to do it?
Using Linq is there a way?
Well, if I've understood you right you want to count deletions / insertions:
Take 7 and put it on 4th place,
Take 9 and put it on 5th place,
Take 5 and put it on 3d place
we have {1, 4, 5, 7, 9} which is sorted with 3 operations. If' it's your case you can
Sort the list:
{1, 7, 4, 9, 5} # initial
| | | | |
{1, 4, 5, 7, 9} # sorted
now build the unordered graph:
nodes: numbers (1, 7, ..., 5)
edges: between numbers in each column (initial and sorted list): 1 - 1, 7 - 4, 4 - 5, 9 - 7, 5 - 9
find out all the loops:
1 - 1 # length == 1
7 - 4 - 5 - 9 # length == 4
Sum all the length - 1 of all loops:
(1 - 1) + (4 - 1) = 3
Edit: In case of insertions (please, note that we don't swap items) only the answer is
|List| - |Longest_Non_Descreasing_Sequence(List)|
were |...| stands for number of items (Count, Length, Size etc). In your case:
|{1, 7, 4, 9, 5}| = 5
|Longest_Non_Descreasing_Sequence({1, 7, 4, 9, 5})| = |{1, 4, 5}| = 3
result = 5 - 3 = 2
Algorithm:
Find out the Longest Non Descreasing Sequence (LNDS), say, with a help of dynamic programming
Insert the rest items into it.
In your case for {1, 7, 4, 9, 5} we have {1, 4, 5} for LNDS and two items {7, 9} to insert:
{1, 7, 4, 9, 5} # initial List {1, 4, 5} is LNDS
{1, 4, 9, 5, 7} # 7 inserted into {1, 4, 5} we have {1, 4, 5, 7} as LNDS
{1, 4, 5, 7, 9} # 9 inserted into {1, 4, 5, 7}
I haven't been able to find anything on google.
I have this piece of code:
Random r = new Random();
int[] output = Enumerable.Range(0, 11).Select(x => x / 2).OrderBy(x => r.Next()).ToArray();
and I am having trouble actually understanding what each element does.
It generates a range of numbers and elements between 0 and 11.
But what does the select(x => x / 2) do ? does it just make pairs of elements,
I know what the whole thing spits out, an array with pairs of numbers, with a single number which has no pair.
but it is a bit above me to fully understand it ?
( is this even okay to ask on here ?? or should I delete the question again ? )
It generates a range of numbers and elements between 0 and 11. But what does the select(x => x / 2) do ? does it just make pairs of elements.
No, Select does what in some programming languages is known as map. It is called on an IEnumerable<T> and has as parameter Func<T,U> a function, and it produces an IEnumerable<U> where each element if the given IEnumerable<T> is processes through the function and the result is emitted in the result.
So in this case, it will take a range from 0 to (excluding) 11, and for each of those integers, perform an integer divsion by two:
csharp> Enumerable.Range(0, 11);
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
csharp> Enumerable.Range(0, 11).Select(x => x/2);
{ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5 }
Since:
{ 0/2, 1/2, 2/2, 3/2, 4/2, 5/2, 6/2, 7/2, 8/2, 9/2, 10/2 }
== { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5 }
Later then that IEnumerable<int> is reordered (using the OrderBy) by using pseudo-random numbers (so we shuffle them) and converted into a list.
.Range(0, 11) // generate a sequence of integers starting at 0 and incrementing 11 times (i.e. the values 0 up to and including 10)
.Select(x => x / 2) // divide each of those values from previous result by 2 and return them
.OrderBy(x => r.Next()) // then order them randomly using a random number
.ToArray(); // return the end result as an array
Think of Select as doing a transformation to each element of the IEnumerable.
For example, let's say we have a list like this:
0 1 2 3 4 5 6 7 8 9 10
Then we call .Select(x => x / 2), we are saying that for each element x in the list, do the following transformation:
x / 2
We divide each element in the list by two:
Original Transformation Result
0 0 / 2 0
1 1 / 2 0
2 2 / 2 1
3 3 / 2 1
4 4 / 2 2
5 5 / 2 2
6 6 / 2 3
7 7 / 2 3
8 8 / 2 4
9 9 / 2 4
10 10 / 2 5
We get
0 0 1 1 2 2 3 3 4 4 5 5
What Select() does is that it evaluates the given expression for every element of the Enumerable it's called on (the original list), and returns a new Enumerable with the results.
For a list:
[2, 4, 6]
it's going to return:
[2/2, 4/2, 6/2]
where / means "division", so the result of the Select() (not the entire LINQ chain) will be:
[1, 2, 3]
Analogously, if your source list is:
words = ["dog", "child", "building"]
And you call:
words.Select(word => word.Length)
you get a list of all the lengths of the strings in the list in order:
[3, 5, 7]
I have list that is guaranteed to contain sequential pairs of identical elements. Is there a way to remove half of repeating values in a list (any one element of each pair)?
Example #1:
Take:
{2, 2, 2, 2, 5, 5}
And return:
{2, 2 , 5}
Example #2:
Take:
{8, 8, 1, 1, 5, 5, 1, 1}
And return:
{8, 1, 5, 1}
There is no need to verify if elements actually comes in pairs.
If the sequence is guaranteed to be made of consecutive pairs, then this works:
values.Where((x, n) => n % 2 == 0)
I want to compare two lists. I want to check if List2 has any of the items in List1. I get unexpected result. Please see my code below.
test code class
class Program
{
static void Main(string[] args)
{
bool loop = true;
int textcount = 1;
while (loop)
{
var collection1 = GetCollection();
var collection2 = GetCollection();
Console.WriteLine("Test No " + textcount.ToString());
Console.WriteLine("Collection 1 =" + String.Join(", ", collection1.ToArray()));
Console.WriteLine("Collection 2 =" + String.Join(", ", collection2.ToArray()));
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
var hasitem = collection1.Any(item => collection2.Contains(item));
watch.Stop();
Console.WriteLine(hasitem.ToString() + " Found in " + watch.ElapsedTicks.ToString());
watch.Reset();
watch.Start();
var hasAtLeastOne = collection1.Intersect(collection2).Any();
watch.Stop();
Console.WriteLine(hasAtLeastOne.ToString() + " With Intersect Found in " + watch.ElapsedTicks.ToString());
textcount++;
Console.ReadKey();
}
}
static Random ran = new Random();
private static IEnumerable<int> GetCollection()
{
for (int i = 0; i < 5; i++)
{
yield return ran.Next(i, 20);
}
}
}
and the result is very annoying. see the last 4 result.
Test No 1
Collection 1 =10, 8, 18, 6, 11
Collection 2 =3, 12, 18, 13, 6
True Found in 3075
True With Intersect Found in 15297
Test No 2
Collection 1 =18, 13, 7, 18, 5
Collection 2 =12, 18, 8, 3, 5
True Found in 22
True With Intersect Found in 100
Test No 3
Collection 1 =1, 6, 15, 7, 9
Collection 2 =16, 15, 14, 14, 12
True Found in 21
True With Intersect Found in 23
Test No 4
Collection 1 =3, 16, 7, 4, 19
Collection 2 =6, 3, 15, 15, 9
True Found in 21
True With Intersect Found in 56
Test No 5
Collection 1 =18, 18, 9, 17, 10
Collection 2 =17, 12, 4, 3, 11
True Found in 25
True With Intersect Found in 20
Test No 6
Collection 1 =9, 9, 2, 17, 19
Collection 2 =17, 2, 18, 3, 15
False Found in 109
False With Intersect Found in 41
Test No 7
Collection 1 =3, 15, 3, 5, 5
Collection 2 =2, 2, 11, 7, 6
True Found in 22
False With Intersect Found in 15
Test No 8
Collection 1 =7, 14, 17, 14, 18
Collection 2 =18, 4, 7, 18, 16
False Found in 28
True With Intersect Found in 19
Test No 9
Collection 1 =3, 9, 6, 18, 9
Collection 2 =10, 3, 17, 17, 18
True Found in 28
True With Intersect Found in 22
Test No 10
Collection 1 =15, 18, 2, 9, 8
Collection 2 =10, 15, 3, 10, 19
False Found in 135
True With Intersect Found in 128
Test No 11
Collection 1 =6, 2, 17, 18, 18
Collection 2 =14, 16, 14, 6, 4
False Found in 20
False With Intersect Found in 17
The problem is that what you call "collection" is actually an unstable sequence of items that changes everytime it is enumerated. The reason for this is the way you implemented GetCollection. Using yield return basically returns a blue print on how to create the sequence. It doesn't return the sequence itself.
And so, everytime that "blue print" is being enumerated, it is being used to create a new sequence.
You can verify this by simply outputing your "collections" twice. You will see that the values are different each time.
And that's the reason why your test yields completely arbitrary results:
You enumerate each collection three times:
First enumeration happens when you output it to the console
Second enumeration happens on the test with Any and Contains. Because this starts a new enumeration new random numbers will be generated.
Third enumeration happens on the Intersect test. This creates yet another set of random numbers.
To fix it, create a stable sequence by calling ToArray() on the result of GetCollection.
This is your problem:
private static IEnumerable<int> GetCollection()
{
for (int i = 0; i < 5; i++)
{
yield return ran.Next(i, 20);
}
}
Make it into this:
private static List<int> GetCollection()
{
return new List<int>
{
ran.Next(0, 20),
ran.Next(1, 20),
ran.Next(2, 20),
ran.Next(3, 20),
ran.Next(4, 20)
};
}
And your problem will disappear.
The long explanation is that when you make an IEnumerable function, you can expect it to repeatedly call the iterator on various LINQ calls (after all, that's what an IEnumerable does, right?). Since you do a yield return <some random number> on each iterator call, you can expect unstable results. Best to either save a reference to the .ToArray() result, or just return a stable list.
I have a function that receives a power of two value.
I need to convert it to an enum range (0, 1, 2, 3, and so on), and then shift it back to the power of two range.
0 1
1 2
2 4
3 8
4 16
5 32
6 64
7 128
8 256
9 512
10 1024
... and so on.
If my function receives a value of 1024, I need to convert it to 10. What is the best way to do this in C#? Should I just keep dividing by 2 in a loop and count the iterations?
I know I can put it back with (1 << 10).
Just use the logarithm of base 2:
Math.Log(/* your number */, 2)
For example, Math.Log(1024, 2) returns 10.
Update:
Here's a rather robust version that checks if the number passed in is a power of two:
public static int Log2(uint number)
{
var isPowerOfTwo = number > 0 && (number & (number - 1)) == 0;
if (!isPowerOfTwo)
{
throw new ArgumentException("Not a power of two", "number");
}
return (int)Math.Log(number, 2);
}
The check for number being a power of two is taken from http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
There are more tricks to find log2 of an integer on that page, starting here:
http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
This is the probably fastest algorithm when your CPU doesn't have a bit scan instruction or you can't access that instruction:
unsigned int v; // find the number of trailing zeros in 32-bit v
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
r = MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> 27];
See this paper if you want to know how it works, basically, it's just a perfect hash.
Use _BitScanForward. It does exactly this.