¿Es este un nombre de variable válido?

23

Objetivo

Escriba un programa o función que verifique si el nombre de una variable es válido y el resultado 1 o Truesi es válido, 0.5 si es válido pero comienza con un guión bajo (_) y 0 o Falsesi no es válido.

Reglas

  • Un nombre de variable en la mayoría de los idiomas es válido si comienza con un guión bajo o una letra (az, AZ, _) y el resto de los caracteres son guiones bajos, letras o números. (az, AZ, 0-9, _)
  • Salida 1 o Truesi el nombre de la variable es válido y 0 o Falsesi no es válido.
  • Sin embargo, no es una buena práctica comenzar una variable con un guión bajo, por lo tanto, devuelva 0.5 si comienza con un guión bajo y el nombre es válido.

Casos de prueba

Entrada

abcdefghijklmnop

Salida

1

Entrada

_test_

Salida

0.5 (comienza con un guión bajo)

Entrada

123abc

Salida

0 (comienza con un número)

Entrada

A_b1C_23

Salida

1

Entrada

_!

Salida

0 (no 0.5 porque no es válido)

Entrada

magical pony1

Salida

0 (No hay espacios)

Se aplican lagunas estándar .

Este es el , por lo que gana el código más corto.

Bonificación: -10% si su programa / función genera 0una cadena vacía ( "").

clamchowder314
fuente
1
¿Podemos emitir verdad / falsedad / cualquier cosa?
CalculatorFeline
55
Solo teniendo en cuenta, en python, a menudo se usan los puntajes inferiores. Las clases necesitan una función init , las funciones de ayuda en las clases a veces comienzan con un guión bajo.
Rɪᴋᴇʀ
1
@EasterlyIrk tenga cuidado con el mini-markdown; que quería decir __init__; Además, no, las clases no necesitan un, __init__pero generalmente tienen uno
gato
66
¿Podemos suponer que la entrada no estará vacía? (La mayoría de las respuestas actuales parecen fallar para la entrada vacía.)
Dennis
1
¿Esa bonificación se redondea hacia arriba o hacia abajo? Si está arriba, realmente no vale la pena tener el conjunto actual de respuestas
Azul

Respuestas:

13

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

Guardado 4 bytes gracias a @ edc65

5,6 bytes guardados gracias a @Mateon

s=>!/^\d|\W|^$/.test(s)/-~(s[0]=='_')
Downgoat
fuente
3
¿Estás absolutamente seguro de que esto no es perl?
seequ
8

05AB1E , 25 24 20 19 bytes

Código:

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

Explicación:

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

En resumen, la fórmula para la cadena sen pseudocódigo es:

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

Pruébalo en línea!

Utiliza la codificación CP-1252 .

Adnan
fuente
6

PHP (50-10% = 45)

Gracias a Schism por el -2 :)

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

No para competir con las respuestas de golflang, pero pensé que lo intentaría de todos modos.

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 tener en cuenta es que en PHP, sin el /umodificador, \wsolo selecciona letras ASCII. En algunos otros idiomas / sabores Regex, este patrón no funcionará.

Editar : veo a muchas personas que usan \ wy \ d en sus respuestas, cuando usan un idioma que también incluye letras y dígitos que no son ASCII. Ese NO es el rompecabezas. Están equivocados. (Todavía no puedo votar / comentar, lamento tener que decirlo de esta manera).

Xesau
fuente
Bienvenido a Programming Puzzles y Code Golf Stack Exchange. Esta es una respuesta genial; a menudo , los desafíos del código golf están dentro de los idiomas, así como entre ellos. ¡Te doy un +1 por esta solución! Bien hecho.
wizzwizz4
1
Puedes afeitar dos personajes con [a-z].../i.
Cisma
@Schism Gracias. No sé cómo logré olvidar eso, por lo general soy bueno en este tipo de rompecabezas de
expresiones
1
Acerca de su edición: ¿puede ser más específico? ¿Qué idiomas? En javascript \des exactamente lo mismo que [0-9]. \wes exactamente lo mismo que [A-Za-z0-9_] developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
edc65
La página de códigos que usa el lenguaje es irrelevante; siempre que la expresión regular maneje ASCII correctamente, es válida. Todas las respuestas actuales basadas en expresiones regulares funcionan, que yo sepa. No está intentando hacer coincidir un nombre de variable en su idioma; más bien, estás tratando de hacer coincidir un nombre de variable basado en las reglas del desafío.
Mego
5

Retina, 30 - 10% = 27 28 - 10% = 25.2 29 - 10% = 26.1 bytes

Ambas versiones califican para bonificación, ya que manejan la entrada vacía correctamente (salidas 0)

Tuve que corregir un error causado por una de las características de expresión regular de .NET, que considera algunos (leer tantos) caracteres Unicode como caracteres de "palabra". Afortunadamente, esto me costó solo un byte en ambas versiones. Solo se redujo a agregar un modificador para hacer que el comportamiento de coincidencia de expresiones regulares sea compatible con los estándares ECMAScript. Más sobre eso aquí .

Nueva versión 28 de 29 bytes, realizada por @ MartinBüttner. ¡Gracias!

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

Explicación

Primero, verificamos si la entrada comienza con un guión bajo. Si lo hace, la entrada se duplica, con una nueva línea en el medio. Por ejemplo: _test_-> _test_\n_test_, donde \nestá la nueva línea. Entonces tratamos de coincidir con nada, que no se inicia con un número, pero es seguido por cualquier número de caracteres "palabra" ( a-z, A-Z, dígitos, y subrayado) en cada línea . Tenga en cuenta que si la entrada comenzó con un guión bajo y fue reemplazada por dos líneas, esto coincidirá con ambas líneas. Luego verificamos si teníamos 2 coincidencias y las reemplazamos por 0.5. La línea vacía o no válida siempre generará 0 coincidencias, y los nombres de variables válidos siempre generarán 1 coincidencia.


Mi propia versión de 30 31 bytes

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

Explicación

En primer lugar, comprobamos si de entrada comienza con un dígito o contiene un carácter no-palabra (que no sea nada a-z, A-Z, dígitos y subrayado). Si lo hace, se descarta porque no es válido. Luego verificamos si comienza con un guión bajo. Si lo hace, se reemplaza con 0.5. Luego comprobamos si comienza con un carácter no numérico (en este punto el primer carácter es cualquiera 0, a-zo A-Z. Sólo a-zy A-Zson no dígitos, obviamente). Si lo hace, se reemplaza con a 1. Luego verificamos si hay una cadena vacía y la reemplazamos por 0.

Pruébalo en línea!
Pruébalo en línea! Versión antigua

daavko
fuente
Espera espera espera. ¿En la ^\D.*etapa puede comenzar con un 0? Eso es raro.
CalculatorFeline
@CatsAreFluffy Puede, si comenzó con ay _fue reemplazado por 0.5. Luego comienza con un 0.
daavko
Esto da incorrectamente un 1 para la entrada Ψ.
AdmBorkBork
@TimmyD Interesante. No entiendo por qué lo hace. La comprobación rápida indica que \wcoincide con caracteres no ASCII, lo que no debería hacer (he intentado darlo ƜƝƞƟƠy ᎳᎴᎵᎶᎷᎸᎹcomo entrada). Lo investigaré más tarde. Posible solución parece reemplazar \wcon [a-zA-Z\d_].
daavko
3

MATL , 27 bytes

1)95=2/8M3Y2m+G7M95h4Y2hmA*

Esto funciona en la versión actual (15.0.0) del lenguaje.

La entrada es una cadena con comillas simples.

Pruébalo en línea!

Explicación

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
fuente
3

Pyke , 21 bytes

(no competitiva, resta de cadena agregada, varias constantes de cadena)

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

Explicación:

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
fuente
3

Python 3, 36 bytes

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

El código tiene 40 bytes de longitud y califica para el bono de -10% .

Tenga en cuenta que esto solo funcionará correctamente para páginas de códigos que no tengan letras / dígitos que no sean ASCII.

Dennis
fuente
2

Gogh , 29 bytes

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

Ejecutar usando:

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

Explicación

                   “ 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                              ”
Puertas de Zach
fuente
2

Perl, 21 bytes

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

La puntuación incluye +1 byte para el -pcambio. Pruébalo en Ideone .

Dennis
fuente
¿podría tener, digamos -$_||$_=...para explicar la respuesta vacía? (usando -porque +es un noop en perl)
Ven
No, eso es un error de tiempo de ejecución. Pero incluso si funcionara, empeoraría mi puntaje.
Dennis
Solo hice pruebas minimalistas, así que confiaré en ti. Es justo que el 10% de 21 bytes no sea mucho ..
Ven
2

Pyth, 19 bytes

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

Pruébalo con el compilador Pyth .

Tenga en cuenta que esto solo funcionará correctamente para páginas de códigos que no tengan letras / dígitos que no sean ASCII.

Cómo 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
fuente
2

Factor , 84 * 0.9 = 76.5

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

Se ejecuta en el oyente (repl), define una cita (función anónima) que toma una cadena y genera {0 | 1/2 | 1}.

Definiéndolo como una palabra, son 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 dos expresiones regulares bi-curry@aplica parcialmente la cita [ matches? 1 0 ? ]a cada expresión regular, dejando dos citas al curry en la pila. biaplica cada cita a la cadena de argumento.

Cada una de esas (citas al curry) deja un 1 o un 0, dependiendo de si coinciden. Las primeras coincidencias en los nombres bien formados, la segunda en los nombres que comienzan con guión bajo.

0 = 1 2 ? / El último valor se reemplaza con un 1 si era 0, o con un 2 si era 1. Luego, el primero (1 o 0, válido o no) se divide por el segundo (2 o 1, comienza con un guión bajo o no) .

¡Esto es muuuucho! Cualquier sugerencia para reducir un poco más apreciada ...

¡Y odio las expresiones regulares!

PD.

{ 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 pasan la prueba;)

fede s.
fuente
Solo me pregunto, ¿es realmente necesario el espacio en blanco? No puedo decir con certeza ya que no sé el idioma o no tengo el intérprete.
Mama Fun Roll
@MamaFunRoll sí, ¡no es el mejor lenguaje de golf! En la tradición de Forth, solo los delimitadores son caracteres en blanco.
fede s.
Oh ya veo. Aquí, ten un voto a favor.
Mama Fun Roll
Yay, ty! Ahora para romper el caos con mi comentario en todas partes priv!
fede s.
2

Dyalog APL , 19 bytes - 10% = 17.1

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

{... ... }función anónima donde el argumento correcto está representado por el
⊃⍵primer carácter (da espacio si está vacío)
'_'=1 si es igual a 'barra inferior, 0 de lo contrario se
1+evalúa a 2 si la barra inferior inicial, 1 de lo contrario
⎕NC⍵ nombra la clase ; -1 si el nombre no es válido, 0 si no está definido (pero el nombre es válido), 2-9 si está definido (y, por lo tanto, es válido)

Adán
fuente
1

Mathematica, 93 bytes

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

Sinceramente, no estoy seguro de si esto se puede jugar más.

LegionMammal978
fuente
1

Perl, 34 + 1 = 35 bytes

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

Usa la -pbandera.

Explicación

$_=/^([^\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
un espagueti
fuente
[_a-zA-Z]-> [^\W\d]si perl funciona igual que JavaScript, creo que también \w*
deberías
@Downgoat parece funcionar bien con \w+.
un spaghetto
coincide con falso paraa
Downgoat
@Downgoat Ah, cierto. Veo.
un 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
Max
fuente
0

JavaScript ES7, 37 bytes

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

Pruébalo en línea

Cómo 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 respuesta

andlrc
fuente
0

Ruby, 44 bytes

->(s){s=~/^(_|\d)?\w*$/?$1?$1==?_?0.5:0:1:0}
Flambino
fuente
No necesita parens alrededor de los parámetros para lambdas stabby
No es que Charles
Además, si puede encontrar una manera de eliminar ese ternario adicional, probablemente pueda guardar algunos bytes. Tal /^([a-z_]).../ivez en lugar de/^(_|\d)?.../
No es que Charles
@NotthatCharles D'oh ... tienes razón. Lo echaré un vistazo más de cerca cuando
tenga la
0

Ruby, 57-10% = 51.3 bytes

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

Un enfoque bastante ingenuo

Flambino
fuente
51,3 bytes, eso sí. :)
Xesau
@ Xesau whoops - vergonzoso. Reparado ahora :)
Flambino
Ahorras una gran cantidad de bytes si usas encadenamiento ternario:->(s){s=~/^$|^\d|\W/?0:s=~/^_/?0.5:1}
Value Ink
@KevinLau Verdadero: ya agregué otra respuesta rubí en ese sentido (aunque tampoco es genial)
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 prueba:

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
fuente
Creo que puedes usar STDIN para comer al menos 10 bytes.
Leaky Nun
0

Lua, 68 * .9 = 61,2 bytes

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

Toma argumentos en la línea de comando

Trebuchette
fuente