영어를 숫자로 변환 [닫기]


27

도전에 대한 짧고 달콤한 설명 :

이 사이트의 다른 몇 가지 질문에 대한 아이디어를 바탕으로 영어로 작성된 숫자를 입력하고 정수 형식으로 변환하는 프로그램에서 가장 창의적인 코드를 작성해야합니다.

건조하고 길고 철저한 사양 :

  • 프로그램은 소문자 영어 zero와 정수 사이 의 정수를 입력으로받습니다 nine hundred ninety-nine thousand nine hundred ninety-nine.
  • 그것은 사이의 수의 출력 만 정수 형태로해야 0하고 999999아무것도 다른 (어떤 공백).
  • 입력이됩니다 NOT 포함 ,또는 and같이, one thousand, two hundred또는 five hundred and thirty-two.
  • 10 자리와 1 자리가 모두 0이 아닌 10 자리보다 큰 경우 공백 대신 1HYPHEN-MINUS 문자로 구분됩니다 -. 수만 곳을위한 Ditto. 예를 들면 다음과 같습니다 six hundred fifty-four thousand three hundred twenty-one.
  • 프로그램이 다른 입력에 대해 정의되지 않은 동작을 가질 수 있습니다.

잘 작동하는 프로그램의 예 :

zero-> 0
fifteen-> 15
ninety-> 90
seven hundred four-> 704
sixty-nine thousand four hundred eleven-> 69411
five hundred twenty thousand two->520002


이것은 독창적이지 않고 여기의 사양과 정확하게 일치하지는 않지만 시작점으로 유용 할 수 있습니다. github.com/ghewgill/text2num/blob/master/text2num.py
Greg Hewgill

이 질문에 대한 답변을 거의 올릴 수 있습니다.
grc

복잡한 문자열 파싱이 왜 필요한가요? pastebin.com/WyXevnxb
blutorange

1
그건 그렇고, 나는 이 질문에 대한 답변 인 IOCCC 항목 을 보았습니다 .
스낵

2
"4 및 20"과 같은 것은 어떻습니까?
솜털

답변:


93

애플 스크립트

일부 쿠퍼 티노 / 마운틴 뷰 사람들을 화나게 할 수있는 어리석은 해키 매쉬업이지만 창의적인 어리 석고 해키 매쉬업 이라고 생각 합니다.

set myNumber to text returned of (display dialog ¬
    "Enter number as text:" buttons {"Continue…"} ¬
    default answer "" default button 1)
tell application "Google Chrome"
    activate
    open location "https://www.google.com"
end tell
delay 5
say "ok google. " & myNumber
delay 2
tell application "System Events"
    tell application process "Google Chrome"
        set fullURL to value of text field 1 of toolbar 1 of window 1
    end tell
end tell
set AppleScript's text item delimiters to "="
display alert item 2 of text items of fullURL

OSX 텍스트를 사용하여 음성을 사용하여 텍스트 번호를 말하고 Google 오디오 검색을 통해 텍스트를 듣고 정수로 변환합니다.

요구 사항

  • OSX
  • 구글 크롬
  • Google 계정에서 음성 인식 사용
  • 적당한 수준으로 볼륨을 올렸다

크롬로드 시간과 Google 조회 시간에 따라 지연 시간을 조정해야 할 수도 있습니다.

입력 예 :

여기에 이미지 설명을 입력하십시오

출력 예 :

여기에 이미지 설명을 입력하십시오


13
나는 그것이 조금 창의적 일지도 모른다 ... ...)
Abraham

5
Lol, 이것은 시원합니다
Justhalf

2
아마도 너무 창의적 일 수 있습니다.
Cheezey 2016 년

일주일 후, 당신의 대답은 분명히 74 표로 이어질 것입니다. 그건 그렇고,이 코드를 사용하면 괜찮습니까? 현재 진행중인 많은 실제 프로젝트에 유용합니다! ;)
Abraham

3
@Abraham 감사합니다! 프로덕션 코드에서 이것을 사용하는 것에 대해 농담하고 있습니까?
디지털 외상

34

배쉬, 93 64 55 문자 *

bsd-games대부분의 Linux 운영 체제에서 사용할 수 있는 환상적인 패키지에는라는 작은 명령 줄 장난감이 number있습니다. 숫자를 영어 텍스트로 바꿉니다. 즉,이 질문과 정반대입니다. 그것은 실제로 정반대입니다. 질문의 모든 규칙은 뒤에옵니다 number. 우연의 일치가 거의 너무 좋습니다.

$ number 42
forty-two.

물론 number질문에 대답하지 않습니다. 우리는 그것을 다른 방향으로 원합니다. 나는 이것에 대해 잠시 동안 생각하고 문자열 파싱과 그 모든 것을 시도한 다음 number모든 999.999 숫자를 호출 하고 무언가가 입력과 일치하는지 확인할 수 있음을 깨달았습니다 . 그렇다면 첫 번째 줄과 일치하는 줄 번호는 내가 찾는 줄 번호의 두 배입니다 ( number모든 번호 뒤에 점을 인쇄합니다). 그렇게 간단합니다. 따라서 더 이상 고민하지 않고 다음은 내 항목에 대한 전체 코드입니다.

seq 0 999999|number -l|awk "/$1/{print (NR-1)/2;exit}"

심지어 단락되기 때문에 "2"를 변환하는 것은 매우 빠르며 더 높은 숫자는 대개 내 상자에서 1 초 이내에 해독됩니다. 다음은 예제 실행입니다.

wn@box /tmp> bash unnumber.sh "zero"
0
wn@box /tmp> bash unnumber.sh "fifteen"
15
wn@box /tmp> bash unnumber.sh "ninety" 
90
wn@box /tmp> bash unnumber.sh "seven hundred four"
704
wn@box /tmp> bash unnumber.sh "sixty-nine thousand four hundred eleven"
69411
wn@box /tmp> bash unnumber.sh "five hundred twenty thousand two"    
520002

물론 number이것이 작동하려면 설치 해야합니다 .


* : 예, 저는 이것이 code-golf도전 이 아니라는 것을 알고 있습니다. 그러나 부족함은 저의 입장에서 가장 독보적 인 품질입니다.


8
+1. 나에게, number이 답변에 대한 가장 독창적 인 것은 반전을 사용 하는 것입니다. 골프는 역시 좋다 :)
Digital Trauma

1
이것은 실제로 매우 창의적입니다! 나는 그것을 좋아한다!
sokie

13

자바 스크립트

(function parse(input) {
  var pat = "ze/on/tw/th.?r/fo/fi/ix/se/ei/ni/ten/ele".split("/");
  var num = "", last = 0, token = input.replace(/-/g, " ").split(" ");
  for(var i in token) {
    var t = token[i];
    for(var p in pat) if(t.match(RegExp(pat[p])) !== null) num += "+" + p;
    if(t.indexOf("een") >= 0) num += "+10";
    if(t.indexOf("lve") >= 0) num += "+10";
    if(t.indexOf("ty") >= 0) num += "*10";
    if(t.indexOf("dr") >= 0) { last = 100; num += "*100"; }
    if(t.indexOf("us") >= 0) {
      if(last < 1000) num = "(" + num + ")"; last = 0;
      num += "*1000";
    }
  }
  alert(eval(num));
})(prompt());

당신은 일부를 좋아 eval()합니까?

브라우저 콘솔에서이 스크립트를 실행하십시오.

편집 : 의견 주셔서 감사합니다. 버그 수정 (다시).


정말 좋은 코드 ^^
zsitro

2
"백
육십

이 프로그램 twelve은 반환 할 때 시작하는 일부 숫자에 대해 실패 합니다 23.
Abraham

에 실패합니다 "twenty".
200_success 2018 년

seven thousand three hundred thirty five10335
Baby

7

파이썬

공을 굴리기 위해.

import re
table = {'zero':0,'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,'thirty':30,'forty':40,'fifty':50,'sixty':60,'ninety':90}
modifier = {'hundred':100,'thousand':1000}

while True:
    text = raw_input()
    result = 0
    tmp = 0
    last_multiplier = 1
    for word in re.split('[- ]', text):
        multiplier = modifier.get(word, 1)
        if multiplier > last_multiplier:
            result = (result+tmp)*multiplier
            tmp = 0
        else:
            tmp *= multiplier
        if multiplier != 1:
            last_multiplier = multiplier
        tmp += table.get(word,0)
    print result+tmp

5

펄 + CPAN

바퀴가 이미 완성 된 이유는 무엇입니까?

use feature 'say';
use Lingua::EN::Words2Nums;

say words2nums $_ while <>;

이 프로그램은 표준 입력 (또는 명령 행 인수로 지정된 하나 이상의 파일)에서 영어 문자열을 한 줄에 하나씩 읽고 해당 숫자를 표준 출력으로 인쇄합니다.

도전 과제의 샘플 입력과 bsd-games number유틸리티 (감사, Wander Nauta!)를 사용하여 텍스트로 변환 된 0에서 999999까지의 숫자로 구성된 철저한 테스트 스위트를 사용 하여이 코드를 테스트 했으며 올바르게 구문 분석합니다 그들 모두. 보너스로서, 또한 그러한 예로서 이해 입력 minus seven(-7), four and twenty(24), four score and seven(87), one gross(144), a baker's dozen(13), eleventy-one(111) 및 googol(10 (100) ).

( 참고 : Perl 인터프리터 자체 이외에도이 프로그램에는 CPAN 모듈 Lingua :: EN :: Words2Nums 가 필요합니다. CPAN 모듈 설치에 대한 지시 사항 은 다음과 같습니다 . Debian / Ubuntu Linux 사용자는 APT 패키지 관리자를 통해이 모듈을 설치할 수도 있습니다. 같은 liblingua-KO-words2nums - 펄 .)


4

파이썬

유효성 검사가 포함 된 일반적인 재귀 솔루션입니다. 필요한 숫자 범위를 단순화 할 수는 있지만 여기에 나와 있습니다.

terms = 'zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen'.split()
tee  = 'twenty thirty forty fifty sixty seventy eighty ninety'.split()
for t in tee:
    terms.append(t)
    for s in terms[1:10]:
        terms.append(t+'-'+s)

terms = dict(zip(terms, range(100)))

modifiers = [('hundred', 100), ('thousand', 1000), ('million', 10**6), ('billion', 10**9)]

def read_num(words):
    if len(words) == 0: return 0
    elif len(words) == 1:
        if words[0] in terms:
            return terms[words[0]]
        else:
            raise ValueError(words[0]+' is not a valid english number.')
    else:
        for word, value in reversed(modifiers):
            if word in words:
                i = words.index(word)
                return read_num(words[:i])*value+read_num(words[i+1:])

    raise ValueError(' '.join(words)+' is not a valid english number.')

while True:
    try:
        print(read_num(input().split()))
    except ValueError as e:
        print(e)

2

VBScript 474

이것은 매우 일상적인 답변입니다 ... 불행히도, @Snack이 거의 동일한 프로세스를 게시했지만 내 앞에 있습니다.

i=split(REPLACE(REPLACE(inputbox(""),"lve","een"),"tho","k"))
o=split("z on tw th fo fi si se ei ni ten ele")
y=split("red *100) k )*1000 ty *10) een +10)")
z=""
p=0
for t=0 to UBOUND(i)
    s=split(i(t),"-")
    u=ubound(s)
    r=s(0)
    for x=0 to UBOUND(o)    
        IF INSTR(r,o(x)) THEN
            z=z+"+"+CSTR(x)
        END IF
        IF u Then
            IF INSTR(s(1),o(x)) THEN
                z=z+CSTR(x)
            END IF
        END IF
    next
    for m=0 to UBOUND(y)
        IF INSTR(r,y(m))AND u=0 THEN
            z=z+y(m+1)
            p=p+1
        END IF
    next
next
Execute("MSGBOX "+String(p,"(")+z)

1

하스켈

다른 재귀 솔루션과 비슷하지만 시간을내어 깨끗하게 정리했습니다.

다음은 모든 설명이 포함 된 전체 소스입니다. http://ideone.com/fc8zcB

-- Define a type for a parser from a list of tokens to the value they represent.
type NParse = [Token] -> Int    

-- Map of literal tokens (0-9, 11-19 and tens) to their names.
literals = [
        ("zero", 0), ("one", 1), ("two", 2), ("three", 3), ("four", 4), ("five", 5), ("six", 6), ("seven", 7), ("eight", 8), ("nine", 9),
        ("eleven", 11), ("twelve", 12), ("thirteen", 13), ("fourteen", 14), ("fifteen", 15), ("sixteen", 16), ("seventeen", 17), ("eighteen", 18), ("nineteen", 19),
        ("ten", 10), ("twenty", 20), ("thirty", 30), ("fourty", 40), ("fifty", 50), ("sixty", 60), ("seventy", 70), ("eighty", 80), ("ninety", 90)
    ]

-- Splits the input string into tokens.
-- We do one special transformation: replace dshes by a new token. Such that "fifty-three" becomes "fifty tens three". 
prepare :: String -> [Token]

-- Let's do the easy stuff and just parse literals first. We just have to look them up in the literals map.
-- This is our base parser.
parseL :: NParse
parseL [tok] = case lookup tok literals of 
    Just x -> x

-- We're going to exploit the fact that the input strings have a tree-like structure like so
--                    thousand
--          hundred             hundred
--      ten       ten       ten         ten
--    lit   lit lit  lit   lit  lit    lit  lit
-- And recursively parse that tree until we only have literal values.
--
-- When parsing the tree
--       thousand
--     h1       h2
-- The resulting value is 1000 * h1 + h2.
-- And this works similarly for all levels of the tree.
-- So instead of writing specific parsers for all levels, let's just write a generic one :

{- genParse :: 
    NParse      : the sub parser
    -> Int      : the left part multiplier
    -> Token    : the boundary token 
    -> NParse   : returns a new parser -}   
genParse :: NParse -> Int -> Token -> NParse    
genParse delegate mul tok = newParser where
    newParser [] = 0
    newParser str = case splitAround str tok of
        -- Split around the boundary token, sub-parse the left and right parts, and combine them
        (l,r) -> (delegate l) * mul + (delegate r)  

-- And so here's the result: 
parseNumber :: String -> Int
parseNumber = parseM . prepare
    where   -- Here are all intermediary parsers for each level
    parseT = genParse   parseL  1       "tens"       -- multiplier is irregular, because the fifty in fifty-three is already multiplied by 10
    parseH = genParse   parseT  100     "hundred"
    parseK = genParse   parseH  1000    "thousand"
    parseM = genParse   parseK  1000000 "million" -- For fun :D

test = (parseNumber "five hundred twenty-three thousand six hundred twelve million two thousand one") == 523612002001

0

커먼 리스프, 94

(write(cdr(assoc(read-line)(loop for i to 999999 collect(cons(format()"~r"i)i)):test #'equalp)))

숫자 대 텍스트 변환은 CL에 내장되어 있지만 다른 방법은 아닙니다. 숫자에 대한 역 매핑을 작성하고 입력을 확인합니다.

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