Calvin Goodale, Developer - Blog
c g o o d a a l e . . c o m

HackerRank: Matrix Layer Rotation (Part 1)

I've been doing a few HackerRank problems each week since I started studying Python (sometimes other things such as take-home challenges for interviews take precedence) to get better at problem solving. I'm at the point now where the problems rated as 'Easy' are very doable for me in less than an hour, and the 'Medium' problems I can usually solve within a few sessions of work. This is my first 'Hard' rated problem attempt, and I thought it would be a good one to work on since the problem is easily understandable for me:

Given a matrix (2d list of lists in this case) and a number of rotations, rotate the entire matrix counter clockwise by the number of rotations and then return the new matrix.

The first thing I did in order to begin solving this problem is to get each matrix 'slice' (with each slice being a rectangular 'box' of elements, for example the outermost box, then the box smaller by 1 on each side, etc) into a string, in order around the box starting from the top left, so I could easily 'rotate' this slice the appropriate number of times:

import itertools

matrix = [[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]]
r = 2


def matrixRotation(matrix, r):
    # Number of rows in the matrix
    rows = len(matrix)
    # Number of columns in the matrix
    columns = len(matrix[0])

    # New list that will contain each slice of the matrix in a new list
    matrices = []
    # The number of slices in the matrix
    matrix_num = min(rows, columns) / 2
    i = 0
    while i < matrix_num:
        single_matrix = []
        # The top (left to right) of the matrix slice
        top = matrix[i][i:rows-i]
        # The right side (top to bottom) of the matrix slice
        right = [matrix[row][rows-1-i] for row in range(i+1, rows-i-1)]
        # The bottom (right to left) of the matrix slice
        bottom = matrix[rows-i-1][i:columns-i]
        bottom.reverse()
        # The left side (bottom to top) of the matrix slice
        left = [matrix[row][i] for row in range(i+1, rows-i-1)]
        left.reverse()
        
        i += 1

        # Append each side of the matrix slice to the single_matrix list, with each side in its own list
        single_matrix.extend([top, right, bottom, left])
        # Turn the single_matrix list of lists into a single list
        single_matrix = [x for x in single_matrix if x != []]
        # Turn into a flat list
        single_matrix = list(itertools.chain(*single_matrix))
        # Rotate this flat list counter clockwise by r
        single_matrix = single_matrix[r:] + single_matrix[:r]
        # Append the rotated list to the matrices list
        matrices.append(single_matrix)

    return matrices

Now I have each slice of the matrix in a flat list and rotated the correct number of times. My next steps will be to turn this flat list back into a matrix of the same number of rows and columns as the original matrix, which for some reason feels more difficult than the steps I took get each slice into a list. My next blog post will (hopefully) detail how I achieved this.

To be continued...


0 Comments

Category Navigation

Today, I restructured my SQL database a bit to better handle the displaying of posts based on their categories. Initially, I had a column in the Post table called "category" that was collecting the category (or categories) that I entered in when making a new post. I realized that it would be better to keep each category on a particular post in a separate row in the table - this way I wouldn't need to split the category cell by comma or space in order to add multiple categories to each post.

There is now a new table in my database specifically for categories, with a column that relates that particular category instance to a specific post. It took me a bit of research to figure out how to do an inner join with a filter in order to first query from the 'categories' table based on a particular category, and then reference that category instance with a specific post, but I was able to solve it with a little help from a programming Discord I am in.

I ended up deciding to add a small sidebar on the /blog page of my website with a drop-down containing a unique list of all of the categories, that when clicked brings you to a page with posts tagged with that particular category, and I'm pretty happy with it so far.


0 Comments

Godot Game Dev

I've also been working on learning Godot, a game development engine that a few of my dev friends are learning in order to make a game together. This week I've been following a tutorial to make an ARPG, and it's been going pretty smoothly. So far, I have a small 'level' scene, with a character that can move around, roll, and attack, as well as some enemies and destructable bushes.

(Not my art or animations, they came from the tutorial)

godot


0 Comments

Cross-Pollination Contamination

Today, I pushed the new website code to a github repository, and was immediately rewarded for doing so when a dev friend noticed that I had a few unprotected endpoints in my routes.py file. I didn't realize that it was possible to create HTTP requests through the browser console or other methods, which would have allowed unauthenticated users to perform admin-only tasks on my website.

To resolve this, I simply had to add a g.user if/else statement to the other routes that are utilizing the POST method. Lesson learned: Pay attention to authentication and endpoints before deploying a website (unless you want one of your friends to post the entirety of The Bee Movie script to your blog page.) Shout out to Ian for using his powers for good instead of evil.

🐝


3 Comments:

Barry B. Benson October 24, 2021
This sweater is Ralph Lauren, and I have no pants.
Chuck Staples October 25, 2021
Always Bee Careful to secure your endpoints.
Kelly Pracht November 11, 2021
Love the projects! Wonder how many open endpoints I have in past websites! Doh!

Commenting functionality

Comments are now functioning on the Blog section of my website. The most difficult part of this was figuring out the best way to relate a comment to a post in the database. Comments have a "post_id" column that is linked to the id of the post it is created under, and I needed to find a way to have this record match up with the related post.

It turns out that jinja can handle this pretty easily within a for loop, and as long as the comment loop is within the post loop you can simply reference the id of the post somewhere in the form you are requesting data from. I used a hidden form and then gave it a value of {{post.id}} (thanks Eben <3) and was able to assign it to a variable in my comments() function and add it as an entry in the database.

<input type="hidden" name="post-id" value="{{post.id">

I gave each comment an "approved" column in the database, which is a boolean that tells me whether or not a comment has been approved. Submitted comments display on my admin page and can be approved or rejected from there - comments that are unapproved are given a value of 0, comments that are approved are given a value of 1, and rejected comments are deleted from the database. I also added a flash message that displays when a user submits a comment to let them know that it is awaiting approval.

I do have a "category" column in the database for blog posts, but I haven't utilized these yet (although I have been adding categories). I will likely display these somewhere under the title at some point in the future.

Next goals:

  • Blog sidebar
  • Search functionality
  • Display by category


0 Comments