13

In postscript, the roll operator is very general and difficult to visualize. How do you make sure you're rolling in the right direction?

I want to get a solid handle on roll because I want to be able to transform functions using variables

/f { % x y z
    /z exch def
    /y exch def
    /x exch def
    x dup mul
    y dup mul
    z dup mul add add % x^2+y^2+z^2
} def

into functions using stack manipulations, more like

/f { % x y z
    3 1 roll dup mul % y z x^2
    3 1 roll dup mul % z x^2 y^2
    3 1 roll dup mul % x^2 y^2 z^2
    add add % x^2+y^2+z^2
} def

or

/f { % x y z
    3 { 3 1 roll dup mul } repeat
    2 { add } repeat      % x^2+y^2+z^2
} bind def

These should both execute faster by having fewer name-lookups (hashtable search).

With roll I always have to test it out; and I usually get it wrong on the first try! I'm okay with exch, though

4

2 回答 2

12

很长一段时间我都难以滚动。我现在记得使用这些方法,它们都是等效的:

押韵(-ish)

新泽西

  • 正 j,滚开

    7 8 9  3 1 roll
    % 9 7 8

  • 否定的,取回它(或“negateeve,然后取回”)

    % 9 7 8
    3 -1 roll
    % 7 8 9


堆栈(东西)

也许更好的思考方式是物理堆栈(例如书籍),因此堆栈的顶部实际上是“在顶部”。

然后正面滚动上升:

   对于 j 次
     拿起 n 本书
     将顶部的放在底部(将子堆栈“向上”移动)
     把它们放回去

并且负滚动下降:

   对于 j 次
     拿起 n 本书
     将底部的放在顶部(将子堆栈“向下”移动)
     把它们放回去

侧身

但我通常将堆栈从侧面描绘出来,就像对象在文件中看起来是一系列文字一样。所以我认为正滚动是把前 j 个东西藏在第 n 个东西后面;和从第 n 件事开始的第 j 件事的负面滚动。给予和接受。

离开。

n j roll

__ j > 0 __     move top j elements to the bottom of n

 n            TOS
  -------------|
 |       j     |
 |        -----|
 |       |     |
 V       V     |

 a b c d e f g h

^       |       |
|       |-------|
^           |
 -<-<-<-<-<-
   move

然后回来。

__ j < 0 __   move j elements from the bottom of n to the top

 n            TOS
  -------------|
 |     j       |
 |-----        |
 |     |       |
 V     V       |

 a b c d e f g h

|       |       ^
|-------|       |
   |           ^
    ->->->->->- 
       move

皮棉辊

还有一种方法是把它画在一边,然后在上面放一个粘轮(可能是一个棉绒滚筒)

(a) (b) (c) (d) (e) 5 3 卷

           _______
          / \
          | 3 |
          | / | \ |
          \_______/
 (a) (b) (c) (d) (e)

然后正向滚动就像弧形一样逆时针旋转并旋转。

       _______ (e)
      // \
      | 3 --| (d)
      | \ |
      \_______/ (C)
 (一) (二)


   (e)__(d)__(c)
     /\ | /\
     | 3 |
     | |
     \_______/
   (一) (二)


   (C)_______
     /\ \
 (d) |-- 3 |
     |/ |
     \_______/
  (e) (a) (b)


    _______
   / \
   | 3 |
   | / | \ |
   \_______/
 (c) (d) (e) (a) (b)

并且负滚动像 arcn 和负旋转一样顺时针旋转。

    _______
   / \
   | 3 |
   | / | \ |
   \_______/
 (a) (b) (c) (d) (e)


   (一个)_______
     /\ \
 (b) |-- 3 |
     |/ |
     \_______/
  (c) (d) (e)


   (c)__(b)__(a)
     /\ | /\
     | 3 |
     | |
     \_______/
   (d) (e)

       _______ (C)
      // \
      | 3 --| (二)
      | \ |
      \_______/ (一个)
 (d) (e)
           _______
          / \
          | 3 |
          | / | \ |
          \_______/
 (d) (e) (a) (b) (c)

消除负面

不难看出负滚动是完全没有必要的,因为如果 j<0,它可以被 nj 代替。例如。

3 -1 roll  % roll bottom 1 element from 3 to the top
3 2 roll   % roll top 2 elements behind the 3rd

是相同的。

16 -4 roll  % roll bottom 4 elements from 16 to the top
16 12 roll  % roll top 12 elements behind the 16th

是相同的。


这导致了最终的、最终的简化视图(尽管上面的每一个都可以工作)。

滚动只是一个大交换

您实际上只是将顶部j元素与下面的nj元素交换

假设您在堆栈上有这个混乱(其中 $TOS$ 标记堆栈的顶部),并且想要正确排序:

g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z  a  b  c  d  e  f $TOS$

向上(向下)计数nj

g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z  a  b  c  d  e  f
26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1
|                                                         | j = 6 .  .  .  .
| n = 26 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

> 26 6 roll   pstack

 a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z

j的负值只是相对于n 个元素中最深的元素定位分割线(它从下面开始计数)。

t  u  v  w  x  y  z  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s
26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1
.  .  .  .   j = -7 |                                                      |
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . n = 26 |

> 26 -7 roll  pstack

 a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z

这是一个方便的函数,它提供了一个更类似于大交换视图的滚动界面。

% r0..rN  s0..sM  N  M   swap   s0..sM  r0..rN
% a gentler interface to the power of roll
/swap {
    exch 1 index add exch
    roll
} def
0 1 2 3 /a /b /c 4 3 swap pstack

输出:

GPL Ghostscript 8.62 (2008-02-29)
Copyright (C) 2008 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
3
2
1
0
/c
/b
/a
GS<7>GS<7>
于 2013-04-14T09:23:11.723 回答
1

简单的说:如果你让一些圆形物体滚动,它与你的距离可能会比以前更大,除非你使用手以外的其他东西(例如:一根魔杖,......)来使物体滚动。

5 1 roll意味着1堆栈顶部的对象随后将与堆栈顶部的距离更大。

10 11 12 13 14 15 16 17 18 19 20 5 1 roll

是一样的

10 11 12 13 14 15 20 16 17 18 19

你看 20 变深了,最后五个元素改变了位置。

5in5 1 roll表示只有堆栈中的前五个对象可以全部改变位置。

-14是相同的模数5,因此很容易记住在应用此解决方案之前必须将负数修改为正数。

于 2017-06-21T15:18:40.483 回答