- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Subtext: Alex is doing some remodeling (rennovating) and can't be bothered doing the calculations himself.
Admin
So who's taking into account the ~1/8" lost at each cut due to the width of the saw blade?
Admin
That's "pints" to old farts like me.
(Real pints, mind, not yer (bad word)y little American ones.)
aptent: 3rd person plural present indicative of the hypothetical French verb apter, "to be apt", j'apte, tu aptes, il/elle/on apte, nous aptons, vous aptez, ils/elles aptent, rarely used outside the 3rd person forms.
Admin
"So who's taking into account the ~1/8" lost at each cut due to the width of the saw blade?"
Ah--I had forgotten about that. Okay, here's my modified code which accounts for the width of the saw blade, again not tested:
using System.Collections.Generic; using System;
namespace WTF_BYOC_AvoidTheSplice { public class BoardCalculator { decimal BladeWidth{ get; set; } Dictionary<decimal, int> BoardQuantities { get; set; } ///
}
Admin
This seems to me to be the "greedy algorithm", if you leave out lengths lost to cuts/miters.
Suppose you have a number of files to copy to CDs. To minimize the number of CDs: Iterate: -- Insert a Cd. Pick the largest file (that is not already copied) that will fit on the remaining space of the cd and put it on the CD. Repeat until the CD is full ,or none of the files left will fit on the CD.
Boards are like files; and walls are like CDs. The difference is that you cut the boards to fit and put the remainder back into your pile.
Start with a pile of an infinite number of 8' and 16' boards. Iterate: -- pick the longest bare wall section. If possible, choose from your pile the shortest board that is (same length as, or longer than) the bare wall section. Trim the board to fit, return the remainder to the pile. Otherwise, choose the longest board that will fit into the space (that is, if the space is 9', you choose an 8' board, not a 16' board).
That minimizes the number of boards. If instead, you want to minimize the number of splices, then you change the above to say "Otherwise, choose a 16' board".
Admin
Admin
Since when were Imperial measurements referred to as US measurements? I don't recall the USA inventing them, or ever admitting to having an empire.
Admin
Sounds like a lazy but functional carpenter.
People should get extra points for using a functional language with lazy evaluation (e.g. Haskell) :-P
Cheers,
Daniel
Admin
Here's a quick-and-dirty solution using a simple algorithm without much optimization:
http://pastebin.com/f564a4a16
It is unit-less, and works with decimals.
The second step fails to consider that the stated length of the bought board is not likely to be exactly the length of the cut you want to make for the wall.
And, related to the 1/8" or so missing due to the kerf of the saw blade, also consider that most of these cuts will be on a miter - for corners and splices. There will be a number of little triangular pieces left over that will could throw of the calculation.
Now, back to real work...
Admin
I have only browsed your code, but I'm guessing you have implemented a heuristic version. Does your program report 2 as the minimum for a set like {6, 6, 5, 5, 5, 3, 2}?
That is, {{6, 5, 5}, {6, 5, 3, 2}}. If it's a greedy algorithm it will report something like {{6, 6, 3}, {5, 5, 5}, {2}} which is not an optimal solution.
This is a known NP complete problem, so it's not a big deal: finding an optimal solution is difficult in general.
Admin
And don't forget to deduct the width of the saw blade whenever you make a cut. This is a quite common mistake.
Admin
"It's far more of a maths challenge than a coding challenge."
Actually, there is a question of optimality, which is interesting. Sure, you could write code that says for every separate measurement, get a single 16' length (or more if the length is greater than 16'). But for a given set of inputs, can you guarantee that your program will give you the measurements of the LEAST amount of moldings to purchase?
To make it even more interesting, what if for the "Hard" version, a 16' board costs $20, and an 8' board costs $12 (or whatever)? Then making your program find the optimal COST becomes slightly more tricky!
DaveE
Admin
You've got it exactly backwards. The long boards are more expensive per foot because of the need of having high quality pieces. A given supply of raw lumber will produce more total footage of 8' boards than 16' boards.
(Note: I'm looking at the costs at the builder level, not the DIY level--I used to work for a cabinet manufacturer.)
Admin
Admin
TRWTF is that the US still uses feet and inches instead of what makes much more sense and is therefore used by the rest of the world.
Admin
A couple people mentioned miter cuts. Having just reno'd my basement and added all the trim, here's the complication:
When you measure the door, the measurements around the frame are the inside measurements of the cuts - the length needed for it will actually be longer - to be precise, the height of the trim longer, for each miter that is needed.
Consider around a door, the two vertical pieces each have one miter, while the top horizontal piece has two miters:
|\ ______/ /| | \ ______ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | door | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
so your algorithm should account for that.
You'll have the same issue with baseboard for bevel cuts, though only based on the thickness: in an inside corner, it's fine, but for an outside corner, you have to add the thickness of the board to the length.
Also, typically 'casing' is used around doors/windows, while 'baseboard' is used along the floor. The only real difference is (especially with MDF) the bottom of the baseboard (against the floor) is typically unfinished and/or has a sharper edge, while on casing, it will be finished/primed, and typically have a rounded edge.
So your algorithm should account for the difference between the two types of material.
Admin
Damn proportional fonts...
Admin
You know what a contractor would do? Just take some more boards, and when he needs a particular length, just go through a pile of offcuts and find the most fitting one.
Admin
To make things interesting, keep in mind that each cut is going to result in 1/8" of wasted material from the saw blade's "kerf". (The amount of wood removed by the saw blade during the cut)
Each time you make a cut you are going to loose 1/8" of the remaining board, so if you make 8 cuts in a 16' board you only end up able to use 15' 11" of the board.
Captcha: bene - Molto Bene!
Admin
easy version in Python: (no time for anything longer, and not including the saw blade width)
Admin
I always found it cheaper and more efficient to order the right amount of wood than to spend the time and money chalking, sanding, and pissing off customers with junk fees. If you build the cost to do it right into the price, the customer is none the wiser.
Admin
Admin
You could also save the time by instead of using 45 degree miters, use plinth blocks at each corner to fancy it up a bit. The labor savings would probably cover the cost of the extra materials. Also I didn't see where windows were to be accounted for. The only rooms I have ever been in with no windows are on a cruise ship and in my office at work.
Admin
It's interesting to me that the "lazy" carpenter is the one doing all these splices.
Wouldn't it be considerably lazier to avoid splices? If your wall is longer than any of your already-cut scraps, just grab another 16-footer?
Admin
Without adding the complication of price, you also could define your ideal solution as the minimum number of splices, and the minimum amount of scrap (in inches of board).
Admin
In some respects using feet & inches actually makes more sense than going metric. Feet divide nicely by 2,3,4,6 which makes scaling something to 1/2, 1/3, or 1/4 of the original size easy, on the other hand, going to 1/10 is a bit of a bitch.
Admin
A good contractor would buy 4 x 12' boards and not bother cutting.
Admin
Haskell, not sure of its running time, not extensively tested (although it passes the example mentioned in the statement of the problem), doesn't account for cuts. But hey, I'm learning haskell so it was fun.
Admin
Should have put "(sort boards)" in calling fillBoards, otherwise when boards are specified in descending order it wastes a lot of wood.
Admin
Ok, Alex has officially made me feel stupid. I couldn't understand a word of this post...
Admin
Solution: Use cheap, white trim. Caulk the seams. Paint it all white.
No maths be needed. Arrrggghhh!
Admin
With the (sort boards) modification of my haskell, it does seem to give reasonable results for the hard case:
Admin
Depends on what kind of wood you're buying (and I don't mean high end hard-to-get). Often, a 16' length of unspliced stainable wood will be noticeably more than the cost of two 8' foot boards just because its harder to get a good quality long piece of unblemished wood...
Admin
Actually, you still might not have enough moulding because you failed to take into account the width of the moulding.
For example the door dimensions are the dimensions of the door jam, but when doing moulding you are going to join two pieces a the corner (hopefully your going to miter the corners, but it will apply even if you don't) and door mouldings are almost always laid flat, so you need to take into account the width of the moulding as <dimension> + 2(pythagorean theorem using moulding width for sides).
So, for example if the moulding is 3" wide and the jam is 32" then: 32+2(sqrt(3^2+3^2)) or 32+2*4.25 (<= note, rounded to nearest easy fraction)
so you moulding length needs to be ~40.5".
Admin
Crap... overanalyzed!
... and screwed that up... I added the length of the diagonal cut... which would not be correct... you simply need to add 2*[moulding width].
so for the example above it would be: 32+2*3.
Admin
Actually, an algorithm for calculating the optimal solution isn't usually too hard to come up with. But it is going to be slow, because it involves comparing all possible solutions. For instance, the travelling salesman problem has an easily understood algorithm that solves the problem, but the algorithm takes a long time to run and gets vastly slower as you add more input data.
In this case, I believe an accurate solution would be to calculate all combinations of wall lengths adding up to all combinations of under 8 and 16 feet, and then compare all these combinations for which is considered optimal. I think the constraints here suggest that "the fewest number of boards" would be considered optimal, but perhaps if the costs of 8 and 16 foot boards were known, the comparison would be total cost and possibly result in different outcomes in some cases.
Admin
I hang with a lot of Canadians.
They all still use Imperial measurements for woodworking anyway.
Admin
This is the "packing" problem in computer science, and can't be solved optimally without investigating every possible combination, which is exponential in the number of cases.
Admin
Yup, I can confirm this one. For whatever reason (perhaps something to do with where building supplies are produced?) we (Canadians) use metric for pretty much everything except construction.
We also use about a 50/50 mix of metric and imperial for recipes and wrench sizes just to keep things confusing.
I'd never really realized this before. As someone who has grown up using the metric system I always wondered what possible advantage having 12 inches in a foot gave, but I'd never put any serious thought into it, so thanks for the info.
Admin
I wrote a python version that assumes longer boards are cheaper. It also makes sure you don't buy a board that is way too long for the project. Example: buying a 16 foot board for 5 inches needed when you have 16 and eight to choose from.
Admin
I can't really see a way to code the easy part without also coding the hard bits.
Easy = only 16' boards Say you need a 10' piece You need to store the remaining 6' piece somewhere The next piece you need, you check if you can supply it with either the single 6' piece you have or with one of your infinite supply of 16' pieces.
So even in the easy option, you'd need to find the best possible fit from a list of available lengths, some of which were in limited supply and some of which were available in infinite amounts. It seems to me that the only real difference in the three tiers is the initial state of this list.
Admin
I found a Wikipedia page about this problem: http://en.wikipedia.org/wiki/Cutting_stock_problem
Admin
That sounds like a linear optimisation problem to me. There are programs where you can enter such problems and they solve it. I don't like to do things that even computers can solve. I want to do things that computers cannot (yet) do and teach them to the computer. ;)
Admin
10 if (not trimmed) hire carpenter 20 if (screwed up) hire lawyer.
100 goto 10
Admin
Admin
I once saw an RFP to solve this problem in 3D -- that is, the pallet packing problem. Given fixed dimensions of 3d space you can use atop each pallet, the algorithm must take a collection of arbitrarily sized (and shaped) items and arrange them onto the least number of pallets where each load is physically possible to pack, supports itself without an outer container, and has a sufficiently low center of gravity.
Admin
If you hire a carpenter with sufficient skill you can't see the join when she splices two boards together. I doubt she would get away with door and window casings but the skirting boards are excellent.
Admin
In practice, there is another constraint you failed to mention; you want to start with the longest piece first and work your way down so that a damaged or wrongly cut piece can be used for something shorter. This constraint results in the usual algorithm that people actually use:
I know this is not ideal, but carpenters don't have time to write code. :)
Admin
This is the same as the classic "bin problem":
http://en.wikipedia.org/wiki/Bin_packing_problem
The analogy is that the bin size represents the max length of an uncut board (say, 16 feet if you've got a big truck). A naive solution works like this:
// array of boards we'll need. Each element represents one uncut board. The value of each element is the number of inches of board remaining. int[] Boards
// Spans that we need to cut. int[] Spans
while(Spans.Count>0) { int thisSpan=Spans[0];
for(int i=0;i<boards.Count;i++) { if(boards[i]>=thisSpan) { boards[i]-=thisSpan; continue; } // add a new board 16 feet long boards[boards.length]=16*12; }
}
Now, the number of elements in Boards is the number of 16 foot boards you'll need.
This isn't a perfect solution, but it's pretty darn close and is correct for almost every situation.
Admin
You could solve this problem using an evolutionary algorithm. There's no guarantee it'll return the optimal result (but usually will) and will run in unit time.
Start by taking any initial valid layout of cuts, do an arbitary number of mutations, keeping track of the best result found so far. The mutation could simply be to move a cut to another board.
I'll give it a go and post my solution later.