25
\$\begingroup\$

Introduction

As ToonAlfrink says: "Me thinks there aren't enough easy questions on here that beginners can attempt!". So the task is very simple. Given a string, output a truthy or falsy value whether the name is official or not.

A name is "official" if it is a single title-case word, that is:

  • If the first letter is capitalized (not official: adnan)
  • If the other letters are not capitalized (not official: AdNaN)
  • If the name doesn't contain any non-alphabetic characters (not official: Adnan123, Adnan!)
  • If the name consists of just one word (not official: Adn an, Adn An)
  • If the name has more than one character (not official: A)

Rules

  • You may provide a function or a program
  • This is , so the submission with the least amount of bytes wins!
  • Note: To simplify things, names like Mary-Ann are in this challenge not official.
  • Assume that there are no leading whitespaces in the name.
  • Assume that only the printable ASCII characters (32-126) are used in the names

Test cases

Input: Adnan
Output: True

Input: adnan
Output: False

Input: AdnaN
Output: False

Input: Adnan123
Output: False

Input: Adnan Adnan
Output: False

Input: A
Output: False

Input: Mary-Ann
Output: False

Leaderboard

/* Configuration */

var QUESTION_ID = 67554; // Obtain this from the url
// It will be like http://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 34388; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "http://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "http://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });  
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];
  
  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    });
    
    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });
    else console.log(body);
  });
  
  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;
    
    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    lang = jQuery('<a>'+lang+'</a>').text();
    
    languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang, user: a.user, size: a.size, link: a.link};
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function (a, b) {
    if (a.lang_raw.toLowerCase() > b.lang_raw.toLowerCase()) return 1;
    if (a.lang_raw.toLowerCase() < b.lang_raw.toLowerCase()) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body { text-align: left !important}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="language-list">
  <h2>Shortest Solution by Language</h2>
  <table class="language-list">
    <thead>
      <tr><td>Language</td><td>User</td><td>Score</td></tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>

\$\endgroup\$
  • 5
    \$\begingroup\$ So my name's not official? I'd better change it then. \$\endgroup\$ – ETHproductions Dec 23 '15 at 23:04
  • 12
    \$\begingroup\$ @ETHproductions If we're using this logic, Lololololololololololol is an official name :) \$\endgroup\$ – Adnan Dec 23 '15 at 23:06
  • 1
    \$\begingroup\$ That doesn't really answer the question. Which is it: "you may assume the name doesn't contain accented letters", or "names with accented letters should yield False"? \$\endgroup\$ – Lynn Dec 24 '15 at 2:29
  • 1
    \$\begingroup\$ As a slightly offbeat Canadian digression, a professor I know wouldn't be happy with your "official" criteria: Robert Smith?. His name actually does have that question mark. Also, Sahaiʔa. \$\endgroup\$ – Iwillnotexist Idonotexist Dec 26 '15 at 7:46
  • 1
    \$\begingroup\$ @FarhanAnam Yes \$\endgroup\$ – Adnan Dec 26 '15 at 13:37

38 Answers 38

6
\$\begingroup\$

Pyth, 16 13 12 bytes

Thanks to @Thomas Kwa for reminding me about titlecase.

&qzr@GrzZ3tz

Test Suite.

&              Boolean and operator
 qz            Equality test on input
  r    3       Titlecase operator
   @G          Setwise intersection with the alphabet
    rzZ        Input to lowercase
 tz            All but the first character of the input
\$\endgroup\$
21
\$\begingroup\$

Retina, 13 bytes

^[A-Z][a-z]+$

Try it online | Test suite (The output 0 means none of the strings matched, which is expected.)

When Retina is only provided with a single line of code, it outputs the number of times the expression matched the input string, so it will output 1 (truthy) if it matches and therefore is an official name and 0 (falsy) if it's not.

Breakdown

^       The beginning of the string
[A-Z]   One uppercase letter
[a-z]+  One or more lowercase letters
$       The end of the string
\$\endgroup\$
  • 8
    \$\begingroup\$ Looks like we need character classes for letters. ;) \$\endgroup\$ – Martin Ender Dec 24 '15 at 0:21
10
\$\begingroup\$

TeaScript, 12 bytes

xO`A-Z][a-z`

Abuses the O function.

Try this online

Test Suite

Explanation

The O function makes this:

x O   `A-Z][a-z`
x.O(/^[A-Z][a-z]+$/)

Then, the O function checks if the regex matches x.


Alternatively, a non-competing TeaScript 3 answer at 7 bytes:

xO/\A\a
\$\endgroup\$
  • \$\begingroup\$ Ahahaha, nice one. At some point while I was working on the Japt interpreter, I used this trick with the isChar function you added. But you may want to explain in more detail for those not in the know. \$\endgroup\$ – ETHproductions Dec 24 '15 at 1:55
  • \$\begingroup\$ Ooooooh, I like the new regex features! \$\endgroup\$ – ETHproductions Dec 27 '15 at 2:06
7
\$\begingroup\$

JavaScript (ES6), 26

n=>/^[A-Z][a-z]+$/.test(n)

By: Edcsixtyfive

f=n=>/^[A-Z][a-z]+$/.test(n)

console.log=x=>O.textContent+=x+'\n'

;['Adnan','adnan','AdnaN','Adnan123','Adnan Adnan','A','Mary-Ann']
.forEach(t=>console.log(t+' '+f(t)))
<pre id=O></pre>

\$\endgroup\$
  • \$\begingroup\$ Darn, you beat me to it. You also outgolfed my version by 5 bytes. \$\endgroup\$ – SuperJedi224 Dec 24 '15 at 0:08
  • 1
    \$\begingroup\$ One byte less: n=>n.match`^[A-Z][a-z]+$` \$\endgroup\$ – user81655 Dec 24 '15 at 4:09
  • \$\begingroup\$ @user81655 an array as a truthy value is too forced IMHO \$\endgroup\$ – edc65 Dec 24 '15 at 9:16
  • \$\begingroup\$ @edc65 It is valid though. \$\endgroup\$ – SuperJedi224 Dec 24 '15 at 15:20
  • 1
    \$\begingroup\$ For only 4 bytes more you get ES5 compliance: /./.test.bind(/^[A-Z][a-z]+$/) \$\endgroup\$ – CR Drost Dec 24 '15 at 17:26
7
\$\begingroup\$

Python, 59 58 bytes

I'm sure there's no real way to beat the Retina version, since this is basically just that within Python. But I think this is my first submission ;)

import re,sys;print(re.match('[A-Z][a-z]+$',sys.argv[1]))

It's a very odd truthy value:

(test2)wayne@arglefraster ~/programming/inactive/golf/67554
⚘ python golf.py AdNan                                                                                                 $? 148  %# 3  10:06:36
None
(test2)wayne@arglefraster ~/programming/inactive/golf/67554
⚘ python golf.py Adnan                                                                                                         %# 3  10:06:40
<_sre.SRE_Match object at 0x7feefea7f440>
(test2)wayne@arglefraster ~/programming/inactive/golf/67554
⚘ python golf.py "Adnan Banana"                                                                                                %# 3  10:06:47
None

(And it does require "" around strings with spaces in it, if passed via the shell)

\$\endgroup\$
  • 1
    \$\begingroup\$ ^ is not needed as re.match() only matches at the beginning of string. \$\endgroup\$ – manatwork Dec 24 '15 at 16:20
  • 1
    \$\begingroup\$ @manatwork nice! Another byte shaved :) I could save another byte with the closing paren, using Python2 \$\endgroup\$ – Wayne Werner Dec 24 '15 at 16:32
  • 1
    \$\begingroup\$ @WayneWerner: that's why you should give the Python version :) I think Python 2 and Python 3 are kind of different languages, at least for codegolf. \$\endgroup\$ – movatica May 23 at 20:01
  • \$\begingroup\$ If you use a anonymous lambda instead of a whole program, you get 45 bytes: lambda s:re.match('[A-Z][a-z]+$',s) import re \$\endgroup\$ – movatica May 23 at 20:25
  • 1
    \$\begingroup\$ @movatica Oh, whoops! \$\endgroup\$ – MilkyWay90 Jun 15 at 22:01
4
\$\begingroup\$

Java, 53 bytes

boolean b(String a){return a.matches("[A-Z][a-z]+");}
\$\endgroup\$
  • \$\begingroup\$ You can use a lambda: s->s.matches("[A-Z][a-z]+") \$\endgroup\$ – Benjamin Urquhart May 17 at 14:58
4
\$\begingroup\$

Python, 50 45 43 41 bytes

lambda s:s.isalpha()*s.istitle()*len(s)>1

Returns True if it's an official name or False if it's not.

\$\endgroup\$
  • \$\begingroup\$ Rules of codegolf state, that you don't need to take the f= into account, saving two bytes. Also, (len(s)>1) saves 5 bytes over s[1:].islower(). :) \$\endgroup\$ – movatica May 23 at 20:24
3
\$\begingroup\$

BotEngine, 203 180 29x6=174

v ABCDEFGHIJKLMNOPQRSTUVWXYZ
>ISSSSSSSSSSSSSSSSSSSSSSSSSSF
v <<<<<<<<<<<<<<<<<<<<<<<<<<
 Tabcdefghijklmnopqrstuvwxyz
> SSSSSSSSSSSSSSSSSSSSSSSSSSF
^E<<<<<<<<<<<<<<<<<<<<<<<<<<

I should really add builtins for identifying uppercase and lowercase letters. That would be much more concise than checking each letter individually.

Rough translation:

for a of input enqueue a
if ABCDEFGHIJKLMNOPQRSTUVWXYZ contains first
 remove first
 while abcdefghijklmnopqrstuvwxyz contains first
  remove first
 if empty
  yield TRUE exit
 else
  yield FALSE exit
else
 yield FALSE exit
\$\endgroup\$
3
\$\begingroup\$

C, 129 122 121 111 bytes

main(c,b,d){b=d=0;while((c=getchar())>13)b|=b|=!b&&c>90|c<65?1:2&&d++&&c<97|c>122?4:2;printf("%d\n",b<3&&d>1);}

Try It Online

main(c,b,d)
{
    b=d=0;
    while((c=getchar())>13)
    {
        // Twiddle bits, 1<<0 for first character and 1<<3 for subsequent
        b|=!b&&c>90|c<65?1:2; // check first character is valid
        b|=d++&&c<97|c>122?4:2; // check later characters are valid
    }
    // If all OK b == 2, if either of above are wrong, b >= 3 due to 
    // extra bits. Also, d should be > 1 for name length to be valid.
    printf("%d\n",b<3&&d>1);
}
\$\endgroup\$
3
\$\begingroup\$

VB6, 48 bytes

Function f(i):f=i Like"[A-Z][a-z]+":End Function
\$\endgroup\$
2
\$\begingroup\$

MATL, 18 bytes

The current version (4.0.0) of the language is used.

This applies the same regular expression as NinjaBearMonkey's answer:

j'^[A-Z][a-z]+$'XX

The output is the string (which is truthy) if it's an official name, and nothing (which is falsy) if it's not.

Examples

>> matl
 > j'^[A-Z][a-z]+$'XX
 > 
> December
December
>> 

>> matl
 > j'^[A-Z][a-z]+$'XX
 > 
> ASCII
>> 
\$\endgroup\$
2
\$\begingroup\$

Haskell, 61 bytes

f(h:t@(_:_))=elem h['A'..'Z']&&all(`elem`['a'..'z'])t
f _=1<0
\$\endgroup\$
  • \$\begingroup\$ One byte fewer \$\endgroup\$ – dfeuer Jun 20 at 5:02
  • \$\begingroup\$ Several more down. You could also use that technique for the other test to be more efficient, but it's the same number of bytes. \$\endgroup\$ – dfeuer Jun 20 at 5:08
2
\$\begingroup\$

Gema, 17 characters

\B<K1><J>\E=1
*=0

Sample run:

bash-4.3$ echo -n 'Adnan' | gema '\B<K1><J>\E=1;*=0'
1

bash-4.3$ echo -n 'adnan' | gema '\B<K1><J>\E=1;*=0'
0

bash-4.3$ echo -n 'Adnan123' | gema '\B<K1><J>\E=1;*=0'
0
\$\endgroup\$
2
\$\begingroup\$

Ruby, 28 bytes

p (gets=~/^[A-Z][a-z]+$/)!=p

-2 bytes( thanks to manatwork )

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

IA-32 machine code, 19 bytes

A function that receives the pointer to a null-terminating string in ecx and returns 0 or 1 in eax (according to the fastcall convention).

Hexdump of the code:

6a 20 58 32 01 74 0a 41 2c 61 3c 1a b0 00 72 f3 c3 40 c3

In assembly language:

    push 32;
    pop eax;

myloop:
    xor al, [ecx];
    jz yes;
    inc ecx;
    sub al, 'a';
    cmp al, 26;
    mov al, 0;
    jb myloop;
    ret;

yes:
    inc eax;
    ret;

The first byte of the input name has its 5th bit flipped (xor with 32) to convert it from capital case to small case. This loads 32 into eax, using 3 bytes of code:

    push 32;
    pop eax;

To check whether the byte is a small letter:

    sub al, 'a';
    cmp al, 26;
    jb myloop;

If not, this code falls through. To return 0 in this case, it puts 0 in al before doing the conditional jump:

    sub al, 'a';
    cmp al, 26;
    mov al, 0;
    jb myloop;

The 0 in al also serves as a xor-mask (or absence of it) for the following bytes of the input name.

A successful exit is when it encounters a zero byte, which stays zero after the xor:

    xor al, [ecx];
    jz yes;

It assumes that the input name is not empty. I guess it's a reasonable assumption about a name (not an arbitrary string)!

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

grep, 16 bytes

This is the pattern:

[A-Z][a-z]+

If you use the -E and -x and -c switches grep will print a count of matching input lines. So if you give it one line you get a 1 or a 0. I think that's how this place works.

The pattern is 11 chars, the whole command line is 23. I've seen people use sed scripts without the command so I don't know what is what. But, it reads stdin, and so you can just type at it. Here's echo:

for a in Adnan adnan Ad\ nan
do  echo "$a" | grep -cxE \[A-Z]\[a-z]+
done

1
0
0
\$\endgroup\$
  • \$\begingroup\$ @Doorknob - seems fair enough to me. thanks very much. which hat did you guess? \$\endgroup\$ – mikeserv Dec 25 '15 at 14:38
  • 1
    \$\begingroup\$ I figured out Hairboat's Revenge. :P \$\endgroup\$ – Doorknob Dec 25 '15 at 14:42
  • \$\begingroup\$ Stop me if (as is quite probable) I'm wrong but you can use grep -Exc so you don't need to count as many bytes for the switches. \$\endgroup\$ – Neil Dec 25 '15 at 19:41
  • \$\begingroup\$ @Neil - i dunno if you're wrong. i have really no idea - have a look at the edit history. \$\endgroup\$ – mikeserv Dec 25 '15 at 20:02
2
\$\begingroup\$

Mathematica 10.1, 46 bytes

LetterQ@#&&#==ToCamelCase@#&&StringLength@#>1&

Uses one less byte than the standard regex solution. It does three checks. LetterQ@# ensures that the string is entirely composed of letters, and StringLength@#>1 invalidates single-letter strings. #==ToCamelCase@# makes less sense, however. ToCamelCase is an undocumented function I found that takes an input string AndOutputsItLikeThis. Since there is only one word, it will capitalize the first letter, so we check if the string is equal to that.

\$\endgroup\$
  • \$\begingroup\$ Is ToCamelCase new in 10.3? Doesn't seem to work in 10.2. \$\endgroup\$ – murphy Dec 25 '15 at 16:20
  • \$\begingroup\$ @murphy, it works for me in 10.1. What do you get with ToCamelCase["foo bar baz"]? \$\endgroup\$ – LegionMammal978 Dec 25 '15 at 16:31
  • \$\begingroup\$ Ok, I can confirm that it works in 10.1. However, in 8.0, 9.0, 10.0 and 10.2 the function is not defined (your test case returns ToCamelCase[foo bar baz]). Strange! Maybe someone can check 10.3? \$\endgroup\$ – murphy Dec 25 '15 at 21:56
2
\$\begingroup\$

bash/zsh/ksh, 25 bytes

[[ $1 =~ ^[A-Z][a-z]+$ ]]

To actually use this, make a file with it as the only line and make the file executable; executable files not recognized as a known binary type are treated as shell scripts (for /bin/sh specifically).

$ printf '[[ $1 =~ ^[A-Z][a-z]+$ ]]' >f
$ chmod +x f
$ wc -c f
25 f
$ for x in 'Adnan' 'adnan' 'AdnaN' 'Adnan123' 'Adnan Adnan' 'A' 'Mary-Ann'; do f "$x" && echo 1 || echo 0; done
1
0
0
0
0
0
0
$ 
\$\endgroup\$
  • 2
    \$\begingroup\$ This works fine in bash, ksh and zsh, but has no chance to work in standard POSIX sh or the compatible dash and yash. To avoid confusion, I suggest to change the answer's title. \$\endgroup\$ – manatwork Dec 24 '15 at 9:57
  • 3
    \$\begingroup\$ Use printf instead of echo to create the file and you’ll get 25 bytes. \$\endgroup\$ – sam hocevar Dec 24 '15 at 15:21
  • \$\begingroup\$ Good points, both of you; both applied. \$\endgroup\$ – Aaron Davies Dec 28 '15 at 17:10
2
\$\begingroup\$

C# 4, 89 bytes

My first attempt at Code Golf. Here it comes:

bool o(string i){return System.Text.RegularExpressions.Regex.IsMatch(i,"^[A-Z][a-z]+$");}

See it in action at Dot Net Fiddle.

\$\endgroup\$
  • \$\begingroup\$ If you use C# 6, you can make it a bit shorter: bool o(string i)=>System.Text.RegularExpressions.Regex.IsMatch(i,"^[A-Z][a-z]+$"); \$\endgroup\$ – ProgramFOX Dec 26 '15 at 14:01
2
\$\begingroup\$

Java, 28 bytes

n->n.matches("[A-Z][a-z]+")

Uses regex to make sure the string consists of an uppercase character followed by at least one lowercase character.

-1 bytes thanks to Benjamin Urquhart

\$\endgroup\$
  • \$\begingroup\$ You can drop the semicolon \$\endgroup\$ – Benjamin Urquhart May 17 at 15:00
  • \$\begingroup\$ @BenjaminUrquhart oh right, thanks \$\endgroup\$ – HyperNeutrino May 18 at 17:45
1
\$\begingroup\$

k4, 39 bytes

{((*x)in .Q.A)&(&/(1_,/x)in .Q.a)&1<#x}

First char is upper, all others are lower, count greater than one.

E.g.:

  {((*x)in .Q.A)&(&/(1_,/x)in .Q.a)&1<#x}'("Adnan";"adnan";"AdnaN";"Adnan123";"Adnan Adnan";"A";"Mary-Ann")
1000000b
\$\endgroup\$
1
\$\begingroup\$

Seriously, 16 bytes

ú4,nÿ=)l1<)ù-Y&&

Hex Dump:

a3342c6e983d296c313c29972d592626

Try It Online

Seriously does not have regex support yet, so the best we can do is:

 4,n                               Push 4 copies of input
    ÿ=                             Check that it's equal to itself converted to titlecase
      )                            Put the boolean on the bottom
       l1<                         Check that it's longer than 1 character
          )                        Put the boolean on the bottom
           ù                       Convert it to lowercase.
ú           -Y                     Check that removing the lowercase alphabet empties it
              &&                   And all the booleans together
\$\endgroup\$
1
\$\begingroup\$

Ocaml, 231 216 197 166 bytes

let f n=let l=String.length n in if l=1 then 0 else let rec e=function 0->1|i->match n.[i] with('a'..'z')->e(i - 1)|_->0 in match n.[0]with('A'..'Z')->e(l - 1)|_->0;;

Example usage:

# f "Adnan";;
- : int = 1

# f "adnan";;
- : int = 0

# f "AdnaN";;
- : int = 0

# f "Adnan123";;
- : int = 0

# f "Adnan Adnan";;
- : int = 0

# f "A";;
- : int = 0

# f "Mary-Ann";;
- : int = 0

Ungolfed (with real function names):

let is_name name =
  let len = String.length name
  in if len = 1 then 0 else
  let rec explode_lower = function
    | 0 -> 1
    | i ->
      match name.[i] with
      | ('a'..'z') -> explode_lower (i - 1)
      | _ -> 0
  in match name.[0] with
  | ('A'..'Z') -> explode_lower (len - 1)
  | _ -> 0;;
\$\endgroup\$
  • \$\begingroup\$ You could actually save about 10% by using booleans instead of integers (bleh!) and replacing those bulky if … then 0 else by … ||. And for that matter by using boolean operators instead of match and ranges, e.g. n.[0]>'@'&n.[0]<'['&e(l-1) \$\endgroup\$ – Gilles Dec 26 '15 at 19:29
1
\$\begingroup\$

SpecBAS - 39 bytes

SpecBAS handles regular expressions through the MATCH command. Output is 0 for false and 1 if true.

1 input n$:  ?MATCH("^[A-Z][a-z]+$",n$)
\$\endgroup\$
1
\$\begingroup\$

Swift 2, 116 bytes

Regex is so verbose in Swift that doing this is much shorter

func e(s:String)->Int{var c=0;for k in s.utf8{if(c==0 ?k<65||k>90:k<97||k>122){return 0};c++};return s.utf8.count-1}

This will return 0 or -1 (in the case of no input) for non-official names, and a number > 0 (which is equal to the length of the string - 1) if the name is official

Ungolfed

func e(s: String) -> Int{
    var c = 0
    for k in s.utf8{
        if(c == 0 ? k < 65 || k > 90 : k < 97 || k > 122){
            return 0
        }
        c++
    }
    return s.utf8.count - 1
}
\$\endgroup\$
1
\$\begingroup\$

C#, 188 bytes

Regular expressions would have been the right way to tackle this, but here's an attempt without it.

bool O(string s){for(int i=1;i<s.Length;i++){if(char.IsUpper(s[i])){return false;}}if(char.IsUpper(s[0])&&s.All(Char.IsLetter)&&!s.Contains(" ")&& s.Length > 1){return true;}return false;}

Longhand

static bool O(string s)
{
    for (int i = 1; i < s.Length; i++)
    {
        if (char.IsUpper(s[i]) )
        {
            return false;
        }
    }
    if (char.IsUpper(s[0]) && s.All(Char.IsLetter) && !s.Contains(" ") && s.Length > 1)
    {
        return true;
    }
    return false;
}

Would love advice on how to make the lowercase check shorter, perhaps without the loop. I just started learning the language, and used this as practice, figured I'd share my result anyway.

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

Perl 5 -p, 18 bytes

$_=/^[A-Z][a-z]+$/

Try it online!

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

PowerShell, 29 bytes

"$args"-cmatch'^[A-Z][a-z]+$'

Try it online!

Does the same regex trick everyone else is using. Has to use case-sensitive match to properly do it at the cost of a byte.

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

Japt, 9 bytes

Returns 1 or 0.

è"^%A%a+$

Try it

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

Perl 6, 17 bytes

{/^<:Lu><:Ll>+$/}

Returns a Match object if this is an official name and Nil otherwise.

Try it online!

\$\endgroup\$
  • \$\begingroup\$ You don't need the m \$\endgroup\$ – Jo King May 22 at 22:58

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.