How to ignore certain elements in a list that will undergo a random process? (pending)

2

This program finds magic squares 3x3 by brute force and automatically prints when you find one.

code:

import random

vetor = [1, 2, 3, 4, 5, 6, 7, 8, 9]

def magicsquare():
    return vetor[0]+vetor[1]+vetor[2]==\
           vetor[3]+vetor[4]+vetor[5]==\
           vetor[6]+vetor[7]+vetor[8]==\
           vetor[0]+vetor[3]+vetor[6]==\
           vetor[1]+vetor[4]+vetor[7]==\
           vetor[2]+vetor[5]+vetor[8]==\
           vetor[0]+vetor[4]+vetor[8]==\
           vetor[2]+vetor[4]+vetor[6]

while not magicsquare():
    random.shuffle(vetor)

print (vetor)

The program running on repl:

link

I can not do a particular function:

Knowing that in a magic square 3x3 , the number 5 will always be in the middle, I would like to already leave it in the middle, that is, it is already, but at the time the program does the "random "I would like you not to touch the number 5 , do not change it from place ...

For the simple fact that, to find a magic square 3x3 with 9 numbers, the possibilities are 362880 thus being the factorial of 9 ...

So if I have practically left the number 5 in place .. they will only pass 8 numbers by "random" and the possibilities will be only 40320 that would be the factorial of 8 .

Now imagine in a square 4x4 with 16 numbers ...

The possibilities are 20 trillion, that is, 20922789888000 but, if I could, I already leave 4 numbers in the right places that did not go through "random", I would only have 12 numbers decreasing possibilities to 479 million , that is 479001600 .

The speed to find the magic squares would increase drastically ...

Now the question:

How to ignore certain elements in a list that will go through a random process?

(Continued)

The code with implementations in 3x3 works perfectly .. but with 4x4 is not working follow code:

 import random

 vetor = [4, 14, 15, 1, 9, 2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 16]

 def shuffle(vetor, frozen_vetor):        
 frozen = [(pos, item) for (pos,item) in enumerate(vetor) if item in 
 frozen_vetor]    
 random.shuffle(vetor)    
 for pos, item in frozen:
     index = vetor.index(item)
     vetor[pos], vetor[index] = vetor[index], vetor[pos]    

 def magicsquare():
     return vetor[0]+vetor[1]+vetor[2]+vetor[3]==\
            vetor[4]+vetor[5]+vetor[6]+vetor[7]==\
            vetor[8]+vetor[9]+vetor[10]+vetor[11]==\
            vetor[12]+vetor[13]+vetor[14]+vetor[15]==\
            vetor[0]+vetor[4]+vetor[8]+vetor[12]==\
            vetor[1]+vetor[5]+vetor[9]+vetor[13]==\
            vetor[2]+vetor[6]+vetor[10]+vetor[14]==\
            vetor[3]+vetor[7]+vetor[11]+vetor[15]==\
            vetor[0]+vetor[5]+vetor[10]+vetor[15]==\
            vetor[3]+vetor[6]+vetor[9]+vetor[12]


while not magicsquare():
    shuffle(vetor, [4, 14, 15, 1, 9])

print (vetor)

Notice that I've used 5 numbers already in the order of the magic square, ignoring them ..

Thentherewouldonlybe%with%numbersfor"random", which would give 11 possibilities ... and find the magic square super fast ... but the program is taking a long time to find the square .. then probably it is using 39916800 in "random" that would give 16 possibilities .. or else you should have some other error in the program ..

    
asked by anonymous 28.12.2017 / 23:38

1 answer

1

One way is to create your own shuffle by ignoring the elements you want:

def shuffle(items, frozen_items):        
    frozen = [(pos, item) for (pos, item) in enumerate(items) if item in frozen_items]    
    random.shuffle(items)    
    for pos, item in frozen:
        index = items.index(item)
        items[pos], items[index] = items[index], items[pos]

    return items

It does not look very pythonic but it's a way of ignoring items when making a shuffle.

Ex:

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print shuffle(vector, [8, 9]) // mantém os números 8 e 9 na posição original

You can adapt to ignore the index instead of the number.

EDIT

To use in your code, maintaining the use of the vector variable by reference:

import random

vetor = [1, 2, 3, 4, 5, 6, 7, 8, 9]

def shuffle(vetor, frozen_vetor):        
    frozen = [(pos, item) for (pos,item) in enumerate(vetor) if item in frozen_vetor]    
    random.shuffle(vetor)    
    for pos, item in frozen:
        index = vetor.index(item)
        vetor[pos], vetor[index] = vetor[index], vetor[pos]    

def magicsquare():
    return vetor[0]+vetor[1]+vetor[2]==\
           vetor[3]+vetor[4]+vetor[5]==\
           vetor[6]+vetor[7]+vetor[8]==\
           vetor[0]+vetor[3]+vetor[6]==\
           vetor[1]+vetor[4]+vetor[7]==\
           vetor[2]+vetor[5]+vetor[8]==\
           vetor[0]+vetor[4]+vetor[8]==\
           vetor[2]+vetor[4]+vetor[6]

while not magicsquare():
    shuffle(vetor, [5]) # ex: mantém o número 5 na posição original

print vetor
    
29.12.2017 / 01:22