# Objective

Write a program or function that checks if a variable name is valid and output 1 or True if it is valid, 0.5 if it is valid but starts with an underscore (_), and 0 or False if it is not valid.

# Rules

• A variable name in most languages is valid if it begins with an underscore or letter (a-z, A-Z, _) and the rest of the characters are either underscores, letters, or numbers. (a-z, A-Z, 0-9, _)
• Output 1 or True if the variable name is valid and 0 or False if not valid.
• However, it is not good practice to start a variable with an underscore, so return 0.5 if it starts with an underscore and the name is valid.

# Test Cases

## Input

abcdefghijklmnop

## Output

1

## Input

_test_

## Output

0.5 (starts with an underscore)

## Input

123abc

## Output

0 (starts with a number)

## Input

A_b1C_23

## Output

1

## Input

_!

## Output

0 (not 0.5 because it's not valid)

## Input

magical pony1

## Output

0 (no spaces)

Standard loopholes apply.

This is , so shortest code wins.

Bonus: -10% if your program/function outputs 0 for an empty string("").

• Can we output truthy/falsy/anything? – CalculatorFeline Mar 19 '16 at 15:14
• Just noting, in python, under scores are often used. Classes need an init function, helper functions in classes are sometimes begun with an underscore. – Rɪᴋᴇʀ Mar 19 '16 at 16:17
• @EasterlyIrk beware of mini-markdown; you meant __init__; also, no, classes do not need an __init__ but typically have one – cat Mar 19 '16 at 16:29
• Can we assume that the input will be non-empty? (Most of the current answers seem to fail for empty input.) – Dennis Mar 19 '16 at 16:35
• Does that bonus round up or down? If up, it's really not worth having for the current set of answers – Blue Mar 19 '16 at 16:41

## JavaScript (ES6), 37 - 10% = 33.3 bytes

Saved 4 bytes thanks to @edc65

Saved 5.6 bytes thanks to @Mateon

s=>!/^\d|\W|^$/.test(s)/-~(s[0]=='_')  • Are you absolutely sure this is not perl? – seequ Mar 21 '16 at 19:56 # 05AB1E, 252420 19 bytes Code: ¬D'_Qsa·+¹žj-""Q*2/  Explanation: ¬ # Push input and also push the first character. D # Duplicate the first character. '_Q # Check if it is equal to an underscore character. sa # Swap and check the duplicate if it's an alphabetic character. · # Double the value. + # Add both values up ¹ # Take the first input. žj- # žj is short for [a-zA-Z0-9_]. This will be substracted from the initial string. ""Q # Check if the string is empty. * # Multiply this with the first value. 2/ # Halve it, resulting into 0.0, 0.5, or 1.0.  In short, the formula for the string s in pseudocode is: ((s[0] == '_' + s.isalpha() × 2) × (s.remove([a-zA-Z0-9_]) == "")) / 2  Try it online! Uses CP-1252 encoding. ## PHP (50 - 10% = 45) Thanks to Schism for the -2 :) preg_match('/^[a-z_]\w*$/i',$s)?$s[0]=='_'?.5:1:0;


Not to compete with the golflang answers, but I thought I'd try it anyways.

preg_match('/^[a-z_]\w*$/i',$s) # Matches every a-zA-Z0-9_ string that doesnt start with a number
0

### Explanation

First of all, we check if input starts with a digit or contains a non-word character (anything other than a-z, A-Z, digits and underscore). If it does, it's discarded, because it's invalid. Then we check if it starts with an underscore. If it does, it's replaced with 0.5. Then we check if it starts with a non-digit character (at this point the first character is either 0, a-z, or A-Z. Only a-z and A-Z are non-digits, obviously). If it does, it's replaced with a 1. Then we check for empty string and replace it with 0.

• Waitwaitwait. At the ^\D.* stage it can start with a 0? That's weird. – CalculatorFeline Mar 19 '16 at 19:55
• @CatsAreFluffy It can, if it started with a _ and was replaced with 0.5. Then it starts with a 0. – daavko Mar 19 '16 at 19:58
• This incorrectly gives a 1 for input Ψ. – AdmBorkBork Mar 21 '16 at 19:27
• @TimmyD Interesting. I don't understand why does it do so. Quick check indicates that \w is matching non-ASCII characters, which it shouldn't do (I've tried to give it ƜƝƞƟƠ and ᎳᎴᎵᎶᎷᎸᎹ as input). I'll look into this later. Possible solution seems replacing \w with [a-zA-Z\d_]. – daavko Mar 21 '16 at 19:43

# MATL, 27 bytes

1)95=2/8M3Y2m+G7M95h4Y2hmA*


This works in current version(15.0.0) of the language.

Input is a string with single quotes.

Try it online!

### Explanation

1)      % take input implicitly. Get its first element
95=     % true if it equals 95 (underscore)
2/      % divide by 2: gives 0.5 if underscore, 0 if not
8M      % push first element of input again
3Y2     % predefined literal: string with all letters
m       % true if it's a letter
+       % add. Gives 1 if letter, 0.5 if underscore
G       % push input again
7M      % push string with all letters again
95h     % concatenate underscore
4Y2h    % predefined literal: string with all digits. Concatenate
mA      % true if all input chars belong to that concatenated string
*       % multiply. Display implicitly


## Pyke, 21 bytes

### (noncompeting, added string subtraction, various string constants)

Qh~u{Q~J\_+-|!Qh\_qh/


Explanation:

Qh~u{                 - Check first char isn't a digit
Q~J\_+-          - Is the input alphanumeric + "_"
|!        - Combine
Qh\_q   - Is the first char an "_"
h/ - Combine


# Python 3, 36 bytes

lambda s:s.isidentifier()/-~(s[:1]=='_')


The code is 40 bytes long and qualifies for the -10% bonus.

Note that this will only work correctly for code pages that don't have non-ASCII letters/digits.

## Pyth, 27 bytes

c!|-rz0++G\_JjkUT}hzJhqhz\_


Test Suite

# Gogh, 29 bytes

÷"[^\W\d]\w*"g¦"_.*"g+÷2=0.5¿


Run using:

$./gogh no '÷"[^\W\d]\w*"g¦"_.*"g+÷2=0.5¿' "_test"  ### Explanation  “ Implicit input ” ÷ “ Duplicate the TOS ” "[^\W\d]\w*"g “ Fully match the STOS against the TOS (regex) ” ¦ “ Swap the STOS and TOS ” "_.*"g “ Fully match the STOS against the TOS (regex) ” + “ Add the TOS to the STOS ” ÷ “ Duplicate the TOS ” 2= “ Determine if the TOS is equal to 2 ” 0.5¿ “ Leave the correct output on the stack ” “ Implicit output ”  # Perl, 21 bytes $_=!/\W|^\d//2**/^_/


The score includes +1 byte for the -p switch. Try it on Ideone.

• could you have, say -$_||$_=... to account for the empty answer? (using - because + is a noop in perl) – Ven Mar 21 '16 at 14:05
• No, that's a runtime error. But even if it worked, it would make my score worse. – Dennis Mar 21 '16 at 15:41
• I only did minimalistic tests, so I'll trust you. Fair that 10% of 21 bytes isn't much.. – Ven Mar 21 '16 at 15:43

# Pyth, 19 bytes

c!:z"\W|^\d"0h!xz\_


Try it with the Pyth Compiler.

Note that this will only work correctly for code pages that don't have non-ASCII letters/digits.

### How it works

c!:z"\W|^\d"0h!xz\_  (implicit) Save the input in z.

:z        0        Test if z matches the following regex:
"\W|^\d"           A non-word character or a digit at the beginning.
This returns True iff z is an invalid name.
!                   Apply logical NOT to yield True iff z is a valid name.
xz\_  Find the first index of the underscore in z.
This yields 0 iff z begins with an underscore.
h!      Apply logical NOT and increment.
This yields 2 if z begins with an underscore, 1 otherwise.
c                    Divide the two results.


# Factor, 84 * 0.9 = 76.5

USE: regexp
[ R/ [_a-zA-Z]\w*/ R/ _.*/ [ matches? 1 0 ? ] bi-curry@ bi 0 = 1 2 ? / ]


Runs on the listener (repl), defines a quotation (anonymous function) that takes a string and outputs { 0 | 1/2 | 1 }.

Defining it as a word it's 97 chars:

USE: regexp
: v ( s -- n ) R/ [_a-zA-Z]\w*/ R/ _.*/ [ matches? 1 0 ? ] bi-curry@ bi 0 = 1 2 ? / ;


### How does it work:

R/ [_a-zA-Z]\w*/ R/ _.*/ defines two regular expressions. bi-curry@ partially applies the quotation [ matches? 1 0 ? ] to each regex, leaving two curried quotations on the stack. bi applies each quotation to the argument string.

Each of those (curried quotations) leave either a 1 or a 0, depending if they matched. The first matches on the well formed names, the second on names starting with underscore.

0 = 1 2 ? / The last value is replaced with a 1 if it was 0, or with a 2 if it was 1. Then the first (1 or 0, valid or not) is divided by the second (2 or 1, starts with underscore or not).

This is loooong! Any pointers to shrinking a bit more appreciated...

And I hate regexps!

### PS.

{ 0 } [ "" v ] unit-test
{ 0 } [ "" v ] unit-test
{ 0 } [ "1" v ] unit-test
{ 0 } [ "1var" v ] unit-test
{ 0 } [ "var$" v ] unit-test { 0 } [ "foo var" v ] unit-test { 1 } [ "v" v ] unit-test { 1 } [ "var" v ] unit-test { 1 } [ "var_i_able" v ] unit-test { 1 } [ "v4r14bl3" v ] unit-test { 1/2 } [ "_" v ] unit-test { 1/2 } [ "_v" v ] unit-test { 1/2 } [ "_var" v ] unit-test { 1/2 } [ "_var_i_able" v ] unit-test { 1/2 } [ "_v4r14bl3" v ] unit-test  all test pass ;) • Just wondering, is the whitespace truly necessary? I can't say for sure since I don't know the language or have the interpreter. – Mama Fun Roll Mar 21 '16 at 23:46 • @MamaFunRoll yeah, not the best golfing language! In the Forth tradition, only delimiter are whitespace chars. – fede s. Mar 22 '16 at 2:59 • Oh, I see. Here, have an upvote. – Mama Fun Roll Mar 22 '16 at 3:07 • Yay, ty! Now to break havoc with my comment-everywhere priv! – fede s. Mar 22 '16 at 3:23 # Dyalog APL, 19 bytes - 10% = 17.1 {(0≤⎕NC⍵)÷1+'_'=⊃⍵}  {⍵} anonymous function where the right argument is represented by ⍵ ⊃⍵ first character (gives space if empty) '_'= 1 if equal to 'underbar, 0 otherwise 1+ evaluates to 2 if initial underbar, 1 otherwise ⎕NC⍵ name class; -1 if invalid name, 0 if undefined (but valid name), 2-9 if defined (and thus valid) # Mathematica, 93 bytes If[#~StringMatchQ~RegularExpression@"[A-Za-z_][0-9A-Za-z_]*",If[#~StringTake~1=="_",.5,1],0]&  I'm honestly not sure if this can be golfed further. # Perl, 34 + 1 = 35 bytes $_=/^([^\W\d])\w*$//(($1 eq"_")+1)


Uses the -p flag.

## Explanation

$_=/^([^\W\d])\w*$//(($1 eq"_")+1) /^([^\W\d])\w*$/                 matches any string that starts with an underscore or a letter of the alphabet followed by 0 or more alphanumeric + underscore characters. The first character is stored in a capture group
/                divide result by
(($1 eq"_")+1) (capture == "_") + 1. This is 1 if the first character was not an underscore and 2 if it was.$_=                                 assign to $_ and implicitly print  • [_a-zA-Z] -> [^\W\d] if perl works the same as JavaScript, I think you'd also have to do \w* – Downgoat Mar 19 '16 at 15:22 • @Downgoat Seems to work fine with \w+. – a spaghetto Mar 19 '16 at 15:24 • matches false for a – Downgoat Mar 19 '16 at 15:26 • @Downgoat Ah, right. I see. – a spaghetto Mar 19 '16 at 15:36 # Python, 84 -10% = 76 bytes lambda x:[0,[[.5,1][x[0]>'z'],0][x[0]<'A']][x.replace('_','a').isalnum()]if x else 0  # JavaScript ES7, 37 bytes x=>!x.match(/\W|^\d/)/2**/^_/.test(x)  Try it online How it works: x=> // Fat arrow function !x.match(/\W|^\d/) // Gives false if contains non word or starting // with a digit. Booleans in numeric context will // be 0 or 1 2** // 2 to the power of... /^_/.test(x) // gives true if starting with '_'. // true -> 1 -> 2**1 -> 2 // false -> 0 -> 2**0 -> 1 / // Devide the lValue boolean with the numeric rValue: // lValue = 0 or 1 // rValue = 2 or 1  Port of @Dennis's Perl answer # Ruby, 44 bytes ->(s){s=~/^(_|\d)?\w*$/?$1?$1==?_?0.5:0:1:0}

• You don't need parens around the parameters for stabby lambdas – Not that Charles Mar 21 '16 at 18:24
• Also if you can figure out a way to drop that extra ternary you can probably save some bytes. Maybe /^([a-z_]).../i instead of /^(_|\d)?.../ – Not that Charles Mar 21 '16 at 18:44
• @NotthatCharles D'oh... you're right. I'll give it a closer look when I a chance – Flambino Mar 21 '16 at 20:35

# Ruby, 57 - 10% = 51.3 bytes

->(s){case s
when'',/^\d/,/\W/
0
when/^_/
0.5
else
1
end}


A pretty naïve approach

• 51.3 bytes, mind you. :) – Xesau Mar 21 '16 at 16:19
• @Xesau whoops - embarassing. Fixed now :) – Flambino Mar 21 '16 at 17:40
• You save a huge amount of bytes if you use ternary chaining: ->(s){s=~/^$|^\d|\W/?0:s=~/^_/?0.5:1} – Value Ink Mar 21 '16 at 20:27 • @KevinLau True - I added another ruby answer in that vein already (though it's not great either) – Flambino Mar 21 '16 at 20:37 # Lua, 82 - 10% = 73.8 v=function(s)return(s:match("^[_%a]+[_%w]*$")and 1or 0)*(s:match("_")and.5or 1)end


Test Cases:

print(v("a") == 1) -- true
print(v("1") == 0) -- true
print(v("_") == 0.5) -- true
print(v("") == 0) -- true
print(v("1a") == 0) -- true
print(v("a1") == 1) -- true
print(v("_1") == 0.5) -- true
print(v("_a") == 0.5) -- true
print(v("1_") == 0) -- true
print(v("a_") == 0.5) -- true

• I think you can use STDIN to eat at least 10 bytes. – Leaky Nun Mar 30 '16 at 15:39

# Lua, 68 * .9 = 61.2 bytes

s=arg[1]print(s:find("^[%a_][%w_]*\$")and(s:find("^_")and.5or 1)or 0)


Takes arguments on the command line