Mikayil Abdullayev
Mikayil Abdullayev

Reputation: 12367

What would be the shortest way to sum up the digits in odd and even places separately

I've always loved reducing number of code lines by using simple but smart math approaches. This situation seems to be one of those that need this approach. So what I basically need is to sum up digits in the odd and even places separately with minimum code. So far this is the best way I have been able to think of:

string number = "123456789";
int sumOfDigitsInOddPlaces=0;
int sumOfDigitsInEvenPlaces=0;
for (int i=0;i<number.length;i++){
   if(i%2==0)//Means odd ones
     sumOfDigitsInOddPlaces+=number[i];
   else
     sumOfDigitsInEvenPlaces+=number[i];    
{
//The rest is not important

Do you have a better idea? Something without needing to use if else

Upvotes: 0

Views: 928

Answers (6)

Cimbali
Cimbali

Reputation: 11395

Assuming number.length is even, it is quite simple. Then the corner case is to consider the last element if number is uneven.

int i=0;
while(i<number.length-1)
{
    sumOfDigitsInEvenPlaces += number[ i++ ];
    sumOfDigitsInOddPlaces += number[ i++ ];
}

if( i < number.length )
    sumOfDigitsInEvenPlaces += number[ i ];
  • Because the loop goes over i 2 by 2, if number.length is even, removing 1 does nothing. If number.length is uneven, it removes the last item.
  • If number.length is uneven, then the last value of i when exiting the loop is that of the not yet visited last element.
  • If number.length is uneven, by modulo 2 reasoning, you have to add the last item to sumOfDigitsInEvenPlaces.

This seems slightly more verbose, but also more readable, to me than Anonymous' (accepted) answer. However, benchmarks to come.


Well, the compiler seems to think my code more understandable as well, since he removes it all if I don't print the results (which explains why I kept getting a time of 0 all along...). The other code though is obfuscated enough for even the compiler.

In the end, even with huge arrays, it's pretty hard for clock_t to tell the difference between the two. You get about a third less instructions in the second case, but since everything's in cache (and your running sums even in registers) it doesn't matter much.

For the curious, I've put the disassembly of both versions (compiled from C) here : http://pastebin.com/2fciLEMw

Upvotes: 1

Aaron Cronin
Aaron Cronin

Reputation: 2103

Since you added C# to the question:

        var numString = "123456789";

        var odds = numString.Split().Where((v, i) => i % 2 == 1);
        var evens = numString.Split().Where((v, i) => i % 2 == 0);

        var sumOfOdds = odds.Select(int.Parse).Sum();
        var sumOfEvens = evens.Select(int.Parse).Sum();

Upvotes: 2

Matt Coubrough
Matt Coubrough

Reputation: 3829

This Java solution requires no if/else, has no code duplication and is O(N):

number = "123456789";
int[] sums = new int[2]; //sums[0] == sum of even digits, sums[1] == sum of odd

for(int arrayIndex=0; arrayIndex < 2; ++arrayIndex) 
{
    for (int i=0; i < number.length()-arrayIndex; i += 2)
    {
       sums[arrayIndex] += Character.getNumericValue(number.charAt(i+arrayIndex));
    } 
}

Upvotes: 1

Aaron Cronin
Aaron Cronin

Reputation: 2103

Do you like Python?

num_string = "123456789"

odds  = sum(map(int, num_string[::2]))
evens = sum(map(int, num_string[1::2]))

Upvotes: 1

Anonymous
Anonymous

Reputation: 2172

int* sum[2] = {&sumOfDigitsInOddPlaces,&sumOfDigitsInEvenPlaces};

for (int i=0;i<number.length;i++)
{
    *(sum[i&1])+=number[i];
}

Upvotes: 3

Freestyle076
Freestyle076

Reputation: 1556

You could use two separate loops, one for the odd indexed digits and one for the even indexed digits. Also your modulus conditional may be wrong, you're placing the even indexed digits (0,2,4...) in the odd accumulator. Could just be that you're considering the number to be 1-based indexing with the number array being 0-based (maybe what you intended), but for algorithms sake I will consider the number to be 0-based. Here's my proposition

number = 123456789;
sumOfDigitsInOddPlaces=0;
sumOfDigitsInEvenPlaces=0;

//even digits
for (int i = 0; i < number.length; i = i + 2){
    sumOfDigitsInEvenPlaces += number[i];
}

//odd digits, note the start at j = 1
for (int j = 1; i < number.length; i = i + 2){
    sumOfDigitsInOddPlaces += number[j];    
}

On the large scale this doesn't improve efficiency, still an O(N) algorithm, but it eliminates the branching

Upvotes: 2

Related Questions