Printing every 10th result in an alternating ± series












12












$begingroup$


Problem:



In the following expression 1-2+3-4+5-6 ... -98+99-100, print result every 10th (10, 20, 30, ...) calculation.



My code:



result  = 0
operand = 1
counter = 0
for i in range(1, 101):
result = result + (i * operand)
counter = counter + 1
operand = operand * -1 #Convert between positive and negative number
if counter >= 10:
counter = 0
print(result)


My problem:



I think this code has not good readability. For example, I used * -1 for changing positive and negative number. But it requires math skill(multiplying a negative number) to understand code.



And I don't sure variable name 'counter' and 'operand' is appropriate for this context.



Is there any suggestion?










share|improve this question











$endgroup$












  • $begingroup$
    Do you need the final result of the whole sum and just want to report progress as the summing is going on, or do you want the sum of only every 10th element and also print progress?
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:29






  • 1




    $begingroup$
    Maybe I'm missing something, but isn't the alternating sum you want $$-sum_{n=1}^{m} n (-1)^n equiv -frac{1}{4}-frac{1}{4}(-1)^m (2m+1)$$ And then you can substitute m = 10n or whatever value you need. Far faster than looping.
    $endgroup$
    – esote
    Dec 11 '18 at 1:35












  • $begingroup$
    @Graipher I want to report progress as the summing is going on. but original question is not clear. So i think it should be interpreted like this.
    $endgroup$
    – jun
    Dec 11 '18 at 1:50












  • $begingroup$
    @esote this seems like the start of an answer
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 21:59






  • 1




    $begingroup$
    @esote Mathematical analysis of a problem in order to reduce code complexity are usually well received.
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 22:20
















12












$begingroup$


Problem:



In the following expression 1-2+3-4+5-6 ... -98+99-100, print result every 10th (10, 20, 30, ...) calculation.



My code:



result  = 0
operand = 1
counter = 0
for i in range(1, 101):
result = result + (i * operand)
counter = counter + 1
operand = operand * -1 #Convert between positive and negative number
if counter >= 10:
counter = 0
print(result)


My problem:



I think this code has not good readability. For example, I used * -1 for changing positive and negative number. But it requires math skill(multiplying a negative number) to understand code.



And I don't sure variable name 'counter' and 'operand' is appropriate for this context.



Is there any suggestion?










share|improve this question











$endgroup$












  • $begingroup$
    Do you need the final result of the whole sum and just want to report progress as the summing is going on, or do you want the sum of only every 10th element and also print progress?
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:29






  • 1




    $begingroup$
    Maybe I'm missing something, but isn't the alternating sum you want $$-sum_{n=1}^{m} n (-1)^n equiv -frac{1}{4}-frac{1}{4}(-1)^m (2m+1)$$ And then you can substitute m = 10n or whatever value you need. Far faster than looping.
    $endgroup$
    – esote
    Dec 11 '18 at 1:35












  • $begingroup$
    @Graipher I want to report progress as the summing is going on. but original question is not clear. So i think it should be interpreted like this.
    $endgroup$
    – jun
    Dec 11 '18 at 1:50












  • $begingroup$
    @esote this seems like the start of an answer
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 21:59






  • 1




    $begingroup$
    @esote Mathematical analysis of a problem in order to reduce code complexity are usually well received.
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 22:20














12












12








12


4



$begingroup$


Problem:



In the following expression 1-2+3-4+5-6 ... -98+99-100, print result every 10th (10, 20, 30, ...) calculation.



My code:



result  = 0
operand = 1
counter = 0
for i in range(1, 101):
result = result + (i * operand)
counter = counter + 1
operand = operand * -1 #Convert between positive and negative number
if counter >= 10:
counter = 0
print(result)


My problem:



I think this code has not good readability. For example, I used * -1 for changing positive and negative number. But it requires math skill(multiplying a negative number) to understand code.



And I don't sure variable name 'counter' and 'operand' is appropriate for this context.



Is there any suggestion?










share|improve this question











$endgroup$




Problem:



In the following expression 1-2+3-4+5-6 ... -98+99-100, print result every 10th (10, 20, 30, ...) calculation.



My code:



result  = 0
operand = 1
counter = 0
for i in range(1, 101):
result = result + (i * operand)
counter = counter + 1
operand = operand * -1 #Convert between positive and negative number
if counter >= 10:
counter = 0
print(result)


My problem:



I think this code has not good readability. For example, I used * -1 for changing positive and negative number. But it requires math skill(multiplying a negative number) to understand code.



And I don't sure variable name 'counter' and 'operand' is appropriate for this context.



Is there any suggestion?







python python-3.x






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 11 '18 at 5:50









200_success

129k15153415




129k15153415










asked Dec 10 '18 at 14:41









junjun

805




805












  • $begingroup$
    Do you need the final result of the whole sum and just want to report progress as the summing is going on, or do you want the sum of only every 10th element and also print progress?
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:29






  • 1




    $begingroup$
    Maybe I'm missing something, but isn't the alternating sum you want $$-sum_{n=1}^{m} n (-1)^n equiv -frac{1}{4}-frac{1}{4}(-1)^m (2m+1)$$ And then you can substitute m = 10n or whatever value you need. Far faster than looping.
    $endgroup$
    – esote
    Dec 11 '18 at 1:35












  • $begingroup$
    @Graipher I want to report progress as the summing is going on. but original question is not clear. So i think it should be interpreted like this.
    $endgroup$
    – jun
    Dec 11 '18 at 1:50












  • $begingroup$
    @esote this seems like the start of an answer
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 21:59






  • 1




    $begingroup$
    @esote Mathematical analysis of a problem in order to reduce code complexity are usually well received.
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 22:20


















  • $begingroup$
    Do you need the final result of the whole sum and just want to report progress as the summing is going on, or do you want the sum of only every 10th element and also print progress?
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:29






  • 1




    $begingroup$
    Maybe I'm missing something, but isn't the alternating sum you want $$-sum_{n=1}^{m} n (-1)^n equiv -frac{1}{4}-frac{1}{4}(-1)^m (2m+1)$$ And then you can substitute m = 10n or whatever value you need. Far faster than looping.
    $endgroup$
    – esote
    Dec 11 '18 at 1:35












  • $begingroup$
    @Graipher I want to report progress as the summing is going on. but original question is not clear. So i think it should be interpreted like this.
    $endgroup$
    – jun
    Dec 11 '18 at 1:50












  • $begingroup$
    @esote this seems like the start of an answer
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 21:59






  • 1




    $begingroup$
    @esote Mathematical analysis of a problem in order to reduce code complexity are usually well received.
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 22:20
















$begingroup$
Do you need the final result of the whole sum and just want to report progress as the summing is going on, or do you want the sum of only every 10th element and also print progress?
$endgroup$
– Graipher
Dec 10 '18 at 15:29




$begingroup$
Do you need the final result of the whole sum and just want to report progress as the summing is going on, or do you want the sum of only every 10th element and also print progress?
$endgroup$
– Graipher
Dec 10 '18 at 15:29




1




1




$begingroup$
Maybe I'm missing something, but isn't the alternating sum you want $$-sum_{n=1}^{m} n (-1)^n equiv -frac{1}{4}-frac{1}{4}(-1)^m (2m+1)$$ And then you can substitute m = 10n or whatever value you need. Far faster than looping.
$endgroup$
– esote
Dec 11 '18 at 1:35






$begingroup$
Maybe I'm missing something, but isn't the alternating sum you want $$-sum_{n=1}^{m} n (-1)^n equiv -frac{1}{4}-frac{1}{4}(-1)^m (2m+1)$$ And then you can substitute m = 10n or whatever value you need. Far faster than looping.
$endgroup$
– esote
Dec 11 '18 at 1:35














$begingroup$
@Graipher I want to report progress as the summing is going on. but original question is not clear. So i think it should be interpreted like this.
$endgroup$
– jun
Dec 11 '18 at 1:50






$begingroup$
@Graipher I want to report progress as the summing is going on. but original question is not clear. So i think it should be interpreted like this.
$endgroup$
– jun
Dec 11 '18 at 1:50














$begingroup$
@esote this seems like the start of an answer
$endgroup$
– Mathias Ettinger
Dec 11 '18 at 21:59




$begingroup$
@esote this seems like the start of an answer
$endgroup$
– Mathias Ettinger
Dec 11 '18 at 21:59




1




1




$begingroup$
@esote Mathematical analysis of a problem in order to reduce code complexity are usually well received.
$endgroup$
– Mathias Ettinger
Dec 11 '18 at 22:20




$begingroup$
@esote Mathematical analysis of a problem in order to reduce code complexity are usually well received.
$endgroup$
– Mathias Ettinger
Dec 11 '18 at 22:20










5 Answers
5






active

oldest

votes


















12












$begingroup$

The first thing you can do to make the sign change obvious is to use operand = -operand, this way you avoid the need for the multiplication operator. Also changing the operand name to sign can help.



You also don't need counter as it will be equal to i before the test. Just change the test to use the modulo (%) operator instead of reseting counter.



And using augmented assignment for result can lead to a more readable line too:



result = 0
sign = 1
for i in range(1, 101):
result += sign * i
sign = -sign
if i % 10 == 0:
print(result)


Now, this probably need to be made more reusable, this means building a function out of this code and avoiding mixing computation and I/Os:



def alternating_sum(start=1, stop=100, step=10):
result = 0
sign = 1
for i in range(start, stop+1):
result += sign * i
sign = -sign
if i % step == 0:
yield result


Usage being:



for result in alternating_sum(1, 100, 10):
print(result)




Also, depending on the problem at hand, you can leverage the fact that every two numbers add-up to -1. So every 10 numbers add-up to -5. If you don't need much genericity, you can simplify the code down to:



def alternating_every_ten(end=100):
reports = end // 10
for i in range(1, reports + 1):
print('After', 10 * i, 'sums, result is', -5 * i)





share|improve this answer











$endgroup$













  • $begingroup$
    I would recommend writing expressions with a sign variable as sign * value to match the standard method of writing numbers.
    $endgroup$
    – Apollys
    Dec 10 '18 at 18:41










  • $begingroup$
    @Apollys Right, fixed.
    $endgroup$
    – Mathias Ettinger
    Dec 10 '18 at 20:11



















6












$begingroup$

You can get rid of your counter and directly use i by using modular arithmetic. i % 10 == 0 is true whenever i is divisible by 10.



You can get rid of your operand = operand * -1 by using itertools.cycle.



from itertools import cycle

result = 0
for i, sign in zip(range(1, 101), cycle([1, -1])):
result += sign * i
if i % 10 == 0:
print(result)


The generation of result itself would be a lot more concise with a generator comprehension, but this excludes the progress prints:



result = sum(sign * i for i, sign in zip(range(1, 101), cycle([1, -1])))





share|improve this answer









$endgroup$













  • $begingroup$
    @MathiasEttinger: It seems like MaartenFabre is already going in that direction in their answer.
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:25










  • $begingroup$
    Yep, saw that after the comment
    $endgroup$
    – Mathias Ettinger
    Dec 10 '18 at 15:28



















5












$begingroup$

instead of doing the +- by hand, you can use the fact that (-1) ** (i-1) * i for i in range(101) alternates the values



Further on, you can use itertools.accumulate and itertools.islice to take the cumulative sum and select every 10th number



numbers = (int((-1) ** (i-1) * i) for i in range(101))
cum_sum = itertools.accumulate(numbers)
numbers_10 = itertools.islice(cum_sum, 10, None, 10)

for i in numbers_10:
print(i)



-5
-10
-15
-20
-25
-30
-35
-40
-45
-50



or alternatively, per 200_success' suggestion:



numbers = (sign * i for sign, i in zip(itertools.cycle((1, -1)), itertools.count(1)))
cum_sum = itertools.accumulate(numbers)
numbers_10 = itertools.islice(cum_sum, 9, 100, 10)





share|improve this answer











$endgroup$













  • $begingroup$
    With this you do not get the final result, though. Maybe with a itertools.tee of the numbers, which you can then sum, but then it is no longer reporting on the progress...
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:24












  • $begingroup$
    what do you mean with the final result? If needed, you need to do cum_sum = list(itertools.accumulate(numbers)) or numbers = [int((-1) ** (i-1) * i) for i in range(101)]
    $endgroup$
    – Maarten Fabré
    Dec 10 '18 at 15:37








  • 2




    $begingroup$
    I like this. Personally, I'd write it as cum_sum = accumulate(sign * n for sign, n in zip(cycle((+1, -1)), count())) to more elegantly express the idea of an infinite series, then extract just the relevant partial sums with for n in islice(cum_sum, 9, 100, 10): print(n).
    $endgroup$
    – 200_success
    Dec 11 '18 at 0:11



















1












$begingroup$

I would convert the sign flip into a generator, created via a generator comprehension, recognizing that evens should be negative:



#  Integers from 1-100, where evens are negative: 1, -2, 3, -4, 5...
sequence_gen = (i if i % 2 else -i for i in range(1,101))


Equivalent to:



def sequence_gen():
for i in range(1, 101):
if bool(i % 2): # For our purposes this is i % 2 == 1:
yield i
else:
yield -i


Then your code becomes:



result = 0
for index, number in enumerate(sequence_gen):
result += number
if index % 10 == 9: # Note the comparison change by starting at 0
print(result)


Note this is about half way to what Mathias proposed, and can be used in conjunction, the combination being:



def sequence_sums(start, stop, step):
result = 0
seq_gen = (i if i % 2 else -i for i in range(start, stop + 1))
for index, number in enumerate(seq_gen):
result += number
if index % step == step - 1:
yield result




You could even go one further step and make the sequence a parameter:



# iterates through a sequence, printing every step'th sum
def sequence_sums(sequence, step):
result = 0
for index, number in enumerate(sequence):
result += number
if index % step == step - 1:
yield result


Called via:



sequence = (i if i % 2 else -i for i in range(1, 101))

for sum in sequence_sums(sequence, 10):
print(sum)





share|improve this answer









$endgroup$









  • 1




    $begingroup$
    Note the comparison change by starting at 0 => enumerate takes a second, optional, argument: start. So you can use enumerate(sequence, 1) and keep the usual comparison of the modulo to 0.
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 8:00



















1












$begingroup$

The other answers are fine. Here is a mathematical analysis of the problem you're trying to solve.



If this code is, for some reason, used in a performance-critical scenario, you can calculate the sum to $m$ in $O(1)$ time.



Notice that:



$$
begin{align}
1-2+3-4+5-6dots m &= -sum_{n=1}^{m}n(-1)^n \
&= sum_{n=1}^{m}n(-1)^{n-1} \
&= frac{1}{4}-frac{1}{4}(-1)^m(2m+1) ; ^*
end{align}
$$



* There was a typo in my original comment.



Because you only want to see every 10th result, we can substitute $m=10u$ where $uinmathbb{Z}$. This is fortunate because for all integers $(-1)^{10u} equiv 1$. Therefore:



$$
begin{align}
frac{1}{4}-frac{1}{4}(-1)^{10u}(20u+1) &= frac{1}{4}-frac{1}{4}(20u+1) \
&= frac{1}{4}-frac{20u+1}{4}\
&= frac{(1-1)-20u}{4} \
&= -5u
end{align}
$$



Look familiar? It results in $-5$, $-10$, $-15$, ...



This fact is obvious from the output, but now knowing the series that produces it, we can calculate the final result for any such $m$ quickly, and every 10th value even easier.



We can avoid computing the exponent $(-1)^m$ because $(-1)^{m} = 1$ for even values of $m$ and $-1$ for odd values.



I'm not as familiar with Python, but here's an example:



def series(m):
alt = 1 if m % 2 == 0 else -1
return int(1/4 - 1/4 * alt * (2 * m + 1))

def series_progress(m):
return -5 * m

m = 134

for i in range(1, m // 10):
print(series_progress(i))

print(series(m))


This avoids the costly computation for the final result. If we just needed the result it would be $O(1)$, but because we give "progress reports" it is more like $lfloorfrac{n}{10}rfloorin O(n)$.






share|improve this answer











$endgroup$













    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209364%2fprinting-every-10th-result-in-an-alternating-%25c2%25b1-series%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    12












    $begingroup$

    The first thing you can do to make the sign change obvious is to use operand = -operand, this way you avoid the need for the multiplication operator. Also changing the operand name to sign can help.



    You also don't need counter as it will be equal to i before the test. Just change the test to use the modulo (%) operator instead of reseting counter.



    And using augmented assignment for result can lead to a more readable line too:



    result = 0
    sign = 1
    for i in range(1, 101):
    result += sign * i
    sign = -sign
    if i % 10 == 0:
    print(result)


    Now, this probably need to be made more reusable, this means building a function out of this code and avoiding mixing computation and I/Os:



    def alternating_sum(start=1, stop=100, step=10):
    result = 0
    sign = 1
    for i in range(start, stop+1):
    result += sign * i
    sign = -sign
    if i % step == 0:
    yield result


    Usage being:



    for result in alternating_sum(1, 100, 10):
    print(result)




    Also, depending on the problem at hand, you can leverage the fact that every two numbers add-up to -1. So every 10 numbers add-up to -5. If you don't need much genericity, you can simplify the code down to:



    def alternating_every_ten(end=100):
    reports = end // 10
    for i in range(1, reports + 1):
    print('After', 10 * i, 'sums, result is', -5 * i)





    share|improve this answer











    $endgroup$













    • $begingroup$
      I would recommend writing expressions with a sign variable as sign * value to match the standard method of writing numbers.
      $endgroup$
      – Apollys
      Dec 10 '18 at 18:41










    • $begingroup$
      @Apollys Right, fixed.
      $endgroup$
      – Mathias Ettinger
      Dec 10 '18 at 20:11
















    12












    $begingroup$

    The first thing you can do to make the sign change obvious is to use operand = -operand, this way you avoid the need for the multiplication operator. Also changing the operand name to sign can help.



    You also don't need counter as it will be equal to i before the test. Just change the test to use the modulo (%) operator instead of reseting counter.



    And using augmented assignment for result can lead to a more readable line too:



    result = 0
    sign = 1
    for i in range(1, 101):
    result += sign * i
    sign = -sign
    if i % 10 == 0:
    print(result)


    Now, this probably need to be made more reusable, this means building a function out of this code and avoiding mixing computation and I/Os:



    def alternating_sum(start=1, stop=100, step=10):
    result = 0
    sign = 1
    for i in range(start, stop+1):
    result += sign * i
    sign = -sign
    if i % step == 0:
    yield result


    Usage being:



    for result in alternating_sum(1, 100, 10):
    print(result)




    Also, depending on the problem at hand, you can leverage the fact that every two numbers add-up to -1. So every 10 numbers add-up to -5. If you don't need much genericity, you can simplify the code down to:



    def alternating_every_ten(end=100):
    reports = end // 10
    for i in range(1, reports + 1):
    print('After', 10 * i, 'sums, result is', -5 * i)





    share|improve this answer











    $endgroup$













    • $begingroup$
      I would recommend writing expressions with a sign variable as sign * value to match the standard method of writing numbers.
      $endgroup$
      – Apollys
      Dec 10 '18 at 18:41










    • $begingroup$
      @Apollys Right, fixed.
      $endgroup$
      – Mathias Ettinger
      Dec 10 '18 at 20:11














    12












    12








    12





    $begingroup$

    The first thing you can do to make the sign change obvious is to use operand = -operand, this way you avoid the need for the multiplication operator. Also changing the operand name to sign can help.



    You also don't need counter as it will be equal to i before the test. Just change the test to use the modulo (%) operator instead of reseting counter.



    And using augmented assignment for result can lead to a more readable line too:



    result = 0
    sign = 1
    for i in range(1, 101):
    result += sign * i
    sign = -sign
    if i % 10 == 0:
    print(result)


    Now, this probably need to be made more reusable, this means building a function out of this code and avoiding mixing computation and I/Os:



    def alternating_sum(start=1, stop=100, step=10):
    result = 0
    sign = 1
    for i in range(start, stop+1):
    result += sign * i
    sign = -sign
    if i % step == 0:
    yield result


    Usage being:



    for result in alternating_sum(1, 100, 10):
    print(result)




    Also, depending on the problem at hand, you can leverage the fact that every two numbers add-up to -1. So every 10 numbers add-up to -5. If you don't need much genericity, you can simplify the code down to:



    def alternating_every_ten(end=100):
    reports = end // 10
    for i in range(1, reports + 1):
    print('After', 10 * i, 'sums, result is', -5 * i)





    share|improve this answer











    $endgroup$



    The first thing you can do to make the sign change obvious is to use operand = -operand, this way you avoid the need for the multiplication operator. Also changing the operand name to sign can help.



    You also don't need counter as it will be equal to i before the test. Just change the test to use the modulo (%) operator instead of reseting counter.



    And using augmented assignment for result can lead to a more readable line too:



    result = 0
    sign = 1
    for i in range(1, 101):
    result += sign * i
    sign = -sign
    if i % 10 == 0:
    print(result)


    Now, this probably need to be made more reusable, this means building a function out of this code and avoiding mixing computation and I/Os:



    def alternating_sum(start=1, stop=100, step=10):
    result = 0
    sign = 1
    for i in range(start, stop+1):
    result += sign * i
    sign = -sign
    if i % step == 0:
    yield result


    Usage being:



    for result in alternating_sum(1, 100, 10):
    print(result)




    Also, depending on the problem at hand, you can leverage the fact that every two numbers add-up to -1. So every 10 numbers add-up to -5. If you don't need much genericity, you can simplify the code down to:



    def alternating_every_ten(end=100):
    reports = end // 10
    for i in range(1, reports + 1):
    print('After', 10 * i, 'sums, result is', -5 * i)






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 10 '18 at 20:11

























    answered Dec 10 '18 at 15:19









    Mathias EttingerMathias Ettinger

    24.4k33184




    24.4k33184












    • $begingroup$
      I would recommend writing expressions with a sign variable as sign * value to match the standard method of writing numbers.
      $endgroup$
      – Apollys
      Dec 10 '18 at 18:41










    • $begingroup$
      @Apollys Right, fixed.
      $endgroup$
      – Mathias Ettinger
      Dec 10 '18 at 20:11


















    • $begingroup$
      I would recommend writing expressions with a sign variable as sign * value to match the standard method of writing numbers.
      $endgroup$
      – Apollys
      Dec 10 '18 at 18:41










    • $begingroup$
      @Apollys Right, fixed.
      $endgroup$
      – Mathias Ettinger
      Dec 10 '18 at 20:11
















    $begingroup$
    I would recommend writing expressions with a sign variable as sign * value to match the standard method of writing numbers.
    $endgroup$
    – Apollys
    Dec 10 '18 at 18:41




    $begingroup$
    I would recommend writing expressions with a sign variable as sign * value to match the standard method of writing numbers.
    $endgroup$
    – Apollys
    Dec 10 '18 at 18:41












    $begingroup$
    @Apollys Right, fixed.
    $endgroup$
    – Mathias Ettinger
    Dec 10 '18 at 20:11




    $begingroup$
    @Apollys Right, fixed.
    $endgroup$
    – Mathias Ettinger
    Dec 10 '18 at 20:11













    6












    $begingroup$

    You can get rid of your counter and directly use i by using modular arithmetic. i % 10 == 0 is true whenever i is divisible by 10.



    You can get rid of your operand = operand * -1 by using itertools.cycle.



    from itertools import cycle

    result = 0
    for i, sign in zip(range(1, 101), cycle([1, -1])):
    result += sign * i
    if i % 10 == 0:
    print(result)


    The generation of result itself would be a lot more concise with a generator comprehension, but this excludes the progress prints:



    result = sum(sign * i for i, sign in zip(range(1, 101), cycle([1, -1])))





    share|improve this answer









    $endgroup$













    • $begingroup$
      @MathiasEttinger: It seems like MaartenFabre is already going in that direction in their answer.
      $endgroup$
      – Graipher
      Dec 10 '18 at 15:25










    • $begingroup$
      Yep, saw that after the comment
      $endgroup$
      – Mathias Ettinger
      Dec 10 '18 at 15:28
















    6












    $begingroup$

    You can get rid of your counter and directly use i by using modular arithmetic. i % 10 == 0 is true whenever i is divisible by 10.



    You can get rid of your operand = operand * -1 by using itertools.cycle.



    from itertools import cycle

    result = 0
    for i, sign in zip(range(1, 101), cycle([1, -1])):
    result += sign * i
    if i % 10 == 0:
    print(result)


    The generation of result itself would be a lot more concise with a generator comprehension, but this excludes the progress prints:



    result = sum(sign * i for i, sign in zip(range(1, 101), cycle([1, -1])))





    share|improve this answer









    $endgroup$













    • $begingroup$
      @MathiasEttinger: It seems like MaartenFabre is already going in that direction in their answer.
      $endgroup$
      – Graipher
      Dec 10 '18 at 15:25










    • $begingroup$
      Yep, saw that after the comment
      $endgroup$
      – Mathias Ettinger
      Dec 10 '18 at 15:28














    6












    6








    6





    $begingroup$

    You can get rid of your counter and directly use i by using modular arithmetic. i % 10 == 0 is true whenever i is divisible by 10.



    You can get rid of your operand = operand * -1 by using itertools.cycle.



    from itertools import cycle

    result = 0
    for i, sign in zip(range(1, 101), cycle([1, -1])):
    result += sign * i
    if i % 10 == 0:
    print(result)


    The generation of result itself would be a lot more concise with a generator comprehension, but this excludes the progress prints:



    result = sum(sign * i for i, sign in zip(range(1, 101), cycle([1, -1])))





    share|improve this answer









    $endgroup$



    You can get rid of your counter and directly use i by using modular arithmetic. i % 10 == 0 is true whenever i is divisible by 10.



    You can get rid of your operand = operand * -1 by using itertools.cycle.



    from itertools import cycle

    result = 0
    for i, sign in zip(range(1, 101), cycle([1, -1])):
    result += sign * i
    if i % 10 == 0:
    print(result)


    The generation of result itself would be a lot more concise with a generator comprehension, but this excludes the progress prints:



    result = sum(sign * i for i, sign in zip(range(1, 101), cycle([1, -1])))






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Dec 10 '18 at 15:12









    GraipherGraipher

    24.3k53586




    24.3k53586












    • $begingroup$
      @MathiasEttinger: It seems like MaartenFabre is already going in that direction in their answer.
      $endgroup$
      – Graipher
      Dec 10 '18 at 15:25










    • $begingroup$
      Yep, saw that after the comment
      $endgroup$
      – Mathias Ettinger
      Dec 10 '18 at 15:28


















    • $begingroup$
      @MathiasEttinger: It seems like MaartenFabre is already going in that direction in their answer.
      $endgroup$
      – Graipher
      Dec 10 '18 at 15:25










    • $begingroup$
      Yep, saw that after the comment
      $endgroup$
      – Mathias Ettinger
      Dec 10 '18 at 15:28
















    $begingroup$
    @MathiasEttinger: It seems like MaartenFabre is already going in that direction in their answer.
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:25




    $begingroup$
    @MathiasEttinger: It seems like MaartenFabre is already going in that direction in their answer.
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:25












    $begingroup$
    Yep, saw that after the comment
    $endgroup$
    – Mathias Ettinger
    Dec 10 '18 at 15:28




    $begingroup$
    Yep, saw that after the comment
    $endgroup$
    – Mathias Ettinger
    Dec 10 '18 at 15:28











    5












    $begingroup$

    instead of doing the +- by hand, you can use the fact that (-1) ** (i-1) * i for i in range(101) alternates the values



    Further on, you can use itertools.accumulate and itertools.islice to take the cumulative sum and select every 10th number



    numbers = (int((-1) ** (i-1) * i) for i in range(101))
    cum_sum = itertools.accumulate(numbers)
    numbers_10 = itertools.islice(cum_sum, 10, None, 10)

    for i in numbers_10:
    print(i)



    -5
    -10
    -15
    -20
    -25
    -30
    -35
    -40
    -45
    -50



    or alternatively, per 200_success' suggestion:



    numbers = (sign * i for sign, i in zip(itertools.cycle((1, -1)), itertools.count(1)))
    cum_sum = itertools.accumulate(numbers)
    numbers_10 = itertools.islice(cum_sum, 9, 100, 10)





    share|improve this answer











    $endgroup$













    • $begingroup$
      With this you do not get the final result, though. Maybe with a itertools.tee of the numbers, which you can then sum, but then it is no longer reporting on the progress...
      $endgroup$
      – Graipher
      Dec 10 '18 at 15:24












    • $begingroup$
      what do you mean with the final result? If needed, you need to do cum_sum = list(itertools.accumulate(numbers)) or numbers = [int((-1) ** (i-1) * i) for i in range(101)]
      $endgroup$
      – Maarten Fabré
      Dec 10 '18 at 15:37








    • 2




      $begingroup$
      I like this. Personally, I'd write it as cum_sum = accumulate(sign * n for sign, n in zip(cycle((+1, -1)), count())) to more elegantly express the idea of an infinite series, then extract just the relevant partial sums with for n in islice(cum_sum, 9, 100, 10): print(n).
      $endgroup$
      – 200_success
      Dec 11 '18 at 0:11
















    5












    $begingroup$

    instead of doing the +- by hand, you can use the fact that (-1) ** (i-1) * i for i in range(101) alternates the values



    Further on, you can use itertools.accumulate and itertools.islice to take the cumulative sum and select every 10th number



    numbers = (int((-1) ** (i-1) * i) for i in range(101))
    cum_sum = itertools.accumulate(numbers)
    numbers_10 = itertools.islice(cum_sum, 10, None, 10)

    for i in numbers_10:
    print(i)



    -5
    -10
    -15
    -20
    -25
    -30
    -35
    -40
    -45
    -50



    or alternatively, per 200_success' suggestion:



    numbers = (sign * i for sign, i in zip(itertools.cycle((1, -1)), itertools.count(1)))
    cum_sum = itertools.accumulate(numbers)
    numbers_10 = itertools.islice(cum_sum, 9, 100, 10)





    share|improve this answer











    $endgroup$













    • $begingroup$
      With this you do not get the final result, though. Maybe with a itertools.tee of the numbers, which you can then sum, but then it is no longer reporting on the progress...
      $endgroup$
      – Graipher
      Dec 10 '18 at 15:24












    • $begingroup$
      what do you mean with the final result? If needed, you need to do cum_sum = list(itertools.accumulate(numbers)) or numbers = [int((-1) ** (i-1) * i) for i in range(101)]
      $endgroup$
      – Maarten Fabré
      Dec 10 '18 at 15:37








    • 2




      $begingroup$
      I like this. Personally, I'd write it as cum_sum = accumulate(sign * n for sign, n in zip(cycle((+1, -1)), count())) to more elegantly express the idea of an infinite series, then extract just the relevant partial sums with for n in islice(cum_sum, 9, 100, 10): print(n).
      $endgroup$
      – 200_success
      Dec 11 '18 at 0:11














    5












    5








    5





    $begingroup$

    instead of doing the +- by hand, you can use the fact that (-1) ** (i-1) * i for i in range(101) alternates the values



    Further on, you can use itertools.accumulate and itertools.islice to take the cumulative sum and select every 10th number



    numbers = (int((-1) ** (i-1) * i) for i in range(101))
    cum_sum = itertools.accumulate(numbers)
    numbers_10 = itertools.islice(cum_sum, 10, None, 10)

    for i in numbers_10:
    print(i)



    -5
    -10
    -15
    -20
    -25
    -30
    -35
    -40
    -45
    -50



    or alternatively, per 200_success' suggestion:



    numbers = (sign * i for sign, i in zip(itertools.cycle((1, -1)), itertools.count(1)))
    cum_sum = itertools.accumulate(numbers)
    numbers_10 = itertools.islice(cum_sum, 9, 100, 10)





    share|improve this answer











    $endgroup$



    instead of doing the +- by hand, you can use the fact that (-1) ** (i-1) * i for i in range(101) alternates the values



    Further on, you can use itertools.accumulate and itertools.islice to take the cumulative sum and select every 10th number



    numbers = (int((-1) ** (i-1) * i) for i in range(101))
    cum_sum = itertools.accumulate(numbers)
    numbers_10 = itertools.islice(cum_sum, 10, None, 10)

    for i in numbers_10:
    print(i)



    -5
    -10
    -15
    -20
    -25
    -30
    -35
    -40
    -45
    -50



    or alternatively, per 200_success' suggestion:



    numbers = (sign * i for sign, i in zip(itertools.cycle((1, -1)), itertools.count(1)))
    cum_sum = itertools.accumulate(numbers)
    numbers_10 = itertools.islice(cum_sum, 9, 100, 10)






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 11 '18 at 9:08

























    answered Dec 10 '18 at 15:19









    Maarten FabréMaarten Fabré

    4,664417




    4,664417












    • $begingroup$
      With this you do not get the final result, though. Maybe with a itertools.tee of the numbers, which you can then sum, but then it is no longer reporting on the progress...
      $endgroup$
      – Graipher
      Dec 10 '18 at 15:24












    • $begingroup$
      what do you mean with the final result? If needed, you need to do cum_sum = list(itertools.accumulate(numbers)) or numbers = [int((-1) ** (i-1) * i) for i in range(101)]
      $endgroup$
      – Maarten Fabré
      Dec 10 '18 at 15:37








    • 2




      $begingroup$
      I like this. Personally, I'd write it as cum_sum = accumulate(sign * n for sign, n in zip(cycle((+1, -1)), count())) to more elegantly express the idea of an infinite series, then extract just the relevant partial sums with for n in islice(cum_sum, 9, 100, 10): print(n).
      $endgroup$
      – 200_success
      Dec 11 '18 at 0:11


















    • $begingroup$
      With this you do not get the final result, though. Maybe with a itertools.tee of the numbers, which you can then sum, but then it is no longer reporting on the progress...
      $endgroup$
      – Graipher
      Dec 10 '18 at 15:24












    • $begingroup$
      what do you mean with the final result? If needed, you need to do cum_sum = list(itertools.accumulate(numbers)) or numbers = [int((-1) ** (i-1) * i) for i in range(101)]
      $endgroup$
      – Maarten Fabré
      Dec 10 '18 at 15:37








    • 2




      $begingroup$
      I like this. Personally, I'd write it as cum_sum = accumulate(sign * n for sign, n in zip(cycle((+1, -1)), count())) to more elegantly express the idea of an infinite series, then extract just the relevant partial sums with for n in islice(cum_sum, 9, 100, 10): print(n).
      $endgroup$
      – 200_success
      Dec 11 '18 at 0:11
















    $begingroup$
    With this you do not get the final result, though. Maybe with a itertools.tee of the numbers, which you can then sum, but then it is no longer reporting on the progress...
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:24






    $begingroup$
    With this you do not get the final result, though. Maybe with a itertools.tee of the numbers, which you can then sum, but then it is no longer reporting on the progress...
    $endgroup$
    – Graipher
    Dec 10 '18 at 15:24














    $begingroup$
    what do you mean with the final result? If needed, you need to do cum_sum = list(itertools.accumulate(numbers)) or numbers = [int((-1) ** (i-1) * i) for i in range(101)]
    $endgroup$
    – Maarten Fabré
    Dec 10 '18 at 15:37






    $begingroup$
    what do you mean with the final result? If needed, you need to do cum_sum = list(itertools.accumulate(numbers)) or numbers = [int((-1) ** (i-1) * i) for i in range(101)]
    $endgroup$
    – Maarten Fabré
    Dec 10 '18 at 15:37






    2




    2




    $begingroup$
    I like this. Personally, I'd write it as cum_sum = accumulate(sign * n for sign, n in zip(cycle((+1, -1)), count())) to more elegantly express the idea of an infinite series, then extract just the relevant partial sums with for n in islice(cum_sum, 9, 100, 10): print(n).
    $endgroup$
    – 200_success
    Dec 11 '18 at 0:11




    $begingroup$
    I like this. Personally, I'd write it as cum_sum = accumulate(sign * n for sign, n in zip(cycle((+1, -1)), count())) to more elegantly express the idea of an infinite series, then extract just the relevant partial sums with for n in islice(cum_sum, 9, 100, 10): print(n).
    $endgroup$
    – 200_success
    Dec 11 '18 at 0:11











    1












    $begingroup$

    I would convert the sign flip into a generator, created via a generator comprehension, recognizing that evens should be negative:



    #  Integers from 1-100, where evens are negative: 1, -2, 3, -4, 5...
    sequence_gen = (i if i % 2 else -i for i in range(1,101))


    Equivalent to:



    def sequence_gen():
    for i in range(1, 101):
    if bool(i % 2): # For our purposes this is i % 2 == 1:
    yield i
    else:
    yield -i


    Then your code becomes:



    result = 0
    for index, number in enumerate(sequence_gen):
    result += number
    if index % 10 == 9: # Note the comparison change by starting at 0
    print(result)


    Note this is about half way to what Mathias proposed, and can be used in conjunction, the combination being:



    def sequence_sums(start, stop, step):
    result = 0
    seq_gen = (i if i % 2 else -i for i in range(start, stop + 1))
    for index, number in enumerate(seq_gen):
    result += number
    if index % step == step - 1:
    yield result




    You could even go one further step and make the sequence a parameter:



    # iterates through a sequence, printing every step'th sum
    def sequence_sums(sequence, step):
    result = 0
    for index, number in enumerate(sequence):
    result += number
    if index % step == step - 1:
    yield result


    Called via:



    sequence = (i if i % 2 else -i for i in range(1, 101))

    for sum in sequence_sums(sequence, 10):
    print(sum)





    share|improve this answer









    $endgroup$









    • 1




      $begingroup$
      Note the comparison change by starting at 0 => enumerate takes a second, optional, argument: start. So you can use enumerate(sequence, 1) and keep the usual comparison of the modulo to 0.
      $endgroup$
      – Mathias Ettinger
      Dec 11 '18 at 8:00
















    1












    $begingroup$

    I would convert the sign flip into a generator, created via a generator comprehension, recognizing that evens should be negative:



    #  Integers from 1-100, where evens are negative: 1, -2, 3, -4, 5...
    sequence_gen = (i if i % 2 else -i for i in range(1,101))


    Equivalent to:



    def sequence_gen():
    for i in range(1, 101):
    if bool(i % 2): # For our purposes this is i % 2 == 1:
    yield i
    else:
    yield -i


    Then your code becomes:



    result = 0
    for index, number in enumerate(sequence_gen):
    result += number
    if index % 10 == 9: # Note the comparison change by starting at 0
    print(result)


    Note this is about half way to what Mathias proposed, and can be used in conjunction, the combination being:



    def sequence_sums(start, stop, step):
    result = 0
    seq_gen = (i if i % 2 else -i for i in range(start, stop + 1))
    for index, number in enumerate(seq_gen):
    result += number
    if index % step == step - 1:
    yield result




    You could even go one further step and make the sequence a parameter:



    # iterates through a sequence, printing every step'th sum
    def sequence_sums(sequence, step):
    result = 0
    for index, number in enumerate(sequence):
    result += number
    if index % step == step - 1:
    yield result


    Called via:



    sequence = (i if i % 2 else -i for i in range(1, 101))

    for sum in sequence_sums(sequence, 10):
    print(sum)





    share|improve this answer









    $endgroup$









    • 1




      $begingroup$
      Note the comparison change by starting at 0 => enumerate takes a second, optional, argument: start. So you can use enumerate(sequence, 1) and keep the usual comparison of the modulo to 0.
      $endgroup$
      – Mathias Ettinger
      Dec 11 '18 at 8:00














    1












    1








    1





    $begingroup$

    I would convert the sign flip into a generator, created via a generator comprehension, recognizing that evens should be negative:



    #  Integers from 1-100, where evens are negative: 1, -2, 3, -4, 5...
    sequence_gen = (i if i % 2 else -i for i in range(1,101))


    Equivalent to:



    def sequence_gen():
    for i in range(1, 101):
    if bool(i % 2): # For our purposes this is i % 2 == 1:
    yield i
    else:
    yield -i


    Then your code becomes:



    result = 0
    for index, number in enumerate(sequence_gen):
    result += number
    if index % 10 == 9: # Note the comparison change by starting at 0
    print(result)


    Note this is about half way to what Mathias proposed, and can be used in conjunction, the combination being:



    def sequence_sums(start, stop, step):
    result = 0
    seq_gen = (i if i % 2 else -i for i in range(start, stop + 1))
    for index, number in enumerate(seq_gen):
    result += number
    if index % step == step - 1:
    yield result




    You could even go one further step and make the sequence a parameter:



    # iterates through a sequence, printing every step'th sum
    def sequence_sums(sequence, step):
    result = 0
    for index, number in enumerate(sequence):
    result += number
    if index % step == step - 1:
    yield result


    Called via:



    sequence = (i if i % 2 else -i for i in range(1, 101))

    for sum in sequence_sums(sequence, 10):
    print(sum)





    share|improve this answer









    $endgroup$



    I would convert the sign flip into a generator, created via a generator comprehension, recognizing that evens should be negative:



    #  Integers from 1-100, where evens are negative: 1, -2, 3, -4, 5...
    sequence_gen = (i if i % 2 else -i for i in range(1,101))


    Equivalent to:



    def sequence_gen():
    for i in range(1, 101):
    if bool(i % 2): # For our purposes this is i % 2 == 1:
    yield i
    else:
    yield -i


    Then your code becomes:



    result = 0
    for index, number in enumerate(sequence_gen):
    result += number
    if index % 10 == 9: # Note the comparison change by starting at 0
    print(result)


    Note this is about half way to what Mathias proposed, and can be used in conjunction, the combination being:



    def sequence_sums(start, stop, step):
    result = 0
    seq_gen = (i if i % 2 else -i for i in range(start, stop + 1))
    for index, number in enumerate(seq_gen):
    result += number
    if index % step == step - 1:
    yield result




    You could even go one further step and make the sequence a parameter:



    # iterates through a sequence, printing every step'th sum
    def sequence_sums(sequence, step):
    result = 0
    for index, number in enumerate(sequence):
    result += number
    if index % step == step - 1:
    yield result


    Called via:



    sequence = (i if i % 2 else -i for i in range(1, 101))

    for sum in sequence_sums(sequence, 10):
    print(sum)






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Dec 10 '18 at 23:22









    TemporalWolfTemporalWolf

    25427




    25427








    • 1




      $begingroup$
      Note the comparison change by starting at 0 => enumerate takes a second, optional, argument: start. So you can use enumerate(sequence, 1) and keep the usual comparison of the modulo to 0.
      $endgroup$
      – Mathias Ettinger
      Dec 11 '18 at 8:00














    • 1




      $begingroup$
      Note the comparison change by starting at 0 => enumerate takes a second, optional, argument: start. So you can use enumerate(sequence, 1) and keep the usual comparison of the modulo to 0.
      $endgroup$
      – Mathias Ettinger
      Dec 11 '18 at 8:00








    1




    1




    $begingroup$
    Note the comparison change by starting at 0 => enumerate takes a second, optional, argument: start. So you can use enumerate(sequence, 1) and keep the usual comparison of the modulo to 0.
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 8:00




    $begingroup$
    Note the comparison change by starting at 0 => enumerate takes a second, optional, argument: start. So you can use enumerate(sequence, 1) and keep the usual comparison of the modulo to 0.
    $endgroup$
    – Mathias Ettinger
    Dec 11 '18 at 8:00











    1












    $begingroup$

    The other answers are fine. Here is a mathematical analysis of the problem you're trying to solve.



    If this code is, for some reason, used in a performance-critical scenario, you can calculate the sum to $m$ in $O(1)$ time.



    Notice that:



    $$
    begin{align}
    1-2+3-4+5-6dots m &= -sum_{n=1}^{m}n(-1)^n \
    &= sum_{n=1}^{m}n(-1)^{n-1} \
    &= frac{1}{4}-frac{1}{4}(-1)^m(2m+1) ; ^*
    end{align}
    $$



    * There was a typo in my original comment.



    Because you only want to see every 10th result, we can substitute $m=10u$ where $uinmathbb{Z}$. This is fortunate because for all integers $(-1)^{10u} equiv 1$. Therefore:



    $$
    begin{align}
    frac{1}{4}-frac{1}{4}(-1)^{10u}(20u+1) &= frac{1}{4}-frac{1}{4}(20u+1) \
    &= frac{1}{4}-frac{20u+1}{4}\
    &= frac{(1-1)-20u}{4} \
    &= -5u
    end{align}
    $$



    Look familiar? It results in $-5$, $-10$, $-15$, ...



    This fact is obvious from the output, but now knowing the series that produces it, we can calculate the final result for any such $m$ quickly, and every 10th value even easier.



    We can avoid computing the exponent $(-1)^m$ because $(-1)^{m} = 1$ for even values of $m$ and $-1$ for odd values.



    I'm not as familiar with Python, but here's an example:



    def series(m):
    alt = 1 if m % 2 == 0 else -1
    return int(1/4 - 1/4 * alt * (2 * m + 1))

    def series_progress(m):
    return -5 * m

    m = 134

    for i in range(1, m // 10):
    print(series_progress(i))

    print(series(m))


    This avoids the costly computation for the final result. If we just needed the result it would be $O(1)$, but because we give "progress reports" it is more like $lfloorfrac{n}{10}rfloorin O(n)$.






    share|improve this answer











    $endgroup$


















      1












      $begingroup$

      The other answers are fine. Here is a mathematical analysis of the problem you're trying to solve.



      If this code is, for some reason, used in a performance-critical scenario, you can calculate the sum to $m$ in $O(1)$ time.



      Notice that:



      $$
      begin{align}
      1-2+3-4+5-6dots m &= -sum_{n=1}^{m}n(-1)^n \
      &= sum_{n=1}^{m}n(-1)^{n-1} \
      &= frac{1}{4}-frac{1}{4}(-1)^m(2m+1) ; ^*
      end{align}
      $$



      * There was a typo in my original comment.



      Because you only want to see every 10th result, we can substitute $m=10u$ where $uinmathbb{Z}$. This is fortunate because for all integers $(-1)^{10u} equiv 1$. Therefore:



      $$
      begin{align}
      frac{1}{4}-frac{1}{4}(-1)^{10u}(20u+1) &= frac{1}{4}-frac{1}{4}(20u+1) \
      &= frac{1}{4}-frac{20u+1}{4}\
      &= frac{(1-1)-20u}{4} \
      &= -5u
      end{align}
      $$



      Look familiar? It results in $-5$, $-10$, $-15$, ...



      This fact is obvious from the output, but now knowing the series that produces it, we can calculate the final result for any such $m$ quickly, and every 10th value even easier.



      We can avoid computing the exponent $(-1)^m$ because $(-1)^{m} = 1$ for even values of $m$ and $-1$ for odd values.



      I'm not as familiar with Python, but here's an example:



      def series(m):
      alt = 1 if m % 2 == 0 else -1
      return int(1/4 - 1/4 * alt * (2 * m + 1))

      def series_progress(m):
      return -5 * m

      m = 134

      for i in range(1, m // 10):
      print(series_progress(i))

      print(series(m))


      This avoids the costly computation for the final result. If we just needed the result it would be $O(1)$, but because we give "progress reports" it is more like $lfloorfrac{n}{10}rfloorin O(n)$.






      share|improve this answer











      $endgroup$
















        1












        1








        1





        $begingroup$

        The other answers are fine. Here is a mathematical analysis of the problem you're trying to solve.



        If this code is, for some reason, used in a performance-critical scenario, you can calculate the sum to $m$ in $O(1)$ time.



        Notice that:



        $$
        begin{align}
        1-2+3-4+5-6dots m &= -sum_{n=1}^{m}n(-1)^n \
        &= sum_{n=1}^{m}n(-1)^{n-1} \
        &= frac{1}{4}-frac{1}{4}(-1)^m(2m+1) ; ^*
        end{align}
        $$



        * There was a typo in my original comment.



        Because you only want to see every 10th result, we can substitute $m=10u$ where $uinmathbb{Z}$. This is fortunate because for all integers $(-1)^{10u} equiv 1$. Therefore:



        $$
        begin{align}
        frac{1}{4}-frac{1}{4}(-1)^{10u}(20u+1) &= frac{1}{4}-frac{1}{4}(20u+1) \
        &= frac{1}{4}-frac{20u+1}{4}\
        &= frac{(1-1)-20u}{4} \
        &= -5u
        end{align}
        $$



        Look familiar? It results in $-5$, $-10$, $-15$, ...



        This fact is obvious from the output, but now knowing the series that produces it, we can calculate the final result for any such $m$ quickly, and every 10th value even easier.



        We can avoid computing the exponent $(-1)^m$ because $(-1)^{m} = 1$ for even values of $m$ and $-1$ for odd values.



        I'm not as familiar with Python, but here's an example:



        def series(m):
        alt = 1 if m % 2 == 0 else -1
        return int(1/4 - 1/4 * alt * (2 * m + 1))

        def series_progress(m):
        return -5 * m

        m = 134

        for i in range(1, m // 10):
        print(series_progress(i))

        print(series(m))


        This avoids the costly computation for the final result. If we just needed the result it would be $O(1)$, but because we give "progress reports" it is more like $lfloorfrac{n}{10}rfloorin O(n)$.






        share|improve this answer











        $endgroup$



        The other answers are fine. Here is a mathematical analysis of the problem you're trying to solve.



        If this code is, for some reason, used in a performance-critical scenario, you can calculate the sum to $m$ in $O(1)$ time.



        Notice that:



        $$
        begin{align}
        1-2+3-4+5-6dots m &= -sum_{n=1}^{m}n(-1)^n \
        &= sum_{n=1}^{m}n(-1)^{n-1} \
        &= frac{1}{4}-frac{1}{4}(-1)^m(2m+1) ; ^*
        end{align}
        $$



        * There was a typo in my original comment.



        Because you only want to see every 10th result, we can substitute $m=10u$ where $uinmathbb{Z}$. This is fortunate because for all integers $(-1)^{10u} equiv 1$. Therefore:



        $$
        begin{align}
        frac{1}{4}-frac{1}{4}(-1)^{10u}(20u+1) &= frac{1}{4}-frac{1}{4}(20u+1) \
        &= frac{1}{4}-frac{20u+1}{4}\
        &= frac{(1-1)-20u}{4} \
        &= -5u
        end{align}
        $$



        Look familiar? It results in $-5$, $-10$, $-15$, ...



        This fact is obvious from the output, but now knowing the series that produces it, we can calculate the final result for any such $m$ quickly, and every 10th value even easier.



        We can avoid computing the exponent $(-1)^m$ because $(-1)^{m} = 1$ for even values of $m$ and $-1$ for odd values.



        I'm not as familiar with Python, but here's an example:



        def series(m):
        alt = 1 if m % 2 == 0 else -1
        return int(1/4 - 1/4 * alt * (2 * m + 1))

        def series_progress(m):
        return -5 * m

        m = 134

        for i in range(1, m // 10):
        print(series_progress(i))

        print(series(m))


        This avoids the costly computation for the final result. If we just needed the result it would be $O(1)$, but because we give "progress reports" it is more like $lfloorfrac{n}{10}rfloorin O(n)$.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 11 '18 at 23:13

























        answered Dec 11 '18 at 23:05









        esoteesote

        2,6761935




        2,6761935






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209364%2fprinting-every-10th-result-in-an-alternating-%25c2%25b1-series%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How do I know what Microsoft account the skydrive app is syncing to?

            When does type information flow backwards in C++?

            Grease: Live!