Hatena::ブログ(Diary)

yutoppの日記

2011-12-13

brainf*cked

むしゃくしゃして書いた。

(12/22 ちょいと書き換え)

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

namespace brainfuck
{
	namespace detail
	{
		struct default_dictionary
		{
			typedef char char_type;
			static const int max_length = 1;

			static const char* increment_pointer()
			{
				return ">";
			}

			static const char* decrement_pointer()
			{
				return "<";
			}

			static const char* repeat()
			{
				return "[";
			}

			static const char* loop()
			{
				return "]";
			}

			static const char* increment_value()
			{
				return "+";
			}

			static const char* decrement_value()
			{
				return "-";
			}

			static const char* input()
			{
				return ",";
			}

			static const char* output()
			{
				return ".";
			}
		};
	}

	template<typename DictT>
	struct dictionary_traits
	{
		typedef typename DictT::char_type char_type; 
		static const int max_length = DictT::max_length;

		static const char_type* increment_pointer()
		{
			return DictT::increment_pointer();
		}

		static const char_type* decrement_pointer()
		{
			return DictT::decrement_pointer();
		}

		static const char_type* repeat()
		{
			return DictT::repeat();
		}

		static const char_type* loop()
		{
			return DictT::loop();
		}

		static const char_type* increment_value()
		{
			return DictT::increment_value();
		}

		static const char_type* decrement_value()
		{
			return DictT::decrement_value();
		}

		static const char_type* input()
		{
			return DictT::input();
		}

		static const char_type* output()
		{
			return DictT::output();
		}
	};

	template<typename IterT, typename DictT = detail::default_dictionary, typename ElemT = unsigned char, std::size_t MemLimit = 30000>
	class interpreter
	{
		typedef DictT dictinary_type;
		typedef ElemT value_type;
		typedef typename std::vector<value_type> container;
		typedef typename container::iterator iterator;
		struct order
		{
			typedef int type;
			enum {
				finish = 0,
				increment_pointer,
				decrement_pointer,
				repeat,
				loop,
				increment_value,
				decrement_value,
				input,
				output,
				nop
			};
		};

	public:
		interpreter( const IterT& begin, const IterT& end )
			: memory_( MemLimit )
			, ptr_( memory_.begin() )
			, begin_( begin )
			, end_( end )
		{}

		bool run()
		{
			return eval( begin_, end_ );
		}

	private:
		bool eval( IterT& it, const IterT& end )
		{
			while( it != end ) {
				const auto order = get_token( it, end );
				const auto& type = order.first;
				if ( type == order::finish )
					break;

				if ( type == order::increment_pointer ) {
					++ptr_;
					if ( ptr_ == memory_.cend() )
						return false;

				} else if ( type == order::decrement_pointer ) {
					if ( ptr_ == memory_.cbegin() )
						return false;
					--ptr_;

				} else if ( type == order::repeat ) {
					if ( *ptr_ ) {
						auto tmp = it;
						std::advance( tmp, order.second );
						if ( !eval( tmp, end ) )
							return false;
					
					} else {
						int depth = 0;
						for(;;) {
							const auto order = get_token( it, end );
							if ( order.first == order::finish )
								return false;

							std::advance( it, order.second );
							if ( order.first == order::loop ) {
								--depth;
								if ( depth == 0)
									break;
							} else if ( order.first == order::repeat ) {
								++depth;
							}
						}
					}
					continue;	

				} else if ( type == order::loop ) {
					return true;

				} else if ( type == order::increment_value ) {
					++(*ptr_);

				} else if ( type == order::decrement_value ) {
					--(*ptr_);

				} else if ( type == order::input ) {
					std::cout << *ptr_ ;

				} else if ( type == order::output ) {
					std::cin >> *ptr_;

				}/* else {
					// nop
				}*/

				std::advance( it, order.second );
			}

			return true;
		}

		std::pair<typename order::type, std::size_t> get_token( const IterT& begin, const IterT& end ) const
		{
			typedef dictionary_traits<dictinary_type> dic_type;

			std::basic_string<typename std::iterator_traits<IterT>::value_type> order;
			std::size_t retry = 0;
			for( auto it=begin; it!=end; ++it, ++retry ) {
				if ( retry >= dic_type::max_length )
					return std::make_pair( order::nop, 1 );

				order += *it;

				if ( order == dic_type::increment_pointer() ) {
					return std::make_pair( order::increment_pointer, order.size() );

				} else if ( order == dic_type::decrement_pointer() ) {
					return std::make_pair( order::decrement_pointer, order.size() );

				} else if ( order == dic_type::repeat() ) {
					return std::make_pair( order::repeat, order.size() );

				} else if ( order == dic_type::loop() ) {
					return std::make_pair( order::loop, order.size() );

				} else if ( order == dic_type::increment_value() ) {
					return std::make_pair( order::increment_value, order.size() );

				} else if ( order == dic_type::decrement_value() ) {
					return std::make_pair( order::decrement_value, order.size() );

				} else if ( order == dic_type::output() ) {
					return std::make_pair( order::input, order.size() );

				} else if ( order == dic_type::input() ) {
					return std::make_pair( order::output, order.size() );
				}
			}

			return std::make_pair( order::finish, 0 );
		}

		container memory_;
		iterator ptr_;
		IterT begin_, end_;
	};

	template<typename IterT>
	bool parse( IterT& begin, IterT end )
	{
		auto bf = interpreter<IterT>( begin, end );
		return bf.run();
	}

	template<typename DictT, typename IterT>
	bool parse( IterT& begin, IterT end )
	{
		auto bf = interpreter<IterT, DictT>( begin, end );
		return bf.run();
	}
}


struct honmono
{
	typedef wchar_t char_type;
	static const int max_length = 6;

	static const char_type* increment_pointer()
	{
		return L"ピャ";
	}

	static const char_type* decrement_pointer()
	{
		return L"<";
	}

	static const char_type* repeat()
	{
		return L"(^q^)";
	}

	static const char_type* loop()
	{
		return L"!";
	}

	static const char_type* increment_value()
	{
		return L"ァ";
	}

	static const char_type* decrement_value()
	{
		return L"-";
	}

	static const char_type* input()
	{
		return L",";
	}

	static const char_type* output()
	{
		return L"ウンバボ";
	}
};



/*------
  main
------*/
int main() {
	const std::wstring s
		= L"ピャァァァァァァァァァ(^q^)<ァァァァァァァァピャ-!<ウンバボ" \
		L"ピャァァァァァァァ(^q^)<ァァァァピャ-!<ァウンバボァァァァァァァ" \
		L"ウンバボウンバボァァァウンバボ(^q^)-!ピャァァァァァァァァ" \
		L"(^q^)<ァァァァピャ-!<ウンバボピャァァァァァァァァァァァ" \
		L"(^q^)<ァァァァァピャ-!<ウンバボピャァァァァァァァァ(^q^)<ァァァピャ-!" \
		L"<ウンバボァァァウンバボ------ウンバボ--------ウンバボ" \
		L"(^q^)-!ピャァァァァァァァァ(^q^)<ァァァァピャ-!<ァウンバボ" \
		L"(^q^)-!ァァァァァァァァァァウンバボ";

	const bool b = brainfuck::parse<honmono>( s.cbegin(), s.cend() );
	if ( !b )
		std::cout << " : error..." << std::endl;
}

結果

Hello World!

2011-08-13

個人的に知らなかった文法メモ 1

手元の紙にでも書いておけよレベルですが自分のことなので書いた紙をたぶん無くすためここにメモる。

関数全体を例外で囲える

コード

#include <iostream>
 
void foo() try
{
        throw "ぽーん";
}
catch(...)
{
        std::cout << "例外!" << std::endl;
}
 
int main()
{
        foo();
}

出力

例外!

なんということでしょう

プロトタイプ宣言になる

コード

#include <iostream>
 
struct hoge
{
        hoge( int = 0 ) {}
};
 
struct fuga
{
        fuga( hoge )
        {
                std::cout << "ctor!" << std::endl;
        }
};
 
int main()
{
        const int num = 5;
 
        fuga var_nano( hoge( num ) );
        fuga var_desu( hoge( 5 ) );
}

出力

ctor!

引数は括弧で囲めるらしいので

fuga var_nano( hoge( num ) );

fuga var_nano( hoge num );

となってしまいプロトタイプ宣言とみなされるため。
C++11なら

fuga var_nano{ hoge( num ) };

こう書けば万事解決っぽい。

2011-07-03

何か

テンプレートに渡せる型を振り分けたかったというか何と言うか・・・

#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>

template< typename T, typename U >
struct is_allowed
        : public boost::is_same<
                typename boost::remove_cv<T>, 
                typename boost::remove_cv<typename U::group_type> >
{};


struct group_0;
struct group_1;

struct A{
        typedef group_0 group_type;
};
 
struct B{
        typedef group_1 group_type;
};
 
 
 
struct policy {
        typedef group_0 allow_type;
};
 
template< typename Policy>
class caller {
        typedef typename Policy::allow_type allow_type;
 
public:
        template< typename T >
        void call() const {
                BOOST_STATIC_ASSERT( ( is_allowed<allow_type, T>::value ) );
        }
};
 
 
int main()
{
        caller<policy> c;
        c.call<A>();
        //c.call<B>();  //これは無理
}

Boost.PPでコムソート

長くなった!

コード
// コムソート - Boost.PPを添えて
// Wikipediaの例のまんま - http://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%A0%E3%82%BD%E3%83%BC%E3%83%88
 
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/replace.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/arithmetic/mul.hpp>
#include <boost/preprocessor/arithmetic/div.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/control/while.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/comparison/not_equal.hpp>
#include <boost/preprocessor/comparison/less.hpp>
#include <boost/preprocessor/comparison/greater.hpp>
 
#define PP_SEQ_SWAP( index_a, index_b, seq ) \
        BOOST_PP_SEQ_REPLACE( \
                BOOST_PP_SEQ_REPLACE( \
                        seq, \
                        index_a, \
                        BOOST_PP_SEQ_ELEM( index_b, seq ) \
                        ), \
                index_b, \
                BOOST_PP_SEQ_ELEM( index_a, seq ) \
                )
 
#define PP_SEQ_COMB_SORT_CALC_GAP( h ) \
        BOOST_PP_DIV( \
                BOOST_PP_MUL( \
                        h, \
                        10 \
                ), \
                13 \
        )
 
#define PP_SEQ_COMB_SORT_MAKE_TUPLE( seq, swaps, gap, is_last ) \
        ( \
                seq, \
                swaps, \
                gap, \
                is_last \
        )
 
#define PP_SEQ_COMB_SORT_GAP_CHECK( state ) \
        PP_SEQ_COMB_SORT_GAP_CHECK_D( \
                BOOST_PP_TUPLE_ELEM( 4, 0, state ), \
                BOOST_PP_TUPLE_ELEM( 4, 1, state ), \
                BOOST_PP_TUPLE_ELEM( 4, 2, state ) \
                )
 
#define PP_SEQ_COMB_SORT_GAP_CHECK_D( seq, swaps, gap ) \
        PP_SEQ_COMB_SORT_MAKE_TUPLE( \
                seq, \
                swaps, \
                BOOST_PP_IF( \
                        BOOST_PP_EQUAL( gap, 1 ), \
                        gap, PP_SEQ_COMB_SORT_CALC_GAP( gap ) \
                        ), \
                BOOST_PP_IF( \
                        BOOST_PP_EQUAL( gap, 1 ), \
                        1, 0 \
                        ) \
                )
 
#define PP_SEQ_COMB_SORT_CALC_GAP_FROM_SEQ( seq ) \
        PP_SEQ_COMB_SORT_CALC_GAP( BOOST_PP_SEQ_SIZE( seq ) )
 
 
#define PP_SEQ_COMB_SORT_SWAP( seq, swaps, gap, is_last, i ) \
        PP_SEQ_COMB_SORT_MAKE_TUPLE( \
                PP_SEQ_SWAP( i, BOOST_PP_ADD( i, gap ), seq ), \
                BOOST_PP_INC( swaps ), \
                gap, \
                is_last \
        )
 
#define PP_SEQ_COMB_SORT_SWAP_CHECK( seq, swaps, gap, is_last, i ) \
        BOOST_PP_IF( \
                BOOST_PP_GREATER( \
                        BOOST_PP_SEQ_ELEM( i, seq ), \
                        BOOST_PP_SEQ_ELEM( BOOST_PP_ADD( i, gap ), seq ) \
                        ), \
                PP_SEQ_COMB_SORT_SWAP( seq, swaps, gap, is_last, i ), \
                PP_SEQ_COMB_SORT_MAKE_TUPLE( seq, swaps, gap, is_last ) \
                )
 
#define PP_SEQ_COMB_SORT_SWAP_OP( unused, state ) \
        PP_SEQ_COMB_SORT_SWAP_OP_D( \
                d, \
                BOOST_PP_TUPLE_ELEM( 2, 0, state ), \
                BOOST_PP_TUPLE_ELEM( 2, 1, state ) \
                )
 
 
#define PP_SEQ_COMB_SORT_SWAP_OP_D( unused, tuple, i ) \
        ( \
                PP_SEQ_COMB_SORT_SWAP_CHECK( \
                        BOOST_PP_TUPLE_ELEM( 4, 0, tuple ), \
                        BOOST_PP_TUPLE_ELEM( 4, 1, tuple ), \
                        BOOST_PP_TUPLE_ELEM( 4, 2, tuple ), \
                        BOOST_PP_TUPLE_ELEM( 4, 3, tuple ), \
                        i \
                        ), \
                BOOST_PP_INC( i ) \
        )
 
 
// i + gap < data.size
#define PP_SEQ_COMB_SORT_SWAP_PRED( d, state ) \
        BOOST_PP_LESS( \
                BOOST_PP_ADD_D( \
                        d, \
                        BOOST_PP_TUPLE_ELEM( 2, 1, state ), \
                        BOOST_PP_TUPLE_ELEM( 4, 2, \
                                BOOST_PP_TUPLE_ELEM( 2, 0, state ) \
                                ) \
                        ), \
                BOOST_PP_SEQ_SIZE( \
                        BOOST_PP_TUPLE_ELEM( 4, 0, \
                                BOOST_PP_TUPLE_ELEM( 2, 0, state ) \
                                ) \
                        ) \
                )       
 
//( ( seq, swaps, gap, is_last ), i )
#define PP_SEQ_COMB_SORT_OP( unused, state ) \
        PP_SEQ_COMB_SORT_GAP_CHECK( \
                BOOST_PP_TUPLE_ELEM( \
                        2, 0, \
                        BOOST_PP_WHILE( \
                                PP_SEQ_COMB_SORT_SWAP_PRED, \
                                PP_SEQ_COMB_SORT_SWAP_OP, \
                                ( \
                                        ( \
                                                BOOST_PP_TUPLE_ELEM( 4, 0, state ), \
                                                0, \
                                                BOOST_PP_TUPLE_ELEM( 4, 2, state ), \
                                                0 \
                                        ), \
                                        0 \
                                ) \
                        ) \
                ) \
        )
 
#define PP_SEQ_COMB_SORT_PRED_NONE( unused ) 1
 
#define PP_SEQ_COMB_SORT_PRED_CHECK_SWAP( state ) \
        BOOST_PP_IIF( \
                BOOST_PP_EQUAL( \
                        BOOST_PP_TUPLE_ELEM( 4, 1, state ), 0 \
                        ), \
                0, 1 )
 
#define PP_SEQ_COMB_SORT_PRED( d, state ) \
        BOOST_PP_IIF( \
                BOOST_PP_EQUAL( \
                        BOOST_PP_TUPLE_ELEM( 4, 3, state ), 1 \
                        ), \
                PP_SEQ_COMB_SORT_PRED_CHECK_SWAP, \
                PP_SEQ_COMB_SORT_PRED_NONE )( state )
 
#define PP_SEQ_COMB_SORT_D( seq ) \
        BOOST_PP_TUPLE_ELEM( \
                4, 0, \
                BOOST_PP_WHILE( \
                        PP_SEQ_COMB_SORT_PRED, \
                        PP_SEQ_COMB_SORT_OP, \
                        ( seq, 0, PP_SEQ_COMB_SORT_CALC_GAP_FROM_SEQ( seq ), 0 ) \
                        ) \
                )
#define PP_SEQ_COMB_SORT_COPY( seq ) seq
 
//( seq, swaps, gap, is_last )
#define PP_SEQ_COMB_SORT( seq ) \
        BOOST_PP_IIF( \
                BOOST_PP_EQUAL( BOOST_PP_SEQ_SIZE( seq ), 1 ), \
                PP_SEQ_COMB_SORT_COPY, \
                PP_SEQ_COMB_SORT_D \
                )( seq )
 
#define PP_COMB_SORT( seq ) \
        BOOST_PP_SEQ_ENUM( \
                PP_SEQ_COMB_SORT( seq ) \
                )
 
#include <iostream>
#include <boost/foreach.hpp>
 
int main()
{
        const int sorted[] = { PP_COMB_SORT( (8)(100)(1)(1)(6)(5)(2)(10)(1)(9) ) };
 
        BOOST_FOREACH( const int i, sorted ) {
                std::cout << i << " ";
        }
}

1 1 1 2 5 6 8 9 10 100 

参考にさせて頂いたサイト

http://www.boost.org/doc/libs/1_46_1/libs/preprocessor/doc/index.html
http://d.hatena.ne.jp/iorate/20110304/1299268769
http://d.hatena.ne.jp/DigitalGhost/20101214/1292354432

http://bit.ly/lhEdQr(深夜に見ると良いです。)

バイナリファイルの読み込み

#include <vector>
#include <fstream>
#include <iterator>

std::vector<char> bin;
std::ifstream fs( "file_name", std::ios::binary );
if ( !fs )
	return false;
const std::istreambuf_iterator<char> begin = fs, end;
std::copy( begin, end, std::back_inserter( bin ) );