แปลงภาษาอังกฤษเป็นตัวเลข [ปิด]


27

คำอธิบายสั้น ๆ และหวานของความท้าทาย:

จากความคิดของคำถามอื่น ๆ ในเว็บไซต์นี้ความท้าทายของคุณคือการเขียนโค้ดที่สร้างสรรค์ที่สุดในโปรแกรมใด ๆ ที่ใช้เป็นตัวเลขที่เขียนด้วยภาษาอังกฤษและแปลงเป็นรูปแบบจำนวนเต็ม

ข้อมูลจำเพาะแห้งยาวและทั่วถึงจริงๆ:

  • โปรแกรมของคุณจะได้รับเมื่อป้อนจำนวนเต็มเป็นตัวพิมพ์เล็กระหว่างzeroและnine hundred ninety-nine thousand nine hundred ninety-nineรวม
  • มันจะต้องส่งออกเฉพาะรูปแบบจำนวนเต็มของตัวเลขระหว่าง0และ999999และไม่มีอะไรอื่น (ไม่มีช่องว่าง)
  • การป้อนข้อมูลจะไม่ได้มี,หรือandเป็นในหรือone thousand, two hundredfive hundred and thirty-two
  • เมื่อสถานที่หลายสิบแห่งมีทั้งที่ไม่ใช่ศูนย์และที่มากกว่า1นั้นจะถูกคั่นด้วยอักขระ HYPHEN-MINUS -แทนที่จะเว้นวรรค เหมือนกันสำหรับหนึ่งหมื่นแห่ง ตัวอย่างเช่น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
สิ่งที่เกี่ยวกับ "สี่และยี่สิบ"
ปุย

คำตอบ:


93

Applescript

โง่ผสมแฮ็คที่อาจทำให้คนคูเปอร์ติโน / เมาน์เทนวิวบางคนรู้สึกแย่ แต่ฉันคิดว่ามันเป็นความคิดสร้างสรรค์ที่โง่เขลา

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 Chrome
  • เปิดใช้งานการรู้จำเสียงในบัญชี Google ของคุณ
  • ปริมาณเพิ่มขึ้นในระดับที่เหมาะสม

อาจต้องปรับการกำหนดเวลาล่าช้าขึ้นอยู่กับความเร็วในการโหลดของ Chrome และเวลาค้นหาของ Google

อินพุตตัวอย่าง:

ป้อนคำอธิบายรูปภาพที่นี่

ตัวอย่างผลลัพธ์:

ป้อนคำอธิบายรูปภาพที่นี่


13
ฉันคิดว่ามันอาจจะเป็นแค่ความคิดสร้างสรรค์เล็กน้อย ... ;)
อับราฮัม

5
ฮ่า ๆ นี่เจ๋ง
justhalf

2
อาจจะสร้างสรรค์เกินไป
Cheezey

หลังจากผ่านไปหนึ่งสัปดาห์คำตอบของคุณชัดเจนในการเป็นผู้นำด้วย 74 คะแนนดังนั้นฉันคิดว่านั่นหมายความว่า .. คุณชนะ! อย่างไรก็ตามถ้าฉันใช้รหัสนี้ มันจะมีประโยชน์มากสำหรับโครงการในโลกแห่งความจริงที่ฉันกำลังทำอยู่ตอนนี้! ;)
อับราฮัม

3
@Abraham ขอบคุณ! คุณล้อเล่นเกี่ยวกับการใช้สิ่งนี้ในรหัสการผลิตใช่ไหม
Digital Trauma

34

Bash, 93 64 55 ตัวอักษร *

ในการที่ยอดเยี่ยมbsd-gamesแพคเกจที่มีอยู่ในส่วนระบบปฏิบัติการลินุกซ์มีของเล่นเล็ก ๆ numberบรรทัดคำสั่งที่เรียกว่า มันเปลี่ยนตัวเลขให้เป็นข้อความภาษาอังกฤษนั่นคือมันตรงกันข้ามกับคำถามนี้ จริงๆมันเป็นตรงข้ามแน่นอน: numberกฎทั้งหมดในคำถามที่จะตามมาด้วย มันเกือบจะดีเกินกว่าที่จะเป็นเรื่องบังเอิญ

$ number 42
forty-two.

แน่นอนnumberไม่ตอบคำถาม เราต้องการวิธีอื่น ๆ ฉันคิดถึงเรื่องนี้numberซักพักแล้วลองแยกสตริงแล้วรู้ว่าฉันสามารถโทรไปที่หมายเลข 999.999 ทั้งหมดและดูว่ามีบางอย่างที่ตรงกับอินพุตหรือไม่ ถ้าเป็นเช่นนั้นบรรทัดแรกที่มันจับคู่มีสองหมายเลขบรรทัดที่ฉันกำลังค้นหา ( numberพิมพ์บรรทัดของจุดหลังทุกหมายเลข) เรียบง่ายเหมือนที่ ดังนั้นโดยไม่ต้องกังวลใจต่อไปนี้เป็นรหัสที่สมบูรณ์สำหรับการเข้าของฉัน:

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

มันเป็นวงจรสั้นดังนั้นการแปลง "สอง" ค่อนข้างเร็วและตัวเลขที่สูงขึ้นก็มักจะถอดรหัสในไม่กี่วินาทีในกล่องของฉัน นี่คือตัวอย่างการเรียกใช้:

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
เมื่อคุณพิมพ์บางอย่างเช่น "หนึ่งร้อยสิบหก" มันจะให้ 126.
scrblnrd3

โปรแกรมนี้ล้มเหลวสำหรับบางหมายเลขเริ่มต้นtwelveเมื่อมันกลับ23มา
อับราฮัม

"twenty"ล้มเหลวใน
200_success

seven thousand three hundred thirty fiveให้ฉัน10335
เด็ก

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

Perl + CPAN

ทำไมต้องบูรณาการล้อเมื่อมันทำมาแล้ว?

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

say words2nums $_ while <>;

โปรแกรมนี้อ่านสตริงภาษาอังกฤษจากอินพุตมาตรฐาน (หรือจากไฟล์อย่างน้อยหนึ่งไฟล์ที่ระบุว่าเป็นอาร์กิวเมนต์บรรทัดคำสั่ง) หนึ่งรายการต่อบรรทัดและพิมพ์ตัวเลขที่เกี่ยวข้องไปยังเอาต์พุตมาตรฐาน

ฉันได้ทดสอบโค้ดนี้โดยใช้ทั้งตัวอย่างอินพุตจากการท้าทายรวมถึงชุดการทดสอบที่ครบถ้วนซึ่งประกอบด้วยตัวเลขตั้งแต่ 0 ถึง 999999 ที่แปลงเป็นข้อความโดยใช้numberยูทิลิตีbsd-games (ขอบคุณ Wander Nauta!) และวิเคราะห์อย่างถูกต้อง พวกเขาทุกคน. เป็นโบนัสนอกจากนี้ยังเข้าใจอินพุตเช่นminus seven(−7), four and twenty(24), four score and seven(87), one gross(144), 144) a baker's dozen(13) eleventy-one(111) และgoogol(10 100 )

( หมายเหตุ:นอกจากล่าม Perl เองแล้วโปรแกรมนี้ยังต้องใช้โมดูล CPAN Lingua :: EN :: Words2Numsต่อไปนี้เป็นคำแนะนำสำหรับการติดตั้งโมดูล CPANผู้ใช้ Debian / Ubuntu Linux อาจติดตั้งโมดูลนี้ผ่านตัวจัดการแพคเกจ APT เป็นliblingua-en-word2nums-perl .)


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

Haskell

คล้ายกับโซลูชันแบบเรียกซ้ำอื่น ๆ ที่ฉันเดา แต่ฉันใช้เวลาในการทำความสะอาด

นี่คือแหล่งข้อมูลที่สมบูรณ์พร้อมคำอธิบายทั้งหมด: 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.