Сколько рубок головы Гераклу нужно совершить, чтобы убить Гидру за Haskell? - PullRequest
2 голосов
/ 27 января 2020

Я довольно новичок в Haskell. Я боролся с очень долго и перепробовал все, что мог придумать. Я хочу, чтобы функция выполняла проверку первого ненулевого элемента, уменьшение его на 1 и увеличение следующего элемента на его позицию в списке (последний элемент начинается с позиции 1). Например:

Пример 1:

[9,0,0,0,0,0,0,0,0] -> [8,8,0,0,0,0,0,0,0] increments the next element by 8 since it's at position 8

Пример 2:

[0,0,0,0,0,0,0,3,1] -> [0,0,0,0,0,0,0,2,2] increments the next element by 1 since it's at position 1

Пример 3:

[0,0,3,2,0,0,0,0,0] -> [0,0,2,8,0,0,0,0,0] increments the next element by 6 since it's at position 6

Мой код работает для всех из случаев выше, за исключением случая, когда последний элемент ненулевой. Например:

[0,0,0,0,0,0,0,0,5] should return [0,0,0,0,0,0,0,0,4] but it gives me the error 'empty list.'

Я знаю, что мне нужно условие, которое проверяет, равна ли длина моего списка 1, и если это так, то текущий элемент должен уменьшаться только на единицу (а не увеличиваться). следующий элемент, так как его нет). Я просто не уверен, как это сделать. Это мой код:

chop :: [Int] -> [Int]
chop [] = []
chop (x:xs) =
    if x > 0
    then [x-1] ++ [head xs + length xs] ++ drop 1 xs
    else [x] ++ chop xs

1 Ответ

7 голосов
/ 27 января 2020

Одним простым способом было бы добавить третий шаблон:

chop [] = []
chop [x] = -- TODO
chop (x:xs) = -- as before

Если вы сделаете это, вы можете рассмотреть возможность сопоставления третьего шаблона с обоими первыми элементами:

chop [] = []
chop [x] = -- TODO
chop (x:x':xs) =
    if x > 0
    then [x-1] ++ [x' + length xs + 1] ++ xs
    else [x] ++ chop (x':xs)

Другой вариант - заставить код для вашего шаблона x:xs работать, даже если xs пуст, используя take 1 вместо head:

chop (x:xs) =
    if x > 0
    then [x-1] ++ map (length xs+) (take 1 xs) ++ drop 1 xs
    else [x] ++ chop xs

Кстати, идиоматически, люди обычно пишите foo:bar вместо [foo] ++ bar всякий раз, когда это возможно (с несколькими исключениями):

chop (x:xs) =
    if x > 0
    then x-1 : head xs + length xs : drop 1 xs
    else x : chop xs
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...