Your code looks pretty good for a newcomer to the language. Some comments:
- I don't quite understand why you need
uni
.
- References to
t[0]
and t[1]
: It's more declarative to unpack tuples/lists and give names to its components -> something, another_thing = t
for i in range(int(f.readline()))
. I won't say this is bad, but certainly not very declarative. Note that itertools.islice can be used to read N lines from a file object -> itertools.islice(f, 10)
.
- Python2: Unless you have a compelling reason, use Python 3.
reduce(lambda...
. As much as I like functional style, code that uses reduce
with long lambdas usually looks cryptic. But I think it's still ok to use reduce
with named functions.
int(f.readline())
. Personally I like to give names to values when it's not clear what they stand for. Granted, this may increase the LOC slightly, but I think it's worthwhile. In this case, if we write number_of_queries = int(f.readline())
and later use the variable, it's easy to see what's going on.
As a first refactor, I'd write:
import itertools
import functools
lines = open("input.txt")
# Parse associations
n_associations = int(lines.readline())
associations = {}
for line in itertools.islice(lines, n_associations):
n, associations_string = line.split(":")
associations[n] = set(associations_string.split())
# Parse and run queries
n_queries = int(lines.readline())
for line in itertools.islice(lines, n_queries):
numbers = line.split()
common = functools.reduce(set.intersection, (associations[n] for n in numbers))
print(" ".join(common))
Ok, now let's take it a step further. Firstly, there are no functions at all, no modularization, that's no good. Secondly, I prefer a functional approach and there is some imperative stuff going on there. That's how I would write it in a more functional and declarative style:
def parse_and_execute_queries(path):
def parse_association(line):
number, associations_string = line.split(":")
return (number, set(associations_string.split()))
def execute_query(associations, query_string):
numbers = query_string.split()
common = functools.reduce(set.intersection, (associations[n] for n in numbers))
return " ".join(common)
lines = open(path)
n_associations = int(lines.readline())
association_lines = itertools.islice(lines, n_associations)
associations = dict(parse_association(line) for line in association_lines)
n_queries = int(lines.readline())
queries_lines = itertools.islice(lines, n_queries)
return (execute_query(associations, line) for line in queries_lines)
for query_result in parse_and_execute_queries("input.txt"):
print(query_result)