Home > Software design >  Test if a permutation of a number exists in a collection
Test if a permutation of a number exists in a collection

Time:10-22

I'm trying to list all numbers with 3 digits where the individual digits sum to a given number.

So far I can return a list of all numbers using this Visual Basic code:

target = 17
i = 1
j = 1
k = 1

Do While i < 10
    Do While j < 10
        Do While k < 10
            r = i   j   k
            If r = target Then
                If i <> j And j <> k And k <> i Then
                    lsNumbers.Add(i & j & k )
                End If
            End If
            k  = 1
        Loop
        If k = 10 Then k = 1
        j  = 1
    Loop
    If j = 10 Then j = 1
    i  = 1
Loop

But I want only unique, non repeating combinations.

For example for the target number 17:

179, 197, 269, 278, 287...

I want to be able to test the current number before I add it to the list, to check if it is a combination of a number already in the list - so 197 would fail because of 179, and 287 would fail because of 278

CodePudding user response:

Observations

Just curious, is excluding the 0 digit on purpose?

To iterate through the possible digits, a well suited instruction pair is FOR NEXT. Definitely simpler than the DO WHILE that you used.

  Loop
  If k = 10 Then k = 1
Loop
If j = 10 Then j = 1

Upon loop completion, the iterator is sure to contain 10. The IF is redundant.

Solution

In order to check if a number, that obeys the condition, is unique in the sense that it is not composed of the same 3 digits as an already validated number, you could consult a 3-D array. If the new number corresponds to a non-zero element in this array, it means that the new number would be using the same digits as an earlier number. That's reason to reject it.

Next code runs in QBasic. You'll have no trouble rewriting it for Visual BASIC.

DIM r%(1 TO 9, 1 TO 9, 1 TO 9)
FOR i% = 1 TO 9
  FOR j% = 1 TO 9
    FOR k% = 1 TO 9
      r%(i%, j%, k%) = 0
    NEXT
  NEXT
NEXT
target% = 17
FOR i% = 1 TO 9
  FOR j% = 1 TO 9
    FOR k% = 1 TO 9
      IF i%   j%   k% = target% THEN
        IF r%(i%, j%, k%) = 0 THEN
          PRINT i% * 100   j% * 10   k%; " ";
          r%(i%, j%, k%) = 1  ' Could do without this one because of the ascending order
          r%(i%, k%, j%) = 1
          r%(j%, i%, k%) = 1
          r%(j%, k%, i%) = 1
          r%(k%, i%, j%) = 1
          r%(k%, j%, i%) = 1
        END IF
      END IF
    NEXT
  NEXT
NEXT

This is my output of valid numbers:

179 188 269 278 359 368 377 449 458 467 557 566 
  • Related