How to resolve the algorithm Casting out nines step by step in the Go programming language

Published on 12 May 2024 09:40 PM
#Go

How to resolve the algorithm Casting out nines step by step in the Go programming language

Table of Contents

Problem Statement

Write a procedure (say

c o 9

( x )

{\displaystyle {\mathit {co9}}(x)}

) which implements Casting Out Nines as described by returning the checksum for

x

{\displaystyle x}

. Demonstrate the procedure using the examples given there, or others you may consider lucky. Note that this function does nothing more than calculate the least positive residue, modulo 9. Many of the solutions omit Part 1 for this reason. Many languages have a modulo operator, of which this is a trivial application. With that understanding, solutions to Part 1, if given, are encouraged to follow the naive pencil-and-paper or mental arithmetic of repeated digit addition understood to be "casting out nines", or some approach other than just reducing modulo 9 using a built-in operator. Solutions for part 2 and 3 are not required to make use of the function presented in part 1. Notwithstanding past Intel microcode errors, checking computer calculations like this would not be sensible. To find a computer use for your procedure: Demonstrate that your procedure can be used to generate or filter a range of numbers with the property

c o 9

( k )

c o 9

(

k

2

)

{\displaystyle {\mathit {co9}}(k)={\mathit {co9}}(k^{2})}

and show that this subset is a small proportion of the range and contains all the Kaprekar in the range. Considering this MathWorld page, produce a efficient algorithm based on the more mathematical treatment of Casting Out Nines, and realizing: Demonstrate your algorithm by generating or filtering a range of numbers with the property

k % (

B a s e

− 1 )

(

k

2

) % (

B a s e

− 1 )

{\displaystyle k%({\mathit {Base}}-1)==(k^{2})%({\mathit {Base}}-1)}

and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Casting out nines step by step in the Go programming language

The provided Go code implements the casting out nines algorithm, which is used to determine if a number is divisible by 9 without actually performing the division operation.

Function co9Peterson

The co9Peterson function takes a base as input and returns a closure function cob that performs the casting out nines algorithm in the specified base. The function cob takes a string representing a number in the specified base as input and returns a byte representing the check digit of the number.

The casting out nines algorithm works by repeatedly adding the digits of a number until a single digit is obtained. If the single digit is 9, then the original number is divisible by 9.

The function addDigits is used to add two digits in the specified base. The function uses the strconv package to convert the digits to integers, adds the integers, and then converts the result back to a string.

The function cob uses a loop to iterate over the digits of the input number. For each digit, the function checks if the digit is equal to the '9' digit in the specified base. If the digit is equal to '9', then it is ignored. Otherwise, the function adds the digit to the current check digit.

After the loop has finished, the function returns the check digit.

Function subset

The subset function takes a base, a beginning number, and an ending number as input and returns a slice of strings representing the candidate Kaprekar numbers in the specified range.

A Kaprekar number is a number whose square, when written in the same base, can be split into two parts that add up to the original number.

The function subset uses the casting out nines algorithm to test if a number is a candidate Kaprekar number. The function first converts the beginning and ending numbers to integers and then generates a casting out nines function for the specified base.

The function then iterates over the range of numbers from the beginning number to the ending number. For each number, the function converts the number to a string and then calls the casting out nines function to get the check digit. The function also calculates the check digit of the square of the number.

If the check digit of the number is equal to the check digit of the square of the number, then the number is a candidate Kaprekar number and is added to the slice of strings.

After the loop has finished, the function returns the slice of strings.

Main Function

The main function tests the subset function with several test cases. For each test case, the main function prints the subset of candidate Kaprekar numbers and the expected Kaprekar numbers. The main function also checks if the subset contains all of the expected Kaprekar numbers.

Example

Here is an example of how to use the subset function to find the candidate Kaprekar numbers in base 10 between 1 and 100:

import "fmt"

func main() {
   s, err := subset(10, "1", "100")
   if err != nil {
       log.Fatal(err)
   }
   fmt.Println(s)
}

Source code in the go programming language

package main

import (
    "fmt"
    "log"
    "strconv"
)

// A casting out nines algorithm.

// Quoting from: http://mathforum.org/library/drmath/view/55926.html
/*
First, for any number we can get a single digit, which I will call the 
"check digit," by repeatedly adding the digits. That is, we add the 
digits of the number, then if there is more than one digit in the 
result we add its digits, and so on until there is only one digit 
left.

...

You may notice that when you add the digits of 6395, if you just 
ignore the 9, and the 6+3 = 9, you still end up with 5 as your check 
digit. This is because any 9's make no difference in the result. 
That's why the process is called "casting out" nines. Also, at any 
step in the process, you can add digits, not just at the end: to do 
8051647, I can say 8 + 5 = 13, which gives 4; plus 1 is 5, plus 6 is 
11, which gives 2, plus 4 is 6, plus 7 is 13 which gives 4. I never 
have to work with numbers bigger than 18.
*/
// The twist is that co9Peterson returns a function to do casting out nines
// in any specified base from 2 to 36.
func co9Peterson(base int) (cob func(string) (byte, error), err error) {
    if base < 2 || base > 36 {
        return nil, fmt.Errorf("co9Peterson: %d invalid base", base)
    }
    // addDigits adds two digits in the specified base.
    // People perfoming casting out nines by hand would usually have their
    // addition facts memorized.  In a program, a lookup table might be
    // analogous, but we expediently use features of the programming language
    // to add digits in the specified base.
    addDigits := func(a, b byte) (string, error) {
        ai, err := strconv.ParseInt(string(a), base, 64)
        if err != nil {
            return "", err
        }
        bi, err := strconv.ParseInt(string(b), base, 64)
        if err != nil {
            return "", err
        }
        return strconv.FormatInt(ai+bi, base), nil
    }
    // a '9' in the specified base.  that is, the greatest digit.
    s9 := strconv.FormatInt(int64(base-1), base)
    b9 := s9[0]
    // define result function.  The result function may return an error
    // if n is not a valid number in the specified base.
    cob = func(n string) (r byte, err error) {
        r = '0'
        for i := 0; i < len(n); i++ { // for each digit of the number
            d := n[i]
            switch {
            case d == b9: // if the digit is '9' of the base, cast it out
                continue
            // if the result so far is 0, the digit becomes the result
            case r == '0':
                r = d
                continue
            }
            // otherwise, add the new digit to the result digit
            s, err := addDigits(r, d)
            if err != nil {
                return 0, err
            }
            switch {
            case s == s9: // if the sum is "9" of the base, cast it out
                r = '0'
                continue
            // if the sum is a single digit, it becomes the result
            case len(s) == 1:
                r = s[0]
                continue
            }
            // otherwise, reduce this two digit intermediate result before
            // continuing.
            r, err = cob(s)
            if err != nil {
                return 0, err
            }
        }
        return
    }
    return
}

// Subset code required by task.  Given a base and a range specified with
// beginning and ending number in that base, return candidate Kaprekar numbers
// based on the observation that k%(base-1) must equal (k*k)%(base-1).
// For the % operation, rather than the language built-in operator, use
// the method of casting out nines, which in fact implements %(base-1).
func subset(base int, begin, end string) (s []string, err error) {
    // convert begin, end to native integer types for easier iteration
    begin64, err := strconv.ParseInt(begin, base, 64)
    if err != nil {
        return nil, fmt.Errorf("subset begin: %v", err)
    }
    end64, err := strconv.ParseInt(end, base, 64)
    if err != nil {
        return nil, fmt.Errorf("subset end: %v", err)
    }
    // generate casting out nines function for specified base
    cob, err := co9Peterson(base)
    if err != nil {
        return
    }
    for k := begin64; k <= end64; k++ {
        ks := strconv.FormatInt(k, base)
        rk, err := cob(ks)
        if err != nil { // assertion
            panic(err) // this would indicate a bug in subset
        }
        rk2, err := cob(strconv.FormatInt(k*k, base))
        if err != nil { // assertion
            panic(err) // this would indicate a bug in subset
        }
        // test for candidate Kaprekar number
        if rk == rk2 {
            s = append(s, ks)
        }
    }
    return
}

var testCases = []struct {
    base       int
    begin, end string
    kaprekar   []string
}{
    {10, "1", "100", []string{"1", "9", "45", "55", "99"}},
    {17, "10", "gg", []string{"3d", "d4", "gg"}},
}
    
func main() {
    for _, tc := range testCases {
        fmt.Printf("\nTest case base = %d, begin = %s, end = %s:\n",
            tc.base, tc.begin, tc.end)
        s, err := subset(tc.base, tc.begin, tc.end)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("Subset:  ", s)
        fmt.Println("Kaprekar:", tc.kaprekar)
        sx := 0
        for _, k := range tc.kaprekar {
            for {
                if sx == len(s) {
                    fmt.Printf("Fail:", k, "not in subset")
                    return
                }
                if s[sx] == k {
                    sx++
                    break
                }
                sx++
            }
        }
        fmt.Println("Valid subset.")
    }
}


  

You may also check:How to resolve the algorithm Miller–Rabin primality test step by step in the Java programming language
You may also check:How to resolve the algorithm Greedy algorithm for Egyptian fractions step by step in the Microsoft Small Basic programming language
You may also check:How to resolve the algorithm Sorting algorithms/Bead sort step by step in the Clojure programming language
You may also check:How to resolve the algorithm Zeckendorf number representation step by step in the Scheme programming language
You may also check:How to resolve the algorithm String case step by step in the DBL programming language