6
\$\begingroup\$

Word equations, but not as you know it! Given a sentence which will include two numbers, numerically, and a spelt operator, in the order seen in the examples, your goal is to give the numerical answer

The operators will be spelt as: "add", "minus", "times" and "divide"

Any real number integer may be used, as suggested by caird and Jonathan

The solution must take one input and give one output

Examples:

Input: 7 add 8         Output: 15
Input: 9 times -2      Output: -18
Input: 24 divide 2     Output: 12
Input: 4 minus 5       Output: -1

You are not required to deal with divide by zero errors.

If you use a method that parses the expression, such as the python eval or exec, there will be no penalties, but if possible try to give a another interesting solution

Scoring:

Fewest bytes will win

\$\endgroup\$
11
  • 1
    \$\begingroup\$ Can we take input as [7, 'add', 8]? Or, perhaps less reasonably, as [7, 8] for one input, and 'add' as a second input? \$\endgroup\$ Sep 15, 2021 at 18:17
  • \$\begingroup\$ @cairdcoinheringaahing the first one yes, as its still one input, the list, and it the correct order, but the second one no \$\endgroup\$
    – george
    Sep 15, 2021 at 18:19
  • \$\begingroup\$ @hyper-neutrino that's a fair point, I'm going to change it but leave a comment about it \$\endgroup\$
    – george
    Sep 15, 2021 at 18:33
  • \$\begingroup\$ @JonathanAllan Real numbers positive or negative rational numbers \$\endgroup\$
    – george
    Sep 15, 2021 at 18:37
  • 2
    \$\begingroup\$ It might be simpler just to limit the input to integers. I doubt it'll change any potential methods, but using "reals" or "decimals" can lead you to spend time/effort into specifying details such as format and precision, and using integers can allow more languages to take part that may not support floats/reals/decimals as easily \$\endgroup\$ Sep 15, 2021 at 18:46

16 Answers 16

7
\$\begingroup\$

Jelly, 14 bytes

Ḣ€Oị2¦“×+ _÷”V

Try it online!

Takes input as e.g. [7, 'add', 8]. Requires no leading 0 for floats (e.g. -.5 instead of -0.5)

How it works

Ḣ€Oị2¦“×+ _÷”V - Main link. Takes a list [l, op, r]
Ḣ€             - First of each.
  O            - Convert to ordinal
    2¦         - To the element at the 2nd index (the op):
   ị  “×+ _÷”  - Index into the string “×+ _÷”
             V - Evaluate as Jelly

For example, consider [7, 'add', 8]. Getting the ead of a number leaves it as is in Jelly, so Ḣ€ turns this into [7, 'a', 8]. We then get the char code of each. Again, O leaves numbers as they are, so this maps it to [7, 97, 8]. We then change only the second element by indexing into “×+ _÷”. Jelly indexing is modular, so we get the \$97 \bmod 5\$th element of this list (i.e. the second, or +). This yields [7, '+', 8], which we then concatenate into a string 7+8 and evaluate as Jelly.

Consider:

Input operator First character Ordinal \$\bmod 5\$ Index into “×+ _÷”
add a 97 2 +
times t 116 1 ×
minus m 109 4 _
divide d 100 0 ÷

Note that 0 maps to ÷ as 1-indexed modular indexing means that 0 is the last element

\$\endgroup\$
0
3
\$\begingroup\$

Factor, 53 bytes

[ first3 swap first 5 mod { / * + 0 - } nth execute ]

Try it online!

This is a port of @caird coinheringaahing's Jelly solution.

Explanation:

It is a quotation (anonymous function) that takes a list of objects from the data stack as input and leaves an integer on the data stack as output. Assuming { 7 "add" 8 } is on the data stack when this quotation is called...

  • first3 Put the first three elements of a sequence on the data stack.

    Stack: 7 "add" 8

  • swap Swap the top two objects on the data stack.

    Stack: 7 8 "add"

  • first Get the first element of a sequence. (In this case, get the first code point of the string "add".)

    Stack: 7 8 97

  • 5 mod Modulo 5.

    Stack: 7 8 2

  • { / * + 0 - } Push a sequence with the possible mathematical functions. 0 is a filler that will never be selected because 3 is not a possible index.

    Stack: 7 8 2 { / * + 0 - }

  • nth Take an index and a sequence and return the object at that index.

    Stack: 7 8 +

  • execute Execute a word that is on the data stack.

    Stack: 15

\$\endgroup\$
3
\$\begingroup\$

C (gcc), 86 \$\cdots\$ 74 73 bytes

m;a;b;f(){scanf("%d %c%*s%d",&a,&m,&b);m%=5;a=m?m-1?m-2?a-b:a+b:a*b:a/b;}

Try it online!

Saved a byte thanks to tsh!!!

Inputs the equation as a string from stdin.
Returns the value of the input equation.

Allowing three parameters:

As allowed for untyped languages like this PHP answer.

C (gcc), 54 52 51 bytes

f(a,s,b)int*s;{a=(int[]){a/b,a*b,a+b,0,a-b}[*s%5];}

Try it online!

Saved 2 bytes thanks to the man himself Arnauld!!!
Saved a byte thanks to Johan du Toit!!!

\$\endgroup\$
5
  • \$\begingroup\$ 52 btyes \$\endgroup\$
    – Arnauld
    Sep 16, 2021 at 12:48
  • \$\begingroup\$ @Arnauld That's brilliant - thanks! :D \$\endgroup\$
    – Noodle9
    Sep 16, 2021 at 12:57
  • \$\begingroup\$ @JohanduToit Seeing as separate parameters are only allowed for those untyped languages that can extract them in order and this already is pushing past that boundary, think it's best to keep them in order. But nice one - thanks! :D \$\endgroup\$
    – Noodle9
    Sep 17, 2021 at 20:15
  • \$\begingroup\$ Maybe, the 74 bytes version, "%d %c%*s%d" is correct. \$\endgroup\$
    – tsh
    Sep 22, 2021 at 7:53
  • \$\begingroup\$ @tsh Nice one - thanks! :D \$\endgroup\$
    – Noodle9
    Sep 22, 2021 at 9:26
3
\$\begingroup\$

AWK, 41 38 bytes

$0=/a/?$1+$3:/t/?$1*$3:/v/?$1/$3:$1-$3

Try it online!

Thanks to Dominic van Essen for the clue that cut 3 chars!

$0=                                     -- Override $0, prints automatically
   /a/?$1+$3:                           -- If there's an "a" we add them
             /t/?$1*$3:                 -- If there's a "t" it's multiplication
                       /v/?$1/$3:       -- If there's a "v" it's division
                                 $1-$3  -- It must be subtraction...

If we have to make sure it will print in the event the operation yields 0 then it would be 2 characters longer, like this.

1,$0=/a/?$1+$3:/t/?$1*$3:/v/?$1/$3:$1-$3
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Do you actually need the second $0=? Without it seems to work Ok for 3 bytes less... \$\endgroup\$ Oct 1, 2021 at 21:52
  • \$\begingroup\$ Good catch, thanks! \$\endgroup\$
    – cnamejj
    Oct 2, 2021 at 7:19
2
\$\begingroup\$

JavaScript (ES6), 56 bytes

Expects a string.

s=>([a,[b],c]=s.split` `,{a:a-+-c,t:a*c,d:a/c,m:a-c}[b])

Try it online!


JavaScript (ES6), 43 bytes

Expects [a, "operator", b].

([a,[b],c])=>({a:a+c,t:a*c,d:a/c,m:a-c})[b]

Try it online!

Or 41 bytes if we can take 3 distinct parameters as input (as suggested by Shaggy).

\$\endgroup\$
3
  • \$\begingroup\$ Does taking input in the format [7,'add',8] save bytes? \$\endgroup\$ Sep 15, 2021 at 19:00
  • \$\begingroup\$ @cairdcoinheringaahing I've added a version using that format. \$\endgroup\$
    – Arnauld
    Sep 15, 2021 at 19:31
  • \$\begingroup\$ You could take them as individual arguments to save another byte, although you may want to ask for confirmation that that would be allowed. \$\endgroup\$
    – Shaggy
    Sep 16, 2021 at 12:17
2
\$\begingroup\$

Java (JDK), 50 bytes

(a,o,b)->o[0]<98?a+b:o[0]<'e'?a/b:o[0]<'n'?a-b:a*b

Try it online!

Input is a int, char[], int.

  • -36 bytes from @ceilingcat
  • -49 bytes from @Kevin Cruijssen

Orignal: Java (JDK), 135 bytes

int o(int a,String o,int b){switch(o.charAt(0)){case'a':return a+b;case'm':return a-b;case't':return a*b;case'd':return a/b;}return 0;}

Try it online!

Simple switch

\$\endgroup\$
1
1
\$\begingroup\$

Python3 142 bytes

def f():
a,b,c=input().split(' ');x=b[0];i=int(a);j=int(c);z=i+j if x=='a' else i*j if x=='t' else int(i/j) if x=='d' else i-j;print(z)

Splits tokens, applies operator and prints result

\$\endgroup\$
1
1
\$\begingroup\$

Python 2, 83 bytes

exec'print '+''.join([`x`,'/*+ -'[ord(str(x)[0])%5]][type(x)==str]for x in input())

Try it online!

\$\endgroup\$
1
1
\$\begingroup\$

PHP, 55 bytes

fn($a,$b,$c)=>[$a/$c,$a*$c,$a+$c,0,$a-$c][ord($b[0])%5]

Try it online!

uses the format [7, 'add', 8]

Nothing new under the sun, combines the tricks used in other answers.

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 95 bytes

Fixed and -2 bytes thanks to Arnauld.

Not too fancy, uses scanf and abuses memory by writing the whole string at the address of a char, mod 5 to get b in single digit range, then ternaries to pick the result.

I had a 0 as the true value for the innermost ternary.... But somehow gcc is perfectly happy without it, if anyone can explain how that works I would appreciate the comment.

a,c;main(){char b;scanf("%d %s %d",&a,&b,&c);b%=5;printf("%d",b-2?b-4?b-1?b?:a/c:a*c:a-c:a+c);}

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Lol... for some reason I used add subtract multiply and divide. Fixed! Thanks for the correction. \$\endgroup\$
    – M Virts
    Sep 16, 2021 at 13:28
1
\$\begingroup\$

Pip, 16 bytes

VaR+XL"/*+ -"@A_

Takes input as a single command-line argument. Try it online!

Explanation

Uses the same "character code mod 5" trick as several other answers.

 a                ; First command-line argument
  R               ; Replace all occurrences of
   +XL            ; the regex [a-z]+ (run of lowercase letters)
                  ; with the following callback function:
              A_  ;  ASCII code of the first character
      "/*+ -"@    ;  used as a (cyclical) index into that string
V                 ; After replacing, evaluate the resulting string as a Pip expression

If taking input as three separate arguments is allowed (e.g. if you can just type python pip.py equation.pip 9 times -2 on the command line), then it's 15 bytes:

Va."/*+ -"@Ab.c

Try it online!

And here's a solution without eval (using three separate arguments) in 18 bytes:

[a/ca*ca+c0a-c]@Ab

Try it online!

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 15 14 bytes

ι˜`¨C"*+-÷"è.V

Input as a list.

Try it online or verify all test cases.

Explanation:

ι               # Uninterleave the (implicit) input-list:
                #  [a,"O",b] becomes [[a,b],["O"]]
 ˜              # Flatten this list: [a,b,"O"]
  `             # Pop and push the three values separated to the stack
   ¨            # Remove the last character of the operator string
    C           # Convert it from a binary string to an integer
     "*+-÷"è    # Modulair 0-based index it into string "*+-÷"
            .V  # Evaluate it as 05AB1E code
                # (after which the result is output implicitly)
String ¨ C Modulair 0-based index Operator
and an 121 1 +
minus minu 714 2 -
times time 752 0 *
divide divid 1331 3 ÷

C on strings basically gets the index of each characters in the string 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzǝʒαβγδεζηθвимнт ΓΔΘιΣΩ≠∊∍∞₁₂₃₄₅₆ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~Ƶ€Λ‚ƒ„…†‡ˆ‰Š‹ŒĆŽƶĀ‘’“”–—˜™š›œćžŸā¡¢£¤¥¦§¨©ª«¬λ®¯°±²³\nµ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ•, and then converts this list of indices to a base-2 integer.

\$\endgroup\$
1
\$\begingroup\$

Japt, 15 bytes

Takes input as an array. Thought there might be some other clever way of working with the charcodes to get the required operator but using caird's method of indexing into the operators seems to be optimal.

OvUg1_Îcg"/*+ -

Try it

Or without using eval:

rUj1 ÎÎcg"/*+ -

Try it

OvUg1_Îcg"/*+ -     :Implicit input of array U
Ov                  :Eval as Japt
  Ug1               :  Modify the element at 0-based index 1 in U
     _              :  By passing it through the following function
      Î             :    First character
       c            :    Charcode
        g"/*+ -     :    Index into "/*+ -"
rUj1 ÎÎcg"/*+ -     :Implicit input of array U
r                   :Reduce by
 Uj1                :  Remove & return, as a singleton array, the element at 0-based index 1 in U
     Î              :  First element
      Îcg"/*+ -     :  As above
\$\endgroup\$
1
\$\begingroup\$

Python 3, 91 bytes

def f(a):a,b,c=a;b=b[0];d=b=='d';return(a+c*((b=='a')-(b=='m')))*[1,[c,1/c][d]][b=='t'or d]

Takes a single input as a listed of the values, i.e. [7, "add", 8] and returns the result of the equation.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Python 3, 71 bytes

x,y,z=input().split()
print(eval(f'{x}{"/*+ -"[ord(str(y)[0])%5]}{z}'))

Try it online!

Inspired by various other answers featuring ord(str(y)[0])%5.

If the input is taken as a list like [5, 'minus', 8], then you can get an answer of only 67 bytes;

lambda l:print(eval(f'{l[0]}{"/*+ -"[ord(str(l[1])[0])%5]}{l[2]}'))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Charcoal, 26 bytes

Nθ≡§S⁰aI⁺θNmI⁻θNtI×θNdI∕θN

Try it online! Link is to verbose version of code. Explanation: Inputs the first number, switches on the string then inputs the second number as it outputs the result of the appropriate operation. 20 bytes with a boring eval-based approach:

IUV⁺θ⁺§+-*/⌕amtd§η⁰ζ

Try it online! Link is to verbose version of code. Explanation: Gets the appropriate Python operator depending on the first letter of the string and evaluates the result as a Python expression.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.