Quarrying with ComputerCraft Turtles

I just recently began playing with ComputerCraft, which is a very cool Minecraft mod that adds programmable computers.   There are also turtles, which are basically computers that can carry out tasks like mining, digging, attacking, etc.  Turtles are fully programmable using Lua and various APIs.  You can do lots of amazing things with turtles.

This is not something amazing, but just a simple modification I made to the turtle's excavate program that allows you to dig stepped quarries giving easier retrieval of the ores around the edges:

9x9 excavate:

excavate14x14x3 quarry:quarry

 Source. You can copy this script directly to your turtle using the turtle's pastebin program.

To dig a quarry, you specify the diameter and the number of blocks to dig down at each diameter, .

It's a fun exercise to work out some of the properties of the resulting quarries.  Given a and , you can dig a quarry that is blocks deep, where if is even and if is odd.  The total height of the quarry is related to the number of constant-diameter levels, by .

Given a and , the total number of blocks you mine in a quarry, , is found by simply adding up all the blocks at a given level and then adding all the levels.  Noting that decreases by two blocks each time you make the quarry square smaller,

where is related to .   Writing this in summation form,

where .  Now, the summation bit is straightforward to see, but the upper limit took some playing around in Mathematica for me to work it out.  This seems to work pretty well, but if anyone can derive this limit (or a better one) more "rigorously", please let me know!

The real goofy vs. regular: A look at skateboarders in the SPoT database

In board sports, riders are "goofy" stance if they lead with their right foot and "regular" stance if they lead with their left. These terms seem to imply that one way is more "correct" or common than the other. I'm goofy, so I'd like to know just how goofy it is to be goofy. It turns out, a little bit goofy.

I checked out the Skatepark of Tampa (SPoT) skateboarder database, which has been maintained for 12 years and is probably the most extensive and detailed online.  The database consists of professional and amateur skateboarders who've been to SPoT for some reason or another.  Given that SPoT has been host to two of the largest annual contests in skateboarding since the mid 90's (the Tampa Pro and the Tampa Am), you can bet that the best have been through the doors. Note that in skateboarding, the term amateur (or am) doesn't necessarily imply that the person is less skilled than a professional - it only implies that the person doesn't have their name on a product yet.

SPoT Database Statistics

Of the 6,047 profiles examined, 12.6% are pro.   4,030 of these profiles had stance data, of which only 44% are goofy.  I personally find this a bit surprising, as I assumed it would be closer to 50%.  To put it mathily, a chi-square test indicated that the difference from 50% is statistically significant,   (where is Cramer's ).

Age
Average 22.79
Median 23

Many of the database entries also included age, which is summarized in the table.  Now, this doesn't necessarily mean that the average age of a competing skateboarder is 23 (I think that may be a tad high). To speculate a bit, I'd guess that the database, which has been maintained for 12 years, adds skaters regularly without deleting older ones.  Assuming that most of the ages are updated over time, the database will accumulate ageing skateboarders who aren't actually active anymore.  For more information about skateboarder age, see this Nerdsday Thursday post.

Also, word clouds are really pretty to look at so, why not, here are the most common first and last names in the database:

SPoT DB Common First Names

SPoT_last_namesNothing surprising here, but it does confirm my previous suspicion about the importance of people named "Mike" in the skate industry.  (Or maybe it's just a common name? Who knows, it's a mystery that will never be solved.)

So there we have it, the archetype skateboarder from the SPoT database is Chris Smith, regular, am, 23.  A very interesting follow up would be to see if there is any link between skateboarding stance, footedness in other sports, and handedness.

If statistics gets you pumped up to go skate, you can leave now.  For the other all of you, here's my favorite winning run from the 2011 Tampa Pro, featuring the very goofy Dennis Busenitz:

Minecraft Calculus: River Crossing Escape

This is a classic introductory calculus problem, with a Minecraft theme.  This particular variation is inspired by example 4 in section 4.5 of Stewart's calculus.

I'll set the scene:  You're weaponless.  You have half a heart and you're being chased by a skeleton archer.  There's a river between you and your cabin.  You need to get to your cabin as quickly as possible!

In more "mathy" terms, you want to get from to .  There are three main ways you can do this:

  1. to directly, diagonally across the river
  2. to and then to
  3. At slight angle from to and then to

We know that swimming is slower than running, so option 1 isn't the best.  Option 2 involves the smallest time in the water, but also the longest distance traveled.

Option 3 is somewhere in between - you spend a bit more time in the water, but the total distance is decreased.  The travel time in this case depends on where exactly point is.  To find the optimal path, we must find the position of which minimizes the travel time.  This sounds like calculus!

Let be the distance between points and .  In math terms, .

We first need an expression for the total time traveled in terms of .  The basic equation for time traveled at constant speed is

.

The first part of the trip is in the water where we travel from to .  We can use Pythagorean's theorem to get this distance as .  Assuming that we can travel at a speed of in the water, the time for this part is

.

The land part of the trip involves traveling what's left over of after having already traveled , so .  Traveling at on land, the time for this part of the trip is

.

The total trip time, , is just the sum of these two.

     (1)

To optimize this function with respect to , we need to find where it is stationary and then verify that this point is a minimum.  This means we want to find a place where the function isn't changing with small changes in .  In other words, we want to find a spot where the derivative is zero.

Taking the derivative gives:

Setting this equal to zero, we can solve for :

     (2)

Let's plug in some numbers!  In Minecraft, you can swim at about 2.2 m/s and sprint at 5.6 m/s.  Let's take the river width to be 7 blocks (1 block = 1 meter).  Plugging in, we find that .  At this point, though, we can't tell if this is a maximum or a minimum.  One way to find out is to examine the curvature of the function at this point by using the 2nd derivative:

Plugging in , we see that which, being positive, means that is a minimum point for .  Visually:

crossing

 

So if you want to get to your cabin as quickly as possible, the fastest route is to swim across the river to a point that is 2.9 meters from point and then run the rest of the way.

This is actually a general problem.  Try replacing the speeds I used with speeds for soul sand, crouching and walking, a boat, etc. and see what happens!  Particularly, what happens to (2) if you can travel more quickly in the water than on land?

 

Scratch Work

Finding  First, rewrite the square root as a power, 

Differentiating, using the chain rule on the first term,  

Finding  Starting with , we differentiate with respect to x.  Note that the derivative of with respect to is 0, so we only have to deal with the first term.  Using the product rule and chain rule:

Cleaning up with some algebra:

 

From the notes: Two masses on a string going through a hole

Two masses on a string going through a hole.  Yeah, that's the stuff we learn about in physics class.  Anyway, this is the first in a (possibly) series of posts where I work out some problem from my lecture notes or homework.  The reason for doing this is because 1) there's a (small) chance it will be useful or interesting to someone else, and 2) the drawn out process of typing this up and thinking about how to explain it helps me study.

Figure 1, two masses on a string going through a hole.

 

Consider two masses connected by a string (figure 1).  The ideal string passes through a hole in a plate which is parallel to the x-y plane.  One mass, is sitting on the plate and is free to rotate about the hole with no friction.  The second mass, , is hanging below the plate and moves only in the vertical z direction under the influence of gravity.   The total length of the string is and we define and to be the distances between the hole and and , respectively, so that .

We can use Lagrangian mechanics to explore the system.  In Cartesian coordinates, the total kinetic energy is the sum of the kinetic energy of each mass:

     (1)

where we've used the dot notation for time derivatives.

Considering that is only rotating about the axis and is moving only vertically, it makes sense to consider switching to a more reasonable coordinate system.  We can transform to cylindrical coordinates with:

Taking derivatives of these with respect to time and inserting them into (1), we can rewrite the kinetic energy in cylindrical coordinates as

where and are now the generalized coordinates of the system.  The potential energy depends only on the height of since is confined to sit on the plate, so

With and we can write the Lagrangian :

We see that does not appear in the Lagrangian, which means that the generalized momentum corresponding to is a conserved quantity:

     (2)

can be identified as the angular momentum of mass .

We can also look at the total energy :

     (3)

From (2) we see that .  Substituting this in (3) gives

We can separate the constants on the left hand side and use the remaining terms to define an effective potential :

Imagine is rotating about the hole.  This means there will be some centripetal (or centrifugal, depending on your reference system) acceleration which will pull the hanging mass up.  We want to find such that the force is an extremum.  In other words:

Setting the derivative equal to zero gives

And solving for :

which gives the radius of "orbit" of mass about the hole for a given angular momentum such that remains suspended in the air.

 

Anti Rage-Induced-Accidental-Disconnect Minecraft Client Mod

We've all been there: You're playing on your favorite Minecraft PvP server, ready to get revenge on the player who just killed you, when suddenly, you're staring blankly at Minecraft's title screen.  How could such a thing happen?  Well, maybe Mr. McMillan has something to say about the matter:

 

Yes, Mr. McMillan, precisely.  The death screen GUI has "Respawn" and "Title screen" buttons that are way too close to each other, resulting in players sometimes unintentionally leaving the game when they actually want to respawn.  Now, this isn't something that happens all the time, but it happens occasionally and it's annoying.

So, in the first and only installment of the new (and old, by the time you read this) series "Weekly 1 Minute Minecraft Mods", we can fix the problem.

We will change this:

 

Before

into this:

 

After

(Texture pack is the beautiful Plast Pack.)

The new layout isn't pretty, but in the case of PvP I'll definitely take function over fashion (with the exception of gold pants).

Making the Mod

You need to download and install Minecraft Coder Pack (MCP).  There is a lot of information about how to do this online.

Once MCP is ready to go, find the file "GuiGameOver.java" in the minecraft/src subdirectory.  In this file, there are only two lines we need to modify:

1
2
this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 72, I18n.getString("deathScreen.respawn")));
this.buttonList.add(new GuiButton(2, this.width / 2 - 100, this.height / 4 + 96, I18n.getString("deathScreen.titleScreen")));

These files add the "Respawn" and "Title screen" buttons.  The only thing we need to change is the third argument to the GuiButton constructor.  We can shift the buttons up and down by changing the values of 72 and 96, with larger values corresponding to a lower position on the screen.  The "after" photo shown above uses values of 70 and 120:

1
2
this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 70, I18n.getString("deathScreen.respawn")));
this.buttonList.add(new GuiButton(2, this.width / 2 - 100, this.height / 4 + 120, I18n.getString("deathScreen.titleScreen")));

Once this is changed, save it and then proceed as you would with any other mod (recompile, reobfuscate, and drop the class in the appropriate Minecraft .jar file after backing everything up, etc.). Now you can crank up your mouse's sensitivity and fail to unintentionally disconnect from your favorite server with ease!

Note that this does involve changing core Minecraft files and so may result in issues if there is an overlap with another mod.  Also, it seems this won't be an issue when 1.7 comes out.

Simple LaTeX Table Generator

Anyone who's ever had to type up a large table in LaTeX knows that it can be a bit of work. When faced with a particulalry large table myself, I of course thought "why not python?".

It turns out there are already a few ways to generate latex tables, but here's my take:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
""" This short script converts a CSV table into latex table.
 
Command Line Arguments:
 
required positional arguments:
infile input file name
 
optional arguments:
-h, --help show this help message and exit
-ncols N, --numbercolumns N
number of columns in file
-vd, --verticaldivider
adds vertical dividers to table
-hd, --horizontaldivider
adds horizontal dividers to table
"""
 
import csv
import sys
import argparse
 
# define and parse input arguments
parser = argparse.ArgumentParser()
parser.add_argument("infile", help="input file name")
parser.add_argument("-ncols", "--numbercolumns", type=int, help="number of columns in file", default=2)
parser.add_argument("-vd", "--verticaldivider", action="store_true", help="adds vertical dividers to table")
parser.add_argument("-hd", "--horizontaldivider", action="store_true", help="adds horizontal dividers to table")
args = parser.parse_args()
 
# csv input and latex table output files
infile = args.infile
outfile = infile +".table"
 
with open(infile, 'r') as inf:
    with open(outfile, 'w') as out:
        reader = csv.reader(inf)
 
        # build the table beginning code based on number of columns and args
        # columns all left justified
        code_header = "\\begin{tabular}{"
        for i in range(args.numbercolumns):
            code_header += " l "
            if i < args.numbercolumns - 1 and args.verticaldivider:
                code_header += "|"
        code_header += "}\n\\hline\n"
        out.write(code_header)
 
        # begin writing data
        for row in reader:
            # replace "," with "&"
            if args.horizontaldivider:
                out.write(" & ".join(row) + " \\\\ \\hline\n")
            else:
                out.write(" & ".join(row) + " \\\\ \n")
 
        if not args.horizontaldivider:
            out.write("\\hline\n")
 
        out.write("\\end{tabular}")

Example input file:

1,2,3
4,5,6

Running with the -vd and -hd flags to specify vertical and horizontal dividers produces:

\begin{tabular}{ l | l | l }
\hline
1 & 2 & 3 \\ \hline
4 & 5 & 6 \\ \hline
\end{tabular}

It's very minimal, and the main idea is that it does 95% of the work for you, leaving only very minor cosmetic tweaks.