42
\$\begingroup\$

Write a function or program that takes as its input a string and prints a truthy value if the string is a pangram (a sequence of letters containing at least one of each letter in the English alphabet) and a falsey value otherwise.

Case of letters should be ignored; If the string is abcdefghijklmnopqrstuvwXYZ, then the function should still return a truthy value. Note that the string can contain any other characters in it, so 123abcdefghijklm NOPQRSTUVWXYZ321 would return a truthy value. An empty input should return a falsey value.


Test cases

AbCdEfGhIjKlMnOpQrStUvWxYz

==> True


ACEGIKMOQSUWY
BDFHJLNPRTVXZ

==> True


public static void main(String[] args)

==> False


The quick brown fox jumped over the lazy dogs. BOING BOING BOING

==> True

This is code golf. Standard rules apply. Shortest code in bytes wins.

\$\endgroup\$
  • 3
    \$\begingroup\$ Plus points if your code can check if input is a Pungram. \$\endgroup\$ – timmyRS May 17 '16 at 16:43
  • 4
    \$\begingroup\$ Question name request: Did the quick brown fox jump over the lazy dog? \$\endgroup\$ – user54200 Aug 4 '16 at 11:59

63 Answers 63

2
\$\begingroup\$

PowerShell v3+, 65 56 52 Bytes

($args.ToLower()-split''|sls [a-z]|group).Count-eq26

Thanks to TessellatingHeckler for the 9-byte golf.

  • Takes the input string, converts it .ToLower()case, then -splits on every character
  • Those are fed into an alias sls for Select-String which matches based on a regex [a-z] to pull out only the letters
  • Those are then fed into Group-Object, so we're only selecting one individual instance of each letter
  • That is then .Counted to see if it's -equal to 26, and prints True or False accordingly
  • Requires PowerShell v3 or newer for the sls alias
\$\endgroup\$
  • \$\begingroup\$ It's a lot easier to pinch someone else's effort and try and shorten it a bit, than to read the questions from scratch - and more fun to compete within PowerShell than to go directly up against CJam and friends. But I can stop chasing your answers if it's annoying, sorry. \$\endgroup\$ – TessellatingHeckler Dec 15 '15 at 16:58
  • \$\begingroup\$ @TessellatingHeckler Not annoying! :D I'm just trying to give you more encouragement! \$\endgroup\$ – AdmBorkBork Dec 15 '15 at 18:00
2
\$\begingroup\$

Batch, 126 + 2 = 128 bytes

@set p="%*"
@for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z)do @set q=!p:%%a=!&if !q!==!p! exit/b 1
@exit/b

Requires CMD /V /C <filename> <input string> so I added 2 bytes for the /V. Alternative 87 + 2 + 26 = 115 byte version:

@set p="%*"
@for %%a in (?)do set q=!p:%%a=!&if !q!==%p% exit/b 1
@exit/b

(+26 for the files named a, b, c ... z that need to exist in the current directory.)

\$\endgroup\$
2
\$\begingroup\$

Rust, 64 bytes

|s:&str|(65u8..91).all(|c|s.to_uppercase().contains(c as char))

You can take a range over chars in Rust,

'a'..'{'

but it's presently useless since you can't iterate over it or collect it or do anything with it. They say arithmetic with characters doesn't make sense, so they won't implement the Add and One traits for it.

Still, lambdas and iterators and type inference keeps it reasonably small.

\$\endgroup\$
2
\$\begingroup\$

Haskell, 43 bytes

f s=until(all(`notElem`s))(succ<$>)"Aa">"["

Try it online!

Iterates through the lowercase/uppercase pairs until it finds one where both are not elements of the input, and checks that this failure is past the alphabet.

\$\endgroup\$
1
\$\begingroup\$

Seriously, 14 13 12 bytes

,ûOk"A["Ox-Y

Hex Dump:

2c964f6b22415b224f782d59

Try it online!

Explanation:

,                  read in the string from stdin
 û                 make it uppercase
  O                push all the character codes to the stack
   k               listify the stack
    "A["           push this string 
        O          pop it and push all of its character codes 
         x         push range(65,91)
          -        do set subtraction with the lists
           Y       logical not the result (so a zero length list becomes 1)

EDIT: moved input to the beginning to save a byte, thanks to @Mego

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 80

I wrote out a solution virtually identical to edc65's entry before I scrolled to the bottom of the page and saw it was already there! Anyway, here's still another alternate JavaScript approach:

s=>[...Array(26)].every((v,i)=>~s.search(RegExp(String.fromCharCode(i+65),"i")))

My original solution (83) with toUpperCase, before I got the idea to use a case-insensitive RegExp from Cᴏɴᴏʀ O'Bʀɪᴇɴ's solution:

s=>[...Array(26)].every((v,i)=>~s.toUpperCase().indexOf(String.fromCharCode(i+65)))

The code uses every to test whether or not every value of i from 0 to 25 casues the expression String.fromCharCode(i+65) to produce a character that exists in the input string (according to a case-insensitive match).

\$\endgroup\$
  • \$\begingroup\$ I wanted to use .every but I couldn't figure out! :D Nice solution! \$\endgroup\$ – Conor O'Brien Dec 10 '15 at 19:26
1
\$\begingroup\$

Mathematica, 44 bytes

Characters@ToLowerCase@#~SubsetQ~Alphabet[]&

Usage:

In[1]:= Characters@ToLowerCase@#~SubsetQ~Alphabet[]&[
         "The quick brown fox jumps over the lazy doge."]

Out[1]= True
\$\endgroup\$
1
\$\begingroup\$

C#, 91 bytes

Requires (18 bytes):

using System.Linq;

Actual function (73 bytes):

bool P(string s)=>s.ToUpper().Distinct().Where(x=>x>64&&x<91).Count()>25;

How it works: the function first converts everything to uppercase, then removes all duplicates and only keeps the letters. If count of items in the resulting enumerable exceeds 25 (then it must be 26), it's a pangram.

\$\endgroup\$
  • \$\begingroup\$ && can be golfed to &, and bool p(string s)=> can be golfed to s=> \$\endgroup\$ – Kevin Cruijssen Feb 22 '18 at 14:28
1
\$\begingroup\$

PHP, 92 bytes

The code:

echo!array_diff(range(a,z),array_keys(array_count_values(str_split(strtolower($argv[1])))));

There is not much golfing in it (the clear code is 102 bytes).

Prepend it with the PHP marker <?php (technically, it is not part of the code), put it into a file (is-it-a-pangram.php) and run it like:

$ php -d error_reporting=0 is-it-a-pangram.php '123abcdefghijklm NOPQRSTUVWXYZ321'

Or put the code directly in the command line:

$php -d error_reporting=0 '... the code here ...' AbCdEfGhIjKlMnOpQrStUvWxYz

It outputs 1 when the input string is a pangram; it doesn't output anything when the string is not a pangram. This is the default representation for boolean values in PHP.

An unambiguous output can be obtained by adding a + sign in front of the echo-ed expression (echo+!array_diff(...);). This way, the boolean value is converted to an integer (1 or 0).

How the code works

It makes the input string lowercase, splits it to individual characters, count the number of occurrences for each character that appears in the string, then makes the difference between the alphabet characters (a to z) and the characters found in the string. If the difference is not empty then not all the letters are found in the string (i.e. the string is not a pangram).

The code and the testcase (using the samples provided in the question) can be found on Github.

\$\endgroup\$
  • 1
    \$\begingroup\$ You actually don't need the array_keys(array_count_values()) at all, and can get the score down to 63. tio.run/… Otherwise your answer is virtually the same as the second one I just posted for this! :) \$\endgroup\$ – 640KB Mar 12 at 17:53
  • \$\begingroup\$ Indeed, sometimes I am not seeing the simplest solution and I tend to find complicated ways to solve the problems. \$\endgroup\$ – axiac Mar 13 at 10:39
1
\$\begingroup\$

Java, 97 96 bytes

boolean s(String t){for(int a=65;++a<91;)if(t.toUpperCase().indexOf(a)<0)return 1<0;return 0<1;}

Assumes ASCII or compatible character encoding.

It loops over the capital letters (65-90), checking if each one is present with indexOf, which takes an int.

\$\endgroup\$
  • \$\begingroup\$ ++a<=90; can be shortened by one byte to ++a<91;. \$\endgroup\$ – Kevin Cruijssen May 17 '16 at 14:11
  • \$\begingroup\$ @KevinCruijssen Thanks. I've updated my answer based on your suggestion. \$\endgroup\$ – rgettman May 17 '16 at 19:35
1
\$\begingroup\$

R, 97 92 bytes

Not competing with @mnel's excellent answer, but nevertheless :

function(s){a=strsplit(s,"")[[1]];m=match;sum(unique(c(m(a,letters,0),m(a,LETTERS,0))))=351}

This function takes your input, breaks it into its letters (strsplit), matches (match function, obviously) each letters of the input with both letters and LETTERS, built-in constant containing lowercases and uppercases letters. The unmatched positions are replaced with 0's.

Then, it eliminates all the redundant positions (unique), and make their sum. Considering there are 26 letters in the alphabet and the 1-indexed positions in R, if all the letters are contained at least once in your input, the sum of their positions will be 1+2+...+25+26, which is 351

- 5 bytes thanks to @plannapus !

\$\endgroup\$
  • \$\begingroup\$ if you were defining a as strsplit(s,"")[[1]] you wouldn't have to repeat a[[1]] twice and thus save 5 bytes. \$\endgroup\$ – plannapus Nov 1 '16 at 8:06
1
\$\begingroup\$

J, 23 bytes

(u:65+i.26)*/@e.toupper

Try it online!

\$\endgroup\$
1
+100
\$\begingroup\$

APL (Dyalog Extended), 6 bytes

∧/⎕A∊⌈

Try it online!

Explanation:

∧/⎕A∊⌈  ⍝ Monadic function train
      ⌈  ⍝ Convert the input to uppercase
  ⎕A∊   ⍝ For each item in the set of uppercase
         ⍝ letters, determine if it exists in the
         ⍝ uppercased input
∧/       ⍝ And-reduce: test if all letters exist
\$\endgroup\$
1
\$\begingroup\$

MathGolf, 11 7 bytes

!▀_▄+▀=

Try it online!

Explanation

MathGolf just got a lowercase operator!, ! is the factorial operator for ints, floats and lists, but now it also works as a lowercase operator for strings.

!          convert input to lowercase
 ▀         get unique characters as string
  _        duplicate
   ▄+      add the lowercase alphabet to the second copy
     ▀=    get unique elements and check that they are unchanged
\$\endgroup\$
1
\$\begingroup\$

Retina, 20 bytes

T`L`l
D`.
C`[a-z]
26

Try it online!

Explained

T`L`l        Transliterate stage. Replaces uppercase letters with lowercase letters.
D`.          Deduplicate stage - keep one copy of every match (meaning every character in this case), discarding suplicates.
C`[a-z]      Count stage - Count lowercase letters
26           (implicit) Count stage - Match the string "26"
             (Since there can't be duplicates, a match means each character occurred once.)
             (output the result of the last stage - 1 for pangrams, 0 for non-pangrams)
\$\endgroup\$
0
\$\begingroup\$

SpecBAS - 107 bytes

1 INPUT a$: LET a$=UP$(a$),c=0
2 FOR EACH l$ IN ["A" TO "Z"]: IF POS(l$,a$)>0 THEN INC c: NEXT l$
3 TEXT c=26

Set a counter to 0, loops through "A" to "Z" and increments the counter if found. Prints 0 (false) or 1 (true) if counter is 26.

\$\endgroup\$
0
\$\begingroup\$

Mumps, 86 bytes

R S F I=65:1:90{S J(I)=0} F I=1:1:$L(S){S Q=$A($E(S,I)) S:Q>92 Q=Q-32 K J(Q)} W '$D(J)

I built an array of nodes with all the ordinals of upper case characters, took the ordinal of each character in the string, converted lowercase to uppercase if necessary, and killed the associating node in the array. Here's my routine a bit more 'ungolfed':

R S                   ; Read STDIN into S
F I=65:1:90{S J(I)=0} ; Create an array of J() with all the uppercase ASCII ordinals
F I=1:1:$L(S)         ; loop through the # of characters in S
    {S Q=$A($E(S,I))  ; Set Q=the ordinal number of each character
    S:Q>92            ; if Q>92 (above the upper case, below the lower case ordinals
    Q=Q-32            ; subtract 32 from Q to convert to upper case.
    K J(Q)}           ; Kill the J(Ordinal) node of the array.
    W '$D(J)          ; $D will output False if there's no nodes in the array, true if some remain. \
                      ; write out the binary 'NOT' of this value.

The braces enable one-liners a bit more easily (multiple lines could add a few characters) and is a function of InterSystems Cache's version of Mumps.

\$\endgroup\$
0
\$\begingroup\$

Ruby, 39 33 bytes

This is the case insensitive version.

->s{(?a..?z).all?{|x|s[/#{x}/i]}}

Ruby, 32 bytes

Invalid (lowercase only)

No one has posted a ruby answer yet, so I made this. Nice and simple.

->s{(?a..?z).all?{|x|s.index x}}
\$\endgroup\$
  • 2
    \$\begingroup\$ It only works for lowercase letters. \$\endgroup\$ – Vasu Adari Dec 11 '15 at 7:45
  • \$\begingroup\$ More love for ruby! ->s{(?a..?z).all?{|x|s[/#{x}/i]}} is 33 bytes. \$\endgroup\$ – blutorange Dec 13 '15 at 20:22
0
\$\begingroup\$

C, 97 bytes

c;t=26;i=26;f[26];p(char*s){while(*s)(c=*s++&~32-65)>=0&c<t?f[c]=1:0;while(i)t-=f[--i];return!t;}

Assumes ASCII or compatible character encoding.

C is not the best tool when it comes to string-related golf, nevertheless it was fun to code.

Globals are not reset, so this function will work as expected only once, but, hey, nobody said it should work the second time! ;-)

Test main:

#include <stdio.h>

int main(int argc, char **argv) {
  if (argc < 2) {
    fprintf(stderr, "Usage: %s <phrase>\n", argv[0]);
    return 1;
  }

  printf("%d\n", p(argv[1]));
}
\$\endgroup\$
0
\$\begingroup\$

R, 77 bytes

g=function(x){length(intersect(unlist(strsplit(tolower(x),"")),letters))==26}

Test cases:

> g("AbCdEfGhIjKlMnOpQrStUvWxYz")
[1] TRUE
> g("ACEGIKMOQSUWY
+ BDFHJLNPRTVXZ")
[1] TRUE
> g("public static void main(String[] args)")
[1] FALSE
> g("The quick brown fox jumped over the lazy dogs. BOING BOING BOING")
[1] TRUE
> g("")
[1] FALSE
\$\endgroup\$
  • \$\begingroup\$ You don't need the curly braces here since there is only one statement, thus saving 2 bytes \$\endgroup\$ – plannapus Nov 1 '16 at 8:19
0
\$\begingroup\$

Groovy, 57 bytes

u={print it.toLowerCase().toList().containsAll('a'..'z')}

Will groovy ever win?

\$\endgroup\$
0
\$\begingroup\$

Bash 4+, 86 48 bytes

Thanks to @Dennis for saving me 38 bytes!

Since return codes are what's checked by test/[ for truthy-ness in bash, the return code should be valid truthy/falsy output, right? If not, I'll edit to echo more typical truthy/falsy values (since bash true/false values are inverted compared to most things)

for x in {a..z}
{ [[ ${1,,} =~ $x ]] || exit 1
}
\$\endgroup\$
  • 1
    \$\begingroup\$ The exit code works as valid truthy/falsy output, since an exit code is a valid way of outputting an integer. \$\endgroup\$ – a spaghetto Dec 10 '15 at 19:56
  • 1
    \$\begingroup\$ 1. do and done can be replaced with { and }. 2. [[ ... ]]||exit 1 is shorter than if...fi. 3. I don't think the tr command is required at all; ${1,,} =~ $x should work just fine. \$\endgroup\$ – Dennis Dec 12 '15 at 13:58
  • \$\begingroup\$ @Dennis I think my tr command got leftover from when I was doing the search more as "is each character of the input in {a..z}" and it just never occurred to me to remove it when I changed that. Wouldn't have caught the other stuff, still getting the hang of this golfing thing \$\endgroup\$ – SnoringFrog Dec 28 '15 at 16:20
0
\$\begingroup\$

C++, 121 bytes

int P(char *s){int c;bitset<26> a;while(c=*s){c=tolower(c)-'a';if(c>=0&&c<26)a.set(c);if(a.all())return 1;s++;}return 0;}
\$\endgroup\$
0
\$\begingroup\$

32-bit x86 machine code, 27 bytes

In hex:

31c031d2ac48780d344024df3c1977f40fabc2ebef31d0c1e006c3

Input: ESI: NULL-terminated string. Returns: EFLAGS.ZF (1=truthy, 0=falsey).

0:  31 c0               xor eax, eax  
2:  31 d2               xor edx, edx  ;Bit array to keep track of letters
_loop :
4:  ac                  lodsb         ;Read next char
5:  48                  dec eax       ;Align 'A' to the power of two boundary, i.e. 0x40
6:  78 0d               js _break     ;...which also tests for NULL
8:  34 40               xor al, 0x40  ;Swap block [0x40..0x7f] (with letters) with [0..0x3f]
a:  24 df               and al, 0xdf  ;Map [0x60..0x7f] to [0x40..0x5f], that's toupper()
c:  3c 19               cmp al, 25    ;Letter are now in the [0..25] range
e:  77 f4               ja _loop      ;Anything else is greater if taken as unsigned
10: 0f ab c2            bts edx, eax  ;Set AL-th bit in EDX
13: eb ef               jmp _loop     
_break :
15: 31 d0               xor eax, edx  ;EAX=~EDX (EAX==-1 here), for pangram EDX==0x03FFFFFF
17: c1 e0 06            shl eax, 6    ;Shift out 6 unused bits. EFLAGS.ZF=EAX<<6==0?1:0
1a: c3                  ret           
\$\endgroup\$
0
\$\begingroup\$

Javascript (using external library - Enumerable) (83 bytes)

 n=>_.From("abcdefghijklmnopqrstuvwxyz").All(x=>_.From(n.toLowerCase()).Contains(x))

Link to library: https://github.com/mvegh1/Enumerable

Code explanation: Load the lowercase alphabet as char array, then test that every single char is contained in the lowercased input

enter image description here

\$\endgroup\$
0
\$\begingroup\$

Java 8, 69 bytes

s->s.toUpperCase().chars().distinct().filter(c->c>64&c<91).count()>25

Alternatives with same byte count:

s->s.chars().map(c->c&~32).distinct().filter(c->c>64&c<91).count()>25
s->s.chars().map(c->c|32).distinct().filter(c->c>96&c<123).count()>25

Try it online.

Similar to @ProgramFOX' C# answer.

\$\endgroup\$
0
\$\begingroup\$

K4, 12 bytes

Solution

&/.Q.a in\:_

Examples:

q)k)&/.Q.a in\:_"AbCdEfGhIjKlMnOpQrStUvWxYz"
1b
q)k)&/.Q.a in\:_"ACEGIKMOQSUWY\nBDFHJLNPRTVXZ"
1b
q)k)&/.Q.a in\:_"public static void main(String[] args)"
0b
q)k)&/.Q.a in\:_"The quick brown fox jumped over the lazy dogs. BOING BOING BOING"
1b

Explanation:

Lowercase the input, check whether each letter in a..z is in this. Take the min.

&/.Q.a in\:_ / the solution
           _ / lowercase
       in\:  / apply in to left and each-right (\:)
  .Q.a       / "abcdefghijklmnopqrstuvwxyz"
&/           / take the minimum
\$\endgroup\$
0
\$\begingroup\$

Perl 5 -p, 30 bytes

$_=lc;@a{/[a-z]/g}++;$_=26==%a

Try it online!

\$\endgroup\$
0
\$\begingroup\$

PHP, 59 bytes

<?=!array_diff($a=range(a,z),str_split(strtolower($argn)));

Try it online!

Alt version 67 bytes

<?=array_intersect($a=range(a,z),str_split(strtolower($argn)))==$a;

Try it online!

Call with php -nF input is from STDIN.

\$\endgroup\$
0
\$\begingroup\$

Japt -!, 6 4 bytes

;CkU

Try it here

\$\endgroup\$
  • \$\begingroup\$ Due to a quirk in how S.k() works, you actually don't need the v :-) \$\endgroup\$ – ETHproductions Feb 23 '18 at 20:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.