Write a function/program that accepts a string of lower/uppercase letters [A-Za-z] as input, that checks whether the occuring letters are unique and in alphabetical order (ignoring lower and uppercase) or not. The output must be truthy if they are unique and in alphabetical order and falsy if not.

Here some testcases

a                           true
abcdefGHIjklmnopqrSTUVWXyz  true     
aa                          false
puz                         true
puzz                        false
puzZ                        false
puZ                         true
PuZ                         true
pzu                         false
pzU                         false
abcdABCD                    false
dcba                        false

If you want, run your program on all words of a wordlist like this one and and post some interesting ones =).


Lowest number of bytes wins.

  • 4
    \$\begingroup\$ Weak test cases. (See my comment on Richard A's PHP answer.) \$\endgroup\$
    – manatwork
    Mar 11, 2015 at 17:20
  • \$\begingroup\$ Does the alphabet loop? Should za be a truthy value? \$\endgroup\$
    – bren
    Sep 24, 2015 at 1:06
  • \$\begingroup\$ No, the alphabet begins with a and ends with z. \$\endgroup\$
    – flawr
    Sep 24, 2015 at 12:17
  • \$\begingroup\$ You should have some test cases that aren't in alphabetical order \$\endgroup\$
    – Jo King
    Mar 3, 2019 at 21:43
  • 1
    \$\begingroup\$ @JoKing I added some. \$\endgroup\$
    – flawr
    Mar 5, 2019 at 9:02

64 Answers 64


CJam, 8 bytes


Here is a test harness for all examples in the challenge. This returns 0 or 1 (which are falsy and truthy, respectively, in CJam).

And here is a script to filter the word list in the question (takes a few seconds to run). You'll have to copy the word list into the input field manually, because it's too long for a permalink.


l        "Read input.";
 el      "Convert to lower case.";
   _$    "Get a copy and sort it.";
     _&  "Remove duplicates (by computing the set intersection with itself).";
       = "Check for equality with original (lower case) word.";

Regex (any flavor), 55 bytes

Some people don't consider regex to be a programming language, but it's been used before, and it's not close to being the shortest.


I've added one byte for the i (case-insensitive) flag. This is very straightforward and might be shorter to generate on the fly.

If regex alone are not allowed, you can use this 56-byte Retina program suggested by Martin Büttner:


Running this on the wordlist linked above yielded 10 6-letter words in alphabetical order.

["abhors", "almost", "begins", "begirt", "bijoux", "biopsy", "chimps", "chinos", "chintz", "ghosty"]

  • 2
    \$\begingroup\$ You can use Retina instead of ES6 if someone complains that regex is not a language: i`^a?b?c?d?e?f?g?h?i?j?k?l?m?n?o?p?q?r?s?t?u?v?w?x?y?z?$ \$\endgroup\$ Mar 1, 2015 at 17:12
  • \$\begingroup\$ @MartinBüttner I'd forgotten about Retina. Thanks! \$\endgroup\$ Mar 1, 2015 at 17:17
  • \$\begingroup\$ @MartinBüttner According to the META (meta.codegolf.stackexchange.com/questions/2028/…) Regexes can be 'seen' somewhat as a programming language. \$\endgroup\$ Mar 2, 2015 at 9:24
  • \$\begingroup\$ @IsmaelMiguel I know. And in fact that definition was specifically chosen to make sure it doesn't rule out regex. But some people still regularly complain, because you can't use regex like any other language. \$\endgroup\$ Mar 2, 2015 at 12:45
  • \$\begingroup\$ @MartinBüttner Those who complain can go to a place called META and look for it. Why no one visits such a beautiful place full of questions that solve most issues? \$\endgroup\$ Mar 2, 2015 at 12:54

Python 3, 44 bytes


A simple approach - check uniqueness, check sortedness.

  • \$\begingroup\$ Can you explain what *s,=... does? \$\endgroup\$
    – flawr
    Mar 1, 2015 at 13:22
  • \$\begingroup\$ @flawr This is called 'starred assignment'. In this code, it simply converts the right side into a list. It's the same as s=list(input().lower()). \$\endgroup\$
    – Jakube
    Mar 1, 2015 at 13:40
  • 1
    \$\begingroup\$ @flawr As Jakube says, here it's just converting input into a list of chars. In general it's a special assignment syntax which lets you do things like x,*y = [1, 2, 3, 4], which assigns 1 to x and [2, 3, 4] to y. \$\endgroup\$
    – Sp3000
    Mar 1, 2015 at 13:42
  • \$\begingroup\$ @mbomb007 *s,= is list(s)... link \$\endgroup\$
    – Sp3000
    Mar 2, 2015 at 22:43
  • 1
    \$\begingroup\$ You can do {*s} instead of set(s) to save 2 bytes. \$\endgroup\$
    – mbomb007
    Jan 17, 2017 at 19:53

><>, 52 42 39 bytes

? )'`':/'@'v

This type of question is one of the few types that ><> is pretty comfortable with, since we only need to deal with one char at a time.


Don't get lost! There's a lot of wrapping here.

0            Push 0. We'll be mapping a-z to 1-26, so 0 will be smaller than everything

i            Read a char of input
:1+? 1n;     If there's no more input, print 1
:'`')?       If the char is bigger than backtick...
  '`'          Push backtick  (which is one before 'a'), else...
  '@'          Push an @ sign (which is one before 'A')
-            Subtract, mapping a-z to 1-26
:{)?         If the new char is bigger than the previous char...
               Repeat from the beginning of the loop, else...
  0n;          Print 0

Previous solution, 42 bytes

? ){:-<'`'/ vv

The interesting thing is that, despite appearing to have the same functionality, the alternative

? ){:-<'`'/ ^^

(The change is in the arrows and mirrors on the far right)

actually gives incorrect results, due to ><>'s interpreter using a Python defaultdict. What happens is that, by traversing through the empty space at the end of the second row, 0s are implicitly placed into the blank spaces when ><> tries to access the cell. This then messes with the ? conditional trampoline at the beginning of the same row, as the newly placed 0s are skipped rather than the v at the end.

  • \$\begingroup\$ I feel like you could save some bytes by only substracting 32 from lowercase letters rather than getting alphabetic index for all letters \$\endgroup\$
    – Aaron
    Sep 23, 2015 at 15:30

Haskell, 52 Bytes

import Data.Char
and.(zipWith(>)=<<tail).map toLower

Usage: (and.(zipWith(>)=<<tail).map toLower) "abcd" which outputs True.


C, 67 65 57 54 (52) characters

f(char*s){int c,d=0;for(;(c=*s++)&&(c&~32)>(d&~32);d=c);return!c;}

a little shorter:

f(char*s){int c,d=0;for(;(c=*s++)&&(c&~32)>d;d=c&~32);return!c;}

and even shorter:

f(char*s){int d=32;for(;(*s|32)>d;d=*s++|32);return!*s;}

Here's a little test: http://ideone.com/ZHd0xl

After the latest suggestions here are still two shorter versions:

// 54 bytes
f(char*s){int d=1;for(;(*s&=95)>d;d=*s++);return!*s;}

// 52, though not sure if valid because of global variable

Also this code relies on the fact, that in ASCII lowercase and uppercase only differ by the 5th bit (32) which I filter out. So this might not work with other encodings obviously.

EDIT: The latest version always sets the 5th bit as |32 is shorter than &~32.

  • \$\begingroup\$ Good use of domain knowledge to handle the case sensitivity issue. \$\endgroup\$
    – RomSteady
    Mar 2, 2015 at 22:55
  • \$\begingroup\$ Save 2 by replacing the for loop with for(;(*s&=95)>d;d=*s++);. And you can initialize d to 1 without changing the result, saving 1 more. See. \$\endgroup\$
    – AShelly
    Mar 3, 2015 at 2:53
  • 1
    \$\begingroup\$ I'm not sure if this is considered legal in code golf, but d;f(char*s){d=32;for...} works, declaring d implicitly as a global int (which, in GCC, is a warning—"data definition has no type or storage class"—but not an error). This saves two bytes. \$\endgroup\$
    – wchargin
    Mar 3, 2015 at 3:13
  • \$\begingroup\$ AShelly hm, didn't consider that. Your suggestion changes the original string though. But whatever, it's code golf :D Also I'm not sure about WChargin's hint as d as a global variable would not really be part of the function. \$\endgroup\$ Mar 3, 2015 at 6:22
  • 1
    \$\begingroup\$ Why not initialize d in the for loop rather than its own statement? That way you save a ;. \$\endgroup\$
    – Josh
    Mar 3, 2015 at 16:38

Ruby, 33


Checks to see if the sorted unique characters are the same as all the characters.

  • 1
    \$\begingroup\$ Think you can get it a little shorter with c==c.sort|c \$\endgroup\$
    – histocrat
    Mar 2, 2015 at 20:59
  • \$\begingroup\$ Ooh, I like that, that's clever. Thanks. \$\endgroup\$
    – britishtea
    Mar 2, 2015 at 21:10

Wolfram Mathematica, 49 37 bytes


P.S. Shorter solution by Martin Büttner:

  • 2
    \$\begingroup\$ #⋃#==#&@*Characters@*ToLowerCase \$\endgroup\$
    – alephalpha
    Mar 2, 2015 at 3:16
  • 1
    \$\begingroup\$ @alephalpha That is beautiful! \$\endgroup\$ Mar 2, 2015 at 17:56

Javascript (ES5), 101

function i(s){b=0;l=''.a

Improved to 87 by edc95:

upvote his comment :)

function i(s){return!s.toUpperCase().split(l='').some(function(c){return(u=l,l=c)<=u})}

Btw, the test cases currently in OP are fulfilled if a program is only checking uniqueness, disregarding order.

I cant write comments yet, so I'll answer some remarks here:

@edc65: Thanks! I tried rewriting it using some(), but I couldn't get a shorter solution, because even though it looks like it would enable me to get rid of the superflous b variable, you need to type "return" twice (same with reduce()), and you can't just return the comparison's result directly, because the last character needs to be saved after the comparison with it.

@edc65: That's a nice use of the comma operator for 87! I edited it into my answer for more visibility.

  • \$\begingroup\$ That's a better idea than mine. Using .some could be even better (52 with ES6) \$\endgroup\$
    – edc65
    Mar 1, 2015 at 17:25
  • \$\begingroup\$ You can remove the space between return and !b to save a char. \$\endgroup\$
    – ProgramFOX
    Mar 1, 2015 at 19:20
  • \$\begingroup\$ As is, just caring white space,96:function i(s){b=0;l='';s.toUpperCase().split('').forEach(function(c){if(c<=l)b=1;l=c});return!b} \$\endgroup\$
    – edc65
    Mar 1, 2015 at 20:02
  • \$\begingroup\$ The same, golfed more,92:function i(s){s.toUpperCase(b=0).split(l='').forEach(function(c){if(c<=l)b=1;l=c});return!b} \$\endgroup\$
    – edc65
    Mar 1, 2015 at 20:03
  • 1
    \$\begingroup\$ Using some(or every, same score),87:function i(s){return!s.toUpperCase().split(l='').some(function(c){return(u=l,l=c)<=u})} \$\endgroup\$
    – edc65
    Mar 1, 2015 at 20:04

Haskell, 90 bytes

Supplies the function f :: String -> Bool

import Data.List
import Distribution.Simple.Utils
f l=g$lowercase l
g l=sort l==l&&l==nub l

Usage (assuming it is saved as golf.hs). ... is used to replace ghci's verbose loading messages.

$ ghci golf.hs
*Main> f "as"
*Main> f "aa"

If someone has a lowercase method shorter than import Distribution.Simple.Utils then please comment.

  • 1
    \$\begingroup\$ Use map toLower from Data.Char instead of lowercase \$\endgroup\$
    – nimi
    Mar 1, 2015 at 17:11
  • 1
    \$\begingroup\$ Also: you can remove the parameter l at f, i.e. f=g.lowercase (or f=g.map toLower if you switch to toLower). Within g one comparison is enough: g l=nub(sort l)==l. \$\endgroup\$
    – nimi
    Mar 1, 2015 at 18:45

J, 17 bytes

Checks if the lowercase sorted /:~ string equals -: the lowercase nub ~. string.


   NB. testing with the example inputs
   ((/:~-:~.)@tolower) every (1$'a');'abcdefGHIjklmnopqrSTUVWXyz';'aa';'puz';'puzz';'puzZ';'puZ';'PuZ'
1 1 0 1 0 0 1 1

As in J a 1-charater long "string" represented as a regular string (with quotes) is just a character atom not a real string I formatted the input appropriately so all input would be real strings. (In the example above I used 1$'a'.)


MATLAB, 29 27 bytes

Now for a one-liner which even makes sense outside of code-golf.

As an anonymous function (use as o('yourstring'))


I guess this function is pretty self-explanatory since it reads like a newspaper ad.

Previous version (29 bytes):


Input must be presented between ' marks, e.g. 'Potato'.


C (44 bytes)


Test it here: http://ideone.com/q1LL3E

Posting this because I can't comment yet, otherwise it would be a suggestion to improve the existing C answer because I completely stole the case-insensitive idea from the existing C answer.

Returns 0 if the string is not ordered, and a non-zero value if ordered.


Golang (65 bytes)

Go is not a golf friendly language, also, i suck at golf...

func a(s[]byte)(bool){return len(s)<2||s[0]|32<s[1]|32&&a(s[1:])}

Run it here: http://play.golang.org/p/xXJX8GjDvr

edit 106->102

edit 102->96

edit 96->91

edit 91->87

edit 87->65

I beat the java version, I can stop for today


VBA (161 bytes)

Function t(s As String)
t = 0
For i = 2 To Len(s)
a = Left(LCase(s), i)
    If Asc(Right(a, 1)) <= Asc(Right(a, 2)) Then Exit Function
t = 1
End Function  

Compares ascii value with previous letter in lowercase, return 0 (false) when its value is smaller / equal and exit function


Brachylog, 3 bytes


Try it online!

The predicate succeeds if the input meets the requirements outlined and fails if it does not, printing true. or false. if run as a program.

       The input,
ḷ      lowercased,
 ⊆     is a not-necessarily-contiguous sub-list of
  Ạ    "abcdefghijklmnopqrstuvwxyz".

The first version I came up with, not explicitly referencing the alphabet:

Brachylog, 4 bytes


Try it online!

        The input,
ḷ       lowercased,
 ≠      in which every character is distinct,
  .     is the output variable,
   o    which sorted,
        is still the output variable.

Pure Bash 4.x, 37

[[ ${1,,} =~ ^`printf %s? {a..z}`$ ]]

Try it online!

Input taken as a command-line parameter. As per standard shell semantics, exit code 0 means true (alphabetic) and exit code != 0 means false (not alphabetic).

The printf creates the regex as in @hsl's solution. The input string is expanded to lowercase and compared against the regex.

Previous answer:

Bash + coreutils, 52

Straightforward solution:

a=`fold -1<<<${1,,}`
cmp -s <(sort -u<<<"$a")<<<"$a"
  • \$\begingroup\$ Note that this requires bash 4.x. \$\endgroup\$
    – Mark Reed
    Mar 2, 2015 at 20:09
  • \$\begingroup\$ @MarkReed Yes. Noted. \$\endgroup\$ Mar 2, 2015 at 20:38
  • \$\begingroup\$ I don't understand what the ${1,,} is for, why can't you just use $1? \$\endgroup\$
    – pxeger
    Jan 21, 2021 at 9:14
  • \$\begingroup\$ @pxeger it makes all letters lowercase - search for ,, here \$\endgroup\$ Jan 22, 2021 at 22:12

J, 21 characters

This is too long. The argument must have rank 1, i.e. it must be a string or vector.

  • tolower yy in lower case.
  • /:~ yy in lexical order.
  • ~. y – the nub of y, that is, y with duplicates removed.
  • x ; yx and y put into boxes and then concatenated.
  • < yy put into a box.
  • x = yx compared element-wise with y.
  • (< y) = (~. y) ; (/:~ y) – a vector indicating if y is equal to its nub and itself sorted.
  • */ y – the product of the items of y, or its logical and if the items are booleans.
  • */ (< y) = (~. y) ; (/:~ y) – a boolean indicating the desired property for lowercase y.

Julia, 44 bytes


This creates an anonymous function that takes a single argument s, converts it to lower case, and compares it to the unique sorted version of the string. It returns a boolean, i.e. true or false. If you want to test it out, assign it like f=s->... and then call f("PuZ"), etc.

  • \$\begingroup\$ Amen to that, @flawr. Thanks for the support. \$\endgroup\$
    – Alex A.
    Mar 2, 2015 at 16:28
  • \$\begingroup\$ I'm slightly late but you can shave 3 bytes \$\endgroup\$
    – MarcMush
    Jan 21, 2021 at 10:02

k (6 bytes)


& returns true if both args are true

/ modifies & to apply "over" a list, like a fold in functional languages

> greater than

': modifies > to apply "each-prior", so returns a vector of booleans stating which elements are greater than their predecessor

_ makes it argument lower case


(0b means boolean false)

q (13 bytes)


q is just syntactic sugar on k. all is defined as &/, and lower is _

  • 4
    \$\begingroup\$ Can you explain how this works? \$\endgroup\$
    – flawr
    Mar 2, 2015 at 16:11
  • \$\begingroup\$ This almost feels like cheating on other languages... Who needs function names, parentheses and semicolons? :) \$\endgroup\$
    – Sanchises
    Mar 2, 2015 at 22:59
  • \$\begingroup\$ @sanchises k has all of those things and they work pretty much the same way as in C style languages. It's just that this problem happens to be expressible as a single statement. \$\endgroup\$
    – mollmerx
    Mar 4, 2015 at 16:50

C# 6, 18 + 82 76 = 94 bytes

Requires (18 bytes):

using System.Linq;

Code (76 bytes):

bool a(string s)=>(s=s.ToLower()).Distinct().OrderBy(x=>x).SequenceEqual(s);

C# 6 supports lambdas to define a function, which is useful for golfing.

Non-C# 6 version:

bool a(string s){return (s=s.ToLower()).Distinct().OrderBy(x=>x).SequenceEqual(s);}

Ungolfed code:

bool IsInAlphabeticalOrder(string s)
    s = s.ToLower();
    return s.Distinct()
            .OrderBy(x => x)

JavaScript (ES6) 54

Convert to uppercase, then to array and sort. If during sort two element are in the wrong order or equal, return 0 (falsy) else 1 (truthy)

Edit Shortened thx to @Optimizer (but still 2 more than the @Tamas solution implemented in ES6: F=s=>[...s.toUpperCase()].every(c=>(u=l,l=c)>u,l=''))


Test in Firefox / FireBug console

.map(w=>w+' '+F(w))

["a 1", "abcdefGHIjklmnopqrSTUVWXyz 1", "aa 0", "puz 1", "puzz 0", "puzZ 0", "puZ 1", "PuZ 1"]

  • 1
    \$\begingroup\$ s= does not seem to be required... \$\endgroup\$
    – Optimizer
    Mar 3, 2015 at 17:26
  • \$\begingroup\$ @Optimizer right, it was a first try when at last i compared the original (uppercased) and the sorted \$\endgroup\$
    – edc65
    Mar 3, 2015 at 18:26

Java 8 - 90 89 87 85 chars

The idea here is to use a 'reduce' function that tracks the last char and "gives up" when it detects the sequence is not strictly ascending.


int f(String s){return s.toLowerCase().chars().reduce(0,(v,c)->(v<0)?v:(c>v)?c:-1);}


int f(String s){
    return s.toLowerCase()
            .reduce(0, (v,c) -> (v<0)? v : (c>v)?c:-1);


System.out.println(new Quick().f("abc"));
System.out.println(new Quick().f("aa"));
System.out.println(new Quick().f("abcdefGHIjklmnopqrSTUVWXyz"));
System.out.println(new Quick().f("puZ"));
System.out.println(new Quick().f("Puz"));
System.out.println(new Quick().f("cba"));



Perl 6, 35 bytes

{my@c=.uc.comb;@c [email protected]}

This produces a callable block; if I could just assume that $_ is already set to the desired word, I could delete the surrounding curly braces and lose two more bytes, but probably the only reasonable way to make that assumption would be to run it with -n and feed the word as standard input, which would add the two bytes right back.

  • \$\begingroup\$ Sure it does. .uc.comb doesn't rearrange anything, so if the uppercased and combed array is equal to the sorted uppercased and combed array, that means it started out in sorted order. \$\endgroup\$
    – Mark Reed
    Mar 3, 2019 at 22:26
  • \$\begingroup\$ right, it's checking the size of the intersection, which ignores order. Ok, updated. \$\endgroup\$
    – Mark Reed
    Mar 3, 2019 at 22:33

R, 37 bytes


Try it online!

Posting since this is substantially different and shorter than Michal's R answer.

Converts the letters to ASCII codepoints with utf8ToInt, then takes modulo 32 so that lower and upper letters are converted to the same numbers 1...26. Computes the pairwise differences, and checks that they are all positive.


Perl, 27

@hsl's regexp dynamically build.

#!perl -p

Also we can do a reverse match: convert the input into a regexp: PuZ => .*p.*u.*z.* and then match this to a string of letters in alphabetical order. Result - also 27 characters.

#!perl -lp

Python, 50 bytes

f=lambda x:sorted(set(x.lower()))==list(x.lower())

Try online here: http://repl.it/c5Y/2


PHP (89 76 72 63 bytes)

I'm pretty horrible at golfing, but I thought I'd give it a shot.


I had to cast the output to an integer, since booleans aren't printed in php.

I was able to remove the echo by using <?=, I also removed the $b.


Removed the space after <?= and followed manatwork's suggestion to cut 4 bytes.

Also, replacing the implode with join and omitting the glue parameter saved another 9 bytes. Thanks manatwork.

  • \$\begingroup\$ You can also force a boolean into integer by adding 0 to it. +0 is shorter than (int). \$\endgroup\$
    – manatwork
    Mar 11, 2015 at 17:09
  • \$\begingroup\$ Though this passes successfully the test cases provided in the question, it definitely not checks for alphabetical order. For example it outputs 1 for “xa”. \$\endgroup\$
    – manatwork
    Mar 11, 2015 at 17:16
  • \$\begingroup\$ There is an alias for implode(), with shorter name: join(). And the first parameter is optional, defaulting to empty string. \$\endgroup\$
    – manatwork
    Mar 11, 2015 at 17:25
  • \$\begingroup\$ @manatwork There is too, completely missed it. Thank you. \$\endgroup\$
    – MisterBla
    Mar 11, 2015 at 17:28
  • \$\begingroup\$ @manatwork I see it doesn't do alphabetical order... which I find weird, array_unique should sort the array. \$\endgroup\$
    – MisterBla
    Mar 11, 2015 at 17:31

Python 2, 43 bytes

lambda s:eval('"%s"'%'"<"'.join(s.lower()))

Try it online!

Puts < symbols between all the letters (converted to lowercase), and then evals it. Python's chained comparison operators are perfectly happy to evaluate the whole thing as one big boolean expression.


Vyxal, 6 bytes


Try it Online!


⇩¨=    # is the lowercase version of the input invariant under:
  ‡Us  # uniquify and sort? 
  • \$\begingroup\$ 3 bytes: ⇩Þ⇧ (filler) \$\endgroup\$
    – naffetS
    Sep 4, 2022 at 21:10
  • \$\begingroup\$ Posted my three-byter myself \$\endgroup\$
    – naffetS
    Sep 5, 2022 at 17:14

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.