2014-09-12 4 views
1

Я не могу заставить код работать правильно. Я сравниваю два верхних числа в стеке. максимальное число будет сверху, а более низкие числа будут отброшены назад.найти наибольшее количество в стеке Postscript

count 
    /length exch def   
    length { 
      1 index 0 index gt { 
        2 1 roll 
        count 1 sub -1 roll 
      }if 
    }repeat 

ответ

2

Во-первых, будьте очень осторожны в выборе имен для своих определений. length - имя оператора. Поэтому, пока ваше определение действует (предположительно в userdict), оператор (в systemdict) недоступен по имени *.

Для любого сложного кода манипулирования стеками очень хорошо писать комментарии, описывающие стек в конце каждой строки. Здесь вы можете использовать «свободные» имена переменных.

count % ... n 

Теперь, поскольку мы используем это значение немедленно, его фактически не нужно определять вообще. Просто оставьте это в стеке.

{ % 

} repeat 

Теперь петли могут показаться сложными для документирования стека, но на самом деле это то же самое. Цикл повторения выводит аргумент повторения счетчика стека, поэтому процедура начинается с содержимого чуть ниже.

{ % ... 

1 index 0 index будет лучше, так как 1 index 1 index (правильно? Потому что первый один сдвинут глубину стека). Но это лучше всего, как 2 copy.

2 copy gt { % ... x y (x>y) 

(x>y) здесь не в стеке, а представляет знание отношений от переменных. 2 1 roll лучше как exch.

 exch % ... y x (x>y) 
     count 1 sub -1 roll % 

Это вытащит второе-нижнее кверху. Смотрите мое руководство для оператора roll: Positive j to roll away, negative to retrieve.

 exch % a b ... y x (x>y) 

Но если x<y тогда мы все еще хотим, чтобы катиться следующий номер со дна, не так ли? Поэтому статья if должна закончиться здесь.

} if 
    count 1 sub -1 roll % a ... y x b 

Если удалить 1 sub, то он захватывает нижнюю часть стека. И тогда я думаю, что он должен делать то, что вы описываете.

} repeat 

Собранный.

count % ... n 
{ % ... 
    2 copy gt { % a ... x y (x>y) 
     exch % a ... y x (x>y) 
    } if  % a ... y x (x>y) 
    count -1 roll % ... y x a (x>y) 
} repeat 

Edit, один день позже: Um. Проблема. Это не правильно. Так как roll происходит после сравнения, то будет лишний ненужный roll, прежде чем цикл завершится, и на нем будет помещено одно из меньших отклоненных значений.

Быстрое исправление добавить

count 1 roll % a ... y x (x>y) 

в самом конце, после цикла. Но я думаю, что лучше всего свернуть сначала, , затем сравнить.

Это проблема с «забором-проводкой», если я когда-либо видел ее.

a b c d e f g h 
      g>h 
      f>g 
     e>f 
     d>e 
    c>d 
    b>c 
a>b 

Поэтому нам понадобятся только n-1 сравнения. Что приводит к этой версии, которая, я думаю, должна работать лучше.

count 1 sub % a b c ... x y n-1 
{ 
    count -1 roll % b c ... x y a 
    2 copy gt { exch } if % b c ... x y a (a>y) 
} repeat 

Там еще один ненужный roll (самый первый), но теперь это безвредно.

[*] Он по-прежнему доступен в процедурах, которые использовали bind.

Смежные вопросы