22
\$\begingroup\$

An Abecedarian Word is a word whose letters are in alphabetical order. Your goal is to write a program that outputs all abecedarian words from a given lexicon.

Rules:

  1. Standard Loopholes are forbidden.

  2. If a word contains punctuation, diacritical marks, or any characters other than ASCII alphabet characters (A-Za-z), remove the entire word.

  3. Words that are abecedarian in ASCII are not necessarily abecedarian for this challenge. For example 'Maddox' shouldn't be considered abecedarian.

  4. Your program should work with any lexicon, but for testing purposes, this one can be used. (If my code works properly) It contains 588 587 abecedarian words that follow the above rules. The lexicon does not count towards your byte total. https://gist.githubusercontent.com/wchargin/8927565/raw/d9783627c731268fb2935a731a618aa8e95cf465/words

  5. As per the request of @Olivier Grégoire, here are the Abecedarian words from the lexicon:
    A Abbott Abby Abe Abel Ac Acrux Aden Ag Ainu Al Alps Am Amos Amy Ann Apr Ar Art As At Au Av B BMW Be Begin Bell Bellow Ben Benny Benz Berry Bert Bess Best Betty Bi Biko Bill Billy Bk Blu Boru Br Btu C Cd Celt Cf Chi Chimu Chou Ci Cl Cm Co Coors Cory Cox Coy Cr Crux Cruz Cs Cu D Dee Deimos Deity Del Dell Dem Denny Depp Di Dino Dior Dis Dix Dot Dow Dr E Eggo Elmo Eloy Emmy Emory Enos Er Es Eu F Finn Finns Flo Flory Fm Fox Fr Fry G Gil Gill Ginny Gino Ginsu Gipsy Guy H Hill Hiss Ho Hz I Ill In Io Ir It Ivy J Jo Joy Jr K Knox Kory Kr L Ln Lot Lott Lou Lr Lt Lu Luz M Mn Mo Moor Moors Mort Moss Mott Mr Mrs Ms Mt N Nov Np O Oort Orr Os Oz P Pt Pu Q R Ru Rx S St Stu T Ty U V W X Y Z a abbess abbey abbot abet abhor abhors ably abort abuzz accent accept access accost ace aces achoo achy act ad add adder adders adds adept ado adopt ads adz aegis aery affix afoot aft aglow ago ah ahoy ail ails aim aims air airs airy all allot allow alloy ally almost alms am ammo amp amps an annoy ant any apt art arty as ass at ax ay b be bee beef beefs beefy been beep beeps beer beers bees beet befit beg begin begins begot begs bell bellow bells belly below belt bent berry best bet bevy bill billow billowy bills billy bin bins biopsy bit blot blow boo boor boors boos boost boot booty bop bops boss bossy bow box boy brr buy buzz by c cell cello cellos cells cent chi chill chills chilly chimp chimps chin chino chinos chins chintz chip chips chit choosy chop choppy chops chow city clop clops clot cloy coo coop coops coos coot cop cops copy cost cosy cot cow cox coy crux cry cs d deem deems deep deeps deer deers deft defy deity dell dells demo demos den dens dent deny dew dewy dill dills dilly dim dims din dins dint dip dips dirt dirty dis diss ditty divvy do door doors dopy dory dos dot dotty dry e eel eels eery effort egg eggs egis ego egos eh ell ells elm elms em empty ems emu envy err errs es ex f fill fills filly film films filmy fin finny fins fir firs first fist fit fix fizz floor floors flop floppy flops floss flow flu flux fly foot fop fops for fort forty fox foxy fry fuzz g ghost gill gills gilt gimpy gin gins gipsy girt gist glop glory gloss glossy glow gnu go goo goop gory got gs guy h hi hill hills hilly hilt him hims hint hip hippy hips his hiss hit ho hoop hoops hoot hop hops horsy hos host hot how i ill ills imp imps in inn inns ins is it ivy j jot joy k kW knot knotty know ks l lo loop loops loopy loot lop lops lorry loss lost lot low lox ls m moo moor moors moos moot mop mops moss mossy most mow ms mu my n no nor nosy not now nu o oops opt or ow ox p pry psst q r rs s sty t tux u v w x y z

  6. This is , so the shortest code in bytes wins!

\$\endgroup\$
2
  • 2
    \$\begingroup\$ I just wanted to say I really like this challenge! \$\endgroup\$ – AJFaraday May 11 at 16:01
  • 2
    \$\begingroup\$ Please add the list of the 587 abecedarian words. \$\endgroup\$ – Olivier Grégoire May 12 at 14:58

22 Answers 22

5
\$\begingroup\$

05AB1E, 6 bytes

Ties a stone arachnid's Vyxal answer for #1.

áʒlD{Q

Try it online!

áʒlD{Q  # full program
áʒ      # all elements of...
        # implicit input...
á       # containing only letters...
 ʒ      # where...
        # (implicit) current element in filter...
  l     # in lowercase...
     Q  # is equal to...
   D    # (implicit) current element in filter...
  l     # in lowercase...
    {   # sorted
        # (implicit) exit filter
        # implicit output
\$\endgroup\$
0
7
\$\begingroup\$

Jelly, 9 bytes

fØẠŒlÞ$ƑƇ

Try it online!

-3 bytes thanks to Nick Kennedy

fØẠŒlÞ$ƑƇ  Main Link
        Ƈ  Keep elements that are
       Ƒ   Invariant when
.[][.]$    Last two links combined, but [ØẠ][ŒlÞ] is an LCC, so it takes another
f          Filtered to keep
 ØẠ        Alphabetical characters
     Þ     And sorted by
   Œl      Lowercase

Basically, "keep elements that are invariant when you filter out non-alphabetical characters and sort alphabetically". Jelly's sort is stable.

\$\endgroup\$
1
  • \$\begingroup\$ @NickKennedy Oh clever, thanks. \$\endgroup\$ – hyper-neutrino May 11 at 16:29
5
\$\begingroup\$

Raku, 32 36 bytes

*.grep:{!/<-[a..z]>/&[le] .comb}o&lc

Try it online!

*.grep: filters the input list on the provided predicate function, which is combined from two other functions using the o function composition operator. The right function (the first to be applied) is the built-in lowercasing function lc. The left, brace-delimited function contains the main logic for this challenge. That function contains two checks, separated by &.

/<-[a..z]>/ is a regex that matches any character other than the lowercase Latin letters "a" through "z". The leading ! negates that test, matching only words containing no such characters.

.comb splits the input string into individual characters. [le] reduces that list of characters with le, which is the less-than-or-equal operator for strings. That's equivalent to char₁ le char₂ le ... le charₙ, which is true if the sequence of characters is lexically monotonically nondecreasing.

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

JavaScript (ES6), 68 bytes

a=>a.filter(w=>(w=w.toLowerCase())==w.match(/[a-z]/g).sort().join``)

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You could save 3 bytes with \w instead of [a-z], unless you want to account for words that include underscores and numbers. \$\endgroup\$ – Sheik Yerbouti May 12 at 0:35
  • 5
    \$\begingroup\$ @SheikYerbouti According to the challenge spec, we are supposed to filter out any word containing any characters other than ASCII alphabet characters. So I'll stick to [a-z]. \$\endgroup\$ – Arnauld May 12 at 6:30
4
\$\begingroup\$

J, 34 32 bytes

#~(-:-.&Alpha_j_-.~[/:toupper)&>

Try it online!

-2 thanks to xash

  • #~ Filter by...
  • (-:]/:toupper)&> Words that are equal to themselves when sorted by their uppercase values...
  • -. And then removing...
  • -.&Alpha_j_ All characters not in [A-Z][a-z].
\$\endgroup\$
0
4
\$\begingroup\$

><>, 86 bytes

10i::}:0(?;a=?v:'['(?v::'`{'@)@(*@:@1+(@}**{10.
+$0.?v0[>100. >~~31. >' ␕'@
  =0l< o^?

Try it online! (The represents the character 0x15.)

Verification

It takes a few minutes, but it works:

C:\Users\conorob\Programming\fish
λ time python fish.py abc.fish <words.txt >out.txt

real    5m18.932s
user    0m0.000s
sys     0m0.031s

C:\Users\conorob\Programming\fish
λ wc out.txt
 587  587 3209 out.txt

Process

First, I like to get a functional program working, even if it is not golfy. 133 bytes:

1001.
>i::}:0(?;a=?v:'['(?v    >::'`{'@)@(*@:@1+(@}**{
                    >' '+^
             >~~?v0[ >1001.
                 >l?!^o

There's a lot of wasted whitespace in this one. So, first, I'll flip line 3 up onto line 1. Then, I'll reorganize the last two lines to occupy more of the trailing spaces, including reversing the last line. 113 bytes:

1001.               >' '+v
>i::}:0(?;a=?v:'['(?^    >::'`{'@)@(*@:@1+(@}**{
     0[>1001.>~~?v
      o^!?l      <

Now that the last line is more flexible, we can move even more of the last two lines into the leading whitespace. 101 bytes:

1001.               >' '+v
>i::}:0(?;a=?v:'['(?^    >::'`{'@)@(*@:@1+(@}**{
 ~~?v0[>1001.>
   l< o^!?

I tried reversing lines 3/4, but that ended up longer because the direction changed. But, now that we made more room on line 3, we can reverse the lowercase procedure back onto line 2. However, to do this, we need to make line 3 jump back to its start before it reaches the lowercase procedure. This is easy to do, since we have a spare leading whitespace. 92 bytes:

1001.
>i::}:0(?;a=?v:'['(?v    >::'`{'@)@(*@:@1+(@}**{
 ~~?v0[>1001.>02.   >' '+^
   l< o^!?

We can shave that wasted space in the loop using a very questionable technique. 91 bytes:

1001.
>i::}:0(?;a=?v:'['(?v::'`{'@)@(*@:@1+(@}**{
 ~~?v0[>1001.>02.   >' ␔'@+$1.
   l< o^!?

I've replaced the unprintable 0x14 here with its unicode equivalent . This bit works by generating a string ' ␔', which gives the values on the stack [char, 32, 20]. The original code computed [char+32], then resumed control flow. We want to use a jump instead of arrow directions, and the point we want to jump to is (1, 20) in the codebox. @ permutes these three values to give us [20, char, 32]. We then perform the sum and move it below 20 (+$), giving us [char+32, 20]. Then, we push 1 and jump to (1, 20) (1.).

We can shave 1 more byte, by using the last bit of extra space on line 4 to save on the ! character. 90 bytes:

1001.
>i::}:0(?;a=?v:'['(?v::'`{'@)@(*@:@1+(@}**{
 ~~?v0[>1001.>02.   >' ␔'@+$1.
 =0l< o^?

We can reorganize this once again, to eliminate the first line. This, however, is still, 90 bytes:

10i::}:0(?;a=?v:'['(?v::'`{'@)@(*@:@1+(@}**{10.
  ~~?v0[>100. >01.   >' ␕'@+$0.
  =0l< o^?

However, this gives us a little more whitespace to play with, allowing us to tuck more of our code into the leading whitespace. 86 bytes:

10i::}:0(?;a=?v:'['(?v::'`{'@)@(*@:@1+(@}**{10.
+$0.?v0[>100. >~~31. >' ␕'@
  =0l< o^?

This has reduced our Unnecessary Space Count™ to 5. At this point, I'm not quite sure where to go. By my reckoning, either the logic ('`{'@)@(*@:@1+(@}**{) must be golfed, or the fundamental structure/approach to the problem must be reworked.

\$\endgroup\$
4
\$\begingroup\$

R, 89 76 bytes

function(d,`+`=lapply)d[gsub('[^A-Z]',21,d+toupper)+utf8ToInt+is.unsorted<1]

Try it online!

Implemented as function taking a strings vector and filtering non-abecedarians out

Steps:

  1. make the string uppercase
  2. replace any non letter character with '21' (i.e. two descending ASCII char)
  3. turn strings into ASCII code points
  4. take only the strings where the code points are sorted
\$\endgroup\$
7
  • \$\begingroup\$ It's been a long time since I golfed in R... I'm very rusty and I expect there's room for big improvements \$\endgroup\$ – digEmAll May 11 at 16:13
  • \$\begingroup\$ Fails for .a (forgot to add something like this in my test case) \$\endgroup\$ – hyper-neutrino May 11 at 16:23
  • \$\begingroup\$ Ouch... we should remove words with punctuation... that's a bit hard in R... \$\endgroup\$ – digEmAll May 11 at 16:26
  • \$\begingroup\$ @digEmAll It's the equivalent of keeping only words with only letters. \$\endgroup\$ – Makonede May 11 at 16:29
  • 1
    \$\begingroup\$ Ok, I missed that part, sorry and thanks for pointing it out \$\endgroup\$ – digEmAll May 11 at 16:33
4
\$\begingroup\$

Ruby -p, 29 + 1 = 30 bytes

$_=$_[/^#{[*?a..?z]*?*}*\s/i]

Try it online!

Uses a regex composed by the letters "a" to "z" joined by "*" to find the words.

\$\endgroup\$
4
+50
\$\begingroup\$

Vyxal a, 9 8 6 bytes

-2 thanks to @Aaron Miller

'⇩:sǍ=

Try it Online!

'⇩:sǍ=   # Full program
         # All inputs (implicit)
'        # where...
 ⇩       # the lowercase version...
     =   # is equal to...
 ⇩:s     # the sorted lowercase version...
    Ǎ    # with only alphabetical characters
         # Implicit output
\$\endgroup\$
1
  • 1
    \$\begingroup\$ ka↔ can be replaced with Ǎ for 6 bytes \$\endgroup\$ – Aaron Miller May 13 at 15:27
3
\$\begingroup\$

Pip -rl, 14 bytes

$LE"az"JLC_FIg

Try it online!

Explanation

             g  List of lines read from stdin (due to -r flag)
           FI   Filter on this function:
        LC_      The string, lowercased
   "az"J         and inserted between "a" and "z"
$LE              is sorted in ascending ASCII order (fold on string-less-than-or-equal)
                Output each element of the result list on a separate line (-l flag)
\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Extended), 18 14 bytes

-4 bytes thanks to Adám!

⊢⌿⍨(∧≡∩∘⎕A)¨∘⌈

Try it online!

¨∘⌈ for each uppercased word:
∩∘⎕A the word intersected with 'AB ... YZ', keeping duplicate letters.
the word sorted ascending.
are those strings equal?

⊢⌿⍨ select words from the input where the result is a 1.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ ⊢⌿⍨(∧≡∩∘⎕A)¨∘⌈ \$\endgroup\$ – Adám May 12 at 7:02
  • \$\begingroup\$ @Adám thanks a lot! I tried ∧≡⎕A∩⊢, but didn't consider might be non-commutative. \$\endgroup\$ – ovs May 12 at 8:01
3
\$\begingroup\$

Java (JDK), 74 bytes

l->l.filter(s->{int p=65,r=1;for(var c:s)r=p>(p=c&95)?0:r;return p<r*91;})

Try it online!

Credits

\$\endgroup\$
3
  • 1
    \$\begingroup\$ -2 bytes by changing r=0 to r=1, ?1 to ?0 and r<1&p<91 to p<r*91. \$\endgroup\$ – Kevin Cruijssen Jun 14 at 10:50
  • 1
    \$\begingroup\$ @KevinCruijssen Nice! You found the optimization I was looking for! I was sure this kind of golf could be done, but I was stuck on trying to optimize on p*r<91 which was the wrong way, as you've just shown me :) \$\endgroup\$ – Olivier Grégoire Jun 14 at 11:08
  • \$\begingroup\$ Yeah, I at first was trying to find something with p*r as well, but realized the <91 would than still be truthy for both cases. If it would have been p>91 it would have been easier. But then it hit me to just put it at the r*91 for p<91/p<0. :) Nice answer, btw! \$\endgroup\$ – Kevin Cruijssen Jun 14 at 12:09
2
\$\begingroup\$

Python 3.8 (pre-release), 68 bytes

lambda x:[y for y in x if y.isalpha()and sorted(f:=y.upper())==[*f]]

Try it online!

Yeah! now Python ties with Javascript!

-24 thanks to @makonede

-5 thanks to @hyper-neutrino

\$\endgroup\$
6
  • 1
    \$\begingroup\$ -2 by removing one pair of parentheses around the assignment expression, since you don't actually need to surround it with extra brackets when already inside some \$\endgroup\$ – Makonede May 11 at 16:06
  • 1
    \$\begingroup\$ -22: lambda x:[y for y in x if y.isalpha()and''.join(sorted(f:=y.upper()))==f] \$\endgroup\$ – Makonede May 11 at 16:27
  • 1
    \$\begingroup\$ -5: lambda x:[y for y in x if y.isalpha()and sorted(f:=y.upper())==[*f]] \$\endgroup\$ – hyper-neutrino May 11 at 16:33
  • 2
    \$\begingroup\$ -3: lambda x:[y for y in x if sorted(f:=y.upper())*y.isalpha()==[*f]] \$\endgroup\$ – dingledooper May 11 at 18:10
  • 5
    \$\begingroup\$ abcdé should be rejected but is accepted \$\endgroup\$ – MarcMush May 11 at 21:31
2
\$\begingroup\$

Factor + math.unicode, 68 bytes

[ [ >upper dup [ LETTER? ] ∀ swap [ <= ] monotonic? and ] filter ]

Try it online!

  • [ ... ] filter Take words from the lexicon for which the quotation returns t.
  • >upper Uppercase the word so case doesn't mess with the test for monotonicity later.
  • dup [ LETTER? ] ∀ Does it only consist of (uppercase) letters?
  • swap [ <= ] monotonic? and And is it also sorted?
\$\endgroup\$
2
\$\begingroup\$

Retina 0.8.2, 61 bytes

^
$'¶
T`L`l`^.+
^
$%'¶
O`\G.
%)`^(.+¶)(\1|.+¶.+)

Gi`^[A-Z]+$

Try it online! Link includes test cases. Explanation:

^
$'¶

Duplicate the word.

T`L`l`^.+

Lowercase the duplicate.

^
$%'¶

Duplicate the lowercased word.

O`\G.

Sort the letters of the lowercase duplicate.

^(.+¶)(\1|.+¶.+)

If the sorted lowercase equals the lowercase word, delete the lowercase and sorted lowercase, otherwise delete everything.

%)`

Run the above stages on each word separately.

Gi`^[A-Z]+$

Keep only words containing letters.

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 18 bytes

ΦA⬤↧ι›№βλ∧μ‹λ↧§ι⊖μ

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

 A                  Input as an array
Φ                   Filtered where
    ι               Current element
   ↧                Lowercased
  ⬤                 All characters satisfy
      №             Count of
        λ           Current character in
       β            Predefined variable lowercase alphabet
     ›              Is greater than
          μ         Current index
         ∧          Logical And
            λ       Current character
           ‹        Is less than
               ι    Current element
              §     Indexed by
                 μ  Current index
                ⊖   Decremented
             ↧      Lowercased
\$\endgroup\$
2
\$\begingroup\$

Python 3, 68 bytes

lambda x:re.findall(f"^{26*'%c*'}$"%(*range(65,91),),x,10)
import re

Try it online!

Python had already a solution (here) but it didn't worked on tests with char like (éèàÈ...).

How it works :

  • re.findall returns all the occurences of a given pattern in a given string.
  • f"^{26*'%c*'}$"%(*range(65,91),) produce the pattern ^A*B*C*...Y*Z*$ which will match any upper abecedarian word.
  • 10 (=2|8) passed in argument to re.findall sets the flag re.IGNORECASE (=2) to disable caseCheck in the string and the flag re.MULTILINE (=8) which apply the pattern to each line of the string.
\$\endgroup\$
1
\$\begingroup\$

Red, 88 bytes

func[b][a: charset[#"a"-#"z"]remove-each w b[any[w <> sort copy w not parse w[any a]]]b]

Try it online!

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

Japt v2.0a0 -f, 7 bytes

Not entirely sure I've understood the spec correctly.

¶ñv o\l

Try it

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

Java 8, 127 bytes

l->l.filter(s->(s=s.toLowerCase()).matches("[a-z]+")&java.util.Arrays.equals(s.chars().toArray(),s.chars().sorted().toArray()))

Full Program (must be run locally)

Java 16, 124 bytes

l->l.filter(s->(s=s.toLowerCase()).matches("[a-z]+")&s.chars().boxed().toList().equals(s.chars().sorted().boxed().toList()))

Java 16 added the Stream#toList method.

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

Julia, 55 bytes

x->x[@.all(isletter,x)isascii(x)issorted(lowercase(x))]

Try it online!

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

perl, 59

say if /^[A-Za-z]+$/ and lc($_) eq join "",sort map {lc} @F

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.