Vyxal 3, 46 bytes
eƛ~ɾ“ʀS:u;ka=1&1FwṪ}∑"ƛƛiṬ▲2⎇¨\ø¹∧F_:w«⎂?[⑴”$%
The counts are:
Perfect: 49
Pangram: 132
Neither: 819
Expects the input to be a single string with each list item on its own line (I tried list input, but there was something weird happening with the input parser with that many items).
Yes, that really is 46 bytes. Vyxal 3 uses a custom Single Byte Character Set (SBCS) to encode programs in a visually appealing way. The raw bytes are:
65 01 7E E2 FE E0 53 3A 75 3B 6B 61 3D 31 26 31 46 77 E5 7D 82 22 01 01 69 E4 E3 32 0E 1C 5C FC A7 EA 46 5F 3A 77 8A 18 3F 5B 14 FF 24 25
Algorithm Explained
The core idea here is to iterate over each string in the input, determine whether it's perfect, a normal pangram, or neither, and collect the results into a single list.
For each string in the input, it needs to be stripped of any non-letter characters and converted to lowercase. This makes the string easier to manipulate. These will be referred to as "modified strings"
Checking for a perfect pangram is easy - a modified string is a perfect pangram if, when sorted, it equals the string "abcdefghijklmnopqrstuvwxyz" (represented as ka in the code - there's shortcut for it).
Checking for a normal pangram requires an extra step of removing duplicate letters after sorting.
Within the program, the results of checking each category of pangramness is stored in a list like [isPerfect, isPangram]. This will be one of [1, 1], [0, 1], [0, 0].
While helpful, this does not lend itself well to separating perfect and normal pangram counts - if you try to aggregate a list of these lists via summing, perfect pangrams will be double counted. And it also does not account for the count of non-pangrams.
Therefore, I do a little code golf magic (TM) to turn this list into something that distinctly identifies whether a string is perfect, pangram, or neither. My thinking here was that the main differing feature is the index of the first 1 in the list. This would map perfect pangrams to 0 and normal pangrams to 1. However, this still doesn't account for non-pangrams.
To remedy this, I append a 1 to the [isPerfect, isPangram] list to ensure there is always a 1, consequently mapping non-pangrams to 2.
0, 1, and 2 are then mapped to [1,0,0], [0,1,0] and [0,0,1] respectively (i.e. a 1 is placed at the corresponding index). This neatly represents [isPerfect, isPangramButNotPerfect, isNeither].
Such a list of lists can then be summed column-wise to get the final result.
Notably, there's some additional nuance to how this is all done during program execution. But this high level explanation is enough to explain pretty much what's going on here.
Program Explained
eƛ~ɾ“ʀS:u;ka=1&1FwṪ}∑"ƛƛiṬ▲2⎇¨\ø¹∧F_:w«⎂?[⑴”$%
e # Split the input on newlines
ƛ } # To each candidate string:
~ɾ # Remove all non-letter characters (i.e. filter by isLetter)
“ # Convert to a single string because the filter leaves the string as a list of characters
ʀ # Convert that to lowercase. We'll call this string x
S:u; # Create a list of [sorted(x), uniqueLettersOnly(sorted(x))]
ka= # And compare each item in that list to the string "abcdefghijklmnopqrstuvwxyz". This automatically performs the equality check for each item in the list through automatic vectorisation (think APL type array programming)
1& # Append a 1 to that list
1Fw # And find the first 1 in that list. You'll need to read the algorithm overview to understand why I'm doing this.
Ṫ # Create a list of at most 3 items where the item at index (first 1) is 1, and where every other item is 0
∑ # Sum the entire list to be left with the list [perfect, pangram, neither]
"ƛƛiṬ▲2⎇¨\ø¹∧F_:w«⎂?[⑴” # This is just a compressed representation of the string "Perfect: %\nPangram: %\nNeither: %". The `%`s will be used for string formatting.
$% # Format that string with the items of the list we summed. The items in the list will be corresponded to the format string, so the first `%` will be replaced with `perfect`, the second `%` will be replaced with `pangram` and the third `%` will be replaced with `neither`.
💎
Explaination created with the help of Luminespire. It's a code explaination formatting tool I made for the fine folk of the Code Golf StackExchange. Notably, there's 0 AI involved with the tool.