<jupyter_start><jupyter_text>Bac à SableExpérimentation autour de différentes fonctionnalités<jupyter_code>from numpy.lib.stride_tricks import as_strided
import numpy as np
import time
from scipy.signal import convolve, convolve2d<jupyter_output><empty_output><jupyter_text>Détection de configuration de capture:<jupyter_code>k_diags = np.array([0.25 * np.array([[-1, 0, 0, 0],
                                    [0, 1, 0, 0],
                                    [0, 0, 1, 0],
                                    [0, 0, 0, -1]]),
                    0.25 * np.array([[0, 0, 0, -1],
                                    [0, 0, 1, 0],
                                    [0, 1, 0, 0],
                                    [-1, 0, 0, 0]])])

k_lines = [0.25 * np.array([[-1, 1, 1, -1]]), 0.25 * np.array([[-1],[1],[1],[-1]])]

#k_free_threes = [np.ones((1,6)), np.ones((6,1)), np.identity(6), np.rot90(np.identity(6))]
k_free_threes = [np.array([1, 2, 2, 2, 2, 1]),
                 np.array([[1], [2], [2], [2], [2], [1]]),
                 np.array([[1, 0, 0, 0, 0, 0],
                           [0, 2, 0, 0, 0, 0],
                           [0, 0, 2, 0, 0, 0],
                           [0, 0, 0, 2, 0, 0],
                           [0, 0, 0, 0, 2, 0],
                           [0, 0, 0, 0, 0, 1]]),
                 np.array([[0, 0, 0, 0, 0, 1],
                           [0, 0, 0, 0, 2, 0],
                           [0, 0, 0, 2, 0, 0],
                           [0, 0, 2, 0, 0, 0],
                           [0, 2, 0, 0, 0, 0],
                           [1, 0, 0, 0, 0, 0]])]
arr = np.random.randint(1,5, size=(1, 2))
arr = np.array([1, 2])
y, x = arr
print(f"valeur de x= {x} valeur de y = {y}")
extend_arr = np.zeros((16,16))
extend_arr[3:-3, 3:-3] = arr
extend_arr
c1 = [0,0]
c2 = [9,0]
c3 = [0,9]
c4 = [9,9]
c5 = [5,3]
c6 = [6,8]
view1 = extend_arr[c1[0]:c1[0]+3+1, c1[1]+3]
view2 = extend_arr[c1[0]+3:c1[0]+2*3+1, c1[1]+3]
view3 = extend_arr[c1[0]+3, c1[1]:c1[1]+3+1]
view4 = extend_arr[c1[0]+3, c1[1]+3:c1[1]+2*3+1]
print(view1) # colonne
print(view2) # colonne
print(view3) # ligne
print(view4) # ligne

conv_c  = np.multiply(view1, k_lines[0])
conv_cc = np.multiply(view2, k_lines[0])
conv_l  = np.multiply(view3, k_lines[0])
conv_ll = np.multiply(view4, k_lines[0])
print(conv_c)
print(conv_cc)
print(conv_l)
print(conv_ll)
res_c = np.sum(conv_c)
res_cc = np.sum(conv_cc)
res_l = np.sum(conv_l)
res_ll = np.sum(conv_ll)
print(res_c)
print(res_cc)
print(res_l)
print(res_ll)
view5 = extend_arr[c1[0]:c1[0] + 3 + 1, c1[1]:c1[1]+3+1]
view6 = extend_arr[c1[0]:c1[0] + 3 + 1, c1[1]+3:c1[1] + 2 * 3  + 1]
view7 = extend_arr[c1[0] + 3:c1[0] + 2 * 3 + 1, c1[1]:c1[1] + 3 + 1]
view8 = extend_arr[c1[0] + 3:c1[0] + 2 * 3 + 1, c1[1] + 3:c1[1] + 2 * 3 + 1]
print(view5)
print(view6)
print(view7)
print(view8)
np.sum(np.multiply(extend_grid[yx[0] : yx[0] + 3 + 1, yx[1] : yx[1] + 3 + 1], k_capture))
np.sum(np.multiply(extend_grid[yx[0] : yx[0] + 3 + 1, yx[1] + 3 : yx[1] + 2 * 3  + 1], k_capture))
np.sum(np.multiply(extend_grid[yx[0] + 3:yx[0] + 2 * 3 + 1, yx[1] : yx[1] + 3 + 1], k_capture))
np.sum(np.multiply(extend_grid[yx[0] + 3:yx[0] + 2 * 3 + 1, yx[1] + 3 : yx[1] + 2 * 3 + 1], k_capture))
sub_shape = k_diags[0].shape
print(sub_shape)
sub_arr = arr
view_shape = tuple(np.subtract(sub_arr.shape, sub_shape) + 1) + sub_shape
np.subtract(sub_arr.shape, sub_shape) + 1
view_shape
sub_arr.strides * 2
sub_arr = np.arange(1,122).reshape(-1,11)
sub_arr
sub_arr[3:8, 3:8]
def subviews_nxp(board:np.array, np:tuple, axis:int=0, b_diag:bool=False):
    if axis == 0 and not b_diag:
        d = board.shape[0] - np[0] + 1
    elif axis == 1 and not b_diag:
        d = board.shape[1] - np[1] + 1
    elif b_diag:
        d = board.shape[0] - max(np) + 1
    sub_views_shape = (d, np[0], np[1])
    sub_views_strides = (board.strides[1] + b_diag * board.strides[0], board.strides[0], board.strides[1])
    sub_views = as_strided(board, sub_views_shape, sub_views_strides)
    return sub_views
res = subviews_nxp(sub_arr[3:8, 3:8], (1,4), axis = 0, b_diag=True)
res
k_capture_l = np.array([[[1, 1, 1, 1]]])
convolve(res, k_capture_l, "valid")
arr_view = as_strided(sub_arr, (9, 4, 4), [80,80,8])
sub_arr.strides * 2
sub_arr.strides[0]
arr_view
def strided4D(arr,arr2,s):
    strided = np.lib.stride_tricks.as_strided
    s0,s1 = arr.strides
    m1,n1 = arr.shape
    m2,n2 = arr2.shape    
    out_shp = (1+(m1-m2)//s, m2, 1+(n1-n2)//s, n2)
    return strided(arr, shape=out_shp, strides=(s*s0,s*s1,s0,s1))
test_arr = np.arange(1,26)
test_arr.reshape(5,5)
k = np.identity(3)
strided4D(test_arr.reshape(5, 5), k, 2)
strided4D(test_arr, k, 2)
def _subboard_4_Conv2D(grid, k_shape:tuple, stride:tuple) -> np.array:
    """ Generates the sub view of the grid to be multiply with the kernel.
    First the shape of the sub_grid array is calculated, it depends on
    the grid shape and the kernel shape.
    The sub_grid array shape will be (n_x, n_y, k_x, k_y) with:
        * n_x: number of application of the kernel along row (with stride of 1)
        * n_y: number of application of the kernel along column (with stride of 1)
        * k_x, k_y: the shape of the kernel
    In this way sub_grid is a numpy array of n_x/n_y rows/columns of (k_x x k_y)
    sub view of the grid.
    Args:
    -----
        k_shape ([tuple[int]]): shape of the kernel
        stride ([tuple(int)]): put self.grid.strides * 2 (but why?)
    """
    view_shape = tuple(np.subtract(grid.shape, k_shape) + 1) + k_shape
    sub_grid = as_strided(grid, view_shape, stride * 2)
    return sub_grid

def _my_conv2D(grid, kernel:np.array) -> np.array:
    """ Retrieves the sub_grid from the function _subboard_4_Conv2D and performs
    the convolution (array multiplication + einstein sum along the 3rd and 4th
    dimensions).
    Args:
    -----
        * kernel ([np.array]): the kernel to use for convolution.
    """
    sub_grid = _subboard_4_Conv2D(grid, k_shape=kernel.shape, stride=grid.strides)
    res_conv = np.multiply(sub_grid, kernel)
    convolved = np.einsum('ijkl->ij', res_conv)
    return convolved.astype('int8')
def check_board(grid):
    """[summary]
    """
    ## Checking if white pair captured
    # Checking the diagonal:
    conv_diag1 = _my_conv2D(k_diags[0])
    conv_diag2 = _my_conv2D(k_diags[1])
    # Checking vertical and horizontal
    conv_lin1 = _my_conv2D(k_lines[0])
    conv_lin2 = _my_conv2D(k_lines[1])
    
    coord_cd1 = np.argwhere(conv_diag1 == 1)
    coord_cd2 = np.argwhere(conv_diag2 == 1)
    coord_cl1 = np.argwhere(conv_lin1 == 1)
    coord_cl2 = np.argwhere(conv_lin2 == 1)
    if coord_cd1.shape[0] != 0:
        for coord in coord_cd1:
            print("[check_board] - conv_diag1")
            grid[coord[0] + 1][coord[1] + 1] = 0
            grid[coord[0] + 2][coord[1] + 2] = 0
    if coord_cd2.shape[0] != 0:
        for coord in coord_cd2:
            print("[check_board] - conv_diag2")
            grid[coord[0] + 1][coord[1] + 2] = 0
            grid[coord[0] + 2][coord[1] + 1] = 0
    if coord_cl1.shape[0] != 0:
        for coord in coord_cl1:
            print("[check_board] - conv_lin1")
            grid[coord[0]][coord[1] + 1] = 0
            grid[coord[0]][coord[1] + 2] = 0
    if coord_cl2.shape[0] != 0:
        for coord in coord_cl2:
            print("[check_board] - conv_lin2")
            grid[coord[0] + 1][coord[1]] = 0
            grid[coord[0] + 2][coord[1]] = 0
    ## Checking if black pair captured
    # Checking the diagonal:
    conv_diag1 = _my_conv2D(-1 * k_diags[0])
    conv_diag2 = _my_conv2D(-1 * k_diags[1])
    # Checking vertical and horizontal
    conv_lin1 = _my_conv2D(-1 * k_lines[0])
    conv_lin2 = _my_conv2D(-1 * k_lines[1])
    print("<<<== CONV_LIN1 ==>>>")
    print(conv_lin1)
    print("<<<== CONV_LIN2 ==>>>")
    print(conv_lin2)
    print("<<<== ========= ==>>>")
    coord_cd1 = np.argwhere(conv_diag1 == 1)
    coord_cd2 = np.argwhere(conv_diag2 == 1)
    coord_cl1 = np.argwhere(conv_lin1 == 1)
    coord_cl2 = np.argwhere(conv_lin2 == 1)
    if coord_cd1.shape[0] != 0:
        for coord in coord_cd1:
            print("[check_board] - conv_diag1 -1")
            grid[coord[0] + 1][coord[1] + 1] = 0
            grid[coord[0] + 2][coord[1] + 2] = 0
    if coord_cd2.shape[0] != 0:
        for coord in coord_cd2:
            print("[check_board] - conv_diag2 -1")
            grid[coord[0] + 1][coord[1] + 2] = 0
            grid[coord[0] + 2][coord[1] + 1] = 0
    if coord_cl1.shape[0] != 0:
        for coord in coord_cl1:
            print("[check_board] - conv_lin1 -1")
            grid[coord[0]][coord[1] + 1] = 0
            grid[coord[0]][coord[1] + 2] = 0
    if coord_cl2.shape[0] != 0:
        for coord in coord_cl2:
            print("[check_board] - conv_lin2 -1")
            grid[coord[0] + 1][coord[1]] = 0
            grid[coord[0] + 2][coord[1]] = 0
def issimplefreethree_position(yx, grid):
    """[summary]
    Args:
    yx ([type]): [description]
    grid ([type]): [description]
    Returns:
    ___: [description]
    """
    tmp = np.zeros((18,18))
    tmp[yx[0] + 4, yx[1] + 4] = 1
    tmp[4:-4, 4:-4] += grid + 1
    r_start, r_end = yx[0], yx[0] + 8
    c_start, c_end = yx[1], yx[1] + 8
    
    print(tmp)
    # Convolution sur la ligne 
    view_l = tmp[yx[0] + 4, yx[1]:yx[1] + 9]
    #print(">=== view_l ===<\n", view_l)
    res_l = [np.sum(np.multiply(view_l[i:i+6], k_free_threes[0])) for i in range(4)]
    #print(">=== res_l ===<\n", res_l)
    
    #Convolution sur la colonne:
    view_c = tmp[yx[0]:yx[0] + 9, yx[1] + 4]
    #print(">=== view_c ===<\n", view_c)
    res_c = [np.sum(np.multiply(view_c[i:i+6], k_free_threes[1].flatten())) for i in range(4)]
    #print(">=== res_c ===<\n", res_c)
    
    # Convolution sur diagonale descendante gauche-droite
    view_d1 = [tmp[yx[0]+i:yx[0]+6+i, yx[1]+i:yx[1]+6+i] for i in range(4)]
    #print(">=== view_d1 ===<\n", np.array(view_d1))
    res_d1 = [np.sum(np.multiply(view_d1[i], k_free_threes[2])) for i in range(4)]
    #print(">=== res_d1 ===<\n", res_d1)
    
    # Convolution sur diagonale montante gauche-droite
    view_d2 = [tmp[yx[0] +3 - i:yx[0] + 9 -i, yx[1]+i:yx[1]+6+i] for i in range(4)]
    #print(">=== view_d2 ===<\n", view_d2)
    res_d2 = [np.sum(np.multiply(view_d2[i], k_free_threes[3])) for i in range(4)]
    #print(">=== res_d2 ===<\n", res_d2)
    res = [*res_l, *res_c, *res_d1, *res_d2]
    if any([np.any(arr >= 16) for arr in res]):
        count = np.count_nonzero(np.array(res) >=16)
        return True, res, count
    return False, res
            
grid1 = np.zeros((10,10))
grid2 = np.zeros((10,10))
grid3 = np.zeros((10,10))
grid4 = np.zeros((10,10))
grid5 = np.zeros((10,10))
grid6 = np.zeros((10,10))
grid7 = np.zeros((10,10))
grid1[0:2,2] = 1

grid2[3:5,2] = 1

grid3[5,0:2] = 1

grid4[6,3:5] = 1

#grid5[[3,4],[3,4]] = 1
grid5[[6, 6], [7, 8]] = 1

grid6[[5, 6], [5, 6]] = 1

grid7[[2, 5],[2, 5]] = 1

grid7
issimplefreethree_position([3,3], grid7)<jupyter_output>[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 2. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 2. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 2. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.[...]<jupyter_text>Détection des doubles free threes<jupyter_code># kernels to check if there is a double free threes
S = 1 # choose a number corresponding to what the stone will be multiply by
V = 1 # choose a number corresponding to what the empty position will be multiply by
s1_a = np.array([[V, 0, 0, 0, 0, 0, 0],
				 [0, S, 0, 0, 0, 0, 0],
				 [0, 0, S, 0, 0, 0, 0],
				 [0, 0, V, S, S, S, V],
				 [0, 0, 0, 0, V, 0, 0]], dtype='int8')
s1_b = np.array([[0, V, 0, 0, 0],
				 [0, S, 0, 0, 0],
				 [0, S, 0, 0, 0],
				 [V, S, S, S, V],
				 [0, V, 0, 0, 0]], dtype='int8')
s1_c = np.array([[0, 0, 0, 0, V],
				 [0, 0, 0, S, 0],
				 [0, 0, S, 0, 0],
				 [V, S, S, S, V],
				 [V, 0, 0, 0, 0]], dtype='int8')
s1_d = np.array([[V, 0, 0, 0, 0, 0, V],
				 [0, S, 0, 0, 0, S, 0],
				 [0, 0, S, 0, S, 0, 0],
				 [0, 0, 0, S, 0, 0, 0],
				 [0, 0, V, 0, V, 0, 0]], dtype='int8')

s2_a = np.array([[V, 0, 0, 0, 0, 0, 0, 0],
				 [0, S, 0, 0, 0, 0, 0, 0],
				 [0, 0, S, 0, 0, 0, 0, 0],
				 [0, 0, 0, V, 0, 0, 0, 0],
				 [0, 0, 0, V, S, S, S, V],
				 [0, 0, 0, 0, 0, V, 0, 0]], dtype='int8')
s2_b = np.array([[0, V, 0, 0, 0],
				 [0, S, 0, 0, 0],
				 [0, S, 0, 0, 0],
				 [0, V, 0, 0, 0],
				 [V, S, S, S, V],
				 [0, V, 0, 0, 0]], dtype='int8')
s2_c = np.array([[0, 0, 0, 0, 0, V],
				 [0, 0, 0, 0, S, 0],
				 [0, 0, 0, S, 0, 0],
				 [0, 0, V, 0, 0, 0],
				 [V, S, S, S, V, 0],
				 [V, 0, 0, 0, 0, 0]], dtype='int8')
s2_d = np.array([[V, 0, 0, 0, 0, 0, 0, 0],
				 [0, S, 0, 0, 0, 0, 0, V],
				 [0, 0, S, 0, 0, 0, S, 0],
				 [0, 0, 0, V, 0, S, 0, 0],
				 [0, 0, 0, 0, S, 0, 0, 0],
				 [0, 0, 0, V, 0, V, 0, 0]], dtype='int8')

s3_a = np.array([[V, 0, 0, 0, 0, 0, 0, 0],
				 [0, S, 0, 0, 0, 0, 0, 0],
				 [0, 0, V, 0, 0, 0, 0, 0],
				 [0, 0, 0, S, 0, 0, 0, 0],
				 [0, 0, 0, V, S, S, S, V],
				 [0, 0, 0, 0, 0, V, 0, 0]], dtype='int8')
s3_b = np.array([[0, V, 0, 0, 0],
				 [0, S, 0, 0, 0],
				 [0, V, 0, 0, 0],
				 [0, S, 0, 0, 0],
				 [V, S, S, S, V],
				 [0, V, 0, 0, 0]], dtype='int8')
s3_c = np.array([[0, 0, 0, 0, 0, V],
				 [0, 0, 0, 0, S, 0],
				 [0, 0, 0, V, 0, 0],
				 [0, 0, S, 0, 0, 0],
				 [V, S, S, S, V, 0],
				 [V, 0, 0, 0, 0, 0]], dtype='int8')
s3_d = np.array([[V, 0, 0, 0, 0, 0, 0, 0],
				 [0, S, 0, 0, 0, 0, 0, V],
				 [0, 0, V, 0, 0, 0, S, 0],
				 [0, 0, 0, S, 0, S, 0, 0],
				 [0, 0, 0, 0, S, 0, 0, 0],
				 [0, 0, 0, V, 0, V, 0, 0]], dtype='int8')

s4_a = np.array([[V, 0, 0, 0, 0, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, S, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, V, 0, 0, 0, 0, 0],
                 [0, 0, 0, V, S, V, S, S, V],
                 [0, 0, 0, 0, 0, V, 0, 0, 0]], dtype='int8')
s4_b = np.array([[0, V, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0],
                 [0, V, 0, 0, 0, 0],
                 [V, S, V, S, S, V],
                 [0, V, 0, 0, 0, 0]], dtype='int8')
s4_c = np.array([[0, 0, 0, 0, 0, V],
                 [0, 0, 0, 0, S, 0],
                 [0, 0, 0, S, 0, 0],
                 [0, 0, V, 0, 0, 0],
                 [V, S, V, S, S, V],
                 [V, 0, 0, 0, 0, 0]], dtype='int8')
s4_d = np.array([[V, 0, 0, 0, 0, 0, 0, 0, V],
                 [0, S, 0, 0, 0, 0, 0, S, 0],
                 [0, 0, S, 0, 0, 0, S, 0, 0],
                 [0, 0, 0, V, 0, V, 0, 0, 0],
                 [0, 0, 0, 0, S, 0, 0, 0, 0],
                 [0, 0, 0, V, 0, V, 0, 0, 0]], dtype='int8')

s5_a = np.array([[V, 0, 0, 0, 0, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, S, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, V, 0, 0, 0, 0, 0],
                 [0, 0, 0, V, S, S, V, S, V],
                 [0, 0, 0, 0, 0, V, 0, 0, 0]], dtype='int8')
s5_b = np.array([[0, V, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0],
                 [0, V, 0, 0, 0, 0],
                 [V, S, S, V, S, V],
                 [0, V, 0, 0, 0, 0]], dtype='int8')
s5_c = np.array([[0, 0, 0, 0, 0, V],
                 [0, 0, 0, 0, S, 0],
                 [0, 0, 0, S, 0, 0],
                 [0, 0, V, 0, 0, 0],
                 [V, S, S, V, S, V],
                 [V, 0, 0, 0, 0, 0]], dtype='int8')
s5_d = np.array([[V, 0, 0, 0, 0, 0, 0, 0, V],
                 [0, S, 0, 0, 0, 0, 0, S, 0],
                 [0, 0, S, 0, 0, 0, V, 0, 0],
                 [0, 0, 0, V, 0, S, 0, 0, 0],
                 [0, 0, 0, 0, S, 0, 0, 0, 0],
                 [0, 0, 0, V, 0, V, 0, 0, 0]], dtype='int8')

s6_a = np.array([[V, 0, 0, 0, 0, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0, 0, 0, 0],
                 [0, 0, V, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, S, 0, 0, 0, 0, 0],
                 [0, 0, 0, V, S, S, V, S, V],
                 [0, 0, 0, 0, 0, V, 0, 0, 0]], dtype='int8')
s6_b = np.array([[0, V, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0],
                 [0, V, 0, 0, 0, 0],
                 [0, S, 0, 0, 0, 0],
                 [V, S, S, V, S, V],
                 [0, V, 0, 0, 0, 0]], dtype='int8')
s6_c = np.array([[0, 0, 0, 0, 0, V],
                 [0, 0, 0, 0, S, 0],
                 [0, 0, 0, V, 0, 0],
                 [0, 0, S, 0, 0, 0],
                 [V, S, S, V, S, V],
                 [V, 0, 0, 0, 0, 0]], dtype='int8')
s6_d = np.array([[V, 0, 0, 0, 0, 0, 0, 0, V],
                 [0, S, 0, 0, 0, 0, 0, S, 0],
                 [0, 0, V, 0, 0, 0, V, 0, 0],
                 [0, 0, 0, S, 0, S, 0, 0, 0],
                 [0, 0, 0, 0, S, 0, 0, 0, 0],
                 [0, 0, 0, V, 0, V, 0, 0, 0]], dtype='int8')

dct_S = {'S1': {'a': s1_a, 'b': s1_b, 'c': s1_c, 'd':s1_d},
         'S2': {'a': s2_a, 'b': s2_b, 'c': s2_c, 'd':s2_d},
         'S3': {'a': s3_a, 'b': s3_b, 'c': s3_c, 'd':s3_d},
         'S4': {'a': s4_a, 'b': s4_b, 'c': s4_c, 'd':s4_d},
         'S5': {'a': s5_a, 'b': s5_b, 'c': s5_c, 'd':s5_d},
         'S6': {'a': s6_a, 'b': s6_b, 'c': s6_c, 'd':s6_d}}
def R_transformation(arr:np.array) -> list:
    l_kernel = []
    for k in [0, 1, 2, 3]:
        l_kernel.append(np.rot90(arr, k))
    return l_kernel

def mR_transformation(arr:np.array) -> list:
    l_kernel = []
    for k in [0, 1, 2, 3]:
        l_kernel.append(np.rot90(np.flipud(arr), k))
    return l_kernel
table_transf = {'S1': {'a': [True, True],
					   'b': [True, False],
        			   'c': [True, True],
              		   'd': [True, False]},
                'S2': {'a': [True, True],
					   'b': [True, True],
					   'c': [True, True],
					   'd': [True, True]},
                'S3': {'a': [True, True],
					   'b': [True, True],
					   'c': [True, True],
					   'd': [True, True]},
                'S4': {'a': [True, True],
					   'b': [True, False],
					   'c': [True, True],
					   'd': [True, False]},
                'S5': {'a': [True, True],
					   'b': [True, True],
					   'c': [True, True],
					   'd': [True, True]},
                'S6': {'a': [True, True],
					   'b': [True, False],
					   'c': [True, True],
					   'd': [True, False]}}
full_kernels = []
for first_k in table_transf.keys():
    for second_k in table_transf[first_k].keys():
        sym1, sym2 = table_transf[first_k][second_k]
        if sym1:
            [full_kernels.append(transf) for transf in R_transformation(dct_S[first_k][second_k])]
        if sym2:
            [full_kernels.append(transf) for transf in mR_transformation(dct_S[first_k][second_k])]
def _subboard_4_Conv2D(grid, k_shape:tuple, stride:tuple) -> np.array:
    """ Generates the sub view of the grid to be multiply with the kernel.
    First the shape of the sub_grid array is calculated, it depends on
    the grid shape and the kernel shape.
    The sub_grid array shape will be (n_x, n_y, k_x, k_y) with:
        * n_x: number of application of the kernel along row (with stride of 1)
        * n_y: number of application of the kernel along column (with stride of 1)
        * k_x, k_y: the shape of the kernel
    In this way sub_grid is a numpy array of n_x/n_y rows/columns of (k_x x k_y)
    sub view of the grid.
    Args:
    -----
        k_shape ([tuple[int]]): shape of the kernel
        stride ([tuple(int)]): put self.grid.strides * 2 (but why?)
    """
    view_shape = tuple(np.subtract(grid.shape, k_shape) + 1) + k_shape
    sub_grid = as_strided(grid, view_shape, stride * 2)
    return sub_grid

def _my_conv2D(grid, kernel:np.array) -> np.array:
    """ Retrieves the sub_grid from the function _subboard_4_Conv2D and performs
    the convolution (array multiplication + einstein sum along the 3rd and 4th
    dimensions).
    Args:
    -----
        * kernel ([np.array]): the kernel to use for convolution.
    """
    sub_grid = _subboard_4_Conv2D(grid, k_shape=kernel.shape, stride=grid.strides)
    res_conv = np.multiply(sub_grid, kernel)
    convolved = np.einsum('ijkl->ij', res_conv)
    return convolved.astype('int8')
v_my_conv2D = np.vectorize(_my_conv2D, signature='(m,n),(p,q)->()')
v_my_conv2D(grid, full_kernels)
grid = np.zeros((19,19), dtype = 'int8')
grid[[3, 4, 6, 6, 6],[3, 4, 6, 7, 8]] = 1
res = _my_conv2D(grid, full_kernels[0])
print(grid.shape)
print(full_kernels[0].shape)
print(res.shape)
res = []
start = time.time()
for kernel in full_kernels:
    res.append(_my_conv2D(grid[], kernel))
end = time.time()
print(end-start)
BLACK = 1
WHITE = -1

k_freethree = np.array([1, 2, 2, 2, 2, 1])

def get_line_idx(yx:np.array):
    return (np.ones((1,9)) * yx[0]).astype('int8'), (np.arange(-4, 5) + yx[1]).astype('int8')


def get_col_idx(yx:np.array):
    return (np.arange(-4, 5) + yx[0]).astype('int8'), (np.ones((1,9)) * yx[1]).astype('int8')


def get_diag1_idx(yx:np.array):
    return (np.arange(-4, 5) + yx[0]).astype('int8'), (np.arange(-4, 5) + yx[1]).astype('int8')


def get_diag2_idx(yx:np.array):
    return (np.arange(4, -5, -1) + yx[0]).astype('int8'), (np.arange(-4, 5) + yx[1]).astype('int8')

def isdoublefreethree_position(yx:np.array, grid:np.array, color:int) -> bool:
        """[summary]
        Args:
            yx ([type]): [description]
            grid ([type]): [description]
        Returns:
            bool: [description]
        """
        pad_width = 5
        c = color
        extend_grid = np.pad(grid + c, pad_width, "constant", constant_values = (0))
        extend_grid[yx[0] + pad_width, yx[1] + pad_width] = 2 * c
        print(extend_grid)
        res = []
        res.append(np.convolve(extend_grid[get_line_idx(yx + pad_width)].reshape(-1,), c * k_freethree, "valid"))
        res.append(np.convolve(extend_grid[get_col_idx(yx + pad_width)].reshape(-1,), c * k_freethree, "valid"))
        res.append(np.convolve(extend_grid[get_diag1_idx(yx + pad_width)], c * k_freethree, "valid"))
        res.append(np.convolve(extend_grid[get_diag2_idx(yx + pad_width)], c * k_freethree, "valid"))
        nb_free_three = 0
        for r_conv in res:
            if (r_conv >= 16).any():
                nb_free_three += 1
        if nb_free_three > 1:
            return True
        return False
grid8 = np.zeros((10,10))
grid8[[2, 3, 5, 5],[2, 3, 6, 7]] = 1
grid8
stone = 1
yx = np.array([5, 5])
isdoublefreethree_position(yx , grid8, stone)
grid9 = np.zeros((10,10))
grid9[[2, 3, 5, 5],[7, 6, 6, 7]] = 1
grid9
isdoublefreethree_position(np.array([4,5]) , grid9, stone)
grid10 = np.zeros((10,10))
grid10[[2, 3, 3, 2],[2, 3, 5, 6]] = 1
grid10[[1], [7]] = -1
grid10
isdoublefreethree_position(np.array([4,4]) , grid10, stone)
isdoublefreethree_position([4, 4], grid10)
test = np.array([[1, 1, 0, 0, 0]])

kernel = np.array([[1, 1, 1, 1],
                   [1, 1, 1, 1],
                   [0, 1, 1, 1],
                   [0, 0, 1, 1],
                   [0, 0, 0, 1]])
np.dot(test, kernel)
test
res = np.array([[-1, -1, -1, -1, -1]])
for _ in range(10):
    res = np.append(res, np.random.randint(low=0, high=10, size=(1,5)), axis=0)
res
res[1:2, 2:4]
(res / np.arange(1, 6)).astype('int8')
res = np.array([[-1, -1]])
for _ in range(10):
    res = np.append(res, np.random.randint(low=0, high=3, size=(1,2)), axis=0)
res = np.delete(res, 0, 0)
res
np.unique(res, axis=0)
i = 0
while i < res.shape[0]:
    print(f"res[{i}]: ", res[i])
    mask = (res == res[i]).all(axis=1)
    mask[0] = False
    print("mask:", mask)
    res = np.delete(res, mask, axis=0)
    i += 1
res
res[1]
tmp
tmp[2:,0]<jupyter_output><empty_output><jupyter_text>Elaboration du scoreboard<jupyter_code>SIZE = 10

kernel = np.array([[1, 0, 1, 0, 1],
                   [0, 1, 1, 1, 0],
                   [1, 1, 1, 1, 1],
                   [0, 1, 1, 1, 0],
                   [1, 0, 1, 0, 1]])

scoreboard = np.zeros((SIZE,SIZE))

grid  = np.zeros((SIZE,SIZE))

nb_white = np.random.randint(35,40)
nb_black = 0
while nb_black <= 0:
	nb_black = nb_white + np.random.randint(-4, 4)

ii = jj = 0
while ii < nb_white:
    x, y = list(np.random.randint(0, SIZE, size = 2))
    grid[y, x] = 1
    ii += 1

while jj < nb_black:
    x, y = list(np.random.randint(0, SIZE, size = 2))
    grid[y, x] = -1
    jj += 1

possible_pos = np.argwhere(grid != 0)
curr_pos = np.array(possible_pos[np.random.randint(0, len(possible_pos) -1, size = 1)][0])

print(f"nb_white = {nb_white} -- nb_black = {nb_black} -- cur_pos = {curr_pos}")
grid
extend_grid = np.pad(grid, 4, "constant", constant_values = 0)
extend_scoreboard = np.pad(scoreboard, 2, "constant", constant_values = 0)
curr_pos
coordy = curr_pos[0] + 4
coordx = curr_pos[1] + 4
extend_grid[coordy-2:coordy+3, coordx-2:coordx+3]

#extend_scoreboard[curr_pos[0]:curr_pos[0]+5,curr_pos[1]:curr_pos[1]+5] = convolve2d(extend_grid[coordy-2:coordy+3, coordx-2:coordx+3], kernel, "same")
convolve2d(extend_grid[coordy-4:coordy+5, coordx-4:coordx+5], kernel, "valid")
extend_scoreboard
scoreboard = extend_scoreboard[2:-2, 2:-2]
scoreboard<jupyter_output><empty_output><jupyter_text>Test sur la caractere terminal d'une séquence de pierre:<jupyter_code>BLACK = 1
WHITE = -1

k_capture = np.array([[-1, 1, 1, -1]])
last_color = BLACK
las_coord = np.array([4,5])
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #
board = np.zeros((11,11))
board[2:7, 5] = BLACK
board[[4,5],[6,6]]= BLACK
board[[4,5],[3,7]] = WHITE
board
start_y = 0
start_x = 5
while (board[start_y, start_x] == 0):
    start_y += 1
end_y = start_y + 5
end_x = start_x
print(f"({start_y};{start_x})  ({end_y};{end_x})")
ROI = board[start_y : end_y, start_x - 2 : end_x + 2 + 1]
ROI
res = convolve2d(ROI, last_color * k_capture, "valid")
res
np.any(res == 3)
dx = dy = 0
for i in range(5):
    dx, dy = dx + 1, dy + 1
    print(f"{dx}, {dy}")
np.rot45(k_capture)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.21102955015998495, 'fraction_numerical': 0.08560135516657255, 'mean_word_length': 2.198795906080674, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '283563', 'license': 'MIT', 'n_tokens_mistral': 13568, 'n_tokens_neox': 11780, 'n_words': 3288, 'path': 'bac_a_sable.ipynb', 'repo_name': 'madvid/42_Gomoku', 'size': '26565'}