hello
hello

Reputation: 65

Creating a list of bits?

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?

Upvotes: 2

Views: 304

Answers (3)

Håken Lid
Håken Lid

Reputation: 23064

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]]]

Upvotes: 1

hygull
hygull

Reputation: 8740

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)
# '~'
# >>>

Upvotes: 0

user4437749
user4437749

Reputation: 74

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.

Upvotes: 0

Related Questions