29
\$\begingroup\$

Write a function or program than can do simple arithmetic (addition, subtraction, multiplication and division) in both base 10 and base 2.

The function will take a mathematical expression as input, and output the correct result in the correct base. The input will be n numbers separated by one or several operators (+ - * /).

If all input values contain only 0 and 1, all values are considered to be binary. If at least one digit is 2-9, all values are considered to be base 10.

Rules:

  • You can assume there will only be one operator between numbers (10*-1 will not appear)
  • You can assume there will be no parentheses.
  • Normal operator precedence (try the expression in the google calculator if you're in doubt).
  • You can not assume there will only be integers
  • There will be no leading zeros in input or output
  • You can assume only valid input will be given
  • You can assume all input values are positive (but the minus operator may make negative output possible, 1-2=-1 and 10-100=-10)
  • REPL is not accepted
  • You may choose to take the input as separate arguments, or as a single argument, but the input has to be in the correct order.
    • I.e. you may represent 1-2 with the input arguments 1, -, 2, but not 1, 2, -.
  • You must accept the symbols + - * / in the input, not plus, minus etc.
  • You must support floating point values (or up to the maximum limit of your language, however supporting only integers is not accepted).
  • eval is accepted

Examples:

1+1
10

1010+10-1
1011

102+10-1
111

1+2+3
6

10*10*10
1000

11*11*11
11011

10*11*12+1
1321

10.1*10.1
110.01

20.2*20.2
408.04

10/5
2

110/10
11

Also accepted (optional line or comma-separated input):
10
+
10
-
1
11    <-- This is the output

This is code golf, so the shortest code in bytes will win.

\$\endgroup\$
3
  • \$\begingroup\$ In the case of 110/10, is 11.0 acceptable? \$\endgroup\$
    – isaacg
    Jan 3, 2016 at 15:16
  • \$\begingroup\$ @isaacg yes, that's ok :-) \$\endgroup\$ Jan 3, 2016 at 15:56
  • 7
    \$\begingroup\$ The downvote... why? \$\endgroup\$ Jan 4, 2016 at 8:55

6 Answers 6

9
\$\begingroup\$

JavaScript ES6, 87 971 1002 1063 102 101 98 1004 93 88 86 bytes

e=>eval(e.match`[2-9]`?e:`(${e.replace(/[\d.]+/g,"('0b'+$&e14)/16384")}).toString(2)`)

Demo + explanation:

function c(e){
    return eval(                        
      e.match`[2-9]`?                  //check if there are numbers 2 to 9
        e:                             //if there're, just compute the result
        "("+                           
         e.replace(                    //otherwise replace...
           /[\d.]+/g,                  //any number...
           "(('0b'+$&e14)/16384)"    //...with itself converted to base 10
         )
        +").toString(2)"               //compute the result and convert it to binary
    )
}

document.write(
   c("1.1*1.1")+"<br>"+
   c("1010+10-1")+"<br>"+
   c("102+10-1")+"<br>"+
   c("1+2+3")+"<br>"+
   c("10*10*10")+"<br>"+
   c("11*11*11")+"<br>"+
   c("10*11*12+1")+"<br>"+
   c("10.1*10.1")+"<br>"+
   c("20.2*20.2")+"<br>"+
   c("10/5")+"<br>"+
   c(`10
      +
      10
      -
      1`)
)


1 - forgot about floats
2 - again floats problem: parseInt floors binary so I have to multiply by 1e14 and then divide by 16384
3 - hope that's achieved the given task, now start to golf :D
4 - there was a bug with dividing

\$\endgroup\$
11
  • 10
    \$\begingroup\$ 106^3 bytes? That's more than a million! \$\endgroup\$ Jan 3, 2016 at 14:28
  • 2
    \$\begingroup\$ @Eth I knew such a comment was coming ;D \$\endgroup\$
    – nicael
    Jan 3, 2016 at 14:29
  • \$\begingroup\$ You can change e.match(/[2-9]/g) to e.match`[2-9]`. \$\endgroup\$
    – user81655
    Jan 3, 2016 at 15:20
  • \$\begingroup\$ @nicael ('0b'+$&*1e14)/1638 this should work but I'm not 100% sure \$\endgroup\$
    – Downgoat
    Jan 3, 2016 at 17:13
  • \$\begingroup\$ @Doᴡɴɢᴏᴀᴛ Hah, here it is :) Seems to work properly. \$\endgroup\$
    – nicael
    Jan 3, 2016 at 17:17
5
\$\begingroup\$

Japt, 77 72 62 60 62* 60 59 51 bytes

OvUf"[2-9]" ?U:"({Ur"[\\d.]+""º$&e14+P n2 /2pE¹"})¤

Explanation (more or less the same as for the JS answer):

Ov                       //eval...
  Uf"[2-9]"              //if input contains the digits 2 to 9
    U:                   //then it's base 10, just compute
    Ur"[\\d.]+"          //otherwise replace all the numbers
    "º$&e14+P n2 /2pE¹"  //with their base 10 equivalents
                         //I.e., take every number, multiple by 10^14, convert to
                         //base 10 and divide by 2^14
                         // º and ¹ are multiple brackets
    ¤                    //means "s2", i.e. convert the result to binary
                 

Try it online!


* didn't divide properly

\$\endgroup\$
10
  • \$\begingroup\$ As of 5 days ago, JS's eval is assigned to Ox. I'll see if it can be further shortened. \$\endgroup\$ Jan 3, 2016 at 16:27
  • \$\begingroup\$ @Eth Thanks, this saves 5 bytes. \$\endgroup\$
    – nicael
    Jan 3, 2016 at 16:43
  • \$\begingroup\$ 5 more bytes saved: OxUf"[2-9]" ?U:`({Ur"\\d+(\\.\\d+)?""(($&e14+P).n(2)/16384)"}).s(2) It's probably possible to make it generate Japt code instead of JS, then use Ov to evaluate that. \$\endgroup\$ Jan 3, 2016 at 16:48
  • \$\begingroup\$ Yup, 62 bytes :) OvUf"[2-9]" ?U:Ur"\\d+(\\.\\d+)?""~~[$&e14+P n2 /16384]" +" s2 The ~~[...] is necessary because mismatched parentheses in a string mess with the transpiler. \$\endgroup\$ Jan 3, 2016 at 16:53
  • 1
    \$\begingroup\$ 51: OvUf"[2-9]" ?U:"({Ur"[\\d.]+""º$&e14+P n2 /2pE¹"})¤ \$\endgroup\$ Jan 3, 2016 at 19:12
5
\$\begingroup\$

Jolf, 31 bytes, noncompeting

I added a decent amount of functions inspired by this challenge, and, as thus, it is considered noncompeting. I'm happy because I finally implemented unary functions (like (H,S,n)=>val in ES6, but are supported in ES5!)

? hi"[2-9]"~eiB~epT mpvid|m'H2H
? hi"[2-9]"                     if the input contains any of 2..9
           ~ei                   evaluate i (implicitly print)
                                else
                   _mpvid        map the input split into number groups
                          m'H2    to H as a binary float
                         |    H   (or keep H, if that doesn't work)
                 pT              join by spaces
               ~e                evaluate
              B                  convert to binary (implicitly print)

Test suite, Try your own input, or manually set the input.

\$\endgroup\$
2
  • 4
    \$\begingroup\$ Your code says "hi" to its readers! \$\endgroup\$
    – Cyoce
    Jan 4, 2016 at 7:48
  • \$\begingroup\$ Wow. I didn't notice that! :D \$\endgroup\$ Jan 4, 2016 at 12:00
5
\$\begingroup\$

Bash, 60 bytes

[ -z `tr -dc 2-9<<<$1` ]&&s='obase=2;ibase=2;';bc -l<<<$s$1

Example Run:

$ ./bin_dec_add.sh 1+1
10
$ ./bin_dec_add.sh 1+2
3
\$\endgroup\$
1
  • \$\begingroup\$ @Pietu1998 dc would require reverse polish ordering of the operations, which is disallowed by the challenge. \$\endgroup\$
    – Tyzoid
    Jan 5, 2016 at 15:52
3
\$\begingroup\$

𝔼𝕊𝕄𝕚𝕟 2, 46 chars / 72 bytes

ë(ïđ/[2-9]⎞?ï:`(⦃ïē/[\d.]+⌿,↪(Յ+$*ḊⁿḎ)/Ẁ²)})ⓑ`

Try it here (Firefox only).

Explanation

ë(ïđ/[2-9]⎞?ï:`(⦃ïē/[\d.]+⌿,↪(Յ+$*ḊⁿḎ)/Ẁ²)})ⓑ` // implicit: ï=input, Ḋ=10, Ḏ=14, Ẁ=128
ë(                                              // eval
  ïđ/[2-9]⎞?                                    // does ï have 2-9?
            ï                                   // if so, eval input
             :                                  // else, eval:
              `(⦃ïē/[\d.]+⌿,                    // replace the binary numbers
                                                // with their base 10 equivalents:
                            ↪(Յ+                // translates to `0b`
                                $*ḊⁿḎ           // matched number * 10^14
                                     )/Ẁ²       // divided by 128^2
                                         )})ⓑ` // converted to binary
                                                // implicit output
\$\endgroup\$
1
\$\begingroup\$

PowerShell, 107 bytes

param($e)iex(("{0}String($($e-replace'(\d+)','{0}Int32("$1",2)'),2)"-f'[Convert]::To'),$e)[$e-match'[2-9]']

Ungolfed

param($e) # Accept single argument
Invoke-Expression # Eval
  ( # Expression, resulting in an array of 2 elements
    (
      "{0}String( # Binary
        $( # Inline subexpression
          $e -replace'(\d+)', '{0}Int32("$1",2)'
          # "1010+10-1" becomes "{0}Int32("1010",2)+{0}Int32("10",2)-{0}Int32("1",2)"
        )
      ,2)"
      -f '[Convert]::To'
      # "{0}Int32("1010",2)+{0}Int32("10",2)-{0}Int32("1",2)" becomes
        "[Convert]::ToString([Convert]::ToInt32("1010",2)+[Convert]::ToInt32("10",2)-[Convert]::ToInt32("1",2),2)"
    ),
      $e # Plain
    )
    [$e-match'[2-9]'] # Return 1st element of array if regex matches, else 0

Example

PS > .\Calc.ps1 1010+10-1
1011

PS > .\Calc.ps1 20.2*20.2
408,04
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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