Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Tuesday, December 4, 2012

Homework - functional style (outer sorting)

I'm attending Algorithms and data structures class this semester. Material it self is quite interesting and one TA is pretty cool too. But I don't like professor(makes whole experience very much worse) and I believe homeworks could be much better. Oh, and we didn't even mention functional approach...you know Haskell, Scala and the like. All we do is imperative, C-style code in Java. Enough ranting. This is how it saw the bright side.

Le problem

We were doing outer sorting. More specifically: balanced natural outer merge sort. I hope I translated this right(probably not). In it's essence the algorithm looks like this

  • you have multiple tracks you read from and write to
  • you have the current element of each track in memory
  • you write out squads(non-descending sub-sequence), this means you take the minimum element that is greater than last of if such element doesn't exist you take the minimal element. 
  • every time a squad ends your write pointer hops to the next track.
  • repeat until all elements are on single track(hopefully sorted in non-descending order)
Reel of 1/2" tape showing beginning-of-ta...
Reel of 1/2" tape showing beginning-of-tape reflective marker. (Photo credit: Wikipedia)
Quite simple right? TA's even provided us classes(talking Java here) InTrack and OutTrack to manage tracks and I/O. Well my problem is that I grew to dislike imperative style. Surely it may matter for performance, but since this is a homework, performance didn't matter - so I wrote pretty code. I wanted my central code(the heart of the algorithm) to be a few lines at most. 
This is my final product(bear in mind there was an additional twist: code should also be capable of sorting in non-ascending order thus the up variable).
Some additional explanation: all tracks should be in separate files(no overwriting - for automatic checking). N is number of tracks, prefix is track name prefix, and i is current iteration.
int i = 0;
Iterable<Integer> source = new InTrack(inName);
MultiSink sink;
do{
    sink = new MultiSink(prefix, i, N, up);
    for(int n : source) sink.write(n);
    source = new MultiSource(prefix, i, N, up);
    i++;
} while (sink.isMoreThanOneUsed());
I'm, probably not allowed to share my full solution because of university rules so I won't.
Now to comment on this. I have a source that's agnostic to the amount of open files. And I have a similar sink. End-point switching is implemented in MultiSink and element choosing is in MultiSource. Both InTrack and MultiSource implement Iterable(and Iterator) so I can use them in a for-each loop. And code is as pretty as I can get it(remaining in java). All in all ~300 lines(with InTrack & stuff). After removing uneeded utility methods and comments ~220 lines. Eww.. Thats way too much.

Scala to the rescue

Lets rewrite this in a functional matter using scala. And while I'm at it, no vars or m
Scala (programming language)
Scala (programming language) (Photo credit: Wikipedia)
utable collections. 
Input can be a collection right? Just implement Traversable. Not really. The whole point of tracks is they only hold one element in memory(or a few for efficiency but that's currently not my concern). So a track can be implemented as a Stream(linked list with a lazy val for tail).
def Reader(filename: String) = {
  val sc = new Scanner(new File(filename))
  def loop(): Stream[Int] = {
    if (sc.hasNextInt){
      sc.nextInt() #:: loop
    } else
      Stream.empty[Int]
  }
  loop()
}
This is the constructor function for the input stream. It just returns a recursive value that has a Scanner in its closure. As stream elements are immutable you get an iron clad guarantee that sc will stay in sync.   And you get all collections stuff for free. Moving on, how to abstract over multiple streams? That should be a stream again right? I kinda feel my code is too complicated and that it could be done simpler but that's what I came up with
def MultiReader(prefix: String, phase: Int, N: Int, up: Boolean) = {
  def loop(last: Int, sources: Seq[Stream[Int]]): Stream[Int] = {
    val nonEmpty = sources.filterNot(_.isEmpty)
    if(nonEmpty.length==0)
      Stream.empty[Int]
    else {
      val (low,high) = nonEmpty.
        map(_.head).zipWithIndex.
          partition(t => up && t._1 < last || !up && t._1 > last)
      val (e,i) = (if(high.length>0) high else low).minBy(_._1)
      e #:: loop(e, nonEmpty.updated(i, nonEmpty(i).tail))
    }
  }
  loop(0, (0 until N).map(n => Reader(prefix + "-" + phase + "-" + n)))
}
Let's walk through. Again the stream is recursive. It starts with a collection of Readers set to right files. Then in each step you filter out empty stream(tracks with no more elements) and partition them according to the last element(in the argument). If there are higher you take their minimum else you take the minimum of lower. And loop with passing on the read element and a new collection - non empty streams with the read one advanced by one element.

Writer was a bit trickier. It needs internal state, but I prohibited mutable state. Solution is to return a new Writer containing a new state every time you write. Then the user must just be careful not to use stale Writers - not that big a deal.
This is the Writer trait
trait Writer{
  def write(num: Int): Writer
  def moreThanOneUsed: Boolean
}
Very simple interface. And here's the recursive constructor function
def Writer(prefix: String, phase: Int, N: Int, up: Boolean): Writer = {
  val tracks = (0 until N).map(
  n => new PrintWriter(
    new BufferedWriter(
      new FileWriter(prefix+"-"+phase+"-"+n))))
  def mkWriter(i: Int, last: Int, used: Boolean): Writer = new Writer{
    def write(num: Int) = {
      val (ni,nu) =
        if (up && num < last || !up && num > last)
          ((i + 1) % tracks.length, true)
        else (i, used)
      tracks(ni).print(num)
      tracks(ni).print(' ')
      tracks(ni).flush()
      mkWriter(ni, num, nu)
    }
    def moreThanOneUsed = used
  }
  mkWriter(0, if (up) Integer.MIN_VALUE else Integer.MAX_VALUE, used=false)
}
Creates all the tracks to be put in the closure. First writer has the proper start value then every next is constructed like this: figure out the new values for track number and 'used'(the long if) then actually write out and return a new writer encapsulating track number and 'used'. Since these writers are quite lightweight garbage collection pressure shouldn't be a problem. Especially since the whole process is bound by I/O. Anyway you could optimize by creating all possible states in advance and just passing a new reference each time.

Putting it all together.
def loop(i: Int, source: Stream[Int]){
  val sink = source.foldLeft(Writer(prefix, i, N, up))(_ write _) 
  if (sink.moreThanOneUsed) loop(i+1, MultiReader(prefix, i, N ,up))
}
loop(0, Reader(inName))
So you take an input stream, fold it over a writer writing in each step. And if you used more than one track you repeat with a new input stream.
I find this solution to be MUCH MORE elegant. Not to mention it's just 65 lines of scala. But it makes me really sad they don't even mention functional programming at algorithms course. I'm probably gonna pay the professor and TA's a visit in near future.


Enhanced by Zemanta

Monday, October 29, 2012

Design patterns are bullshit!

It all started Monday morning at college. Professor of Information Systems was talking about evolution of programming techniques and at the end of the chain was OOP. The pinnacle of program design. Well, no. Even professor admitted that OOP failed to deliver. (No word on FP though, I was kinda disappointing). This made me thinking about problems of Java and the like.
Some hours later I'm sitting in cafe Metropol above Kiberpipa having tea with some friends - freshmen from FRI. And one of them asks me if there is a class on design patterns. I give a puzzled look and say no and he goes on to explain he's currently reading Design Patterns in C#. Apparently an awesome book that teaches you some general approaches to problems.
But I have quite strong opinions on some topics. And one of them are design patterns. I believe they are bullshit and I said that. I didn't read the GoF book and I don't have any intention to do so in near future. But I'm familiar with some patterns. Mostly workarounds for shortcomings of OOP languages and contrived solutions to non-existent problems. And I explained this.
Response was to paraphrase: "Well, MVC is a great design pattern". But I argued that it isn't a design pattern at all. Since everybody had a laptop, a quick wiki search cleared this up. It's an architectural pattern. Not a design pattern.

What are design patterns

So I asked him out of curiosity for some patterns from the book(also trying to prove my point).

Singleton

Well I used this one, so I cannot say it's bad. But I can still say it's overused and when it lets you access mutable object graph. Because this leaks mutable shared data all across your code base. But it gets real messy with double locking and stuff like that. Luckily Java solves this with enum. Now design pattern becomes just a keyword. That doesn't qualify as a pattern in my book. C# has static classes that are basically same thing, singleton instance held by the class loader. For some reason C# folks call this Monostate, but it's the same concept. Concepts are important, because they're language agnostic. Even though patterns try, they inherently aren't. And just for the last nail in the coffin. Scala has object keyword that creates a singleton. 

Factory, static factory...

This one is also abused. You even have metafactories that produce factories. Srsly...wtf? That's exactly like currying but wrapped up in objects and contrived to the point you no longer see it's currying. The only useful use-case for them is abstraction over constructors. That is, a single method that, depending on the arguments calls some constructor for the type it constructs. But again, this is hardly a pattern. 

Decorator

Decorator in statically typed languages means just implementing an interface or mixing in a trait(scala). I don't see the point here. That's why interfaces(traits) exist. 

Proxy

My friend insisted that this is something like Strategy pattern(didn't use the word) but from the other way. Proxy is the user of strategy object. Anyway strategy is just a wrapper for function value, nothing to see here. But not I googled it and I'm even more puzzled. It seems this means object reuse. Like literally sharing data. You know, like you do with any immutable values. Did I misread?

And about here we digressed to static vs dynamic typing. Sadly I was the only one for static. Apparently nobody wants compiler to help them. Now I'm sad. Compilers are one of the best programs out there. And with type inference they do all the work for you. You must be a fool not to use one and rather do a shitload of unit tests instead.

So... and anyone point to a useful design pattern or am I right and they truly are bullshit?
Enhanced by Zemanta

Cool Monday: HList and Shapeless

Java (programming language)
Java (programming language) (Photo credit: Wikipedia)
HList as in heterogenous lists. This means every element is of different type. Yeah sure, just list List<Object> in Java, but that is in no way typesafe. I want compiler to know the type of every element and stop me if I try to do something silly.

Linked lists to the rescue

So what's a linked list anyway? A sequence of nodes with pointers to next. And a nice implementation(still talking Java here) would be generic to allow type-safety for homogeneous lists. It turns out generic are solution for HLists too. Just introduce additional type parameter. Apocalisp has a great post on implementing them in Java. Here's just a factory method to see the gist
public static <E, L extends HList<L>> HCons<E, L> HCons(final E e, final L l) {
   return new HCons<E,L>(e, l);
}
Problem comes with instantiation.
final HConsInteger[], HNil>>> b =
      cons(4.0, cons("Bar", cons(new Integer[]{1, 2}, nil())));
Java requires A LOT of type annotation. It works but it's just painful and it doesn't pay off.

Type inference to the rescue

Type inference gets rid of this problem entirely. Let's implement whole working HList in scala.
abstract class HList[H,T<:HList[_,_]] {
  def head: H
  def tail: T
  def ::[A](a: A) = Hcons(a, this)
}

object HNil extends HList[Nothing, Nothing]{
  def head = throw new IllegalAccessException("head of empty hlist")
  def tail = throw new IllegalAccessException("tail of empty hlist")
}

case class Hcons[H,T<:HList[_,_]](private val hd: H, private val tl: T) extends HList[H, T]{
  def head = hd
  def tail = tl
}
So this list can be instantiated like this
scala> val myHList = 1 :: "hi" :: 2.0 :: HNil
myHList: Hcons[Int,HList[java.lang.String,HList[Double,HList[Nothing,Nothing]]]] = Hcons(1,Hcons(hi,Hcons(2.0,HNil$@dbb62c)))

And it just works. Scala compiler does all the heavy lifting with type annotations. This implementation bare bones and doesn't provide any useful methods(even random access!). Check out Miles Sabin's shapeless project for a useful implementation and much more. I provides indexing, map, fold, concatenation, type-safe casts, conversions to tuples(and abstracting over arities!) and back. And even conversions with case classes. Just click the link above and read the readme. It's awesome.
Enhanced by Zemanta

Friday, September 21, 2012

Power sets

It all started out when a friend of mine(check him out) told me a story about someone having an interview at Google. He was live coding and asked to implement a function that computes a power set of a given set. He totaly over-engineered it and after an hour of fiddling came up with 4-liner in python. Ok. Big deal. How hard can it be? I immediately started to brainstorm a solution of my own(and Matevž helped). Paraphrased train of thought below.

So what is a power set? Say a power set of set A. It's a set of all subsets of A. It's all possible combinations of including and excluding single elements. So it's like applying filters to the original set. Wait a sec, a set of size n has 2 to the n-th power subsets. It all matches up. N-bit number are said filters. So you count from 0 to 2^n-1 you enumerate exactly all the filters and therefore all the subsets. You just calculated the power set. This took about 30sec in real time.

Another minute to sketch the implementation.
You implement set as Lists. Let's say Java is the language of choice. An
y reasonable input would be shorter than 64 elements, at least on current machinery. So long can be used as counter. And now a nested for loop to iterate over elements and appending them if counter && (1 << n). Simple.

Won't post the code since I never wrote it.

The original blogpost

Enhanced by ZemantaThis happened in a lab at Faculty for Computer and Information science. On my way home I started thinkking....what is that 4-line implementation? It can't be my algorithm, that won't fit - it just isn't that elegant. Matevž also told me who was the original author and it was someone whose blog I was subscribed to(I still am, it's pretty awesome, check it out). So I searched for the original blogpost. And found it. It wasn't four lines. And it was(as Swizec admits) wrong.
def powerset(set):
      binaries = [bin(a) for a in range(2^len(set))]
      power = []
      for yeses in binaries:
        subset = []
 yeses = str(yeses)
 for i in range(len(yeses)):
                 if yeses[i] == “1”:
          subset.append(set[i])
 power.append(subset)
      return power
But more importantly, it's essentially my algorithm. (And it didn't took him an hour, read the post, it's interesting)

And then I realised. This is ugly. Quite ugly. It may be efficient and allow for doing iteration and evaluating it lazily, but oh boy it's ugly. Can't it be done in a simpler way?

Recursive solution

So by asking how I compute a power set I obtained the imperative algorithm above.
Balanced tree
Balanced tree (Photo credit: Wikipedia)
 Time to change the question. What is a power set? 
It's a set of leaves of a balanced binary decision tree. Every inner node represents a decision to either take or leave out the element at respective index(I assume elements are indexed). That is root node responds to first element, it's children to second element, etc. Every leaf can be computed by following the decision path.  It's a recursive structure. So the tree can be decomposed to left and right subtree and recombined. An this is repeated until you get to leaves. So a power set of A is an union of the power set of "A minus the first element" and the same power set again but with every subset added the first element. Subtrees are represented by the two powersets and the recombination by adding head element to one set of sets and then doing the union. And to stop the recursion: power set of an empty set is a set containing just an empty set. 
My attempt to formally express what I just written:

Now let's do that in code, my language of choice now is scala
def power[A](set: List[A]): List[List[A]] = set match {
    case Nil => List(Nil)
    case head::tail => power(tail) flatMap (set => List(set, head::set))
}
Yay just four lines. and the last one barely matters. But I can do even better. The same code in haskell
power [] = [[]]
power (head:tail) = power tail >>= \set ->[set, head:set]
Both code snippets don't comply exactly to the equation. I swapped in flat-map instead of union. It gets rid of repetition(but I don't know the math notation, sadly). So you apply the lambda that creates both sides of the union to your list and then flatten it to produce the same result.

This code may look a bit cryptic at first sight but once you parse the syntax you can grasp the intention much more quickly than the imperative version. At least I can. Recursion is quite nice once you get used to it.
Enhanced by Zemanta