Problem 820. Eliminate unnecessary polygon vertices
Thanks for Cris for pointing out a hole in my original test suite. I added a test case that has a removable vertex as the first row of P and rescored all entries.
I think test case 7 is wrong - the starting vertex [1 2] can be removed can't it?
Thanks, Richard. I have updated test case 7, and the solutions are being rescored.
And now I think the vertices for test case 7 are coming out in the wrong order (cyclic shifted)] :-)
I agree with Richard. I believe my solution is correct now, but test case 7 is failing it.
This is the second time I've gotten up in the middle of the night to try to fix this. ;-) In my previous attempt to fix test case 7, I was fooled by the diagram I drew.
I've modified test case 7 again. When I run your latest solution, Cris, it passes. We'll see what happens when the solutions all get rescored again.
Sorry Steve! Hope you got some sleep in the end :)
Final discussion of the problem is up on the MATLAB blogs now:
Mixing vertices, lines and polygons is not fair because vertices and lines are not polygons and their simplification algorithm is not the same (multiple vertices can be simplified by using the function unique for instance). The author should at least change the problem description imho to "Eliminate unnecessary vertices at any shape or form". Anyway, It's a good problem (having non-manifold polygons is hard enough even without non-polygons).
Aargh ... sorry, used a function from the neural network toolbox without realising it. Didn't know it existed (normr)
If there's any way this one could be deleted I'd like it to be, because I think it's cheating (and Sven and I had a good competition going on!)
It's alright Richard... when I get home I'll just add normr=@(x)normaliseVector3d(x) to the top of my script and we'll be back in business... we might be near an optimised business but business nonetheless. As long as we don't resort to hacking the test suite via some huge regexp string then I'm still in the game.
No, gaming the test suite is out! Although Steve could yet make a mess of all this by using a polygon with floating point vertices ...
Hehe... yep I'm sure that would send us scrambling to add a tolerance to whatever-the-current-best-solution-was. But if this were intended for a bwboundaries(BW,'noholes','minimal') type option to bwboundaries, then all coordinates could be assumed integers and even the normalisation would be an unnecessary step since bwboundaries never skips a pixel.
Hey guys ... Don't worry, I'm not going to mess with you by adding new test cases that are subject floating-point round-off error. This will be in interesting point to discuss when I post a follow-up on my blog.
Nicely done! Do you think we've converged on the optimum yet?
Cheers, obviously I shamelessly adopted your favourite function.
I honestly thought we'd converged to an optimum (although a slightly distorted use of that word) back at around 64, then 55, then 48... so I only tentatively think we've reached the end. I'd certainly be relieved to call it a draw :)
I thought that maybe we could get rid of the extra arguments to sum(,2) and any(,2) by converting to a row matrix, but doing so would add arguments circshift(), so that way may not have any improvements left.
I do know that *every single line* of our function generates an M-Lint warning :) Oh, except the function name now.
Yeah, I tried all sorts of ways to do that too! I was trying to figure out a better way to normalise the matrix. I discovered normr, posted my solution, and then realised that it was actually a toolbox function. I'd be happy to have that entry removed :| If you replace the normalisation line with normr(diff(P)) you can get the 36
Hah, "Undefined function or variable 'normr'." A while back I had a version with normalizeVector3d(), part of the geom3d() package I use all the time...
I'd be interested to see under the hood of normr... I hope it's vectorized via bsxfun()
no it doesn't! it does something like:
n = sqrt(sum(x.^2,2));
x = x ./ n(:, ones(1, size(x,2)));
Well then, I bet that the following would run faster and work on any dimensioned data (such as a [10,2,50] sized matrix representing 50 sets of 10 XY vectors):
normr = @(v)bsxfun(@rdivide, v, sqrt(sum(v.^2, 2)));
This one uses the best tool in MATLAB :)
Ha! I just knew I'd come back from soccer and see you drop the score a bit. Nice one. Best tool in MATLAB? I like bsxfun, but that's already there... maybe it's an anonymous function... we'll see...
any hints on how to reduce the size of this thing?
Hi Anton, here's a hint: You're chopping down P then taking the difference between itself and its circshift. This is very close to just a simple diff() command. Circshift is a useful function, but not quite where you've got it ;)
Think of it this way:
A diff() will get vectors from one point to the next. If any neighbouring vectors point in the exact same direction, they are fair game to remove. More specifically, whenever the direction of the line *changes*, you've found a vertex you want to keep. How can you detect that?
stealing another one of Sven's tricks
Ahaha... I was hoping that silly ans trick was the on you used... turns out there's another somewhere!
The ans trick was the one I used ... to go from 54 to 52 ...
Yeah, there's one more you'll find that should get you to 51... unless it's already there :)
Hah, Richard, this one's just a sneaky tweak to the only bit I could see that was left... I think you deserve the better score with some improvements that you made that I hadn't thought of (using circshift instead of indexing was a nice touch). I think we left the realm of "nice robust solution" at around the 74/75 mark, and now we've entered the "cody-driven tweak" shadowy underworld that I hope nobody ventures into when making real products :)
aargh! what did you do this time!
OK, figured it (except I used length!). Ther emust be something else :)
Oh, and thanks! But my score is only going down largely thanks to your tweaks. I think it's very much a team effort at this point.
Cheating a bit - assuming exact cancellation. So this method is only suitable for integer coordinates, and I'm not even convinced that that will always work!
Problem Recent Solvers23
Project Euler: Problem 10, Sum of Primes
Compress strings (not springs)
More from this Author5
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!Start Hunting!