Este é um nome de variável válido?

23

Objetivo

Escreva um programa ou função que verifique se um nome de variável é válido e gera 1 ou Truese é válido, 0,5 se é válido, mas começa com um sublinhado (_) e 0 ou Falsese não é válido.

Regras

  • Um nome de variável na maioria dos idiomas é válido se começar com um sublinhado ou letra (az, AZ, _) e o restante dos caracteres forem sublinhados, letras ou números. (az, AZ, 0-9, _)
  • Saída 1 ou Truese o nome da variável for válido e 0 ou Falsese não for válido.
  • No entanto, não é uma boa prática iniciar uma variável com um sublinhado; portanto, retorne 0,5 se começar com um sublinhado e o nome for válido.

Casos de teste

Entrada

abcdefghijklmnop

Saída

1

Entrada

_test_

Saída

0.5 (começa com um sublinhado)

Entrada

123abc

Saída

0 (começa com um número)

Entrada

A_b1C_23

Saída

1

Entrada

_!

Saída

0 (não 0,5 porque não é válido)

Entrada

magical pony1

Saída

0 (sem espaços)

Aplicam-se brechas padrão .

Isso é , então o código mais curto vence.

Bônus: -10% se o seu programa / função gerar 0uma string vazia ( "").

clamchowder314
fonte
1
Podemos produzir verdade / falsidade / qualquer coisa?
CalculatorFeline
5
Apenas observando, em python, as pontuações são frequentemente usadas. As classes precisam de uma função init , as funções auxiliares nas classes às vezes são iniciadas com um sublinhado.
Rɪᴋᴇʀ
1
O @EasterlyIrk tem cuidado com a mini-remarcação; você quis dizer __init__; Além disso, não, as classes não precisam de um, __init__mas normalmente têm um
cat
6
Podemos assumir que a entrada será não vazia? (A maioria das respostas atuais parecem falhar para a entrada vazia.)
Dennis
1
Esse bônus é arredondado para cima ou para baixo? Se-se, não é realmente vale a pena ter para o atual conjunto de respostas
Azul

Respostas:

13

JavaScript (ES6), 37 - 10% = 33,3 bytes

Guardado 4 bytes graças a @ edc65

Guardado 5,6 bytes graças a @Mateon

s=>!/^\d|\W|^$/.test(s)/-~(s[0]=='_')
Downgoat
fonte
3
Você tem certeza absoluta de que isso não é perl?
seequ
8

05AB1E , 25 24 20 19 bytes

Código:

¬D'_Qsa·+¹žj-""Q*2/

Explicação:

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

Em resumo, a fórmula para a sequência sno pseudocódigo é:

((s[0] == '_' + s.isalpha() × 2) × (s.remove([a-zA-Z0-9_]) == "")) / 2

Experimente online!

Usa a codificação CP-1252 .

Adnan
fonte
6

PHP (50 - 10% = 45)

Obrigado ao Schism pela -2 :)

preg_match('/^[a-z_]\w*$/i',$s)?$s[0]=='_'?.5:1:0;

Para não competir com as respostas do golflang, mas pensei em tentar de qualquer maneira.

preg_match('/^[a-z_]\w*$/i', $s) # Matches every a-zA-Z0-9_ string that doesnt start with a number
?   $s[0] == '_'                   # Then, if it starts with an _
    ?   .5                         # give 0.5 points
    :   1                          # If it doesn't, give 1
:   0;                             # If it didn't match the regex, give 0

Algo a se notar é que, no PHP, sem o /umodificador, \wapenas seleciona letras ASCII. Em alguns outros idiomas / tipos de expressão regular, esse padrão não funcionará.

Editar : vejo muitas pessoas usando \ w e \ d em suas respostas, quando usam um idioma que inclui letras e dígitos não-ASCII também. Esse não é o quebra-cabeça. Eles estão errados. (Não é possível votar / comentar ainda, desculpe-me por contar dessa maneira.)

Xesau
fonte
Bem-vindo à Programação de quebra-cabeças e Code Golf Stack Exchange. Esta é uma ótima resposta; os desafios do código-golfe estão dentro dos idiomas e também entre eles. Estou lhe dando um +1 por esta solução! Bem feito.
Wizzwizz4
1
Você pode cortar dois caracteres com [a-z].../i.
Schism
@Schism Obrigado. Não sei como eu consegui esquecer que, geralmente eu sou bom em este tipo de puzzles regex :)
Xesau
1
Sobre sua edição: você pode ser mais específico - quais idiomas? Em javascript \dé exatamente o mesmo que [0-9]. \wé exatamente o mesmo que [A-Za-z0-9_] developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/…
edc65 21/16
A página de código que o idioma usa é irrelevante; desde que o regex manipule corretamente o ASCII, ele é válido. Todas as respostas atuais baseadas em regex funcionam, que eu saiba. Você não está tentando corresponder um nome de variável no seu idioma; em vez disso, você está tentando corresponder um nome de variável com base nas regras do desafio.
Mego 22/03
5

Retina, 30 - 10% = 27 28 - 10% = 25,2 29 - 10% = 26,1 bytes

Ambas as versões se qualificam para o bônus, pois lidam corretamente com entradas vazias (saídas 0)

Eu tive que corrigir um bug causado por um dos recursos de regex do .NET, que considera alguns (leia tantos) caracteres Unicode como caracteres "word". Felizmente, isso me custou apenas um byte em ambas as versões. Tudo se resumia a adicionar um modificador para tornar o comportamento de correspondência de expressões regulares compatível com os padrões ECMAScript. Mais sobre isso aqui .

Nova versão de 28 bytes de 28 , feita por @ MartinBüttner. Obrigado!

^ _
$ _¶_
Mme` ^ (?! \ D) \ w + $
2
0,5

Explicação

Primeiro, verificamos se a entrada começa com um sublinhado. Nesse caso, a entrada é duplicada, com uma nova linha no meio. Por exemplo: _test_-> _test_\n_test_, onde \nestá a nova linha. Em seguida, tentar igualar qualquer coisa, que não começa com um número, mas é seguido por qualquer número de caracteres "palavra" ( a-z, A-Z, números e sublinhado) em cada linha . Observe que se a entrada começou com um sublinhado e foi substituída por duas linhas, isso corresponderá às duas linhas. Em seguida, verificamos se tivemos 2 correspondências e as substituímos por 0.5. Linhas vazias ou inválidas sempre produzirão 0 correspondências e nomes de variáveis ​​válidas sempre produzirão 1 correspondência.


Minha própria versão de 30 bytes de 31 bytes

Ae` ^ \ d | \ W
^ _. *
0,5
^ \ D. *
1
^ $
0 0

Explicação

Primeiro de tudo, vamos verificar se entrada começa com um dígito ou contém um caractere não-palavra (outra coisa senão a-z, A-Z, dígitos e sublinhado). Se isso acontecer, ele será descartado, porque é inválido. Depois, verificamos se ele começa com um sublinhado. Se isso acontecer, é substituído por 0.5. Em seguida, vamos verificar se ele começa com um personagem não-dígito (neste momento o primeiro caractere ou é 0, a-zou A-ZOnly. a-zE A-Zsão não-dígitos, obviamente). Se isso acontecer, é substituído por um 1. Em seguida, verificamos se há uma string vazia e a substituímos por 0.

Experimente online!
Experimente online! Versão antiga

daavko
fonte
Espere, espere, espere. Na ^\D.*fase, pode começar com um 0? Isso é estranho.
CalculatorFeline
@CatsAreFluffy Pode, se começou com um _e foi substituído por 0.5. Então começa com um 0.
daavko 19/03/16
Isso incorretamente fornece 1 para entrada Ψ.
21716 AdmBorkBork
@TimmyD Interesting. Eu não entendo por que isso acontece. A verificação rápida indica que \westá correspondendo caracteres não ASCII, o que não deve ser feito (tentei fornecer ƜƝƞƟƠe ᎳᎴᎵᎶᎷᎸᎹcomo entrada). Vou analisar isso mais tarde. A solução possível parece ser substituída \wpor [a-zA-Z\d_].
Daavko 21/03/16
3

MATL , 27 bytes

1)95=2/8M3Y2m+G7M95h4Y2hmA*

Isso funciona na versão atual (15.0.0) do idioma.

Entrada é uma string com aspas simples.

Experimente online!

Explicação

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
Luis Mendo
fonte
3

Pyke , 21 bytes

(não competitivo, subtração de string adicionada, várias constantes de string)

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

Explicação:

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
Azul
fonte
3

Python 3, 36 bytes

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

O código tem 40 bytes e se qualifica para o bônus de -10% .

Observe que isso só funcionará corretamente para páginas de código que não tenham letras / dígitos não ASCII.

Dennis
fonte
2

Pitão, 27 bytes

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

Suíte de teste

Azul
fonte
2

Gogh , 29 bytes

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

Execute usando:

$ ./gogh no '÷"[^\W\d]\w*"g¦"_.*"g+÷2=0.5¿' "_test"

Explicação

                   “ 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                              ”
Zach Gates
fonte
2

Perl, 21 bytes

$_=!/\W|^\d//2**/^_/

A pontuação inclui +1 byte para o -pswitch. Experimente em Ideone .

Dennis
fonte
você poderia dizer, -$_||$_=...para dar conta da resposta vazia? (usando -porque +é um noop em perl) #
21416 Ven Ven
Não, isso é um erro de tempo de execução. Mas mesmo que funcionasse, pioraria minha pontuação.
Dennis
Eu só fiz testes minimalistas, então vou confiar em você. É justo que 10% dos 21 bytes não sejam muito .. #
2120 Ven Ven
2

Pitão, 19 bytes

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

Experimente com o Pyth Compiler .

Observe que isso só funcionará corretamente para páginas de código que não tenham letras / dígitos não ASCII.

Como funciona

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.
Dennis
fonte
2

Fator , 84 * 0,9 = 76,5

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

Executa no ouvinte (repl), define uma cotação (função anônima) que pega uma string e gera {0 | 1/2 1}.

Definindo como uma palavra, são 97 caracteres:

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

Como funciona:

R/ [_a-zA-Z]\w*/ R/ _.*/define duas expressões regulares. bi-curry@aplica parcialmente a cotação [ matches? 1 0 ? ]a cada regex, deixando duas cotações ao curry na pilha. biaplica cada cotação à sequência de argumentos.

Cada uma dessas (cotações ao curry) deixa 1 ou 0, dependendo da correspondência. As primeiras correspondências nos nomes bem formados, a segunda nos nomes começando com sublinhado.

0 = 1 2 ? / O último valor é substituído por 1 se for 0 ou com 2 se for 1. Então o primeiro (1 ou 0, válido ou não) é dividido pelo segundo (2 ou 1, começa com sublinhado ou não) .

Isso é loooong! Quaisquer dicas para encolher um pouco mais apreciado ...

E eu odeio 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

todos os testes aprovados;)

fede s.
fonte
Apenas imaginando, o espaço em branco é realmente necessário? Não posso ter certeza, pois não conheço o idioma ou tenho o intérprete.
Mama Fun Roll
@MamaFunRoll sim, não é a melhor linguagem de golfe! Na quarta tradição, apenas delimitador são caracteres de espaço em branco.
fede s.
Ah eu vejo. Aqui, tenha um voto positivo.
Mama Fun Roll
Yay, ty! Agora, para arruinar o meu comentário - em todo lugar priv!
fede s.
2

Dyalog APL , 19 bytes - 10% = 17,1

{(0≤⎕NC⍵)÷1+'_'=⊃⍵}

{... ... }função anônima onde o argumento direita é representada por
⊃⍵primeiro caractere (dá espaço se vazia)
'_'=1 se igual a 'underbar, 0 caso contrário
1+avalia a 2 se underbar inicial, 1 caso contrário
⎕NC⍵ nome da classe ; -1 se nome inválido, 0 se indefinido (mas nome válido), 2-9 se definido (e, portanto, válido)

Adão
fonte
1

Mathematica, 93 bytes

If[#~StringMatchQ~RegularExpression@"[A-Za-z_][0-9A-Za-z_]*",If[#~StringTake~1=="_",.5,1],0]&

Sinceramente, não tenho certeza se isso pode ser jogado mais.

LegionMammal978
fonte
1

Perl, 34 + 1 = 35 bytes

$_=/^([^\W\d])\w*$//(($1 eq"_")+1)

Usa a -pbandeira.

Explicação

$_=/^([^\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
um spaghetto
fonte
[_a-zA-Z]-> [^\W\d]se perl funciona da mesma forma JavaScript, eu acho que você também teria que fazer\w*
Downgoat
@Downgoat Parece funcionar bem \w+.
a spaghetto
corresponde a falso paraa
Downgoat 19/03/16
@Downgoat Ah, certo. Entendo.
um spaghetto
1

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
Máx.
fonte
0

JavaScript ES7, 37 bytes

x=>!x.match(/\W|^\d/)/2**/^_/.test(x)

Experimente online

Como funciona:

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

andlrc
fonte
0

Ruby, 44 bytes

->(s){s=~/^(_|\d)?\w*$/?$1?$1==?_?0.5:0:1:0}
Flambino
fonte
Você não precisa de parênteses em torno dos parâmetros para lambdas stabby
Não que Charles
Além disso, se você conseguir descobrir uma maneira de eliminar esse ternário extra, provavelmente poderá salvar alguns bytes. Talvez /^([a-z_]).../iem vez de/^(_|\d)?.../
Não que Charles
@NotthatCharles D'oh ... você está certo. Vou dar uma olhada mais de perto quando
tiver
0

Ruby, 57 - 10% = 51,3 bytes

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

Uma abordagem bastante ingênua

Flambino
fonte
51,3 bytes, lembre-se. :)
Xesau
@Xesau whoops - embaraçoso. Corrigido agora :)
Flambino 21/03
Você economiza uma quantidade enorme de bytes se usar o encadeamento ternário:->(s){s=~/^$|^\d|\W/?0:s=~/^_/?0.5:1}
Value Ink
@KevinLau verdadeiro - acrescentei outra resposta rubi nesse sentido já (embora não seja grande quer)
Flambino
0

Lua, 82 - 10% = 73,8

v=function(s)return(s:match("^[_%a]+[_%w]*$")and 1or 0)*(s:match("_")and.5or 1)end

Casos de teste:

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
xaxa
fonte
Eu acho que você pode usar STDIN para comer pelo menos 10 bytes.
Freira Furada
0

Lua, 68 * .9 = 61,2 bytes

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

Recebe argumentos na linha de comando

Trebuchette
fonte