grep { len($_) == 10 && /^[^a]*a[^a]*$/i && /^[^b]*b[^b]*$/i && /^[^c]*c[^c]*$/i && /k.$/i } @words;
Is there a simpler way? grep { len($_) == 10 && /^[^a]*a[^a]*$/i && /^[^b]*b[^b]*$/i && /^[^c]*c[^c]*$/i && /k.$/i } @words;
Is there a simpler way? $ grep '^........k.$' /usr/share/dict/words | grep a | grep b | grep c | grep -v 'a.*a' | grep -v 'b.*b' | grep -v 'c.*c'
backstroke
bailiwicks
benchmarks
branchlike
bushwhacks
greenbacks
matchbooks
piggybacks
roadblocks
scrapbooks
slingbacks
throwbacks
thumbtacks [me@fedora ~]$ time perl -n -e 'length($_) == 10 && /^[^a]*a[^a]*$/i && /^[^b]*b[^b]*$/i && /^[^c]*c[^c]*$/i && /k.$/i && print' /usr/share/dict/words | wc -l
26
real 0m0,168s
user 0m0,162s
sys 0m0,007s
[me@fedora ~]$ time perl -n -e '/^(?=.{8}k.$)(?=[^a]*a[^a]*$)(?=[^b]*b[^b]*$)(?=[^c]*c[^c]*$)/ && print' /usr/share/dict/words | wc -l
17
real 0m0,260s
user 0m0,254s
sys 0m0,006s
[me@fedora ~]$ time perl -n -e '/^.{8}k.$/ && /a/ && /b/ && /c/ && !/a.*a/ && !/b.*b/ && !/c.*c/ && print' /usr/share/dict/words | wc -l
17 real 0m0,115s
user 0m0,109s
sys 0m0,008s
[me@fedora ~]$ time bash -c "grep '^........k.\$' /usr/share/dict/words | grep a | grep b | grep c | grep -v 'a.*a' | grep -v 'b.*b' | grep -v 'c.*c'" | wc -l
17
real 0m0,015s
user 0m0,010s
sys 0m0,020s
[me@fedora ~]$ time awk '/^.{8}k.$/ && /a/ && /b/ && /c/ && !/a.*a/ && !/b.*b/ && ! /c.\*c/ { print }' /usr/share/dict/words | wc -l
17
real 0m0,129s
user 0m0,124s
sys 0m0,006s
[me@fedora ~]$ time perl -n -e 'local $_ = lc; length == 11 && substr($_,8,1) eq "k" && join("",sort [/([abc])/g]->@*) eq "abc" && print' /usr/share/dict/words | wc -l
17 real 0m0,234s
user 0m0,228s
sys 0m0,007s sed -e '/^........k.$/!d; /a/!d; /b/!d; /c/!d; /a.*a/d; /b.*b/d; /c.*c/d' /usr/share/dict/words
I wouldn't expect it to be much faster than AWK, but not much slower either.Interesting that the pipeline is the fastest! I would expect the sheer number of separate processes to slow things down considerably, but apparently it doesn't really matter. Probably because the first `grep` already filters out most of the dictionary, so there isn't a lot of I/O through the pipes.
[me@fedora ~]$ time sed -e '/^........k.$/!d; /a/!d; /b/!d; /c/!d; /a.*a/d; /b.*b/d; /c.*c/d' /usr/share/dict/words | wc -l
17
real 0m0,075s
user 0m0,070s
sys 0m0,006sThe IO doesn’t matter so much because they’re done in parallel. Whereas the other examples have to filter each word throw the entirety of their steps before they can proceed onto the next word.
[me@fedora ~]$ time perl -n -e 'length($_) == 11 && /^[^a]*a[^a]*$/i && /^[^b]*b[^b]*$/i && /^[^c]*c[^c]*$/i && /k.$/i && print' /usr/share/dict/words | wc -l
17
real 0m0,160s
user 0m0,153s
sys 0m0,008s ^(?=.{8}k.$)(?=[^a]*a[^a]*$)(?=[^b]*b[^b]*$)(?=[^c]*c[^c]*$) $ perl -ne 'print if /^(?=.{8}k.$)(?=[^a]*a[^a]*$)(?=[^b]*b[^b]*$)(?=[^c]*c[^c]*$)/' /usr/share/dict/words perl -ne '/^(?=([abc].*){3})(?!.*([abc]).*\2).{8}k.$/&&print' /usr/share/dict/words [me@fedora ~]$ time perl -ne '/^(?=([abc].*){3})(?!.*([abc]).*\2).{8}k.$/&&print' /usr/share/dict/words | wc -l
6
real 0m0,118s
user 0m0,112s
sys 0m0,007s [me@fedora ~]$ time perl -ne 'print if /^(?=.{8}k.$)(?=[^a]*a[^a]*$)(?=[^b]*b[^b]*$)(?=[^c]*c[^c]*$)/' /usr/share/dict/words | wc -l
17
real 0m0,250s
user 0m0,245s
sys 0m0,006s my @found = grep {
local $_ = lc;
length == 10 &&
substr($_,8,1) eq "k" &&
join("",sort [/([abc])/g]->@*) eq "abc"
} @words;