web-dev-qa-db-ja.com

Python配列の回転

だから私はpythonでブロックスワップアルゴリズムを実装しています。

私がフォローしているアルゴリズムはこれです:

初期化A = arr [0..d-1]およびB = arr [d..n-1] 1)AのサイズがBのサイズと等しくなるまで以下を実行します

a)Aが短い場合、BrがAと同じ長さになるようにBをBlとBrに分割します。AとBrを入れ替えてABlBrをBrBlAに変更します。これでAは最終位置にあるので、Bの断片で繰り返します。

b)Aが長い場合は、AをAlとArに分割して、AlがBと同じ長さになるようにします。AlとBを入れ替えて、AlArBをBArAlに変更します。これでBは最終位置にあるので、Aの部分で繰り返します。

2)最後に、AとBのサイズが等しい場合、それらをブロックスワップします。

同じアルゴリズムがこのWebサイトのCに実装されています- Array Rotation

私のpython同じコードは

a = [1,2,3,4,5,6,7,8]

x = 2

n = len(a)


def rotate(a,x):
    n = len(a)

    if x == 0 or x == n:
        return a

    if x == n -x:
        print(a)
        for i in range(x):
            a[i], a[(i-x+n) % n] = a[(i-x+n) % n], a[i]
        print(a)
        return a

    if x < n-x:
        print(a)
        for i in range(x):
            a[i], a[(i-x+n) % n] = a[(i-x+n) % n], a[i]
        print(a)
        rotate(a[:n-x],x)
    else:
        print(a)
        for i in range(n-x):
            a[i], a[(i-(n-x) + n) % n] = a[(i-(n-x) + n) % n] , a[i]
        print(a)
        rotate(a[n-x:], n-x)

rotate(a,x)
print(a)

各段階で正しい値を取得していますが、再帰的な関数呼び出しが期待した結果を返さず、原因を理解できていないようです。誰かが私の再帰の何が間違っているのか説明できますか?そして何が可能な代替となり得るか。

11
Samarth

Python deque を使用して、リストを所定の位置に回転できます。

>>> from collections import deque
>>> d=deque([1,2,3,4,5])
>>> d
deque([1, 2, 3, 4, 5])
>>> d.rotate(2)
>>> d
deque([4, 5, 1, 2, 3])
>>> d.rotate(-2)
>>> d
deque([1, 2, 3, 4, 5])

またはリストスライスを使用:

>>> li=[1,2,3,4,5]
>>> li[2:]+li[:2]
[3, 4, 5, 1, 2]
>>> li[-2:]+li[:-2]
[4, 5, 1, 2, 3]

符号の規則はdeque.rotateとスライスでは反対であることに注意してください。

同じ符号規則を持つ関数が必要な場合:

def rotate(l, y=1):
   if len(l) == 0:
      return l
   y = -y % len(l)     # flip rotation direction
   return l[y:] + l[:y]

>>> rotate([1,2,3,4,5],2)
[4, 5, 1, 2, 3]
>>> rotate([1,2,3,4,5],-22)
[3, 4, 5, 1, 2]
>>> rotate('abcdefg',3)
'efgabcd'

Numpyの場合は、 np.roll を使用するだけです

>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.roll(a, 1)
array([9, 0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> np.roll(a, -1)
array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])

または、上記と同じrotateの派手なバージョンを使用できます(ここでも、符号とnp.rollの違いに注意してください)。

def rotate(a,n=1):
    if len(a) == 0:
        return a
    n = -n % len(a)     # flip rotation direction
    return np.concatenate((a[n:],a[:n]))  
24
dawg

Pythonでの配列ローテーションの簡単な略記構文は、

arr = arr[numOfRotations:]+arr[:numOfRotations]

例:

arr = [1,2,3,4,5]
rotations = 4
then 

arr = arr[4:]+arr[:4]

くれます

[5、1、2、3、4]

Kの大きな値(kは回転数)に対して右回転と左回転が必要であるという問題を見つけたため、任意のサイズのkに対して次の関数を実装しました。

右回転(左から右へ:1234-> 4123):

def right_rotation(a, k):
   # if the size of k > len(a), rotate only necessary with
   # module of the division
   rotations = k % len(a)
   return a[-rotations:] + a[:-rotations]

左円形回転(右から左へ:1234-> 2341):

def left_rotation(a, k):
   # if the size of k > len(a), rotate only necessary with
   # module of the division
   rotations = k % len(a)
   return a[rotations:] + a[:rotations]

出典:

5
Ângelo Polotto

実際にブロックスワップを実装する必要がありますか、それとも単に配列を回転させようとしていますか? pythonでは、CWおよびCWWローテーションを使用して

Zip(*arr[::-1])

そして

Zip(*arr)[::-1]
5
wflynny

このコードをpython arrayの左回転に使用できます

import copy
def leftRotate(arr,n) :
    _arr = copy.deepcopy(arr)
    for i in range(len(arr)-n):
        arr[i] = arr[i+n]
    for j in range(n):
        arr[(len(arr)-n)+j] = _arr[j]

arr = [1, 2, 3, 4, 5, 6, 7] 
leftRotateby = 3
leftRotate(arr,leftRotateby)
print arr 
#output:: [4, 5, 6, 7, 1, 2, 3]
1
a.patidar

のスライスを再帰呼び出しに渡すと、同じ変数を渡さなくなると思います。関数の追加の引数として、a全体とスライスの上限/下限を渡してみてください。

たとえば、次の関数について考えてみます。

def silly(z):
  z[0] = 2

私は次のことを試しました:

>>> z = [9,9,9,9,9,9]
>>> silly(z)
>>> z
[2, 9, 9, 9, 9, 9]
>>> silly(z[3:])
>>> z
[2, 9, 9, 9, 9, 9]

スライスへの変更がアレイ全体に保持されていないことがわかります

好奇心から、どのような成果が得られ、どのような成果が期待されますか?

1
user1245262