0

I am trying to permute an array based on values from another array. A = [5, 6, 7, 8] P = [1, 3 ,2, 0] Should return [6, 8, 7, 5]

I have the below code written in python. I wanted to see if this is an acceptable approach to this problem or if there are better ways to solve this problem

def permute(A, P):
    for i in range(len(P)):
        if i != P[i]:
            if int(P[P[i]]) >= 0:
                if A[i]>0:
                    A[i], P[i]=A[P[i]], -A[i]
                else:
                    A[i], P[i] = A[P[i]], f"{A[i]}"
            else:
                if isinstance(P[P[i]],int):
                    A[i], P[i] = -P[P[i]], -A[i]
                else:
                    A[i], P[i] = int(P[P[i]]), f"{A[i]}"
    return(A)

I store the original value from A as a negative value in P so i can retrieve it back by changing the sign. However I am doing a string convert if the value in the original array is negative to keep a track of when the values are negative vs when i store them as negative in P.

This code works but looking for ideas on if this can be done in a much cleaner way

5
  • 3
    Seems like [A[i] for i in P ] would be a bit easier. Commented Jul 2, 2020 at 5:20
  • what's all this about negative values and string conversion? why does it matter what value they have if all you're doing is shifting positions in the list? Commented Jul 2, 2020 at 5:21
  • Looks like OP is trying to permute A in-place Commented Jul 2, 2020 at 5:22
  • @HansMusgrave still doesn't make sense. Even if it was meant to be a "reversible" permutation or in-place, both tasks shouldn't require manipulating the values based on what value (sign) and type they are Commented Jul 2, 2020 at 5:23
  • Yes i think i overlooked i am able to swap without changing the signs or string convert Commented Jul 3, 2020 at 17:37

4 Answers 4

1

In-place copying, using P to track original values. Copies original values swapped to P. If index value in P already iterated over, use P, else use value in A (to check if it has been overwritten yet).

A = [5, 6, 7, 8]
P = [1, 3 ,2, 0]
for i,p in enumerate(P):
  P[i]=A[i]
  A[i]=P[p] if p < i else A[p]

It would have been even simpler to just copy values to P directly if you need in-place without creating a list (slightly more efficient in both time and space as well), and use P as the new A, but it seems like you want to do it in-place on A for some reason, and only use P as a temporary store.

List comprehension is also simpler to implement, and creates a copy without mutating the lists.

Difference in efficiency shouldn't ever really matter. Even if you're dealing with extremely large lists in resource constrained situations, it's not likely to ever be a noticeable difference, let alone be the bottleneck.

Sign up to request clarification or add additional context in comments.

Comments

0

If I understand correctly, isn't this what you want?

A = [5, 6, 7, 8]
P = [1, 3 ,2, 0]

for i in range(len(P)):
    print(A[P[i]])

Comments

0

Seems straigt forward to use list comprihension:

A = [5, 6, 7, 8]
P = [1, 3 ,2, 0]

print([A[i] for i in P ])

Also, if you use a numpy array istead, you can simply use the P array as indexing for the new list:

import numpy as np

A = np.array([5, 6, 7, 8])
P = [1, 3 ,2, 0]

print(A[P])

Also giving the correct answer.

Comments

0

I think i should have mentioned this earlier, the solutions is to update list in place and so i cannot do prints. But i was able to come up with a better algorithm to update without changing signs or string convert

def permute(A, P):
    for i in range(len(P)):
        if i != P[i]:
            if P[i] >= i:
                A[i], P[i]=A[P[i]], A[i]
            else:
                A[i], P[i] = P[P[i]]
    return P 

1 Comment

fyi if you look at my answer, it is actually a simplified version of what you have here except that mine purposely keeps the final result in A to stay true to your original code. If you are okay with mutating P as you have done here, you actually don't need any conditional branching at all. You can just do one loop of P[i]=A[P[i]] and return P, which is what I was referring to in the second paragraph.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.