53
\$\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\$
2
  • 3
    \$\begingroup\$ Plus points if your code can check if input is a Pungram. \$\endgroup\$
    – Sainan
    Commented May 17, 2016 at 16:43
  • 14
    \$\begingroup\$ Question name request: Did the quick brown fox jump over the lazy dog? \$\endgroup\$
    – user54200
    Commented Aug 4, 2016 at 11:59

97 Answers 97

2
\$\begingroup\$

APL, 10 bytes

∧/⊃∊/⎕C⎕A⍞

Explanation:

⍞   ⍝ Character input and…
⎕A  ⍝ …alphabet are enclosed into a nested array
⎕C  ⍝ Convert both to lower case
∊/  ⍝ Put membership function between them
⊃   ⍝ Disclose the nested array
∧/  ⍝ Reduce by conjuction
\$\endgroup\$
2
\$\begingroup\$

Zsh --nocaseglob, 19 bytes

>_${1//\/}<*{a..z}*

Attempt This Online!

Outputs via exit code: 0 for pangram, 1 for non-pangram

If we don't have to handle the empty string, then the _ can be removed for -1 byte.

If we don't have to handle strings with slashes in them, the ${1//\/} can be changed to just $1 for -6 bytes:

Zsh --nocaseglob, 12 bytes

>$1<*{a..z}*

Attempt This Online!

Zsh ties APL and K, and beats J??

Explanation

  • $1: input
  • //\/: remove all slashes (because filenames can't contain them)
  • _: prepend underscore (because you can't create files with empty names, so we have to ensure it is non-empty)
  • >: create a file with that name
  • <*{a..z}*: search for files matching each of the patterns *a*, *b*, etc.

This effectively checks that the created file contains each letter between a and z. If any check fails, the program with exit with status code 1. Otherwise, it exits with 0.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ What's the shortest you can get without --nocaseglob? \$\endgroup\$
    – Deadcode
    Commented Jul 4, 2022 at 19:58
  • 1
    \$\begingroup\$ @Deadcode This 25 byter is the shortest I've got, but that also uses grep -i which is basically equivalent to --nocaseglob. Or here's 27 bytes without something like that. \$\endgroup\$
    – pxeger
    Commented Jul 4, 2022 at 20:06
  • 1
    \$\begingroup\$ @Deadcode Actually here's 22 bytes \$\endgroup\$
    – pxeger
    Commented Jul 4, 2022 at 20:10
  • \$\begingroup\$ Beats Japt, does it?! \$\endgroup\$
    – Shaggy
    Commented Sep 15, 2022 at 11:20
  • \$\begingroup\$ @Shaggy Oops, no. \$\endgroup\$
    – pxeger
    Commented Sep 15, 2022 at 11:51
2
\$\begingroup\$

K (ngn/k), 13 bytes

~#(!26)^97!_:

Try it online!

  • _: lowercase the (implicit) input
  • 97! mod the ASCII character codes by 97 (so a becomes 0, f 6, z 25, etc. etc.)
  • (!26)^ remove the character codes that are present from 0..25
  • ~# do any character codes corresponding to letters remain?

An alternative 14-byte answer is:

~26-/~"a{"'?_:

Try it online!

  • ?_: get the distinct lowercased characters in the input
  • ~"a{"' identify which characters in the input are letters (1 in the resulting bitmask) and which are not letters (these become 0s)
  • ~26-/ not the result of a minus-reduce seeded with 26 (if all letters are present in the input, this will return 1, and otherwise 0)
\$\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\$
1
  • \$\begingroup\$ I wanted to use .every but I couldn't figure out! :D Nice solution! \$\endgroup\$ Commented Dec 10, 2015 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\$

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\$
2
  • 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
    Commented Mar 12, 2019 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
    Commented Mar 13, 2019 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\$
2
  • \$\begingroup\$ ++a<=90; can be shortened by one byte to ++a<91;. \$\endgroup\$ Commented May 17, 2016 at 14:11
  • \$\begingroup\$ @KevinCruijssen Thanks. I've updated my answer based on your suggestion. \$\endgroup\$
    – rgettman
    Commented May 17, 2016 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\$
1
  • \$\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
    Commented Nov 1, 2016 at 8:06
1
\$\begingroup\$

Japt -!, 6 4 bytes

;CkU

Try it here

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

APL(NARS), 22 chars, 44 bytes

{∧/×↑+/↑¨{+/⍵=⎕a⎕A}¨⍵}

test:

  h←{∧/×↑+/↑¨{+/⍵=⎕a⎕A}¨⍵}
  h 'abcdefghijklmnopqrstuvwXYZ'
1
  h '123abcdefghijklm NOPQRSTUVWXYZ321'
1
  h 'public static void main(String[] args)'
0
  h 'The quick brown fox jumped over the lazy dogs. BOING BOING BOING'
1
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 9 6 bytes

⬤β№↧θι

Try it online! Link is to verbose version of code. Outputs a Charcoal boolean (- for true, nothing for false). Just checks that each lowercase letter appears at least once in the lowercase input Explanation:

 β      Lowercase alphabet
⬤       All characters satisfy
  №     (Non-zero) count of
     ι  Current lowercase letter in
    θ   First input
   ↧    Lowercased
        Implicitly print
\$\endgroup\$
1
\$\begingroup\$

Burlesque, 16 bytes

zzXX@azr@Jx/IN=s

Try it online!

                                                 [IN]
zz    # Lowercase input                          [in]
XX    # Split into characters                    [i,n]
@azr@ # Push lowercase alphabet                  [i,n],[a,..,z]
Jx/   # Duplicate and bring the input to the top [a,..,z],[a,..,z],[i,n]
IN    # Intersection of the two                  [a,..,z],alpha IN input
=s    # Is equal to the alphabet when sorted     1/0
\$\endgroup\$
1
\$\begingroup\$

Stax, 5 bytes

é►Ö_Z

Run and debug it

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

BaCon, 49 bytes

?IIF(AMOUNT(UNIQ$(EXPLODE$(LCASE$(s$))))>25,1,0)

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

Factor + math.unicode, 34 23 bytes

[ >lower ALPHABET ⊃ ]

Try it online!

-11 bytes thanks to @Bubbler!

Explanation:

This is a quotation (anonymous function) that takes a string as input and leaves a boolean value as output.

  • >lower Convert a string to lowercase.
  • ALPHABET Push a string containing the lowercase alphabet to the data stack.
  • Is the input a superset of the alphabet?
\$\endgroup\$
3
  • \$\begingroup\$ subset? is two bytes shorter than diff "" =. Kudos to all set operations working on plain sequences :) \$\endgroup\$
    – Bubbler
    Commented Mar 29, 2021 at 0:57
  • \$\begingroup\$ Also, if you accept to use sets.extras, you can shorten swap subset? further to superset? (which has that exact definition). \$\endgroup\$
    – Bubbler
    Commented Mar 29, 2021 at 1:09
  • \$\begingroup\$ @Bubbler Thanks for that insight. superset? also exists in math.unicode as for further reduction. \$\endgroup\$
    – chunes
    Commented Mar 29, 2021 at 2:01
1
\$\begingroup\$

C, 87 bytes

For platforms that use ASCII character coding.

f(char*s){char*t=s,i,r=0;for(;*t;)*t++|=32;for(i=97;i<123;)r|=!strchr(s,i++);return!r;}

This first modifies the input string to make it all lower-case (it doesn't matter what happens to non-letters, as they will not become letters or NUL). Then we test each lower-case letter to see whether it's present.

For an EBCDIC version, we need to replace *t++|=32; with *t++|=64; and for(i=97;i<123;) with for(i=193;i<234;i+=7*(i&16==9)+i==161).

Simple test program:

#include<stdio.h>
int main(int argc, char **argv)
{
    while (*++argv) {
        printf("%s: ", *argv);
        printf("%s\n", f(*argv) ? "Yes" : "No");
    }
}

Online test

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

Scratch, 145 bytes

define(s
set[z v]to[abcdefghijklmnopqrstuvwxyz
set[i v]to[
set[o v]to[1
repeat[26
change[i v]by(1
set[o v]to((o)*<(s)contains(letter(l)of(z
say(o

Uses scratchblocks syntax.

Function should have "Run before screen refresh" checked. Defines a function with an empty name and one argument (s). Output is 1 if s is a pangram and 0 if it is not.

<[]contains[]> works in scratchblocks syntax (which I used), but <[]contains[]?> is used in Scratch. This adds an extra byte, but because I'm using scratchblocks syntax, I don't think it should count.

\$\endgroup\$
2
  • \$\begingroup\$ set[i v]to((i)+(1 is a byte shorter than change[i v]by(1 if I've gotten my byte count correct. Also, very nice scratch answer! \$\endgroup\$
    – lyxal
    Commented Mar 30, 2021 at 21:40
  • \$\begingroup\$ @Lyxal Thanks, but it looks like it's two bytes longer to me. \$\endgroup\$
    – Bo_Tie
    Commented Mar 31, 2021 at 12:24
1
\$\begingroup\$

C, 64 bytes

n=63<<26;f(char*s){while(*s)n|=1<<(tolower(*s++)-97);return!~n;}

Explanation

  • Create a mask of 32-26 = 0b111111 = 63 and shl by 26 (you will understand why) with n=63<<26;

  • Iterate over string, set bit at index tolower(*s) - 'a' with while(*s)n|=1<<(tolower(*s++)-97);
    NB: Characters beyond 'z', {|}~, do not matter, as flags are already set.

  • Reverse all bits with ~, if all letters were encountered it should give 0, else it would give value of all letters that were missing in the char array. We return the opposite with !, so it becomes true if it is a pangram, else false.

\$\endgroup\$
3
  • \$\begingroup\$ Is n ever reseted on second call? \$\endgroup\$
    – l4m2
    Commented Apr 2, 2021 at 13:18
  • \$\begingroup\$ it is not, it is a trick to save 4 bytes (int and space), if you want it to be reset you just move n declaration inside the function (68 bytes). \$\endgroup\$ Commented Apr 2, 2021 at 16:02
  • \$\begingroup\$ 53 bytes \$\endgroup\$
    – c--
    Commented Aug 21, 2022 at 21:16
1
\$\begingroup\$

JavaScript (ES9), 38 bytes

a=>a.match(/$|([A-Z])(?!.*\1)/igs)[25]

Try it online!

$| just to not crash if there's no letter. Worth mentioned competitor

\$\endgroup\$
7
  • \$\begingroup\$ I like this; it may not be the shortest overall but it's the shortest that runs fast. Here is a JavaScript ES9 way of doing it: Try it online! Please note that it's good manners to credit the code your answer is based on. \$\endgroup\$
    – Deadcode
    Commented Apr 2, 2021 at 13:54
  • \$\begingroup\$ Oh damn, my ES9 variant isn't always correct: Try it online! it fails when the first character is a non-letter and there are 25 unique letters. \$\endgroup\$
    – Deadcode
    Commented Apr 2, 2021 at 14:08
  • 1
    \$\begingroup\$ @Deadcode We all missed that the +1 can be easily saved \$\endgroup\$
    – l4m2
    Commented Apr 2, 2021 at 14:26
  • \$\begingroup\$ Well done. But I suggest you name the language "JavaScript (ES6)" or "JavaScript ES6" because it doesn't have anything specific to SpiderMonkey (the test harness doesn't count). \$\endgroup\$
    – Deadcode
    Commented Apr 2, 2021 at 14:41
  • \$\begingroup\$ I just realized this doesn't accept multi-line input like the challenge requires. I've fixed my answer at +1 byte cost, and here's the same fix for yours: Try it online! – note that this requires changing your language spec to "JavaScript (ES9)". \$\endgroup\$
    – Deadcode
    Commented Apr 11, 2021 at 21:55
1
\$\begingroup\$

Fig, \$9\log_{256}(96)\approx\$ 7.408 bytes

lca+//KUa

Try it online!

Returns -1 for falsy, and a non-negative integer for truthy.

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

Uiua, 17 14 bytes

/↧/↥∊⊠+"aA"⇡26

Try it!

-3 thanks to Lynn

/↧/↥∊⊠+"aA"⇡26
           ⇡26  # 0..25
     ⊠+"aA"     # get lowercase and uppercase alphabet
    ∊           # masks of which letters are in the input
  /↥            # max of each column
/↧              # minimum
\$\endgroup\$
2
  • \$\begingroup\$ Interesting language! /↧/↥∊⊠+"aA"⇡26 seems to work. \$\endgroup\$
    – lynn
    Commented Oct 15, 2023 at 16:56
  • \$\begingroup\$ Ah geez that's smart. Thanks! \$\endgroup\$
    – chunes
    Commented Oct 15, 2023 at 17:04
0
\$\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\$
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
  • 2
    \$\begingroup\$ It only works for lowercase letters. \$\endgroup\$
    – Vasu Adari
    Commented Dec 11, 2015 at 7:45
  • \$\begingroup\$ More love for ruby! ->s{(?a..?z).all?{|x|s[/#{x}/i]}} is 33 bytes. \$\endgroup\$
    – blutorange
    Commented Dec 13, 2015 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\$
1
  • \$\begingroup\$ You don't need the curly braces here since there is only one statement, thus saving 2 bytes \$\endgroup\$
    – plannapus
    Commented Nov 1, 2016 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\$
3
  • 1
    \$\begingroup\$ The exit code works as valid truthy/falsy output, since an exit code is a valid way of outputting an integer. \$\endgroup\$ Commented Dec 10, 2015 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
    Commented Dec 12, 2015 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\$ Commented Dec 28, 2015 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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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