1

I am trying to create an additive persistence program where the user inputs a number and the program outputs the total number of iterations (or additive persistence).

I want to code it so that I do not use the string data type.
Are there any built-in functions or otherwise that I can use so that I can split a large number into its separate digits?

Things to note:

  1. I am coding in a console application in VB.Net
  2. I am relatively new at coding
GSerg
  • 76,472
  • 17
  • 159
  • 346
FZCube42
  • 35
  • 1
  • 8
  • 2
    Question is not clear, can you give an example how the app should work? – HojjatK Feb 11 '20 at 18:05
  • 1
    @HojjatK https://en.wikipedia.org/wiki/Persistence_of_a_number – GSerg Feb 11 '20 at 18:13
  • 1
    Does this answer your question? [Is there an easy way to turn an int into an array of ints of each digit?](https://stackoverflow.com/questions/829174/is-there-an-easy-way-to-turn-an-int-into-an-array-of-ints-of-each-digit) – GSerg Feb 11 '20 at 18:15
  • Why do you not want to turn it into a string? – Kenneth K. Feb 11 '20 at 18:17

2 Answers2

2

To get the last digit of a number in base 10, you can use the modulo operator, known as Mod, thus:

1234 Mod 10 = 4
32 Mod 10 = 2

and so on.

When you have the last digit, it can in essence be chopped off by using integer division:

1234 \ 10 = 123
32 \ 10 = 3

So now the process can be repeated to get what has become the last digit. Once the original number has been reduced to 0, the algorithm has finished.

As you don't need the digits in any particular order, we don't have to worry about that.

So, given:

Function GetDigits(n As Int64) As List(Of Int64)
    Dim digits As New List(Of Int64)
    While n > 0
        digits.Add(n Mod 10)
        n = n \ 10
    End While

    Return digits

End Function

You could do:

Console.WriteLine(String.Join(" ", GetDigits(12345678900)))

to get an output of:

0 0 9 8 7 6 5 4 3 2 1

I used an Int64 (a.k.a. Long) for the parameter of GetDigits so that you can use numbers with more digits than an Int32 (a.k.a. Integer) can hold.

From that, you can:

Function AdditivePersistence(n As Int64) As Integer
    Dim pers = 0
    While n > 9
        pers += 1
        n = GetDigits(n).Sum()
    End While

    Return pers

End Function
Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • If you are returning a List of digits, why are these Int64? Given that the only possible values are 0-9, then `List` is more than adequate and would be a much better description of the values that you are returning. – Jonathan Willcock Feb 11 '20 at 22:46
  • @JonathanWillcock It avoids the extra conversion step of `digits.Add(Convert.ToInt32(n Mod 10))`, and costs pretty much nothing as the OP is unlikely to be worried about memory usage. As I mentioned, I used Int64s so that there are more digits available to play with. Of course, it could be changed to use the BigInteger type from System.Numerics if even more digits were desired. An Int16 would only be a nuisance at best: [Int16 - bytes capacity in.net?](https://stackoverflow.com/q/17511737/1115360) – Andrew Morton Feb 12 '20 at 09:24
  • @AndrewMorton could the same code be used with a queue instead of a list? The only reason I'm asking is that I'm not as familiar with lists as I am with queues. Would a queue accomplish the same things as a list in your code? – FZCube42 Feb 13 '20 at 07:35
  • @FZCube42 I'm not sure that a queue would add anything to the solution compared to using a list. I've added an example of how the function could be used to help with calculating additive persistence; as you can see, it is easy to get the sum of the elements of a list. – Andrew Morton Feb 13 '20 at 09:15
  • @AndrewMorton I have managed to implement your example code into my program using a queue. I thank you for clear and helpful assistance. :) -FZ – FZCube42 Feb 13 '20 at 16:46
-2

You can do this using LINQ with Math functions.

Function getSum(number As Integer) As Integer
    Return CInt(Enumerable.Range(0, CInt(Math.Round(Math.Log10(number), 0)) + 1).
                Select(Function(i) Math.Truncate(number / (10 ^ i)) Mod 10).Sum())
End Function
  • Enumerable.Range: creates integers from 0 to log10 of number. This is the number of digits - 1.
  • Select: divides the number by (10 ^ the integer), removes decimals, performs modulo 10 to get just the ones portion.
  • Sum: sums these numbers

Put it in a loop in a function which counts how many times we have claled the function until the result is < 9

Function persistence(number As Integer) As Integer
    Dim count = 0
    Console.WriteLine($"Original Number: {number}")
    Do
        number = getSum(number)
        Console.WriteLine($"Number: {number}")
        count += 1
    Loop While number > 9
    Console.WriteLine($"Persistence: {count}")
    Return count
End Function
persistence(2718)

Original Number: 2718
Number: 18
Number: 9
Persistence: 2

It is simpler with strings. Although you said you don't want to use strings, here is a solution with them.

Function getSum(number As Integer) As Integer
    Return number.ToString().Sum(Function(c) CInt(c.ToString()))
End Function
  • Convert the individual characters in the number's string to numbers and sum them.
djv
  • 15,168
  • 7
  • 48
  • 72
  • @kiLLua It wasn't me, but probably because someone noticed that the OP wants to avoid using strings. Also, it appears that someone else has recently come along and downvoted everything in this Q&A too. – Andrew Morton Feb 13 '20 at 20:43