These have the same regex as in my regex answer. I felt it was worth posting a standalone answer showing its use in languages that don't require an import to access regex functions (resulting in very effective golf). In order of how favorably it compares against the current best non-regex answer.
This answer previously showed programs/functions that couldn't handle multiline input (as the challenge demonstrates is required by its second test case), but they all do so properly now unless otherwise noted.
Java, 46 bytes
a->a.matches("(?si:.*([A-Z])(?!.*\\1)){26}.*")
(46 bytes, always slow) - Try it online!
a->a.matches("(?si:.*?([A-Z])(?!.*\\1)){26}.*")
(47 bytes, slow for non-matches) - Try it online!
a->a.matches("(?si)(?>.*?([A-Z])(?!.*\\1)){26}.*")
(50 bytes, reasonable speed) - Try it online!
PHP, 53 or 55 bytes
PHP imposes a strict backtracking limit (or time limit?) on its regexes, so the version that would be 52 bytes doesn't work at all; it always returns an empty result (except for very short non-pangram strings, for which it prints 0
).
<?=preg_match('/(.*?(\pL)(?!.*\2)){26}/si',$argv[1]);
(53 bytes) - Try it online!
The 53 byte version, however, actually runs fast; it prints an empty result or 0
for false, and prints 1
for true. However, with sufficiently long pangram strings having a long separation between occurrences of new letters, it returns a false negative, due to taking too long to process the string.
<?=preg_match('/(?>.*?(\pL)(?!.*\1)){26}/si',$argv[1]);
(55 bytes) - Try it online!
<?=preg_match('/^(?>.*?(\pL)(?!.*\1)){26}/si',$argv[1]);
(56 bytes) - Try it online!
These versions print 0
for false and 1
for true.
This beats 640KB's answer when it is ported to handle multiline input:
<?=!array_diff(range(a,z),str_split(strtolower($argv[1])));
(59 bytes) - Try it online!
JavaScript ES9, 38 bytes
a=>/(.*([A-Z])(?!.*\2)){26}/si.test(a)
(38 bytes, always slow) - Try it online!
a=>/(.*?([A-Z])(?!.*\2)){26}/si.test(a)
(39 bytes, slow for non-matches) - Try it online!
a=>/((?=(.*?([A-Z])(?!.*\3)))\2){26}/si.test(a)
(47 bytes, fairly reasonable speed) - Try it online!
a=>/^((?=(.*?([A-Z])(?!.*\3)))\2){26}/si.test(a)
(48 bytes, very reasonable speed) - Try it online!
When looping this set of test cases, it can be seen that the 48 byte version is about 12 times as fast as the 47 byte version (in SpiderMonkey's regex engine).
This now ties in length with l4m2's answer, which counts individual regex matches. Given the speed difference, that answer obviously wins.
Ruby, 35 bytes
->s{s=~/(.*([A-Z])(?!.*\2)){26}/mi}
(35 bytes, always slow) - Try it online!
->s{s=~/(.*?([A-Z])(?!.*\2)){26}/mi}
(36 bytes, slow for non-matches) - Try it online!
->s{s=~/(?>.*?([A-Z])(?!.*\1)){26}/mi}
(38 bytes, fairly reasonable speed) - Try it online!
->s{s=~/^(?>.*?([A-Z])(?!.*\1)){26}/mi}
(39 bytes, very reasonable speed) - Try it online!
When looping this set of test cases, the same result is seen: the 39 byte version is 12 times as fast as the 38 byte version.
This is 2 bytes longer than Alexis Andersen's mixed code/regex answer.
Ruby -n0
, 30 bytes
Prints nil
for false and 0
for true, which are respectively falsey and truthy in Ruby. If printing 0
or 1
is desired, replace ~
with !!
(+1 byte).
p ~/(.*([A-Z])(?!.*\2)){26}/mi
(30 bytes, always slow) - Try it online!
p ~/(.*?([A-Z])(?!.*\2)){26}/mi
(31 bytes, slow for non-matches) - Try it online!
p ~/(?>.*?([A-Z])(?!.*\1)){26}/mi
(33 bytes, fairly reasonable speed) - Try it online!
p ~/^(?>.*?([A-Z])(?!.*\1)){26}/mi
(34 bytes, very reasonable speed) - Try it online!
This is 2 bytes longer than Alexis Andersen's answer when it is ported to be a full program using -n0
instead of a lambda (and it prints false
or true
):
p (?a..?z).all?{|c|~/#{c}/i}
(28 bytes) - Try it online!
Perl 5 -p0
, 28 bytes
$_=/(.*(\pL)(?!.*\2)){26}/si
(28 bytes, always slow) - Try it online!
$_=/(.*?(\pL)(?!.*\2)){26}/si
(29 bytes, slow for non-matches) - Try it online!
$_=/(?>.*?(\pL)(?!.*\1)){26}/si
(31 bytes, fairly reasonable speed) - Try it online!
$_=/^(?>.*?(\pL)(?!.*\1)){26}/si
(32 bytes, very reasonable speed) - Try it online!
This is 2 bytes longer than Xcali's regex + hash answer when its [a-z]
is replaced with \pL
. Also, for some reason that answer only requires the -p
command-line parameter yet still works with multiline input, while this one requires -p0
to do so.
Perl 5, 40 bytes
say@ARGV[0]=~/(.*(\pL)(?!.*\2)){26}/si+0
(40 bytes, always slow) - Try it online!
say@ARGV[0]=~/(.*?(\pL)(?!.*\2)){26}/si+0
(41 bytes, slow for non-matches) - Try it online!
say@ARGV[0]=~/(?>.*?(\pL)(?!.*\1)){26}/si+0
(43 bytes, fairly reasonable speed) - Try it online!
say@ARGV[0]=~/^(?>.*?(\pL)(?!.*\1)){26}/si+0
(44 bytes, very reasonable speed) - Try it online!
This is 4 bytes longer than a port of Xcali's regex + hash answer with [a-z]
replaced with \pL
:
++@a{(uc@ARGV[0])=~/\pL/g};say%a==26
(36 bytes) - Try it online!
Reading multiline input from stdin instead of a command-line argument would be 4 bytes longer, replacing @ARGV[0]
with join('',<>)
.