Calculatrice Worded

14

Une version simpliste de la calculatrice numérique anglaise

Tâche

Écrivez un programme qui prend une chaîne en entrée et génère le résultat de l'expression.

Règles

La chaîne d'entrée sera libellée et non numérique.

Il n'y aura pas de parenthèses.

L'ordre de calcul sera diviser, multiplier, soustraire puis ajouter.

Pour les mêmes opérations, les calculs doivent être effectués de gauche à droite.

Tous les nombres entrés seront des entiers de -999 à 999 (les deux inclus)

La sortie sera un entier de n'importe quelle plage.

La division sera toujours parfaitement divisible et zéro ne sera jamais un dénominateur.

La restriction de cas pour l'entrée est facultative. Vous n'avez pas à vérifier la validité de l'entrée.

Format de nombre

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

Pour les nombres négatifs: ajouter minusà son équivalent positif

Format d'opération

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

Exemples:

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

C'est le code-golf donc le code le plus court gagne

Vedant Kandoi
la source
1
Dupliquer? - Je pense que c'est assez proche pour être considéré comme tel.
Kirill L.
2
C'est très proche en effet. Mais je pense que celui-ci est mieux spécifié et a des limitations plus raisonnables.
Arnauld
1
@Arnauld Je garderai cela ouvert alors mais si les autres pensent différemment, marquez-le simplement comme doublon.
Vedant Kandoi
15
Dis-je one times two. Utilise timenormal?
Jo King
2
Je pense que vous vouliez dire «une fois de sept cents?
ouflak

Réponses:

18

JavaScript (ES6), 257 252 249 235 octets

Enregistré 3 octets grâce à @Shaggy

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)

Essayez-le en ligne!

Comment?

WLjeW+L+W

Nombres

 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"

Les opérateurs

 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"

Interprétation

nje

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
  )                       //
Arnauld
la source
11

Perl 6 , 170 139 139 129 128 124 122 octets

-13 octets grâce à nwellnhof!

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

Essayez-le en ligne!

univalà la rescousse! Cela bat (actuellement) même des langues de golf comme05AB1E !

Explication:

*.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
Jo King
la source
7

Python 2 , 333 ... 284 277 275 octets

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

Essayez-le en ligne!

TFeld
la source
5

Langue Wolfram 95 94 82 octets

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

# représente l'entrée pour la fonction pure.

Si nécessaire, StringReplaceremplace "time" par times "," plus moins "par" moins "(through "me "->"mes ", "plus m"->"m", respectivement). Les formulaires de remplacement raccourcis, suggérés par lirtosiast, ont permis d'économiser 12 octets.

Interpreter["SemanticExpression"] fait tout le reste.

DavidC
la source
Pouvez-vous changer "time "->"times "vers "me"->"mes"et "plus minus"->"minus"vers "plus m"->"m"?
lirtosiast
Oui. Excellentes suggestions.
DavidC
3

05AB1E , 166 147 141 139 135 octets

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

Beaucoup trop longtemps .. J'essaierai de jouer au golf d'ici.

-4 octets grâce à @Emigna .
-2 octets grâce à @JoKing .

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

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)

Voir cette astuce de mes 05AB1E (sections Comment utiliser le dictionnaire? , Comment les chaînes Compresser ne fait pas partie du dictionnaire? Et Comment compresser les grands entiers? ) Pour comprendre comment“¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“,'…§,'°¡,.•4º»Ÿć'Rþн•,Ž9oet“‰´Øè„Æ€ººß“ le travail.

Exemple étape par étape:

  • Contribution: two hundred twenty two divided by two times minus fifty seven plus three hundred eighteen minus minus ten
  • Étape 1: supprimer "par": two hundred twenty two divided two times minus fifty seven plus three hundred eighteen minus minus ten
  • Étape 2: Convertissez "zéro" en "douze" avec le nombre correct: 2 hundred twenty 2 divided 2 times minus fifty 7 plus 3 hundred 8een minus minus 10
  • Étape 3: supprimez tous les "t": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8een minus minus 10
  • Étape 4: Remplacez tous les "een" par "+10": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8+10 minus minus 10
  • Étape 5: remplacez tous les "centaines" par "* 100": 2 *100 weny 2 divided 2 imes minus fify 7 plus 3 *100 8+10 minus minus 10
  • Étape 6: Remplacez tous ["wen", "hir", "for", "fif"] par le chiffre correct: 2 *100 2y 2 divided 2 imes minus 5y 7 plus 3 *100 8+10 minus minus 10
  • Étape 7: Remplacez tous les "y" par "* 10": 2 *100 2 *10 2 divided 2 imes minus 5 *10 7 plus 3 *100 8+10 minus minus 10
  • Étape 8: Diviser par ["plus", "moins", "ime", "imes", "divisé"]: ["2 *100 2 *10 2 "," 2 "," "," 5 *10 7 "," 3 *100 8+10 "," "," 10"]
  • Étape 9: Divisez chacun des espaces: [["2","","*100","2","*10","2",""],["","","2",""],["",""],["","5","*10","7",""],["","3","","*100","8+10",""],["",""],["","10"]]
  • Étape 10: supprimer les éléments vides: [["2","*100","2","*10","2"],["2"],[],["5","*10","7"],["3","*100","8+10"],[],["10"]]
  • Étape 11: Divisez en parties de taille 2 et joignez: [["2*100","2*10","2"],["2"],"",["5*10","7"],["3*100","8+10"],"",["10"]]
  • Étape 12: Python evalchacun:[[200,20,2],[2],"",[50,7],[300,18],"",[10]]
  • Étape 13: Additionnez chacun: [222,2,"",57,318,"",10]
  • Étape 14: Repoussez la chaîne du registre et supprimez tout sauf les lettres: dividedimesminusplusminusminus
  • Étape 15: Remplacez "plus", "moins", "imes", "ime", "divisé" par les caractères de l'opérateur et ajoutez-les par un espace: [" /"," *"," -"," +"," -"," -"]
  • Étape 16: entrelacer et joindre les deux ensemble: 222 /2 * -57 +318 - -10
  • Sortie: Python evalla chaîne, et sortie implicitement:-5999.0
Kevin Cruijssen
la source
Je n'ai pas essayé de faire une solution à partir de zéro ou étudié la vôtre en détail, mais j'ai remarqué un golf .
Emigna
@Emigna Merci!
Kevin Cruijssen
2

sfk , 572 449 423 octets

Cela pourrait être une seule ligne, mais pour les lire, j'ai utilisé des sauts de ligne au lieu d'espaces.

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

Essayez-le en ligne!

Οurous
la source