right algorithm, but too slow to work it out, TODO