Home > database >  How do I generate a nested array that contains all possible 4 digit permutations 6 numbers with repe
How do I generate a nested array that contains all possible 4 digit permutations 6 numbers with repe

Time:06-08

Given a number of digits n = 1, 2, 3, 4, 5, 6.

I wanted to generate a nested array S that will contain all possible 4 digit permutations of n. since 6^4 = 1296, there will be 1296 possible permutations.

Example: S = [[1,1,1,1],[1,1,1,2],[1,1,2,2]...[6,6,6,6]]

I started the nested loop with the first index with value of [1,1,1,1] Then used a for in loop with range 0..1295 and tried to carry over the value of S[i] to S[i 1] then increment the value of S[i 1][x], where x always starts at 3 then is decremented until it reaches 0 then it becomes 3 again. The problem with my procedure is when i try to increment the S[i 1][x], S[i] also increments its S[i][x]. In the code below S is instead called 'all_possible_combinations'

all_possible_combinations = Array.new(1296) {Array.new(4)}
all_possible_combinations[0] = [1, 1 ,1 ,1]
x = 3
for i in 0..1295
    if i   1 == 1296
        break
    else
        all_possible_combinations[i 1] = all_possible_combinations[i]
        all_possible_combinations[i 1][x]  = 1
        x -= 1
        if x == 0
            x = 3
        end
    end
end

[Attached image shows debugging process where Si][x] also gets incremented

CodePudding user response:

You may compute that array as follows.

a = [1, 2, 3, 4, 5, 6]
b = a.repeated_permutation(4).to_a
  #=> [[1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 1, 3], [1, 1, 1, 4], [1, 1, 1, 5],
  #    [1, 1, 1, 6], [1, 1, 2, 1], [1, 1, 2, 2], [1, 1, 2, 3], [1, 1, 2, 4],
  #    ...
  #    [6, 6, 5, 3], [6, 6, 5, 4], [6, 6, 5, 5], [6, 6, 5, 6], [6, 6, 6, 1],
  #    [6, 6, 6, 2], [6, 6, 6, 3], [6, 6, 6, 4], [6, 6, 6, 5], [6, 6, 6, 6]]
b.size
  #=> 1296

See Array#repeated_permutation

If the array a may contain duplicates and you wish to remove duplicate permutations you may wish to tack on Array#uniq.

a = [1, 1, 3, 1, 1, 6]
b = a.repeated_permutation(4).to_a.uniq
  #=> [[1, 1, 1, 1], [1, 1, 1, 3], [1, 1, 1, 6], [1, 1, 3, 1],
  #    [1, 1, 3, 3], [1, 1, 3, 6], [1, 1, 6, 1], [1, 1, 6, 3], 
  #    [1, 1, 6, 6], [1, 3, 1, 1], [1, 3, 1, 3], [1, 3, 1, 6],       
  #    [1, 3, 3, 1], [1, 3, 3, 3], [1, 3, 3, 6], [1, 3, 6, 1],
  #    [1, 3, 6, 3], [1, 3, 6, 6], [1, 6, 1, 1], [1, 6, 1, 3],
  #    [1, 6, 1, 6], [1, 6, 3, 1], [1, 6, 3, 3], [1, 6, 3, 6],
  #    [1, 6, 6, 1], [1, 6, 6, 3], [1, 6, 6, 6], [3, 1, 1, 1],
  #    [3, 1, 1, 3], [3, 1, 1, 6], [3, 1, 3, 1], [3, 1, 3, 3],
  #    [3, 1, 3, 6], [3, 1, 6, 1], [3, 1, 6, 3], [3, 1, 6, 6],
  #    [3, 3, 1, 1], [3, 3, 1, 3], [3, 3, 1, 6], [3, 3, 3, 1],
  #    [3, 3, 3, 3], [3, 3, 3, 6], [3, 3, 6, 1], [3, 3, 6, 3],
  #    [3, 3, 6, 6], [3, 6, 1, 1], [3, 6, 1, 3], [3, 6, 1, 6],
  #    [3, 6, 3, 1], [3, 6, 3, 3], [3, 6, 3, 6], [3, 6, 6, 1],
  #    [3, 6, 6, 3], [3, 6, 6, 6], [6, 1, 1, 1], [6, 1, 1, 3],
  #    [6, 1, 1, 6], [6, 1, 3, 1], [6, 1, 3, 3], [6, 1, 3, 6],
  #    [6, 1, 6, 1], [6, 1, 6, 3], [6, 1, 6, 6], [6, 3, 1, 1],
  #    [6, 3, 1, 3], [6, 3, 1, 6], [6, 3, 3, 1], [6, 3, 3, 3],
  #    [6, 3, 3, 6], [6, 3, 6, 1], [6, 3, 6, 3], [6, 3, 6, 6],
  #    [6, 6, 1, 1], [6, 6, 1, 3], [6, 6, 1, 6], [6, 6, 3, 1],
  #    [6, 6, 3, 3], [6, 6, 3, 6], [6, 6, 6, 1], [6, 6, 6, 3],
  #    [6, 6, 6, 6]]
b.size
  #=> 81

CodePudding user response:

To create a sequence where each element is generated based on the previous one, there's Enumerator.produce, e.g.:

enum = Enumerator.produce([1, 1, 1, 1]) do |a, b, c, d|
  d  = 1                # ^^^^^^^^^^^^
                        # initial value
  if d > 6
    d = 1
    c  = 1
  end

  if c > 6
    c = 1
    b  = 1
  end

  if b > 6
    b = 1
    a  = 1
  end

  if a > 6
    raise StopIteration # <- stops enumeration
  end

  [a, b, c, d]          # <- return value = next value
end

I've kept the example intentionally simple, using an explicit variable for each of the four digits. You could of course also have an array and use a little loop to handle the increment / carry.

The above gives you:

enum.count        #=> 1296
enum.first(3)     #=> [[1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 1, 3]]
enum.to_a.last(3) #=> [[6, 6, 6, 4], [6, 6, 6, 5], [6, 6, 6, 6]]
  •  Tags:  
  • ruby
  • Related