Creating a list of bits?

Viewed 154

Currently, I have two functions: char2bin and segmentString.

segmentString takes a string and a fill character and returns lists of 8 character strings. For example, if there is a 13 character string, it splits it into a list of two strings where the second string has 3 fill characters to make it a complete 8.

>>>segmentString("Hello, World!", "-")
['Hello, W', 'orld!---']

char2bin takes individual string characters (single character) and turns them into a list of 8 bits. It does not work for multiple character strings. For example,

>>>char2bin('a')
[0,1,1,0,0,0,0,1]
>>>char2bin('abc')
(ERROR)

I need to create a function (in this example, let's call it framer) that takes the result from segmentString and convert it into a list of bits, where each list of bits are contained in a separate list within a list.

For example, from the segmentString function, this would create a list of two strings. Each letter of each separate string is converted into a list of bits, and each list of bits is contained as a list for each string.

>>>F=framer("Hello, World!", "-")
>>>F
[[[0, 1, 0, 0, 1, 0, 0, 0], [0, 1, 1, 0, 0, 1, 0, 1], [0,1, 1, 0, 1, 1, 0, 0], [0, 1, 1, 0, 1, 1, 0, 0], [0, 1, 1, 0, 1, 1,1,1], [0, 0, 1, 0, 1, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 1,1, 1,0, 1, 1, 1]], [[0, 1, 1, 0, 1, 1, 1, 1], [0, 1, 1, 1, 0, 0,1, 0], [0,1, 1, 0, 1, 1, 0, 0], [0, 1, 1, 0, 0, 1, 0, 0], [0, 0,1, 0, 0, 0, 0,1], [0, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1,1, 0], [0, 1, 1, 1,1, 1, 1, 0]]]

As you can see, there is one general list that contains two lists that contain 8 lists of bits, which were converted from a string character by char2bin. How would I do this?

3 Answers

You can use a list comprehension for this:

def char2bin(byte):
    return list(map(int, format(byte, '08b')))

def segmentString(text, padding, chunksize):
    for index in range(0, len(text), chunksize):
        yield text[index:index + chunksize].ljust(chunksize, padding)

def framer(text, padding='-', chunksize=8, encoding='utf8'):
    return [[char2bin(byte) for byte in segment] for segment in
            segmentString(text.encode(encoding), padding.encode(encoding), chunksize)]

This uses utf8 encoding, but since your input text is all ascii characters, there's one byte per character.

>>> framer('Hello, World!')
[[[0, 1, 0, 0, 1, 0, 0, 0],
  [0, 1, 1, 0, 0, 1, 0, 1],
  [0, 1, 1, 0, 1, 1, 0, 0],
  [0, 1, 1, 0, 1, 1, 0, 0],
  [0, 1, 1, 0, 1, 1, 1, 1],
  [0, 0, 1, 0, 1, 1, 0, 0],
  [0, 0, 1, 0, 0, 0, 0, 0],
  [0, 1, 0, 1, 0, 1, 1, 1]],
 [[0, 1, 1, 0, 1, 1, 1, 1],
  [0, 1, 1, 1, 0, 0, 1, 0],
  [0, 1, 1, 0, 1, 1, 0, 0],
  [0, 1, 1, 0, 0, 1, 0, 0],
  [0, 0, 1, 0, 0, 0, 0, 1],
  [0, 0, 1, 0, 1, 1, 0, 1],
  [0, 0, 1, 0, 1, 1, 0, 1],
  [0, 0, 1, 0, 1, 1, 0, 1]]]

Non-ascii characters require multiple bits to encode.

>>> framer('', padding='\x00')
[[[1, 1, 1, 1, 0, 0, 0, 0],
  [1, 0, 0, 1, 1, 1, 1, 1],
  [1, 0, 0, 1, 0, 0, 1, 0],
  [1, 0, 1, 0, 1, 0, 0, 1],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0]]]

You could either use list comprehensions or make use of the itertools module.

You can learn more about list comprehensions here, and more about itertootls here.

You can use below code to achieve your goal.

def segment_string(s, fill_by):
    l = []
    while s:
        if len(s) < 8:
            s = s + (fill_by) * (8 - len(s))

        l.append(s[0:8])
        s = s[8:]   

    return l  # ['Hello, W', 'orld!---']

def char2bin(ch):
    a = bin(ord(ch))[2:]
    l = [int(c) for c in a]

    if len(l) < 8:
        l = ([0] * (8 - len(l))) + l # Adding extra 0s to front (if len(l) < 8)

    return l # [0, 1, 0, 0, 1, 0, 0, 0]

def framer(s, fill_by='-'):
    segments = segment_string(s, fill_by) # Calling segment_string()
    print(segments)

    arr = []
    for segment in segments:
        arr2 = []
        for ch in segment:
            arr3 = char2bin(ch); # Calling char2bin()
            arr2.append(arr3)

        arr.append(arr2)

    return arr # final list to be returned


if __name__ == "__main__":
    f = framer('Hello, World!', '~')
    print(f)
Output »
[[[0, 1, 0, 0, 1, 0, 0, 0], [0, 1, 1, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1, 0, 0], [0, 1, 1, 0, 1, 1, 0, 0], [0, 1, 1, 0, 1, 1, 1, 1], [0, 0, 1, 0, 1, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 1, 1]], [[0, 1, 1, 0, 1, 1, 1, 1], [0, 1, 1, 1, 0, 0, 1, 0], [0, 1, 1, 0, 1, 1, 0, 0], [0, 1, 1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 1], [0, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 0]]]

# >>> bin(126)
# '0b1111110'
# >>>
# >>> chr(126)
# '~'
# >>>
Related