DEV Community

Keff
Keff

Posted on

[Challenge] Add numbers without (+-*/)

Time for another casual little challenge.

For this one there are only 2 rules:

  • you must add numbers a and b together
  • you must NOT use the +-*/ operators

Apart from that there are no more rules, and can be done with any language you want!

Pseudocode:

a = 2
b = 32

add(a, b) => 34
Enter fullscreen mode Exit fullscreen mode

Test:

add(a, b) == a + b
Enter fullscreen mode Exit fullscreen mode

Have fun! Let's see what you come up with!

Top comments (30)

Collapse
Ā 
shekohex profile image
shekohex •
const fn add<const A: usize, const B: usize>() -> usize {
    struct _Add<const A: usize, const B: usize> {
        _a: [u8; A],
        _b: [u8; B],
    }
    core::mem::size_of::<_Add<A, B>>()
}

#[test]
fn it_works() {
    assert_eq!(add::<40, 2>(), 42);
}
Enter fullscreen mode Exit fullscreen mode

Compile time execution goes brrrrrr šŸ˜‚

Here is the full code with other solutions: https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=3fd17ceb138f1e2c230987bd93d93f25

Collapse
Ā 
pyrsmk profile image
AurĆ©lien Delogu •

Can you explain the trick with size?

Collapse
Ā 
shekohex profile image
shekohex •

The memory size of the struct _Add here would be the size of _a and _b combined, in other words for any type T and length of n, [T; n] has the size of n * size_of::<T>(), and since here T is u8 and its size is just 1 byte; hence [u8; n] is just n bytes. Using this; the size of _Add would be the size of [u8; A] (A bytes) and the size of [u8; B] (B bytes); will result in total is A+B bytes.

Thread Thread
Ā 
pyrsmk profile image
AurĆ©lien Delogu •

Yes but this is where I'm lost. Wouldn't be the returned value 2 in every case?

Thread Thread
Ā 
shekohex profile image
shekohex •

No, in the test case, A = 40 means [0u8; 40] that also means 40 bytes, and B = 2 which is [0u8; 2] that's 2 bytes, which is total of 42 bytes.

Thread Thread
Ā 
pyrsmk profile image
AurĆ©lien Delogu • • Edited

Ah indeed, thanks! I misunderstood the syntax.

edit : that's a really smart solution btw, thanks for sharing

Collapse
Ā 
nombrekeff profile image
Keff •

Nice, that's really interesting! I like how the compiler replaces the Iterator example with a + b lol 🤣

Collapse
Ā 
shekohex profile image
shekohex •

Crazy!
(for anyone wonder what iterators, check out the rust playground link I've posted, there is other solution that uses iterators instead of const generics)

Collapse
Ā 
thedenisnikulin profile image
Denis •

Rust gang lesssgooo

Collapse
Ā 
coderduck profile image
duccanhole •
function add(a, b)
{
    if (b == 0)
        return a;
    else
        return Add(a ^ b, (a & b) << 1);
}
Enter fullscreen mode Exit fullscreen mode
Collapse
Ā 
naveennamani profile image
naveennamani • • Edited

Stop using if else - some dev.to author

Thats a nice logical solution

Collapse
Ā 
nombrekeff profile image
Keff •

Wise solution 😜

Collapse
Ā 
kinvoki profile image
kinvoki •

Crystal or Ruby

def add(a, b)
  while b != 0
    carry = a & b
    a = a ^ b
    b = carry << 1
  end
  return a
end
Enter fullscreen mode Exit fullscreen mode
Collapse
Ā 
object_required profile image
Nikolai Kim •

Thank you for the challenge, I finally got into WebAssembly šŸŽ‰

async function makeAdd() {
  /*
   * (module
   *   (func $add (;0;) (export "add") (param $var0 f64) (param $var1 f64) (result f64)
   *     local.get $var0
   *     local.get $var1
   *     f64.add
   *   )
   * )
   */
  const response = await fetch("data:application/octet;base64,AGFzbQEAAAABBwFgAnx8AXwDAgEABwcBA2FkZAAACgkBBwAgACABoAs=")
  const buffer = await response.arrayBuffer()
  const { instance } = await WebAssembly.instantiate(buffer)

  return instance.exports.add
}

;(async function () {
  const add = await makeAdd()

  for (var a = -1; a <= 1; a += 1) {
    for (var b = -1; b <= 1; b += 1) {
      var s = add(a, b)
      var ok = s === a + b

      console[ok ? 'info' : 'warn'](`${ok ? 'āœ…' : 'āŒ'} add(${a}, ${b}) = ${s}`)
    }
  }
}())
Enter fullscreen mode Exit fullscreen mode
Collapse
Ā 
pyrsmk profile image
AurĆ©lien Delogu • • Edited

This is clearly cheating, but here we go with a Ruby solution :D

def add(a, b)
  [a, b].sum
end
Enter fullscreen mode Exit fullscreen mode
Collapse
Ā 
nombrekeff profile image
Keff •

Hahahah true xD if we stick to the rules yup... but I think I'll pass this one. I guessed there would be some languages that had built-in methods like this! What's the language BTW?

Collapse
Ā 
pyrsmk profile image
AurĆ©lien Delogu •

Ruby and, by extension, Crystal.

Collapse
Ā 
naveennamani profile image
naveennamani •
a.__add__(b)
Enter fullscreen mode Exit fullscreen mode

In python

Collapse
Ā 
pyrsmk profile image
AurĆ©lien Delogu •

Nice cheat :p

Collapse
Ā 
armousness profile image
Sean Williams •

I spent an unfortunate amount of time on this...

fn add(a: u32, b: u32) -> u32 {
    let mut carry = false;
    let mut result = 0;
    for i in 0..32 {
        let mask = 1 << i;
        let a_in = (a & mask) > 0;
        let b_in = (b & mask) > 0;
        let s =
            match (a_in, b_in, carry) {
                (false, false, true) => 1,
                (false, true, false) => 1,
                (true, false, false) => 1,
                (true, true, true) => 1,
                _ => 0,
            } << i;
        result = result | s;
        carry =
            match (a_in, b_in, &carry) {
                (false, true, true) => true,
                (true, false, true) => true,
                (true, true, false) => true,
                (true, true, true) => true,
                _ => false,
            };
    }
    result
}

fn main() {
    let a = 10521;
    let b = 830127;
    println!("the usual algorithm: {} + {} = {}", a, b, a + b);
    println!("the funky algorithm: {} + {} = {}", a, b, add(a, b));
}
Enter fullscreen mode Exit fullscreen mode

Output:

the usual algorithm: 10521 + 830127 = 840648
the funky algorithm: 10521 + 830127 = 840648
Enter fullscreen mode Exit fullscreen mode

This currently only works on unsigned integers. I don't feel like spending the time now to remember how two's complement works.

Collapse
Ā 
armousness profile image
Sean Williams •

Though I guess I'll be a bit more pedantic with this one: for i in 0..32 smuggles in some integer addition. So here's the set theoretic implementation, which has—less reliance on plus signs:

#[derive(Debug)]
enum Num {
    S(Box<Num>),
    Z,
}

fn s(n: Num) -> Num {
    Num::S(Box::new(n))
}

fn z() -> Num {
    Num::Z
}

fn set_add(a: Num, b: Num) -> Num {
    let mut result = a;
    let mut work = b;
    loop {
        match work {
            Num::S(next) => {
                result = s(result);
                work = *next;
            },
            Num::Z => return result,
        }
    }
}

fn main() {
    let a = s(s(s(z()))); // i.e., 3
    let b = s(s(s(s(s(z()))))); // i.e., 5
    println!("3 + 5 = {:?}", set_add(a, b));
}
Enter fullscreen mode Exit fullscreen mode

Output:

3 + 5 = S(S(S(S(S(S(S(S(Z))))))))
Enter fullscreen mode Exit fullscreen mode

Z means zero, and S means increment. So this is zero incremented eight times.

Collapse
Ā 
pyrsmk profile image
AurĆ©lien Delogu •

Here's another, more serious, attempt (still in Ruby) :

def add(a, b)
  (-a...b).size
end
Enter fullscreen mode Exit fullscreen mode

Some explanations : in Ruby 0..10 is called a range. It is really useful to make arbitrary loops or splice an array, for example. Simply, a range is a suite of values. The syntax I used here is 0...10 (note the three dots) which is an exclusive range : the suite of values goes from 0 to 9. So the trick is to have a range going from -a to b and excluding b because 0 is included in the suite.

Collapse
Ā 
lexlohr profile image
Alex Lohr •
const add = (a, b) => Array(a).fill(0).concat(Array(b).fill(0)).length
Enter fullscreen mode Exit fullscreen mode
Collapse
Ā 
lexlohr profile image
Alex Lohr •
const add = (a, b) => `${' '.repeat(a)}${' '.repeat(b)}`.length
Enter fullscreen mode Exit fullscreen mode
Collapse
Ā 
domedev94 profile image
domedev94 •
$a = 2;
$b = 32;
add($a,$b);

function add($n1,$n2){
    return count(array_merge(array_fill(0,$n1,"a"),array_fill(0,$n2,"b")));
}

Enter fullscreen mode Exit fullscreen mode
Collapse
Ā 
nombrekeff profile image
Keff •

Nice one!! I also thought of this solution!!! Not very scalable but cool nonetheless