Добавление 0 к списку, пока его длина не станет 8 в Haskell - PullRequest
2 голосов
/ 18 апреля 2020

Итак, я должен сделать десятичное число в двоичном списке следующим образом: intToBitString 4 = [1,0,0]. Что я и сделал следующим образом:

intToBitString n = reverse (helper n)

helper 0 = []
helper n 
        | n `mod` 2 == 1 = 1 : helper (n `div` 2) 
        | n `mod` 2 == 0 = 0 : helper(n `div` 2)

Но тогда мне также нужно создать функцию с именем intToByte, которая дополняет список нулями до тех пор, пока его длина не составит 8 элементов. (таким образом, делая это байтовой строкой) Вот так: intToByte 7 = [0, 0, 0, 0, 0, 1, 1, 1]

Я пробовал так много вещей, но они никогда не работают. Я новичок, поэтому знаю только «если» l oop, как я показал выше, и рекурсию, но я не знаю ничего фантастического. Одна из моих попыток:

intToByte 0 = [0]

intToByte n
        | eight n == helper2 n = reverse (helper2 n)
        | otherwise = eight n

helper2 0 = []
helper2 n 
        | n `mod` 2 == 1 = 1 : helper2 (n `div` 2) 
        | n `mod` 2 == 0 = 0 : helper2 (n `div` 2)

eight n
        | length (helper2 n) < 8 = 0 : eight n
        | otherwise = helper2 n

Я работал над этим так много часов, что меня это смущает. Но это часть важного задания, поэтому помощь будет очень признательна!

Ответы [ 3 ]

3 голосов
/ 18 апреля 2020

Во-первых, вы можете упростить свой код с помощью:

helper2 :: Integral i => i -> [i]
helper2 0 = []
helper2 n = r : helper2 q
    where (q,r) = quotRem n 2

Во-вторых, вышеприведенное - это big endian представление [wiki] . Действительно, 7 представляется как [1,1,1], тогда как 14, например, представляется как [0,1,1,1]. Если мы хотим изменить это, мы можем работать с аккумулятором:

helper2 :: Integral i => i -> [i]
helper2 = go []
    where go rs 0 = rs
          go rs n = go (r:rs) q
              where (q,r) = quotRem n 2

Таким образом, 7 сопоставляется с [1,1,1] и 14 с [1,1,1,0]. Но теперь нам все еще нужно добавить ведущие нули. Мы можем сделать это, например, указав количество элементов, уже добавленных в список:

eight :: Integral i => i -> [i]
eight = go [] <b>0</b>
    where go rs <b>l</b> 0 = replicate <b>(8-l)</b> 0 ++ rs
          go rs <b>l</b> n = go (r:rs) <b>(l+1)</b> q
              where (q,r) = quotRem n 2
2 голосов
/ 18 апреля 2020

Заполнение может быть таким же простым, как вычисление количества дополнительных элементов, которые нужно вывести в список sh, и затем получить эти элементы с помощью функции replicate из Prelude:

padLeft :: Int -> a -> [a] -> [a]
padLeft n x xs = replicate (n - length xs) x ++ xs

Например:

> padLeft 8 0 [1, 1, 0]
[0,0,0,0,0,1,1,0]
1 голос
/ 18 апреля 2020

Один из подходов состоит в том, чтобы определить функцию bits так, чтобы bits k преобразовал ее аргумент в битовую строку длиной k:

bits :: Int -> Int -> [Int]
bits 0 _n = []
bits k n | n < 0         = error "bits: negative"
         | n > 2 * m - 1 = error "bits: overflow"
         | otherwise     = let (i, j) = n `divMod` m in i : bits (k - 1) j
  where m = 2 ^ (k - 1)

Ваша функция eight была бы легко записана как

eight :: Int -> [Int]
eight = bits 8

Это дает:

> eight 4
[0,0,0,0,0,1,0,0]

> eight 7
[0,0,0,0,0,1,1,1]
...