All projects listed below are personal projects that I completed at my leisure. None of them were graded assignments. All projects listed either have at least publicly accessible GitHub repos associated with them or another way of interacting with them.
My Lights Out app is based on the 1995 handheld electronic game by Tiger Electronics of the same name. In the 1995 version, the game board consists of a 5x5 grid of lights, and then when game starts, a seemingly random pattern of lights is presented to the player. The player's objective is to toggle lights to turn all of the lights off with button presses, preferably in as few presses as possible.
When a light is pressed, the on/off state of the pressed light and all directly adjacent lights are toggled.
Although similar handheld games and apps already exists. There are two things that I belive make my app unique: variable board sizes, and mathematical optimization.
Many of the apps availiable today only feature a single board size, usually the classic 5x5. This makes the app less challenging once the user finds a reliable method for solving the single board size and limits the number of possible scrambles. For the 5x5 board, there are 223=8388608 distinct ways to create a scramble. However, there are at least 4 different ways to create any given scramble, leaving at most 219=524288 unique scrambles. All of these scrambles can be solved in at most 15 button presses.
My app allows user to play any board size from the trivial 1x1 to the daunting 10x10, providing orders of magnitude more unique scrambles than the 5x5 alone. I would have allowed even larges sizes, but the buttons were getting too small to reliably press.
In fact, just the 10x10 size has 2100, over 1 nonillion unique scrambles. For comparision, if each unique board were printed on a sheet of paper .1mm thick, the stack of paper would reach to the edge of the observable universe 13.4 billion light years away.
User have yet another dimension opened to them in being able to play by only pressing buttons that are already on. Although all puzzles that can be solved normally can also be solved by only pressing on buttons, it makes for a much more difficult challenge because the way that most learn to solve the 5x5 board requires pressing off buttons.
I already mentioned how any 5x5 board can be solved in at most 15 button presses. Puzzle enthuiasts and recreational mathematicians like Jaap Scherphuis proved this to be the case. Jaap in particular uses a method of treating solving the board as a linear algebra problem that is described by mathematician Marlow Anderson and Todd Feil in their 1998 paper Turning Lights Out with Linear Algebra.
I implemented Andserson and Feil's method of row-reducing matricies modulo 2 to determine the minimum number of clicks needed to solve any given board. This way users can know how their solve is compared to the absolute best they could do.
Although this value is only one on a screen, I think it provides valuable information to users about a given puzzle's difficults and their own solving abilities that no other app has.
This application started when my high-school engineering class had just moved into a larger building. It was common for expensive tools to get lost or stolen, so we needed a way to find these items and identify any culprits.
Although the new building already had some installed security cameras, there were still many blind spots, and footage could only be saved up to one week, meaning that if a tool were discovered missing after one week had passed, the traditional security cameras would not be useful in recovering it. My solution was to use Raspberry Pi's, which are small, cheap, and single-board computers, as "smart"" security cameras. These devices would be cheaper and easier to install than traditional cameras, and they could be more easily moved to another location if needed.
My first goal was to cut down on the storage space needed for footage without sacrificing picture quality or other valuable information. My solution was for the smart cameras to record video only when they detect motion. This way, disk space wouldn't be wasted on recording hours of the exact scene, but would still catch thieves as they walked into view.
This method worked extremely well. In many cases, hours of video was cut down to mere minutes. However, changing lighting conditions throughout the day could add noise to the image that would be mistaken for motion. I decided to fix this problem by having a threshold for motion that could be calibrated and changed automatically throughout the day. However, I wanted to make sure thieves would still be recorded, regardless of the lighting conditions. This is where computer vision came to my aid. Using Python's OpenCV library, I searched the video feed for faces. If any faces were detected, a green rectangle would be drawn around the face in the video feed, an image of the frame containing the face would be saved, and the camera would wait to recalibrate until no faces were detected.
Taken from the camera's results is an image below of me walking through the frame, the camera has seen my face and is recording video.
Code and results for this and other Python projects are available on GitHub here.
I created INSERT DOMAIN HERE because I felt that my front-end development skills were lacking. Front-end development is taught (if at all) in most computer science curriculums as an afterthought. However, I believe that just as students are taught to make clean, legible, and well-documented code through comments and programming paradigms (like object-oriented), they should also be taught how to make clean, navigable, and intuitive front ends. After all, this is the portion of a product with which most end-users will interact.
Although you are already viewing the website, all the code is available here.
While taking a summer physics class dealing with Maxwell's Equations, which are written in the language of multivariable calculus, I realized how much of the subject I had forgotten, despite taking a multivariable calculus class (Calc III) only nine months earlier. I also knew that several of my friends who would be taking Calc III in the coming semester had already requested my advice about the class or to look at my handwritten notes, but I like to have my notes as a reference.
I decided to digitize my notes using LaTeX in a textbook structure: chapters with sections and sub-sections. I would also add better visual aids than my hurriedly-made sketches using images from textbooks and other online resources. This way, I could more easily share clear, legible notes, keep the original, and refresh my understanding in the process. By the time I was finished, I had condensed the several-thousand page textbook into an 81-page guide that still contained scores of visual aids and many full-length proofs. I feel much more confident in my abilities, and I think my friends will be able to learn from me much more easily.
After completing my notes, I posted the results to r/math, an online community of math enthusiasts. To my surprise, my post was incredibly well-received. Several users suggested open-sourcing my work so that they and others in the community could make corrections and suggest additions.
So, I spent much of the next two weeks converting my GoogleDoc-LaTeX hybrid into a pure LaTeX document. The repo is available and has already taken several contributions.
The language that people choose to use can provide insight into their background and character. Although reasonable people can vhemently disagree, a good indicator of mutual respect between two parties is that neither resorts to vulgarity. Inspired by other bots on platforms like Reddit and Discord, that could provide infrmation on the lauguage that users have used and play a part in keeping online discussion civil, I set out to create a Twitter bot that, when requested by another Twitter user, would provide information on vulgarities that users have recently tweeted.
Bad Word Count Bot Report for @badwordsmovie's last 100 tweets— Bad Word Count Bot (@BadWordCount) October 9, 2019
bitch - 3
hell - 3
fucking - 2
fuck - 2
ass - 1
cunt - 1
fucker - 1
damn - 1
tits - 1
asshole - 1
shit - 1
I wrote the bot in Python, following basic online video tutorials that detailed how to work with the Twitter API through the python library tweepy. Although these tutorials showed me how to detect when a user had @ mentioned the bot and how to respond to tweets, the real challenge and substance of this bot came from accesing another user's tweets, parsing through them to find bad words, and reporting the frequency of these bad words within the 280-character limit of a Tweet.
After finding seperate answers on how to access a given user's tweets, I got to work on detecting bad words. Although I found several GitHub repos that contained lists of bad words, many were too comprehensive, marking even words with possible negative connotationsm, like the names of political parties, as bad. I eventually settled on a list of 444 common words collected by Google. This list was comprehensive enough to cover most bad word, and even common variations like swapping a letter for a number. On the implementation side, I took advantage of Python's built-in dictionary functionality to find matching bad words in a user's 100 most recent tweets and rank them by frequency.
For deployment, I settled on a free service reccomended in one of the simple video tutorials, PythonAnywhere. I know that this solution is probably not best practice, but I struggled with trying to use other platforms like Heroku because I could not work out compatability issues or find documentation detailed enough to fix issues.
The bot's Twitter handle is @BadWordCount. Go ahead and try it out on some of your favorite twitter users. The code that the bot is running is on my GitHub. Feel free to look at some of the other projects I've done while you're there.
I originally started working on this project in high school to practice array manipulation in preparation for the AP Computer Science A exam. My main goal at that point was to be able to find the reduced-row echelon form of a given array of doubles, allowing me to solve linear systems of equations.
As my knowledge grew regarding object-oriented programming and the applications of matrices to structures like networks, so did this project. I added a "Vector" class where one could determine vector information (e.g., cross-product and dot-product) or use these Vectors to populate a Matrix. One major change I made was making the "Matrix" class generically-typed, with "BinaryMatrix" and "NumericMatrix" extending the Matrix class and adding additional data type-specific functionality. For example, a specific application of the BinaryMatrix class is the ability to represent and determine qualities (e.g., reflexive, transitive, trichotomous) of binary relations; the DoubleMatrix class can solve linear systems of equations like originally intended.
I also learned the importance of unit testing and code coverage. Currently, all fully-implemented classes have 100% method coverage, at least 90% line coverage, and all tests passing. I will continue to add more unit tests and maintain high coverage as I implement greater functionality.
Below is a recent coverage report. All concrete classes, except those in the graph package and NumericMatrix, have more than 95% line coverage. Classes in the graph package are not yet ready for a round of testing, and NumericMatrix may soon be deleted, depending on whether this library will support matrices of non-numerical values.
In the future, I want to continue adding functionality for important objects in mathematics and computer science that are commonly represented as matrices. This includes items like Markov Chains and graphs. I am especially excited about developing weighted and directed graphs (digraphs) for applications like pathfinding and optimization.
Code and JavaDoc for the Linear Algebra library is available here.
Visuals have always been an effective and fun way for me to learn, especially when the topic is abstract. The tkinker, turtle, and Pillow Python GUI libraries allow for simple image manipulation, down to the pixel level.
For example, the left image below visualizes how numbers change after a given number of iterations in the unsolved Collatz conjecture; it has been my phone background for several years. For a more artistic visualization, see the right image below, which applies a smeared watercolor effect.
One can also visualize more useful and common mathematical ideas. The left image below shows how horizontal and vertical lines in the complex plane are transformed under e^(1/z). One can clearly see concentric cardioids. The right image below shows the graph of several common functions, like sine and the natural logarithm.
The Turtle library allows one to trace out colored paths in an image, like the rainbow spiral no the left below. Getting a little more advanced, one can create recursive shapes, like the Koch Snowflake, Serpinski Triangle, and dragon curve, shown below.
One can also make other startlingly complex images from a simple set of recursive rules. The below images, known colleteively as "strange attractors," show a tree, Barnsley Fern, pine branch and piece of tall grass. The procedural generation techniques used to create these images, known as L-systems, are used in many of today's popular video games to make random, realistic terrain and plants.
The images above and many others that I made in Python, as well as the code used to create them, are available on GitHub here. Code and results for this and other Python projects are available on GitHub here.