# Spelling Bee Acceptable

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);
}
}

• Could you include a test case? – Dennis Nov 9 '18 at 2:05
• 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. – Nathan Merrill Nov 9 '18 at 2:05
• Honestly, this is the easy part. Finding words that fit a partially revealed word is harder – Jo King Nov 9 '18 at 11:19
• I meant, this is the hard part of finding words that could ever be solutions. – NoLongerBreathedIn Nov 9 '18 at 19:56
• 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. – NoLongerBreathedIn Nov 10 '18 at 20:55

# 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!

# 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.

# 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)


# 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.


# 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


# JavaScript, 33 bytes

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


Try it online, using Dennis' test cases

# 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!

• Shouldn't 9 be 8? – Galen Ivanov Nov 9 '18 at 8:03
• Fixed. Weird, I could have sworn the OP said 8 was the max length allowed before. Anyway, ty... – Jonah Nov 9 '18 at 14:19

# 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

• Wow, w.chars.distinct.count. Turn each of those words into a symbol and you have a golfing language! xD – Quintec Nov 9 '18 at 12:56
• @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 – Kevin Cruijssen Nov 9 '18 at 13:06
• Hehe, also basically same for my APL answer. It meets in the middle: 11 bytes :P – Quintec Nov 9 '18 at 15:24

# 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.

# 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'

# C# (.NET Core), 58 bytes

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


Try It Online!

# 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!

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

# 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.

• 25 bytes: my%h;@h{/./g}=1;%h<8&&say (%h<8 requires Perl 5.26) – nwellnhof Nov 12 '18 at 12:25

# 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'

# Charcoal, 12 bytes

ΦＡ›⁸ＬΦι⁼μ⌕ιλ


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

 Ａ              Input array
Φ               Filter strings where
⁸            Literal 8
›             Is greater than
Ｌ           Length of
ι         Current string
Φ          Filtered on characters where
μ       Inner index
⁼        Equals
λ    Current character's
⌕      First index in
ι     Current string
Implicitly print matching strings

• 10? – ASCII-only Nov 18 '18 at 5:12

# Japt -f, 6 bytes

¬â Ê<8


Try it, using Dennis' test cases

# 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)

# 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


# 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