Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Im having trouble converting the functions from dictionary/lists to numpy/pandas

ID: 3818280 • Letter: I

Question

Im having trouble converting the functions from dictionary/lists to numpy/pandas. The first function can be done with field=np.zeros((n,n)), where n=4 or n=3. But the remaining are a bit tough to understand. Any suggestions? (Python query)

import random
import copy

def create_field(n):
    field = []
    for i in range(n):
        field.append([0] * n)
    return field

def check_result(field, sign, n, m):
    # check if there are _m_ entries of _sign_ in a line
  
    # check rows
    for i in range(n):
        cnt = 0
        for j in range(n):
            if field[i][j] == sign:
                cnt = cnt + 1
                if cnt >= m:
                    return [sign, "Horiz", i, j]
            else:
                cnt = 0
  
    # check columns
    for i in range(n):
        cnt = 0
        for j in range(n):
            if field[j][i] == sign:
                cnt = cnt + 1
                if cnt >= m:
                    return [sign, "Vert", j, i]
            else:
                cnt = 0
      
    # check diag left
    for i in range(m-n, n-m+1):
        cnt = 0
        for j in range(n):
            if j+i >= 0 and j+i < n:
                if field[i+j][j] == sign:
                    cnt = cnt + 1
                    if cnt >= m:
                        return [sign, "Diag Left", i+j, j]
                else:
                    cnt = 0
      
    # check diag right
    for i in range(m-n, n-m+1):
        cnt = 0
        for j in range(n):
            if j+i >= 0 and j+i < n:
                if field[j+i][n-j-1] == sign:
                    cnt = cnt + 1
                    if cnt >= m:
                        return [sign, "Diag Right", j+i, n-j-1]
                else:
                    cnt = 0        
  
    return True


#### Next step for given field and playing strategy

def next_step(field, sign, palyer_function):
    next_step = palyer_function(field, sign)
    if len(next_step) > 0:
        field[next_step[0]][next_step[1]] = sign
        return True
    else:
        return False


#### Random player

def play_random(field, sign):
    # return list [row, column] or empty list []
    possible_steps = []
    for i in range(n):
        if field[i].count(0) > 0:
            temp = []
            for j in range(n):
                if field[i][j] == 0:
                    temp.append(j)
            possible_steps.append((i,temp))
          
    if len(possible_steps):     
        temp = random.sample(possible_steps, 1)[0]
        next_step = (temp[0], random.sample(temp[1], 1)[0])
        return next_step
    else:
        return []

#### Function to create

def play_smart(field, sign):
    # return list [row, column] or empty list []
    possible_steps = []
    for i in range(n):
        if field[i].count(0) > 0:
            for j in range(n):
                if field[i][j] == 0:
                    possible_steps.append([i, j])
  
    my_next_step = []  
    if len(possible_steps):
        for s in possible_steps:
            field_temp = copy.deepcopy(field)
            field_temp[s[0]][s[1]] = sign
            temp = check_result(field_temp, sign, n, m)
            if temp != True:
                my_next_step = s
                break
      
#        if len(my_next_step) == 0:
#            random.shuffle(possible_steps)
#            for s in possible_steps:
#                field_temp = copy.deepcopy(field)
#                field_temp[s[0]][s[1]] = sign
#                temp = check_result(field_temp, sign, n, m-1)
#                if temp != True:
#                    my_next_step = s
#                    break
      
      
        if len(my_next_step) == 0:
            my_next_step = random.sample(possible_steps, 1)[0]
  
    return my_next_step

#### Main code

n = 3 # size of the field
m = 3 # length of a line to win

k = random.sample([1,2], 2) # select who is first and who is second

field = create_field(n)

fun =[play_random, play_smart]

res = True
while res == True:
    if next_step(field, k[0], fun[k[0]-1]):
        res = check_result(field, k[0], n, m)
        if res == True and next_step(field, k[1], fun[k[1]-1]):
            res = check_result(field, k[1], n, m)
    else:
        res = [0, "Draw - no winner"]
else:
    print("=#=#=#=#=")
    for i in field:
        print(i)
    print(res)


### Multiple runs

report = []
for i in range(1000):
    k = random.sample([1,2], 2) # select who is first and who is second
  
    field = create_field(n)
  
    fun =[play_random, play_smart]
  
    res = True
    while res == True:
        if next_step(field, k[0], fun[k[0]-1]):
            res = check_result(field, k[0], n, m)
            if res == True and next_step(field, k[1], fun[k[1]-1]):
                res = check_result(field, k[1], n, m)
        else:
            res = [0, "Draw - no winner"]
    else:
        report.append(res[0])

print("=#=#=#=#=")
print(report.count(1) / len(report))
print(report.count(2) / len(report))
print(report.count(0) / len(report))

Explanation / Answer

Hi,

As you've asked for suggestions, here are mine:

An example to be thought about could be this:

You see, how the dictionary here has been converted to a numpy array?

That must do your job. But, over that, I'd suggest you to take a look at numpy.fromiter() which saves you from the use of the intermediate tuples, and that is why it is more memory-friendly.

I believe the above suggestions should be sufficient for you.