Sözlü Hesap Makinesi


14

İngilizce sayısal hesap makinesinin basit bir versiyonu

Görev

Bir dizeyi girdi olarak alan ve ifadenin sonucunu çıkaran bir program yazın.

kurallar

Giriş dizesi rakamla ifade edilecek ve rakam değil.

Parantez olmayacak.

Hesaplama sırası bölünecek, çarpılacak, çıkartılacak ve eklenecektir.

Aynı işlemler için hesaplamalar soldan sağa yapılmalıdır.

Tüm giriş numaraları -999 ile 999 arasında bir tam sayı olacaktır (her ikisi de dahil)

Çıktı herhangi bir aralığın tamsayısı olacaktır.

Bölünme her zaman mükemmel bölünebilir olacak ve sıfır asla payda olmayacak.

Vaka girişi için kısıtlama isteğe bağlıdır. Girişin geçerliliğini kontrol etmek zorunda değilsiniz.

Sayı Biçimi

0 to 20 -> zero,one,two...nineteen,twenty
21 to 99 -> twenty one,twenty two.....ninety eight,ninety nine
100 to 999 -> one hundred, one hundred one, one hundred two...one hundred ten....two hundred fifty....nine hundred ninety eight,nine hundred ninety nine

Negatif sayılar için: minusPozitif karşılığına ekleyin

Çalışma Biçimi

Addition: one plus two
Subtraction: one minus two
Multiplication: one time two #Note that for one on the left of multiplication, it is one time and not times.
                two times one hundred
Division: forty divided by two

Örnekler:

o/p <- input

20     four times five
35     twenty plus fifteen
70     fifty plus five times four
-90    minus one time ninety
25     twenty one minus minus four
45     ninety divided by two
700    one time seven hundred 
555    one hundred eleven times two plus three hundred thirty three
99     one hundred plus minus one
45     forty five plus two hundred times zero
 4     four
-3     three minus three minus three

Bu kod golf, bu yüzden en kısa kod kazanır


1
Çiftleme? - Bence bu böyle düşünülecek kadar yakın.
Kirill

2
Gerçekten çok yakın. Ama bence bu daha iyi belirlenmiş ve daha makul sınırlamaları var.
Arnauld

1
@O zaman bunu açık tutacağım, ancak başkaları farklı düşünürse, sadece kopya olarak işaretleyin.
Vedant Kandoi

15
Ben söylüyorum one times two. timeNormal mi kullanıyorsunuz ?
Jo King

2
Sana 'bir kez geliyordu düşünüyorum lar yediyüz'?
ouflak

Yanıtlar:


18

JavaScript (ES6), 257 252 249 235 bayt

@Shaggy sayesinde 3 bayt kaydedildi

s=>eval(s.split` `.map(w=>(i='zeonwohrr44fx3n5t54nn3leel8tou7fn7n98etetwthfofisiseeinihuplmitidiby'.match(/../g).findIndex(x=>~(w+w.length+w).search(x)))>28?n+' '+'+-*/ '[n='',i-29]:(n=+n+(i<28?i<20?i:i*10-180:n*99),''),n='').join``+n)

Çevrimiçi deneyin!

Nasıl?

Giriş dizesi kelimelere ayrıldıktan sonra, uzunluğunda her kelimesi , bulunabilen ilk 2 karakterlik anahtar alt dizgisini arayarak bir dizine dönüştürülür .WLiW+L+W

sayılar

 index | word              | word + length + word         | key substring
-------+-------------------+------------------------------+---------------
    0  | "zero"            | "zero4zero"                  | "ze"
    1  | "one"             | "one3one"                    | "on"
    2  | "two"             | "two3two"                    | "wo"
    3  | "three"           | "three5three"                | "hr"
    4  | "four"            | "four4four"                  | "r4"
    5  | "five"            | "five4five"                  | "4f"
    6  | "six"             | "six3six"                    | "x3"
    7  | "seven"           | "seven5seven"                | "n5"
    8  | "eight"           | "eight5eight"                | "t5"
    9  | "nine"            | "nine4nine"                  | "4n"
   10  | "ten"             | "ten3ten"                    | "n3"
   11  | "eleven"          | "eleven6eleven"              | "le"
   12  | "twelve"          | "twelve6twelve"              | "el"
   13  | "thirteen"        | "thirteen8thirteen"          | "8t"
   14  | "fourteen"        | "fourteen8fourteen"          | "ou"
   15  | "fifteen"         | "fifteen7fifteen"            | "7f"
   16  | "sixteen"         | "sixteen7sixteen"            | "n7"
   17  | "seventeen"       | "seventeen9seventeen"        | "n9"
   18  | "eighteen"        | "eighteen8eighteen"          | "8e"
   19  | "nineteen"        | "nineteen8nineteen"          | "te"
   20  | "twenty"          | "twenty6twenty"              | "tw"
   21  | "thirty"          | "thirty6thirty"              | "th"
   22  | "forty"           | "forty5forty"                | "fo"
   23  | "fifty"           | "fifty5fifty"                | "fi"
   24  | "sixty"           | "sixty5sixty"                | "si"
   25  | "seventy"         | "seventy7seventy"            | "se"
   26  | "eighty"          | "eighty6eighty"              | "ei"
   27  | "ninety"          | "ninety6ninety"              | "ni"
   28  | "hundred"         | "hundred7hundred"            | "hu"

Operatörler

 index | word              | word + length + word         | key substring
-------+-------------------+------------------------------+---------------
   29  | "plus"            | "plus4plus"                  | "pl"
   30  | "minus"           | "minus5minus"                | "mi"
   31  | "times" or "time" | "times5times" or "time4time" | "ti"
   32  | "divided"         | "divided7divided"            | "di"
   33  | "by"              | "by2by"                      | "by"

yorumlama

Geçerli sayı, boş bir dizeye başlatılan saklanır . Sonraki kelimenin dizini verildiğinde, aşağıdaki mantık geçerlidir:ni

i > 28 ?                  // if the word is an operator:
  n +                     //   append n (which is either an empty string or a number)
  ' ' +                   //   append a space
  '+-*/ '[n = '', i - 29] //   reset n to an empty string and append the operator
                          //   the useless keyword 'by' is translated into a harmless space
: (                       // else:
    n =                   //   update n:
      +n + (              //     force the coercion of the current value of n to a number
        i < 28 ?          //     if the word is not 'hundred':
          i < 20 ?        //       if the value of the word is less than 'twenty':
            i             //         add i
          :               //       else:
            i * 10 - 180  //         add i * 10 - 180 (e.g. 'fifty' -> 23 * 10 - 180 = 50)
        :                 //     else:
          n * 99          //       multiply n by 100 by adding 99 * n to itself
      ),                  //
    ''                    //   remove this word from the original string
  )                       //

11

Perl 6 , 1701391281212412212 bayt

Nwellnhof sayesinde -13 bayt!

{S:g/(<:N>+)+%\s/({'+'X$0})/.EVAL}o{S:g/" ҈"/00/}o{TR"⁢ʼn؊⟠"*/൰ "}o*.words>>.&{chr first *.uniname.comb(.uc),1..*}

Çevrimiçi deneyin!

univaltekrar kurtarmaya! Bu (şu anda) gibi golf dillerini bile yeniyor 05AB1E!

Açıklama:

*.words     # Split by word boundaries (in this case spaces)
       >>.{                            }  # Map each word to
           chr first             ,1..*    # The first character where:
                     *.uniname      # The unicode name of that character
                                    # e.g. DIGIT FIVE
                      .comb(.uc)    # Contains the uppercase of the word
{             }o  # Pass this list to another function
                  # That converts the list to a string
 TR"⁢ʼn؊⟠"*/൰ "    #"# And parse out the garbage characters that were wrong
                  # INVISIBLE TIMES => "*"
                  # LOZENGE DIVIDED BY HORIZONTAL RULE => "/"
                  # ARABIC-INDIC PER TEN THOUSAND SIGN => "൰" (value ten)
                  # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE => " "
{S:g/" ҈"/00/}o   # Replace the character for "hundred" with 00

{                                }o   # And finally combine with
 S:g/(<:N>+)+%\s/   # Substitute each number-like character separated by spaces
                /({'+'X$0})/   # With the numbers prefixed by '+'s, in brackets
               # This works because Perl 6 supports numeric unicode literals, like
               # ፳ => 20, ፴ => 30, ፺ => 90, etc.
                            .EVAL   # And finally evaluate the whole expression

7

Python 2 , 333 ... 284 277 275 bayt

lambda s:eval(''.join((list('+-/*')+[`N(w,0)*100+N(w,2)`])['pmdt'.find(w)]for w in re.split(' *(?:(p|m)|(t|d)i|by).*? ',s)if w))
N=lambda x,y:sum(10*(w[-3:]in'lveen')+'zeontwthfofisiseeiniteel'.find(w[:2])/2*10**('y'in w)for w in x.rpartition('hundred')[y].split())
import re

Çevrimiçi deneyin!


5

Wolfram Dili 95 94 82 bayt

Interpreter["SemanticExpression"][#~StringReplace~{"me "->"mes ","plus m"->"m"}]&

# saf fonksiyonun girdisini temsil eder.

Gerekirse StringReplace" 'süreleri ile "zaman" yerine artı eksi '(aracılığıyla eksi' ile' "me "->"mes ", "plus m"->"m" sırasıyla). Tarafından önerilen kısaltılmış yedek formları, lirtosiast12 bayt tasarruf etti.

Interpreter["SemanticExpression"] gerisini halleder.


Değiştirmek Can "time "->"times "için "me"->"mes"ve "plus minus"->"minus"hiç "plus m"->"m"?
lirtosiast

Evet. Mükemmel öneriler.
DavidC

3

05AB1E , 166 147 141 139 135 bayt

„byK“¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“#vyN:}'tK'…§¦'+T«:'°¡„ *т«©:.•1×j›o!ĆÖ•3ôŽ9oS:'y®¨:©“‰´Øè„Æ€ººß“'tK#UX¡εð¡õK2ôJ.EO}®áX"+-**/"S:Sðì.ιJ.E

Çok uzun .. Buradan golf oynamaya çalışacağım.

@Emigna sayesinde -4 bayt . @JoKing
sayesinde -2 bayt .

Çevrimiçi deneyin veya tüm test senaryolarını doğrulayın .

Açıklama:

byK                 # Remove "by" from the (implicit) input-string
“¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“
                     # Push string "zero one two three four five six seven eight nine ten eleven twelve"
 #                   # Split by spaces
  v   }              # Loop over each of these items:
   yN:               #  Replace the item with its 0-indexed index
'tK                 '# Remove all "t"
'…§¦                '# Push string "teen", and remove the first character: "een"
    '+              '# Push string "+"
      T«             # Append 10: "+10"
        :            # Replace all "een" with "+10"
'°¡                 '# Push string "hundred"
    *               # Push string " *"
      т«             # Append 100: " *100"
        ©            # Store it in the register (without popping)
         :           # Replace all "hundred" with " *100"
.•4º»Ÿć'Rþн•        '# Push string "wenhirforfif"
            3ô       # Split the string into parts of size 3: ["wen","hir","for","fif"]
              Ž9o    # Push integer 2345
                 S   # Split to digits: [2,3,4,5]
                  :  # Replace each
'y                  '# Push string "y"
  ®                  # Push the " *100" from the register
   ¨                 # Remove the last character: " *10"
    :                # Replace all "y" with " *10"
©                    # Save the current string in the register (without popping)
 “‰´Øè„Æ€ººß“        # Push string "plus minus times time divided"
             'tK    '# Remove all "t": "plus minus imes ime divided"
                #    # Split by spaces: ["plus","minus","imes","ime","divided"]
                 U   # Pop and save it in variable `X`
                  X  # And push variable `X` back again
                   ¡ # Split the string by those operator-strings
ε          }         # Map each substring to:
 ð¡                  #  Split by spaces (NOTE: cannot be `#`; if the string contains no
                     #   spaces, `#` remains string, whereas `ð¡` wraps it in a list)
   õK                #  Remove empty strings from the list
     2ô              #  Split the list into parts of two
       J             #  Join each pair together
        .E           #  Evaluate each as a Python `eval` expression
          O          #  Sum them
®                    # Put the string from the register to the stack again
 á                   # Remove everything except for letters
  X                  # Push variable `X`: ["plus","minus","imes","ime","divided"]
   "+-**/"           # Push string "+-**/"
          S          # Split to characters: ["+","-","*","*","/"]
           :         # Replace each
S                    # Split the string of operators to loose characters
 ðì                  # Prepend a space before each
                   # Interweave all sums with these operator-characters
     J               # Join everything together to a single string
.E                   # Evaluate each as a Python `eval` expression (and output implicitly)

Benim bu 05AB1E ucu bakın (bölümler Nasıl sözlüğü kullanılır? , Nasıl sözlük kompres dizeleri değil parçası? Ve ne kadar büyük tamsayılar sıkıştırmak için? ) Anlamak için “¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“, '…§, '°¡, .•4º»Ÿć'Rþн•, Ž9o, ve “‰´Øè„Æ€ººß“işi.

Adım adım örnek:

  • Giriş: two hundred twenty two divided by two times minus fifty seven plus three hundred eighteen minus minus ten
  • Adım 1: "Tarafından" kaldırın: two hundred twenty two divided two times minus fifty seven plus three hundred eighteen minus minus ten
  • 2. Adım: "Sıfır" ı "oniki" ile doğru numaraya dönüştürün: 2 hundred twenty 2 divided 2 times minus fifty 7 plus 3 hundred 8een minus minus 10
  • Adım 3: Tüm "t" leri kaldırın: 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8een minus minus 10
  • Adım 4: Tüm "een" leri "+10" ile değiştirin: 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8+10 minus minus 10
  • 5. Adım: Tüm "yüz" ifadelerini "* 100" ile değiştirin: 2 *100 weny 2 divided 2 imes minus fify 7 plus 3 *100 8+10 minus minus 10
  • Adım 6: "," fif "] için tüm [" wen "," hir "," yerine doğru haneyi yerleştirin: 2 *100 2y 2 divided 2 imes minus 5y 7 plus 3 *100 8+10 minus minus 10
  • Adım 7: Tüm "y" yerine "* 10" yazın: 2 *100 2 *10 2 divided 2 imes minus 5 *10 7 plus 3 *100 8+10 minus minus 10
  • Adım 8: ["artı", "eksi", "ime", "imes", "bölünmüş"] ile bölün: ["2 *100 2 *10 2 "," 2 "," "," 5 *10 7 "," 3 *100 8+10 "," "," 10"]
  • Adım 9: Her birini boşluklara ayırın: [["2","","*100","2","*10","2",""],["","","2",""],["",""],["","5","*10","7",""],["","3","","*100","8+10",""],["",""],["","10"]]
  • 10. Adım: Boş öğeleri kaldırın: [["2","*100","2","*10","2"],["2"],[],["5","*10","7"],["3","*100","8+10"],[],["10"]]
  • Adım 11: 2 boyutlu parçalara bölün ve katılın: [["2*100","2*10","2"],["2"],"",["5*10","7"],["3*100","8+10"],"",["10"]]
  • Adım 12: evalHer birini pitonla :[[200,20,2],[2],"",[50,7],[300,18],"",[10]]
  • 13. Adım: Her birini toplayın: [222,2,"",57,318,"",10]
  • Adım 14: Dizeyi kayıttan yeniden itin ve harfler hariç her şeyi kaldırın: dividedimesminusplusminusminus
  • Adım 15: "Artı", "eksi", "imes", "ime", "bölünmüş" ifadelerini operatör karakterleriyle değiştirin ve bir boşlukla değiştirin: [" /"," *"," -"," +"," -"," -"]
  • Adım 16: İç içe geçin ve her ikisini de birleştirin: 222 /2 * -57 +318 - -10
  • Çıktı: Dizeyi Python evalve dolaylı olarak çıktı:-5999.0

Sıfırdan bir çözüm yapmaya çalışmadım veya ayrıntılı olarak kendiniz çalıştım, ama bir golf fark ettim .
Emigna

@Emigna Teşekkürler!
Kevin Cruijssen

2

SFK , 572 449 423 bayt

Bunların hepsi bir satır olabilir, ancak okumak amacıyla boşluk yerine satırsonu kullandım.

xed -i
_plus_+_
_minus_-_
_times[ortext]time_*_
_divided?by_/_
+xed
"_[white][2 chars of a-z][chars of a-z]ty_[parts 1,2]0_"
"_[white][2 chars of a-z][chars of a-z]een_[part1]1[part2]_"
_ten_10_
_lev_11_
_twe_12_
+xed
_ze_0_
_on_1_
_tw_2_
_th_3_
_fo_4_
_fi_5_
_si_6_
_se_7_
_ei_8_
_ni_9_
+xed
_0[white][keep][digit]__
"_[chars of e-z ]__"
+xed
"_?dd[keep][2 digits]_[part1]_"
_?dd[keep][digit]_[part1]0_
_dd_00_
+calc #text

Çevrimiçi deneyin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.