Skip to main content
Dennis shaved off 11
Source Link

grep and awk, 6868 56 bytes

The script:

echo $(grep`grep -o '[A-Za-z0-9_]*'|awk'\w*'|awk '!x[tolower(substr($0,1,1))]++')]++'`

Explanation:

  • grep -o matches the legal words, printing each on its own line.

  • awk takes the first letter of each line with substr, makes it lowercase, and then increments a hashtable entry with that key. If the value was 0unset before the increment, the line is printed.

  • echo $(...) turns the lines back into words

I previously tried to create a solution without awk, using uniq, sort, grep and bash but fell just short. History in the edits.

Thanks to Dennis for some improvements I missed.

grep and awk, 68 bytes

The script:

echo $(grep -o '[A-Za-z0-9_]*'|awk '!x[tolower(substr($0,1,1))]++')

Explanation:

  • grep -o matches the legal words, printing each on its own line.

  • awk takes the first letter of each line with substr, makes it lowercase, and then increments a hashtable entry with that key. If the value was 0 before the increment, the line is printed.

  • echo $(...) turns the lines back into words

I previously tried to create a solution without awk, using uniq, sort, grep and bash but fell just short. History in the edits.

grep and awk, 68 56 bytes

The script:

echo `grep -o '\w*'|awk '!x[tolower(substr($0,1,1))]++'`

Explanation:

  • grep -o matches the legal words, printing each on its own line.

  • awk takes the first letter of each line with substr, makes it lowercase, and then increments a hashtable entry with that key. If the value was unset before the increment, the line is printed.

  • echo ... turns the lines back into words

I previously tried to create a solution without awk, using uniq, sort, grep and bash but fell just short. History in the edits.

Thanks to Dennis for some improvements I missed.

grep and awk solution, instead of all that nonsense before!
Source Link

GNU coreutils plusgrep and awk, 13268 bytes

The script:

echo $(grep -o '[A-Za-z0-9_]*'>F
r=^\9_]*'|awk '!x[tolower($substr(for l in {a..z} {0..9} _;do grep -im1 ^$l F;done|tr \\n \|$0,1,1)~\)$
echo $(egrep "$r" F|awk '!x[$0]++']++')

Explanation:

  • grep -o matches the legal words, printing each on its own line, which we save to a file F.

  • Then we loopawk takes the 37 potential starting "letters".

  • For eachfirst letter we do a case insensitive searchof each line with -isubstr,

  •   makes it lowercase, and use -m1 to print only the first match (or nothing).

  • We combine the results intothen increments a regular expression called r, for example:

      r=^(are|dogs|Look|There|3|_|~)$
    
  • egrep useshashtable entry with that regexp to pull out only the desired wordskey.

  • But if any of If the desired words appear more than oncevalue was 0 before the increment, egrep will display all of them. So we use awk to remove the duplicatesline is printed.

  • Finally echo $(...) turns the lines back into space-delimited words. (This technique is not recommended for general use, since echo -n does not print -n!)

Using it:

$ echo "Look ^_^ .... There are 3 little dogs :)" | bash ./test.sh
Look _ There are 3 dogs

$ echo "Take all first words for each letter... this is a test" | bash ./test.sh
Take all first words each letter is

$ echo 'Oh no multiple no noooooo no argh!' | bash ./test.sh
Oh no multiple argh

I had initially hopedpreviously tried to usecreate a solution without sort|uniq -iw1awk but sort would always place "a" before "all". Since I had to use, using awkuniq in the end, I could have just gone for a shorter solution with awksort alone!, grep and bash but fell just short. History in the edits.

GNU coreutils plus awk, 132 bytes

The script:

grep -o '[A-Za-z0-9_]*'>F
r=^\($(for l in {a..z} {0..9} _;do grep -im1 ^$l F;done|tr \\n \|)~\)$
echo $(egrep "$r" F|awk '!x[$0]++')

Explanation:

  • grep -o matches the legal words, printing each on its own line, which we save to a file F.

  • Then we loop the 37 potential starting "letters".

  • For each letter we do a case insensitive search with -i,

  •   and use -m1 to print only the first match (or nothing).

  • We combine the results into a regular expression called r, for example:

      r=^(are|dogs|Look|There|3|_|~)$
    
  • egrep uses that regexp to pull out only the desired words.

  • But if any of the desired words appear more than once, egrep will display all of them. So we use awk to remove the duplicates.

  • Finally echo $(...) turns the lines back into space-delimited words. (This technique is not recommended for general use, since echo -n does not print -n!)

Using it:

$ echo "Look ^_^ .... There are 3 little dogs :)" | bash ./test.sh
Look _ There are 3 dogs

$ echo "Take all first words for each letter... this is a test" | bash ./test.sh
Take all first words each letter is

$ echo 'Oh no multiple no noooooo no argh!' | bash ./test.sh
Oh no multiple argh

I had initially hoped to use sort|uniq -iw1 but sort would always place "a" before "all". Since I had to use awk in the end, I could have just gone for a shorter solution with awk alone!

grep and awk, 68 bytes

The script:

echo $(grep -o '[A-Za-z0-9_]*'|awk '!x[tolower(substr($0,1,1))]++')

Explanation:

  • grep -o matches the legal words, printing each on its own line.

  • awk takes the first letter of each line with substr, makes it lowercase, and then increments a hashtable entry with that key. If the value was 0 before the increment, the line is printed.

  • echo $(...) turns the lines back into words

I previously tried to create a solution without awk, using uniq, sort, grep and bash but fell just short. History in the edits.

Post Undeleted by joeytwiddle
Fixed the final requirement with the help of awk
Source Link

GNU coreutils, 56 bytes but broken plus awk, 117 bytes but broken132 bytes

Use grep 37 times to pull out the first word for each letter. (56 bytes)The script:

grep -o '[A-Za-z0-9_]*'>F
echo r=^\($(for l in {a..z} {0..9} _;do grep -im1 ^$l F;doneF;done|tr \\n \|)~\)$
echo $(egrep "$r" F|awk '!x[$0]++')

Explanation:

  • -o matches legal words and prints each on its own line.

    grep -o matches the legal words, printing each on its own line, which we save to a file F.

  • -i is case-insensitive.

    Then we loop the 37 potential starting "letters".

  • -m1 prints just the first match.

    For each letter we do a case insensitive search with -i,

  • echo ... is a naughty way to turn the lines back into space-delimited words.

    and use -m1 to print only the first match (or nothing).

  • We combine the results into a regular expression called r, for example:

      r=^(are|dogs|Look|There|3|_|~)$
    
  • egrep uses that regexp to pull out only the desired words.

  • But if any of the desired words appear more than once, egrep will display all of them. So we use awk to remove the duplicates.

  • Finally echo $(...) turns the lines back into space-delimited words. (This technique is not recommended for general use, since echo -n does not print -n!)

But this does not preserve the original order of words in the input. That requirement wasn't explicitly stated in the question, butUsing it was heavily implied by the sample outputs.:

$ echo "Look ^_^ .... There are 3 little dogs :)" | bash ./test.sh
are dogs Look _ There are 3 _dogs

So in order to restore the original word order, we need one more grep, this time selecting all (any) of the desired words. (117 bytes)

grep -o '[A-Za-z0-9_]*'>F
r=^\($(for l in {a..z} {0..9} _;do grep -im1 ^$l F;done|tr \\n \|)~\)$
egrep "$r" F|trecho \\n"Take \all 

By way of explanation, this is the regexp you see if you echo "$r":

^(are|dogs|Look|There|3|_|~)$

Example use:

$first echowords "Lookfor ^_^each .letter... There are 3this littleis dogsa :)"test" | bash ./test.sh
LookTake _all Therefirst arewords 3each dogsletter is

Unfortunately that final grep will happily match a duplicated word more than once!

 
$ echo 'Oh no multiple no noooooo no argh!' | bash ./test.sh
Oh no multiple no no argh

So at this point I will admit defeat, throw up my hands, and just share what I have so far.


I had originallyinitially hoped to get a nice simple solution usinguse uniqsort|uniq -w1iw1, but removing duplicates requires sorting:

tr \  \\n|sort|uniq -iw1|tr \\n \ 

And sortsort would always place "a" before "and":

$ echo "Take all first words for each letter... this is a test" | bash ./test.sh
a each first is letter... Take words

I would love to hear from you if you know how to get sort to sort lines by the first character only, and otherwise preserve order. (I failed"all". Since I had to master sort'suse -kawk option.)

But even in that case, restoring the original order of the words appears to be difficult.

If only uniq could work on unsorted inputend, weI could have gotten away with it. And my answer would have been muchjust gone for a shorter too. ;-)solution with awk alone!

GNU coreutils, 56 bytes but broken, 117 bytes but broken

Use grep 37 times to pull out the first word for each letter. (56 bytes)

grep -o '[A-Za-z0-9_]*'>F
echo $(for l in {a..z} {0..9} _;do grep -im1 ^$l F;done)
  • -o matches legal words and prints each on its own line.
  • -i is case-insensitive.
  • -m1 prints just the first match.
  • echo ... is a naughty way to turn the lines back into space-delimited words.

But this does not preserve the original order of words in the input. That requirement wasn't explicitly stated in the question, but it was heavily implied by the sample outputs.

$ echo "Look ^_^ .... There are 3 little dogs :)" | bash ./test.sh
are dogs Look There 3 _

So in order to restore the original word order, we need one more grep, this time selecting all (any) of the desired words. (117 bytes)

grep -o '[A-Za-z0-9_]*'>F
r=^\($(for l in {a..z} {0..9} _;do grep -im1 ^$l F;done|tr \\n \|)~\)$
egrep "$r" F|tr \\n \ 

By way of explanation, this is the regexp you see if you echo "$r":

^(are|dogs|Look|There|3|_|~)$

Example use:

$ echo "Look ^_^ .... There are 3 little dogs :)" | bash ./test.sh
Look _ There are 3 dogs

Unfortunately that final grep will happily match a duplicated word more than once!

$ echo 'Oh no multiple no noooooo no argh!' | bash ./test.sh
Oh no multiple no no argh

So at this point I will admit defeat, throw up my hands, and just share what I have so far.


I had originally hoped to get a nice simple solution using uniq -w1, but removing duplicates requires sorting:

tr \  \\n|sort|uniq -iw1|tr \\n \ 

And sort would always place "a" before "and":

$ echo "Take all first words for each letter... this is a test" | bash ./test.sh
a each first is letter... Take words

I would love to hear from you if you know how to get sort to sort lines by the first character only, and otherwise preserve order. (I failed to master sort's -k option.)

But even in that case, restoring the original order of the words appears to be difficult.

If only uniq could work on unsorted input, we could have gotten away with it. And my answer would have been much shorter too. ;-)

GNU coreutils plus awk, 132 bytes

The script:

grep -o '[A-Za-z0-9_]*'>F
r=^\($(for l in {a..z} {0..9} _;do grep -im1 ^$l F;done|tr \\n \|)~\)$
echo $(egrep "$r" F|awk '!x[$0]++')

Explanation:

  • grep -o matches the legal words, printing each on its own line, which we save to a file F.

  • Then we loop the 37 potential starting "letters".

  • For each letter we do a case insensitive search with -i,

  • and use -m1 to print only the first match (or nothing).

  • We combine the results into a regular expression called r, for example:

      r=^(are|dogs|Look|There|3|_|~)$
    
  • egrep uses that regexp to pull out only the desired words.

  • But if any of the desired words appear more than once, egrep will display all of them. So we use awk to remove the duplicates.

  • Finally echo $(...) turns the lines back into space-delimited words. (This technique is not recommended for general use, since echo -n does not print -n!)

Using it:

$ echo "Look ^_^ .... There are 3 little dogs :)" | bash ./test.sh
Look _ There are 3 dogs

$ echo "Take all first words for each letter... this is a test" | bash ./test.sh
Take all first words each letter is
 
$ echo 'Oh no multiple no noooooo no argh!' | bash ./test.sh
Oh no multiple argh

I had initially hoped to use sort|uniq -iw1 but sort would always place "a" before "all". Since I had to use awk in the end, I could have just gone for a shorter solution with awk alone!

Post Deleted by joeytwiddle
Source Link
Loading