Actions

Difference between revisions of "Arrange timed code.cpp"

From Just in Time

(Created page with "//// Copyright (c) 2013 Danny Havenith //// Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.or...")
 
Line 1: Line 1:
//// Copyright (c) 2013 Danny Havenith //// Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) //
+
<syntaxhighlight lang="cpp">
 +
//
 +
// Copyright (c) 2013 Danny Havenith
 +
//
 +
// Distributed under the Boost Software License, Version 1.0. (See accompanying
 +
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 +
//
  
#include <iostream> #include <string> #include <map> #include <vector> #include <algorithm> #include <limits> #include <boost/foreach.hpp>
+
#include <iostream>
 +
#include <string>
 +
#include <map>
 +
#include <vector>
 +
#include <algorithm>
 +
#include <limits>
 +
#include <boost/foreach.hpp>
  
using namespace std; /// Simple struct that can be used as an input to describe blocks of assembly instructions with jumps and labels struct labelinfo { string label; string jumpto; };
+
using namespace std;
 +
/// Simple struct that can be used as an input to describe blocks of assembly instructions with jumps and labels
 +
struct labelinfo {
 +
    string label;
 +
    string jumpto;
 +
};
  
/// a contiguous block of assembly instructions. /// This structure holds information about the size of the block, /// all relative jumps that emanate from this block and all labes that /// are defined in this block. struct block { typedef map<string, int> labelmap; int
+
/// a contiguous block of assembly instructions.
 +
/// This structure holds information about the size of the block,
 +
/// all relative jumps that emanate from this block and all labes that
 +
/// are defined in this block.
 +
struct block
 +
{
 +
    typedef map<string, int> labelmap;
 +
    int     size;
 +
    string  name;
 +
    labelmap labels;
 +
    labelmap jumps;
  
string
+
    bool operator<( const block &other) const
 +
    {
 +
        return name < other.name;
 +
    }
 +
};
  
labelmap labels; labelmap jumps;
+
/// Parse labelinfo structs and create disjunct blocks.
 +
/// This function will traverse the range of labelinfos and create blocks on-the-go.
 +
/// The last statement of a block is recognized by the label "END", whenever this label is encountered all
 +
/// statements so far will be combined in one block and this block will be appended to the result.
 +
vector<block> parse_blocks( labelinfo *begin, labelinfo *end)
 +
{
 +
    vector<block> result;
  
bool operator<( const block &other) const { return name < other.name; } };
+
    int current_line = 0;
 +
    block current_block;
 +
    while (begin != end)
 +
    {
 +
        if (begin->label == "END")
 +
        {
 +
            current_block.size = current_line + 1;
 +
            result.push_back( current_block);
 +
            current_line = 0;
 +
            current_block = block();
 +
        }
 +
        else
 +
        {
 +
            if (!begin->label.empty())
 +
            {
 +
                if (current_line == 0) current_block.name = begin->label;
 +
                current_block.labels[begin->label] = current_line;
 +
            }
 +
            if (!begin->jumpto.empty())
 +
            {
 +
                current_block.jumps[begin->jumpto] = current_line;
 +
            }
 +
            ++current_line;
 +
        }
 +
        ++begin;
 +
    }
 +
    return result;
 +
}
  
/// Parse labelinfo structs and create disjunct blocks. /// This function will traverse the range of labelinfos and create blocks on-the-go. /// The last statement of a block is recognized by the label "END", whenever this label is encountered all /// statements so far will be combined in one block and this block will be appended to the result. vector<block> parse_blocks( labelinfo *begin, labelinfo *end) { vector<block> result;
+
/// Given a sequence of blocks, determine the absolute addresses of the labels that
 +
/// appear in each block.
 +
block::labelmap map_labels( const vector<block>& blocks)
 +
{
 +
    block::labelmap label_addresses;
  
int current_line = 0; block current_block; while (begin != end) { if (begin->label == "END") { current_block.size = current_line + 1; result.push_back( current_block); current_line = 0; current_block = block(); } else { if (!begin->label.empty()) { if (current_line == 0) current_block.name = begin->label; current_block.labels[begin->label] = current_line; } if (!begin->jumpto.empty()) { current_block.jumps[begin->jumpto] = current_line; } ++current_line; } ++begin; } return result; }
+
    // determine absolute labels
 +
    int current_block_startaddress = 0;
 +
    BOOST_FOREACH( const block &b, blocks)
 +
    {
 +
        BOOST_FOREACH( const block::labelmap::value_type &label, b.labels)
 +
        {
 +
            label_addresses[label.first] = label.second
 +
                    + current_block_startaddress;
 +
        }
 +
        current_block_startaddress += b.size;
 +
    }
  
/// Given a sequence of blocks, determine the absolute addresses of the labels that /// appear in each block. block::labelmap map_labels( const vector<block>& blocks) { block::labelmap label_addresses;
+
    return label_addresses;
 +
}
  
// determine absolute labels int current_block_startaddress = 0; BOOST_FOREACH( const block &b, blocks) { BOOST_FOREACH( const block::labelmap::value_type &label, b.labels) { label_addresses[label.first] = label.second + current_block_startaddress; } current_block_startaddress += b.size; }
+
/// Determine whether a sequence of blocks matches the criterium of valid jumps.
 +
/// This criterium is matched if all jumps are close enough to their destination labels.
 +
/// Close enough, in this case, means that the offset between jump and destination must fall within [-63,64]
 +
/// This function is faster than the calculate_fit() function because it can terminate immediately if it finds a jump
 +
/// that does not qualify.
 +
bool is_fit( const vector<block> &blocks)
 +
{
 +
    block::labelmap label_addresses = map_labels(blocks);
  
return label_addresses; }
+
    // see if all jumps are in range.
 +
    int current_block_startaddress = 0;
 +
    BOOST_FOREACH( const block &b, blocks)
 +
    {
 +
        BOOST_FOREACH( const block::labelmap::value_type &jump, b.jumps)
 +
        {
 +
            int offset = label_addresses[jump.first] - (jump.second + current_block_startaddress);
 +
            if (offset > 64 || offset < -63) return false;
 +
        }
 +
        current_block_startaddress += b.size;
 +
    }
  
/// Determine whether a sequence of blocks matches the criterium of valid jumps. /// This criterium is matched if all jumps are close enough to their destination labels. /// Close enough, in this case, means that the offset between jump and destination must fall within [-63,64] /// This function is faster than the calculate_fit() function because it can terminate immediately if it finds a jump /// that does not qualify. bool is_fit( const vector<block> &blocks) { block::labelmap label_addresses = map_labels(blocks);
+
    return true;
 +
}
  
// see if all jumps are in range. int current_block_startaddress = 0; BOOST_FOREACH( const block &b, blocks) { BOOST_FOREACH( const block::labelmap::value_type &jump, b.jumps) { int offset = label_addresses[jump.first] - (jump.second + current_block_startaddress); if (offset > 64 || offset < -63) return false; } current_block_startaddress += b.size; }
+
/// This is largely a copy of the is_fit() function with some changes. Instead of returning a fit/not-fit boolean,
 +
/// this function returns a score that is calculated as the maximum (absolute) jump distance.
 +
/// This function is slightly less efficient than that is_fit() function, because it needss to complete the
 +
/// calculation, even if the score is higher than the fitness criterium.
 +
int calculate_fit( const vector<block> &blocks)
 +
{
 +
    block::labelmap label_addresses = map_labels( blocks);
  
return true; }
+
    // calculate the maximum jump offset in this sequence of blocks.
 +
    int max_offset = 0;
 +
    int current_block_startaddress = 0;
 +
    BOOST_FOREACH( const block &b, blocks)
 +
    {
 +
        BOOST_FOREACH( const block::labelmap::value_type &jump, b.jumps)
 +
        {
 +
            int offset = label_addresses[jump.first] - (jump.second + current_block_startaddress);
 +
            if (offset > max_offset) max_offset = offset;
 +
            if (-offset > max_offset) max_offset = -offset;
 +
        }
 +
        current_block_startaddress += b.size;
 +
    }
  
/// This is largely a copy of the is_fit() function with some changes. Instead of returning a fit/not-fit boolean, /// this function returns a score that is calculated as the maximum (absolute) jump distance. /// This function is slightly less efficient than that is_fit() function, because it needss to complete the /// calculation, even if the score is higher than the fitness criterium. int calculate_fit( const vector<block> &blocks) { block::labelmap label_addresses = map_labels( blocks);
+
    return max_offset;
 +
}
  
// calculate the maximum jump offset in this sequence of blocks. int max_offset = 0; int current_block_startaddress = 0; BOOST_FOREACH( const block &b, blocks) { BOOST_FOREACH( const block::labelmap::value_type &jump, b.jumps) { int offset = label_addresses[jump.first] - (jump.second + current_block_startaddress); if (offset > max_offset) max_offset = offset; if (-offset > max_offset) max_offset = -offset; } current_block_startaddress += b.size; }
+
/// Description of the code blocks. This was created with some spreadsheet magic from the original code spreadsheet
 +
/// because I was too lazy to implement input text parsing.
 +
labelinfo labels[] = {
 +
{ "M2", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "H1"},
 +
{ "", ""},
 +
{ "", "L16"},
 +
{ "", ""},
 +
{ "L9", ""},
 +
{ "", ""},
 +
{ "L5", ""},
 +
{ "", ""},
 +
{ "", "L1"},
 +
{ "", ""},
 +
{ "", "M1"},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "L4"},
 +
{ "", ""},
 +
{ "L12", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "END", ""},
 +
{ "L1", ""},
 +
{ "", "M2"},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "L8"},
 +
{ "", ""},
 +
{ "L15", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "END", ""},
 +
{ "L10", ""},
 +
{ "", "M3"},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "L12"},
 +
{ "", ""},
 +
{ "L4", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "END", ""},
 +
{ "M4", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "H1"},
 +
{ "", ""},
 +
{ "", "L9"},
 +
{ "", ""},
 +
{ "L16", ""},
 +
{ "", ""},
 +
{ "L13", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "L10"},
 +
{ "", ""},
 +
{ "", "M4"},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "L15"},
 +
{ "", ""},
 +
{ "L8", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "END", ""},
 +
{ "M1", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "H2"},
 +
{ "", ""},
 +
{ "", "L9"},
 +
{ "", ""},
 +
{ "END", ""},
 +
{ "M3", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", "H2"},
 +
{ "", ""},
 +
{ "", "L16"},
 +
{ "", ""},
 +
{ "END", ""},
 +
{ "H1", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "END", ""},
 +
{ "H2", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "", ""},
 +
{ "END", ""},
 +
};
  
return max_offset; }
+
/// Print out the optimum sequence of code blocks (=with minimum max jump distance).
 +
/// This function will simply iterate over all 40K permutations of 8 blocks and calculate the score for each
 +
/// permutation.
 +
int main()
 +
{
 +
    vector<block> blocks = parse_blocks( labels, labels + sizeof labels/sizeof labels[0] );
 +
    sort( blocks.begin(), blocks.end());
  
/// Description of the code blocks. This was created with some spreadsheet magic from the original code spreadsheet /// because I was too lazy to implement input text parsing. labelinfo labels[] = { { "M2", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", "H1"}, { "", ""}, { "", "L16"}, { "", ""}, { "L9", ""}, { "", ""}, { "L5", ""}, { "", ""}, { "", "L1"}, { "", ""}, { "", "M1"}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", "L4"}, { "", ""}, { "L12", ""}, { "", ""}, { "", ""}, { "END", ""}, { "L1", ""}, { "", "M2"}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", "L8"}, { "", ""}, { "L15", ""}, { "", ""}, { "", ""}, { "END", ""}, { "L10", ""}, { "", "M3"}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", "L12"}, { "", ""}, { "L4", ""}, { "", ""}, { "", ""}, { "END", ""}, { "M4", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", "H1"}, { "", ""}, { "", "L9"}, { "", ""}, { "L16", ""}, { "", ""}, { "L13", ""}, { "", ""}, { "", ""}, { "", "L10"}, { "", ""}, { "", "M4"}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", "L15"}, { "", ""}, { "L8", ""}, { "", ""}, { "", ""}, { "END", ""}, { "M1", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", "H2"}, { "", ""}, { "", "L9"}, { "", ""}, { "END", ""}, { "M3", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "", "H2"}, { "", ""}, { "", "L16"}, { "", ""}, { "END", ""}, { "H1", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "END", ""}, { "H2", ""}, { "", ""}, { "", ""}, { "", ""}, { "", ""}, { "END", ""}, };
+
    BOOST_FOREACH( const block &b, blocks)
 +
    {
 +
        cout << b.name << "\n";
 +
    }
  
/// Print out the optimum sequence of code blocks (=with minimum max jump distance). /// This function will simply iterate over all 40K permutations of 8 blocks and calculate the score for each /// permutation. int main() { vector<block> blocks = parse_blocks( labels, labels + sizeof labels/sizeof labels[0] ); sort( blocks.begin(), blocks.end());
+
    vector<block> best_blocks;
 +
    int min_offset = numeric_limits<int>::max();
 +
    do
 +
    {
 +
        int new_offset = calculate_fit( blocks);
 +
        if (new_offset < min_offset)
 +
        {
 +
            best_blocks = blocks;
 +
            min_offset = new_offset;
 +
            cout << min_offset << ", ";
 +
        }
 +
    } while (next_permutation( blocks.begin(), blocks.end()));
  
BOOST_FOREACH( const block &b, blocks) { cout << b.name << "\n"; }
 
  
vector<block> best_blocks; int min_offset = numeric_limits<int>::max(); do { int new_offset = calculate_fit( blocks); if (new_offset < min_offset) { best_blocks = blocks; min_offset = new_offset; cout << min_offset << ", "; } } while (next_permutation( blocks.begin(), blocks.end()));
+
    if (is_fit(best_blocks))
 +
    {
 +
        cout << "\nSuccess:\n";
 +
    }
 +
    else
 +
    {
 +
        cout << "\nNothing\n";
 +
    }
  
if (is_fit(best_blocks)) { cout << "\nSuccess:\n"; } else { cout << "\nNothing\n"; }
+
    BOOST_FOREACH( const block &b, best_blocks)
 +
    {
 +
        cout << b.name << "\n";
 +
    }
  
BOOST_FOREACH( const block &b, best_blocks) { cout << b.name << "\n"; }
+
    return 0;
 +
}
  
return 0; }
+
</syntaxhighlight>

Revision as of 16:38, 12 February 2013

//
// Copyright (c) 2013 Danny Havenith
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <limits>
#include <boost/foreach.hpp>

using namespace std;
/// Simple struct that can be used as an input to describe blocks of assembly instructions with jumps and labels
struct labelinfo {
    string label;
    string jumpto;
};

/// a contiguous block of assembly instructions.
/// This structure holds information about the size of the block,
/// all relative jumps that emanate from this block and all labes that
/// are defined in this block.
struct block
{
    typedef map<string, int> labelmap;
    int      size;
    string   name;
    labelmap labels;
    labelmap jumps;

    bool operator<( const block &other) const
    {
        return name < other.name;
    }
};

/// Parse labelinfo structs and create disjunct blocks.
/// This function will traverse the range of labelinfos and create blocks on-the-go.
/// The last statement of a block is recognized by the label "END", whenever this label is encountered all
/// statements so far will be combined in one block and this block will be appended to the result.
vector<block> parse_blocks( labelinfo *begin, labelinfo *end)
{
    vector<block> result;

    int current_line = 0;
    block current_block;
    while (begin != end)
    {
        if (begin->label == "END")
        {
            current_block.size = current_line + 1;
            result.push_back( current_block);
            current_line = 0;
            current_block = block();
        }
        else
        {
            if (!begin->label.empty())
            {
                if (current_line == 0) current_block.name = begin->label;
                current_block.labels[begin->label] = current_line;
            }
            if (!begin->jumpto.empty())
            {
                current_block.jumps[begin->jumpto] = current_line;
            }
            ++current_line;
        }
        ++begin;
    }
    return result;
}

/// Given a sequence of blocks, determine the absolute addresses of the labels that
/// appear in each block.
block::labelmap map_labels( const vector<block>& blocks)
{
    block::labelmap label_addresses;

    // determine absolute labels
    int current_block_startaddress = 0;
    BOOST_FOREACH( const block &b, blocks)
    {
        BOOST_FOREACH( const block::labelmap::value_type &label, b.labels)
        {
            label_addresses[label.first] = label.second
                    + current_block_startaddress;
        }
        current_block_startaddress += b.size;
    }

    return label_addresses;
}

/// Determine whether a sequence of blocks matches the criterium of valid jumps.
/// This criterium is matched if all jumps are close enough to their destination labels.
/// Close enough, in this case, means that the offset between jump and destination must fall within [-63,64]
/// This function is faster than the calculate_fit() function because it can terminate immediately if it finds a jump
/// that does not qualify.
bool is_fit( const vector<block> &blocks)
{
    block::labelmap label_addresses = map_labels(blocks);

    // see if all jumps are in range.
    int current_block_startaddress = 0;
    BOOST_FOREACH( const block &b, blocks)
    {
        BOOST_FOREACH( const block::labelmap::value_type &jump, b.jumps)
         {
            int offset = label_addresses[jump.first] - (jump.second + current_block_startaddress);
            if (offset > 64 || offset < -63) return false;
        }
        current_block_startaddress += b.size;
    }

    return true;
}

/// This is largely a copy of the is_fit() function with some changes. Instead of returning a fit/not-fit boolean,
/// this function returns a score that is calculated as the maximum (absolute) jump distance.
/// This function is slightly less efficient than that is_fit() function, because it needss to complete the
/// calculation, even if the score is higher than the fitness criterium.
int calculate_fit( const vector<block> &blocks)
{
    block::labelmap label_addresses = map_labels( blocks);

    // calculate the maximum jump offset in this sequence of blocks.
    int max_offset = 0;
    int current_block_startaddress = 0;
    BOOST_FOREACH( const block &b, blocks)
    {
        BOOST_FOREACH( const block::labelmap::value_type &jump, b.jumps)
        {
            int offset = label_addresses[jump.first] - (jump.second + current_block_startaddress);
            if (offset > max_offset) max_offset = offset;
            if (-offset > max_offset) max_offset = -offset;
        }
        current_block_startaddress += b.size;
    }

    return max_offset;
}

/// Description of the code blocks. This was created with some spreadsheet magic from the original code spreadsheet
/// because I was too lazy to implement input text parsing.
labelinfo labels[] = {
{ "M2", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", "H1"},
{ "", ""},
{ "", "L16"},
{ "", ""},
{ "L9", ""},
{ "", ""},
{ "L5", ""},
{ "", ""},
{ "", "L1"},
{ "", ""},
{ "", "M1"},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", "L4"},
{ "", ""},
{ "L12", ""},
{ "", ""},
{ "", ""},
{ "END", ""},
{ "L1", ""},
{ "", "M2"},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", "L8"},
{ "", ""},
{ "L15", ""},
{ "", ""},
{ "", ""},
{ "END", ""},
{ "L10", ""},
{ "", "M3"},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", "L12"},
{ "", ""},
{ "L4", ""},
{ "", ""},
{ "", ""},
{ "END", ""},
{ "M4", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", "H1"},
{ "", ""},
{ "", "L9"},
{ "", ""},
{ "L16", ""},
{ "", ""},
{ "L13", ""},
{ "", ""},
{ "", ""},
{ "", "L10"},
{ "", ""},
{ "", "M4"},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", "L15"},
{ "", ""},
{ "L8", ""},
{ "", ""},
{ "", ""},
{ "END", ""},
{ "M1", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", "H2"},
{ "", ""},
{ "", "L9"},
{ "", ""},
{ "END", ""},
{ "M3", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", "H2"},
{ "", ""},
{ "", "L16"},
{ "", ""},
{ "END", ""},
{ "H1", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "END", ""},
{ "H2", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "", ""},
{ "END", ""},
};

/// Print out the optimum sequence of code blocks (=with minimum max jump distance).
/// This function will simply iterate over all 40K permutations of 8 blocks and calculate the score for each
/// permutation.
int main()
{
    vector<block> blocks = parse_blocks( labels, labels + sizeof labels/sizeof labels[0] );
    sort( blocks.begin(), blocks.end());

    BOOST_FOREACH( const block &b, blocks)
    {
        cout << b.name << "\n";
    }

    vector<block> best_blocks;
    int min_offset = numeric_limits<int>::max();
    do
    {
        int new_offset = calculate_fit( blocks);
        if (new_offset < min_offset)
        {
            best_blocks = blocks;
            min_offset = new_offset;
            cout << min_offset << ", ";
        }
    } while (next_permutation( blocks.begin(), blocks.end()));


    if (is_fit(best_blocks))
    {
        cout << "\nSuccess:\n";
    }
    else
    {
        cout << "\nNothing\n";
    }

    BOOST_FOREACH( const block &b, best_blocks)
    {
        cout << b.name << "\n";
    }

    return 0;
}