Как применить операцию aritmethi c к каждому элементу в списке списков, содержащих целые числа? - PullRequest
0 голосов
/ 09 апреля 2020

Я хотел бы узнать, как написать функцию, которая бы принимала два параметра, то есть a 'и b' (которые являются функциями), а также список списков;

И затем, если сумма элементов в любом списке в списке int-списков (я имею в виду целые числа) является нечетным числом, она будет выполнять операцию умножения - функцию a '(мульт. с тем же целым числом -> x * x), над каждым элементом в этом списке.

В противном случае, если сумма элементов в любом списке в списке int-списков будет четной, будет выполнена операция сложения - функция b '(добавить с то же самое целое число -> x + x) для каждого из элементов в этом списке.

Таким образом, вызов функции со входом будет таким:

func a b [[1;3];[8;3]];;

. .. и тогда результат должен выглядеть следующим образом:

- : int list list = [[2; 6]; [64; 9]]

Сумма элементов в первом списке является четным числом, поэтому первый список будет добавлен, а сумма элементов во втором списке будет нечетной число, что означает, что второй список будет м ultiplied.

Я написал эту функцию в Ocaml как упражнение, и я действительно изо всех сил пытаюсь понять этот язык; Я хотел бы знать, что я делаю неправильно ... Кроме того, стратеги c помощь будет высоко ценится! то есть объяснение того, как все на самом деле работает здесь в Ocaml, хотя я не совсем новичок ie для Ocaml, я уже многое узнал о хвостовых рекурсивных функциях, это просто обмен параметрами между функции, которые меня беспокоят.

Хорошо, вот код:

let a = List.map (List.fold_left ( + ) 0)
let b = List.map (List.fold_left ( * ) 0)

let rec func a b lists = if lists = [] then []

             else if ((List.map (List.fold_left ( + ) 0)) mod 2 = 0) then List.map
                     (List.fold_left ( + ) 0)
             else List.map (List.fold_left ( * ) 0)

(* Function call: *)
func (fun x -> x*x) (fun x -> x+x) [[1;3];[5;7]];;

1 Ответ

0 голосов
/ 09 апреля 2020

Вы имеете дело со списками списков здесь. Таким образом, вам нужно List.map список списков, а также List.map каждый отдельный список.

Когда вы делаете List.map (List.fold_left ( + ) 0), у вас есть частичное применение к двум функциям:
Для List.fold_left вы даете функцию, которую нужно применить, и начальный элемент, и оставляете с функцией, которая все еще принимает list.
Для List.map задан первый аргумент (функция, которая будет применена), и в итоге вы получите функцию, которая по-прежнему будет принимать список списков: Итак, на данный момент это все еще неоцененная функция. Вы не можете сделать mod 2 с ним, потому что у вас нет целого числа.

Ваши a и b, определенные вверху, на самом деле не используются, потому что они будут затенены аргументы функции в вашем func.
Когда вы вызываете func (fun x -> x*x) (fun x -> x+x) [[1;3];[5;7]];;, a будет (fun x -> x*x), b будет (fun x -> x+x), а ваш lists будет [[1;3];[5;7]].

Ваш func не является рекурсивной функцией, он не вызывает сам себя. List.map, который вы используете, не является хвостовой рекурсией, а List.fold_left - это.
См .:
https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html#VALmap
https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html#VALfold_left
Это может быть полезно для понимания хвостовой рекурсии: https://www.cs.cornell.edu/courses/cs3110/2020sp/textbook/data/tail_recursion.html

Я бы минимально изменил ваш код следующим образом:

let func a b lists = 
  let is_even l = List.fold_left ( + ) 0 l mod 2 = 0 in
  List.map (fun l -> if is_even l then List.map b l else List.map a l) lists

(* Function call: *)
let _ = func (fun x -> x*x) (fun x -> x+x) [[1;4];[5;7]]

Он отображает список списков так что l это список. Затем он проверяет, является ли сумма этого списка четной, и, если это так, применяет функцию b к каждому отдельному элементу, в противном случае a.

EDIT: если вы хотите сделать его рекурсивным, Вы можете отключить List.map с помощью List.rev_map, а затем перевернуть сопоставленный список с помощью List.rev.

...