failing like never before

1May/090

GNU Readline

I reccently wrote a shell for a project in my CS class. One of the advanced features that my partner and I implmented in the shell, was tabbed completion, and in order to implemet this extremely useful shell feature, we used the GNU readline library. The GNU Readline library is a beast, and not in the good way. Its a great hulking pile of code and documentation, intended to provide a ton of features for reading typed lines. Once you figure out what all the function pointers, bindings, and generators in the Readline library are supposed to do, things become much more straightfoward, but it doesn't negate the fact that initially figuring out Readline is a bit of a pain in the butt.

The first thing I did after we were told that the Readline library could make our project easier to design, was to pop open a terminal and type "man readline". What I got was a basic summary of Readline, so in order to get the full library manual I had to resort to Google. I did however, happen to see this at the bottom of the manpage:

BUGS

It's too big and too slow.

Now if even the guys working on the Readline library think thats its too big and too slow, we may have a potential problem on our hands.

One of the plus sides of however Readline's enormity was that it does offer a whole slew of features, like a kill ring, and generators for tab-completion of filenames and usernames. It would be very nice though, if all these features could be implemented without the need for a manual that probably took me longer to read, then it did for me to code up a generator for command line completion.

Tagged as: , , , No Comments
1May/095

My Google Interview

Its been a while now, but here it is anyways...

About six or seven weeks ago, I scored a phone interview (technically two) with Google's IT department for a summer internship. Nobody was more surprised then I was that Google actually found my resume somewhat impressive enough to warrent a phone interview, especially considering my less-then-stellar GPA and the enormous number of super-intelligent applicants Google recieves every day. The two interviews were each forty-five minutes long, and the interviewers (both intelligent IT guys,  and not technically incompetent manager types) took pretty much all of the alloted time.

These days, almost every CS guy dreams of working for Google and so I've heard a few things about their interviews before, which I would like to mention before I get into my interview. A few years ago when I was an intern at Intel, they had a lady come in to tell all the high school interns about how to be successful in scoring future jobs. She spent a lot of time teaching us how to walk properly, shake hands, sit in a proper manner, dress, and answer generic interview questions. She told us that Google interviewers like to ask broad open ended questions like "how would you sell ice to an eskimo" and "why are manhole covers round," and promptly put us to answering similar questions. A few months later, I went to a Google Tech Talk at my University, where a Google software engineer was asked by someone in the audience if Google did in fact like to ask interview questions like "why are manhole covers round." The Google rep resonded with the following:

"In my time at Google I have interviewed several software engineers and I have never asked a question like that before. Google is not in the business of making manhole covers. If we did make manhole covers, we might ask those kinds of questions."

I think occassionally, a Google interviewer might throw in a brain teaser if they just want to burn some time, but apparently they don't do it too often.

Anyways, going on to my interview... I was interviewing for an IT position, so unlike the software developer positions where they barrage you with an endless stream of algorithim and programming questions (Why is quicksort log(n)? Whats the best sorting algorithim to use in this scenario? What data structure would you use for this? etc.) there was almost no programming invovled in my interview. And since the recruiter and HR person told me pretty much nothing about what I should expect, I went into the interview pretty much cold.

10Mar/090

Muxing the Clock

My final lab project for my digital design class is basically a free-for-all, design your own project. The project that my lab partner and I have chosen includes displaying a countdown timer on four seven-segment displays. We wanted to have the displayed value decrementing once every second, and we also wanted to make it so that the user could pause the counter and change the displayed value with push-buttons. The only problem with this scenario is that since the counters are connected to a 1Hz clock, the speed at which a user can set the displayed values is also 1Hz. This is bad, as we quickly found out, because it is unbearably slow, especially when you want to set a value of 100. So I came up with what I thought was a great idea: mux the clock input on the counters and then use the "set" button as the mux selector. If one of the mux inputs was then a 1Hz signal and the other a 4Hz clock, we'd be able to switch back and forth between the clock signals at will. Like most things I come up with, I thought it was a brilliant idea. And like most of my ideas, it died in the implementation phase.

The results of muxing the clock signal resulted in a buggy counter that would often spaz out whenever the "set" button was pressed. The clock would settle back into a regular pattern after one or two cycles, but the damage would have already been done: nobody wants to have a clock timer that explodes in a mad counting rush every time you press a button. I believe the reason for the bugginess is due to the fact that the rising and falling edges of the 1Hz and 4Hz clock do not coincide in time perfectly, and so when the mux switches clocks the counters see a clock signal that fluctuates at a weird rate for a brief interval.

And one more thing that I've learned in digital design lab: Xilinx software is total crap. Project files get regularly corrupted, the program crashes at odd times, compiling takes so long that I could probably wire the design by hand faster, and the auto-wirer was designed by a disgruntled employee on crack. The quiet murmuring that fills the digital design lab room is frequently broken by loud exclaimations of "I hate this software," "I will find the engineer that designed this auto-wirer and kill him,"  "#$(@*$&(@!***#&!!" and other such phrases (generally not by me). I could maybe understand the total crappiness if Xilinx's ISE was a beta version and avaliable for free, but its not. We're running version 9.2 (somewhere around there) and the school paid buttloads for Xilinx's POS software. Please don't even bother with Xilinx.

2Mar/091

One Last Try

I hate comparing other blogs to mine, because the conclusion I'm bound to reach is almost inevitably the same almost-painful answer. The problem is twofold: firstly, I'm not a very good writer and I never was, and secondly, I have almost nothing to write about.

Now the first problem I can live with, I will never be an amazing writer and it is not my goal to become one; I can live with being passably decent (being mediocre is something that college has introduced me to). But the second issue bothers me. And I wonder sometimes if its because my life is so monumentally boring that I have absolutely nothing exciting to write about, or if its merely that I'm incapable of turning mundane events into something that others might find interesting (like some bloggers are able to do). (I do so hope that it is the latter, because that would seem to imply that I'm not a total loser.) I tried over the summer, to keep a brief daily log of what was going on in my life, and it didn't take me long to realize that the only thing duller then my daily logs is a grocery list. But what the hey, I'm going to try again to write about my life, and see what happens again. So here goes:

About two weeks ago, one of my suitemates discovered the amazingness that is Heroes, and so after he finished with his midterms, he sat down with another of my suitemates and watched all of the first season of Heroes in one day, all twenty-three episodes (each one about 45 minutes long). Now if only our study habits were that good... But of course my roommate and I couldn't ignore the television extravaganza that was going on in our living room, and so by the next day we had watched two episodes and were hooked. My roommate and I finished the last episode of season one two days ago (and what a terrible and unsatisfying conclusion it was; they should have just shot Peter in the head, he would have healed anyways) and we've vowed not to start on season two until finals for this quarter are over. It remains to be seen of course, whether or not we'll be able to hold to our vows.

I managed to get an internship earlier this quarter, and though I enjoy it, its only another testament to my loser-ness. No other engineer that I know of, besides myself of course, has an unpaid internship, (companies are always looking to hire good engineers and engineers tend to be in short supply, so most companies are willing to fork over large sums of money to hire undergraduate engineers). But of course, I managed to find myself an internship at an internet startup that doesn't have the money to pay its interns, and I took the position because it seems that at the rate things are progressing, no other company is bound to hire me. On the plus side, I actually enjoy my internship position (as compared to some of my previous positions), I only have to go to the office once a week at the very most, and I get to polish up on my Ruby skills. With some luck, I may be able to turn this into a paying gig, although I think that would first require that the startup start making some money first. I spent a good chunk of time this weekend putting some work into knocking together some Ruby code, and was able to produce a new class for fetching and performing operations on e-mails using POP3. Since our web application will occasionally send a user a new e-mail (for forgotten passwords, registration confirmations, etc), I had to have a way to test if the e-mails were coming through OK. So I wrote a class that would grab an e-mail from some arbitrary e-mail account, find the newest e-mail matching a subject line, scan it to check its OK, and then extract the pertinent URL from the message body and follow it. It wasn't a very long class, but the regular expressions took me absolutely forever since I've never been much of a regex expert. I've also been writing a class that will extract data from a CSV file and then return the values from each line as an array.

We're using Selenium RC at work to do our unit testing of the web application, and although I think Selenium is pretty awesome, I've found it to be pretty freakin' slow. One very simple test cases, with only a few button clicks, assertions, and wait-for-page-to-loads, took about eleven seconds to run. Considering that we're going to be dumping over a hundred different sets of data into the CSV files for the test scenarios, running a whole series of test cases is going to be my new favorite excuse for slacking off. The biggest bottlenecks right now, appear to be the setup and tear-down times since Selenium has to start and stop Firefox for every new test case, the amount of time it takes to fetch a new e-mail using POP3, and the page refresh-times.

One of my friends is on the school's triathlon team, and recently proposed that I should join. I thought at first that our triathlon team does the full-out "Ironman" triathlon with a 26ish mile run, 113 mile bike-ride, and similarly long swim, and I immediately threw the idea out as ridiculous. But as it turns out, our school does a ridiculously short version of the triathlon that is more of an all-out sprint then anything else (seriously, their run is what I do every other night for my brief work-out). Its something that I could imagine myself being able to complete without too much of a problem, but I doubt that I'd be able to sprint that long. Of course I'd need a real racing bike first, something that isn't a twenty year-old chromoly steel mountain bike with friction shifters and a knocking headset.

Oh, and I've just checked my enrollment times for classes and have found that my second-pass is today at 4:30, and I have no idea what classes I should take. Woot.

(I guess this wasn't too bad of a write-up, certainly it couldn't be called an instant sleep-inducer for every living person.)

9Feb/090

A Simple Weird Sorter

This is a little toy program written for one of my CS classes. The program takes a positive integer N as an argument and reads from stdin until it gets an EOF. The program then sorts the input using qsort, while assuming that each element to be supported is N bytes long.

Fun facts: the output from this program looks kinda cool if you do "./program_name 1 < index.html" where index.html is some large webpage.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define MEM_SIZE 100

// for the sake of ease, token length and input array are global
unsigned long global_token;
char * in_ptr;

// comparator for qsort,
// returns 1 if a is bigger, -1 is smaller, 0 if equal
int comparator(const void  * a, const void * b)
{
  unsigned int i;
  int r_value = 0;
  for(i = 0; i < global_token; ++i)
  {
    if( *(i + (char*)a) < *(i + (char*)b))
      return -1;
    else if ( *(i + (char*)a) > *(i + (char*)b))
      return 1;
  }
  return 0;
}

// get input from stdin and save it to dynmaically allocated memory
unsigned long get_input()
{
  char* temp_in_ptr;
  unsigned long ar_size, n_ar_size;
  unsigned long max_size = MEM_SIZE;
  for(ar_size = 0; !feof(stdin); ++ar_size) // loop until EOF
  {
    if(max_size == (1 + ar_size)) // check if more memory is needed
    {
      temp_in_ptr =(char *)realloc(in_ptr,
                  (size_t)(MEM_SIZE + max_size));
      if(!temp_in_ptr) // returns error and exits if realloc fails
      {
        fprintf(stderr, "Error in allocating memory for input.");
        fprintf(stderr, "Input data may be too large.\n");
        free(in_ptr); // free dynamically allocated memory
        exit(1);
      }
      in_ptr = temp_in_ptr;
      max_size += MEM_SIZE;
    }
    *(in_ptr + ar_size) = fgetc(stdin); // get next char from input
    if(ferror(stdin)) // check for read error
    {
      fprintf(stderr, "Error encountered in reading input.\n");
      free(in_ptr); // free dynamically allocated memory
      exit(1);
    }
  }
  ar_size --; // get rid of EOF char
  // if string was not multiple of token length, need to make it
  // a multiple of token length and fill end with '\0'
  if(ar_size % global_token != 0)
  {
    n_ar_size =
       (global_token * (unsigned int)(ar_size / global_token + 1));
    if(n_ar_size > max_size) // check if more memory is needed
    {
      temp_in_ptr = (char *)realloc(in_ptr, (size_t)n_ar_size);
      if(!temp_in_ptr) // check for error in mem allocation
      {
          fprintf(stderr, "Error in allocating memory for input.");
          fprintf(stderr, "Input data may be too large.\n");
          free(in_ptr); // free dynamically allocated memory
          exit(1);
      }
      in_ptr = temp_in_ptr;
    }
    for(; ar_size != n_ar_size; ++ar_size) // fill with '\0'
    {
      *(ar_size + in_ptr) = '\0';
    }
  }
  return ar_size;
}  

int main(int argc, char** argv)
{
  unsigned long ar_size, i;
  in_ptr = (char *)malloc(MEM_SIZE * sizeof(char));

  if (argc < 2)
  {
    fprintf(stderr, "Must provide at least one argument.\n");
    free(in_ptr); // free dynamically allocated memory
    exit(1);
  }
  // use strtoul() to convert char to long int
  // and use errno to check for error in conversion
  errno = 0;
  global_token = strtoul(*(argv + 1), NULL, 0);
  if(!global_token || errno == ERANGE)
  {
    fprintf(stderr, "Argument must be a positive integer.\n");
    free(in_ptr); // free dynamically allocated memory
    exit(1);
  }    

  ar_size = get_input(); // get data from stdin
  // sort with qsort
  qsort(in_ptr, (size_t)(ar_size / global_token),
      (size_t)(sizeof(char) * global_token) , comparator);

  for(i = 0; i < ar_size; ++i) //print sorted data
  {
    printf("%c", *(in_ptr + i));
  }
  free(in_ptr); // free dynamically allocated memory
  return 0;
}
Tagged as: , , , No Comments
15Jan/090

Seven-Segment Display in VHDL

I wrote my first VHDL project last night during lab, andgot to see my design come to life when I programmed it into a Spartan3 FPGA. It was a pretty basic program, that changed a seven-segment display (like those old LED screens on old calculators) based on which switches were flipped. The four switches used were a BCD (Binary Encoded Decimal) value, so if the first and fourth switches were on and the second and third switches were off, then the BCD value would be 9 (1001). The seven-segment display would then display the value "9" if the switches were in position 1001. Fairly simple to design and program, but quite fun to play with. My VHDL code is below.


entity seven_segment is

port(
    x3,x2,x1,x0: in std_logic;
    a,b,c,d,e,i,g: out std_logic
);

end seven_segment;

architecture Behavioral of seven_segment is

begin
    a <= NOT( x1 OR x3 OR (x2 AND x0) OR (NOT(x2) AND NOT(x0)) );
    b <= NOT( NOT(x2) OR x3 OR (x1 AND x0) OR (NOT(x1) AND NOT(x0)) );
    c <= NOT( x3 OR x2 OR x0 OR (NOT(x0) AND NOT(x1)) );
    d <= NOT( x3 OR (NOT(x0) AND NOT(x2)) OR (x1 AND NOT(x0)) OR
        (x1 AND NOT(x2)) OR (x2 AND x0 AND NOT(x1)) );
    e <= NOT( (x1 AND NOT(x0)) OR (NOT(x2) AND NOT(x0)) );
    i <= NOT( x3 OR (NOT(X0) AND NOT(x1)) OR (x2 AND NOT(X0) AND x1) OR
        (x2 AND NOT(x1)) );
    g <= NOT( x3 OR (NOT(x1) AND x2) OR (x1 AND NOT(x0)) OR
        (x1 and NOT(x2)) );

end Behavioral;

1Dec/082

OMFG WordPress

As some of you may know, (and by "some," I do mean "me") I started my blog on a homemade CMS. It was simply and not particulary well written, but it did what I wanted it to and I never had problems with it after I finished its testing phase. I move to Typo because I wanted more and was too lazy to code a whole bunch of new features into my CMS, but discovered that, at the time, Typo was oh-so-slow and terribly buggy. So I switched to WordPress. And I've been on WordPress for almost a year now.

I like WordPress; its easy to use, and yet has a goodly number of features to get me through the day. The fact that I've stayed loyal to it after almost a year is a testament to how much I like it (I have a very short and fickle attention). But I cannot for the life of me, understand why the bloody hell the WordPress developers feel they have to push a new release at least once a month!

I generally don't have a problem with a rapid development timeline, but WordPress just really aggravates me. A Linux distribution with a nice package manager (Debian, Red Hat, Arch, etc.) can easily update all packages to the current version with a single very simple command. But such is generally not the case for the upgrading of WordPress. A lot of the people that run WordPress (like me) have to go and update their codebase by hand, which can really get old fast. Mind you, upgrading WordPress isn't hard at all, as it just requires some copy and pasting, but it does tend to be a pain in the butt, especially since you have to do it so often. (It just occurred to  me that I can simplify the whole process with a fairly basic script, but thats beside the point for now.)

I notice that a lot of WordPress releases are for bug fixes, rather then for new features, which begs the question why the development team doesn't just spend some more time debugging before they label their software as production-ready. And because of WordPress's constant bug fixes, I always feel impelled to upgrade to the newest release.

I'm starting to wander a little bit here, I know, so just to bring it back, OMFG WordPress!!! Why must you release so often??!?!

7Nov/080

Keeping It Clean

Ernest Hemingway once said, "I write one page of masterpiece to ninety one pages of shit...I try to put the shit in the wastebasket." And just like writers, programmers also manage to produce quite a bit of shit. Of course, most programmers are perfectly capable of recognizing when they've created an inelegant function, but because of time restraints and deadlines, they just keep on going. But students that are still learning to program, often have trouble recognizing when code is in desperate need of deletion.

A university-level programming class usually requires students to spend a great deal of time working on projects and homework. So its quite easy, after hours of coding, to become emotionally attached to one's code. Generally, a student programmer will make a mistake in a function or block of code, and so they'll add in a quick little fix. Eventually, after numerous little fixes, their function starts to become a giant, awkward, lumbering behemoth that is still wrong.

The most obvious choice is to simply, as Hemingway so succinctly said, "put the shit in the wastebasket" and start from the beginning. But the student has managed, after hours of labor, to become extremely attached to their hundred lines of awkward code and just can't manage to throw away the terrible result of all their hard labor. I say this because when I was learning to program, I often found myself becoming too attached to my code. On one particular occasion, I spent two days patching up the code for my self-balancing AVL binary tree, which was frankly, a piece of shit. Eventually, I threw my AVL tree class in the garbage, started again from scratch, and recreated a working tree class in a few hours.  If I had only been a little more emotionally detached, I might have realized how stupid I was acting.

In order to keep code clean and effective, student programmers need to learn to stop falling in love with their misshapen code-children; code cannot love you back, so don't waste your time developing emotions for it. Just keep it clean kids, and save the loving for another time.