Monday, July 20, 2009

Day 38

Today I worked on improving the historyComparer some more. I needed a way to take two lists of tables, and match them up in length and in value. So if I had a list of 3 tables and a list of four tables, where table 1 of the first list matched table 2 of the second list, I would ten add a blank table before table 1 of the first list. This would line up the matching tables as well as the end of both lists (they would both be 4 tables long). But then I also needed to guarantee that if two tables didn't match eachother, the would not be in the same row/lined up. The process would look something like this:

List1 List 2 ---> List1 List2 -----> List1 List2
_A_ X_____ blank_ X _______blank__ X
_B_ Y_______ A__ Y_________ A__ blank
_C_ B_______ B__ B_______ blank__ Y
_D_ Z_______ C__ Z_________ B___ B
_--_ D_______D__ D_________C__ blank
_________________________blank__ Z
__________________________ D___ D

This way, when comparing the tables of two page's test history, the user would be able to easily see which tables have changed, new tables, deleted tables, and so forth.
The solution was to first, put the tables in lists like above, then to compare the tables, then line them up, then finally add blanks where needed. This sounds simple enough, but what ended up happening was that I had loops inside loops inside of loops.
The process would start by comparing each table to every other table in the other list. Every time the comparison found a match, it would add the index of those two tables to a list of pairs, to keep track of the matches. Once all the matches were found, it would loop through the matches trying to line them up by adding in blank tables. But every time a blank table was added to a one of the lists, the indices of the matches had to be updated, so it would have to loop through the matches again inside the first loop, updating all the indices. After all the matches were lined up, it would loop through the lists adding blank tables anywhere there were two tables in a row that didn't match, and then again update all the match indices. Finally, it would make sure both lists had the same number of tables by adding blanks to the end of either list if needed.
Now I have a lot of refactoring to do to make the code explain itself. This is, I think, the most important part of coding, and its a good thing I have tests.

4 comments:

  1. Your list example is very hard to understand, please make it preserve the white-space.

    ReplyDelete
  2. Thank you for pointing that out, I hope it is now easier to read.

    ReplyDelete
  3. That is much better. Thanks. It sounds like this takes time \Omega(n^3) in the worst case and \Theta(n^2) in the best case, n being the number of tables.

    What happens with
    List1 List2
    __A_____B__
    __B_____A__

    probably

    __A___blank
    __B_____B__
    blank___A__

    ?

    ReplyDelete
  4. Indeed you are correct. At the moment I don't deal with switcharoos, I try to preserve the original order. Your right however, soon enough someone is going to want the table matching to be smarter, and thus in the next release I will probably have to fix this.

    ReplyDelete