#wolfram-mathematica
#wolfram-mathematica
Вопрос:
В настоящее время я изучаю Mathematica и читал некоторые конспекты лекций, в которых пытались объяснить рекурсивные функции, затем они привели следующие примеры:
mapg[list_] := Prepend[ mapg[Rest[list]] , g[First[list]] ];
mapg[{}] := {};
mapg[{a, b, c}]
что дает результат: {g [a], g [b], g[c]}
Хотя я понимаю значение отдельных функций (Prepend, Rest, First), я не понимаю, как это рекурсивная функция и как она на самом деле работает, чтобы выдавать результат, который она дает.
Другой приведенный пример:
primefactorial[1] := 1;
primefactorial[n_] := If[PrimeQ[n], n # , #] amp;@primefactorial[n - 1]
primefactorial /@ Range[23]
Что дает результат: {1, 2, 6, 6, 30, 30, 210, 210, 210, 210, 2310, 2310, 30030, 30030,
30030, 30030, 510510, 510510, 9699690, 9699690, 9699690, 9699690,
223092870}
Опять же, хотя я понимаю, что делает функция PrimeQ и функция If, я не понимаю, что делает фактическая рекурсивная функция. В частности, что делает «n #» в функции If? Кроме того, что делает @primefactorial[n-1] ? Что именно применяется к primefactorial[n-1]?
Ответ №1:
Первый
mapg[list_] := Prepend[ mapg[Rest[list]] , g[First[list]] ];
mapg[{}] := {};
mapg[{a, b, c}]
это просто способ записи Map[g, list]
с добавлением g[First[list]]
mapg[Rest[list]]
. Ключевой частью здесь является то, что они определили
mapg[{}] = {}
так что есть конкретный базовый вариант, и вы не повторяете бесконечно. Это работает, потому что
Rest[{a}] == {}
Если вы развернете то, что происходит поэтапно в этом вызове, вы получите
mapg[{a, b, c}] == Prepend[Prepend[Prepend[{}, c], b], a]
Второй случай немного сложнее, поскольку они использовали чистую (анонимную) нотацию функций. В этом случае они имеют
If[PrimeQ[n], n # , #] amp;@primefactorial[n - 1] ==
If[PrimeQ[n], n*primefactorial[n - 1], primefactorial[n - 1]]
который просто говорит, что если n
это простое число, то умножьте его на предыдущее разложение факториала, в противном случае ничего не делайте и просто верните предыдущее разложение.
Рекурсия происходит на primefactorial[n - 1]
шаге, где снова для предотвращения бесконечной рекурсии они определили
primefactorial[1] = 1
Вы могли бы символически расширить это следующим образом
symbolicPrimeFactorial[1] := prime[1];
symbolicPrimeFactorial[n_] := If[PrimeQ[n], prime[n]*#, #] amp;@symbolicPrimeFactorial[n - 1]
symbolicPrimeFactorial /@ Range[1, 23, 2] // Column
prime[1]
prime[1] prime[2] prime[3]
prime[1] prime[2] prime[3] prime[5]
prime[1] prime[2] prime[3] prime[5] prime[7]
prime[1] prime[2] prime[3] prime[5] prime[7]
prime[1] prime[2] prime[3] prime[5] prime[7] prime[11]
prime[1] prime[2] prime[3] prime[5] prime[7] prime[11] prime[13]
prime[1] prime[2] prime[3] prime[5] prime[7] prime[11] prime[13]
prime[1] prime[2] prime[3] prime[5] prime[7] prime[11] prime[13] prime[17]
prime[1] prime[2] prime[3] prime[5] prime[7] prime[11] prime[13] prime[17] prime[19]
prime[1] prime[2] prime[3] prime[5] prime[7] prime[11] prime[13] prime[17] prime[19]
prime[1] prime[2] prime[3] prime[5] prime[7] prime[11] prime[13] prime[17] prime[19] prime[23]
и, надеюсь, это довольно ясно, что происходит
Комментарии:
1. Большое вам спасибо! У меня только что возник быстрый вопрос о первом примере, когда вы упомянули разворачивание, чтобы посмотреть, что происходит поэтапно, и написали:
mapg[{a, b, c}] == Prepend[Prepend[Prepend[{}, c], b], a]
Почему это не так,mapg[{a, b, c}] == Prepend[Prepend[Prepend[{}, g[c]], g[b]], g[a]]
вместо этого? Или я неправильно понял ваше объяснение?2. @user839136 это то, что я просто забыл о
g
переносе. Конечно, следует отметить, что на самом деле мы никогда не использовали бы просто такую функцию. Гораздо лучше использоватьMap
вместо