Archive for August 2006
On 08/11/06 (mm/dd/yy :) the wheel was reinvented:
int start = 3; std::list<int> path = listiniter(start); std::list<int> dirs = listiniter<int>(4, 5); std::transform (dirs.begin(), dirs.end(), path.begin(), std::back_inserter(path), std::plus<int>()); std::list<int>::iterator i = path.begin(); assert(*i==3); ++i; assert(*i==7); ++i; assert(*i==12); ++i; assert(i==path.end());
Boost rocks.
#define PUSHER(z, n, data) data .push_back(x##n);
#define LISTINITER(z, n, data) \
template<class T> \
inline std::list<T> \
listiniter(BOOST_PP_ENUM_PARAMS(n, T x)) \
{ \
std::list<T> ret; \
BOOST_PP_REPEAT(n, PUSHER, ret) \
return ret; \
}
BOOST_PP_REPEAT(31, LISTINITER, _)
Though it can be implemented in c++ lightly.
#include <list>
#include <functional>
...
template<class T, class C, class F>
std::list<T>
path_accum(std::list<T> start,
C comb,
std::list<F> list)
{
while(list.size()>0)
{
start.push_back(comb(start.back(),list.front()));
list.pop_front();
}
return start;
}
...
std::list<int> start;
start.push_back(3);
std::list<int> list;
list.push_back(4);
list.push_back(5);
std::list<int> ret = path_accum(start,std::plus<int>,list);
std::list<int>::const_iterator i=ret.begin();
assert(*i==3); ++i;
assert(*i==7); ++i;
assert(*i==12); ++i;
assert(i==ret.end());
One can use previous 'accum to compute paths, when there are move-vectors in list. In this case you can easily inject the lambda used before into the main algorithm as shown below.
(defun path-accum (start comb list)
(if (null list)
start
(path-accum (append start
(list (funcall comb
(car (last start))
(car list))))
comb
(cdr list))))
(path-accum '(3) '+ '(4 5))
=> (3 7 12)
Nice.
(defun accum (start comb list)
(if (null list)
start
(accum (funcall comb start (car list))
comb
(cdr list))))
(accum '(3)
(lambda (start new)
(append start
(list (+ new
(car (last start))))))
'(4 5))
=> (3 7 12)