Как работает функция скремблирования? (Глава 1 Опытного интригана)

Согласно книге, это определение функции,

Функция scramble принимает непустой кортеж, в котором ни один аргумент не больше его собственного индекса, и возвращает кортеж той же длины. Каждое число в аргументе рассматривается как обратный индекс от его собственной позиции до точки, предшествующей в кортеже. Результат в каждой позиции получается путем обратного отсчета от текущей позиции по этому индексу.

И это несколько примеров,

      ; Examples of scramble
(scramble '(1 1 1 3 4 2 1 1 9 2))       ; '(1 1 1 1 1 4 1 1 1 9)
(scramble '(1 2 3 4 5 6 7 8 9))         ; '(1 1 1 1 1 1 1 1 1)
(scramble '(1 2 3 1 2 3 4 1 8 2 10))    ; '(1 1 1 1 1 1 1 1 2 8 2)

Вот реализация,

      (define pick
  (λ (i lat)
    (cond
      ((eq? i 1) (car lat))
      (else (pick (sub1 i)
                  (cdr lat))))))

(define scramble-b
  (lambda (tup rev-pre)
    (cond
      ((null? tup) '())
      (else
       (cons (pick (car tup) (cons (car tup) rev-pre))
             (scramble-b (cdr tup)
                         (cons (car tup) rev-pre)))))))

(define scramble
  (lambda (tup)
    (scramble-b tup '())))

1 ответ

Если словесное описание выглядит расплывчатым и трудным для понимания, мы можем попробовать следовать самому коду, превращая его в более наглядный псевдокод по мере продвижения:

      pick i [x, ...ys] = 
  case i { 
     1 --> x ;
     pick (i-1) ys }
==>
  pick i xs = nth1 i xs
     (* 1 <= i <= |xs| *)

scramble xs = 
   scramble2 xs []

scramble2 xs revPre =
 case xs {
   [] --> [] ;
   [x, ...ys] -->
     [ pick x [x, ...revPre],
       ...scramble2 ys
              [x, ...revPre]] }

Таким образом,

      scramble [x,y,z,w, ...] 
 =
  [ nth1 x [x]       (*x=1..1*)
  , nth1 y [y,x]     (*y=1..2*)
  , nth1 z [z,y,x]   (*z=1..3*)
  , nth1 w [w,z,y,x] (*w=1..4*)
  , ... ]

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

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

Другие вопросы по тегам