The MathJam...
by SirCalcsALot, Jan 27, 2021, 1:49 AM
Thanks to the AoPS devs for getting the classroom working so the mathjam could take place. 
Just going to put this here:


Just going to put this here:

Pendulum Art Avatars
by SirCalcsALot, Nov 30, 2020, 2:12 AM
Hello! 
I've got some more simulations of pendulum art, and I decided to turn some of the results into avatars. Feel free to use any that you like!
You can save images by right clicking on them and pressing 'Save Image As..' (at least, that's how it works on chrome).
Here are the 10 avatars I created. The sizes are a bit off, but I tested that these all work as avatars.
#1:
#2:
#3:
#4:
#5:
#6:
#7:
#8:
#9:
#10:
If you have a specific orientation or colors that are not shown, let me know in the comments and I might be able to make a custom avatar for you.

I've got some more simulations of pendulum art, and I decided to turn some of the results into avatars. Feel free to use any that you like!

Here are the 10 avatars I created. The sizes are a bit off, but I tested that these all work as avatars.
#1:

#2:

#3:

#4:

#5:

#6:

#7:

#8:

#9:

#10:

If you have a specific orientation or colors that are not shown, let me know in the comments and I might be able to make a custom avatar for you.

Virtual Pendulum Art
by SirCalcsALot, Nov 26, 2020, 4:56 AM
Hi all!
It's been a while since I've posted, but I've gotten busy with college and haven't had a chance to mess with the night vision project too much. In the meanwhile, I thought I would share the results of some code I wrote (with a teammate) for my Programming for Physicists class.
As you can see above, we are working on building a computational model for pendulum art. Based on the results we have achieved, I think we need to move from writing code to to writing our presentation slides...
It's pretty cool what you can do with 300 lines of C++ code and 60 lines of Python code.
It's been a while since I've posted, but I've gotten busy with college and haven't had a chance to mess with the night vision project too much. In the meanwhile, I thought I would share the results of some code I wrote (with a teammate) for my Programming for Physicists class.

As you can see above, we are working on building a computational model for pendulum art. Based on the results we have achieved, I think we need to move from writing code to to writing our presentation slides...

It's pretty cool what you can do with 300 lines of C++ code and 60 lines of Python code.

I made night vision!1!!!iI!i!
by SirCalcsALot, Oct 17, 2020, 7:04 PM
Yay, the parts I've been waiting for finally came. After a bit of time tinkering with the parts, computer code, circuit diagrams, and tape, my first night vision prototype is complete.
Introducing: Night Vision Beta Version Prototype v.1.-1
Don't try this at home. For those who are curious on how it's built, see the instructional image below (more details coming out in a later post, maybe).
Now, here are some images of the night vision in action.
First, here are my cats. (Note that ultrasound doesn't bounce well off kitties which is why the range isn't accurate.) G.G.Otto says that I was blasting them with sound and light and they don't even know.
Next, a lawnmower that's been sitting in my yard for so long we had to weedwack around it. (Notice that ultrasound does bounce nicely off broken down lawnmowers...)
Finally, here's my jungle. There probably is 96 ft 7 in off empty space in front of me, so I guess the range finder works?!?
Stay safe, and see you next time!
(Inspiration for this project came from Star Wars: the Mandalorian. Sadly, cheap thermal cameras are out of stock due to covid.)
Introducing: Night Vision Beta Version Prototype v.1.-1


Now, here are some images of the night vision in action.
First, here are my cats. (Note that ultrasound doesn't bounce well off kitties which is why the range isn't accurate.) G.G.Otto says that I was blasting them with sound and light and they don't even know.


Next, a lawnmower that's been sitting in my yard for so long we had to weedwack around it. (Notice that ultrasound does bounce nicely off broken down lawnmowers...)

Finally, here's my jungle. There probably is 96 ft 7 in off empty space in front of me, so I guess the range finder works?!?

Stay safe, and see you next time!
(Inspiration for this project came from Star Wars: the Mandalorian. Sadly, cheap thermal cameras are out of stock due to covid.)
NxNxN Default Generator
by SirCalcsALot, Aug 27, 2020, 3:49 AM
As requested by sonone, here is my code to my NxNxN default generator. I don't have time to explain the code, so you'll have to figure out how it works on your own. Feel free to ask in questions in the comments though! This code is in an incomplete state since the project got put on the back burner and I forgot about it. Add extra features if you want! 
Suggestion for anyone interested: try to make it where the stacking doesn't result in a 'drop off'. The code currently doesn't generate avatars uniformly.
Tip: avatars larger than 20 x 20 x 20 will likely time out on AoPS.
![[asy]
size(5cm,5cm);
/*
CREATED BY SIRCALCSALOT
BASED OFF SONONE'S 3x3 SELECTIVE DEFAULT GENERATOR
DO NOT USE WITHOUT PERMISSION
CODE MAY BE HARD TO TAMPER WITH
SO STORE IN AN AIRTIGHT CONTAINER
THANKS!
*/
srand(seconds());
import three;
currentprojection=orthographic(3,3,3);
//++++ customization ++++
pen top = rgb(153/255,200/255,99/255);
pen left = rgb(254/255,245/255,182/255);
pen right = rgb(27/255, 135/255, 212/255);
pen edges=invisible; // invisible recommended for large cubes
int max_side = 23;
int max_rand_side = 23;
int rand_colors = 1;
int rand_shape = 1;
int rand_side = 0;
int rand_bg_color = 0;
int[][] custom_heights = {
{3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{2, 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, 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, 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, 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}};
//++++ end customization ++++
/* BEGIN MADE BY SIRCALCSALOT */
if (rand_side == 1) {
max_side = rand() % max_rand_side + 1;
}
if (rand_colors == 1) {
top = rgb((rand()%256)/255, (rand()%256)/255,(rand()%256)/255);
left = rgb((rand()%256)/255, (rand()%256)/255,(rand()%256)/255);
right = rgb((rand()%256)/255, (rand()%256)/255, (rand()%256)/255);
}
if (rand_bg_color == 1) {
edges = edges + rgb((rand()%256)/255, (rand()%256)/255, (rand()%256)/255);
}
if (max_side >= 4) {
edges = edges + linewidth(0.5);
}
if (max_side >= 9) {
edges = edges + linewidth(0.25);
}
/* END MADE BY SIRCALCSALOT */
/* MADE BY SONONE */
path3 leftface=(1,0,0)--(1,1,0)--(1,1,1)--(1,0,1)--cycle;
path3 rightface=(0,1,0)--(1,1,0)--(1,1,1)--(0,1,1)--cycle;
path3 topface=(0,0,1)--(1,0,1)--(1,1,1)--(0,1,1)--cycle;
for(int i=0; i<max_side; ++i){
for(int j=0; j<max_side; ++j){
draw(shift(i,j,-1)*surface(topface),top,nolight);
draw(shift(i,j,-1)*topface,edges);
draw(shift(i,-1,j)*surface(rightface),right,nolight);
draw(shift(i,-1,j)*rightface,edges);
draw(shift(-1,j,i)*surface(leftface),left,nolight);
draw(shift(-1,j,i)*leftface,edges);
}
}
picture CUBE;
draw(CUBE,surface(leftface),left,nolight);
draw(CUBE,surface(rightface),right,nolight);
draw(CUBE,surface(topface),top,nolight);
draw(CUBE,topface,edges);
draw(CUBE,leftface,edges);
draw(CUBE,rightface,edges);
/* END MADE BY SONEONE */
/* BEGIN MADE BY SIRCALCSALOT */
int[][] heights = new int[max_side][max_side];
for (int i = 0; i < max_side; ++i) {
for (int j = 0; j < max_side; ++j) {
heights[i][j] = 0;
}
}
for (int i = 0; i < max_side; ++i) {
heights[i][max_side-1-i] = rand() % (max_side+1);
}
for (int k = 1; k < max_side; ++k) {
for (int i = 0; i < max_side - k; ++i) {
heights[i][max_side-1-k-i] = max_side - rand() % (max_side + 1 - max(heights[i+1][max_side-1-k-i],heights[i][max_side-k-i]));
}
}
for (int k = 1; k < max_side; ++k) {
for (int i = k; i < max_side; ++i) {
int above = heights[i][max_side-i-1+k-1];
int leftof = heights[i-1][max_side-i+k-1];
heights[i][max_side-i+k-1] = rand() % (min(above,leftof) + 1);
}
}
/* for (int i = 1; i < max_side; ++i) {
int above = heights[i][max_side-i-1];
int leftof = heights[i-1][max_side-i];
heights[i][max_side-i] = rand() % (min(above,leftof) + 1);
}
for (int i = 2; i < max_side; ++i) {
int above = heights[i][max_side-i-1+1];
int leftof = heights[i-1][max_side-i+1];
heights[i][max_side-i+1] = rand() % (min(above,leftof) + 1);
}*/
if (rand_shape == 0) {
for (int i = 0; i < max_side; ++i) {
for (int j = 0; j < max_side; ++j) {
heights[i][j] = custom_heights[i][j];
}
}
}
for (int i = 0; i < max_side; ++i) {
for (int j = 0; j < max_side; ++j) {
for (int k =0; k < min(heights[i][j], max_side); ++k) {
add(shift(i,j,k)*CUBE);
}
}
}
real a = 2*max_side/3;
draw((0,0,0)--(0,0,sqrt(3)*a),invisible);
draw((0,0,0)--(0,0,-sqrt(3)*a),invisible);
draw((0,0,0)--(-a,a,0),invisible);
draw((0,0,0)--(a,-a,0),invisible);
/* END MADE BY SIRCALCSALOT */
[/asy]](//latex.artofproblemsolving.com/f/d/0/fd0b7584abfc69b9b052ead49a21bc60b692a669.png)

Suggestion for anyone interested: try to make it where the stacking doesn't result in a 'drop off'. The code currently doesn't generate avatars uniformly.
Tip: avatars larger than 20 x 20 x 20 will likely time out on AoPS.
![[asy]
size(5cm,5cm);
/*
CREATED BY SIRCALCSALOT
BASED OFF SONONE'S 3x3 SELECTIVE DEFAULT GENERATOR
DO NOT USE WITHOUT PERMISSION
CODE MAY BE HARD TO TAMPER WITH
SO STORE IN AN AIRTIGHT CONTAINER
THANKS!
*/
srand(seconds());
import three;
currentprojection=orthographic(3,3,3);
//++++ customization ++++
pen top = rgb(153/255,200/255,99/255);
pen left = rgb(254/255,245/255,182/255);
pen right = rgb(27/255, 135/255, 212/255);
pen edges=invisible; // invisible recommended for large cubes
int max_side = 23;
int max_rand_side = 23;
int rand_colors = 1;
int rand_shape = 1;
int rand_side = 0;
int rand_bg_color = 0;
int[][] custom_heights = {
{3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{2, 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, 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, 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, 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}};
//++++ end customization ++++
/* BEGIN MADE BY SIRCALCSALOT */
if (rand_side == 1) {
max_side = rand() % max_rand_side + 1;
}
if (rand_colors == 1) {
top = rgb((rand()%256)/255, (rand()%256)/255,(rand()%256)/255);
left = rgb((rand()%256)/255, (rand()%256)/255,(rand()%256)/255);
right = rgb((rand()%256)/255, (rand()%256)/255, (rand()%256)/255);
}
if (rand_bg_color == 1) {
edges = edges + rgb((rand()%256)/255, (rand()%256)/255, (rand()%256)/255);
}
if (max_side >= 4) {
edges = edges + linewidth(0.5);
}
if (max_side >= 9) {
edges = edges + linewidth(0.25);
}
/* END MADE BY SIRCALCSALOT */
/* MADE BY SONONE */
path3 leftface=(1,0,0)--(1,1,0)--(1,1,1)--(1,0,1)--cycle;
path3 rightface=(0,1,0)--(1,1,0)--(1,1,1)--(0,1,1)--cycle;
path3 topface=(0,0,1)--(1,0,1)--(1,1,1)--(0,1,1)--cycle;
for(int i=0; i<max_side; ++i){
for(int j=0; j<max_side; ++j){
draw(shift(i,j,-1)*surface(topface),top,nolight);
draw(shift(i,j,-1)*topface,edges);
draw(shift(i,-1,j)*surface(rightface),right,nolight);
draw(shift(i,-1,j)*rightface,edges);
draw(shift(-1,j,i)*surface(leftface),left,nolight);
draw(shift(-1,j,i)*leftface,edges);
}
}
picture CUBE;
draw(CUBE,surface(leftface),left,nolight);
draw(CUBE,surface(rightface),right,nolight);
draw(CUBE,surface(topface),top,nolight);
draw(CUBE,topface,edges);
draw(CUBE,leftface,edges);
draw(CUBE,rightface,edges);
/* END MADE BY SONEONE */
/* BEGIN MADE BY SIRCALCSALOT */
int[][] heights = new int[max_side][max_side];
for (int i = 0; i < max_side; ++i) {
for (int j = 0; j < max_side; ++j) {
heights[i][j] = 0;
}
}
for (int i = 0; i < max_side; ++i) {
heights[i][max_side-1-i] = rand() % (max_side+1);
}
for (int k = 1; k < max_side; ++k) {
for (int i = 0; i < max_side - k; ++i) {
heights[i][max_side-1-k-i] = max_side - rand() % (max_side + 1 - max(heights[i+1][max_side-1-k-i],heights[i][max_side-k-i]));
}
}
for (int k = 1; k < max_side; ++k) {
for (int i = k; i < max_side; ++i) {
int above = heights[i][max_side-i-1+k-1];
int leftof = heights[i-1][max_side-i+k-1];
heights[i][max_side-i+k-1] = rand() % (min(above,leftof) + 1);
}
}
/* for (int i = 1; i < max_side; ++i) {
int above = heights[i][max_side-i-1];
int leftof = heights[i-1][max_side-i];
heights[i][max_side-i] = rand() % (min(above,leftof) + 1);
}
for (int i = 2; i < max_side; ++i) {
int above = heights[i][max_side-i-1+1];
int leftof = heights[i-1][max_side-i+1];
heights[i][max_side-i+1] = rand() % (min(above,leftof) + 1);
}*/
if (rand_shape == 0) {
for (int i = 0; i < max_side; ++i) {
for (int j = 0; j < max_side; ++j) {
heights[i][j] = custom_heights[i][j];
}
}
}
for (int i = 0; i < max_side; ++i) {
for (int j = 0; j < max_side; ++j) {
for (int k =0; k < min(heights[i][j], max_side); ++k) {
add(shift(i,j,k)*CUBE);
}
}
}
real a = 2*max_side/3;
draw((0,0,0)--(0,0,sqrt(3)*a),invisible);
draw((0,0,0)--(0,0,-sqrt(3)*a),invisible);
draw((0,0,0)--(-a,a,0),invisible);
draw((0,0,0)--(a,-a,0),invisible);
/* END MADE BY SIRCALCSALOT */
[/asy]](http://latex.artofproblemsolving.com/f/d/0/fd0b7584abfc69b9b052ead49a21bc60b692a669.png)
A code to make a code to make a code...
by SirCalcsALot, Aug 15, 2020, 9:08 PM
Hi everyone! It's been a while since my last post, but I finally finished another project I can share.
I saw a post by sonone on the LaTeX and Asymptote that showed a random QR code made with Asymptote. Since QR codes have certain rules, so I thought I'd attempt at making a scannable QR code with Asymptote. It turns out Python was easier to work with, so I implemented the main algorithm with and had Python print the Asymptote code to draw the QR code. And that's where the title of my post comes in, I made a Python code to write Asymptote code to draw a QR code.
Anyway, here is the code for anyone curious: QR Code Generator. To use the code, simply run the program and enter a valid string that is less than 45 characters in length. You can only enter strings with valid characters: 0-9, A-Z (capital only), and a few special characters such as :, /, ., and +. For this, reason the QR code is a little limited in the types of urls you can link with it. I ended up having to use a link shorten (bit.ly to be precise) to get links to certain websites to work.
To actually generate the QR codes, I used this tutorial. My QR code generator is just the tip of the iceberg! The code is a bit long since I ended up using a lot of dictionaries to store tables instead of actually computing the numbers in those tables. In principle, these are the steps you need to take when generating a QR code:
QR codes are pretty handy since it makes it really easy to share data quickly on the fly! You can also set your profile picture to a QR code of something you want to advertise. That's free advertising space on every post you make!
Fun fact: Python already has a module to generate QR codes called pyqrcode. You can download it using the command pip3 install pyqrcode (no guarantees, but that's what worked on my Raspberry Pi).
Here are a few example QR codes generated with my code.
![[asy]
int[][] qrdata = {{1,1,1,1,1,1,1,0,1,1,0,0,1,0,1,1,1,1,1,1,1},
{1,0,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1},
{1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,1,0,1,0,1,0,0,1,0,0,1,1,1,0,0},
{1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,1,1,1,1,0},
{0,1,1,0,1,0,1,1,1,1,1,0,1,1,0,1,0,0,0,1,1},
{1,1,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1},
{0,1,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0},
{0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,0},
{1,1,1,1,1,1,1,0,0,1,0,0,0,1,1,1,1,0,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,1,1,0,0,1,0,1,0,0,1},
{1,0,1,1,1,0,1,0,0,1,0,1,0,0,1,1,0,0,1,1,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,1,0,0,0,0,0,1,0},
{1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,1,0,0,0,0},
{1,0,0,0,0,0,1,0,1,0,0,1,1,0,1,1,1,0,0,0,0},
{1,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,1,1,1,1,0},
};
int side = 21;filldraw((-4, 4)--(-4,-(side+4))--(side+4, -(side+4))--(side+4, 4)--cycle, white);
for (int i = 0; i < side; ++i) {
for (int j = 0; j < side; ++j) {
if (qrdata[j][i] == 1) {
fill((i, -j)--(i+1,-j)--(i+1,-j-1)--(i,-j-1)--cycle, black);
}
}
}
[/asy]](//latex.artofproblemsolving.com/3/e/3/3e36f39f0d57cf2a2a00ccec51f9cdfc177587b2.png)
![[asy]
int[][] qrdata = {{1,1,1,1,1,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1},
{1,0,0,0,0,0,1,0,0,1,1,1,1,0,1,1,1,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,0,1,1,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,1,0,1,1,0,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,1},
{1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,1,0,1,0,1,1,1,0,0,0,1,1,0,0,1,1,1,0,0},
{1,0,1,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,1,1,0,0,0,0,0},
{1,0,1,1,0,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,0,1,0,0,0},
{1,1,1,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,1,0,1,1,1,0,1},
{0,0,0,1,1,1,1,0,0,1,1,0,1,0,0,0,0,1,0,0,1,1,0,0,0},
{0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,0,0,1,1,1,0,1,1},
{0,1,0,1,0,1,1,0,1,1,1,1,0,0,0,1,1,1,0,1,0,0,0,0,1},
{1,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,1,1,1,0,1,1,0,1,1},
{0,0,0,0,1,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,1,1},
{1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,1,1,0,1,0,1,0,0,0,1},
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,0,0,0,1,1,1,1,0},
{1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,1,1,1,1,1,1,1,0,0},
{1,0,1,1,1,0,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1},
{1,0,1,1,1,0,1,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,1,1,0},
{1,0,0,0,0,0,1,0,1,0,1,1,1,1,0,1,1,1,0,0,0,0,1,0,1},
{1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,0,1,0,0,1,0,0,1},
};
int side = 25;filldraw((-4, 4)--(-4,-(side+4))--(side+4, -(side+4))--(side+4, 4)--cycle, white);
for (int i = 0; i < side; ++i) {
for (int j = 0; j < side; ++j) {
if (qrdata[j][i] == 1) {
fill((i, -j)--(i+1,-j)--(i+1,-j-1)--(i,-j-1)--cycle, black);
}
}
}
[/asy]](//latex.artofproblemsolving.com/5/9/0/5906afe20b80d35eda060d74e18ff83f88a505f5.png)
![[asy]
int[][] qrdata = {{1,1,1,1,1,1,1,0,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,1,1,1},
{1,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,1,1,0,1,1,0,1,0,1,0,0,0,0,0,1},
{1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,1,1,1,1,0,1,0,1,0,0,0,1,0,0,1,1,1,0,0},
{0,1,1,0,1,1,0,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,1,0,1,1,1,0,1,0,0,1,0},
{1,1,1,1,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,0,0,0,0,1,0},
{0,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1},
{1,0,0,1,0,0,1,1,1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,1,0,1,0,1,1,0},
{1,1,0,1,0,1,0,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,0,1,0,1,1,1,1,0,1,0,0,0,0,1,0},
{1,1,1,0,1,1,1,0,1,0,0,1,0,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,0,1,0,0,1,0,0,0},
{1,1,0,1,0,1,0,1,0,0,1,1,0,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1},
{0,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,0,1,1,1,1,1,0,0,1,0,0,0},
{0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,1,1,1,1,0,0,1,0,0,0,1,0,1,0,1,1,1,1,0,0,0,0},
{1,0,0,1,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,0,0,1,1,1,1,1},
{0,0,1,1,1,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0,1,0,0,1,0,0,0,0,0},
{0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,1,0,1,1,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1},
{0,1,0,0,1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,0,0,1},
{0,1,0,0,0,1,1,1,1,1,1,0,0,0,1,0,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,0,0,1},
{1,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,1,0,0,1,0,0,1,0,0},
{0,1,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,1,0},
{0,0,1,0,0,1,0,0,1,1,0,1,0,0,0,1,1,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,1,1,0,0,1},
{0,1,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,0,0,1,0,1,0},
{1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,1,1,0,1,1,0,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,1},
{0,0,1,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0},
{0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,1,1,1,0,0,0,1,1,1,1,1},
{1,1,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,1,0,1,1,1,1,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,1,1,1,0,1,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0},
{1,0,1,1,1,0,1,0,0,1,1,1,1,1,0,1,0,1,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,0},
{1,0,1,1,1,0,1,0,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,1,1,0,1,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,1,1,0,0,0,0},
{1,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,0,0,0,1,1,1,0,1,1,0,1},
{1,1,1,1,1,1,1,0,1,1,0,0,1,0,1,1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1},
};
int side = 37;filldraw((-4, 4)--(-4,-(side+4))--(side+4, -(side+4))--(side+4, 4)--cycle, white);
for (int i = 0; i < side; ++i) {
for (int j = 0; j < side; ++j) {
if (qrdata[j][i] == 1) {
fill((i, -j)--(i+1,-j)--(i+1,-j-1)--(i,-j-1)--cycle, black);
}
}
}
[/asy]](//latex.artofproblemsolving.com/2/4/b/24bbabfc6866c170ca0ac48e7f5f5a3bdc668ccf.png)
Let me know if you have any questions about using my QR code generator or generating QR codes in general.
I saw a post by sonone on the LaTeX and Asymptote that showed a random QR code made with Asymptote. Since QR codes have certain rules, so I thought I'd attempt at making a scannable QR code with Asymptote. It turns out Python was easier to work with, so I implemented the main algorithm with and had Python print the Asymptote code to draw the QR code. And that's where the title of my post comes in, I made a Python code to write Asymptote code to draw a QR code.

Anyway, here is the code for anyone curious: QR Code Generator
class QRCode: ''' supports Version 1, 2, 4, and 5 QR codes with quality L encodes data in alphanumeric form ''' def __init__(self, version, dataStr): '''QRCode.__init__(int, str) -> None Initializes QRCode object ''' ## Look-up tables self.charCapacityDict = {'1L':25 ,'2L':47, '3L':77, '4L':114, '5L':154, '6L':195, '1M':20 ,'2M':38, '3M':61, '4M':90, '5M':122, '6M':154, '1Q':16 ,'2Q':29, '3Q':47, '4Q':67, '5Q':87, '6Q':108, '1H':10 ,'2H':20, '3H':35, '4H':50, '5H':64, '6H':84} self.bytesCapacityDict = {'1L':19 ,'2L':34, '3L':55, '4L':80, '5L':108, '6L':136, '1M':16 ,'2M':28, '3M':44, '4M':64, '5M':86, '6M':108, '1Q':13 ,'2Q':22, '3Q':34, '4Q':48, '5Q':62, '6Q':76, '1H':9 ,'2H':16, '3H':26, '4H':36, '5H':46, '6H':60} self.ECcodewords = {'1L': (7,1,19), '2L':(10,1,34) ,'3L':(15,1,55) , '4L':(20,1,80) ,'5L':(26,1,108)} self.generatorPolynomials = {7:[0,87,229,146,149,238,102,21], 10:[0,251,67,46,61,118,70,64,94,32,45], 15:[0,8,183,61,91,202,37,51,58,237,140,124,5,99,105], 20:[0,17,60,79,50,61,163,26,187,202,180,221,225,83,239,156,164,212,212,188,190], 26:[0,173,125,158,2,103,182,118,17,145,201,111,28,165,53,161,21,245,142,13,102,48,227,153,145,218,70], 18:[0,215,234,158,94,184,97,118,170,79,187,152,148,252,179,5,98,96,153]} self.alphanumEncode = {'0': '0', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', 'A': '10', 'B': '11', 'C': '12', 'D': '13', 'E': '14', 'F': '15', 'G': '16', 'H': '17', 'I': '18', 'J': '19', 'K': '20', 'L': '21', 'M': '22', 'N': '23', 'O': '24', 'P': '25', 'Q': '26', 'R': '27', 'S': '28', 'T': '29', 'U': '30', 'V': '31', 'W': '32', 'X': '33', 'Y': '34', 'Z': '35', '$':'37', '%': '38', '*': '39', '+': '40', '-': '41', '.': '42', '/': '43', ':': '44', ' ': '36'} self.formatStrings = {'L0': '111011111000100','L1': '111001011110011', 'L2': '111110110101010','L3': '111100010011101', 'L4': '110011000101111','L5': '110001100011000', 'L6': '110110001000001','L7': '110100101110110'} # raise AttributeError's for unsupported data types if version not in range(1,6) or version == 3: raise AttributeError if self.charCapacityDict[str(version)+"L"] < len(dataStr): raise AttributeError # define attributes self.dataStr = dataStr.upper() self.error = 'L' self.dataBits = '' self.errorBits = '' self.bits = '' self.mask = 3 self.version = version self.size = 17 + 4 * version self.matrix = [[0 for i in range(self.size)] for j in range(self.size)] self.reserved = [] # set up grid and encode data self.encode_data() self.encode_ec() self.interleave_blocks() self.add_finders() self.add_reserved_areas() self.add_alignment_patterns() self.add_darkmodule() self.add_timing() self.place_data_bits() self.add_format_string(self.mask) self.apply_mask(self.mask) def __str__(self): '''str(QRCode) -> str string method for QRCode object''' out = "" # empty string for r in range(self.size): for c in range(self.size): out += str(self.matrix[r][c]) + " " out += "\n" # add new line at end of row return out def asy(self): '''QRCode.asy() -> str returns string containing asymptote code to draw QR code''' # define output matrix qrdata in asymptote out = "[asy]\nint[][] qrdata = {" for r in range(self.size): row = "{" for c in range(self.size): row += str(self.matrix[r][c]) + "," row = row[:len(row)-1] # remove last comma row += "},\n" # add newline and bracket out += row # add code to draw matrix out += "};\nint side = " + str(self.size) + ";" out += '''filldraw((-4, 4)--(-4,-(side+4))--(side+4, -(side+4))--(side+4, 4)--cycle, white); for (int i = 0; i < side; ++i) { for (int j = 0; j < side; ++j) { if (qrdata[j][i] == 1) { fill((i, -j)--(i+1,-j)--(i+1,-j-1)--(i,-j-1)--cycle, black); } } }\n[/asy]''' return out # return asymptote code as string def encode_data(self): '''QRCode.encode_data() -> str Encodes alphanumeric characters as binary and returns it''' # if not empty, don't allow new encoding if self.dataBits != '': return self.dataBits # determine number of bits size = 8*self.bytesCapacityDict[str(self.version) + self.error] # add alphanumeric encoding indicator self.dataBits += '0010' # alphanumeric mode charCount = bin(len(self.dataStr))[2:] # add chracter count indicator self.dataBits += '0' * (9-len(charCount)) + charCount # char count indicator # convet characters to binary and add to string for i in range(0, len(self.dataStr)-1, 2): first = int(self.alphanumEncode[self.dataStr[i]]) second = int(self.alphanumEncode[self.dataStr[i+1]]) score = bin(45 * first + second)[2:] score = "0" * (11-len(score)) + score self.dataBits += score if len(self.dataStr) % 2 == 1: first = int(self.alphanumEncode[self.dataStr[len(self.dataStr)-1]]) score = bin(first)[2:] score = "0" * (6-len(score)) + score self.dataBits += score # add terminator self.dataBits += '0' * min(4, size-len(self.dataBits)) # add padding if len(self.dataBits) % 8 != 0: self.dataBits += '0' * (8 - len(self.dataBits) % 8) for i in range((size - len(self.dataBits))//8): if i % 2 == 0: self.dataBits += '0'*(8-len(bin(236)[2:])) + bin(236)[2:] else: self.dataBits += '0'*(8-len(bin(17)[2:])) + bin(17)[2:] return self.dataBits def encode_ec(self): '''QRCode.encode_ec() -> str Calculates error correction bits and returns them''' # if already encoded, don't allow new encoding if self.errorBits != "": return self.errorBits # get message coefficients message = [] for i in range(0, len(self.dataBits), 8): message.append(int(self.dataBits[i:i+8],base=2)) # get generator polynomial generator = self.generatorPolynomials[self.ECcodewords[str(self.version)+self.error][0]] # calculate error correction code words ECcodewords = self.error_correction_coeff(message, generator) # combine to form error correction string for word in ECcodewords: binary = bin(word)[2:] self.errorBits += '0' * (8-len(binary)) + binary if self.version > 1: self.errorBits += '0' * 7 return self.errorBits def convert_to_int(self, coeff): '''QRCode.conver_to_int(int) -> int Convert exponent alpha^coeff to integer newCoeff''' exp_to_int = {-1:0, 0: 1, 1: 2, 2: 4, 3: 8, 4: 16, 5: 32, 6: 64, 7: 128, 8: 29, 9: 58, 10: 116, 11: 232, 12: 205, 13: 135, 14: 19, 15: 38, 16: 76, 17: 152, 18: 45, 19: 90, 20: 180, 21: 117, 22: 234, 23: 201, 24: 143, 25: 3, 26: 6, 27: 12, 28: 24, 29: 48, 30: 96, 31: 192, 32: 157, 33: 39, 34: 78, 35: 156, 36: 37, 37: 74, 38: 148, 39: 53, 40: 106, 41: 212, 42: 181, 43: 119, 44: 238, 45: 193, 46: 159, 47: 35, 48: 70, 49: 140, 50: 5, 51: 10, 52: 20, 53: 40, 54: 80, 55: 160, 56: 93, 57: 186, 58: 105, 59: 210, 60: 185, 61: 111, 62: 222, 63: 161, 64: 95, 65: 190, 66: 97, 67: 194, 68: 153, 69: 47, 70: 94, 71: 188, 72: 101, 73: 202, 74: 137, 75: 15, 76: 30, 77: 60, 78: 120, 79: 240, 80: 253, 81: 231, 82: 211, 83: 187, 84: 107, 85: 214, 86: 177, 87: 127, 88: 254, 89: 225, 90: 223, 91: 163, 92: 91, 93: 182, 94: 113, 95: 226, 96: 217, 97: 175, 98: 67, 99: 134, 100: 17, 101: 34, 102: 68, 103: 136, 104: 13, 105: 26, 106: 52, 107: 104, 108: 208, 109: 189, 110: 103, 111: 206, 112: 129, 113: 31, 114: 62, 115: 124, 116: 248, 117: 237, 118: 199, 119: 147, 120: 59, 121: 118, 122: 236, 123: 197, 124: 151, 125: 51, 126: 102, 127: 204, 128: 133, 129: 23, 130: 46, 131: 92, 132: 184, 133: 109, 134: 218, 135: 169, 136: 79, 137: 158, 138: 33, 139: 66, 140: 132, 141: 21, 142: 42, 143: 84, 144: 168, 145: 77, 146: 154, 147: 41, 148: 82, 149: 164, 150: 85, 151: 170, 152: 73, 153: 146, 154: 57, 155: 114, 156: 228, 157: 213, 158: 183, 159: 115, 160: 230, 161: 209, 162: 191, 163: 99, 164: 198, 165: 145, 166: 63, 167: 126, 168: 252, 169: 229, 170: 215, 171: 179, 172: 123, 173: 246, 174: 241, 175: 255, 176: 227, 177: 219, 178: 171, 179: 75, 180: 150, 181: 49, 182: 98, 183: 196, 184: 149, 185: 55, 186: 110, 187: 220, 188: 165, 189: 87, 190: 174, 191: 65, 192: 130, 193: 25, 194: 50, 195: 100, 196: 200, 197: 141, 198: 7, 199: 14, 200: 28, 201: 56, 202: 112, 203: 224, 204: 221, 205: 167, 206: 83, 207: 166, 208: 81, 209: 162, 210: 89, 211: 178, 212: 121, 213: 242, 214: 249, 215: 239, 216: 195, 217: 155, 218: 43, 219: 86, 220: 172, 221: 69, 222: 138, 223: 9, 224: 18, 225: 36, 226: 72, 227: 144, 228: 61, 229: 122, 230: 244, 231: 245, 232: 247, 233: 243, 234: 251, 235: 235, 236: 203, 237: 139, 238: 11, 239: 22, 240: 44, 241: 88, 242: 176, 243: 125, 244: 250, 245: 233, 246: 207, 247: 131, 248: 27, 249: 54, 250: 108, 251: 216, 252: 173, 253: 71, 254: 142, 255: 1} newCoeff = [] for el in coeff: newCoeff.append(exp_to_int[el]) return newCoeff def convert_to_exp(self, coeff): '''QRCode.convert_to_exp(int) -> int COnvert int coeff to exponent alpha^newCoeff''' int_to_exp = {0: -1, 1: 0, 2: 1, 3: 25, 4: 2, 5: 50, 6: 26, 7: 198, 8: 3, 9: 223, 10: 51, 11: 238, 12: 27, 13: 104, 14: 199, 15: 75, 16: 4, 17: 100, 18: 224, 19: 14, 20: 52, 21: 141, 22: 239, 23: 129, 24: 28, 25: 193, 26: 105, 27: 248, 28: 200, 29: 8, 30: 76, 31: 113, 32: 5, 33: 138, 34: 101, 35: 47, 36: 225, 37: 36, 38: 15, 39: 33, 40: 53, 41: 147, 42: 142, 43: 218, 44: 240, 45: 18, 46: 130, 47: 69, 48: 29, 49: 181, 50: 194, 51: 125, 52: 106, 53: 39, 54: 249, 55: 185, 56: 201, 57: 154, 58: 9, 59: 120, 60: 77, 61: 228, 62: 114, 63: 166, 64: 6, 65: 191, 66: 139, 67: 98, 68: 102, 69: 221, 70: 48, 71: 253, 72: 226, 73: 152, 74: 37, 75: 179, 76: 16, 77: 145, 78: 34, 79: 136, 80: 54, 81: 208, 82: 148, 83: 206, 84: 143, 85: 150, 86: 219, 87: 189, 88: 241, 89: 210, 90: 19, 91: 92, 92: 131, 93: 56, 94: 70, 95: 64, 96: 30, 97: 66, 98: 182, 99: 163, 100: 195, 101: 72, 102: 126, 103: 110, 104: 107, 105: 58, 106: 40, 107: 84, 108: 250, 109: 133, 110: 186, 111: 61, 112: 202, 113: 94, 114: 155, 115: 159, 116: 10, 117: 21, 118: 121, 119: 43, 120: 78, 121: 212, 122: 229, 123: 172, 124: 115, 125: 243, 126: 167, 127: 87, 128: 7, 129: 112, 130: 192, 131: 247, 132: 140, 133: 128, 134: 99, 135: 13, 136: 103, 137: 74, 138: 222, 139: 237, 140: 49, 141: 197, 142: 254, 143: 24, 144: 227, 145: 165, 146: 153, 147: 119, 148: 38, 149: 184, 150: 180, 151: 124, 152: 17, 153: 68, 154: 146, 155: 217, 156: 35, 157: 32, 158: 137, 159: 46, 160: 55, 161: 63, 162: 209, 163: 91, 164: 149, 165: 188, 166: 207, 167: 205, 168: 144, 169: 135, 170: 151, 171: 178, 172: 220, 173: 252, 174: 190, 175: 97, 176: 242, 177: 86, 178: 211, 179: 171, 180: 20, 181: 42, 182: 93, 183: 158, 184: 132, 185: 60, 186: 57, 187: 83, 188: 71, 189: 109, 190: 65, 191: 162, 192: 31, 193: 45, 194: 67, 195: 216, 196: 183, 197: 123, 198: 164, 199: 118, 200: 196, 201: 23, 202: 73, 203: 236, 204: 127, 205: 12, 206: 111, 207: 246, 208: 108, 209: 161, 210: 59, 211: 82, 212: 41, 213: 157, 214: 85, 215: 170, 216: 251, 217: 96, 218: 134, 219: 177, 220: 187, 221: 204, 222: 62, 223: 90, 224: 203, 225: 89, 226: 95, 227: 176, 228: 156, 229: 169, 230: 160, 231: 81, 232: 11, 233: 245, 234: 22, 235: 235, 236: 122, 237: 117, 238: 44, 239: 215, 240: 79, 241: 174, 242: 213, 243: 233, 244: 230, 245: 231, 246: 173, 247: 232, 248: 116, 249: 214, 250: 244, 251: 234, 252: 168, 253: 80, 254: 88, 255: 175} newCoeff = [] for el in coeff: newCoeff.append(int_to_exp[el]) return newCoeff def error_correction_coeff(self, messageIntCoeff, generatorAlphaCoeff): '''QRCOde.error_correction_coeff(list, list) -> list Returns a list of error correction coefficients as integers''' numSteps = len(messageIntCoeff) # pad message with 0's # pad generator polynomial with -1's message = [] message.extend(messageIntCoeff) message.extend([0] * (len(generatorAlphaCoeff)-1)) generator = [] generator.extend(generatorAlphaCoeff) generator.extend([-1] * (len(messageIntCoeff)-1)) for steps in range(numSteps): # find first term of message polynomial firstCoeff = self.convert_to_exp([message[0]])[0] # multiply generator polynomial by first term result = [] for i in range(len(generator)): if generator[i] != -1: result.append((generator[i] + firstCoeff) % 255) else: result.append(-1) # convert resulting polynomial to int coeffs result = self.convert_to_int(result) # XOR resulting polynomial with message for i in range(len(message)): message[i] = message[i] ^ result[i] # set message polynomial to result message.pop(0) generator.pop(-1) return message def interleave_blocks(self): '''QRCode.interleave_blocks() -> str Combine data and error correction bits and return result''' self.bits = self.dataBits + self.errorBits return self.bits def add_finders(self): '''QRCode.add_finders() -> list Add finders to matrix and return it''' finderPattern = [[1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1]] # add finder patterns to all three locations for i in range(7): for j in range(7): # add patterns finderModule = finderPattern[i][j] self.matrix[i][j] = finderModule self.matrix[self.size-7+i][j] = finderModule self.matrix[i][self.size-7+j] = finderModule # reserve areas in matrix with finders self.reserved.append((i, j)) self.reserved.append((self.size-7+i, j)) self.reserved.append((i, self.size-7+j)) return self.matrix def add_reserved_areas(self): '''QRCode.add_reserved_areas() -> None reserve seperator and format location''' # vertical seperators for i in range(8): for j in [(0, 7), (0, self.size - 8), (self.size - 8, 7)]: (r, c) = j self.reserved.append((r+i, c)) # horizontal seperators for i in range(8): for j in [(7, 0), (self.size - 8, 0), (7, self.size - 8)]: (r, c) = j self.reserved.append((r, c+i)) # format info area for i in range(9): if (i, 8) not in self.reserved: self.reserved.append((i, 8)) if (8, i) not in self.reserved: self.reserved.append((8, i)) if (8, self.size-8+i) not in self.reserved: self.reserved.append((8, self.size-8+i)) if (self.size-8+i, 8) not in self.reserved: self.reserved.append((self.size-8+i, 8)) def add_alignment_patterns(self): '''QRCode.add_alignment_patterns() -> list Add alignment pattern to matrix and return it''' alignPattern = [[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]] # don't add alignment patterns to version 1 if self.version == 1: return self.matrix # add alignment pattern otherwise for i in range(5): for j in range(5): row = 10 + self.version * 4 - 2 self.matrix[row + i][row + j] = alignPattern[i][j] self.reserved.append((row + i, row + j)) return self.matrix def add_timing(self): '''QRCode.add_timing() -> list Add timing patterns to matrix and return it''' # define and add timing patterns for i in range(8, self.size-8): # add a 1 for dark squares if i % 2 == 0: self.matrix[6][i] = 1 self.matrix[i][6] = 1 # reserve all modules in timing pattern self.reserved.append((6, i)) self.reserved.append((i, 6)) return self.matrix def add_darkmodule(self): '''QRCode.add_darkmodule() -> list Add dark module to matrix and return it''' self.matrix[self.size-8][8] = 1 self.reserved.append((self.size-8, 8)) return self.matrix def place_data_bits(self): '''QRCode.place_data_bits() -> list Add data and error correction bits to matrix and return it''' msgIndex = 0 for r in range(self.size-1, 0, -2): # up a column if r % 4 == 0: if r <= 6: r -= 1 for c in range(self.size-1,-1, -1): # place bits if (c, r) not in self.reserved: # add a bit self.matrix[c][r] = int(self.bits[msgIndex]) msgIndex += 1 if (c, r-1) not in self.reserved: # add a bit self.matrix[c][r-1] = int(self.bits[msgIndex]) msgIndex += 1 # down a column elif r % 4 == 2: if r <= 6: r -= 1 for c in range(self.size): # place bits if (c, r) not in self.reserved: # add a bit self.matrix[c][r] = int(self.bits[msgIndex]) msgIndex += 1 if (c, r-1) not in self.reserved: # add a bit self.matrix[c][r-1] = int(self.bits[msgIndex]) msgIndex += 1 return self.matrix def apply_mask(self, mask): '''QRCode.apply_mask(int) -> list Applies the given mask and returns the updated matrix''' # loop through grid for r in range(self.size): for c in range(self.size): # if it is not a reserved cell, ... if (r,c) not in self.reserved: # apply correct mask if mask == 0 and (r + c) % 2 == 0: self.matrix[r][c] = (self.matrix[r][c] + 1) % 2 elif mask == 1 and r % 2 == 0: self.matrix[r][c] = (self.matrix[r][c] + 1) % 2 elif mask == 2 and c % 3 == 0: self.matrix[r][c] = (self.matrix[r][c] + 1) % 2 elif mask == 3 and (r + c) % 3 == 0: self.matrix[r][c] = (self.matrix[r][c] + 1) % 2 elif mask == 4 and (r//2 + c//3) % 2 == 0: self.matrix[r][c] = (self.matrix[r][c] + 1) % 2 elif mask == 5 and (r*c) % 2 + (r * c) % 3 == 0: self.matrix[r][c] = (self.matrix[r][c] + 1) % 2 elif mask == 6 and (r*c) %2 + ((r*c) % 3) % 2 == 0: self.matrix[r][c] = (self.matrix[r][c] + 1) % 2 elif mask == 7 and (r+c) % 2 + ((r*c) % 3 ) % 3 == 0: self.matrix[r][c] = (self.matrix[r][c] + 1) % 2 return self.matrix def add_format_string(self, mask): '''QRCode.add_format_string(int) -> list Adds format string to matrix and returns it''' # get format string formatString = self.formatStrings['L' + str(mask)] # add format string to grid for i in range(7): self.matrix[8][self.size-8+i] = int(formatString[i+7]) self.matrix[self.size-1-i][8] = int(formatString[i]) for i in range(6): self.matrix[8][i] = int(formatString[i]) self.matrix[i][8] = int(formatString[14-i]) self.matrix[8][7] = int(formatString[6]) self.matrix[8][8] = int(formatString[7]) self.matrix[7][8] = int(formatString[8]) return self.matrix def valid_str(string): '''valid_str(str) -> bool returns true if valid str, false otherwise''' if len(string) == 0: return False if len(string) > 150: print("Maximum lenght exceeded!") return False validChars = "1234567890QWERTYUIOPASDFGHJKLZXCVBNM$%*+-./: " for ch in string: if ch not in validChars: print(ch + " is an invalid character!") return False return True userInput = '' while not valid_str(userInput): print("Valid charcaters: 0-9, A-Z (captial only), $, %, *, +, -, ., /, and :") print("Maximum Length: 150 characters.") userInput = input("Please enter a string to encode using only valid characters: ") qr = QRCode(2, userInput) print("Your Asymptote code is below. Please go to aops.com/texer to render the asymptote code.") print() print(qr.asy())
To actually generate the QR codes, I used this tutorial. My QR code generator is just the tip of the iceberg! The code is a bit long since I ended up using a lot of dictionaries to store tables instead of actually computing the numbers in those tables. In principle, these are the steps you need to take when generating a QR code:
- Encode the given data as binary.
- Find the error correction code words and code those in binary.
- Place the data and error correction code words in the matrix.
- Add required blocks such as the finders (big squares at the corners).
- Add the format data to tell what version and mask is used.
- Apply a data ask to make the code easier to process.
QR codes are pretty handy since it makes it really easy to share data quickly on the fly! You can also set your profile picture to a QR code of something you want to advertise. That's free advertising space on every post you make!

Fun fact: Python already has a module to generate QR codes called pyqrcode. You can download it using the command pip3 install pyqrcode (no guarantees, but that's what worked on my Raspberry Pi).
Here are a few example QR codes generated with my code.
Figure 1: Version 1 QR Code (up to 25 alphanumeric characters) containing the text "HELLO WORLD"
![[asy]
int[][] qrdata = {{1,1,1,1,1,1,1,0,1,1,0,0,1,0,1,1,1,1,1,1,1},
{1,0,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1},
{1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,1,0,1,0,1,0,0,1,0,0,1,1,1,0,0},
{1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,1,1,1,1,0},
{0,1,1,0,1,0,1,1,1,1,1,0,1,1,0,1,0,0,0,1,1},
{1,1,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1},
{0,1,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0},
{0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,0},
{1,1,1,1,1,1,1,0,0,1,0,0,0,1,1,1,1,0,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,1,1,0,0,1,0,1,0,0,1},
{1,0,1,1,1,0,1,0,0,1,0,1,0,0,1,1,0,0,1,1,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,1,0,0,0,0,0,1,0},
{1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,1,0,0,0,0},
{1,0,0,0,0,0,1,0,1,0,0,1,1,0,1,1,1,0,0,0,0},
{1,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,1,1,1,1,0},
};
int side = 21;filldraw((-4, 4)--(-4,-(side+4))--(side+4, -(side+4))--(side+4, 4)--cycle, white);
for (int i = 0; i < side; ++i) {
for (int j = 0; j < side; ++j) {
if (qrdata[j][i] == 1) {
fill((i, -j)--(i+1,-j)--(i+1,-j-1)--(i,-j-1)--cycle, black);
}
}
}
[/asy]](http://latex.artofproblemsolving.com/3/e/3/3e36f39f0d57cf2a2a00ccec51f9cdfc177587b2.png)
Figure 2: Version 2 QR Code (up to 47 alphanumeric characters) containing the url "HTTPS://BIT.LY/SIRCALCSALOTSBLOG"
![[asy]
int[][] qrdata = {{1,1,1,1,1,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1},
{1,0,0,0,0,0,1,0,0,1,1,1,1,0,1,1,1,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,0,1,1,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,1,0,1,1,0,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,1},
{1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,1,0,1,0,1,1,1,0,0,0,1,1,0,0,1,1,1,0,0},
{1,0,1,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,1,1,0,0,0,0,0},
{1,0,1,1,0,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,0,1,0,0,0},
{1,1,1,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,1,0,1,1,1,0,1},
{0,0,0,1,1,1,1,0,0,1,1,0,1,0,0,0,0,1,0,0,1,1,0,0,0},
{0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,0,0,1,1,1,0,1,1},
{0,1,0,1,0,1,1,0,1,1,1,1,0,0,0,1,1,1,0,1,0,0,0,0,1},
{1,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,1,1,1,0,1,1,0,1,1},
{0,0,0,0,1,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,1,1},
{1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,1,1,0,1,0,1,0,0,0,1},
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,0,0,0,1,1,1,1,0},
{1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,1,1,1,1,1,1,1,0,0},
{1,0,1,1,1,0,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1},
{1,0,1,1,1,0,1,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,1,1,0},
{1,0,0,0,0,0,1,0,1,0,1,1,1,1,0,1,1,1,0,0,0,0,1,0,1},
{1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,0,1,0,0,1,0,0,1},
};
int side = 25;filldraw((-4, 4)--(-4,-(side+4))--(side+4, -(side+4))--(side+4, 4)--cycle, white);
for (int i = 0; i < side; ++i) {
for (int j = 0; j < side; ++j) {
if (qrdata[j][i] == 1) {
fill((i, -j)--(i+1,-j)--(i+1,-j-1)--(i,-j-1)--cycle, black);
}
}
}
[/asy]](http://latex.artofproblemsolving.com/5/9/0/5906afe20b80d35eda060d74e18ff83f88a505f5.png)
Figure 3: Version 5 QR Code (up to 154 alphanumeric characters) containing the text "IT IS A PERIOD OF CIVIL WAR. REBEL SPACESHIPS STRIKING FROM A HIDDEN BASE HAVE WON THEIR FIRST VICTORY AGAINST THE EVIL GALACTIC EMPIRE."
![[asy]
int[][] qrdata = {{1,1,1,1,1,1,1,0,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,1,1,1},
{1,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,1,1,0,1,1,0,1,0,1,0,0,0,0,0,1},
{1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,1,1,1,1,0,1,0,1,0,0,0,1,0,0,1,1,1,0,0},
{0,1,1,0,1,1,0,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,1,0,1,1,1,0,1,0,0,1,0},
{1,1,1,1,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,0,0,0,0,1,0},
{0,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1},
{1,0,0,1,0,0,1,1,1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,1,0,1,0,1,1,0},
{1,1,0,1,0,1,0,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,0,1,0,1,1,1,1,0,1,0,0,0,0,1,0},
{1,1,1,0,1,1,1,0,1,0,0,1,0,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,0,1,0,0,1,0,0,0},
{1,1,0,1,0,1,0,1,0,0,1,1,0,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1},
{0,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,0,1,1,1,1,1,0,0,1,0,0,0},
{0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,1,1,1,1,0,0,1,0,0,0,1,0,1,0,1,1,1,1,0,0,0,0},
{1,0,0,1,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,0,0,1,1,1,1,1},
{0,0,1,1,1,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0,1,0,0,1,0,0,0,0,0},
{0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,1,0,1,1,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1},
{0,1,0,0,1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,0,0,1},
{0,1,0,0,0,1,1,1,1,1,1,0,0,0,1,0,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,0,0,1},
{1,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,1,0,0,1,0,0,1,0,0},
{0,1,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,1,0},
{0,0,1,0,0,1,0,0,1,1,0,1,0,0,0,1,1,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,1,1,0,0,1},
{0,1,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,0,0,1,0,1,0},
{1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,1,1,0,1,1,0,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,1},
{0,0,1,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0},
{0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,1,1,1,0,0,0,1,1,1,1,1},
{1,1,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,1,0,1,1,1,1,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,1,1,1,0,1,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0},
{1,0,1,1,1,0,1,0,0,1,1,1,1,1,0,1,0,1,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,0},
{1,0,1,1,1,0,1,0,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,1,1,0,1,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,1,1,0,0,0,0},
{1,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,0,0,0,1,1,1,0,1,1,0,1},
{1,1,1,1,1,1,1,0,1,1,0,0,1,0,1,1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1},
};
int side = 37;filldraw((-4, 4)--(-4,-(side+4))--(side+4, -(side+4))--(side+4, 4)--cycle, white);
for (int i = 0; i < side; ++i) {
for (int j = 0; j < side; ++j) {
if (qrdata[j][i] == 1) {
fill((i, -j)--(i+1,-j)--(i+1,-j-1)--(i,-j-1)--cycle, black);
}
}
}
[/asy]](http://latex.artofproblemsolving.com/2/4/b/24bbabfc6866c170ca0ac48e7f5f5a3bdc668ccf.png)
Figure 4: Version 5 QR Code (up to 154 alphanumeric characters) containing the text "ONE LAST EXAMPLE"
![[asy]
int[][] qrdata = {{1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1},
{1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,0,1,0,0,1,1,1,1,1,0,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,0,1,0,1,0,1,1,1,0,1},
{1,0,1,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,0,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,1,1,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1},
{1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,1,0,1,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,1,0,0,1,1,1,0,0},
{0,1,1,1,1,1,0,0,1,0,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,1,1,1,0,1,1},
{0,0,0,0,1,0,1,1,0,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,1,0,1},
{1,0,1,0,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,1,0,0,1,1,1,1,1,0,1,0,0,1,0,1,1,0},
{0,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,0,1,0,1,0,0,1,0,1,0},
{0,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1},
{1,0,0,0,1,0,1,0,0,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,0,1,0,0,1,1,1,0,1,1,0,0},
{1,0,0,0,1,1,0,1,1,1,1,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,1,1,1,0,0},
{0,1,0,0,0,0,1,0,1,1,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,0,1,1,1,0,1,0,0},
{0,1,0,0,0,1,0,1,1,1,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,0,1,0,0,0,0},
{0,1,0,0,0,1,1,0,1,0,1,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1},
{0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,1,1,1,1,1,0,0,1,0,1,0,0,1,1,0,0,1,1,1,0,0,0},
{0,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,1,0,0,0,1,0},
{1,0,0,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,1,0,1,0,1,0,0},
{0,0,0,1,0,0,1,0,0,0,1,1,1,1,0,0,1,0,1,0,0,1,1,1,1,1,0,0,1,0,1,1,1,1,1,0,0},
{1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,0,1,0,1,1,1,0,1},
{0,1,1,0,0,0,1,1,1,0,0,0,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,1,0,1,0,1,0,0,0},
{0,1,1,1,0,1,0,0,1,1,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,1},
{0,1,0,0,1,0,1,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,1,1,0,1,1,0,0,1,0,1,0,0,1,1,1,1,1,0,0,1,0,1,1,1,1,1,0,1,1,1},
{0,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,1,0,1,1,1,1,1,1,1,0,0,1,0},
{0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,1,1,1,0,1,0,0,0,0,1,1,1,0,0,0,1,1,0,1,1},
{1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1,0,0,1,0,1,0,0,1,1,1,1,0,1,0,1,0,1,0,1},
{1,0,0,0,0,0,1,0,0,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0},
{1,0,1,1,1,0,1,0,0,0,1,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,1,1,1,1,1,0,1,1,1},
{1,0,1,1,1,0,1,0,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0},
{1,0,0,0,0,0,1,0,1,0,1,1,1,1,1,1,0,0,1,0,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,0,1},
{1,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,0,1,0,0,1,0,0,1,0,1},
};
int side = 37;filldraw((-4, 4)--(-4,-(side+4))--(side+4, -(side+4))--(side+4, 4)--cycle, white);
for (int i = 0; i < side; ++i) {
for (int j = 0; j < side; ++j) {
if (qrdata[j][i] == 1) {
fill((i, -j)--(i+1,-j)--(i+1,-j-1)--(i,-j-1)--cycle, black);
}
}
}
[/asy]](http://latex.artofproblemsolving.com/d/f/d/dfdc14774062faaf4fb1c08165febffa5d504c4e.png)
"Drawing" the AoPS Logos with Python Turtle
by SirCalcsALot, Jul 18, 2020, 5:09 AM
Hi! 
I saw a competition to draw the best AoPS Online Logo with turtle on a private forum. CaptainFlint suggested that instead of drawing the logo, he could take it from the AoPS website. I decided to steal his idea and program this concept myself. I'm not submitting this as part of the competition for two reasons: collaboration was not allowed and all the program does is steal the logo from the website and display it with turtle.
Here is the code! The idea behind the code is as follows:
I've attached the resulting turtle drawing to this post. Enjoy!

I saw a competition to draw the best AoPS Online Logo with turtle on a private forum. CaptainFlint suggested that instead of drawing the logo, he could take it from the AoPS website. I decided to steal his idea and program this concept myself. I'm not submitting this as part of the competition for two reasons: collaboration was not allowed and all the program does is steal the logo from the website and display it with turtle.
Here is the code!
import os import turtle import requests from svglib.svglib import svg2rlg from reportlab.graphics import renderPM def open_svg_from_web(link, filename): """open_svg_from_web(str, str) -> None link: str containing link to svg file filename: name to save svg file as """ with open(filename, 'wb') as f: f.write(requests.get(link).content) f.close() def convert_svg_to_gif(svg, gif): """convert_svg_to_gif(str, str) -> None svg: str with name of svg file gif: str with name of gif file """ drawing = svg2rlg(svg) renderPM.drawToFile(drawing, gif, fmt="GIF") def image_to_turtle(wn, t, imagename, x, y): """image_to_turtle(turtle.Screen, turtle.Turtle, str, int, int) -> None wn: turtle screen t: turtle used to draw imagename: name of image to set turtle's shape to x: x-coord of turtle's position y: y-coord of turtle's position """ wn.register_shape(imagename) t.penup() t.forward(x) t.left(90) t.forward(y) t.shape(imagename) # lists of web links, svg filenames, and gif file names web_links = ['https://artofproblemsolving.com/assets/images/logos/aops-main.svg', \ 'https://artofproblemsolving.com/assets/images/logos/aops-online.svg', \ 'https://beastacademy.com/assets/images/logos/aops-ba.svg', \ 'https://aopsacademy.org/assets/images/logos/aops-academy-national.svg'] svg_files = ["aops.svg", "online.svg", "ba.svg", "academy.svg"] gif_files = ["aops.gif", "online.gif", "ba.gif", "academy.gif"] wn = turtle.Screen() # set up turtle window turtles = [turtle.Turtle() for t in range(4)] # set up turtle for each logo positions = [0, -68, -89, -35] # positions to line up logos # load each file from the web and display on screen for action in range(4): open_svg_from_web(web_links[action], svg_files[action]) # get logo from web convert_svg_to_gif(svg_files[action], gif_files[action]) # convert to gif image_to_turtle(wn, turtles[action], gif_files[action], positions[action], 75 * (2-action)) # draw it on screen wn.mainloop() # wait for user to exit befor removing files # remove all saved files used for removal in range(4): os.remove(svg_files[removal]) os.remove(gif_files[removal])
- Navigate to the url of the image and download it as an .svg file.
- Convert this .svg file to a .gif file since turtle can only display gif's.
- Move the turtle to the correct location and change it's shape to the gif file.
- Finally, repeat these steps for the other three logos
I've attached the resulting turtle drawing to this post. Enjoy!

RSA Encryption Program with Assembly!!
by SirCalcsALot, Jul 16, 2020, 5:54 PM
Hello everyone!
I thought I would share the RSA encryption program I've mentioned in a previous post. It is written in ARM assembly and can process RSA encryption of up 400 bits, with a max 31 bit key length. Because of the short key length, it is very unsecure and can be easily hacked with something like Wolfram Alpha. I designed this code as a final project for my engineering class on microprocessors and assembly language.
Here are a few things about the code:
I've attached the report I wrote up to submit for my project (I had to split it into pieces because of the max file limit on AoPS). The report talks a bit more about the algorithms used as well as shows some test cases. If you look carefully, you will notice that I cited Wikipedia in this report since that is were I got one of my algorithms!
Since the code is over 100 lines, I've included it in a hide tag. Feel free to ask me any questions about the code or assembly in general. Assembly really takes you down to the lower levels of programming and you need to think about things like
Click to see code
I'll try to answer any question you all might have on assembly, so feel free to ask if you want to know about something. Enjoy the code!
(Since I could only attach three files, the first appendix with the code is here and the second appendix with a longer test is here. Let me know if you have issues with these links.)
I thought I would share the RSA encryption program I've mentioned in a previous post. It is written in ARM assembly and can process RSA encryption of up 400 bits, with a max 31 bit key length. Because of the short key length, it is very unsecure and can be easily hacked with something like Wolfram Alpha. I designed this code as a final project for my engineering class on microprocessors and assembly language.
Here are a few things about the code:
- Assembly uses something called registers to manipulate data. We have 12 registers we can use that act as our twelve possible variables. Each register can hold a maximum of 32 bits, so in some places I needed two registers to work with 64 bit numbers.
- Since we only have 12 variables, sometimes we have to push data into the stack to save it for later when we need to access it again.
- The version of ARM assembly I was using doesn't have a moduluo operator, so I had to implement my own.
- To perform the operation
, I implemented a semi-fast algorithm. Initially I used a recursive approach, but I had to switch to an iterative approach due to memory constraints.
I've attached the report I wrote up to submit for my project (I had to split it into pieces because of the max file limit on AoPS). The report talks a bit more about the algorithms used as well as shows some test cases. If you look carefully, you will notice that I cited Wikipedia in this report since that is were I got one of my algorithms!

Since the code is over 100 lines, I've included it in a hide tag. Feel free to ask me any questions about the code or assembly in general. Assembly really takes you down to the lower levels of programming and you need to think about things like
- How functions work and how do you return something from a function.
- How lists work (we actually need an address as well as the number of items in the list).
- How variables work. Some variables point to actual values in memory. Others point to the address in memory that the data is at.
Click to see code
AREA RESET, DATA, READONLY EXPORT __Vectors __Vectors DCD 0x20001000 ; stack pointer value when stack is empty DCD Reset_Handler ; reset vector ALIGN encrypted EQU 0x20000000 ; location of encrypted array decrypted EQU 0x20000500 ; location of decrypted array AREA MYDATA, DATA, READONLY m DCB "ECE 118L", 0, 0 ; message with padding mSize DCD 10 ; message size (bytes) n DCD 1009199683 ; modulus e DCD 17 ; public exponent d DCD 415526641 ; private exponent ALIGN AREA MYCODE, CODE, READONLY ENTRY EXPORT Reset_Handler Reset_Handler _main PROC ; start of main LDR R4, =m ; address of message array LDR R2, =e ; public exponent address LDR R2, [R2] ; public exponent value LDR R3, =n ; modulus address LDR R3, [R3] ; modulus value LDR R6, =encrypted ; address of encrypted array LDR R7, =decrypted ; address of decrypted array LDR R8, =mSize ; address containing message size LDR R8, [R8] ; value of message size (bytes) LSR R8, #1 ; value of message size (half words) MOV R5, #0 ; set encryption loop counter to 0 LoopE LDRH R1, [R4, R5, LSL #1] ; get two characters to encrypt PUSH {R1, R2, R3} ; save values of R1, R2, R3 BL exp_mod ; compute m^e mod n (encryption) POP {R1, R2, R3} ; restore values of R1, R2, R3 STR R0, [R6, R5, LSL #2] ; store encrypted data as a word ADD R5, #1 ; update loop counter CMP R5, R8 ; check if loop counter < mSize BLT LoopE ; continue LoopE if true MOV R5, #0 ; set decryption loop counter to 0 LDR R2, =d ; private exponent address LDR R2, [R2] ; private exponent value LoopD LDR R1, [R6, R5, LSL #2] ; get encrypted word PUSH {R1, R2, R3} ; save values of R1, R2, R3 BL exp_mod ; compute m^d mod n (decryption) POP {R1, R2, R3} ; restore values of R1, R2, R3 STRH R0, [R7, R5, LSL #1] ; store decrypted data as half word ADD R5, #1 ; update loop counter CMP R5, R8 ; check if loop counter < mSize BLT LoopD ; continue LoopD if true Done B Done ; dead loop ENDP ; end of main ; subroutine to compute a^b mod c ; inputs: R1 -> a, R2 -> b, R3 -> c ; output: R0 = R1^R2 mod R3 exp_mod PROC ; begin process PUSH {R4, R5, LR} ; save R4, R5, and LR CMP R2, #0 ; check if exponent is 0 BNE elseEM ; if not, continue MOV R0, #1 ; if true, return 1 POP {R4, R5, LR} ; restore R4, R5, and LR BX lr ; branch back to caller elseEM MOV R4, #1 ; value of y LoopEM ADD R5, R4, #0 ; move R4 into R5 AND R5, R2, #1 ; get last bit of R5 CMP R5, #0 ; check if R4 is even BNE nxtEM ; if so, continue PUSH {R1, R2} ; save R1 and R2 UMULL R1, R2, R1, R1 ; compute (R1)^2 and store in R2:R1 BL Modulo ; find (R2:R1) mod R3 POP {R1, R2} ; restore R1 and R2 ADD R1, R0, #0 ; move R0 into R1 LSR R2, R2, #1 ; R2 = R2/2 CMP R2, #1 ; if R2 is 1 BLS endEM ; end loop BL LoopEM ; otherwise, continue loop nxtEM PUSH {R1, R2} ; save R1 and R2 UMULL R1, R2, R1, R4 ; compute (x * y) and store in R2:R1 BL Modulo ; find (R2:R1) mod R3 POP {R1, R2} ; restore R1 and R2 ADD R4, R0, #0 ; y = (x * y) mod R3 PUSH {R1, R2} ; save R1 and R2 UMULL R1, R2, R1, R1 ; compute (R1)^2 and store in R2:R1 BL Modulo ; find (R2:R1) mod R3 POP {R1, R2} ; restore R1 and R2 ADD R1, R0, #0 ; set x = x^2 mod R3 SUB R2, R2, #1 ; set loop counter to n-1 LSR R2, R2, #1 ; set loop counter to (n-1)/2 CMP R2, #1 ; if R2 is greater than 1 BHI LoopEM ; continue LoopEM endEM PUSH {R1, R2} ; save R1 and R2 UMULL R1, R2, R1, R4 ; compute R1 * R4 BL Modulo ; compute (R2:R1) mod R3 POP {R1, R2, R4, R5, LR} ; restore R1, R2, R4, R5, and LR BX lr ; branch back to caller ENDP ; end process ; subroutine to take R2:R1 mod R3 ; inputs: R2 -> top half of number ; R1 -> bottom half of number ; R3 -> modulus ; output: R0 -> the remainder Modulo PROC ; begin process PUSH {R4, R5, LR} ; save R4, R5, LR MOV R0, #0 ; intitialze remainder as 0 MOV R4, #63 ; loop counter LoopM LSL R0, #1 ; shift the remainder 1 bit to the left PUSH {R0, R1, R2, R3} ; save the number and divisor ADD R3, R4, #0 ; move R4 into R3 (nth bit) BL get_bit ; find Nth bit and store in R0 ADD R5, R0, #0 ; move Nth bit into R5 POP {R0, R1, R2, R3} ; restore the number and divisor ADD R0, R0, R5 ; add Nth bit to remainder CMP R0, R3 ; if remainder greater than divisor SUBHS R0, R0, R3 ; subtract remainder SUBS R4, R4, #1 ; subtract 1 from loop counter BGE LoopM ; if loop counter > 0> continue loop POP {R4, R5, LR} ; save R4, R5, LR BX lr ; branch back to caller ENDP ; end of process ; subroutine to find Nth bit of R2:R1 ; inputs: R2 -> top half of number ; R1 -> bottom half of number ; R3 -> value of N ; output: R0 -> get_bit PROC ; start process PUSH {R4, LR} ; save R4, LR CMP R3, #32 ; check if shift is >= 32 bits LSRLO R1, R3 ; if not, shift the lower register by R3 ANDLO R0, R1, #1 ; and return last bit after shift SUBHS R4, R3, #32 ; if so, subtract 32 from R3 LSRHS R2, R4 ; and shift the upper half by R4 ANDHS R0, R2, #1 ; return last bit after shift POP {R4, LR} ; restore R4, LR BX LR ; branch back to caller ENDP ; end of process END ; end of program
I'll try to answer any question you all might have on assembly, so feel free to ask if you want to know about something. Enjoy the code!

(Since I could only attach three files, the first appendix with the code is here and the second appendix with a longer test is here. Let me know if you have issues with these links.)
Attachments:
This post has been edited 3 times. Last edited by SirCalcsALot, Jul 16, 2020, 6:25 PM
So apparently there is a lot of math research on "default avatars"
by SirCalcsALot, Jul 15, 2020, 2:07 AM
Hey everyone!
This is just a quick update but I was looking into default avatars in a little more detail. It turns out their official name is "plane partitions" and I recommend taking a look at the Wikipeida page on plane partitions. I also found out that there has been research done on an algorithm to sample random plane partitions.
You might also be interested in Lozenge tiling which is a view of plane partitions in a two dimensional view! I'll probably post more about this after my summer engineering class ends and I have more time on my hands.
Let me know if you have any questions!
This is just a quick update but I was looking into default avatars in a little more detail. It turns out their official name is "plane partitions" and I recommend taking a look at the Wikipeida page on plane partitions. I also found out that there has been research done on an algorithm to sample random plane partitions.
You might also be interested in Lozenge tiling which is a view of plane partitions in a two dimensional view! I'll probably post more about this after my summer engineering class ends and I have more time on my hands.
Let me know if you have any questions!
This is a place for me to put interesting programs and problems (maybe some electrical engineering too!). To see Asymptote codes, use the Asymptote tag.
Archives















Shouts
Submit
113 shouts
Contributors
Tags
About Owner
- Posts: 4021
- Joined: Jun 28, 2014
Blog Stats
- Blog created: Feb 13, 2015
- Total entries: 43
- Total visits: 13027
- Total comments: 238
Search Blog