2017-06-28 1 views
2

J'ai un tableau de bord d'échecs qui ressemble à ceci:Trouver une limite diagonale dans une matrice unidimensionnelle

00 01 02 03 04 05 06 07 
08 09 10 11 12 13 14 15 
16 17 18 19 20 21 22 23 
24 25 26 27 28 29 30 31 
32 33 34 35 36 37 38 39 
40 41 42 43 44 45 46 47 
48 49 50 51 52 53 54 55 
56 57 58 59 60 61 62 63 

Maintenant, je suis en train de trouver une fonction de position, un numéro sur la carte, qui donne moi l'avant dernier numéro dans la diagonale haut/droite, par exemple pour 60, j'essaie de trouver 38, pour 30, j'essaye de trouver 22. Je pourrais coder dur la chose foutue, mais ce serait vraiment plus agréable de trouver une fonction qui fait ceci. Jusqu'à présent, il me perplexe.

Je n'ai pas eu de problèmes avec les diagonales bas/droite et diagonale et haut/gauche, mais celle-ci me bute. Toute aide est appréciée.

suit ci-dessous le code, je travaille sur:

# EightQueens.py 
# Joshua Marshall Moore 
# [email protected] 
# June 24th, 2017 

# The eight queens problem consists of setting up eight queens on a chess board 
# so that no two queens threaten each other. 

# This is an attempt to find all possible solutions to the problem. 

# The board is represented as a set of 64 numbers each representing a position 
# on the board. Array indexing begins with zero. 

# 00 01 02 03 04 05 06 07 
# 08 09 10 11 12 13 14 15 
# 16 17 18 19 20 21 22 23 
# 24 25 26 27 28 29 30 31 
# 32 33 34 35 36 37 38 39 
# 40 41 42 43 44 45 46 47 
# 48 49 50 51 52 53 54 55 
# 56 57 58 59 60 61 62 63 

# Test: 
# The following combination should yield a True from the check function. 

# 6, 9, 21, 26, 32, 43, 55, 60 

from itertools import combinations 
import pdb 

# works 
def down_right_boundary(pos): 
    boundary = (8-pos%8)*8 
    applies = (pos%8)+1 > int(pos/8) 
    if applies: 
     return boundary 
    else: 
     return 64 

# works 
def up_left_boundary(pos): 
    boundary = ((int(pos/8)-(pos%8))*8)-1 
    applies = (pos%8) <= int(pos/8) 
    if applies: 
     return boundary 
    else: 
     return -1 

def up_right_boundary(pos): 
    boundary = [7, 15, 23, 31, 39, 47, 55, 62][pos%8]-1 
    # 7: nil 
    # 14: 7-1 
    # 15: 15-1 
    # 21: 7-1 
    # 22: 15-1 
    # 23: 23-1 
    # 28: 7-1 
    # 29: 15-1 
    # 30: 23-1 
    # 31: 31-1 
    # 35: 7-1 
    # 36: 15-1 
    # 37: 23-1 
    # 38: 31-1 
    # 39: 39-1 
    # 42: 7-1 
    # 43: 15-1 
    # 44: 23-1 
    # 45: 31-1 
    # 46: 39-1 

    applies = pos%8>=pos%7 
    if applies: 
     return boundary 
    else: 
     return -1 

def down_left_boundary(pos): 
    boundary = 64 
    applies = True 
    if applies: 
     return boundary 
    else: 
     return 64 

def check(positions): 

    fields = set(range(64)) 
    threatened = set() 

    # two queens per quadrant 
    quadrants = [ 
     set([p for p in range(0, 28) if (p%8)<4]), 
     set([p for p in range(4, 32) if (p%8)>3]), 
     set([p for p in range(32, 59) if (p%8)<4]), 
     set([p for p in range(36, 64) if (p%8)>3]) 
    ] 

    #for q in quadrants: 
    # if len(positions.intersection(q)) != 2: 
    #  return False 

    # check the queen's ranges 
    for pos in positions: 

     pdb.set_trace() 

     # threatened |= set(range(pos, -1, -8)[1:]) # up 
     # threatened |= set(range(pos, 64, 8)[1:]) # down 
     # threatened |= set(range(pos, int(pos/8)*8-1, -1)[1:]) # left 
     # threatened |= set(range(pos, (int(pos/8)+1)*8, 1)[1:]) # right 

     # down right diagonal: 
     # There are two conditions here, one, the position is above the 
     # diagonal, two, the position is below the diagonal. 
     # Above the diagonal can be expressed as pos%8>int(pos/8). 
     # In the event of a position above the diagonal, I need to limit the 
     # range to 64-(pos%8) to prevent warping the board into a field that 
     # connects diagonals like Risk. 
     # Otherwise, 64 suffices as the ending condition. 
     threatened |= set(range(pos, down_right_boundary(pos), 9)[1:]) # down right 

     print(pos, threatened) 
     pdb.set_trace() 
     # 

     # up left diagonal: 
     # Similarly, if the position is above the diagonal, -1 will suffice as 
     # the range's ending condition. Things are more complicated if the 
     # position is below the diagonal, as I must prevent warping, again. 
     threatened |= set(range(pos, up_left_boundary(pos), -9)[1:]) # up left 

     print(pos, threatened) 
     pdb.set_trace() 
     # 

     # up right diagonal: 
     # Above the diagonal takes on a different meaning here, seeing how I'm 
     # dealing with the other diagonal. It is defined by pos58>pos%7. Now I 
     # restrict the range to a (pos%8)*8, creating a boundary along the right 
     # side of the board. 
     threatened |= set(range(pos, up_right_boundary(pos), -7)[1:]) # up right 

     print(pos, threatened) 
     pdb.set_trace() 
     # 

     # down left diagonal: 
     # I reuse a similar definition to that of the diagonal as above. The 
     # bound for left hand side of the board looks as follows: 
     # ((pos%8)*7)+(pos%8) 
     threatened |= set(range(pos, down_left_boundary(pos), 7)[1:]) # down left 

     print(pos, threatened) 
     pdb.set_trace() 
     # 

    if len(positions.intersection(threatened)) > 0: 
     return False 

    return True 


if __name__ == '__main__': 

    # print(check(set([55]))) # pass 
    # print(check(set([62]))) # pass 
    # print(check(set([63]))) # pass 
    # print(check(set([48]))) # pass 
    # print(check(set([57]))) # pass 
    # print(check(set([56]))) # pass 
    # print(check(set([8]))) # pass 

    # print(check(set([1]))) # fail 
    # print(check(set([0]))) 
    # print(check(set([6]))) 
    # print(check(set([15]))) 
    # print(check(set([7]))) 

    # print(check(set([6]))) 
    # print(check(set([9]))) 
    print(check(set([21]))) 
    print(check(set([26]))) 
    print(check(set([32]))) 
    print(check(set([43]))) 
    print(check(set([55]))) 
    print(check(set([60]))) 





    print(
     check(set([6, 9, 21, 26, 32, 43, 55, 60])) 
    ) 

    # for potential_solution in combinations(range(64), 8): 
     # is_solution = check(set(potential_solution)) 
     # if is_solution: 
      # print(is_solution, potential_solution) 
+1

Pouvez-vous s'il vous plaît montrer du code? Ce n'est pas clair ce que vous avez essayé et ce que vous êtes coincé. Je ne suis pas sûr de comprendre les entrées et les sorties de la fonction désirée. 60 n'est pas sur la même ligne diagonale que 38. – 4castle

+0

60 n'est pas la même ligne diagonale que 38. Je cherche le numéro qui vient avant le dernier élément sur la ligne diagonale. –

+0

Il sera utilisé dans une fonction de gamme, donc celle avant la diagonale. –

Répondre

1

En utilisant les positions de échiquiers suivantes:

chessboard = [0,1,2,3,4,5,6,7, 
       8,9,10,11,12,13,14,15, 
       16,17,18,19,20,21,22,23, 
       24,25,26,27,28,29,30,31, 
       32,33,34,35,36,37,38,39, 
       40,41,42,43,44,45,46,47, 
       48,49,50,51,52,53,54,55, 
       56,57,58,59,60,61,62,63] 

j'ai écrit une fonction qui correspond à ce que vous voulez (les commentaires décrivent code):

def return_diagonal(position): # with position being chessboard position 

    while ((position+1)%8) != 0: # while (chess position)+1 is not divisible by eight: 
      position -= 7   # move diagonally upwards (7 chess spaces back) 

    position -= 1     # when reached the right end of the chessboard, move back one position 

    if position < 6:    # if position happens to be in the negative: 
     position = 6    # set position by default to 6 (smallest possible value) 

    return position    # return the position 

La fonction demande d'abord si la position est dans la dernière colonne.

Si ce n'est pas le cas, retournez 7 espaces, qui vont en diagonale vers le haut-droite.

Et il vérifie à nouveau jusqu'à ce qu'il arrive à la dernière colonne. Là, il remonte d'un espace, de sorte qu'il fait un espace à partir de la gauche de l'extrémité droite de l'échiquier.

Cependant, si ce nombre est négatif (comme c'est le cas pour de nombreux nombres en haut à gauche), cela signifie que la diagonale s'étend complètement au-delà de l'échiquier 8x8.

Ainsi, par défaut, la réponse devrait être 6.

je lui ai donné quelques tests

print(60,return_diagonal(60)) 
print(30,return_diagonal(30)) 
print(14,return_diagonal(14)) 
print(1,return_diagonal(1)) 

Avec la sortie suivante:

position originale, la seconde au dernier numéro de la diagonale montante/droite

60 38 
30 22 
14 6 
1 6 
+0

@JoshuaMoore Je pense avoir trouvé une solution réalisable. S'il y a des choses à clarifier, n'hésitez pas à répondre à ce commentaire. Merci! – Larry

+1

Merci pour la réponse. C'est tellement simple que je pourrais me donner un coup de pied. Je suppose que j'espérais un "pythonic" de résoudre ça, mais votre façon de travailler fonctionne très bien, merci! –