将数字字符串从单词转换为整数


19

将包含数字作为单词的字符串转换为整数,而忽略前导零。

例子

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

假设条件

提交内容可以假定:

  1. 输入字符串由空格分隔的数字词组成。
  2. 所有单词都是有效的(在“零” ..“九”的范围内)且小写。空输入的行为是不确定的。
  3. 输入字符串始终表示范围内的无符号数字,int并且决不能为空字符串。

计分

答案将以字节计分,而字节数越少越好。


3
欢迎来到该网站。我们通常希望从这里缺少的问题中得到几件事。最重要的是所有挑战都必须具备的客观评分标准
小麦巫师

3
除此之外,这个问题在规格上非常稀疏。您应该准确地指定提交内容所需要的内容。一句话和一个例子不符合我们对挑战的明确标准。
小麦巫师

3
除了已经说过的内容外,我们还有一个沙箱,用户可以在其中将挑战发布到主要之前。这样一来,您在发布信息时会丢失更少的信息。如果您以不错的积极态度看待网站上的其他近期帖子,我想您会发现您的问题和解决方案与我们在此处所做的都不完全一致。
FryAmTheEggman

3
冒着学究的危险,我想指出的range "zero".."nine"是未完全指定。
不相关的字符串

4
令人讨厌的是,内建Interpreter@"SemanticNumber"函数在Mathematica中完全做到了这一点-除了它在以开头的字符串上失败zero zero
格雷格·马丁

Answers:


22

PHP,74字节

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

在线尝试!

试图获得一种不会复制现有答案的解决方案。我为每个单词获取了32位长度(crc32)的循环冗余校验和多项式,然后对其进行mod 20和mod 11以获得每个数字从0到10的唯一值(缺少6)的混合。然后使用该唯一值找到实际数字。

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

另一种使用74字节CRC32的替代方法%493%10在线尝试!

另一种使用74字节CRC32的替代方法%2326%11在线尝试!


PHP,74字节

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

在线尝试!

另一个具有相同长度的替代方法是md5,在单词的第22个字符(唯一为每个单词赋予唯一值的字符)之后使用该字符映射到数字。


这是一个很酷的答案
Juan Sebastian Lozano



6

果冻 19  17字节

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

单子链接,接受产生整数的字符列表。

在线尝试!

我的Python 2答案差不多。


以前

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

在线尝试!

很可能更短的路,但是这是第一次来到介意的方式。


从enklact字符串中删除零以避免递减,因为无论如何都找不到零...聪明!
不相关的字符串

1
啊,我看你也用同样的方法,很好。
乔纳森·艾伦

5

Python 3中1079177,90个字节

-16字节,由Sriotchilism O'Zaic提供

+13个字节以删除前导零

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

在线尝试!



好一个!这样,我什至可以完全删除定界符:)
movatica

1
随着挑战的更新,它不再有效,因为它包含前导零。:(
麦向导


1
@movatica您的修复不正确。该lstrip方法剥离字符串中作为其参数给出的每个字符,因此当“ e”被剥离时,“八二”变为“第八二”。同样,“零零零”应该打印出“ 0”,而不是发出错误。
NemPlayer

5

Perl 6的35 32个字节

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

在线尝试!

说明

{                              }  # 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

5

C(gcc),89个字节

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

在线尝试!

感谢@Ceilingcat最聪明的技巧:

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

3

05AB1E18 16 字节

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

在线尝试。

说明:

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

看到这个05AB1E尖矿(部分如何压缩字符串不是字典的一部分吗?理解为什么.•ƒ/ÿßÇf•"rothuvsein"



3

05AB1E17 16字节

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

在线尝试!

其他05AB1E答案完美配合,但使用了完全不同的方法。

•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

3

视网膜0.8.246个 45字节

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

^0+\B

在线尝试!链接包括测试用例。说明:

\w+
¶$&$&$&

将每个单词放在自己的行上,一式三份。

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

使用@UnrelatedString的字符串音译每行的第7个字符。

\D

删除所有剩余的非数字字符。

^0+\B

删除前导零(但至少保留一位数字)。

以前的46字节更传统的解决方案:

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

^0+\B

在线尝试!链接包括测试用例。说明:

T`z\wuxg`E

这句话zerotwofoursixeight独特的包含字母zwuxg。将其音译为偶数。

on
1
th
3
fi
5
se
7
ni
9

对于奇数位,只需分别匹配每个单词的前两个字母。

\D

删除所有剩余的非数字字符。

^0+\B

删除前导零(但至少保留一位数字)。


2

果冻20 18 17字节

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

在线尝试!

通过user202729的字符串压缩器运行“ rothuvsein” 产生的 -2个字节。

窃取Jonathan Allan的零零enklact字符串并将其放入结构稍有不同的程序中,因此为-1个字节。

Ḳ                    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.


2

Japt,13 个字节

¸mg6 ì`Ψuv 

尝试一下

似乎其他人都对1,000,000我抱有相同的想法-本来可以省去编写脚本以蛮力压缩最佳压缩字符串的麻烦,却发现直到索引为止(很早,我还没有咖啡因呢!),“罗氏菌素”是唯一可能的字符串!

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

压缩字符串包含的字符在码点206168117118160136


1
...您真的尝试了高达1000000吗?数字名称长度的lcm为60,因此没有其他尝试尝试尝试(60等于0、61等于1等)。
Grimmy

1
@肮脏,太早了,我还没有咖啡因!将一百万美元插入我编写的脚本以生成所有可能性就像其他任何数字一样容易,并且节省了我在LCM上进行数学运算的时间。
毛茸茸的

2

Ruby63字节52字节,50字节

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

-2多亏了超值墨水的提示


欢迎来到Code Golf!在Ruby中,$*是的别名ARGV,因此可以随意使用它来节省额外的字节。
价值墨水

2

T-SQL,110字节

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

换行符仅用于可读性。

一世

说明:

  1. STRING_SPLIT 接受输入字符串并在空格处将其分隔
  2. CHARINDEX接受前2个字符,并返回string中(从1开始)的位置'_ontwthfofisiseeini''ze'为零不在字符串中,并为“未找到”返回0。下划线确保我们只能得到2的倍数。
  3. 除以2得到最终数字
  4. STRING_AGG 将数字粉碎回没有分隔符
  5. 0+强制将隐式转换为INT并删除所有前导零。1*也可以。

2

x86机器代码,46字节

十六进制转储:

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

这是一个fastcall函数-接收指向该字符串的指针ecx,并在中返回结果eax

哈希函数乘以魔术数 1856645926,对XOR输入字节进行a 运算,并向右移2位。

保存和恢复noclobber寄存器(ediebx)占用了4个字节,但是我没有找到一种更有效的方法来实现这一点。存储常数10 inebx尤其令人讨厌!

用相应的代码字节反汇编:

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

等效的C代码:

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

您是如何找到魔术数字的?
烟火

我使用C代码进行了搜索-尝试了所有32位数字和所有移位。目前只有几种可能性-代码中发现的唯一一个在高达至2000000000
anatolyg

您可以使用edx代替edi(将edx推到idiv之前,在其后弹出eax,使用ebx的imul,将edx添加到edx)以节省一个字节。
彼得·费里



1

木炭,19字节

I⍘⭆⪪S §ι⁶rothuvsein

在线尝试!链接是详细版本的代码。@KevinCruijssen的05AB1E答复端口。说明:

    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

1

PowerShell,48字节

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

在线尝试!

rothuvsein多亏乔纳森·艾伦(Jonathan Allan),使用与其他人相同的技巧。希望通过拼写输入参数,在TIO上它表现为单独的命令行参数。


1

Kotlin,83个字节

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

+1字节,如果您想支持 toLong()

与rothuvsein相同的技巧,由于kotlin的nice toInt()和,节省了一些宝贵的字节fold()。我只是不能撼动那种感觉,虽然可以削减更多的字节...



1

Windows Batch,169个字节

@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%


0

VBA,160字节

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

匹配字符串中的前两个字符,不包括零。


0

培根83 72字节

假设字符串以w $提供,则此代码使用正则表达式根据每个单词的唯一前2个字符在“ zeontwthfofisiseeini”中查找索引。然后将索引除以2,以提供正确的结果。

FOR x$ IN w$:r=r*10+REGEX("zeontwthfofisiseeini",LEFT$(x$,2))/2:NEXT:?r
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.