5

I need to add the digits on the even and odd places in an integer. Say, Let number = 1234567. Sum of even place digits = 2+4+6 = 12 Sum of odd place digits = 1+3+5+7 = 16

Wait, don't jump for an answer!

I'm looking for codes with minimal lines, preferably one-line codes. Similar to what 'chaowman' has posted in the thread Sum of digits in C#.

Does anyone has some cool codes. Thanks.

Community
  • 1
  • 1
abhilashca
  • 249
  • 1
  • 8
  • 21
  • 2
    Just one question, Do we start counting as odd/even from the left or from the right? This will make a difference if the number has even number of digits. – erelender Aug 24 '09 at 09:11

13 Answers13

9
    bool odd = false;

    int oddSum = 1234567.ToString().Sum(c => (odd = !odd) ? c - '0' : 0 );

    odd = false;

    int evenSum = 1234567.ToString().Sum(c => (odd = !odd) ? 0 : c - '0' );
Ed Guiness
  • 34,602
  • 16
  • 110
  • 145
2

It's not a one-liner, but the following works:

int oddSum = 0, evenSum = 0;
bool odd = true;
while (n != 0) {
    if (odd)  
        oddSum += n % 10;
    else
        evenSum += n % 10;
    n /= 10;
    odd = !odd;
}

EDIT:

If you want it on one line:

int oddSum = 0, evenSum = 0; bool odd = true; while (n != 0) { if (odd) oddSum += n % 10; else evenSum += n % 10; n /= 10; odd = !odd; }
Patrick McDonald
  • 64,141
  • 14
  • 108
  • 120
  • @ThePower: I think you have a misunderstanding. OP asks for the sums of numbers at even and odd places, not even and odd digits. – erelender Aug 24 '09 at 09:21
  • Damn, Patrick, it took me too long to remove the line breaks from your post and by the time my post went up you had already edited yours. :( – Imagist Aug 24 '09 at 09:25
  • 1
    I like your one-liner Humor Sense! Thanks. – abhilashca Aug 24 '09 at 09:42
2

If you liked chaowmans solution to the other question, this would be the logical extension to even/odd numbers:

int even = 17463.ToString().Where((c, i) => i%2==1).Sum(c => c - '0');
int odd  = 17463.ToString().Where((c, i) => i%2==0).Sum(c => c - '0');

A loop might be simpler and more efficient though:

for (odd = even = 0; n != 0; n /= 10) {
  tmp = odd;
  odd = even*10 + n%10;
  even = tmp;
}

And it's also not really longer or more complicated. Both versions determine the "oddness" from the left of the number.

sth
  • 222,467
  • 53
  • 283
  • 367
2
"1234567".Where((ch, i) => i % 2 == 0).Sum(ch => ch - '0')
Lloyd
  • 1,324
  • 7
  • 10
1

If you're looking for the inevitable stupid LINQ tricks version, here's one:

var result = 1234567
    .ToString()
    .Select((c, index) => new { IndexIsOdd = index % 2 == 1, ValueOfDigit = Char.GetNumericValue(c) })
    .GroupBy(d => d.IndexIsOdd)
    .Select(g => new { OddColumns = g.Key, sum = g.Sum(item => item.ValueOfDigit) });
foreach( var r in result )
    Console.WriteLine(r);

I'm sure that can be mutated into a one-liner by someone bored (and remove converting it to a string as a way of generating the digits).

EDIT: Using Tuples to make it shorter (but more confusing)

var result = 1234567
    .ToString()
    .Select((c, index) => Tuple.Create( index % 2 == 1, Char.GetNumericValue(c))
    .GroupBy(d=>d.Item1)
    .Select(g => new { OddColumns = g.Key, Sum = g.Sum(item => item.Item2) });
foreach( var r in result )
    Console.WriteLine(r);
Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
1

Ruben's version with modified Grouping logic:

bool isOdd = false; 
var sums = 1234567
    .ToString()
    .Select(x => Char.GetNumericValue(x))
    .GroupBy(x => isOdd = !isOdd)
    .Select(x => new { IsOdd = x.Key, Sum = x.Sum() });

foreach (var x in sums)
    Console.WriteLine("Sum of {0} is {1}", x.IsOdd ? "odd" : "even", x.Sum);
Martin Jonáš
  • 2,309
  • 15
  • 12
  • 1
    Nice, but I'm really not a fan of the mutating flag trick [in ay of the versions] - each loop over the enumerable will rely on the state in there [and will preclude having interleaved versions etc.]. But then as long as we're trying to do Stupid Coding Tricks, then that's all fine and dandy. – Ruben Bartelink Aug 24 '09 at 10:04
1

Here's my one-long-liner using LINQ that (a) calculates the odd and even totals in a single line, (b) doesn't convert the original number to an intermediate string, and (c) doesn't have any side-effects:

var totals = Enumerable.Range(0, 10)
    .Select(x => (number / (int)Math.Pow(10, x)) % 10)
    .Where(x => x > 0)
    .Reverse()
    .Select((x, i) => new { Even = x * (i % 2), Odd = x * ((i + 1) % 2) })
    .Aggregate((a, x) => new { Even = a.Even + x.Even, Odd = a.Odd + x.Odd });

Console.WriteLine(number);         // 1234567
Console.WriteLine(totals.Even);    // 12
Console.WriteLine(totals.Odd);     // 16

(The code above counts the odd/even positions from left-to-right. To count from right-to-left instead just remove the call to Reverse. Calculating from L-to-R will give different results than R-to-L when number has an even number of digits.)

LukeH
  • 263,068
  • 57
  • 365
  • 409
  • Note that I'm not recommending this method: A standard loop would be shorter, faster and easier to understand. This is just me jumping through hoops to answer the "preferably one line" request in the question! – LukeH Aug 24 '09 at 12:17
0

I don't really know C# but here's a one-liner that may look a bit familiar to Patrick McDonald:

int oddSum = 0, evenSum = 0; bool odd = true; while (n != 0) { if (odd) oddSum += n % 10; else evenSum += n % 10; n /= 10; odd = !odd; }
Imagist
  • 18,086
  • 12
  • 58
  • 77
0
 int evenSum = 1234567.ToString().ToCharArray().Where((c, i) => (i % 2 == 0)).Sum(c => c - '0');
 int oddSum = 1234567.ToString().ToCharArray().Where((c, i) => (i % 2 == 1)).Sum(c => c - '0');
0
int number = 1234567;
int oddSum = 0;
int evenSum = 0;
while(number!=0)
{
  if (n%2 == 0) evenSum += number % 10;
  else oddSum += number % 10;
  number /= 10;
}
0
int n = 1234567;
int[] c = new int[2];
int p = 0;
n.ToString().Select(ch => (int)ch - '0').ToList().ForEach(d => { c[p] += d; p ^= 1; });
Console.WriteLine("even sum = {0}, odd sum = {1}", c[0], c[1]);

Shorter one:

int n = 1234567, p = 0;
int[] c = new int[2];
while (n > 0) { c[p] += n % 10; n /= 10;  p ^= 1; };
Console.WriteLine("even sum = {0}, odd sum = {1}", c[p ^ 1], c[p]);
0

This works if you're starting from the right. At least, it works in C++. I don't know C#, as I said. I kind of hope they removed some of this nonsense in C#.

It's not a one-liner, but it's one statement if you discount the declaration (which I think is fair):

int oddSum, evenSum;
for(bool odd = ((oddSum = evenSum = 0) == 0);
    n != 0;
    odd = (!odd || (n /= 10) == n + (oddSum += (odd ? n % 10 : 0) - evenSum + (evenSum += (!odd ? n % 10 : 0)))))
;

As extra credit, here's a one-line Python script that will turn all of your C# solutions into one-liners.

one_liner.py
open(__import__('sys').argv[2]','w').write(open(__import__('sys').argv[1],'r').read().replace('\n',''))

Usage:

python one_liner.py infile outfile
Imagist
  • 18,086
  • 12
  • 58
  • 77
0

This works without LINQ.

var r = new int[]{0,0}; for (int i=0; i<7; i++) r[i%2]+="1234567"[i]-48;
System.Console.WriteLine("{0} {1}",r[0],r[1]);
Sklivvz
  • 30,601
  • 24
  • 116
  • 172