Неверный вывод для функции, которая суммирует предыдущие элементы списка - PullRequest
0 голосов
/ 04 июня 2019

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

Это то, что я получил до сих пор:

let counter1 = ref 0;;
let rec sumthingy = fun list ->
    match list with
    | [] -> []
    | [a] -> [a]
    | hd::tl -> if List.length list > !counter1
             then (counter1:=!counter1 + 1 ;
         [ (sum list !counter1 ) ] @ sumthingy list)
         else [];;

let total = ref 0;;
let counter = ref 0;;
let rec sum = fun list n ->
    match list with
    | [] -> !total
    | [a] ->  if !counter != n then
        (counter:= !counter + 1;
        total:= !total + a; 
        !total) else !total
    | hd::tl -> if !counter != n then
        (counter:= !counter + 1;
        total:= !total + hd; 
        sum tl n) else !total;;

sum [1;2;3] 1;;
sumthingy [1;2;3];;

Функция «sum» прекрасно работает сама по себе, поэтому проблема должна быть в «sumthingy».

Ожидаемое значение для [1; 2; 3] равно [1; 3; 6], но по какой-то причине я получаю [6; 6; 6].

ПРИМЕЧАНИЕ. Я знаю индексыиз счетчиков неточны.sum [1; 2; 3] 1 должно вывести 3, но выдает 1. В данный момент для меня это не имеет большого значения, я просто хочу, чтобы это работало.

Ответы [ 2 ]

0 голосов
/ 04 июня 2019

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

Сначала я выбрал бы простое решение:

  1. Реализация функции, которая дает список, и n возвращаетсумма элементов списков от 0 до nth

  2. Подайте функцию от (1) до map и получите желаемый результат.

Что-то вроде

let sum lst n =
  let rec aux lst s m =
    match lst, m with
    | [], _ -> s
    | hd::tl, 0 -> s+hd
    | hd::tl, _ -> aux tl (s+hd) (m-1)
  in
  aux lst 0 n
;;

let sumthingy lst =
  List.mapi (fun i _ -> sum lst i) lst
;;

utop # sumthingy [1;3;5;7];;
- : int list = [1; 4; 9; 16]

Это решение далеко не оптимально - оно вычисляет сумму с самого начала, несмотря на тот факт, что для каждого элемента у нас уже есть вычисленная сумма предыдущих, поэтому в идеале нам нужно простоОперация 1 сумма, чтобы получить каждый следующий элемент.Но это должно быть достаточно хорошо в качестве отправной точки ...

0 голосов
/ 04 июня 2019

Рассмотрим это выражение:

[ (sum list !counter1 ) ] @ sumthingy list

Поскольку вы пишете императивный код (с побочными эффектами), результат зависит от порядка вычисления левой и правой сторон @. Но OCaml не гарантирует оценку заказа.

Полагаю, порядок не соответствует ожиданиям.

Вы можете гарантировать заказ, используя let:

let x = expr1 in
let y = expr2 in
x @ y

Это гарантирует, что expr1 оценивается до expr2.

(Еще лучшим решением было бы написать код без побочных эффектов: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...