good algoritm, too slow to work it out, TODO