HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Pangrams implementation using Linq

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementationlinqusingpangrams

Problem

This is a continuation of my LINQ stories from Pangrams-Hackerrank. Similarly, this challenge has been asked before in python Pangrams python Implementation but I have tried to accomplish this challenge using LINQ.

Here is a summary of the question


Roy wanted to increase his typing speed for programming contests. So, his friend advised him to type the sentence "The quick brown fox jumps over the lazy dog" repeatedly, because it is a pangram. (Pangrams are sentences constructed by using every letter of the alphabet at least once.)


After typing the sentence several times, Roy became bored with it. So he started to look for other pangrams.


Given a sentence , tell Roy if it is a pangram or not.


Input Format


Input consists of a string .


Constraints


Length of can be at most 103(1≤|s|≤103) and it may contain spaces, lower case and upper case letters. Lower-case and upper-case instances of a letter are considered the same.


Output Format


Output a line containing pangram if is a pangram, otherwise output not pangram.

Sample Input

Input #1

We promptly judged antique ivory buckles for the next prize


Input #2

We promptly judged antique ivory buckles for the prize


Sample Output

Output #1

pangram


Output #2

not pangram


Explanation

In the first test case, the answer is pangram because the sentence contains all the letters of the English alphabet.

Here is my implementation

```
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.IO;
class Solution {
static void Main(String[] args) {
/ Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution /

string pangramInput = Console.ReadLine();
var alphabet = Enumerable.Range(97, 26).Select((x) => (char)x);
var pangramCheck = pangramInput.Replace(" ", "").ToLower().OrderBy((letter) => letter).Dis

Solution

First a review...

Long extension chains

With lengthy linq chains it's a good idea to break them into multiple lines. Especially here on CR so that we don't have to scroll horizontally.

String interpolation

string answer = pangramCheck ? "pangram" : "not pangram";


We could optimize it as:

var answer = $"{(pangramCheck ? string.Empty : "not ")}pangram";


or you can make it even prettier by encapsulating this logic in an extension:

public static string Negate(this string value, bool negate)
{
    return $"{(negate ? string.Empty : "not ")}{value}";
}


so you then have:

Console.WriteLine("pangram".Negate(isPangram));


Consistency

string text
string answer


Don't you like var for strings because you already use for the other two variables? ;-)

Magic numbers

Enumerable.Range(97, 26)


This would be easier to understand if you used constants:

const string alphabetLength = z - a + 1;
Enumerable.Range('a', alphabetLength)


Not LINQ

.Replace(" ", "").ToLower()


This two kill the linq idea of your question. Consider this instead:

text
    .Select(char.ToLower)
    .Where(char.IsLetter)


Alternative solution

Then an alternative version...

If using a HashSet is still linq-ish enougth then I replaced the Distinct with the Aggregate that uses one and makes it na O(n) solution for the English aphabet:

const int alphabetLength = 'z' - 'a' + 1;
var isPangram =
    text
    .Select(char.ToLower)
    .Where(char.IsLetter)
    .Aggregate(new HashSet(), (acc, next) => { acc.Add(next); return acc; })
    .Count == alphabetLength;


UPDATE

Well, I forgot that we don't have to scan the entire string. As soon as we have the required chars we can stop. So this improved version should be faster for long texts:

const int alphabetLength = 'z' - 'a' + 1;
var chars = new HashSet();

var testedChars = text
    .Select(char.ToLower)
    .Where(char.IsLetter)
    .TakeWhile(x => { chars.Add(x); return chars.Count != alphabetLength; })
    .Count();

var isPangram = chars.Count == alphabetLength;

Code Snippets

string answer = pangramCheck ? "pangram" : "not pangram";
var answer = $"{(pangramCheck ? string.Empty : "not ")}pangram";
public static string Negate(this string value, bool negate)
{
    return $"{(negate ? string.Empty : "not ")}{value}";
}
Console.WriteLine("pangram".Negate(isPangram));
string text
string answer

Context

StackExchange Code Review Q#145790, answer score: 4

Revisions (0)

No revisions yet.