I'm looking for any possible improvements in terms of memory usage and speed, but really any advice is welcome.
Problem statement:
John has discovered various rocks. Each rock is composed of various elements, and each element is represented by a lower-case Latin letter from 'a' to 'z'. An element can be present multiple times in a rock. An element is called a gem-element if it occurs at least once in each of the rocks.
Given the list of rocks with their compositions, display the number of gem-elements that exist in those rocks.
Input Format
The first line consists of an integer, , the number of rocks. Each of the next lines contains a rock's composition. Each composition consists of lower-case letters of English alphabet.
Constraints Each composition consists of only lower-case Latin letters ('a'-'z'). length of each composition
Output Format
Print the number of gem-elements that are common in these rocks. If there are none, print 0.
My code: Essentially I build N lists of True or False values (since the number of times the same element appears doesn't matter), and at the end just "and" them two by two using reduce to end up with a final list of True values for the elements that were True in each rock, and then just sum up the True values.
import sys
from functools import reduce
# this is just to get test cases input
N = int(input())
strings = []
for i in range(N):
strings.append(input())
# actual implementation starts here
lists = [[False] * 26 for i in range(N)]
for i in range(N):
for c in strings[i]:
# ord() gives the ASCII value of a character
lists[i][ord(c) - ord('a')] = True
final_list = reduce(lambda x, y: [x[i] and y[i] for i in range(26)], lists)
print(reduce(lambda x, y: x + y, final_list))