Анимация
JavaScript
|
Главная Библионтека 146 Глава 4 • Массивы Пример 4.2. (продолжение) $rows = int(($#clata+$cols) / $cols), # Задать маску для ускорения вычислений $mask = sprintf( %%-%cls , $maxlen-1), # Подпрограмма для обнаружения последнего элемента строки sub EOL { ($item+1) % $cols == О } # Обработать каждый элемент, выбирая нужный фрагмент # на основании позиции for ($iteiii = О, $item < $rows « $cols, $item++) { my $target = ($item % $cols) * $rows + int($iteiii/$cols) my Spiece = sprintf($mask $target < ©data $data[$target] ), Ipiece =~ s/\s+$ if EOL(), # Последний элемент не выравнивать print Spiece, print \n If EOL(), # Завершить при необходимости print \n If EOL(), # He переносится -- только для Linux sub getwinsize { ray Iwinsize = \0 x 8, my STIOCGWINSZ = 0x40087468, If (loctKSTDOUT, STIOCGWINSZ, Swinsize)) { (Srows, Scols, Sxpixel, Sypixel) = unpack( 84 , Swinsize), } else { Scols = 80, Наиболее очевидный способ вывести отсортированный список по столбцам - последовательно выводить каждый элемент списка, выравнивая его пробелами до определенной ширины. Когда вывод достигает конца строки, происходит переход на следующую строку. Но такой вариант хорош лишь тогда, когда строки читаются слева направо. Если данные должны читаться по столбцам, сверху вниз, приходится искать другое решение. Программа words представляет собой фильтр, который генерирует выходные данные по столбцам. Она читает все входные данные и запоминает максимальную длину строки. После того как все данные будут прочитаны, ширина экрана делится на длину самой большой входной записи - результат равен ожидаемому количеству столбцов. Затем программа входит в цикл, который выполняется для каждой входной записи. Однако порядок вывода неочевиден. Предположим, имеется список из девяти элементов: Неправильно Правильно 12 3 14 7 4 5 6 2 5 8 7 8 9 3 6 9 4.19. Программа: permute Проблема Вам никогда не требовалось сгенерировать все возможные перестановки массива или выполнить некоторый фрагмент для всех возможных перестановок? Например: % echo man bites dog permute dog bites man bites dog man dog man bites man dog bites bites man dog man bites dog Количество возможных перестановок для множества равно факториалу числа элементов в этом множестве. Оно растет чрезвычайно быстро, поэтому не стоит генерировать перестановки для большого числа элементов: Размер множества Количество перестановок
Программа words производит все необходимые вычисления, чтобы элементы (1,4,7) выводились в одной строке, (2,5,8) - в другой и (3,6,9) - в последней строке. Текущие размеры окна определяются вызовом loctl. Этот вариант прекрасно работает - в той системе, для которой он был написан. В любой другой он не подойдет. Если вас это устраивает, хорошо В рецепте 12.14 показано, как определить размер окна в вашей системе с помощью файла ioctl.pch или программы на С. Решение из рецепта 15.4 отличается большей переносимостью, однако вам придется установить модуль с CPAN. > Смотри также- Рецепт 15.4. Соответственно, выполнение операции для всех возможных перестановок занимает много времени. Сложность факториальных алгоритмов превышает количество частиц во Вселенной даже для относительно небольших входных значений. Факториал 500 больше, чем десять в тысячной степени! use Math Biglnt, sub factorial { my $n = shift, my $s = 1, $s ♦= $n-while $n > 0, return $s, print factorial(Math Biglnt->new( 500 )), +1220136...(1035 digits total) Два решения, приведенных ниже, отличаются порядком возвращаемых перестановок. Решение из примера 4.3 использует классический алгоритм списковых перестановок, используемый знатоками Lisp. Алгоритм относительно прямолинеен, однако в нем создаются ненужные копни. Кроме того, в решении жестко закодирован простой вывод перестановок без каких-либо дополнительных действий. Пример 4.3. tdc-permute й/sf/bin/perl -п й tsc permute вывод всех перестановок введенных слов permute([split], []), sub permute { my ©Items = ©{ $ [0] }, my ©perms = ©{ $ [1] }, unless (©Items) { print ©perms\n , } else { my(©newiteiiis,©newperms, $i), foreach $i (0 $й11етз) { ©newitems = ©items, ©newperms = ©perms, unshift(©newperms, splice(©newitems, $i, 1)), permute([©newitems], [©newperms]), Решение из примера 4.4, предложенное Марком-Джейсоном Доминусом (Mark-Jason Dofflinus), более элегантно и работает примерно на 25% быстрее. Вместо того чтобы рассчитывать все перестановки, программа генерирует п-ю конкретную перестановку. Элегантность проявляется в двух аспектах. Во-первых, в программе удается избежать рекурсии, кроме как при вычислении факториала (который алгоритмом перестановок обычно не используется). Во-вторых, вместо перестановки реальных данных генерируется перестановка целых чисел. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 [ 43 ] 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |