Для домашней работы меня попросят реализовать метод дополнения двух в Haskell, который при задании списка чисел в Binary возвращает список дополнений двух из этого списка.Дополнение Дополнения как можно более простое без функций более высокого порядка
>>>twoComplement [0,0,0,1,1,0,1,0]
[1,1,1,0,0,1,1,0]
Поэтому я не разрешено использовать функции высшего порядка, таких как last
, init
и т.д. Это должно быть как можно более простым. Я хочу научиться писать красивый код.
Я хотел бы сделать это без использования обратных функций, но при необходимости мне разрешено.
Я уже много пробовал. Я понимаю, что мне нужно перевернуть все биты, что не сложно.
flipBits [] = []
flipBits (x:xs)
|x == 0 = 1:flipBits xs
|x == 1 = 0:flipBits xs
|otherwise: error "Only 0 and 1 are allowed."
Но добавление одной части кажется мне очень сложным. Особенно с переносом, если я добавлю 1 к уже существующему 1. Также нельзя использовать генераторы списков. Это все о списках понимания и конкатенаторе :
.
Редактировать: С помощью vkuo я написал следующее, что, похоже, хорошо работает до сих пор.
twoComplement:: [Integer] -> [Integer]
twoComplement [] = []
twoComplement lst = turn(tC(turn(lst)))
where
tC (x:xs)
|x == 1 = 1:flipp xs
|x == 0 = x:tC xs
flipp [] = []
flipp(x:xs)
|x == 0 = 1:flipp xs
|x == 1 = 0:flipp xs
turn [] = []
turn (x:xs) = turn xs ++ [x]
Если мы хотим использовать reverse
, мы должны сделать это сами. Поэтому я сделал это. Интересно, есть ли способ без реверса?
Покажите, что вы пробовали для своей функции 'twoComplement', а другие, скорее всего, помогут вам. Вы не можете ожидать, что другие просто напишут код для вас. – ray
Пытливый способ подумать о дополнении двойки - это сканировать битную строку справа налево, пока не нанести первый удар, а затем перевернуть все биты, следующие за ним. – vkuo
'last' и' init' не являются [функциями более высокого порядка] (https: //en.wikipedia.org/wiki/Higher-order_function) ... – Cactus