It's a bit overly clever. I am a huge fan of Peter Norvig (and he was once my skip-level boss), but I'd call this code out in a code review for being obtuse.
Notice that the input, `nums`, is a set. So he's taking the intersection of two sets. One set always has one item, so the result will be a collection with either 0 or 1 items.
It could have also been written as:
first(x * (2020 - x)
for x in nums
if (2020 - x) in nums and x != (2020 - x))
But that has a lot of duplication, so it'd probably be best to just use an imperative approach here and do something like:
def day1_1(nums):
"Find 2 distinct numbers that sum to 2020, and return their product."
for x in nums:
y = 2020 - x
if x == y:
continue
if y in nums:
return x * y
I am not sure I would advocate for this but, from Python 3.8, this is an instance where assignment expressions could allow the first code without duplication.
first(x * y
for x in nums
if (y := 2020 - x) in nums and x != y)
I agree, tuvistavie! But my default machine has 3.7 installed, and I didn't want to get too far ahead of readers. Sometime next year I'll go to 3.8, and look forward to using ":="
The "x == y" test looks like a bug to me, unless duplicate entries are not allowed. For example [1010,1010,1721,979,366,299,675,1456] should return 1010 * 1010, not 1721 * 299.
def day1_1(nums):
"Find 2 distinct numbers that sum to 2020, and return their product."
return first(x * y
for x in nums
for y in nums & {2020 - x}
if x != y)
`nums` is a set of integers
`nums & {2020 - x}` Finds all the numbers that are in the set of `nums` and the set of `{2020 - x}` - this basically extracts a number, `y`, for which `x+y = 2020`.
So for each x in nums, he extracts a number from nums that, added to x, equals 2020. If there is such a number y, he checks if it is the same as x, and only if it is different, does he yield in his generator, as the product of y and x.
{2020 - x} is a single item set. nums & {2020 - x} does set intersection with nums, which restricts nums to either the item that sums with x to 2020 or nothing if there is no such item in nums.