I guess that in my last post, I didn't realize that the purpose of the exercise they gave me was to re-implement these ADT methods, even though they already existed. However, that was not made clear, and so someone who is familiar with the ADT (which would hopefully be the people following the curriculum) would probably be confused by the fact that they are overriding this list functionality with identical methods.
Tuesday, December 23, 2014
Changes 12/17/14
Did EIMACS Test 21 with Sam. It wasn't too hard, they had a lot of inserting into priority queues, then popping off the values in various ways.
Changes 12/23/14 - Javascript
I was ready for an EIMACS test but couldn't take it, so I just worked on JavaScript. I'm trying to make the shaking elements on ahirschberg.github.io use canvases instead of changing the position of the elements directly, because that is more reliable and less resource intensive for the browser, since only the pixels move within the canvas rather than the browser constantly having to update the object's position in the DOM.
Monday, December 22, 2014
Changes 12/22/14 - EIMACS Sets and Maps, ListQueue analysis
Today, I worked though the set and map unit of EIMACS. It's been pretty straight forward, and mostly review.
Kevin emailed me after seeing my post about the ListQueue exercise. He had a couple of questions about the implementation:
Kevin emailed me after seeing my post about the ListQueue exercise. He had a couple of questions about the implementation:
- Can ListQueue be substituted polymorphically anywhere a LinkedList is used?
- What are the implications of inheriting both interface and implementation
- Since Java doesn't have private inheritance, should composition be used instead?
- How does this example play with the Liskov Substitution Principle?
I wasn't familiar with some of the terminology he used, but I tried to answer his questions. For his first question about substitution, as far as I can tell ListQueue could be substituted for any LinkedList<Object> anywhere in the code, since it is a subclass which changes no functionality. However, it's important to note that ListQueue hard codes in the fact that it inherits from LinkedList<Object> and not LinkedList<E>, so this object could only be used when the compiler is expecting a LinkedList<Object>, and not, for example, when using a LinkedList<String>.
I'm not sure what the second question means, since LinkedList<E> is a concrete class that implements List<E>.
For question three, I'm first going to write out what private inheritance and composition are.
- Private inheritance is when a child class inherits from a base class, but does not make any of the methods of the base class (including the public ones) publicly accessible.
- Composition is when one object internally relies on other objects. In this case, composition would make the LinkedList<E> a private object defined within ListQueue, rather than a direct inheritance.
I think composition would make more sense for the ListQueue class, although it's not really clear what the purpose/role is anyway so it's hard to say
For question four, the Liskov substitution principle states that if S is a subtype of T, any expectations for the public interface of T should also be assumed about S, and therefore S could be replaced with T. This is only true when referring to a LinkedList of Objects. I'm not sure if that qualifies as adhering to the principle.
Thursday, December 18, 2014
Changes 12/18/14
Continued working with Sam on the UMD contest problem 6 - Breaking Vigenere Cipher, which required you to develop a program to find the probable length of the keyword used to scramble a string by looking at distances between repeated patterns of letters. First, we identified the frequencies of each three letter combination appearing in the text. Next, for any combination that appeared more than once, we found the distance between the indexes of those combinations. Finally, we found the values between 4 and 20 (this range was given to us in the problem description) that were factors of the distances we found. If a factor matched up with more than 90% of the distances, it was added to a results array. Sam did most of the work on this, and I helped him out with some stuff. I would like to review the code in more depth so that I can understand his approach a little bit better, though. I'll definitely read his blog on this topic.
Tuesday, December 16, 2014
Changes 12/16/14
Today I reviewed my answers for EIMACS test 21. I started learning about stacks and queues. I also came across this really strange exercise. The code started off as: The interesting thing is that this code already works perfectly, since LinkedList already has the methods #add(), #isEmpty(), #peek(), #pop(), and #remove(). However, their solution overrides these methods and re-implements them to have practically identical functionality:I'm not really sure what the point of that was.
I also learned about PriorityQueues, which take Compareable objects and rather than popping the first or last element added, they pop the element with the lowest value as determined by #compareTo(). The way they explained it was kind of weird, but I assume that this type of data structure does have use in actual applications.
I also learned about PriorityQueues, which take Compareable objects and rather than popping the first or last element added, they pop the element with the lowest value as determined by #compareTo(). The way they explained it was kind of weird, but I assume that this type of data structure does have use in actual applications.
Monday, December 15, 2014
Changes 12/15/14
EIMACS:
- Finished learning about quicksort, reviewed big O notation
- Reviewed the Java List interface and some of the concrete classes like linked lists, ArrayLists, and their traversal methods like iterators and ListIterators.
- Took EIMACS test 21, which was on lists and iteration.
Friday, December 12, 2014
Changes 12/12/14
EIMACS:
Looked at the quicksort a little bit more, using their graphical explanation. Based on my observation, it "locks in" elements to their final resting positions by incrementing the position of a bottom index and decrementing the position of the top index. Along the way, if it finds that an element at a bottom index greater than the pivot element and an element at a top index less than the pivot element, they are swapped. Eventually, the top and bottom indexes intersect, or cross over one another, such that the top index is less than the bottom index. At this point, the pivot element is known to be greater than all elements in indexes less than the pivot index and less than all elements in indexes greater than the pivot due to how the elements were swapped. The pivot element is now in its final position in the array, and the list is then split along the pivot element, and the process repeats recursively.
Sam showed me a cool website which gives a visual of the quicksort (along with other sorting algorithms)
Sam showed me a cool website which gives a visual of the quicksort (along with other sorting algorithms)
Thursday, December 11, 2014
Changes 12/11/14
Stuff:
- EIMACS - Learned more about quicksort. I'll write more in depth about what I'm understanding/not understanding tomorrow.
- Other stuff - helped Jack with some ATIC mobile site stuff
Wednesday, December 10, 2014
Tuesday, December 9, 2014
Changes 12/9/14
EIMACS:
Finished up learning about merge sort, and started learning about quicksort. Interestingly enough, a basic recursive quicksort was actually really easy for me to understand, since it was a lot like the merge sort algorithm. However, it's starting to get into the in-place quicksort, which is very complex and confusing. I'm pretty sure I've already gone through this section (I already did EIMACS test 20, which is after this part), but I figure I should probably review it anyway because of its complexity.
Monday, December 8, 2014
Changes 12/8/14
EIMACS:
Today I worked through some more of the EIMACS curriculum. I learned about the merge sort algorithm, which I actually thought was pretty cool. It works by splitting the array in half, then splitting those halves in half and so on. It then merges each fragment back together, eventually sorting the array.
Web Design:
Helped fix the /~atic/ site when viewed on a mobile device by changing the mediaquery from max-width: 480px to max-device-width: 480px.
Thursday, December 4, 2014
Changes 12/4/14
EIMACS:
- Did some more exercises, where I had to debug other people's mistakes. Debugging (or writing) algorithms is something I'm really not good at. It's just very hard for me to visualize what I'm doing
- I did well on the exercises though
Wednesday, December 3, 2014
Changes 12/3/14
Java:
- Finished Shut The Box algorithm with Sam, and I think now I understand how it works. Tomorrow I'll spend some time trying to mark it up.
- Source
Web Design:
- Learned how to import code directly into my blog using github gists.
- You can do this by going to gist.github.com and typing in code, then copying and pasting the embed script they give you
Tuesday, November 25, 2014
Changes 11/25/14
Java:
- Changed PythagoreanSpeed program so that it recorded run time in nanoseconds rather than milliseconds. Tweaked the output slightly
- I set it to do 100 passes at levels 50, 100, 500, and 1000:
Timings: =======(n = 50)======= Strategy UMD solution: 0.1177920396039604 ms. Strategy UMD solution with Math.pow: 0.7689506237623762 ms. Strategy UMD solution with pre-squared array: 0.1406431188118812 ms. Strategy pre-squared with hash: 0.23302989108910893 ms. =======(n = 100)======= Strategy UMD solution: 0.2192501683168317 ms. Strategy UMD solution with Math.pow: 1.022717900990099 ms. Strategy UMD solution with pre-squared array: 0.15266823762376236 ms. Strategy pre-squared with hash: 0.21271922772277227 ms. =======(n = 500)======= Strategy UMD solution: 17.247952891089106 ms. Strategy UMD solution with Math.pow: 126.09220794059407 ms. Strategy UMD solution with pre-squared array: 12.931144465346534 ms. Strategy pre-squared with hash: 1.3764326336633663 ms. =======(n = 1000)======= Strategy UMD solution: 132.50848051485147 ms. Strategy UMD solution with Math.pow: 1036.010291940594 ms. Strategy UMD solution with pre-squared array: 100.51113749504951 ms. Strategy pre-squared with hash: 5.131068326732674 ms.
- I didn't add any code to round the output, so past the hundreds place or so those digits are probably not significant
- Pushed changes to github
- I then added an additional algorithm which is O(n2log(n)). All other conditions were kept the same.
- Github link to algorithm
Timings: =======(n = 50)======= Strategy UMD solution: 0.12460728712871287 ms. Strategy UMD solution with Math.pow: 0.8824542277227723 ms. Strategy UMD solution with pre-squared array: 0.09626874257425742 ms. Strategy pre-squared with hash: 0.24894374257425742 ms. Strategy pre-squared with binary search: 0.14212682178217823 ms. =======(n = 100)======= Strategy UMD solution: 0.24023814851485148 ms. Strategy UMD solution with Math.pow: 1.1169474059405942 ms. Strategy UMD solution with pre-squared array: 0.23458126732673265 ms. Strategy pre-squared with hash: 0.2551629306930693 ms. Strategy pre-squared with binary search: 0.21795613861386137 ms. =======(n = 500)======= Strategy UMD solution: 17.942774574257427 ms. Strategy UMD solution with Math.pow: 126.00360138613861 ms. Strategy UMD solution with pre-squared array: 13.263654326732674 ms. Strategy pre-squared with hash: 1.4827347524752474 ms. Strategy pre-squared with binary search: 5.845997277227723 ms. =======(n = 1000)======= Strategy UMD solution: 132.98607085148515 ms. Strategy UMD solution with Math.pow: 1002.6387993267326 ms. Strategy UMD solution with pre-squared array: 100.78688199009902 ms. Strategy pre-squared with hash: 5.523412445544555 ms. Strategy pre-squared with binary search: 32.41068194059406 ms.
- It's interesting that the binary search algorithm is actually faster at low values of n, likely because a hash of the values doesn't need to be created.
Monday, November 24, 2014
Changes 11/24/14
Stuff:
- Replied to Mr. Elkner's comment about infinite meta refresh
- Read Kevin's email, he suggested that I improve the timings program by adding multiple values for n. I was originally going to do values of {100, 1000, 10000, 100000}, but some of the algorithms seem to take a very long time values of n past 1000 so I'm not sure if I should figure out which ones run in a reasonable amount of time at large N values and run those, or just cut off the test after like 2,000 or so.
- To keep run-time down, I only did three passes for each level, so the average values aren't as accurate as they could be.
Timings: Strategy UMD solution with n 100: 2 ms. Strategy UMD solution with Math.pow with n 100: 17 ms. Strategy UMD solution with pre-squared array with n 100: 1 ms. Strategy pre-squared with hash with n 100: 2 ms. ====== Strategy UMD solution with n 1000: 103 ms. Strategy UMD solution with Math.pow with n 1000: 753 ms. Strategy UMD solution with pre-squared array with n 1000: 70 ms. Strategy pre-squared with hash with n 1000: 13 ms. ====== Strategy UMD solution with n 2000: 797 ms. Strategy UMD solution with Math.pow with n 2000: 6051 ms. Strategy UMD solution with pre-squared array with n 2000: 637 ms. Strategy pre-squared with hash with n 2000: 21 ms. ======
- I realized that these numbers were being averaged as longs, and changed it so that they would be divided as doubles. I re-ran the test:
Timings: Strategy UMD solution with n 100: 2.75 ms. Strategy UMD solution with Math.pow with n 100: 19.75 ms. Strategy UMD solution with pre-squared array with n 100: 1.75 ms. Strategy pre-squared with hash with n 100: 1.75 ms. ====== Strategy UMD solution with n 1000: 94.25 ms. Strategy UMD solution with Math.pow with n 1000: 754.5 ms. Strategy UMD solution with pre-squared array with n 1000: 70.75 ms. Strategy pre-squared with hash with n 1000: 15.0 ms. ====== Strategy UMD solution with n 2000: 725.75 ms. Strategy UMD solution with Math.pow with n 2000: 6063.0 ms. Strategy UMD solution with pre-squared array with n 2000: 559.5 ms. Strategy pre-squared with hash with n 2000: 19.0 ms. ======
Changes 11/21/14
Ruby:
- Installed Ruby on Rails to my Ubuntu VM
EIMACS:
- Read more about selection sort
Thursday, November 20, 2014
Changes 11/20/14
Web design:
- Migrated website from students.gctaa.net/~ahirschberg/ to ahirschberg.github.io
- I also accidentally created a redirect loop (now fixed), and I was surprised that chrome didn't warn me at all.
Wednesday, November 19, 2014
Changes 11/19/14
Java:
- Updated weekend blog post about Pythagorean Timings, uploaded timing source code to github
- Started learning about sorts
Website:
- Set up ahirschberg.github.io to redirect to my students website
- Learned about using meta refresh to redirect: code
Tuesday, November 18, 2014
Changes 11/18/14
EIMACS:
- Took EIMACS test 18, which was on binary and sequential sorts
- I'm finding that the tests put a lot of focus on being able to work through these obscure, pointless algorithms for no clear reason other than to jump through their hoop to get the answer.
- For example:
- What is the value returned by the line newsearch( new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 9 )?
public static int newsearch( int[] a, int t ) { int n = (a.length - 1) / 2; int k = 0; while ( true ) { for ( int j = 0 ; j < a.length ; j += n ) { k++; if ( t == a[ j ] ) { return k; } } n--; } }
- And my approach for solving it:
- What does this even do? Why would you ever want to do this?? They make these complex algorithms for no reason! The only thing they are testing is my patience by making me work through each iteration, not my knowledge of searches.
Monday, November 17, 2014
Changes 11/17/14
I didn't like this:
public boolean equals( Object o )
{
return compareTo( (Item)o ) == 0;
}
{
return compareTo( (Item)o ) == 0;
}
EIMACS:
- I don't like this because you would never, ever want to use the first implementation of equals. Even though they make a note of this, it shows that the philosophy for their curriculum is out of touch with reality.
- Since the AB exam is no longer a thing, eimacs really needs to update their curriculum to stop focusing on the Collegeboard's curriculum. Operators like instanceof are important in Java, and acting like they don't exist is just plain stupid. I wish they would just teach instanceof once so they don't have to make a special case every time instanceof is necessary for solving a problem.
- Learned more about binary search, and wrote my own, which was kind of tough because I knew roughly what it should look like but forgot what the midpoint should be set to on each iteration.
- I had mid = (high - low) / 2, when it should actually be low + (high - low) / 2, or (high + low) / 2
- Learned that a binary search runs in O( log2n )
Changes Weekend 11/14 to 11/16
Java:
- Fixed the problems I was having with getting different counts in different Pythagorean Triples algorithms run on the same data set. What I realized was that the non-hash algorithms would count a Pythagorean Triple for each valid C value if there was more than one, while the hashed algorithm would not. For example, in the set {3,4,5,5}, the O(n3) algorithms would find 2 triples in this set, while the hashed algorithm would find one. To remedy this, I set the O(n3) algorithms to break once a C value had been found.
- Created a program that tests the average run times for various implementations of the Pythagorean Triples program with n=1000
Timings: Strategy UMD solution: 115 ms. Strategy UMD solution with Math.pow: 984 ms. Strategy UMD solution with pre-squared array: 78 ms. Strategy pre-squared with hash: 6 ms.
- The accuracy of this measurement could probably be improved if I had used something more accurate than System.currentTimeMillis(), but as it is it illustrates how much faster using a hash is than any other implementation.
Web Design:
- I made a website over the weekend: tommywiseau.github.io
- It's a tribute to the movie The Room, written and directed by Tommy Wiseau
- It's essentially like a soundboard, but for videos. Left clicking one of the video buttons will play the video, and right clicking will toggle looping on the video.
- If you click Tommy Wiseau's face in the top left, it plays a recording of one of the many times Tommy Wiseau laughs awkwardly.
- If you don't like hearing bad words, make sure to click the "toggle NSFW" button!
- Additionally, if you want to be taken on a magical cinematic experience, press the "Play all" button.
Friday, November 14, 2014
Changes 11/14/14
UMD Programming Contest / Java:
- At NSF Kevin and I started working on a way to benchmark the efficiency of the various algorithms used to find Pythagorean triples.
- We are testing UMD's base solution, their solution with Math.pow used to square the arrays, their solution with a pre-squared array, and Kevin's solution with a pre-squared array and hash.
- The program runs, but Kevin's solution finds a different number of triples than the other three strategies. For example: count 1619 did not equal lastCount 1454 for strategy: pre-squared with hash
- I'm not sure the best way to go about debugging this, I'll work on it on Monday.
Changes 11/13/14
Java:
- Took eimacs test 17, which was on inheritance (abstract classes and interfaces)
- Reviewed sequential and binary search algorithms
Wednesday, November 12, 2014
Changes 11/12/14
UMD Programming Contest:
- Uploaded Vigenere Cipher problem to github
- It took me a while to figure out because I was having trouble with a certain line.
- The correct implementation is:
sb.append((char)('A' + ((keyChar + plainChar) % 26)));
- At first, I didn't quite understand what I was doing. Sam and I had gone through the problem together, but I didn't fully understand his solution, so I decided to work on it on my own. I was pretty good on everything else in the program, but couldn't quite remember what this line had done in his program.
- Basically what this line does is take a character from a target string and offset it by the distance between a character in a "key" string and the letter A, which is the fundamental of a Vigenere Cipher.
- I kept thinking that the keyChar should be subtracted from the plainChar, because I felt like they should be a range. Obviously, that wasn't correct, and it threw me through a loop because I couldn't figure out what I was doing wrong
- Eventually I decided to work through the example they gave in the problem description while also looking at my code, which is how I figured out what I was doing wrong
- Doing this problem also made me realize I need to get more experience with the modulus operator (%).
- Sam used them really well in his implementation to loop the index for the character we were looking at in the key string and making sure that the offset for the character loops back around when it happens to offset past Z.
Changes 11/11/14
UMD Contest:
- Worked with Sam on the Vigenere Cipher problem (number 3)
- He got it almost right away, but I'm still working on my implementation, because I'm having trouble debugging it.
Friday, November 7, 2014
Changes 11/7/14
UMD Programming Contest:
- Had a conversation with Kevin about more efficient ways to fulfill the functionality requested by the Pythagorean triples problem from the contest.
- He suggested converting the array to a hash, using two for loops in order to identify a and b values, then checking if the corresponding c value was present in the hash.
- Since getting a specific element in a hash table is an O( 1 ) operation (although I haven't learned that yet), his solution would bring this down to O( n2 ).
- He also suggested pre-sorting the array and pre-squaring all the values, which would bring performance benefits for large values of n
- Looked at UMD's solution to the Pythagorean triples problem
- I guess I'm not quite clear on the design philosophy behind this contest. Are we supposed to have the simplest solution, the most elegant, the fastest? Can I pull in more advanced constructs like Hashes, or am I stuck with only the default imports of Java. In their solution for this problem, they used Arrays.sort(), but did not use Math.pow().
Thursday, November 6, 2014
Changes 11/6/14
UMD Programming Contest:
- Realized I had made an incorrect assumption about the data. The first number of each set to check (such as in the table at the bottom of page 4 of the pdf) appears to be number of integers on that line, and not actually a number to be checked for triple-ness.
- This had also caused me to make the incorrect assumption that each number was to be counted only once, which clearly isn't true, because the line 5 13 12 3 4 5 is expected to output both {5 12 13} and {3 4 5}. Since the first five in that set is the number of integers, the second five has to be counted twice.
- After making this assumption, I then wasted valuable time making the program set values it had identified were Pythagorean triples to -1 and adding integer > 0 checks to all the for loops so that values of -1 would be ignored.
- I also feel like the designers were very lazy in their setup of the environment, which leads to problems like this where they have hardcoded the expected length of the line into the file without being explicit about what they are doing.
- To be fair, they did say:
- "The first line in the test data file contains the number of test cases (< 100). After that, each line contains one test case: the first number is n (3 ≤ n ≤ 50), the size of the sequence, and the following n numbers are the sequence (not necessarily in any order)"
- However, that's not worded very intuitively, and I either missed that completely or just didn't understand what they were saying. One of the lessons I'm taking away from this problem in particular is to read the prompt and explanation very carefully.
- I eventually got an implementation that worked, although it runs in O( n3 ) since there are three nested for loops.
- Even in victory, I feel defeated, especially because I had to cheat a little and googled the best way to find the b value in a2 + b2 = c2, where a < b < c.
- I found a really simple solution to finding this intermediate value on stackoverflow, which was to add a+b+c and subtract the min and max values, leaving the only value that wasn't an extreme. I wish I could have thought of this on my own, but I just don't have enough practice with this sort of thing yet.
Changes 11/5/14
UMD Programming Contest:
- Wow today was horrible
- The enviroment they have set up for the programming contest makes it almost impossible to debug your code. They set System.out to output to a file, so if for whatever reason your program doesn't write the file, you have no way to find out why. I ran into a problem where my for loops were causing endless execution, but the program gave no indication of this. I checked in a normal java environment, and it turns out that the code:
int i = 0; for (int j = 0; j < 5; i++) System.out.print("");
Monday, November 3, 2014
Changes 11/3/14
UMD Programming Contest:
- Wasted about 45 minutes trying to import the pythagorean triples project into IntelliJ. I eventually got it by selecting "Import Project" > "Create Project From Existing Sources". Previously I had been selecting "Import Project from External Model", which wouldn't be set up correctly.
- Eventually I'll switch over to Eclipse
- Working on the Pythagorean Triples problem
- I'm sure there's plenty of resources on finding Pythagorean triples online, but I don't think I would be allowed to look at those during the contest, so I'm not going to look at those.
Friday, October 31, 2014
Changes 10/31/14
Ruby:
- Began creating a new thread pool prototype which has separate "download" and "parse" threads, to see how this construct might work in the end program
Website:
Thursday, October 30, 2014
Changes 10/30/14
UMD Contest:
- Removed the unnecessary function to add missing zeroes to a binary number from ErrorDetection.java. The functionality of the program is identical, but the code is much less complex.
Ruby:
- Clarified a previous blog post with Mr. Elkner. I clarified why 20.times.each is redundant in ruby. 20.times returns an iterator, and calling .each on that iterator (or calling 20.times.each) just returns itself (the same iterator) again.
Wednesday, October 29, 2014
Changes 10/29/14
UMD Programming:
- Worked on 2012 UMD programming contest question 1 (page 3 of the link), which involves error detection for 16 bit integers
- My implementation is here.
- It actually ended up being an easy problem, the hard part was getting used to the environment. They had a TryTest file which loaded preset integers and their check bits, but it took a while to figure out that this is how I was meant to test my file
- Since Integer.toBinaryString(int i) doesn't allow you to specify the expected bits, I figured that I should append the missing zeros to the front, so an integer like 42 would return "0000000000101101" and not "101101". In Python or Ruby, you could just do "0" * (16 - binary_string.length) + binary_string, but there is no way to do a string operation like this in Java as far as I could tell.
- I ended up writing a whole separate method to prepend the missing zeroes.
- In hindsight, I actually wasted a lot of time doing this, because only the ones are counted anyway. Using the method I painstakingly created ends up being functionally equivalent to just calling Integer.toBinaryString(int i).
- Line 11 can be replaced with Integer.toBinaryString() for an identical result.
- I think my performance on this problem would have really benefited from a plan, rather than just jumping right in. If I had thought about it more, I would have realized that Integer.toBinaryString() is sufficient for finding the number of '1's present in a binary integer.
Tuesday, October 28, 2014
Changes 10/28/14
Java:
- Did the first Stringlist activity, where you are essentially creating a string-like class that follows the ADT list interface.
- I was unhappy because it forced me to use string concatenation where a StringBuilder would have been much more efficient.
- The underlying store of character data in the eimacs implementation was a String. Replacing this String with a StringBuilder make much more sense, as the object's implementation of List interface methods like #add() and #set() suggests that the underlying data will be modified quite a bit.
- I also had some trouble during that activity because I couldn't figure out how to get the length of a string.
- This caused me to realize that Java's naming conventions are really counter intuitive, and place too much emphasis on implementation details.
- To get the length of an array, you call Array[].length;
- To get the length of a String, you call String#length();
- To get the length of a List, you call List#size();
- The reason I took 10 minutes trying to figure out how to get the length of a string was because I falsely remembered that you didn't need brackets after it. A programmer really shouldn't need to care that the length of an array is a static field while the length of a String is a method, but Java forces you to know that because you must put brackets after #length when calling it on String.
- Then, they take this and just throw it all out when implementing ADT list, making it #size() instead. I was also falsely under the impression that the naming convention was .length when the length is a static field and #size() when the length must be found using a method, but this is not the case.
- If I was using Eclipse or IntelliJ, I would have figured this out right away, but the eimacs web interface doesn't have tab completion.
Life Skills:
- Learned how to order pizza online, which I had never done before. People were kinda mean about it though, and acted like I was stupid for not knowing exactly how to do my first time.
- Learned that the Dominos website shows you coupons, which I guess is to make you feel like you are spending less on pizza. One coupon cut our order from $30 to $20, and that $20 seems like much less when compared to the $30 than it might if that was the original order price.
- I'm assuming that's what their going for, because it's kinda stupid that you can get the exact same order for a drastically different price depending on whether you click on the site a couple of extra times or not
Monday, October 27, 2014
Changes 10/27/14
Java:
- Worked on some more exercises out of eimacs.
- Started working on a string class called StringList that implements the interface of a list. However, it's stupid because they are making it extremely inefficient for the sake of simplicity, so methods such as #add() and #set() use the + operand on a string, so a new string must be returned for each operation. This makes me not even want to bother writing it, because it's a really stupid design.
Saturday, October 25, 2014
Changes 10/23/14 (at NSF meetup) and 10/25/14
NSF Stuff:
- Kevin showed me a really interesting video where a C# API developer wanted to make his interface very understandable, and to do this was trying to avoid returning null in a method to try to read a string from a file. He felt that this would be inconsistent with the rest of his interface, as other methods that returned strings were guaranteed to not be null.
- He went through various different approaches, which should hold true (to some extent) in any language.
- What he settled on was returning a Maybe, a collection guaranteed to have either 0 or 1 elements: 0 elements if the file couldn't be read, and 1 if it could, where the element was the string. This way, he could write code to handle a case with 0 elements much more fluidly than just having a null check.
- I also learned some stuff about C#!
- I guess the string data type is a primitive, because it was written as "string" when declaring the return type for his methods. If my memory is correct, I think you can write it as String as well.
- I also learned about the out parameter in C#, which was used in one of the approaches to the problem, albeit one that the guy in the video didn't like. It's still useful to know that you could have a specific variable be modified by a separate method, though. I think that's pretty cool.
Ruby:
- Updated code and committed to repo.
- Fixed ThreadPool#join_all so that it works correctly.
- Now, when called, it sets the finished flag to true, then does one of two things:
- If there are still elements in the task queue, Thread#join is called on each of the worker threads. Since the finish flag is now true, each worker thread continues to work as normal, but will abort once it completes a task and finds the task queue to be empty. Once all worker threads have completed tasks and found the queue to be empty, the #join_all method will release the lock on the thread it is called in (the main thread, most likely) and the program can continue on.
- If the task queue is empty when #join_all is called, ThreadPool#kill_all is called, which terminates all worker threads. This prevents a deadlock where all the threads are waiting on the queue already, and therefore never check to see that the finished flag has been set to true.
- I also cleaned up some things in the code, and learned some stuff along the way!
- I had a while loop that was something like
int i = 0 while i < 20 do ... i+=1 end
However this is very un-ruby like. I changed this to be
20.times do |i| ... end
which is much cleaner and easier to read. In doing this, I also realized that I had code that read:some_integer.times.each_with_index do |i|
which is just awful. It can be rewritten with the exact same functionality assome_integer.times do |i|
. I'm not sure why I thought I needed to call #each on that, let alone #each_with_index! (If #each is redundant, #each_with_index is doubly redundant because you are already using the integer as an index, so getting the index of that index makes no sense)
Thursday, October 23, 2014
Changes 10/23/14
Java:
- Finished lesson on LinkedLists.
- It was informative, they showed how adding a ListNode#getPrevious method and tail variable allowed much faster access to elements more than halfway into the list, since the list could now be iterated both backwards and forwards.
- Learned about iterators, which optimize the traversal of lists based on what kind of list it is. For example, a LinkedList iterator prevents you from needing to call LinkedList#get(i) when traversing, since #get() is an O( n ) operation.
- For each loops in java (ex: for (Object o : list) ) actually use iterators when traversing
- Learned about ListIterators, a subset of iterators that add more methods like #previous(), #add(E x) which adds at the current iterative position, and #set(E x) which sets the current item to x. E is a generic type, meaning that the user sets the actual type when creating the list. As an example, LinkedList<String>() would cause E to be a String.
Wednesday, October 22, 2014
Changes 10/22/14
Java:
- Read more on eimacs about ADT interfaces in Java. The curriculum is focusing on LinkedLists and their implementation.
- They are now talking about adding a getPrevious() method to each node in addition to getNext(), which will allow you to traverse the List both backward and forward. The drawback of this would be a larger memory footprint.
Tuesday, October 21, 2014
Changes 10/21/14
Life Achievements:
- I managed to shut down Aki's computer using only my face. I pressed the power button with my finger to open the shutdown menu, but he grabbed my hands. I used my nose to push the down arrow twice and then the enter key, which selects the standby option.
Java:
- Read more in the Data Structures and Abstractions with Java book
- Started reading about big O in the ADT list implementation.
- Commented my own ADT Linked List implementation with run times.
- Separated the LList tests into a separate file.
- Had a good discussion about problems with Java's implementation, such as the fact that it is written by a corporation and therefore doesn't place any trust in the programmer
Ruby:
- Removed the condition variable wait from threading_queue_pooled.rb
- The condition variable allows the programmer to sleep a thread while waiting on a resource from another thread. Once the resource is available, the #signal method is called, which releases the lock on one of the threads waiting on the variable.
- However, I realized that I actually don't want this in my case, because Queue#pop already sleeps the thread when empty, making the condition variable redundant. Additionally, the ConditionVariable#signal method doesn't do anything if the condition variable isn't currently causing the thread to wait, so if it is called when the thread is parsing stuff it is completely ignored. Therefore, the threads always ended up waiting forever, because each element pushed to the queue would only be signaled once, and if that signal happened to be ignored, the condition variable would continue to pause the thread, even though there were more tasks in the queue.
Monday, October 20, 2014
Changes 10/20/14
Title:
public int firstDuplicate( int[] a ) { int y = -1; for ( int i = 0 ; i < a.length - 1 && y == -1 ; i++ ) { if ( a[ i ] == a[ i + 1 ] ) y = i; } return y; }
- I've never seen an exit condition within the boolean of a for loop, which threw me off for one of the quiz questions for eimacs.
- This function could be simplified by removing the y variable and simply returning i when a[i] is found to equal a[i+1]
- I also was reminded that big O notation refers to asymptotic behavior, so a function with points (0,0), (1,1) (2,4) and (3,9) could still be O(n), because big O deals with behavior of large values for n
Friday, October 17, 2014
Changes 10/17/14
Java:
- Where the summation identity n(n+1)/2 comes from:
- If you have a sequence 1 + 2 + . . . + n - 1 + n, if you begin with the first and last terms and move inward, you will find that each of these adds to n + 1:
- 1 + n = n+1
- 2 + n-1 = n+1
- 3 + n-2 = n+1
- So you end up adding (n+1) n / 2 times, because each (n+1) accounts for two elements (one from each end), and therefore there are 1/2 * n instances of (n+1).
- I also tried to understand where the summation identity n(n-1)/2 comes from
- If you have a sequence 1 + 2 + . . . + n - 1, if you begin with the first and last terms and move inward, you will find that each of these adds to n:
- 1 + n - 1 = n
- 2 + n-2 = n
- 3 + n-3 = n
- But you only have (n-1) of these terms, which is where the n-1 comes from. Then, like the above identity, you have to divide by 2, so you get a final identity of (n-1)n/2 or n(n-1)/2
Changes 10/16/14 - NSF Meetup
NSF Meetup:
- Talked with Kevin and another guy (can't remember his name, sorry) about threading. Kevin suggested that the threads shouldn't be directly popping off of the queue, but instead be interacting with a middleman. However, I'm not sure that this is necessary, as this object (as I imagine it, at least) wouldn't really be adding any functionality, but instead would just act as a redundant intermediary between the threads and the queue.
- We also talked about my problems with ThreadPool#join_all. I learned that the ConditionVariable#broadcast method will wake up all the threads waiting on it, as opposed to ConditionVariable#signal, which wakes up only one. However, since Queue.pop already pauses the thread, I'm not sure that my ConditionVariable is even necessary
- I also talked more about what I want to do in college. I said that one of the reasons I don't like the math-heavy portions of programming is that I don't want to feel like a burden on anyone else. In college, I would have professors whose whole job is to make sure that the students understand the information. In high school, though, neither I nor my teachers have time to do this type of thing.
Thursday, October 16, 2014
Changes 10/16/14
Ruby:
- File in its current state
- Today I worked on testing how the ThreadPool handled extreme conditions, such as a long list of tasks or a large number of threads. The code I've written seems to handle these cases well.
- When I started trying to implement #join_all and #kill_all methods for the thread pool, I ran into some difficulties
- For #join_all, the intended behavior is for each thread to complete the current task, all the remaining tasks in the queue to be completed, and once these two conditions are met, for all the threads to stop. However, since each thread is an infinite loop of checking whether there is anything to pop off the tasks queue, simply calling #join on each thread (the current implementation on line 31) will result in a deadlock because the none of the threads ever actually finish
- I'm not sure how to remedy this. It seems that calling #join_all should stop the queue from accepting new tasks, allow each thread to continue as normal, and once the queue is completely empty, allow all threads to finish but prevent them from looping back into the waiting state (waiting state would occur on line 12). This is quite a complex behavior, and I will have to put some additional thought into how it should be implemented
Why I like programming:
- Kevin asked me to write about why I like to program, in order to figure out what college and career paths might be good for me.
- I enjoy programming because I love creating unique and interesting things. Programming is really cool because your creations actually do something; they work to achieve a task that you as the writer and designer have set out to complete. I enjoy the feeling of writing a section of a program so that it fulfills its obligations and is well designed. I also like the problem solving aspect: programming would be boring if everything were easy. However, I'm always worried that I will never figure out whatever problem I happen to be stuck on at the moment, and this feeling of hopelessness can take away from the enjoyment quite a bit. One of the things that drives me away from the more mathematical side of programming is the difficulty I have understanding it. If I were to focus on the mathematics behind algorithms, I would need a good teacher there to answer my questions. I do get this type of help in Advanced Topics when I need it, and I would expect that college professors would be able and willing to help me if I take these types of classes in college.
- Sorry if that was hard to read or understand, it was sort of a brain dump. Let me know if you have any questions!
Tuesday, October 14, 2014
Changes 10/14/14
Ruby:
- File in its current state
- Got a better understanding of mutexes and condition variables by playing around with the code
- Mutexes ensure that only one thread at a time executes a critical section of code, while condition variables can temporarily disable a mutex upon receiving a signal.
- This allows me to have a mutex around the statement which pops an item off of the queue, but temporarily release that mutex when a new item is added to the queue
- I also realized that I had an error in my logic. I was creating blocks of code to be executed with an incrementing variable saved in the block. However, blocks don't store their variables' values, but instead evaluate them when they are called.
- I was doing
i=0 loop do block = lambda { i } queue.push(block) i+=1 end
- However, by the time the block was called, the i variable had already changed from what I expected it to be
Friday, October 10, 2014
Changes 10/9/14
NOTE: This is Thursday's post. Friday's post is below this.
Stuff:
- Watched pyCon talk about a history of Javascript as told by someone in the year 2035. It was really interesting, and I learned a lot about how computers worked, especially in regards to memory addressing.
- I realized that using WordNet for word replacement isn't going to be as easy as I thought, because words like "went" which are past tenses of verbs aren't included in the base dictionary. It seems like there is a way to convert "went" into "go", but I will have to look into that further. In addition, determining what part of speech a word is can be tough. For example, in the sentence "I go to the store", go is interpreted as a noun, a Chinese board game, rather than a verb. I think this might be too complex of a project to work on in high school, especially at the level of commitment I'm willing to put into it.
Changes 10/10/14
NOTE: This is Friday's post. Thursday's post is above this.
Ruby:
- Completed a rudimentary thread pool that takes tasks and delegates threads to complete those tasks
- I'm sure it's not quite thread safe, and I'm not sure how scale-able it is in it's current form to use in a real program.
Other:
- I'll think about Kevin's email over the weekend and answer it on tuesday.
Wednesday, October 8, 2014
Changes 10/8/14
Java:
- I finally realized why the equation n( n + 1 ) / 2 comes up so much in measuring efficiency of algorithms. It is the identity of 1 + 2 + . . . + n. So for algorithms that have multiple loops, this comes in handy, because things tend to increase from 1 to n.
- For example, in the algorithm:
sum = 0 for i = 1 to n { for j = 1 to i sum = sum + 1 }
- In this image I wrote out what the algorithm would do when n = 5. I then counted up the number of additions and assignments (which was something they did in the textbook), and saw that the number of assignments matched up with what the book said. They found that there were 1 + n(n + 1) / 2 assignments in this loop and n(n + 1) / 2 additions, leading to an overall operation cost of n2 + n + 1. This matches up with what I calculated at the bottom of the page.
Tuesday, October 7, 2014
Changes 10/7/14
Ruby:
Java:
- Started reading Data Structures and Abstraction in Java's section about big O notation. So far they seem to do a better job of explaining than either of the other two resources I used. One thing I really liked about it was that when they introduced the concept of algorithms of varying efficiency to accomplish the same task, they gave examples and then broke those examples down into their speeds based on the number of calculations done.
- I still don't quite understand how they got n(n+1)/2 as the number of additions in the algorithm:
sum = 0 for i = 1 to n { for j = 1 to i sum = sum + 1 }
- Mainly, I don't really understand how they are calculating this. I guess the first n would come from the exterior loop, but how is the (n+1)/2 calculated?
Monday, October 6, 2014
Changes 10/6/14
Advanced Data Structures:
- Kept reading about measuring the efficiency of algorithms out of the book on Safari
- I started talking about amortized analysis of algorithms, but I didn't really understand what they were trying to say. It turns out that the book covers topics beyond the scope of a 2nd semester computer science course, so I'm not going to use it anymore
Ruby:
- Got distracted and started working on a small project that will eventually replace words in a sentence based on their definitions/parts of speech
- Uses ruby-wordnet, which is a really cool lexical(?) dictionary
Friday, October 3, 2014
Changes 10/3/14
Ruby:
- Added a mutex to the @queue.empty logic in threading_queue.rb (lines 22-25), because it probably should be an atomic operation. This means that if multiple threads are acting on the queue, between the @queue.empty? check and the @queue.pop statement, there should be no opportunity for another thread to modify the queue.
- Started working on a thread pool for multiple parsers/downloaders, but I'm kind of stuck
- I'm not sure what data structure I should store the different parse threads in, and how to make the best use of them. For example, if there are 20 things in the parse queue and only 10 threads to handle them, how can the program get notified when a thread has completed its task so that I can assign it to the next item in the queue?
Code:
file = @lock.synchronize do puts "Waiting for queue" if @queue.empty? @queue.pop # this method is blocking if @queue is empty end
Changes 10/2/14
Java:
- Read more about timing algorithms and big O notation
Ruby:
- Talked to Kevin about threading, watched some videos by Avdi Grim about threading in ruby
Wednesday, October 1, 2014
Changes 10/1/14
Java:
- Uploaded LList.java to github. It still needs some formatting work, as the code to exhibit the functionality (The LListTest class) should probably be in a separate document from LList
- The LList class's actual behavior doesn't start until line 64, which probably isn't good.
- I also finished up big O notation in eimacs and started reading about it in the Software Engineering and Development book. It seems like a thorough explanation so far, but there are still things that they don't explain. This might just be because I'm jumping into the middle of the book, though.
- The main thing was that in this image, they don't really explain where they get the ~(N^2)/2 and ~(N^3)/6 from. I'm assuming it's just because you don't know when the if conditional will be satisfied, but it will average out to being near the middle, hence the 1/2.
Tuesday, September 30, 2014
Changes 9/30/14
Java:
- Looked at Safari textbook, but only a little
- Learned more about looking at big O notation for measuring the efficiency of algorithms
- In my LList program, added support for adding elements to a specific index. It was actually really simple to implement. I'll set up Github for Windows tomorrow and upload the source.
Monday, September 29, 2014
Changes 9/29/14
Ruby:
- Added threading_queue to github
- See previous post for my thoughts on how it works
Java:
- Learned more about big O notation and mapping out the amount of time it takes functions to run.
- I'm having trouble understanding some of the things they are doing, so I'll have to talk to you tomorrow about it, since I'm out of time today
- Forgot to look at the safari book, I'll do that tomorrow as well
Friday, September 26, 2014
Changes 9/26/14
Ruby:
- Looked into ruby's Queue object
- Saw that the method Queue#pop, which returns the first element and removes it from the queue, is blocking, meaning that it will block its thread if the queue is empty while waiting for a value to return.
- This is great for me, because I was looking for a way to have a thread that could pause itself while waiting for files to download and resume itself once those files are downloaded
- I rewrote my threading test to use the queue object, and it ended up being much more straight-forward and probably more thread safe as well
- In the code marked 1. in the code section I have an excerpt I came up with to utilize Queue#pop. This code is intended to be run in a method in a separate thread, and will either parse items if there are any in the queue or do nothing while waiting for more to be added
- END_PARSE_SYM is a constant value that is added to the queue when another method, Parser#finish, is called. As you can see by the code, this signals that there are no more files for the queue to wait for, and therefore the infinite while loop is exited.
- One choice I made while writing my Parser class was to keep the thread behavior up to the code calling the Parser#parse method, meaning that Parser doesn't actually have any multithreading code.
- Instead, you must call something like what is listed in code excerpt 2. The statement within the { } runs in a separate thread, which is good, because in its current form, this method blocks its thread due to the Queue#pop statement being called on an empty queue within Parser#parse
- A side effect of this is that if you call parser.parse in the main thread, it throws a deadlock exception, because the @queue.pop statement is now blocking the main thread, so nothing will ever happen. I think this is acceptable behavior though, because Parser#parse really should never be called in the main thread anyway.
- I will look into other ways to throw an exception if Parser#parse is being called in the main thread
Code:
1.
def parse ... while true do puts "Waiting for queue" if @queue.empty? file = @queue.pop break if file == END_PARSE_SYM <... parse code here > end end2.
thread = Thread.new { parser.parse }
Thursday, September 25, 2014
Changes 9/25/14
Java:
- Worked more on improving the LList class
- Added a size() variable, so you can get the size of the LList
- Each time an element is added to the array, the size is increased
- Currently there is no way to remove elements, so the size can never decrease
- With this size() variable, the class can also do bounds checking. For example, with the code LList<String> llist = new LList<String>("sudo", "rm", "-rf");, calling llist.get(5); would result in Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 5 out of bounds for <LList elements=[sudo, rm, -rfl]>
- As you can see from this example, the LList.toString() method prints out the elements it contains. This uses a StringBuilder object to avoid the inefficiencies of adding strings together with the + operator (such as "abc" + "def"). Instead, you use the append() method of StringBuilder, then convert the StringBuilder to a string when you want to use it as one.
- I think that the LList structure is really interesting. The fact that you can have infinitely sized lists with no penalty for adding or removing elements is really cool, but I can see the drawbacks as well. For example, if something happens and one Node gets unlinked, all the other Nodes after it will get unlinked as well.
- Tomorrow I will work on implementing a remove() method for elements, and finish implementing a LList.toArray() method, which will return an array of the data stored in the LList
Tuesday, September 23, 2014
Changes 9/23/14
Java:
- Continued reading the Data Structures and Abstractions book
- Renamed my ChainLink class to Nodes like they have in the book, and hid them within a class called LList, so the end user doesn't have to deal with creating and traversing Nodes himself. Instead, the LList class takes care of it
- Right now it doesn't actually work, but I'll fix it tomorrow
Monday, September 22, 2014
Changes 9/22/14
Java:
- Finished up looking at quicksorts
- Started learning about preconditions, postconditions, and loop invariants, which are assertions you can make within a loop
- Started learning about timing functions
Friday, September 19, 2014
Changes 9/19/14
Java:
- Finished up the eimacs hash table section
- I feel like it wrapped up too quick, it just showed the basics without really talking about advanced hash collision strategies and stuff like that
- Started looking at sorting algorithms
- It's walking me through how an in-place quicksort works, which is when an array is sorted just by swapping the placement of elements
- It's very complicated, but they do a good job of walking you through it slowly
- They have an interactive example where it highlights the step the program is on, and explains what is being done
Thursday, September 18, 2014
Changes 9/18/14
Java:
- Got eIMacs account
- Started the advanced topics curriculum
- Started learning about hashes and hash tables
- Every object in Java has a hashCode() method, which is implemented in different ways. For example, Integer's hashCode is simply the number it represents. The hashCode of Strings has to do with the values of the characters in the string.
- There can be multiple objects with the same hash, however, and the data structure must make some attempt to resolve this
Wednesday, September 17, 2014
Changes 9/17/14
Java:
- Chapter 6 starts talking about linked data, and uses the analogy of desks in a classroom, where each desk has the number of the next desk in the sequence on it.
- This allows the instructor to access any desk in the series, simply by memorizing the number of the first desk, then asking each desk in succession what the number of the next desk is.
- I decided to test this out in Java, so I wrote a ChainLink class.
- Each ChainLink has two fields, a data field and a next field. The data field contains a string, and the next field is initially set to null.
- The method I wrote to set up the chain is called like this:
- createChain(new ChainLink("value1"), new ChainLink("value2"), new ChainLink("value3"), new ChainLink("value4"));
- This takes each ChainLink, and sets the next value of each to the next ChainLink in the sequence. The ChainLink with datavalue "value4" has its next field set to null, though.
- Then you can get a ChainLink at whatever index you want, with the getLink() method!
- Unfortunately I didn't have time to finish the chapter, though.
Tuesday, September 16, 2014
Changes 9/16/14
Java:
- Read more in the Java book, started looking at the ADT List structure
- So far the book has been walking through an implementation of a List class that uses an array to store items and has methods to add, remove, etc.
- Some of it is review from AP Comp Sci, like how variables deal with actual objects in memory
- One approach to having a list with no maximum length is to double the size of the array each time it becomes full. This is better than just adding 1 slot when one is needed, because you end up having to do less operations as more and more items are added.
Monday, September 15, 2014
Changes 9/15/14
Ruby:
- Read Kevin's email, which talked about problems with a variable being modified in separate threads
- This can cause problems, because one thread may find its information about the variable out of date.
- For example, if one thread stored a list's length in a variable, and another thread removed all elements from the list, then the original thread's length variable would become out of date.
- This example's failure is easy to fix though, and I'm not sure what the best way to discover the faults in what I've written
Java:
- Learned about Javadoc, assertions, and inheritance
- Javadocs allow you to show other developers what the different variables in your methods do. When someone enters a method with a Javadoc into their IDE, it will pop up with your explanation of what the variables do and what it returns
- Assertions are a way to test your code, but you need to set a compiler flag to have them do anything, and I don't know how to set that
- For example, assert x > 0; will throw an exception if the flag is set and x is less than or equal to 0
Friday, September 12, 2014
Changes 9/12/14
Java:
- Fleshed out the T type test to support 2 separate data types for the two values, so it is defined with new T_Test<String, Integer>(); for example
- Read about inheritance, and wrote a class testing how methods override each other.
- Basically, the methods of a base class will be overridden by methods further down in the inheritance. For example, if Person inherits from Thing, and both have a method called exist(), Person's exist method will override Thing's if the created object is a Person.
Thursday, September 11, 2014
Changes 9/11/14
Java:
- Read a bit more of the book
- Figured out how to set font size for IntelliJ (since I'm on a high DPI screen, everything was tiny)
Ruby:
- Read Kevin's feedback on the parser mockup
- Investigated race conditions (when the program freezes up or crashes due to two threads trying to modify the same thing at once)
- Tomorrow I will try to replace the array I am using as a stack with something thread safe.
- Interestingly, the built in ruby objects might be thread safe, as discussed here.
Wednesday, September 10, 2014
Changes 9/10/14
Java:
- Set up my JDK and IntelliJ Idea, which is the IDE I will be using
- Wrote a simple class to test out how Java handles a class like public class ExampleClass<T> {}
- Essentially I can then replace T with whatever I want when defining a new instance of ExampleClass, like new ExampleClass<String> or new ExampleClass<Integer> (you can't use primitive data types like int or float, though)
- Then, any time you put a T in the class definition, it will be replaced with whatever the data type is, so with the statement public T exampleVariable;, exampleVariable would be of type String in the first case and of type Integer in the second. This is pretty cool, and was not something I really understood before.
Changes 9/9/14
Java:
- Read book, and started installing IntelliJ, which is a java IDE.
- I'm on windows, and I couldn't figure out how to set my java home directory
Monday, September 8, 2014
Changes 9/8/14
NSF:
- Sent Kevin my parser/downloader mockup for his thoughts
Data Structures
- Started reading Data Structures and Abstractions with Java
Friday, September 5, 2014
Changes 9/5/14
NSFPatents2:
- Worked on a threading mockup for the NSFPatents2 application
- Eventually we want the program to be able to download files and parse local copies at the same time.
- I'm working on creating that functionality in a separate program to see what the basic structure should be.
- Basically it has two things happening concurrently
- Downloading of patent files
- Parsing of patent files which have already been downloading
- It is set up currently to "download" a file and notify the parser that there is a new file to be parsed.
- If there is already a parse in progress, it should add the new file to the queue.
- If there is no parse in progress, the notify method will create a thread so that the file can be parsed.
- This way, the program properly handles adding new files to the parse whether there is a currently parsing file or not.
Thursday, September 4, 2014
Wednesday, September 3, 2014
Wednesday, June 11, 2014
Changes 6/11/14
jQuery:
- Finally figured out how to programmatically create canvas elements
- Got width of images that were not actually visible on the page by using vanilla Javascript to create image objects and set source, then use natural width [1]
- Began looking at switching the shaker class over to canvas
Code:
img = new Image(); img.src = imgurl
img.naturalWidth // equals whatever the width of the base image is
Tuesday, June 10, 2014
Changes 6/10/14
jQuery:
- Began process of converting shaking mlg elements to canvas after this successful test
- Didn't get very far though
Thursday, June 5, 2014
Changes 6/5/14
jQuery:
- Reworked the mlg element creation, as there was repeated code between the hitmarker creation and mlgElement creation. I moved the shared code into a placeImage function, which takes an object which holds parameters.
- Changed the shaker from shaking the body to shaking only the mlgElements.
- Moved the mlg toggle button's onclick into the code, defining it with a jQuery event.
- Added a github repo for the website.
Wednesday, June 4, 2014
Changes June 4, 2014
jQuery:
- Continued trying to figure out why the mlg toggle button press doesn't always fire, but I couldn't really figure it out. I think it might have to do with lag in the browser due to the shaking and element fading.
Tuesday, June 3, 2014
Changes 6/3/14
jQuery:
- Fixed a bug where I had put setInterval(generateMLGElement(), 500);, which did not generate elements after the interval. I'm not really sure why, but changing it to setInterval(function() {generateMLGElement()}, 500); fixed the problem.
- I also began investigating a problem where the button press does not always stop or start the shakes and element fades. As far as I can tell the onclick method of the button does not always fire when the button has been pressed.
- Figured out that jQuery does use css selectors, and the reason it wasn't working for me was I had used the selector button.mlg to try to select a button I had never set to the mlg class. By adding the class in html, everything worked fine.
Wednesday, May 28, 2014
Changes 5/28/14
jQuery:
- I'm still trying to make elements shake. I almost have it, but I have this weird problem when trying to programatically animate an element.
- I'm using the code $(selector).animate({next_dir : sign + '=15px'}); to animate, where selector is something passed into the surrounding code, and next_dir and sign change depending on the number of iterations.
- This code does not work for some reason, and there is something wrong with next_dir. It's super weird because passing the function as $(selector).animate({"left" : sign + '=15px'}); works correctly but setting next_dir = "left" and passing $(selector).animate({next_dir : sign + '=15px'}); does not work, saying that there is an invalid property id.
Saturday, May 24, 2014
Changes 5/24/14 (Bonus!)
jQuery:
- Script visible at http://students.gctaa.net/~ahirschberg/, actual script here. Note that these may change.
- Got my script working; image elements fade in and out at random locations.
- Now the elements actually get removed correctly, instead of sitting invisible and slowing down the browser
- I implemented an id delegation system which I had originally written for the movable window project I was working on. I then improved it by allowing for ids to be deassigned and "recycled". I ran into some interesting problems.
- For example, look at code snippet 1. Substituting $(this).attr("id") for ele_id in the timeoutManager.addElement(...); line should be the same thing, right? The .attr("id") method just pulls the id out of the element being created, which had its id set to ele_id. There SHOULD be no difference between them. However, these two are NOT necessarily the same. Javascript is super weird, and when I was testing I entered into the console a for loop which would call generateMLGElement() many times with no delay, and I found that the function itself would fully execute, but queue the .load() statements, which would be executed later (So if you ran generateMLGElement() 4 times extremely rapidly, it would execute all the code in the body excluding the stuff in .load() 4 times, then execute the stuff within .load() for each element after all that was completed). This caused the ele_id to always be set to the id of the greatest element created for every single element. So if the four elements were created, the ele_id accessed by every .load() function would be 4, regardless of what the id was supposed to be. I worked around this by pulling the id out of the element itself rather than relying on the element id.
- If you couldn't quite understand what I was talking about, try modifying mlg.js so that the timeoutManager is sent ele_id rather than than .attr("id") in its addElement method (the one shown in the code snippet). If you enter into the console a for loop such as for (var i = 0; i <=5; i++) {generateMLGElement();}, you will see that the elements with ids 0 through 4 will not be removed but instead remain on the page (faded, but still there), because the id 5 will have been removed and registered for every element.
Code:
function generateMLGElement() {
...
ele_id = ID_PREFIX + idManager.assign()
element =
$('<img class="mlg" src="'+ imagesrc +'" ' + 'id="' + ele_id + '">').load(function() {
...
timeoutManager.addElement($(this).attr("id"), 2000);
})
...
}
Friday, May 23, 2014
Changes 5/23/14
Nothing:
- Didn't really do anything because of the workplace readiness picture and having to leave early.
- jQuery: Realized that I need to set element ids in order to fade and remove elements a specific time after they are created, since remove is not queueable after a delay().
Subscribe to:
Posts (Atom)
{
return ( o instanceof Item ) &&
( compareTo( (Item)o ) == 0 );
}