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

``````

Test:

``````add(a, b) == a + b
``````

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

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],
}
}

#[test]
fn it_works() {
}
``````

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

Denis

Rust gang lesssgooo

Keff

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

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)

Aurélien Delogu

Can you explain the trick with size?

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.

Aurélien Delogu

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

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.

Aurélien Delogu • Edited

Ah indeed, thanks! I misunderstood the syntax.

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

duccanhole
``````function add(a, b)
{
if (b == 0)
return a;
else
return Add(a ^ b, (a & b) << 1);
}
``````

naveennamani • Edited

Stop using if else - some dev.to author

Thats a nice logical solution

Keff

Wise solution 😜

konung

Crystal or Ruby

``````def add(a, b)
while b != 0
carry = a & b
a = a ^ b
b = carry << 1
end
return a
end
``````

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));
}
``````

Output:

``````the usual algorithm: 10521 + 830127 = 840648
the funky algorithm: 10521 + 830127 = 840648
``````

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

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));
}
``````

Output:

``````3 + 5 = S(S(S(S(S(S(S(S(Z))))))))
``````

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

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
*   )
* )
*/
const response = await fetch("data:application/octet;base64,AGFzbQEAAAABBwFgAnx8AXwDAgEABwcBA2FkZAAACgkBBwAgACABoAs=")
const buffer = await response.arrayBuffer()
const { instance } = await WebAssembly.instantiate(buffer)

}

;(async function () {

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

console[ok ? 'info' : 'warn'](`\${ok ? '✅' : '❌'} add(\${a}, \${b}) = \${s}`)
}
}
}())
``````

Aurélien Delogu

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

``````def add(a, b)
(-a...b).size
end
``````

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.

naveennamani
``````a.__add__(b)
``````

In python

Aurélien Delogu

Nice cheat :p

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
``````

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?

Aurélien Delogu

Ruby and, by extension, Crystal.

domedev94
``````\$a = 2;
\$b = 32;

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

``````

Keff

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

Alex Lohr
``````const add = (a, b) => Array(a).fill(0).concat(Array(b).fill(0)).length
``````

Alex Lohr
``````const add = (a, b) => `\${' '.repeat(a)}\${' '.repeat(b)}`.length
``````

Migsar Navarro

js

``````const toArr = x => Array.from({ length: x });
const add = (a,b) =>  [...toArr(a), ...toArr(b)].length

``````

Jon Randy 🎖️

Dangerous one:

``````const add = (a,b)=>eval(`\${a}\${String.fromCharCode(43)}\${b}`)
``````

Jon Randy 🎖️ • Edited
``````const add=(a,b,c)=>{for(;b;c=a&b,a=a^b,b=c<<1);return a}
``````

A bit shorter (if you don't mind polluting namespace):

``````const add=(a,b)=>{for(;b;c=a&b,a=a^b,b=c<<1);return a}
``````

Keff

It kinda is nasty 🤣 I like it though