Solution to Dummy Packet Assembler (Task from r/dailyprogrammer)

I tried to solve the Packet Assembler task posted at r/dailyprogrammer.

The Question is this:

When a message is transmitted over the internet, it is split into multiple packets, each packet is transferred individually, and the packets are reassembled into the original message by the receiver. Because the internet exists in the real world, and because the real world can be messy, packets do not always arrive in the order in which they are sent. For today's challenge, your program must collect packets from stdin, assemble them in the correct order, and print the completed messages to stdout.

The point of reading from stdin is to simulate incoming packets. For the purposes of this challenge, assume there is a potentially unlimited number of packets. Your program should not depend on knowing how many packets there are in total. Simply sorting the input in its entirety would technically work, but defeats the purpose of this exercise.

Input Format is this:

Each line of input represents a single packet. Each line will be formatted as X Y Z some_text, where X Y and Z are positive integer and some_text is an arbitrary string. X represents the message ID (ie which message this packet is a part of). Y represents the packet ID (ie the index of this packet in the message) (packets are zero-indexed, so the first packet in a message will have Y=0, the last packet in a message will have Y=Z-1). Z represents the total number of packets in the message.

Here is the Python3 solution I did

from re import split

packets[p_id] = {}
packets[p_id]["len"] = len
packets[p_id]["packets"] = {}

return packets

def add_packet(packets, p_id, p_num, p_len, msg):
if p_id not in packets.keys():

if p_num > packets[p_id]["len"]:
return packets

packets[p_id]["packets"][p_num] = msg

return packets

def main():
packets = {}
while True:
try:
recv = split(r'\s+', input())

int(recv[2]), " ".join(recv[3:]))
except EOFError:
break

for p_id in sorted(packets):
for packet in range(packets[p_id]["len"]):
print("%d %d %d %s" %(p_id, packet, packets[p_id]["len"], packets[p_id]["packets"][packet]))

if __name__ == '__main__':
main()


Please rate this solution and suggest some improvements that can be made?

• Rate this solution is rather subjective (reviewers don't rate code on this site), but you'll definitely receive feedback and improvements on any/all aspects of the code. – Mathieu Guindon Oct 13 '17 at 13:38
• @Mat'sMug I mean just reviewing it. – Jøê Grèéñ Oct 19 '17 at 14:47

I think this code is very straightforward and easy to read. Good job!

Some nitpicks are,

You have a few PEP8 violations none all that concerning.

1. Should add a second white line between imports and your functions
2. Line too long, at your print statement
3. Continuation line under-indented for visual indent
4. printf style formatting is recommended against

Code suggestions

I would use a namedtuple instead of a dictionary, since it is much cleaner looking and easier to use. When to use a namedtuple!

Using the above suggestions and adhering PEP8 I get the following.

from re import split
from collections import namedtuple

def get_messages():
Message = namedtuple('Message', 'idx num length message')
messages = []

while True:
try:
recv = split(r'\s+', input())
messages.append(Message(recv[0], recv[1], recv[2], ' '.join(recv[3:])))
except EOFError:
return messages

def print_messages(messages):
for message in messages:
print("{}  {} {} {}"
.format(message.idx, message.num, message.length, message.message))

def main():
messages = sorted(get_messages(), key=lambda x: (x.idx, x.num))
print_messages(messages)

if __name__ == '__main__':
main()

• Thanks! TBH i am not too familiar with NamedTuples, that's why I don't use them! Thanks for PEP8s too! – Jøê Grèéñ Oct 19 '17 at 14:52