将英语转换为没有内置或库的数字


14

这个挑战与其他挑战相似,但是我提出了一个限制(请参阅下面的黑体字),我认为这会造成很大的差异,并且(我希望)也很有趣。

挑战

以任何编程语言编写一个程序或函数,该程序或函数采用n不超过正整数的英语名称作为输入作为100返回n值。

禁止使用标准漏洞,并且您不能使用已经执行此操作的任何内置函数,外部工具或库

以字节为单位的最短源代码获胜。

测试

在所有input->output情况下:

one              -> 1
two              -> 2
three            -> 3
four             -> 4
five             -> 5
six              -> 6
seven            -> 7
eight            -> 8
nine             -> 9
ten              -> 10
eleven           -> 11
twelve           -> 12
thirteen         -> 13
fourteen         -> 14
fifteen          -> 15
sixteen          -> 16
seventeen        -> 17
eighteen         -> 18
nineteen         -> 19
twenty           -> 20
twenty-one       -> 21
twenty-two       -> 22
twenty-three     -> 23
twenty-four      -> 24
twenty-five      -> 25
twenty-six       -> 26
twenty-seven     -> 27
twenty-eight     -> 28
twenty-nine      -> 29
thirty           -> 30
thirty-one       -> 31
thirty-two       -> 32
thirty-three     -> 33
thirty-four      -> 34
thirty-five      -> 35
thirty-six       -> 36
thirty-seven     -> 37
thirty-eight     -> 38
thirty-nine      -> 39
forty            -> 40
forty-one        -> 41
forty-two        -> 42
forty-three      -> 43
forty-four       -> 44
forty-five       -> 45
forty-six        -> 46
forty-seven      -> 47
forty-eight      -> 48
forty-nine       -> 49
fifty            -> 50
fifty-one        -> 51
fifty-two        -> 52
fifty-three      -> 53
fifty-four       -> 54
fifty-five       -> 55
fifty-six        -> 56
fifty-seven      -> 57
fifty-eight      -> 58
fifty-nine       -> 59
sixty            -> 60
sixty-one        -> 61
sixty-two        -> 62
sixty-three      -> 63
sixty-four       -> 64
sixty-five       -> 65
sixty-six        -> 66
sixty-seven      -> 67
sixty-eight      -> 68
sixty-nine       -> 69
seventy          -> 70
seventy-one      -> 71
seventy-two      -> 72
seventy-three    -> 73
seventy-four     -> 74
seventy-five     -> 75
seventy-six      -> 76
seventy-seven    -> 77
seventy-eight    -> 78
seventy-nine     -> 79
eighty           -> 80
eighty-one       -> 81
eighty-two       -> 82
eighty-three     -> 83
eighty-four      -> 84
eighty-five      -> 85
eighty-six       -> 86
eighty-seven     -> 87
eighty-eight     -> 88
eighty-nine      -> 89
ninety           -> 90
ninety-one       -> 91
ninety-two       -> 92
ninety-three     -> 93
ninety-four      -> 94
ninety-five      -> 95
ninety-six       -> 96
ninety-seven     -> 97
ninety-eight     -> 98
ninety-nine      -> 99
one hundred      -> 100

1
一个内建工具可以完成一半的工作,例如查找代码点的unicode名称。
布拉德·吉尔伯特b2gills '02

@ BradGilbertb2gills不,这不是很好。
鲍勃,

Answers:


22

C,160字节

g(char*s){char i=1,r=0,*p="k^[#>Pcx.yI<7CZpVgmH:o]sYK$2";for(;*s^'-'&&*s;r+=*s++|9);r=r%45+77;for(;*p!=r;p++,i++);return((*s^'-')?0:g(s+1))+(i<21?i:10*(i-18));}

测试一下

int main ()
{
    char* w[] = {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty-one", "twenty-two", "twenty-three", "twenty-four", "twenty-five", "twenty-six", "twenty-seven", "twenty-eight", "twenty-nine", "thirty", "thirty-one", "thirty-two", "thirty-three", "thirty-four", "thirty-five", "thirty-six", "thirty-seven", "thirty-eight", "thirty-nine", "forty", "forty-one", "forty-two", "forty-three", "forty-four", "forty-five", "forty-six", "forty-seven", "forty-eight", "forty-nine", "fifty", "fifty-one", "fifty-two", "fifty-three", "fifty-four", "fifty-five", "fifty-six", "fifty-seven", "fifty-eight", "fifty-nine", "sixty", "sixty-one", "sixty-two", "sixty-three", "sixty-four", "sixty-five", "sixty-six", "sixty-seven", "sixty-eight", "sixty-nine", "seventy", "seventy-one", "seventy-two", "seventy-three", "seventy-four", "seventy-five", "seventy-six", "seventy-seven", "seventy-eight", "seventy-nine", "eighty", "eighty-one", "eighty-two", "eighty-three", "eighty-four", "eighty-five", "eighty-six", "eighty-seven", "eighty-eight", "eighty-nine", "ninety", "ninety-one", "ninety-two", "ninety-three", "ninety-four", "ninety-five", "ninety-six", "ninety-seven", "ninety-eight", "ninety-nine", "one hundred"};

    int n;
    for (n = 1; n <= 100; n++)
    {
        printf ("%s -> %d\n", w[n], g(w[n]));
        if (n != g(w[n]))
        {
            printf ("Error at n = %d", n);
            return 1;
        }
    }
    return 0;
}

怎么运行的

一些尝试后,我发现,地图中的“例外”号的功能onetwothreefourfivesixseveneightnineteneleventwelvethirteenfourteenfifteensixteenseventeeneighteennineteentwentythirtyfortyfiftysixtyseventyeightyninetyone hundred,可打印的ASCII字符k.[<*cKwye(S_-C)7=4&o]sYgmN,分别。

该函数是:

char hash (char* s)
{
    char r = 0;

    while (*s)
    {
        r += *s|9;
        s++;
    }

    return r%45+77;
}

打高尔夫球的程序将计算hash输入的功能,直到到达字符串或字符的末尾为止-。然后,它搜索字符串中的哈希k.[<* cKwye(S_-C)7=4&o]sYgmN并确定相应的数字。如果到达输入字符串的末尾,则返回数字,如果-到达a,则返回该数字加上应用于其余输入字符串的高尔夫球程序的结果。


我在想,如果有C的高尔夫版本,它实际上可能会击败CJam Pyth Japt等语言……
busukxuan

11

的JavaScript(ES6),175个 166 163 156 153 147字节

@Neil节省了7个字节

a=>+a.replace(/.+te|.*el|y$/,x=>x[1]?'on-'+x:'-d').split(/ |-|dr/).map(x=>"un|d,on|le,w,th,fo,f,x,s,h,i,".split`,`.findIndex(y=>x.match(y))).join``

在这里验证:

怎么运行的

基本思想是将每个数字分成其数字字,然后将每个字映射到相应的数字。几乎所有的单词都设置为与一个简单的正则表达式正确匹配,但是存在一些异常:

  • eleven通过nineteen:如果单词包含一个el或一个te中间(避免ten),我们添加on-到开始,这些变化对on-eleven通过on-nineteen
  • twentythirty等:替换一个尾随y-d变化这些到twent-dthirt-d

现在我们将连字符,空格和drs 分开。这会将11到99的所有内容拆分为相应的数字字,然后"one hundred"拆分为[one,hun,ed]。然后,我们通过正则表达式数组映射这些单词中的每个单词,并保留最先匹配的单词的索引。

0: /un|d/ - This matches the "hun" and "ed" in 100, as well as the "d" we placed on the end of 20, 30, etc.
1: /on|le/ - Matches "one" and the "on" we placed on the beginning of 11 through 19, along with "eleven".
2: /w/ - Matches "two", "twelve", and "twenty".
3: /th/ - Matches "three" and "thirty".
4: /fo/ - Matches "four" and "forty".
5: /f/ - "five" and "fifty" are the only words by now that contain an "f".
6: /x/ - "six" and "sixty" are the only words that contain an "x".
7: /s/ - "seven" and "seventy" are the only words by now that contain an "s".
8: /h/ - "eight" and "eighty" are the only words by now that contain an "h".
9: /i/ - "nine" and "ninety" are the only words by now that contain an "i".
10: /<empty>/ - "ten" is the only word left, but it still has to be matched.

到现在为止,每个输入都将是正确数字的数组。我们要做的就是将它们与一起加入join``,将其与一元数转换为数字+,然后就完成了。


请解释。
鲍勃

@Bob当然,添加了解释。
ETHproductions 2016年

不行.findIndex(y=>x.match(y))
尼尔

@Neil我没有意识到那会,但是确实如此,谢谢!
ETHproductions 2016年

我很确定您可以使用别名replace
Mama Fun Roll

6

sh + coreutils,112个字节

可以一次在所有测试用例上运行,每行一个。

sed -r "`awk '$0="s/"$0"/+"NR"/g"'<<<"on
tw
th
fo
fi
si
se
ei
ni
te|lv
el"`
s/ /y0/
s/y/*10/
s/^\+|[a-z-]//g"|bc

说明

反引号awk评估为sed脚本

s/on/+1/g       # one, one hundred
s/tw/+2/g       # two, twelve, twenty
s/th/+3/g       # three, thirteen, thirty
s/fo/+4/g       # ...
s/fi/+5/g
s/si/+6/g
s/se/+7/g
s/ei/+8/g
s/ni/+9/g
s/te|lv/+10/g   # ten, -teen, twelve
s/el/+11/g      # eleven

它将部分数字转换为数字表示形式。

fife            ->    +5ve
ten             ->    +10n
eleven          ->    +11even
twelve          ->    +2e+10e
sixteen         ->    +6x+10en
thirty-seven    ->    +3irty-+7ven
forty-four      ->    +4rty-+4ur
eighty          ->    +8ghty
one hundred     ->    +1e hundred

sed脚本的其他行

s/ /y0/
s/y/*10/

照顾-tys和one hundred

+3irty-+7ven    ->    +3irt*10-+7ven
+4rty-+4ur      ->    +4rt*10-+4ur
+8ghty          ->    +8ght*10
+1e hundred     ->    +1ey0hundred      ->    +1e*100hundred

最后,删除前导+s以及不是万能的+*或一个数字。

s/^\+|[a-z-]//g"

仅保留数学表达式

fife            ->    5
sixteen         ->    6+10
forty-four      ->    4*10+4
eighty          ->    8*10
one hundred     ->    1*100

并可以用管道插入bc


4

Pyth,79 76 75 68字节

感谢@ETHproductions提供7个字节。

?}"hu"z100sm*+hxc."ewEСBu­["2<d2?|}"een"d}"lv"dTZ?}"ty"dT1cz\-

基本上首先检查100的特殊情况,然后使用数字0到11的前两个字母组成的数组来确定输入的语义,并根据后缀(“ -ty”和“ -teen”;“ 12中的lv“是另一种极端情况。首先将输入分成单词列表,然后将每个单词映射到一个值,然后将它们求和。

在pythonic伪代码中:

                           z = input()    # raw, unevaluated
                           Z = 0
                           T = 10
?}"hu"z                    if "hu" in z:  # checks if input is 100
  100                        print(100)
                           else:
sm                           sum(map( lambda d: # evaluates each word, then sum
  *                            multiply(
   +hxc."ewEСBu­["2<d2           plusOne(chop("ontwth...niteel",2).index(d[:2])) + \
                                 # chops string into ["on","tw",..."el"]
                                 # ."ewEСBu­[" is a packed string
     ?|}"een"d}"lv"dTZ               (T if "een" in d or "lv" in d else Z),
                                     # add 10 for numbers from 12 to 19
   ?}"ty"dT1                     T if "ty" in d else 1),  # times 10 if "-ty"
  cz\-                         z.split("-"))  # splits input into words

测试套件


Python 3,218个字节

z=input()
if "hu" in z:print(100);exit()
print(sum(map(lambda d:([0,"on","tw","th","fo","fi","si","se","ei","ni","te","el"].index(d[:2])+(10 if "een" in d or "lv" in d else 0))*(10 if "ty" in d else 1),z.split("-"))))

基本上与Pyth答案相同。


无关:

我刚刚发现了对生命,宇宙和万物的答案的有意义的版本:是茶渴的树枝。哇,那渴望喝茶的树枝!我不确定还有多少其他答案,但是对于我的答案,如果输入是“ tea-thirsty-twigs”,则输出为42。


我相信使用打包的字符串可以节省七个字节。复制输出并将其放在"ontwthfofisiseeiniteel"该程序中。
ETHproductions 2016年

@ETHproductions哇,谢谢!我上次检查时,字符串的开头仍然有“ ze”,并且打包无法进行。打完球后我再也没有检查过。再次感谢xD
busukxuan 2016年

@ETHproductions是的,我实际上做了,它在伪代码下。
busukxuan

2

Python 3中,365个 361 310 303字符

打高尔夫球

def f(a):
 y=0
 for i in a.split("-"):
  x="one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir;four;fif;six;seven;eigh;nine;twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".replace(";","teen,").split(",").index(i)
  y+=x+1 if x<20 else range(30,110,10)[x-20]
 return y

不打高尔夫球

 def nameToNumber (numberName):
    names = ["one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen",
             "fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty","thirty","forty","fifty",
             "sixty","seventy","eighty","ninety","one hundred"]
    numbers = range(30, 110, 10)
    number = 0
    for n in numberName.split("-"):
        x = names.index(n)
        number += x + 1 if x < 20 else numbers[x - 20]
    return number

短45个字符: n="one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen,twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".split(",")但是如我所见,应该在不将其分配给变量n的情况下工作,只需.index()直接对其调用即可。
manatwork '16

短7个字符: "one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir;four;fif;six;seven;eigh;nine;twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".replace(";","teen,").split(",")
manatwork '16

StackExchange网站引擎有一个令人讨厌的习惯:它将不可见的字符(U200C零宽度非联接符和U200B零宽度空格)插入到注释中发布的代码中。您也复制粘贴了它们。我编辑了您的帖子以将其删除。
manatwork '16

2

哈斯克尔, 252 231字节

let l=words;k=l"six seven eight nine";w=l"one two three four five"++k++l"ten eleven twelve"++((++"teen")<$>l"thir four fif"++k)++[n++"ty"++s|n<-l"twen thir for fif"++k,s<-"":['-':x|x<-take 9w]]in maybe 100id.flip lookup(zip w[1..])

这将创建从“一个”到“九十九”的所有英文数字名称的列表,然后查找输入的索引。如果它不存在,则我们处于边缘情况“一百”,因此它返回100,否则它将返回索引。

不打高尔夫球

-- k in the golfed variant
common = words "six seven eight nine" 

-- w in the golfed variant
numbers = words "one two three four five" ++ common
       ++ words "ten eleven twelve" ++ [p ++ "teen" | p <- words "thir four fif" ++ common]
       ++ [p ++ "ty" ++ s| p <- words "twen thir for fif" ++ common
                         , s <- "" : map ('-':) (take 9 numbers)]

-- part of the expression in the golfed variant
convert :: String -> Int
convert s = maybe 100 id $ lookup s $ zip numbers [1..]

2

Python 2,275个字符

def x(n):a='one two three four five six seven eight nine ten eleven twelve'.split();t='twen thir four fif six seven eigh nine'.split();b=[i+'teen'for i in t[1:]];c=[i+'ty'for i in t];return(a+b+[i+j for i in c for j in ['']+['-'+k for k in a[:9]]]+['one hundred']).index(n)+1

它简单地建立了每个数字的列表并找到索引。


1

Japt,82个字节

+Ur`(.+)¿``¿-$1` r"y$""-d" q$/ |-|dr/$ £`un|Üaiwo|ØÏ¿ifoifix¿iÊ¿¿e¿iv`qi b_XfZ}Ãq

¿代表一个不可打印的字符。在线测试!

基于我的JS答案。如果输出不需要是整数,则减去一个字节,因为它看起来与字符串完全相同。

怎么运行的

+Ur`(.+)¿` `¿-$1`  r"y$""-d" q/ |-|dr/ £  `un|Üaiwo|ØÏ¿ifoifix¿iÊ¿¿e¿iv`          qi b_ XfZ}à q
+Ur"(.+)te""on-$1" r"y$""-d" q/ |-|dr/ mX{"un|dioniwo|wenithifoifixisihineiteiniv"qi bZ{XfZ}} q

Ur"(.+)te""on-$1" // Replace "thirteen", "fourteen", etc. with "on-thiren", "on-fouren", etc.
r"y$""-d"         // Replace "twenty", "thirty", etc. with "twent-d", "thirt-d", etc.
q/ |-|dr/         // Split at occurances of a space, hyphen, or "dr". By now,
                  // "one", "thirteen", "twenty", "sixty-six", "one hundred" will have become:
                  // "one", "on" "thiren", "twent" "d", "sixty" "six", "one" "hun" "ed"
mX         }      // Map each item X in the resulting array to:
"..."qi           //  Take this string, split at "i"s,
b_XfZ}            //  and find the first item Z where X.match(RegExp(Z)) is not null.
                  //  See my JS answer to learn exactly how this works.
                  // Our previous example is now
                  // "1", "1" "3", "2" "0", "6" "6", "1" "0" "0"
+              q  // Join and convert to integer.
                  // 1, 13, 20, 66, 100

1

JavaScript 214 199字节

与往常一样:事实证明,这太久了,无法竞争,但是既然我完成了,那么不发布此消息将是一种浪费。

也许有一种显而易见的方法可以让我更进一步地打高尔夫球?

e=s=>s.slice(-1)=='d'?100:'  ontwthfofisiseeinite'.indexOf(s.slice(0,2))/2;f=s=>([t,u]=s.split('-'),~s.indexOf`le`?11:~s.indexOf`lv`?12:e(t)+(t.slice(-3)=='een')*10+''+(u?e(u):t.slice(-1)=='y'?0:''))

JSFiddle测试用例


1
如何改变ff=s=>([t,u]=s.split('-'),~s.indexOf('le')?11:~s.indexOf('lv')?12:e(t)+(t.slice(-3)=='een')*10+''+(u?e(u):t.slice(-1)=='y'?0:''))?同样,可以将单个字符串参数传递给类似这样的函数:s.indexOf`lv`
ETHproductions 2016年

@ETHproductions太好了,谢谢!我不知道JS具有逗号运算符,并且字符串传递的简写也非常有用。
vvye '02

1

Perl,158个字节

@s=split/(\d+)/,'te1ten0l1le1on1tw2th3fo4fi5si6se7ei8ni9d00';foreach(split'-',$n=$ARGV[0]){for($i=0;$i<$#s;$i+=2){m/$s[$i]/&&print$s[$i+1]}}$n=~/ty$/&&print 0

从命令行运行。one hundred必须输入"one hundred"以阻止将其解释为两个输入。

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.