1
\$\begingroup\$

This is similar to this question. However, I have a different goal in mind: Reduce the wordlist to words that could appear. The easy part is to delete hyphens and similar.

The hard part, however: Remove words containing more than seven letters.

So, the problem:
Given a set of words containing only lowercase (or uppercase) ASCII letters, remove the words containing eight or more different letters.

Any input and output format is acceptable.

Standard loophole rules apply.

Shortest byte count wins.

Clever solutions are better, and faster is better as well.

My solution (implementing a quite clever O(n) algorithm, noncompetitive ref implementation):

#include <stdio.h>                                                              
#include <stdint.h>                                                             

int main(void) {                                                                
  char str[1024];                                                               
  while(scanf("%s\n", str) == 1) {                                              
    uint32_t st = 0;                                                            
    int s = 0;                                                                  
    for(char *p = str; *p && s <= 7; p++) {                                     
      s += ~st >> (*p - 'a') & 1;                                               
      st |= 1 << (*p - 'a');                                                    
    }                                                                           
    if(s <= 7)                                                                  
      printf("%s\n", str);                                                      
  }                                                                             
}
\$\endgroup\$
5
  • 5
    \$\begingroup\$ Could you include a test case? \$\endgroup\$
    – Dennis
    Commented Nov 9, 2018 at 2:05
  • 12
    \$\begingroup\$ It's generally bad practice to have an upper limit on the score. The reason is that some languages are especially verbose or difficult to program in, and the 307 byte requirement would arbitrarily disallow them from competing. \$\endgroup\$ Commented Nov 9, 2018 at 2:05
  • \$\begingroup\$ Honestly, this is the easy part. Finding words that fit a partially revealed word is harder \$\endgroup\$
    – Jo King
    Commented Nov 9, 2018 at 11:19
  • \$\begingroup\$ I meant, this is the hard part of finding words that could ever be solutions. \$\endgroup\$ Commented Nov 9, 2018 at 19:56
  • \$\begingroup\$ I meant O(n) where n is the length of the word. In other words, to deal with a word of length n, it does O(n) work. \$\endgroup\$ Commented Nov 10, 2018 at 20:55

19 Answers 19

4
\$\begingroup\$

APL (Dyalog Unicode), 11 bytes

{⍵/⍨8>≢∪⍵}¨

Takes input as a list of strings.

Explanation:

{⍵/⍨8>≢∪⍵}¨
{       ⍵}¨ for each word
       ∪    take unique letters
    8>≢     length less than 8 as a boolean (0 or 1)
 ⍵/⍨        repeat word that many times

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ the result contains empty strings. you can fix that preserving the byte count: ⊢(/⍨)8>≢∘∪¨ \$\endgroup\$
    – ngn
    Commented Nov 11, 2018 at 7:44
3
\$\begingroup\$

Perl 6, 20 bytes

*.grep(8>*.comb.Set)

Try it online!

Filters by words that have a set of letters with size less than 8.

\$\endgroup\$
3
\$\begingroup\$

05AB1E, 5 bytes

ʒÙg8‹

Try it online.

Explanation:

ʒ        # Filter the (implicit) input-list by:
 Ù       #  Only leave distinct letters of the word
  g      #  Take its length
   8‹    #  And only leave those with a length smaller than 8
         # (And output implicitly after we're done filtering)
\$\endgroup\$
2
\$\begingroup\$

Jelly, 6 bytes

Qṫ¥Ðḟ8

Try it online!

How it works

Qṫ¥Ðḟ8  Main link. Argument: A (array or words)

   Ðḟ   Filterfalse; only keep the words W of A for which the chain to the left
        returns a falsy value.
  ¥         Combine the two links to the left into a dyadic chain.
Q               Unique; remove duplicate letters from W.
 ṫ   8          Tail 8; remove the first 7 letters of the result.
\$\endgroup\$
2
\$\begingroup\$

MathGolf, 6 bytes

Ç{▀£7>

Try it online!

Explanation

Really similar to the 05AB1E solution, but I lose one byte thanks to explicitly having to define the code block for filtering.

Ç       Implicit faulty filter by block
 {      Start block
  ▀     Get unique characters of string
   £    Get length
    7>  Is greater than 7
\$\endgroup\$
2
\$\begingroup\$

J, 10 bytes

#~8>#@~.@>

explanation

#~ 8 > #@~.@>
#~                 NB. filter the input based on...
   8 >             NB. is 8 greater than...
       #@          NB. the length of...
         ~.@       NB. the unique characters of...
            >      NB. the unboxed input. 

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Shouldn't 9 be 8? \$\endgroup\$ Commented Nov 9, 2018 at 8:03
  • 1
    \$\begingroup\$ Fixed. Weird, I could have sworn the OP said 8 was the max length allowed before. Anyway, ty... \$\endgroup\$
    – Jonah
    Commented Nov 9, 2018 at 14:19
2
\$\begingroup\$

Java 8, 46 bytes

s->s.filter(w->w.chars().distinct().count()<8)

Try it online.

Explanation:

s->               // Method with String-Stream as both parameter and return-type
  s.filter(w->    //  Filter the words in the input-Stream by:
    w.chars()     //  Convert the String to characters
     .distinct()  //  Only leave distinct characters
     .count()<8)  //  Only leave words with less than 8 distinct characters
\$\endgroup\$
3
  • \$\begingroup\$ Wow, w.chars.distinct.count. Turn each of those words into a symbol and you have a golfing language! xD \$\endgroup\$
    – Quintec
    Commented Nov 9, 2018 at 12:56
  • \$\begingroup\$ @Quintec Hehe, it's what I do in my 05AB1E answer. :) s->s is implicit input in 05AB1E; filter(w-> is ʒ; .chars() is implicitly again; .distinct() is Ù; .count() (or length) is g; <8 is 8‹; and the closing ) is implicitly since it's at the end of the 05AB1E program (if I wanted to do something after the filter I'd have to close it with }); and finally outputting is implicitly again. So my Java and 05AB1E are similar, one is a 46 bytes function and the other a 5 bytes full program, though. xD \$\endgroup\$ Commented Nov 9, 2018 at 13:06
  • \$\begingroup\$ Hehe, also basically same for my APL answer. It meets in the middle: 11 bytes :P \$\endgroup\$
    – Quintec
    Commented Nov 9, 2018 at 15:24
1
\$\begingroup\$

Python 2, 40 bytes

lambda i:[x for x in i if len(set(x))<8]

Try it online!

Test cases borrowed from @Dennis. Input and output are both lists.

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

Red, 54 bytes

func[b][foreach a b[if 8 > length? unique a[print a]]]

Try it online!

The first test set was taken from Dennis'

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

JavaScript, 33 bytes

a=>a.filter(s=>new Set(s).size<8)

Try it online, using Dennis' test cases

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

C# (.NET Core), 58 bytes

 a=>a.Where(x=>x.GroupBy(y=>y).Count()<8)

Try It Online!

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

C (gcc), 104 95 bytes

Dennis's word set was also used here.

Thanks to nwellnhof for the suggestions.

char*s,*t;f(i,j,k){for(;~scanf("%ms",&s);i<8&&puts(s))for(i=j=0,t=s;*t;j=k)k=j|1<<*t++,i+=j<k;}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ 96 bytes, if you're OK with implementation- and undefined behavior. \$\endgroup\$
    – nwellnhof
    Commented Nov 9, 2018 at 10:15
  • \$\begingroup\$ @nwellnhof What's a little UD between friends for code golf? :-) \$\endgroup\$
    – ErikF
    Commented Nov 9, 2018 at 17:16
1
\$\begingroup\$

perl -nlE, 32 bytes

my%h;@h{/./g}=();say if keys%h<8

This reads words from STDIN, printing out those with less than 7 different characters.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 25 bytes: my%h;@h{/./g}=1;%h<8&&say (%h<8 requires Perl 5.26) \$\endgroup\$
    – nwellnhof
    Commented Nov 12, 2018 at 12:25
1
\$\begingroup\$

C++ (gcc), 105 104 bytes

#import<bits/stdc++.h>
f(){for(char*n;~scanf("%ms",&n);)std::set<int>(n,n+strlen(n)).size()<8&&puts(n);}

Try it online!

-1 byte thanks to @ceilingcat

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

Racket, 95 bytes

(require racket/set)(define(f l)(filter(lambda(x)(<(set-count(list->set(string->list x)))8))l))

Try it online!

The test set was taken from Dennis'

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

Charcoal, 12 bytes

ΦA›⁸LΦι⁼μ⌕ιλ

Try it online! Link is to verbose version of code. Explanation:

 A              Input array
Φ               Filter strings where
   ⁸            Literal 8
  ›             Is greater than
    L           Length of
      ι         Current string
     Φ          Filtered on characters where
        μ       Inner index
       ⁼        Equals
           λ    Current character's
         ⌕      First index in
          ι     Current string
                Implicitly print matching strings
\$\endgroup\$
1
  • \$\begingroup\$ 10? \$\endgroup\$
    – ASCII-only
    Commented Nov 18, 2018 at 5:12
0
\$\begingroup\$

Japt -f, 6 bytes

¬â Ê<8

Try it, using Dennis' test cases

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

JavaScript (ES6), 53 bytes

Without using a set:

a=>a.filter(w=>[...w].every(o=c=>o[c]=o[c]||--k,k=8))

Try it online! (using Dennis' test set)

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

Snap! 4, scratchblocks2 syntax

(pretending that Snap! exclusive blocks are valid in scratchblocks2 but functions use the Scratch define)

69 bytes

b takes a list of strings.

define((b)
report((#)keep items such that(<(length of [])<[7]>)from(b
\$\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.