Преобразование «0xUsernames»


25

0xUsernames

Есть так много людей, использующих службу обмена сообщениями, что им не хватает места для хранения всех имен пользователей! Чтобы исправить это, они начнут хранить имена пользователей как шестнадцатеричные, где это возможно.

Если имя пользователя состоит только из символов 0123456789ABCDEF(без учета регистра), оно может быть преобразовано в шестнадцатеричное и сохранено как целое число. Например, имя пользователя ba5eba11может быть интерпретировано как 0xBA5EBA11шестнадцатеричное целое число.

Но как насчет 05AB1E? Это ведущий ноль, который будет потерян. Таким образом, всякий раз, когда мы конвертируем имя пользователя, мы обязательно ставим перед ним 1перед чтением его как целое число.


Соревнование

Ваша задача - написать программу или функцию, которая, учитывая непустое имя пользователя в виде строки, «гекса-сжимает» имя пользователя:

  • Если его можно интерпретировать как шестнадцатеричное целое число, добавьте 1, интерпретируйте как шестнадцатеричное и затем выведите результат как основание 10.
  • В противном случае просто верните строку без изменений.

Это , поэтому выигрывает самое короткое решение (в байтах)! Встроенные функции преобразования базы разрешены.


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

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

Как и имена пользователей в большинстве систем обмена сообщениями, входные строки будут содержать только буквенно-цифровые символы и подчеркивания.

Помните, что вам всегда нужно добавить ведущий 1перед преобразованием!

"ba5eba11" -> 7421737489
"05AB1E"   -> 17148702
"dec0de"   -> 31375582
"Beef"     -> 114415    
"da7aba5e" -> 7960443486
"500"      -> 5376

"DENNIS" -> "DENNIS"
"Garth"  -> "Garth"
"A_B_C"  -> "A_B_C"
"0x000"  -> "0x000"

Для справки, вот реализация Python 3, которую я использовал для тестовых случаев (ungolfed):

import re

def convert_name(name):
    if re.fullmatch('^[0-9A-Fa-f]+$', name):
        return int('1' + name.upper(), base = 16)
    else:
        return name

Ах, не видел этого. Кроме того, что если некоторые из более крупных тестовых случаев приводят к числам, выходящим за пределы самого большого целочисленного типа нашего языка?
Дверная ручка

2
@ Doorknob хороший улов. Я скажу, что полученное целое число никогда не будет больше, чем стандартный целочисленный тип вашего языка. (пожалуйста, не злоупотребляйте этим и используйте язык с 1-битными целыми числами)
FlipTack

Можно ли считать, что ввод вводится только заглавными буквами?
Адам

@ Извините, но ваша программа не должна учитывать регистр символов (см.
Контрольные

Как и Unary, за исключением того, что он кодирует имена пользователей вместо BF
MilkyWay90

Ответы:


27

05AB1E , 4 байта

D1ìH

объяснение

D    Duplicate input
 1ì  Prepend 1
   H Interpret as hexadecimal and implicitly display the value in base 10

Если на входе есть недопустимые шестнадцатеричные символы, Hничего не вставляется, поэтому последним значением в стеке будет дублированный ввод, поэтому программа печатает свой ввод в случае неверного ввода.

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


9
Ирония здесь довольно сильна. 05AB1Eявляется действительным именем пользователя.
devRicher

1
Это верно, однако имя было выбрано в виде шестнадцатеричного числа. Следовательно это действительно :)
Osable

Интересно, почему ты обманываешь. Попытка придумать способ использовать $ вместо этого ...
Волшебная Осьминога Урна

16

JavaScript (ES6), 15 байт

s=>'0x1'+s-0||s

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

'0x1'+sпреобразует входные данные в буквальную шестнадцатеричной строку с префиксом 1, например 0x105ab1e. Затем -0приводит результат к числу. JavaScript видит 0xв начале и неявно пытается конвертировать из шестнадцатеричной; если sсодержит какие-либо не шестнадцатеричные символы, это возвращает NaN. Так как это неверно (и вывод 0никогда не может быть дан из-за предварительно добавленного 1), мы можем использовать ||sдля возврата, sесли преобразование в шестнадцатеричный код не удалось.

Тестовый фрагмент

f = s=>'0x1'+s-0||s

for(i of [
  "ba5eba11", "05AB1E", "dec0de", "Beef", "da7aba5e", "500",
  "DENNIS", "Garth", "A_B_C", "0x000"
]) console.log(i + ":", f(i));


2
Очень хорошее решение!
Grax32

Неявное литье действительно прекрасно ...: ')
Downgoat

10

Python 2 , 44 байта

Принимает ввод в виде строки в кавычках. -2 байта благодаря Роду!

a=input()
try:exec'a=0x1'+a
except:1
print a

Поскольку мы гарантируем, что входные данные будут содержать только буквенно-цифровые символы и символы подчеркивания, нет никакого способа создать допустимый Python после того, 0x1как иметь шестнадцатеричную строку. Если на входе есть что-то еще, ошибка игнорируется и печатается так, как было изначально.

Казалось, я не могу сделать регулярное выражение более коротким, чем try/except. На самом деле, регулярное выражение оказалось ужасно многословным:

import re
lambda n:re.match('^[0-9A-F]+$',n,2)and int('1'+n,16)or n

Вы также можете заменить a=int('1'+a,16)на exec'a=0x1'+a(вероятно, необходимо проверить)
Род

Вы знаете, у нас будет тот же самый точный ответ, если я продолжу играть в гольф, верно?
Энтони Фам

Не работает для имен пользователей, которые были бы допустимыми Python в этом контексте, например "+input()".
heinrich5991

терпит неудачу для "abc" (обратите внимание на пробел в конце) (int разрешает пробел в начале и в конце)
Siphor

Я не знаю точно, как это для Python 2, но я думаю, что вы можете снять скобки ()вinput()
RudolfJelin


7

Perl, 27 байт

-1 байт благодаря @ardnew .

26 байт кода + -pфлаг.

$_=hex"1$_"if!/[^0-9a-f]/i

Предоставить ввод без окончательного перевода строки. С echo -n, например:

echo -n 05AB1E | perl -pe '$_=hex"1$_"if!/[^0-9a-f]/i'

Пояснение
Это довольно просто: /[^0-9a-f]/iверно, если ввод содержит символ, отличный от тех, которые разрешены внутри шестнадцатеричных чисел. Если $_значение равно false (содержит входные данные), оно устанавливается на преобразованное значение (преобразование выполняется встроенным hex).
И $_неявно печатается благодаря -pфлажку.


Вы можете побрить байт, избегая троичной операции$_=hex"1$_"if!/[^0-9a-f]/i
ardnew

@ardnew Хм, теперь, когда ты это сказал, этот троичный был довольно ужасен ... В любом случае, спасибо!
Дада


3

Пакет, 33 байта

@(cmd/cset/a0x1%1 2>nul)||echo %1

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

В качестве аргумента передается строка, к ней добавляется 1, а строка неявно преобразуется в десятичную и печатается. Если строка не является допустимой шестнадцатеричной, она просто отображается.

Следует отметить, что, поскольку пакетная математика использует 32-разрядные целые числа со знаком, наибольшее допустимое имя пользователя FFFFFFF.

cmd /c принимает следующую команду, запускает ее в новом терминале и завершает работу.

set /a выполняет математику и неявно отображает результат в десятичном виде, если он не сохранен в переменной.

0x1%1 указывает set на добавление 1 к первому аргументу (это легко, поскольку все пакетные переменные являются строками) и указывает, что строка должна рассматриваться как шестнадцатеричная.

2>nul заставляет замолчать любые ошибки, возникающие из-за неправильного шестнадцатеричного числа

||является логическим ИЛИ и выполняет команду справа, если команда слева не удалась. Скобки делают все до этой точки одной командой.

echo %1 просто отображает первый аргумент.


3

Common Lisp, 71

(lambda(n)(or(ignore-errors(parse-integer(format()"1~A"n):radix 16))n))

тесты

Определить функцию

CL-USER> (lambda(n)(or(ignore-errors(parse-integer(format()"1~A"n):radix 16))n))
#<FUNCTION (LAMBDA (N)) {10041D213B}>

Укажите список ожидаемых входных данных, как указано в вопросе:

CL-USER> '("ba5eba11" -> 7421737489
"05AB1E"   -> 17148702
"dec0de"   -> 31375582
"Beef"     -> 114415    
"da7aba5e" -> 7960443486
"500"      -> 5376

"DENNIS" -> "DENNIS"
"Garth"  -> "Garth"
"A_B_C"  -> "A_B_C"
"0x000"  -> "0x000")
("ba5eba11" -> 7421737489 "05AB1E" -> 17148702 "dec0de" -> 31375582 "Beef" ->
 114415 "da7aba5e" -> 7960443486 "500" -> 5376 "DENNIS" -> "DENNIS" "Garth" ->
 "Garth" "A_B_C" -> "A_B_C" "0x000" -> "0x000")

Разбор и сбор результатов

CL-USER> (loop for (in _ out) on * by #'cdddr
               collect (list in out (funcall ** in)))
(("ba5eba11" 7421737489 7421737489) ("05AB1E" 17148702 17148702)
 ("dec0de" 31375582 31375582) ("Beef" 114415 114415)
 ("da7aba5e" 7960443486 7960443486) ("500" 5376 5376)
 ("DENNIS" "DENNIS" "DENNIS") ("Garth" "Garth" "Garth")
 ("A_B_C" "A_B_C" "A_B_C") ("0x000" "0x000" "0x000"))

Убедитесь, что ожидаемые результаты соответствуют фактическим:

CL-USER> (every (lambda (x) (equalp (second x) (third x))) *)
T

2

C 108 байтов

i;f(char*s){char*S=malloc(strlen(s)+2);*S=49;strcpy(S+1,s);sscanf(S,"%x%c",&i,&i)<2?printf("%d",i):puts(s);}

Это функция, которая принимает строку в качестве аргумента и печатает результат в STDOUT.

i;                           // declare i as an int
f(char*s){
char*S=malloc(strlen(s)+2);  // allocate space for a new string with 1 more char
*S=49;                       // set the first char to '1' (ASCII 49)
strcpy(S+1,s);               // copy the original string to the remainder
sscanf(S,"%x%c",&i,&i)       // scan a hex integer followed by any char
<2?                          // if less than 2 items were scanned (i.e. the hex
                             // integer made up the entire string),
printf("%d",i)               // output the hex integer
:puts(s);}                   // otherwise, output the original string

Хорошее использование неявного int:)
FlipTack

2

JavaScript: 46 41 байт

s=>/[^\dA-F]/i.test(s)?s:parseInt(1+s,16)

/[^0-9a-f]/i
Регулярное

Я сохранил 1 байт, заменив 0-9на \d3 байта, добавив флаг без учета регистра (спасибо @GilZ) и еще 2 байта, удалив F=, что не нужно. Спасибо за предложение.
Лука

2

PHP, 42 байта

hex2bin () возвращает false, если ввод не является допустимой шестнадцатеричной строкой. Это короче, чем использование регулярных выражений для поиска не шестнадцатеричных цифр, но нам нужен оператор @, потому что он не молчит, когда он терпит неудачу.

<?=@hex2bin($s=$argv[1])?hexdec("1$s"):$s;

hex2binне подходит для строк с неравной длиной. Тем не менее на два байта короче, чем при использовании preg_match: <?=@hex2bin($s=$argv[1])|@hex2bin($s.a)?hexdec("1$s"):$s;для 57 байтов.
Тит

2

bash, 46 35 31 байт

(echo $[0x1$1])2> >(:)||echo $1

Сохраните как скрипт и передайте имя пользователя в качестве аргумента.


1

Python 2 - 63, 52, 5046 байт

n=input()
try:n=int("1"+n,16)
except:1
print n

При этом используется Python, int()который преобразует любую строку с соответствующим основанием в базу 10. В этом случае строка является номером 1, присоединенным к входу. Если ввод недопустим (содержит символы, отличные от 0123456789ABCDEF(без учета регистра), он возвращает ValueError:

n = input()                   # Get input (with quotes)
try:                          # Trying conversion to base 10
    n = int("1"+n,16)        
except:                       # If invalid string for base 36,
    1                         # do nothing to n
print n                       # Print result

Попробуй это здесь!

Спасибо @FlipTack за сохранение 15 байт!


Что если строка не начинается с нуля? Вы должны добавлять только один слева от строки, если она начинается с нуля.
0WJYxW9FMN

@FlipTack Ой, глупый я.
0WJYxW9FMN

1

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

p gets=~/^[a-f\d]+\s$/i?('1'+$&).to_i(16):$_

Я мог бы удалить 3 байта, изменив putsна p, но я чувствую, что вывод будет считаться неправильным, так как в конце он имеет новую строку.

Редактировать: изменено, putsпоскольку pв конце обычно принимаются завершающие символы новой строки, спасибо @Mego.


Конечные переводы строк на STDOUT обычно считаются приемлемыми.
Mego


1

Дьялог АПЛ , 37 байт

Не использует встроенную проверку или преобразование hex-dec. Требуется ⎕IO←0по умолчанию во многих системах.

{∧/(u1(819⌶)⍵)∊d←⎕D,6↑⎕A:161,du⋄⍵}

Ungolfed:

{
    d  D , 6  A
    u1 (819⌶) 
    ∧/ u  d: 16  1 , d  u
    
}

d ← ⎕D , 6 ↑ ⎕Ad получает D igits следуют первые 6 элементов A lphabet

u ← 1 (819⌶) ⍵вы получаете заглавные (819 ≈ "большой") аргумент

∧/ u ∊ d: если все элементы u являются членами d , то:
16 ⊥ 1 , d ⍳ u найдите индексы u в d , добавьте 1 и оцените как основание 16

else: вернуть (неизмененный) аргумент

TryAPL онлайн:

  1. Установите ⎕IOв ноль, определите замену для (запрещено в TryAPL по соображениям безопасности) и установите ⎕PP( P rint P recision) значение 10 для больших результатов.

  2. Попробуйте все тестовые случаи


1

REXX, 49 48 байтов

signal on syntax
pull a
a=x2d(1||a)
syntax:
say a

signal on syntaxГоворит переводчику , чтобы перейти к метке syntaxвсякий раз , когда возникает ошибка синтаксиса. Программа пытается переназначить aпреобразованную версию с шестнадцатеричным в десятичное с начальным 1, но переходит на syntaxметку, если это не удается. Если преобразование проходит, оно просто игнорирует метку и выводит переназначенную переменную.


2
Не могли бы вы объяснить свой код, пожалуйста
Энтони Фам

0

PowerShell , 35 байт

param($v)(($h="0x1$v"|iex),$v)[!$h]

Попробуйте онлайн! или Запустите все тестовые случаи!

объяснение

  1. Принять параметр ( $v)
  2. Создайте двухэлементный массив, где первый элемент ( 0) является результатом строки, содержащей 0x1$vpiped into Invoke-Expression( iex), при этом одновременно присваивая это значение $h. Если преобразование не удастся, $hостанется $null.
  3. Второй элемент массива - это исходный параметр.
  4. Индекс в массив с логическим -notзначением $h. Все, что $hесть, будет неявно преобразовано в [bool]( $nullв случае неправильного преобразования станет $false, положительное целое число в случае успешного преобразования станет $true) перед отрицанием, которое затем неявно преобразуется [int]в индексатор массива []( $trueбудет 1, $falseбудет 0), в результате чего первый элемент массива (результат преобразования) был выбран, если преобразование было успешным, и второй элемент, выбранный, если преобразование было неудачным.

0

Скала, 40 байт

s=>try{BigInt("1"+s,16)}catch{case e=>s}

Использование:

val f:(String=>Any)=s=>try{BigInt("1"+s,16)}catch{case e=>s}
f("ba5eba11") //returns 7421737489

Объяснение:

s=>                //define a anonymous function with a parameter called s
  try {              //try...
    BigInt("1"+s,16)   //to contruct a BigInt from "1" prepended to the number, parsing it as base 16
  } catch {          //if the constructor throws an exception
    case e =>          //in case of an execption which we'll call e
      s                  //return s
  }

0

C #, 58 байт

u=>{try{u=Convert.ToInt64("1"+u,16)+"";}catch{}return u;};

Разоблачен тестовыми примерами:

using System;
class Class
{
    public static void Main()
    {
        Func<string, string> convert = 
            u=>
            {
                try
                {
                    u = Convert.ToInt64("1" + u, 16) //Prepends "1" and tries to convert the string to and integer using base 16.
                        + ""; //Appending an empty string converts the integer to a string. Shorter than calling .ToString()
                }
                catch { } //If the conversion fails catch the exception and discard it.
                return u; //Return the result, or the unmodified input if the conversion failed.
            };

        Console.WriteLine(convert("ba5eba11"));
        Console.WriteLine(convert("05AB1E"));
        Console.WriteLine(convert("dec0de"));
        Console.WriteLine(convert("Beef"));
        Console.WriteLine(convert("da7aba5e"));
        Console.WriteLine(convert("500"));
        Console.WriteLine(convert("DENNIS"));
        Console.WriteLine(convert("Garth"));
        Console.WriteLine(convert("A_B_C"));
        Console.WriteLine(convert("0x000"));
        Console.Read();
    }
}

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


0

Дротик, 51 байт

(s)=>int.parse('1$s',radix:16,onError:(_)=>null)??s

Попробуй здесь

Большая часть накладных расходов связана с именованными параметрами ... О, хорошо!

По крайней мере, Dart позволяет вам динамически печататься, если вы хотите: D

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