1+1 = 10, 1+2 = 3

26

1

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.

Stewie Griffin

Posted 2016-01-03T13:41:03.753

Reputation: 43 471

In the case of 110/10, is 11.0 acceptable? – isaacg – 2016-01-03T15:16:43.850

@isaacg yes, that's ok :-) – Stewie Griffin – 2016-01-03T15:56:07.797

5The downvote... why? – Stewie Griffin – 2016-01-04T08:55:12.587

Answers

5

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

nicael

Posted 2016-01-03T13:41:03.753

Reputation: 4 585

As of 5 days ago, JS's eval is assigned to Ox. I'll see if it can be further shortened.

– ETHproductions – 2016-01-03T16:27:36.497

@Eth Thanks, this saves 5 bytes. – nicael – 2016-01-03T16:43:59.413

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. – ETHproductions – 2016-01-03T16:48:17.477

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.

– ETHproductions – 2016-01-03T16:53:58.467

@Eth Heh, I've come with another 62 bytes solution thanks to the Ov – nicael – 2016-01-03T16:55:43.713

16384 => 2pE ;) – ETHproductions – 2016-01-03T17:00:34.617

@Ethprod Exactly! – nicael – 2016-01-03T17:02:52.193

151: OvUf"[2-9]" ?U:"({Ur"[\\d.]+""º$&e14+P n2 /2pE¹"})¤ – ETHproductions – 2016-01-03T19:12:26.053

@Eth yep, shortening this too, but didn't think about ¤ – nicael – 2016-01-03T19:13:51.970

(sorry for late) You can save 1 byte on using %d instead of \\d (PS: This is 51 chars, but 54 bytes due to use of multibyte characters) – RedClover – 2017-10-04T18:20:15.407

9

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

nicael

Posted 2016-01-03T13:41:03.753

Reputation: 4 585

10106^3 bytes? That's more than a million! – ETHproductions – 2016-01-03T14:28:42.107

2@Eth I knew such a comment was coming ;D – nicael – 2016-01-03T14:29:04.073

You can change e.match(/[2-9]/g) to e.match\[2-9]``. – user81655 – 2016-01-03T15:20:10.477

@user Thanks :) – nicael – 2016-01-03T15:22:04.660

@nicael ('0b'+$&*1e14)/1638 this should work but I'm not 100% sure – Downgoat – 2016-01-03T17:13:00.277

@Doᴡɴɢᴏᴀᴛ Hah, here it is :) Seems to work properly. – nicael – 2016-01-03T17:17:10.620

/\d+(\.\d+)?/g => /[\d.]+/g? – ETHproductions – 2016-01-03T19:05:31.050

@Eth Haha, didn't even think that there're not so many characters that the regex should be that strict, nice solution :) – nicael – 2016-01-03T19:09:04.803

@nicael, very nice. It might have been unclear in the question text, but the input with line breaks was optional in case your language/program/function couldn't handle a one-line input. I don't know if you're using extra chars to support the last example, but if you do: It's not necessary, so you can shorten your code a bit =) – Stewie Griffin – 2016-01-04T07:34:14.540

@Stewie No extra chars, that's a feature of JavaScript when using template strings. Note how the last example is wrapped in \`` instead of"` :) – nicael – 2016-01-04T08:35:46.927

Hmm, weird syntax highlighting bug: in the explanation line that starts with a regex, the parser thinks the second slash starts the regex, not the first. Thus, the comment is black instead of grey. – ETHproductions – 2016-01-05T16:57:01.923

@Eth Yeah, noticed this. – nicael – 2016-01-05T17:07:20.490

5

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.

Conor O'Brien

Posted 2016-01-03T13:41:03.753

Reputation: 36 228

4Your code says "hi" to its readers! – Cyoce – 2016-01-04T07:48:43.627

Wow. I didn't notice that! :D – Conor O'Brien – 2016-01-04T12:00:50.940

5

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

Tyzoid

Posted 2016-01-03T13:41:03.753

Reputation: 692

@Pietu1998 dc would require reverse polish ordering of the operations, which is disallowed by the challenge. – Tyzoid – 2016-01-05T15:52:39.720

3

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

Mama Fun Roll

Posted 2016-01-03T13:41:03.753

Reputation: 7 234

1

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

beatcracker

Posted 2016-01-03T13:41:03.753

Reputation: 379