DEV Community

Cover image for Can you…? - Calculator

Can you…? - Calculator

Medea on May 20, 2022

Can you make a calculator in any language which DOES NOT use the +, -, *, / operators.

Anyone who does will get a shoutout on my next Can you post.

Collapse
 
ben profile image
Ben Halpern

Too lazy to figure out how to deal with the remainder in division, but here is a cut at a calculator in Ruby that doesn't use math operators.

def add(num_1, num_2)
  [num_1, num_2].sum
end

def multiply(num_1, num_2)
  arr = []
  num_1.times do |n|
    arr << num_2
  end
  arr.sum
end

def subtract(num_1, num_2)
  subtractable = num_2.positive? ? "-#{num_2}".to_i : num_2.to_s.gsub("-", "").to_i
  [num_1, subtractable].sum
end

def divide(num_1, num_2)
  arr = []
  while num_1 >= num_2
    arr << "whatever"
    num_1 = subtract(num_1, num_2)
  end
  arr.size
end
Enter fullscreen mode Exit fullscreen mode
Collapse
 
vulcanwm profile image
Medea

Wow .sum is a function in Ruby? That made it so easy.

Collapse
 
ben profile image
Ben Halpern

Yeah, that's sort of a cheat — but Ruby's like that 🤣

eval("10 + 10") also would have been a quick answer here, but that seemed just a bit too easy.

Thread Thread
 
vulcanwm profile image
Medea • Edited

Oh- wow

Collapse
 
katafrakt profile image
Paweł Świątkowski • Edited

Okay, let's do this without using sum or eval then 🙃

module Calculator
  DivisionByZero = Class.new(RuntimeError)

  module_function

  def add(x,y) = y.abs.times.
    reduce(x) {|acc,_| y > 0 ? acc.next : acc.pred }

  def sub(x,y) = y.abs.times.
    reduce(x) {|acc,_| y > 0 ? acc.pred : acc.next }

  def mult(x,y) = y.abs.times.
    reduce(0) {|acc,_| add(acc,x)}.
    then {|num| y < 0 ? invert(num) : num } 

  def div(x,y) 
    raise DivisionByZero if y.zero?

    divisor = y.abs
    val = x.abs
    times = 0
    while sub(val,divisor) >= 0
      val = sub(val,divisor)
      times = times.next
    end
    times = x >= 0 ? times : invert(times)
    y >= 0 ? times : invert(times)
  end

  def invert(x) = x > 0 ? sub(0,x) : x.abs
end

require 'rspec'

RSpec.describe(Calculator) do
  specify { expect(Calculator.add(5,6)).to eq(11) } 
  specify { expect(Calculator.add(5,0)).to eq(5) } 
  specify { expect(Calculator.add(0,5)).to eq(5) } 
  specify { expect(Calculator.add(-5,5)).to eq(0) } 

  specify { expect(Calculator.sub(5,6)).to eq(-1) }
  specify { expect(Calculator.sub(5,1)).to eq(4) }
  specify { expect(Calculator.sub(0,1)).to eq(-1) }
  specify { expect(Calculator.sub(-5,2)).to eq(-7) }
  specify { expect(Calculator.sub(-5,-2)).to eq(-3) }
  specify { expect(Calculator.sub(5,-2)).to eq(7) }

  specify { expect(Calculator.mult(2,3)).to eq(6) }
  specify { expect(Calculator.mult(2,0)).to eq(0) }
  specify { expect(Calculator.mult(0,10)).to eq(0) }
  specify { expect(Calculator.mult(0,-10)).to eq(0) }
  specify { expect(Calculator.mult(1,-10)).to eq(-10) }
  specify { expect(Calculator.mult(-1,-10)).to eq(10) }

  specify { expect(Calculator.div(6,2)).to eq(3) }
  specify { expect(Calculator.div(6,6)).to eq(1) }
  specify { expect(Calculator.div(7,3)).to eq(2) }
  specify { expect(Calculator.div(-6,3)).to eq(-2) }
  specify { expect(Calculator.div(0,3)).to eq(0) }
  specify { expect(Calculator.div(6,-5)).to eq(-1) }
  specify { expect{ Calculator.div(6,0) }.to raise_error(Calculator::DivisionByZero) }
end
Enter fullscreen mode Exit fullscreen mode

I'm kind of not happy with div, but hard to do it nicely without introducing fractions.

cc @ben

Collapse
 
ben profile image
Ben Halpern

Nice stuff!

Collapse
 
vulcanwm profile image
Medea

Woah this is really nice!

Collapse
 
vulcanwm profile image
Medea

Is that a cheat lmao?

 
vulcanwm profile image
Medea

Great!!!