Discussion:
algorithmic question
Adam Megacz
2004-03-29 07:21:58 UTC
Permalink
Brainteaser for yall. Earlier, I sized grid columns/rows by setting
each column to its minwidth and then handing out the slack in
proportion to the column's weight. This isn't what most people
"expect", though.

I'm trying to figure out how to do it in O(n) time (I figured out O(n
log n)) -- not because I care so much about the difference between
those two, but because O(nlgn) solutions are rarely incremental. In
other words, I want something where if very little has changed (like,
for example, only the goal width), we can use the old solution to get
the new one very quickly.

To make it harder, all this stuff has to be done with integers, *and*
the error has to be deterministic so that the columns don't "vibrate"
when you resize things really quickly. Basically this means that the
rounding error has to wind up in the same place regardless of whether
you computed the sizes from scratch or recycled the old solution.

Here's the formal statement of the problem:

You have a goal width for the sum of the columns. You must find 'k'
such that when each column is set to:

min(maxwidth, max(minwidth, k*weight))

the sum of all the columns equals the goal weight. Basically each
column is k*weight, and then you crop it to that column's max/min
size.

Winner gets a cookie.

- a
--
"It's lucky," he added, after a pause, "that there are such a lot of
islands in the world. I almost envy you, Mr. Watson."

-- Mustapha Mond
Charles Goodwin
2004-03-29 12:03:27 UTC
Permalink
Post by Adam Megacz
Brainteaser for yall. Earlier, I sized grid columns/rows by setting
each column to its minwidth and then handing out the slack in
proportion to the column's weight. This isn't what most people
"expect", though.
Expectation usually is of the end result, not of the method to achieve
said result. In this case the result is as expected (although I've
encountered a few bugs).
Post by Adam Megacz
I'm trying to figure out how to do it in O(n) time (I figured out O(n
log n)) -- not because I care so much about the difference between
those two, but because O(nlgn) solutions are rarely incremental. In
other words, I want something where if very little has changed (like,
for example, only the goal width), we can use the old solution to get
the new one very quickly.
Having been working on Box.java a bit, one concern here would be how to
store the old solution such that we don't use copious amounts of memory
for each box. Currently there's a set of static LENGTH [65535] arrays.
Wouldn't that multiplied by several thousand be quite bloated?
Post by Adam Megacz
You have a goal width for the sum of the columns. You must find 'k'
min(maxwidth, max(minwidth, k*weight))
the sum of all the columns equals the goal weight. Basically each
column is k*weight, and then you crop it to that column's max/min
size.
That sounds nice and elegant but sadly it's not that simple.

What happens when a box, low down in the ascendency chain, resizes such
that it affects the width of the column it is in? How do you notify the
parent that one of it's column widths has changed? Or are you proposing
two functions in Box.java, quick_resize() and full_resize(), for this?
Post by Adam Megacz
Winner gets a cookie.
What flavour/type?
--
- Charlie

Charles Goodwin <charlie-***@public.gmane.org>
Online @ http://www.charlietech.com
Charles Goodwin
2004-03-30 12:18:33 UTC
Permalink
Post by Charles Goodwin
What happens when a box, low down in the ascendency chain, resizes such
that it affects the width of the column it is in? How do you notify the
parent that one of it's column widths has changed? Or are you proposing
two functions in Box.java, quick_resize() and full_resize(), for this?
There definitely needs to be two different directions for resizing, one
for the parent to resize and propogate changes downwards and another for
a child resizing with changes propogated upwards.

I'm reluctant to take this on because I really am far from in a
position, Java talent wise, to implement it properly. I have made a
number of adjustments to Box.java to make it work better including
fixing Bug 471 and correcting colspan/rowspan semantics, so I hope to
have done a lot of the work for the correct 'parent propogating
downwards resize' pass.

There's still a small bug in it but I hoped to have broken all the
changes out in order to help isolate the problem I'm having, but darcs
is being a pain. Was up 'til 5am last night because of darcs. Lovely.

Never do mass 'no's to darcs record. The next time you try to record it
seems to have forgotten an awful lot. (First time, said 'no' around 20
changes, second time there were only 3 changes to say 'no' to.)

Still, darcs is still significantly better than CVS. ;)
--
- Charlie

Charles Goodwin <charlie-***@public.gmane.org>
Online @ http://www.charlietech.com
Charles Goodwin
2004-03-30 12:22:27 UTC
Permalink
Post by Charles Goodwin
Never do mass 'no's to darcs record. The next time you try to record it
seems to have forgotten an awful lot. (First time, said 'no' around 20
changes, second time there were only 3 changes to say 'no' to.)
Still, darcs is still significantly better than CVS. ;)
Cancel that. Yet another error between chair and keyboard. Somebody
should replace that buggy component.
--
- Charlie

Charles Goodwin <charlie-***@public.gmane.org>
Online @ http://www.charlietech.com
Jeff Buhrt
2004-03-30 13:36:33 UTC
Permalink
I have noticed the same thing, don't type ahead to darcs! It will puke.
For example 'yyyyy...' when pulling patches, it die instead of applying
when done.

-Jeff
Post by Charles Goodwin
Post by Charles Goodwin
Never do mass 'no's to darcs record. The next time you try to record it
seems to have forgotten an awful lot. (First time, said 'no' around 20
changes, second time there were only 3 changes to say 'no' to.)
Still, darcs is still significantly better than CVS. ;)
Cancel that. Yet another error between chair and keyboard. Somebody
should replace that buggy component.
Adam Megacz
2004-04-01 10:38:12 UTC
Permalink
Post by Charles Goodwin
There definitely needs to be two different directions for resizing, one
for the parent to resize and propogate changes downwards and another for
a child resizing with changes propogated upwards.
Right; see NEEDS_REFLOW (upwards) and reflow() (downwards).
Post by Charles Goodwin
I'm reluctant to take this on because I really am far from in a
position, Java talent wise, to implement it properly.
I'm impressed with how well you've figured out the details of the
reflow algorithm. I can take care of the implementation.

- a
Charles Goodwin
2004-04-01 12:54:06 UTC
Permalink
Post by Adam Megacz
Post by Charles Goodwin
I'm reluctant to take this on because I really am far from in a
position, Java talent wise, to implement it properly.
I'm impressed with how well you've figured out the details of the
reflow algorithm. I can take care of the implementation.
Reverse engineering good code is always easier than writing good code.

(I'll stop now before this starts to get soppy.)
--
- Charlie

Charles Goodwin <charlie-***@public.gmane.org>
Online @ http://www.charlietech.com
Charles Goodwin
2004-04-01 17:04:52 UTC
Permalink
Post by Adam Megacz
Post by Charles Goodwin
There definitely needs to be two different directions for resizing, one
for the parent to resize and propogate changes downwards and another for
a child resizing with changes propogated upwards.
Right; see NEEDS_REFLOW (upwards) and reflow() (downwards).
Only NEEDS_REFLOW and reflow() don't exist - do you really mean
MARK_REFLOW and repack()?

What's the difference between MARK_REFLOW and MARK_REFLOW_b?

Also MARK_REFLOW_b is never declared anywhere in Box.java or anywhere
else, although it is used several times:

charlie-***@public.gmane.org ibex $ egrep -r MARK_REFLOW_b src/org/ibex/*
src/org/ibex/Box.java: //#define MARK_REFLOW_b for(Box b2 = b; ...
src/org/ibex/Box.java: MARK_REFLOW_b;
src/org/ibex/Box.java: MARK_REFLOW_b;

(Why doesn't this make the compiler barf?)

Perhaps that could be causing some of the unecessary repack() calls?
--
- Charlie

Charles Goodwin <charlie-***@public.gmane.org>
Online @ http://www.charlietech.com
Jeff Buhrt
2004-04-01 19:18:18 UTC
Permalink
Charlie,

MARK_REFLOW_b() is a macro. The '//#define' is picked up by the ibex
preprocessor, thus one thing expanded going to 'build'.

-Jeff
Post by Charles Goodwin
Post by Adam Megacz
Post by Charles Goodwin
There definitely needs to be two different directions for resizing, one
for the parent to resize and propogate changes downwards and another for
a child resizing with changes propogated upwards.
Right; see NEEDS_REFLOW (upwards) and reflow() (downwards).
Only NEEDS_REFLOW and reflow() don't exist - do you really mean
MARK_REFLOW and repack()?
What's the difference between MARK_REFLOW and MARK_REFLOW_b?
Also MARK_REFLOW_b is never declared anywhere in Box.java or anywhere
src/org/ibex/Box.java: //#define MARK_REFLOW_b for(Box b2 = b; ...
src/org/ibex/Box.java: MARK_REFLOW_b;
src/org/ibex/Box.java: MARK_REFLOW_b;
(Why doesn't this make the compiler barf?)
Perhaps that could be causing some of the unecessary repack() calls?
Charles Goodwin
2004-04-01 19:31:18 UTC
Permalink
Post by Jeff Buhrt
MARK_REFLOW_b() is a macro. The '//#define' is picked up by the ibex
preprocessor, thus one thing expanded going to 'build'.
Yeah, I saw it in the //#define but at the time thought 'it's commented
out, can't be that'... looks like I temporarily forgot about the
preprocessing setup for Box.java. ;)
--
- Charlie

Charles Goodwin <charlie-***@public.gmane.org>
Online @ http://www.charlietech.com
Adam Megacz
2004-04-01 10:37:04 UTC
Permalink
Post by Charles Goodwin
Having been working on Box.java a bit, one concern here would be how to
store the old solution such that we don't use copious amounts of memory
for each box.
Precisely. You do get to store the width/height of the box in its
width/height properties. And adding a few flags (like
CANNOT_GET_ANY_BIGGER) would be okay.
Post by Charles Goodwin
What happens when a box, low down in the ascendency chain, resizes such
that it affects the width of the column it is in? How do you notify the
parent that one of it's column widths has changed?
When you change the box's size, it will propagate a needs_reflow() up
the tree, which sets the NEED_REFLOW flag on all its parents, which
then causes the reflow() operation to trace down the tree along the
same path before rendering.

- a
Charles Goodwin
2004-04-06 03:24:17 UTC
Permalink
Post by Adam Megacz
Winner gets a cookie.
Was it nice? (You did win it fair and square.)
--
- Charlie

Charles Goodwin <charlie-***@public.gmane.org>
Online @ http://www.charlietech.com
Loading...