Ubah string angka dari kata menjadi integer

19

Ubah string yang berisi digit sebagai kata menjadi bilangan bulat, dengan mengabaikan nol di depan.

Contohnya

  • "four two"-> 42.
  • "zero zero zero one"-> 1.

Asumsi

Pengajuan dapat mengasumsikan bahwa:

  1. String input terdiri dari kata-kata digit yang dipisahkan oleh spasi.
  2. Semua kata valid (dalam kisaran "nol" .. "sembilan") dan huruf kecil. Perilaku untuk input kosong tidak ditentukan.
  3. String input selalu merupakan angka yang tidak ditandai dalam kisaran intdan tidak pernah menjadi string kosong.

Mencetak gol

Jawaban akan dinilai dalam byte dengan lebih sedikit byte menjadi lebih baik.

Sparkler
sumber
3
Selamat datang di situs ini. Ada beberapa hal yang biasanya kita harapkan dari pertanyaan yang hilang di sini. Yang paling penting adalah kriteria penilaian objektif yang harus dimiliki semua tantangan.
Wheat Wizard
3
Selain itu pertanyaan ini sangat jarang pada spesifikasi. Anda harus menentukan dengan tepat apa yang diperlukan dari kiriman tanpa ambiguitas. Satu kalimat dan satu contoh saja tidak sesuai dengan standar kejelasan kita untuk tantangan.
Wheat Wizard
3
Di atas apa yang telah dikatakan, kami memiliki kotak pasir di mana pengguna dapat memposting tantangan mereka sebelum mempostingnya ke utama. Dengan begitu Anda akan kehilangan informasi yang lebih sedikit ketika membuat posting. Jika Anda melihat posting terbaru lainnya di situs dengan penerimaan yang cukup positif, saya pikir Anda akan melihat bahwa pertanyaan dan solusi Anda tidak cukup sejalan dengan apa yang kami lakukan di sini.
FryAmTheEggman
3
Dengan risiko menjadi bertele-tele, saya ingin menunjukkan bahwa range "zero".."nine"itu tidak sepenuhnya ditentukan.
String Tidak Terkait
4
Mengganggu, builtin Interpreter@"SemanticNumber"melakukan hal ini dalam Mathematica — kecuali bahwa ia gagal pada string yang dimulai dengan zero zero .
Greg Martin

Jawaban:

22

PHP , 74 byte

foreach(explode(' ',$argn)as$w)$n.='793251_8640'[crc32($w)%20%11];echo+$n;

Cobalah online!

Mencoba mendapatkan solusi yang tidak menyalin jawaban yang ada. Saya mendapatkan polinomial redundansi checksum siklik dengan panjang 32-bit ( crc32 ) untuk setiap kata dan kemudian melakukan mod 20 dan mod 11 di atasnya untuk mendapatkan nilai-nilai unik dari 0 hingga 10 (hilang 6) untuk setiap digit. Kemudian menggunakan nilai unik itu saya menemukan digit yang sebenarnya.

| Word  | CRC32      | %20 | %11 | Equivalent digit |
|-------|------------|-----|-----|------------------|
| zero  | 2883514770 | 10  | 10  | 0                |
| one   | 2053932785 | 5   | 5   | 1                |
| two   | 298486374  | 14  | 3   | 2                |
| three | 1187371253 | 13  | 2   | 3                |
| four  | 2428593789 | 9   | 9   | 4                |
| five  | 1018350795 | 15  | 4   | 5                |
| six   | 1125590779 | 19  | 8   | 6                |
| seven | 2522131820 | 0   | 0   | 7                |
| eight | 1711947398 | 18  | 7   | 8                |
| nine  | 2065529981 | 1   | 1   | 9                |

Alternatif 74 bytes CRC32 lainnya menggunakan %493%10: Coba online!

Alternatif 74 bytes CRC32 lainnya menggunakan %2326%11: Coba online!


PHP , 74 byte

foreach(explode(' ',$argn)as$w)$n.=strpos(d07bfe386c,md5($w)[21]);echo+$n;

Cobalah online!

Alternatif lain dengan panjang yang sama, mengambil karakter ke-22 di md5kata (hanya karakter yang memberikan nilai unik untuk setiap kata) dan kemudian menggunakan karakter itu untuk memetakan ke digit.

Night2
sumber
Ini adalah jawaban yang keren
Juan Sebastian Lozano
9

Python 2 ,  71  70 byte

-1 berkat ovs (digunakan findsebagai pengganti index)

lambda s:int(''.join(`'rothuvsein'.find((w*3)[6])`for w in s.split()))

Cobalah online!

Jonathan Allan
sumber
7

JavaScript (ES6),  70 67 66  62 byte

Disimpan 3 byte berkat @ovs

s=>+s.replace(/\w+ ?/g,s=>'2839016547'[parseInt(s,36)%204%13])

Cobalah online!

Arnauld
sumber
1
'2839016547'[parseInt(s,36)%204%13]adalah 3 byte lebih pendek.
Ovs
6

Jelly ,  19  17 byte

Ḳµ7ị“*;nÄƲ]³Ṙ»i)Ḍ

Tautan monadik yang menerima daftar karakter yang menghasilkan bilangan bulat.

Cobalah online!

Cukup banyak port jawaban Python 2 saya.


Sebelumnya

ḲŒ¿€i@€“©¥q£½¤MÆÑ‘Ḍ

Cobalah online!

Ada sangat mungkin cara yang lebih pendek, tapi ini adalah cara yang pertama kali datang ke pikiran.

Jonathan Allan
sumber
Menghapus nol dari string enklact untuk menghindari decrementing, karena tidak ditemukan nol bagaimanapun ... pintar!
String Tidak Terkait
1
Ah saya melihat Anda melakukan metode yang sama, bagus.
Jonathan Allan
5

Python 3 , 107 , 91 , 77 , 90 byte

-16 byte oleh Sriotchilism O'Zaic

+13 byte untuk menghapus nol terkemuka

lambda s:int(''.join(map(lambda w:str('zeontwthfofisiseeini'.index(w[:2])//2),s.split())))

Cobalah online!

movatica
sumber
Yang bagus! Dengan begitu, saya bahkan dapat menjatuhkan pembatas sepenuhnya :)
movatica
1
Dengan pembaruan pada tantangan, ini tidak lagi berlaku karena mencakup nol di depan. :(
Wheat Wizard
1
@movatica Perbaikan Anda salah. The lstripMetode strip setiap karakter dalam string yang diberikan sebagai argumen itu, sehingga "delapan dua" menjadi "ight dua", sebagai "e" akan dilucuti. Juga, "nol nol nol" harus mencetak "0", tidak memberikan kesalahan.
NemPlayer
5

Perl 6 , 35 32 byte

{+uniparse 'SP'~S:g/<</,DIGIT /}

Cobalah online!

Penjelasan

{                              }  # Anonymous block
                S:g/<</,DIGIT /   # Insert ",DIGIT " at
                                  # left word boundaries
           'SP'~  # Prepend 'SP' for space
  uniparse  # Parse list of Unicode names into string
 +  # Convert to integer
nwellnhof
sumber
5

C (gcc) , 89 byte

i,n;f(char*w){for(i=n=0;n=*w%32?n^*w:(i+=n-2)&&!printf(L"8 0  72 3  59641"+n%17),*w++;);}

Cobalah online!

Terima kasih untuk trik cerdas @Ceilingcat:

- printf instead of putchar.   
- !printf instead of printf()&0. 
- And wide char !
AZTECCO
sumber
3

05AB1E , 18 16 byte

#ε6è}.•ƒ/ÿßÇf•Åβ

Cobalah online.

Penjelasan:

#                 # Split the (implicit) input-string on spaces
 ε  }             # Map each string to:
  6è              #  Get the character at 0-based index 6 (with automatic wraparound)
     .•ƒ/ÿßÇf    # Push compressed string "rothuvsein"
              Åβ  # Convert the characters from custom base-"rothuvsein" to an integer
                  # (after which the top of the stack is output implicitly as result)

Lihat ini 05AB1E ujung tambang (bagian Cara string kompres bukan bagian dari kamus? ) Untuk memahami mengapa .•ƒ/ÿßÇf•adalah "rothuvsein".

Kevin Cruijssen
sumber
3

05AB1E , 17 16 byte

•D±¾©xWÄ0•I#HèTβ

Cobalah online!

Ikat sempurna dengan jawaban 05AB1E lainnya , tetapi menggunakan pendekatan yang sama sekali berbeda.

•D±¾©xWÄ0•               # compressed integer 960027003010580400
          I#             # split the input on spaces
            H            # convert each word from hex (eg "one" => 6526)
             è           # index (with wrap-around) into the digits of the large integer
              Tβ         # convert from base 10 to integer
Grimmy
sumber
3

Retina 0.8.2 , 46 45 byte

\w+
¶$&$&$&
%7=T`r\ot\huvs\ein`d`.
\D

^0+\B

Cobalah online! Tautan termasuk kasus uji. Penjelasan:

\w+
¶$&$&$&

Letakkan setiap kata di barisnya sendiri dan rangkap tiga.

%7=T`r\ot\huvs\ein`d`.

Menerjemahkan karakter ke-7 dari setiap baris menggunakan string @ UnrelatedString.

\D

Hapus semua karakter non-digit yang tersisa.

^0+\B

Hapus angka nol di depan (tapi tinggalkan setidaknya satu digit).

46 byte sebelumnya solusi yang lebih tradisional:

T`z\wuxg`E
on
1
th
3
fi
5
se
7
ni
9
\D

^0+\B

Cobalah online! Tautan termasuk kasus uji. Penjelasan:

T`z\wuxg`E

Kata-kata zero, two, four, sixdan eightunik berisi huruf zwuxg. Transliterasikan ke angka genap.

on
1
th
3
fi
5
se
7
ni
9

Untuk digit aneh, cukup cocokkan dua huruf pertama dari setiap kata secara terpisah.

\D

Hapus semua karakter non-digit yang tersisa.

^0+\B

Hapus angka nol di depan (tapi tinggalkan setidaknya satu digit).

Neil
sumber
2

Jelly , 20 18 17 byte

Ḳ7ị“*;nÄƲ]³Ṙ»iƲ€Ḍ

Cobalah online!

-2 byte dari menjalankan "rothuvsein" melalui kompresor string user202729 .

-1 byte dari mencuri string bebas-nol Jonathan Allan, dan meletakkannya dalam program terstruktur yang sedikit berbeda.

Ḳ                    Split the input on spaces,
              Ʋ€     for each word
             i       find the 1-based index (defaulting to 0)
   “*;nÄƲ]³Ṙ»        in "othuvsein"
 7ị                  of the element at modular index 7,
                Ḍ    and convert from decimal digits to integer.
String yang tidak terkait
sumber
2

C ++ (gcc) , 478 218 142 byte

- (banyak) terima kasih kepada Jo King

int f(string s){char c[]="N02K8>IE;6";int i=0,n=0;while(s[i]){n=n*10-1;while((s[i]^s[i+1])+47!=c[++n%10]);while(s[i++]!=' '&&s[i]);}return n;}

Cobalah online!

Sparkler
sumber
1
127 byte
ceilingcat
2

Japt , 13 byte

¸mg6 ì`Ψuv 

Cobalah

Sepertinya semua orang mengalahkan saya dengan ide yang sama - bisa menyelamatkan diri dari kerumitan menulis skrip untuk memaksa paksa string optimal untuk kompresi, hanya untuk menemukan bahwa, hingga indeks 1,000,000(masih awal, saya belum punya saya kafein!), "rothuvsein" adalah satu - satunya string yang mungkin!

¸mg6 ì`...     :Implicit input of string
¸              :Split on spaces
 m             :Map
  g6           :  Character at index 6 (0-based, with wrapping)
     ì         :Convert from digit array in base
      `...     :  Compressed string "rothuvsein"

String dikompresi berisi karakter di codepoints 206, 168, 117, 118, 160& 136.

Shaggy
sumber
1
... apakah Anda benar-benar mencoba hingga 1000000? Lcm dari panjang nama digit adalah 60, jadi tidak ada gunanya mencoba lebih dari itu (60 sama dengan 0, 61 hingga 1, dll).
Grimmy
1
@ Grimy, masih pagi, saya belum minum kafein! Memasukkan sejuta ke dalam skrip yang saya tulis untuk menghasilkan semua kemungkinan semudah nomor lainnya dan menyelamatkan saya dari matematika di LCM.
Shaggy
2

Ruby , 63 byte , 52 byte , 50 byte

p $*.map{|d|'rothuvsein'.index (d*3)[6]}.join.to_i

-2 Berkat tip nilai tinta

Harrowed
sumber
Selamat datang di Golf Code! Di Ruby, $*adalah alias untuk ARGV, jadi silakan menggunakannya untuk menyimpan byte tambahan.
Nilai Tinta
2

T-SQL, 110 byte

SELECT 0+STRING_AGG(CHARINDEX(LEFT(value,2),'_ontwthfofisiseeini')/2,'')
FROM STRING_SPLIT((SELECT*FROM i),' ')

Line break hanya untuk keterbacaan.

Input diambil melalui tabel saya, sesuai aturan IO kami . Saya bisa menyimpan 14 byte dengan mempopulasikan variabel string, tetapi itu hanya diperbolehkan jika bahasa tidak memiliki metode input lain.

Penjelasan:

  1. STRING_SPLIT mengambil string input dan memisahkannya di spasi
  2. CHARINDEXmengambil 2 karakter pertama dan mengembalikan posisi (berbasis 1) dalam string '_ontwthfofisiseeini'.'ze'untuk nol tidak ada dalam string dan mengembalikan 0 untuk "tidak ditemukan". Garis bawah memastikan kita hanya mendapatkan kelipatan dua.
  3. Bagilah dengan 2 untuk mendapatkan angka terakhir
  4. STRING_AGG menghancurkan digit kembali bersama tanpa pemisah
  5. 0+memaksa konversi implisit ke INT dan menjatuhkan semua nol di depan. 1*juga akan bekerja.
BradC
sumber
2

kode mesin x86, 46 byte

Hexdump:

57 53 33 c0 33 ff f6 01 0f 75 15 6a 0a 5b 99 f7
f3 6b ff 0a 03 fa 33 c0 38 01 75 0f 97 5b 5f c3
69 c0 26 2b aa 6e 32 01 c1 e8 02 41 eb d8

Ini adalah fastcallfungsi - menerima pointer ke string ecx, dan mengembalikan hasilnyaeax .

Fungsi hashing dikalikan dengan angka ajaib 1856645926, apakah aXOR byte input, dan bergeser ke kanan dengan 2 bit.

Menyimpan dan memulihkan register noclobber ( edidan ebx) memerlukan 4 byte, tetapi saya tidak menemukan cara yang lebih efisien untuk mengimplementasikannya. Menyimpan konstanta 10 inebx sangat menyebalkan!

Disassembly dengan byte kode yang sesuai:

57                   push        edi  ; edi = result
53                   push        ebx  ; we use ebx to store the constant 10
33 C0                xor         eax,eax  
33 FF                xor         edi,edi  
    myloop:
F6 01 0F             test        byte ptr [ecx],0Fh  ; check for end of word
75 15                jne         myhash
6A 0A                push        0Ah  
5B                   pop         ebx  
99                   cdq              ; prepare 64-bit dividend in edx:eax
F7 F3                div         eax,ebx  ; find the remainder of division by 10
6B FF 0A             imul        edi,edi,0Ah
03 FA                add         edi,edx  ; update the result
33 C0                xor         eax,eax  ; reset the hash temporary variable
38 01                cmp         byte ptr [ecx],al  ; check for end of input (here al=0)
75 0F                jne         mycontinue
97                   xchg        eax,edi  ; set the return register
5B                   pop         ebx  ; restore registers
5F                   pop         edi  ; restore registers
C3                   ret  
    myhash:
69 C0 26 2B AA 6E    imul        eax,eax,6EAA2B26h  ; hashing...
32 01                xor         al,byte ptr [ecx]  ; hashing...
C1 E8 02             shr         eax,2  ; hashing...
    mycontinue:
41                   inc         ecx  ; next input byte
EB D8                jmp         myloop

Kode C Setara:

int doit(const char* s)
{
    int result = 0;
    unsigned temp = 0;
    while (true)
    {
        int c = *s++;
        if ((c & 15) == 0)
        {
            temp %= 10;
            result = result * 10 + temp;
            temp = 0;
            if (c == 0)
                break;
            else
                continue;
        }
        temp *= 1856645926;
        temp ^= c;
        temp >>= 2;
    }
    return result;
}
anatolyg
sumber
Bagaimana Anda menemukan angka ajaib?
Sparkler
Saya melakukan pencarian menggunakan kode C saya - mencoba semua angka 32-bit dan semua shift. Hanya ada beberapa kemungkinan - kode hanya ditemukan satu dalam kisaran hingga 2000000000.
anatolyg
Anda dapat menggunakan edx alih-alih edi (tekan edx sebelum idiv, pop eax sesudahnya, imul dengan ebx, tambahkan eax ke edx) untuk menyimpan satu byte.
peter ferrie
1

Bersih , 88 byte

import StdEnv,Text
$s=toInt{#i\\n<-split" "s,c<-:"rothuvsein"&i<-['0'..]|c==(n+n+n).[6]}

Cobalah online!

Sangat berdasarkan jawaban Jonathan Allan .
Menggunakan pemahaman untuk pengindeksan bukan indexOf/ elemIndex.

Suram
sumber
1

J , 38 byte

('b\e~mjPxw['i.[:u:70+1#.15|3&u:)&>@;:

Cobalah online!

Jonah
sumber
1

Arang , 19 byte

I⍘⭆⪪S §ι⁶rothuvsein

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Port dari jawaban 05AB1E @ KevinCruijssen. Penjelasan:

    S               Input string
   ⪪                Split on spaces
  ⭆                 Map over words and join
       ι            Current word
      §             Cyclically indexed
        ⁶           Literal `6`
 ⍘       rothuvsein Custom base conversion
I                   Cast to string for implicit print
Neil
sumber
1

PowerShell , 48 byte

+-join($args|%{'rothuvsein'.indexof(($_*3)[6])})

Cobalah online!

Menggunakan rothuvseintrik yang sama seperti yang lainnya, terima kasih kepada Jonathan Allan. Mengharapkan argumen input melalui splatting, yang pada TIO bermanifestasi sebagai argumen baris perintah yang terpisah.

AdmBorkBork
sumber
1

Kotlin, 83 byte

fun String.d()=split(' ').fold(""){a,b->a+"rothuvsein".indexOf((b+b+b)[6])}.toInt()

+1 byte jika Anda ingin mendukung rindu dengan toLong()

Trik rothuvsein yang sama seperti yang lain, menghemat beberapa byte berharga berkat kotlin yang bagus toInt()dan fold(). Aku hanya tidak bisa menghilangkan perasaan bahwa beberapa byte lagi dapat dicukur ...

Alex Papageorgiou
sumber
1

sed -re , 78 byte

s/three/3/g;s/five/5/g;s/\w\w(\w)\w*/\1/g;s/ //g;y/eouxvgnr/12467890/;s/^0*//
Herzausrufezeichen
sumber
1

Windows Batch, 169 byte

@setlocal enabledelayedexpansion
@set z=zeontwthfofisiseeini
:a
@set b=%1
@for /l %%c in (0,2,18)do @if "!b:~0,2!"=="!z:~%%c,2!" set/aa=a*10+%%c/2&shift&goto a
@echo %a%
Peter Ferrie
sumber
0

VBA, 160 byte

Function e(s)
s = Split(s, " ")
For i = LBound(s) To UBound(s)
s(i) = Int((InStr("ontwthfofisiseeini", Left(s(i), 2)) + 1) / 2)
Next
e = Val(Join(s, ""))
End Function

Cocokkan dua karakter pertama dalam sebuah string, nol dikecualikan.

pengguna3819867
sumber
0

BaCon , 83 72 byte

Dengan asumsi string disediakan dalam w $, kode ini mencari indeks di "zeontwthfofisiseeini" menggunakan ekspresi reguler berdasarkan 2 karakter pertama yang unik dari setiap kata. Indeks kemudian dibagi 2 dengan memberikan hasil yang benar.

FOR x$ IN w$:r=r*10+REGEX("zeontwthfofisiseeini",LEFT$(x$,2))/2:NEXT:?r
Peter
sumber