È un nome di variabile valido?


23

Obbiettivo

Scrivi un programma o una funzione che controlla se un nome di variabile è valido e genera 1 o Truese è valido, 0,5 se è valido ma inizia con un trattino basso (_) e 0 o Falsese non è valido.

Regole

  • Un nome variabile nella maggior parte delle lingue è valido se inizia con un carattere di sottolineatura o una lettera (az, AZ, _) e il resto dei caratteri sono caratteri di sottolineatura, lettere o numeri. (az, AZ, 0-9, _)
  • Uscita 1 o Truese il nome della variabile è valido e 0 o Falsese non valido.
  • Tuttavia, non è buona norma avviare una variabile con un carattere di sottolineatura, quindi restituire 0,5 se inizia con un carattere di sottolineatura e il nome è valido.

Casi test

Ingresso

abcdefghijklmnop

Produzione

1

Ingresso

_test_

Produzione

0.5 (inizia con un trattino basso)

Ingresso

123abc

Produzione

0 (inizia con un numero)

Ingresso

A_b1C_23

Produzione

1

Ingresso

_!

Produzione

0 (non 0,5 perché non è valido)

Ingresso

magical pony1

Produzione

0 (no spazi)

Si applicano scappatoie standard .

Questo è , quindi vince il codice più corto.

Bonus: -10% se il tuo programma / funzione genera 0una stringa vuota ( "").


1
Possiamo produrre verità / falsità / qualcosa?
Calcolatrice

5
Solo notare, in pitone, vengono spesso utilizzati i punteggi. Le classi hanno bisogno di una funzione init , le funzioni di supporto nelle classi a volte iniziano con un trattino basso.
Rɪᴋᴇʀ

1
@EasterlyIrk attenzione al mini-markdown; intendevi __init__; inoltre, no, le classi non hanno bisogno di un __init__ma in genere ne hanno uno
cat

6
Possiamo supporre che l'input sarà non vuoto? (La maggior parte delle risposte attuali sembrano fallire per input vuoto.)
Dennis

1
Il bonus viene arrotondato per eccesso o per difetto? Se è attivo, non vale davvero la pena di avere l'attuale serie di risposte
Blue

Risposte:


13

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

Salvato 4 byte grazie a @ edc65

5,6 byte salvati grazie a @Mateon

s=>!/^\d|\W|^$/.test(s)/-~(s[0]=='_')

3
Sei assolutamente sicuro che questo non sia perl?
Seequ,

8

05AB1E , 25 24 20 19 byte

Codice:

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

Spiegazione:

¬                     # 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 breve, la formula per la stringa sin pseudocodice è:

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

Provalo online!

Utilizza la codifica CP-1252 .


6

PHP (50-10% = 45)

Grazie a Schism per il -2 :)

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

Non competere con le risposte del golflang, ma ho pensato di provarlo comunque.

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

Qualcosa da notare è che in PHP, senza il /umodificatore, \wseleziona solo lettere ASCII. In alcune altre lingue / gusti Regex, questo modello non funzionerà.

Modifica : vedo molte persone che usano \ w e \ d nelle loro risposte, quando usano una lingua che include anche lettere e cifre non ASCII. Questo NON è il puzzle. Si sbagliano. (Non posso ancora sottovalutare / commentare, mi dispiace doverlo dire in questo modo.)


Benvenuti in Puzzle di programmazione e scambio di code golf stack. Questa è un'ottima risposta; spesso le sfide del code-golf sono sia nelle lingue che tra di loro. Ti sto dando un +1 per questa soluzione! Molto bene.
wizzwizz4,

1
Puoi radere due personaggi con [a-z].../i.
Scism

@Schism Grazie. Non so come sono riuscito a dimenticarlo, di solito sono bravo in questo tipo di puzzle regex :)
Xesau

1
Informazioni sulla modifica: puoi essere più specifico - quali lingue? In javascript \dè esattamente lo stesso di [0-9]. \wè esattamente lo stesso di [A-Za-z0-9_] developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
edc65

La tabella codici utilizzata dalla lingua è irrilevante; fintanto che il regex gestisce correttamente ASCII, è valido. Tutte le risposte attuali basate su regex funzionano, per quanto ne so. Non stai cercando di abbinare un nome di variabile nella tua lingua; piuttosto, stai cercando di abbinare un nome di variabile in base alle regole della sfida.
Mego

5

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

Entrambe le versioni si qualificano per il bonus, poiché gestiscono correttamente input vuoti (output 0)

Ho dovuto correggere un bug causato da una delle funzionalità regex di .NET, che considera alcuni (leggi tanti) caratteri Unicode come caratteri "word". Fortunatamente, questo mi è costato solo un singolo byte in entrambe le versioni. Si trattava solo di aggiungere un modificatore per rendere il comportamento di regex matching conforme agli standard ECMAScript. Maggiori informazioni qui .

Nuova versione da 28 29 byte, realizzata da @ MartinBüttner. Grazie!

^ _
$ _¶_
Mme` ^ (?! \ D) \ w + $
2
0.5

Spiegazione

Innanzitutto, controlliamo se l'input inizia con un trattino basso. In tal caso, l'input viene duplicato, con una nuova riga in mezzo. Ad esempio: _test_-> _test_\n_test_, dove si \ntrova la nuova riga. Poi cerchiamo di abbinare qualsiasi cosa, che non inizia con un numero, ma è seguito da un numero qualsiasi di caratteri "parola" ( a-z, A-Z, cifre, e di sottolineatura) su ogni linea . Si noti che se l'input è iniziato con un trattino basso ed è stato sostituito da due righe, questo corrisponderà a entrambe le righe. Quindi controlliamo se abbiamo avuto 2 partite e le sostituiamo con 0.5. La riga vuota o non valida genererà sempre 0 corrispondenze e i nomi di variabili validi restituiranno sempre 1 corrispondenze.


La mia versione da 30 a 31 byte

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

Spiegazione

Prima di tutto, controlliamo se inizia in ingresso con una cifra o contiene un carattere non-parola (qualcosa di diverso a-z, A-Z, cifre e underscore). Se lo fa, viene scartato, perché non è valido. Quindi controlliamo se inizia con un trattino basso. In tal caso, viene sostituito con 0.5. Poi controlliamo se inizia con un carattere non numerico (a questo punto il primo carattere è o 0, a-zo A-Z. Solo a-ze A-Zsono non cifre, ovviamente). In tal caso, viene sostituito con a 1. Quindi controlliamo la stringa vuota e la sostituiamo con 0.

Provalo online!
Provalo online! Vecchia versione


Aspetta aspetta aspetta. Nella ^\D.*fase può iniziare con uno 0? Quello è strano.
CalculatorFeline

@CatsAreFluffy Può, se è iniziato con a _ed è stato sostituito con 0.5. Quindi inizia con un 0.
daavko

Ciò fornisce erroneamente un 1 per l'input Ψ.
AdmBorkBork,

@TimmyD Interessante. Non capisco perché lo faccia. Il controllo rapido indica che \wcorrisponde a caratteri non ASCII, cosa che non dovrebbe fare (ho provato a darlo ƜƝƞƟƠe ᎳᎴᎵᎶᎷᎸᎹcome input). Ci penserò più avanti. La possibile soluzione sembra sostituirsi \wa [a-zA-Z\d_].
Daavko,

3

MATL , 27 byte

1)95=2/8M3Y2m+G7M95h4Y2hmA*

Funziona con la versione corrente (15.0.0) della lingua.

L'input è una stringa con virgolette singole.

Provalo online!

Spiegazione

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

3

Pyke , 21 byte

(non competitiva, sottrazione di stringhe aggiunta, varie costanti di stringa)

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

Spiegazione:

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

3

Python 3, 36 byte

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

Il codice è lungo 40 byte e si qualifica per il bonus del -10% .

Nota che funzionerà correttamente solo per le pagine di codice che non hanno lettere / cifre non ASCII.



2

Gogh , 29 byte

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

Esegui utilizzando:

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

Spiegazione

                   “ 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                              ”

2

Perl, 21 byte

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

Il punteggio include +1 byte per lo -pswitch. Provalo su Ideone .


potresti avere, dire -$_||$_=...per spiegare la risposta vuota? (usando -because +è un noop in perl)
Ven

No, questo è un errore di runtime. Ma anche se funzionasse, peggiorerebbe il mio punteggio.
Dennis,

Ho fatto solo test minimalisti, quindi mi fiderò di te. È giusto che il 10% di 21 byte non sia molto ..
Ven

2

Pyth, 19 byte

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

Provalo con il compilatore Pyth .

Nota che funzionerà correttamente solo per le pagine di codice che non hanno lettere / cifre non ASCII.

Come funziona

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.

2

Fattore , 84 * 0.9 = 76.5

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

Viene eseguito sul listener (sostituisci), definisce un preventivo (funzione anonima) che accetta una stringa e genera {0 | 1/2 | 1}.

Definendolo come una parola è 97 caratteri:

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

Come funziona:

R/ [_a-zA-Z]\w*/ R/ _.*/definisce due espressioni regolari. bi-curry@applica parzialmente la quotazione [ matches? 1 0 ? ]a ogni regex, lasciando in pila due citazioni al curry. biapplica ogni citazione alla stringa dell'argomento.

Ognuno di questi (citazioni al curry) lascia un 1 o uno 0, a seconda che corrispondano. Il primo corrisponde ai nomi ben formati, il secondo ai nomi che iniziano con il trattino basso.

0 = 1 2 ? / L'ultimo valore viene sostituito con 1 se era 0 o con 2 se era 1. Quindi il primo (1 o 0, valido o no) viene diviso per il secondo (2 o 1, inizia con trattino basso o meno) .

Questo è incredibile! Qualche suggerimento per ridursi un po 'più apprezzato ...

E odio 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

tutti i test pass;)


Mi chiedo solo, lo spazio bianco è veramente necessario? Non posso dirlo con certezza poiché non conosco la lingua o non ho l'interprete.
Mama Fun Roll,

@MamaFunRoll sì, non la migliore lingua per giocare a golf! Nella tradizione Forth, solo i delimitatori sono caratteri di spazi bianchi.
fede s.

Oh, capisco. Ecco un voto positivo.
Mama Fun Roll,

Yay, ty! Ora per rompere il caos con il mio commento, ovunque priv!
fede s.

2

Dyalog APL , 19 byte - 10% = 17.1

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

{... ... }funzione anonima in cui l'argomento giusto è rappresentato dal
⊃⍵primo carattere (dà spazio se vuoto)
'_'=1 se uguale a 'underbar, 0 altrimenti
1+valuta a 2 se underbar iniziale, 1 altrimenti
⎕NC⍵ nome class ; -1 se nome non valido, 0 se non definito (ma nome valido), 2-9 se definito (e quindi valido)


1

Mathematica, 93 byte

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

Onestamente non sono sicuro che questo possa essere ulteriormente approfondito.


1

Perl, 34 + 1 = 35 byte

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

Usa la -pbandiera.

Spiegazione

$_=/^([^\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]se perl funziona come JavaScript, penso che dovresti farlo anche \w*
tu

@Downgoat Sembra funzionare bene \w+.
uno spaghetto il

corrisponde falso pera
Downgoat

@Downgoat Ah, giusto. Vedo.
uno spaghetto il

1

Python, 84-10% = 76 byte

lambda x:[0,[[.5,1][x[0]>'z'],0][x[0]<'A']][x.replace('_','a').isalnum()]if x else 0

0

JavaScript ES7, 37 byte

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

Provalo online

Come funziona:

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


0

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

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

@NotthatCharles D'oh... you're right. I'll give it a closer look when I a chance
Flambino

0

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

@Xesau whoops - embarassing. Fixed now :)
Flambino

You save a huge amount of bytes if you use ternary chaining: ->(s){s=~/^$|^\d|\W/?0:s=~/^_/?0.5:1}
Value Ink

@KevinLau True - I added another ruby answer in that vein already (though it's not great either)
Flambino

0

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

0

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.