내장 또는 라이브러리없이 영어를 숫자로 변환


14

이 문제는 유사하다 이 다른 그러나 나는 (아래 굵은 텍스트를 참조) 내가 훨씬 diffent와 (I 희망) 재미 중 하나를 만든 것이라고 생각하는 제한했다.

도전

프로그램이나 입력으로 양의 정수의 영어 이름 걸리는 모든 프로그래밍 언어에서 함수 쓰기 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
코드 포인트의 유니 코드 이름을 찾는 것과 같이 작업의 절반을 수행하는 내장 기능은 어떻습니까?
브래드 길버트 b2gills

@ BradGilbertb2gills 아니오, 그것은 좋지 않습니다.
Bob

답변:


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

작동 원리

일부 시도 후, 나는 "뛰어난"번호를 매핑하는 기능을 발견 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, 인쇄 가능한 ASCII 문자로 k, ., [, <, *, , c, K, w, y, e, (, S, _, -, C, ), 7, =, 4, &,o, ], s, Y, g, m, N, 각각.

이 기능은 다음과 같습니다.

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

자바 스크립트 (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 .
  • twenty, thirty, 등 : 뒤에 교체 y-d변경이에 twent-d, thirt-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

.findIndex(y=>x.match(y))작동 하지 않습니까?
Neil

@ Neil 나는 그것을 알지 못했지만 감사합니다!
ETHproductions

별칭을 지정할 수 있다고 확신합니다 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

설명

백틱 awksed스크립트 로 평가

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/

-ty와 돌봐 one hundred.

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

마지막으로, 최고의 제거 +의이 아니라 모든 것을 +, *또는 숫자를.

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 "는 또 다른 코너 케이스입니다. 먼저 입력을 단어 목록으로 분할 한 다음 각 단어를 값에 매핑하고 요약합니다.

파이썬 의사 코드에서 :

                           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

테스트 스위트


파이썬 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입니다.


압축 된 문자열 을 사용하여 7 바이트를 절약 할 수 있다고 생각 합니다 . 출력을 복사 "ontwthfofisiseeiniteel"하여이 프로그램 대신에 배치 하십시오.
ETHproductions

@ETHproductions 와우, 고마워! 내가 마지막으로 확인했을 때, 끈의 머리 부분에 여전히 "ze"가 있었고 포장이 작동하지 않았습니다. 골프를 치고 난 후에 한 번 더 확인하지 않았습니다. 다시 한번 감사드립니다. xD
busukxuan

@ETHproductions 예 실제로 실제로는 의사 코드 아래에 있습니다.
busukxuan

2

파이썬 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

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

StackExchange 사이트 엔진에는 자극적 인 습관이 있습니다. 주석에 게시 된 코드에 보이지 않는 문자 (U200C Zero Width Non-Joiner 및 U200B Zero Width Space)를 삽입합니다. 복사하여 붙여 넣었습니다. 게시물을 삭제하여 삭제했습니다.
manatwork

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..])

"one"에서 "ninety-nine"까지 모든 영어 숫자 이름 목록을 만든 다음 입력 색인을 찾습니다. 존재하지 않는 경우, 우리는 가장 중요한 경우 "100"이므로을 반환하고 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

파이썬 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

apt, 82 바이트

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

각각 ¿은 인쇄 할 수없는 문자를 나타냅니다. 온라인으로 테스트하십시오!

내 JS 답변을 기반으로합니다. 출력이 문자열과 동일하게 표시되므로 출력이 정수일 필요가없는 경우 1 바이트를 빼십시오.

작동 원리

+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

자바 스크립트, 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
로 바꾸는 f것은 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:''))어떻습니까? 또한 단일 문자열 인수를 다음과 같은 함수로 전달할 수 있습니다.s.indexOf`lv`
ETHproductions

@ETHproductions 감사합니다! JS에 쉼표 연산자가 있다는 것을 몰랐고 문자열 전달의 속기도 실제로 유용합니다.
vvye

1

펄, 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"두 개의 입력으로 해석되는 것을 중지 하려면로 입력해야합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.