Как применить показатели к построенному списку в ракетке - PullRequest
1 голос
/ 15 апреля 2020

enter image description here Так что я знаю, как построить список в ракетке, используя, build-list

, например:

(build-list 2 add1) => (list 1 2)

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

Например: показатель 3, он начнется в 0 и закончится в 3, применяя его к 1 и 2 из встроенного списка.

1^0 * 1^1 * 1^2 * 1^3 
2^0 * 2^1 * 2^2 * 2^3 

Примерно то, что у меня есть.

(define (list-of-numbers m n)
(apply * (build-list (get m) (lambda (n) (expt n n)))))

  (define (get m)
    (build-list m add1))

Вывод должен быть:

(list-of-numbers 2 3) ⇒ (list 1 64)

1 × 1 × 1 × 1 = 1 
1 × 2 × 4 × 8 = 64

Ответы [ 2 ]

2 голосов
/ 16 апреля 2020

Решение, использующее build-list, может начаться с создания списка из m элементов:

(build-list m add1)

Здесь (build-list 2 add1) -> (1 2)

Далее, один мог бы map над списком с помощью build-list снова, чтобы создать список списков. Нам понадобится процедура для применения к списку, например (1 2), которая будет составлять список из каждого элемента. Обратите внимание, что каждый элемент должен преобразовываться в список n+1 элементов (в случае list-of-numbers 2 3 у нас есть n == 3):

(lambda (x) (build-list (add1 n) some-procedure))

Когда эта процедура применяется к элементу из (1 2) мы должны получить список типа (1 1 1 1) или (1 2 4 8). С этой целью some-procedure будет вызываться на номер в диапазоне [0, n]. Что нужно сделать some-procedure, это взять его номер из первого списка (x в приведенном выше выражении lambda) и увеличить его до степени его числа из второго списка (число в диапазоне * 1027). *). Итак, теперь можно записать some-procedure как:

(lambda (y) (expt x y))

Здесь x берется из первого выражения lambda, а y берется из диапазона [0, n], предоставленного build-list. Теперь нам нужно map это составное lambda выражение поверх первого списка, который мы построили:

(map (lambda (x) (build-list (add1 n) (lambda (y) (expt x y))))
     (build-list m add1))

Если бы мы должны были проверить результат вышеприведенного отображения с входами 2 и 3 для m и n, соответственно, мы получили бы:

'((1 1 1 1) (1 2 4 8))

Осталось только умножить apply на подсписки здесь; опять же, мы можем map a lambda выражение, которое использует apply в каждом из подсписков, оставляя нам список результатов:

(define (list-of-numbers m n)
  (map (lambda (s) (apply * s))
       (map (lambda (x) (build-list (add1 n) (lambda (y) (expt x y))))
            (build-list m add1))))

Вот пример вывода:

scratch.rkt> (list-of-numbers 2 3)
'(1 64)
scratch.rkt> (list-of-numbers 3 3)
'(1 64 729)
scratch.rkt> (list-of-numbers 3 2)
'(1 8 27)

Есть ли что-нибудь, что я могу использовать вместо применения?

Вместо использования apply, можно снова использовать map с примененным выражением lambda foldl вместе с умножением на подсписки:

(define (list-of-numbers-2 m n)
  (map (lambda (x) (foldl * 1 x))
       (map (lambda (x) (build-list (add1 n) (lambda (y) (expt x y))))
            (build-list m add1))))

Работает так же, как и раньше:

scratch.rkt> (list-of-numbers-2 2 3)
'(1 64)
scratch.rkt> (list-of-numbers-2 3 3)
'(1 64 729)
scratch.rkt> (list-of-numbers-2 3 2)
'(1 8 27)
1 голос
/ 15 апреля 2020

Для каждого из них у вас есть показатели 0..3, которые вы можете получить с помощью build-list 4

> (build-list 4 (lambda (n) n))
(list 0 1 2 3)

Затем вы можете поместить expt вызов внутри лямбды

> (build-list 4 (lambda (n) (expt 2 n)))
(list 1 2 4 8)

Если вы хотите умножить элементы списка, вы можете использовать apply *

> (apply * (build-list 4 (lambda (n) (expt 2 n))))
64
...