Это допустимое имя переменной?


23

Задача

Напишите программу или функцию, которая проверяет, является ли имя переменной допустимым, и выводит 1 или, Trueесли она действительна, 0,5, если она действительна, но начинается с подчеркивания (_), и 0, или Falseесли она недействительна.

правила

  • Имя переменной в большинстве языков допустимо, если оно начинается с подчеркивания или буквы (az, AZ, _), а остальные символы являются либо подчеркиванием, буквами или цифрами. (az, AZ, 0-9, _)
  • Выведите 1 или, Trueесли имя переменной допустимо, и 0 или, Falseесли не допустимо.
  • Однако не рекомендуется начинать переменную со знака подчеркивания, поэтому возвращайте значение 0,5, если оно начинается со знака подчеркивания и имя является допустимым.

Тестовые случаи

вход

abcdefghijklmnop

Выход

1

вход

_test_

Выход

0.5 (начинается с подчеркивания)

вход

123abc

Выход

0 (начинается с номера)

вход

A_b1C_23

Выход

1

вход

_!

Выход

0 (не 0.5, потому что это не верно)

вход

magical pony1

Выход

0 (без пробелов)

Применяются стандартные лазейки .

Это , поэтому выигрывает самый короткий код.

Бонус: -10%, если ваша программа / функция выдает 0пустую строку ( "").


1
Можем ли мы вывести правду / ложь / что-нибудь?
CalculatorFeline

5
Стоит отметить, что в питоне часто используются заниженные оценки. Классы нуждаются в функции инициализации , вспомогательные функции в классах иногда начинаются с подчеркивания.
R

1
@EasterlyIrk остерегайтесь мини-уценки; ты имел в виду __init__; Кроме того, нет, классы не нужны , __init__но, как правило, есть
кошка

6
Можем ли мы предположить, что вход будет не пустым? (Большинство текущих ответов, кажется, не для пустого ввода.)
Деннис

1
Этот бонус округляется вверх или вниз? Если это так, то на текущий набор ответов это не имеет смысла
Blue

Ответы:


13

JavaScript (ES6), 37 - 10% = 33,3 байта

Сохранено 4 байта благодаря @ edc65

Сохранено 5,6 байта благодаря @Mateon

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

3
Вы абсолютно уверены, что это не Perl?
Seequ

8

05AB1E , 25 24 20 19 байтов

Код:

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

Объяснение:

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

Короче говоря, формула для строки sв псевдокоде:

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

Попробуйте онлайн!

Использует кодировку CP-1252 .


6

PHP (50 - 10% = 45)

Спасибо Schism за -2 :)

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

Не конкурировать с ответами на гольф-поле, но я все равно решил попробовать.

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

Следует отметить, что в PHP без /uмодификатора \wвыбираются только буквы ASCII. В некоторых других языках / вариантах Regex этот шаблон не будет работать.

Изменить : я вижу много людей, использующих \ w и \ d в своих ответах, когда они используют язык, который также включает не-ASCII буквы и цифры. Это НЕ загадка. Они ошибаются. (Невозможно понизить / прокомментировать, извините за необходимость сказать это таким образом.)


Добро пожаловать в Программирование Пазлов и Code Golf Stack Exchange. Это отличный ответ; часто проблемы кода-гольфа возникают как внутри языков, так и между ними. Я даю вам +1 за это решение! Отлично сработано.
wizzwizz4

1
Вы можете сбрить двух персонажей с помощью [a-z].../i.
Раскол

@ Раскол Спасибо. Не знаю, как мне удалось забыть об этом, обычно я хорошо
разбираюсь

1
О вашем редактировании: можете ли вы быть более конкретным - на каких языках? В javascript \dэто точно так же, как [0-9]. \wявляется exactlly же , как [A-Za-z0-9_] developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/...
edc65

Кодовая страница, которую использует язык, не имеет значения; до тех пор, пока регулярное выражение правильно обрабатывает ASCII, оно действительно. Насколько мне известно, все текущие ответы на основе регулярных выражений работают. Вы не пытаетесь сопоставить имя переменной на вашем языке; скорее вы пытаетесь сопоставить имя переменной на основе правил в задаче.
Мего

5

Сетчатка, 30 - 10% = 27 28 - 10% = 25,2 29 - 10% = 26,1 байта

Обе версии имеют право на бонус, так как они правильно обрабатывают пустой ввод (выходные данные 0)

Мне пришлось исправить ошибку, вызванную одной из функций регулярных выражений .NET, которая рассматривает некоторые (прочитайте столько же) символов Юникода как символы «слова». К счастью, это стоило мне только одного байта в обеих версиях. Все сводилось только к добавлению модификатора, чтобы поведение соответствия регулярных выражений соответствовало стандартам ECMAScript. Подробнее об этом здесь .

Новый 28 29 байт версия, сделанная @ MartinBüttner. Благодарность!

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

объяснение

Сначала мы проверяем, начинается ли ввод с подчеркивания. Если это так, ввод дублируется, с новой строкой между ними. Например: _test_-> _test_\n_test_, где \nнаходится новая строка. Тогда мы пытаемся соответствовать что - нибудь, что не начинается с числа, но следует любое количество «слов» символов ( a-z, A-Zцифры и символ подчеркивания) в каждой строке . Обратите внимание, что если ввод начинался с подчеркивания и был заменен на две строки, это будет соответствовать обеим строкам. Затем мы проверяем, было ли у нас 2 совпадения, и заменяем их на 0.5. Пустая или неверная строка всегда будет давать 0 совпадений, а допустимые имена переменных всегда будут давать 1 совпадение.


Моя собственная 30 -байтовая версия

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

объяснение

Прежде всего, мы проверяем , если вход начинается с цифры или содержит не слово символ (ничего, кроме a-z, A-Z, цифры и подчеркивание). Если это так, он отбрасывается, потому что он недействителен. Затем мы проверяем, начинается ли это с подчеркивания. Если это так, он заменяется на 0.5. Затем мы проверяем , если она начинается с нецифры характера (в этот момент первый символ является либо 0, a-zили A-Z. Только a-zи A-Zне имели цифры, очевидно). Если это так, он заменяется на 1. Затем мы проверяем пустую строку и заменяем ее на 0.

Попробуйте онлайн!
Попробуйте онлайн! Старая версия


Waitwaitwait. На ^\D.*этапе это может начинаться с 0? Это странно.
CalculatorFeline

@CatsAreFluffy Может, если он начинался с _и был заменен на 0.5. Затем начинается с 0.
Даавко

Это неправильно дает 1 для ввода Ψ.
AdmBorkBork

@TimmyD Интересно. Я не понимаю, почему это так. Быстрая проверка показывает, что \wэто совпадает с не-ASCII символами, что не должно делать (я пытался дать это ƜƝƞƟƠи в ᎳᎴᎵᎶᎷᎸᎹкачестве ввода). Я посмотрю на это позже. Возможное решение кажется заменой \wна [a-zA-Z\d_].
Даавко

3

MATL , 27 байт

1)95=2/8M3Y2m+G7M95h4Y2hmA*

Это работает в текущей версии (15.0.0) языка.

Ввод - это строка с одинарными кавычками.

Попробуйте онлайн!

объяснение

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

Пайк , 21 байт

(неконкуренция, добавленное вычитание строки, различные строковые константы)

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

Объяснение:

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 байт

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

Код длиной 40 байт соответствует бонусу -10% .

Обратите внимание, что это будет работать правильно только для кодовых страниц, которые не имеют букв / цифр, отличных от ASCII.



2

Гог , 29 байт

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

Запустите с помощью:

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

объяснение

                   “ 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 байт

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

Оценка включает +1 байт для -pпереключения. Попробуйте это на Ideone .


не могли бы вы, скажем, ответить -$_||$_=...за пустой ответ? (использование -потому +, что в Perl noop)
Ven

Нет, это ошибка во время выполнения. Но даже если бы это сработало, это ухудшило бы мой счет.
Денис

Я только сделал минималистичные тесты, поэтому я буду доверять вам. Справедливо, что 10% из 21 байта не много ..
Ven

2

Pyth, 19 байт

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

Попробуйте это с Pyth Compiler .

Обратите внимание, что это будет работать правильно только для кодовых страниц, которые не имеют букв / цифр, отличных от ASCII.

Как это работает

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

Коэффициент , 84 * 0,9 = 76,5

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

Запускает прослушиватель (repl), определяет цитату (анонимная функция), которая принимает строку и выводит {0 | 1/2 | 1}

Определяя это как слово, это 97 символов:

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

Как это работает:

R/ [_a-zA-Z]\w*/ R/ _.*/определяет два регулярных выражения. bi-curry@частично применяет цитату [ matches? 1 0 ? ]к каждому регулярному выражению, оставляя две каррированные цитаты в стеке. biприменяет каждую цитату к строке аргумента.

Каждая из этих (каррированных цитат) оставляет либо 1, либо 0, в зависимости от того, соответствуют ли они. Первое соответствует хорошо сформированным именам, второе - именам, начинающимся с подчеркивания.

0 = 1 2 ? / Последнее значение заменяется на 1, если оно было 0, или на 2, если оно было 1. Тогда первое (1 или 0, действительное или нет) делится на второе (2 или 1, начинается с подчеркивания или нет) ,

Это очень долго! Любые указатели на сокращение немного более ценится ...

И я ненавижу регулярные выражения!

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

все испытания проходят;)


Просто интересно, действительно ли пробелы необходимы? Я не могу сказать наверняка, так как я не знаю язык или не имею переводчика.
Mama Fun Roll

@MamaFunRoll да, не самый лучший язык для игры в гольф! В традиции Forth, только разделитель - это пробельные символы.
Федерация с.

А ну понятно. Здесь есть голосование.
Mama Fun Roll

Ууу ты! Теперь, чтобы сломать хаос с моим комментарием - везде прив!
Федерация с.

2

Dyalog APL , 19 байт - 10% = 17,1

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

{... ... }анонимную функцию , где право аргумент , представленный
⊃⍵первым символом (дает пространство , если пусто)
'_'=1 , если значение «подчеркивания, 0 в противном случае имеет
1+значение 2 , если начальное подчеркивание, 1 в противном случае
⎕NC⍵ имя класса ; -1 если недопустимое имя, 0 если не определено (но действительное имя), 2-9, если определено (и, следовательно, допустимо)


1

Mathematica, 93 байта

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

Я, честно говоря, не уверен, что это может быть дальше в гольфе.


1

Perl, 34 + 1 = 35 байт

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

Использует -pфлаг.

объяснение

$_=/^([^\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]Если Perl работает так же, как JavaScript, я думаю, вам также придется это делать\w*
Downgoat

@Downgoat Кажется, хорошо работать с \w+.
спагетто

соответствует false дляa
Downgoat

@ Downgoat Ах, да. Понимаю.
спагетто


0

JavaScript ES7, 37 байт

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

Попробуйте онлайн

Как это работает:

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

Порт @ Денниса Perl ответ


0

Рубин, 44 байта

->(s){s=~/^(_|\d)?\w*$/?$1?$1==?_?0.5:0:1:0}

Тебе не нужны парены вокруг параметров для лямбд
не то, что Чарльз

Также, если вы можете найти способ отбросить эту лишнюю троицу, вы, вероятно, можете сэкономить несколько байтов. Может быть, /^([a-z_]).../iвместо/^(_|\d)?.../
не то, что Чарльз

@ NotthatCharles D'Oh ... ты прав. Я расскажу об этом поближе, когда у меня будет шанс
Фламбино

0

Рубин, 57 - 10% = 51,3 байта

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

Довольно наивный подход


Заметьте, 51,3 байта. :)
Xesau

@ Xesau упс - неловко. Исправлено сейчас :)
Flambino

Вы сохраняете огромное количество байтов, если используете тройную цепочку:->(s){s=~/^$|^\d|\W/?0:s=~/^_/?0.5:1}
Value Ink

@KevinLau Правда - я уже добавил еще один рубиновый ответ в этом ключе (хотя и не очень)
Flambino

0

Луа, 82 - 10% = 73,8

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

Тестовые случаи:

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

Я думаю, что вы можете использовать STDIN, чтобы съесть как минимум 10 байт.
Утренняя монахиня

0

Lua, 68 * .9 = 61,2 байта

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

Принимает аргументы в командной строке

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.