]> granicus.if.org Git - python/commitdiff
Make deque.rotate() smarter. Beef-up related tests.
authorRaymond Hettinger <python@rcn.com>
Sun, 8 Feb 2004 04:05:26 +0000 (04:05 +0000)
committerRaymond Hettinger <python@rcn.com>
Sun, 8 Feb 2004 04:05:26 +0000 (04:05 +0000)
Lib/test/test_deque.py
Modules/collectionsmodule.c

index 016c2aeaf261d805029ba93811959e38acfe865d..f3bc59f8ce7a28f88d3f93e8d60c7ea435649545 100644 (file)
@@ -41,16 +41,50 @@ class TestBasic(unittest.TestCase):
         self.assertEqual(list(d), list(reversed('abcd')))
 
     def test_rotate(self):
-        s = 'abcde'
+        s = tuple('abcde')
+        n = len(s)
+
+        d = deque(s)
+        d.rotate(1)             # verify rot(1)
+        self.assertEqual(''.join(d), 'eabcd')
+
+        d = deque(s)
+        d.rotate(-1)            # verify rot(-1)
+        self.assertEqual(''.join(d), 'bcdea')
+        d.rotate()              # check default to 1
+        self.assertEqual(tuple(d), s)
+
+        for i in xrange(n*3):
+            d = deque(s)
+            e = deque(d)
+            d.rotate(i)         # check vs. rot(1) n times
+            for j in xrange(i):
+                e.rotate(1)
+            self.assertEqual(tuple(d), tuple(e))
+            d.rotate(-i)        # check that it works in reverse
+            self.assertEqual(tuple(d), s)
+            e.rotate(n-i)       # check that it wraps forward
+            self.assertEqual(tuple(e), s)
+
+        for i in xrange(n*3):
+            d = deque(s)
+            e = deque(d)
+            d.rotate(-i)
+            for j in xrange(i):
+                e.rotate(-1)    # check vs. rot(-1) n times
+            self.assertEqual(tuple(d), tuple(e))
+            d.rotate(i)         # check that it works in reverse
+            self.assertEqual(tuple(d), s)
+            e.rotate(i-n)       # check that it wraps backaround
+            self.assertEqual(tuple(e), s)
+
         d = deque(s)
-        d.rotate(2)
-        self.assertEqual(''.join(d), 'deabc')
-        d.rotate(3)
-        self.assertEqual(''.join(d), s)
-        d.rotate(-3)
-        self.assertEqual(''.join(d), 'deabc')
-        d.rotate(-15)
-        self.assertEqual(''.join(d), 'deabc')
+        e = deque(s)
+        e.rotate(BIG+17)        # verify on long series of rotates
+        dr = d.rotate
+        for i in xrange(BIG+17):
+            dr()
+        self.assertEqual(tuple(d), tuple(e))
 
     def test_len(self):
         d = deque('ab')
index d60ede163d86eb6b1958e1c1c9e5b113042041d0..0e0b2d6ac85f601d8492d5792922edc0bae05211 100644 (file)
@@ -247,14 +247,21 @@ PyDoc_STRVAR(extendleft_doc,
 static PyObject *
 deque_rotate(dequeobject *deque, PyObject *args)
 {
-       int i, n;
+       int i, n=1, len=deque->len, halflen=(len+1)>>1;
        PyObject *item, *rv;
 
-       if (!PyArg_ParseTuple(args, "i:rotate", &n))
+       if (!PyArg_ParseTuple(args, "|i:rotate", &n))
                return NULL;
 
-       if (n == 0  ||  deque->len == 0)
+       if (len == 0)
                Py_RETURN_NONE;
+       if (n > halflen || n < -halflen) {
+               n %= len;
+               if (n > halflen)
+                       n -= len;
+               else if (n < -halflen)
+                       n += len;
+       }
 
        for (i=0 ; i<n ; i++) {
                item = deque_pop(deque, NULL);
@@ -280,7 +287,7 @@ deque_rotate(dequeobject *deque, PyObject *args)
 }
 
 PyDoc_STRVAR(rotate_doc, 
-"Rotate the deque n steps to the right.  If n is negative, rotates left.");
+"Rotate the deque n steps to the right (default n=1).  If n is negative, rotates left.");
 
 static int
 deque_len(dequeobject *deque)