Mengonversi “0xUsernames”


25

0x Nama pengguna

Ada begitu banyak orang yang menggunakan layanan olahpesan sehingga mereka kehabisan ruang untuk menyimpan semua nama pengguna! Untuk memperbaikinya, mereka akan mulai menyimpan nama pengguna sebagai heksadesimal, jika memungkinkan.

Jika nama pengguna hanya terdiri dari karakter 0123456789ABCDEF(tidak peka huruf besar-kecil), itu dapat dikonversi menjadi heksadesimal dan disimpan sebagai integer. Misalnya, nama pengguna ba5eba11dapat diartikan sebagai 0xBA5EBA11, integer heksadesimal.

Tapi bagaimana dengan itu 05AB1E? Itu mendapat nol di depan, yang akan hilang. Jadi, setiap kali kami mengonversi nama pengguna, kami pastikan untuk menambahkan 1sebelumnya sebelum membacanya sebagai bilangan bulat.


Tantangan

Tugas Anda adalah menulis sebuah program atau fungsi yang, diberi nama pengguna yang tidak kosong sebagai string, 'heksa-kompres' nama pengguna:

  • Jika itu dapat ditafsirkan sebagai bilangan bulat heksadesimal, tambahkan 1, diartikan sebagai heksadesimal, dan kemudian cetak hasilnya sebagai basis 10.
  • Jika tidak, kembalikan string yang tidak dimodifikasi.

Ini adalah , jadi solusi terpendek (dalam byte) menang! Fungsi konversi basis bawaan diizinkan.


Uji Kasus

Anda dapat mengasumsikan bahwa setiap bilangan bulat yang dihasilkan berada dalam rentang bilangan bulat standar bahasa Anda.

Seperti halnya nama pengguna pada sebagian besar sistem pengiriman pesan, string input hanya akan berisi alfanumerik dan garis bawah.

Ingat, Anda selalu perlu menambahkan arahan 1sebelum konversi!

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

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

Untuk referensi, berikut ini adalah implementasi Python 3 yang saya gunakan untuk kasus uji (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

Ah, tidak melihatnya. Juga, bagaimana jika beberapa kasus uji yang lebih besar menghasilkan angka di luar batas tipe integer terbesar bahasa kita?
Gagang Pintu

2
@ Donorknob tangkapan yang bagus. Saya akan mengatakan bahwa integer yang dihasilkan tidak akan pernah lebih dari tipe integer standar bahasa Anda. (tolong jangan penyalahgunaan ini dan gunakan bahasa dengan integer 1-bit)
FlipTack

Apakah boleh untuk menganggap input hanya huruf besar?
Adám

@ Adám maaf, tetapi program Anda harus peka terhadap huruf besar-kecil (lihat kotak uji)
FlipTack

Seperti Unary, kecuali itu penyandian nama pengguna dan bukan BF
MilkyWay90

Jawaban:


27

05AB1E , 4 byte

D1ìH

Penjelasan

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

Jika input memiliki karakter hex yang tidak valid, Htidak akan mendorong apa pun sehingga nilai terakhir pada stack akan menjadi input yang digandakan, itu sebabnya program mencetak inputnya jika input yang tidak valid.

Cobalah online!


9
Ironinya cukup kuat di sini. 05AB1Eadalah nama pengguna yang valid.
devRicher

1
Itu benar, namun nama itu dipilih sebagai angka heksadesimal. Oleh karena itu valid :)
Osable

Ingin tahu mengapa Anda menipu. Mencoba memikirkan cara untuk menggunakan $ sebagai gantinya ....
Magic Octopus Mm

16

JavaScript (ES6), 15 byte

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

Bagaimana itu bekerja

'0x1'+smengubah input menjadi string heksadesimal literal dengan prepended 1, mis 0x105ab1e. Lalu -0gips hasilnya ke nomor. JavaScript melihat 0xdi awal dan secara implisit mencoba untuk mengkonversi dari heksadesimal; jika sberisi karakter non-heksadesimal, ini akan mengembalikan NaN. Karena ini falsy (dan output 0tidak pernah dapat diberikan karena prepended 1), kita dapat menggunakan ||suntuk mengembalikan sjika konversi hex gagal.

Cuplikan tes

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
Solusi yang sangat bagus!
Grax32

Pengecoran implisit benar-benar indah ...: ')
Downgoat

10

Python 2 , 44 byte

Mengambil input sebagai string yang dikutip. -2 byte terima kasih kepada Rod!

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

Karena kami dijamin bahwa input hanya akan berisi alfanumerik dan garis bawah, tidak ada cara untuk membuat Python yang valid setelah 0x1selain memiliki string hex. Jika input lain, kesalahan diabaikan, dan dicetak seperti semula.

Saya sepertinya tidak bisa membuat pertandingan regex lebih pendek dari try/except. Faktanya, regex ternyata sangat bertele-tele:

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

Anda juga dapat mengganti a=int('1'+a,16)dengan exec'a=0x1'+a(mungkin, perlu menguji)
Rod

Anda tahu, kita harus memiliki jawaban yang persis sama jika saya terus bermain golf, kan?
Anthony Pham

Tidak berfungsi untuk nama pengguna yang akan menjadi Python yang valid dalam konteks itu, misalnya "+input()".
heinrich5991

gagal untuk "abc" (perhatikan spasi putih di akhir) (int memungkinkan spasi putih di awal dan akhir)
Siphor

Saya tidak tahu persis bagaimana itu untuk Python 2, tapi saya pikir Anda dapat menghapus tanda kurung ()diinput()
RudolfJelin

8

Perl 6 , 19 byte

{:16(1~S/_/Z/)//$_}

Menguji

Diperluas:

{   # bare block lambda with implicit parameter 「$_」

    :16(     # convert from base 16
      1
      ~      # Str concatenated
      S/_/Z/ # replace an underscore with an invalid base 16 character
    )

  //         # defined or

    $_       # the input unchanged

}

7

Perl, 27 byte

-1 byte terima kasih kepada @ardnew .

26 byte kode + -pbendera.

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

Masukkan input tanpa baris akhir final. Dengan echo -nmisalnya:

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

Penjelasan
Ini sangat mudah: /[^0-9a-f]/ibenar jika input berisi karakter selain yang diizinkan di dalam angka heksadesimal. Jika salah, $_(yang berisi input) diset ke nilai yang dikonversi (konversi dilakukan oleh builtin hex).
Dan $_dicetak secara tersirat berkat -pbendera.


Anda dapat mencukur byte dengan menghindari operasi ternary$_=hex"1$_"if!/[^0-9a-f]/i
ardnew

@ardnew Hum, sekarang Anda mengatakannya, ternary itu cukup mengerikan ... Bagaimanapun, terima kasih!
Dada


3

Batch, 33 byte

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

Bagaimana itu bekerja

Sebuah string diteruskan sebagai argumen, 1 didahului dengan itu, dan string secara implisit dikonversi menjadi desimal dan dicetak. Jika string tidak heksadesimal, itu hanya ditampilkan.

Perlu dicatat bahwa karena matematika bets menggunakan bilangan bulat 32-bit yang ditandatangani, nama pengguna terbesar yang diizinkan adalah FFFFFFF.

cmd /c mengambil perintah berikutnya, menjalankannya di terminal baru, dan keluar.

set /a melakukan matematika dan secara implisit menampilkan hasilnya dalam desimal ketika tidak disimpan ke variabel.

0x1%1 memberitahu set untuk menambahkan 1 ke argumen pertama (ini mudah karena semua variabel batch adalah string) dan menunjukkan bahwa string harus diperlakukan sebagai heksadesimal.

2>nul membungkam setiap kesalahan yang dihasilkan dari nomor heksadesimal yang tidak valid

||adalah OR logis dan melakukan perintah di sebelah kanan jika perintah di sebelah kiri tidak berhasil. Tanda kurung membuat semuanya hingga titik ini satu perintah.

echo %1 cukup tampilkan argumen pertama.


3

Common Lisp, 71

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

Tes

Tentukan fungsi

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

Kutip daftar input yang diharapkan, seperti yang diberikan oleh pertanyaan:

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")

Parsing dan kumpulkan hasilnya

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"))

Periksa apakah output yang diharapkan cocok dengan yang sebenarnya:

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

2

C, 108 byte

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);}

Ini adalah fungsi yang mengambil string sebagai argumen dan mencetak hasilnya ke 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

Bagus menggunakan int:) implisit
FlipTack

2

JavaScript: 46 41 byte

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

Regex bisa lebih pendek 2 byte:/[^0-9a-f]/i
GilZ

Saya menyimpan 1 byte dengan mengganti 0-9oleh \d, 3 byte dengan menambahkan flag case-insensitive (terima kasih @GilZ) dan 2 byte lebih banyak dengan menghapus F=, yang tidak diperlukan. Terima kasih untuk sarannya.
Luke

2

PHP, 42 byte

hex2bin () mengembalikan false jika input bukan string hex yang valid. Ini lebih pendek daripada menggunakan regex untuk mencari digit non hex, tetapi kita membutuhkan operator @ karena tidak diam ketika gagal.

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

hex2bingagal untuk string dengan panjang yang tidak rata. Masih dua byte lebih pendek dari dengan preg_matchmeskipun: <?=@hex2bin($s=$argv[1])|@hex2bin($s.a)?hexdec("1$s"):$s;untuk 57 byte.
Titus

2

bash, 46 35 31 byte

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

Simpan sebagai skrip, dan berikan nama pengguna sebagai argumen.


1

Python 2 - 63, 52, 50, 46 Bytes

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

Ini menggunakan Python int()yang mengubah string apa pun dengan basis yang sesuai menjadi basis 10. Dalam hal ini, string adalah angka 1 yang melekat pada input. Jika input tidak valid (memiliki karakter selain 0123456789ABCDEF(tidak peka huruf besar-kecil), ia mengembalikan 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

Coba di sini!

Terima kasih kepada @FlipTack karena telah menghemat 15 byte!


Bagaimana jika string tidak dimulai dengan nol? Anda seharusnya hanya menambahkan satu di sebelah kiri string jika dimulai dengan nol.
0WJYxW9FMN

@FlipTack Whoops, konyol saya.
0WJYxW9FMN

1

Ruby, 47 44 byte

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

Aku bisa menghapus 3 byte dengan mengubah putsuntuk p, tapi aku merasa seperti output akan dianggap salah karena memiliki baris baru di akhir.

Sunting: Diubah putskarena ptrailing newlines biasanya diterima, terima kasih @Mego.


Mengejar baris baru di STDOUT biasanya dianggap dapat diterima.
Mego


1

Dyalog APL , 37 byte

Tidak menggunakan validasi bawaan atau konversi hex-dec. Membutuhkan ⎕IO←0yang default pada banyak sistem.

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

Tidak Disatukan:

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

d ← ⎕D , 6 ↑ ⎕Ad mendapat D igits diikuti oleh 6 elemen pertama dari lfabet A

u ← 1 (819⌶) ⍵u mendapat argumen huruf besar (819 ≈ "Besar")

∧/ u ∊ d: jika semua elemen u adalah anggota d , maka:
16 ⊥ 1 , d ⍳ u cari indeks u dalam d , tambahkan 1, dan evaluasi sebagai basis 16

lain: kembalikan argumen (tidak dimodifikasi)

TryAPL online:

  1. Set ⎕IOke nol, menentukan pengganti (dilarang di TryAPL untuk alasan keamanan), dan set ⎕PP( P etak P recision) ke 10 untuk hasil besar

  2. Coba semua test case


1

REXX, 49 48 byte

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

The signal on syntaxmemberitahu juru bahasa untuk melompat ke label syntaxsetiap kali kesalahan sintaksis terjadi. Program mencoba untuk menetapkan ulang adengan versi konversi hex-to-desimal dengan angka 1 terkemuka, tetapi melompat ke syntaxlabel jika gagal. Jika konversi tidak lulus, itu hanya mengabaikan label dan menampilkan variabel yang ditugaskan kembali.


2
Bisakah Anda jelaskan kode Anda
Anthony Pham

0

PowerShell , 35 byte

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

Cobalah online! atau Jalankan semua test case!

Penjelasan

  1. Ambil parameter ( $v)
  2. Buat array dua elemen di mana elemen pertama ( 0) adalah hasil dari string yang berisi 0x1$vpiped into Invoke-Expression( iex), sementara secara bersamaan menetapkan nilai ini ke $h. Jika konversi gagal, $hakan tetap ada $null.
  3. Elemen kedua dari array adalah parameter asli.
  4. Indeks ke dalam array dengan nilai boolean -notdari $h. Apa pun $hyang akan dikonversi secara implisit menjadi [bool]( $nulldalam kasus konversi yang tidak valid akan menjadi $false, bilangan bulat positif dalam kasus konversi yang berhasil menjadi $true) sebelum dinegasikan, yang kemudian secara implisit dikonversi ke [int]oleh pengindeks array []( $trueakan 1, $falseakan menjadi 0), sehingga menghasilkan elemen pertama dari array (hasil konversi) dipilih jika konversi berhasil, dan elemen kedua dipilih jika konversi tidak berhasil.

0

Scala, 40 byte

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

Pemakaian:

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

Penjelasan:

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 byte

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

Tidak disatukan dengan kasus uji:

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();
    }
}

Coba online


0

Dart, 51 byte

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

Coba di sini

Sebagian besar overhead berasal dari parameter bernama ... Oh well!

Setidaknya Dart memungkinkan Anda diketik secara dinamis, jika Anda ingin: D

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.