Mutual recursion - Naming the opponent serve - pingpong Problem statement
Ping-pong

The ping-pong sequence counts up starting from 1 and is always either counting up or counting down. At element k, the direction switches if k is a multiple of 7 or contains the digit 7. The first 30 elements of the ping-pong sequence are listed below, with direction swaps marked using brackets at the 7th, 14th, 17th, 21st, 27th, and 28th elements:




Implement a function pingpong that returns the nth element of the ping-pong sequence without using any assignment statements.


You may use the function num_sevens, which you defined in the previous question.


Use recursion - the tests will fail if you use any assignment statements.


Hint: If you're stuck, first try implementing pingpong using assignment statements and a while statement. Then, to convert this into a recursive solution, write a helper function that has a parameter for each variable that changes values in the body of the while loop.

def pingpong(n):
    &quot;&quot;&quot;Return the nth element of the ping-pong sequence.

    &gt;&gt;&gt; pingpong(7)
    7
    &gt;&gt;&gt; pingpong(8)
    6
    &gt;&gt;&gt; pingpong(15)
    1
    &gt;&gt;&gt; pingpong(21)
    -1
    &gt;&gt;&gt; pingpong(22)
    0
    &gt;&gt;&gt; pingpong(30)
    6
    &gt;&gt;&gt; pingpong(68)
    2
    &gt;&gt;&gt; pingpong(69)
    1
    &gt;&gt;&gt; pingpong(70)
    0
    &gt;&gt;&gt; pingpong(71)
    1
    &gt;&gt;&gt; pingpong(72)
    0
    &gt;&gt;&gt; pingpong(100)
    2
    &gt;&gt;&gt; from construct_check import check
    &gt;&gt;&gt; # ban assignment statements
    &gt;&gt;&gt; check(HW_SOURCE_FILE, 'pingpong', ['Assign', 'AugAssign'])
    True
    &quot;&quot;&quot;
    &quot;*** YOUR CODE HERE ***&quot;


Solution
package main

import &quot;fmt&quot;

func numSevens(x int) int {
    if x == 0 {
        return 0
    }
    if x%10 == 7 {
        return 1 + numSevens(x/10)
    } else {
        return numSevens(x / 10)
    }
}


func pingPong(n int) int {

    var player1 func(int, int, bool) int
    var player2 func(int, int, bool) int
    player1 = func(currentIndex int, pingPongValue int, receiveOpponentBall bool) int {
        if currentIndex == n {
            return pingPongValue
        }

        if receiveOpponentBall {
            return player1(currentIndex+1, pingPongValue+1, false)
        }

        if numSevens(currentIndex) &gt; 0 || currentIndex%7 == 0 {
            return player2(currentIndex, pingPongValue, true)
        }
        return player1(currentIndex+1, pingPongValue+1, false)
    }

    player2 = func(currentIndex int, pingPongValue int, receiveOpponentBall bool) int {
        if currentIndex == n {
            return pingPongValue
        }

        if receiveOpponentBall {
            return player2(currentIndex+1, pingPongValue-1, false)
        }
        if numSevens(currentIndex) &gt; 0 || currentIndex%7 == 0 {
            return player1(currentIndex, pingPongValue, true)
        }
        return player2(currentIndex+1, pingPongValue-1, false)
    }

    return player1(1, 1, false)
}

func main() {
    //fmt.Println(numSevens(12345))
    fmt.Println(pingPong(29))
}


Below code is written without using mutual recursion:
func pingPongRecur(n int) int {
    toggleValue := 1 ^ -1
    increment := 1

    var runSequence func(int, int) int
    runSequence = func(currentIndex int, pingPongValue int) int {
        if currentIndex == n {
            return pingPongValue
        }
        if numSevens(currentIndex) &gt; 0 || currentIndex%7 == 0 {
            increment ^= toggleValue
        }
        return runSequence(currentIndex+1, pingPongValue+increment)

    }
    return runSequence(1, 1)
}



How to give better name than receiveOpponentBall variable? How to  improve other variable naming convention? based on given problem statement.

Please add improvements in the above code from aspect of readability &amp; good abstraction
From the problem statement:

Implement a function pingpong that returns the nth element of the
ping-pong sequence without using any assignment statements.
You may use the function num_sevens, which you defined in the previous
question.
Use recursion - the tests will fail if you use any assignment
statements.
Hint: If you're stuck, first try implementing pingpong using
assignment statements and a while statement. Then, to convert this
into a recursive solution, write a helper function that has a
parameter for each variable that changes values in the body of the
while loop.


Code should be correct, maintainable, robust, reasonably efficient, and, most importantly, readable.

Your first solution makes far too much of a simple switch in the increment value with duplicated functions differing merely in the literal integer values 1 and -1. It requires a diff comparison to find the small, obscure differences between the largely duplicate player1 and player2 functions. Duplication of code hurts maintainability. The solution introduces an obscure player abstraction which is not part of the problem statement. It is not readable. Also, the solution uses multiple assignment statements for the player function variables: &quot;the tests will fail if you use any assignment statements.&quot;

While the problem statement did say you may use num_sevens, this problem asks &quot;if k contains the digit 7&quot;. To count all occurences of digit 7 when we only care about the first occurence is inefficient.

Your second solution, &quot;code written without using mutual recursion&quot;, which you added later, is clearly incorrect. It uses multiple assignment statements: &quot;the tests will fail if you use any assignment statements.&quot; For no apparent reason, you use the name toogle instead of switch and you complicate things by introducing a toggleValue variable.
toggleValue := 1 ^ -1
increment := 1
. . .
        increment ^= toggleValue

The toggleValue variable is unnecessary and the toggle algorithm is obscure. Simplicity is a virtue.
increment := 1
. . .
        increment *= -1 // switch


The Problem Statement is an academic problem designed to discover if you have learned some fundamental programming concepts: recursion and no assignment statements. The Hint gives a detailed road-map to a solution. You did not answer the problem as stated so you get an F.

Here is an example of the sort of solution that the problem statement likely expected:

Use recursion. First try implementing pingpong using assignment
statements and a while statement. Then, to convert this into a
recursive solution, write a helper function that has a parameter for
each variable that changes values in the body of the while loop.

package main

import &quot;fmt&quot;

func digitSeven(x int) bool {
    if x &lt;= 0 {
        return false
    }
    if x%10 == 7 {
        return true
    }
    return digitSeven(x / 10)
}

func increment(incr int, x int) int {
    if x%7 == 0 || digitSeven(x) {
        return incr * -1
    }
    return incr
}

func pingpong(n int, i int, v int, incr int) int {
    if i &gt; n {
        return v
    }
    return pingpong(n, i+1, v+incr, increment(incr, i))
}

func PingPong(n int) int {
    return pingpong(n, 1, 0, 1)
}

func main() {
    for n := 1; n &lt;= 30; n++ {
        fmt.Println(n, PingPong(n))
    }
}

Playground: https://play.golang.org/p/8H6l-CpLlye
Output:
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 6
9 5
10 4
11 3
12 2
13 1
14 0
15 1
16 2
17 3
18 2
19 1
20 0
21 -1
22 0
23 1
24 2
25 3
26 4
27 5
28 4
29 5
30 6