Language detail: C++
Coverage: 67.67%
|
number of '+' ratings |
contribution for coverage |
Unsolved challenges
- echoクライアント (Nested Flatten)
- tailの実装 (Nested Flatten)
- lessの実装 (Nested Flatten)
- LL Golf Hole 1 - tinyurl.comを使ってURLを短縮する (Nested Flatten)
- コード圧縮 (Nested Flatten)
codes
LL Golf Hole 5 - 最上位の桁を数え上げる
(Nested
Flatten)
mattsanさんの#7145を参考に標準入力に対応しつつgolf化. 164bytes. 改行5,空白4省略可で実質155bytes 本当はoperator<()を定義してcout<cin とかやりたかったけど、短さを優先しました。
1 2 3 4 5 6 7 | #include<iostream>
using namespace std;
void f(ostream&o,istream&i){
int c=0,d=1,n;i>>n;
while(c<=n)o<<c<<"\n"&&(c+=d)&&c/d/10&&(d*=10);
}
main(){f(cout,cin);}
|
別関数に分けずにベタでmain内に書いたほうがよっぽど短かった orz というわけで元コードは自分で-1. 116btyes.実質109bytes
1 2 3 4 5 | #include<iostream>
main(){
int c=0,d=1,n;std::cin>>n;
while(c<=n)std::cout<<c<<"\n"&&(c+=d)&&c/d/10&&(d*=10);
}
|
標準入力に対応させてみました
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <iostream>
#include <cstdlib>
#include <cstring>
void func(int m, int n = 0)
{
char buf[BUFSIZ];
int i = 1;
int size = ::strlen(::itoa(n, buf, 10)) - 1;
std::cout << n << std::endl;
while(size--) i *= 10;
if(m > n) return func(m, n+i);
}
int main(int argc, char* argv[])
{
argc == 2 ? func(::atoi(argv[1])) : func(300);
}
|
ちょっと不格好かなぁ…。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <iostream>
void count(int n)
{
int d = 1;
int i = 0;
while(i <= n)
{
std::cout << i << std::endl;
i += d;
if((i / (d * 10) > 0))
{
d *= 10;
}
}
}
int main(int, char* [])
{
count(300);
return 0;
}
|
LL Golf Hole 4 - 文章から単語の索引を作る
(Nested
Flatten)
Boost(1.35.0)を使ってどうにかこうにか。
もはやGolfではないです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include <iostream>
#include <string>
#include <vector>
#include <map>
#include <iterator>
#include <algorithm>
#include <boost/asio.hpp>
#include <boost/regex.hpp>
using namespace std;
using namespace boost;
using namespace boost::asio;
typedef vector<string> Strings;
typedef map<string, vector<int> > Dic;
int main()
{
ip::tcp::iostream src( "www.gnu.org", "http" );
src << "GET /licenses/gpl.txt HTTP/1.0\r\n"
<< "Host: www.gnu.org\r\n"
<< "\r\n"
<< flush;
// 読み込み
Strings lines;
string s;
bool body = false;
while(getline(src, s))
{
if(body) lines.push_back(s);
if(s == "\r") body = true;
}
// 解析
regex re("¥¥w+");
Dic dic;
int lineno = 1;
for(Strings::const_iterator i = lines.begin(); i != lines.end(); ++i)
{
sregex_iterator ri(i->begin(), i->end(), re);
sregex_iterator end;
for(; ri != end; ++ri)
{
dic[ri->str()].push_back(lineno);
}
++lineno;
}
// 書き出し
for(Dic::const_iterator i = dic.begin(); i != dic.end(); ++i)
{
cout << i->first << ":";
copy(i->second.begin(), i->second.end(), ostream_iterator<int>(cout, ","));
cout << endl;
}
return 0;
}
|
LL Golf Hole 3 - 13日の金曜日を数え上げる
(Nested
Flatten)
LLでないですし、ぜんぜん短くありませんし(ry
えーっと。ほとんどCです。
「今日から」の部分が一番面倒くさいことになってしまいました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <ctime>
#include <iostream>
int dayOfWeek(int y, int m, int d)
{
if((m == 1) || (m == 2))
{
y--;
m += 12;
}
return (y + y / 4 - y / 100 + y / 400 + (13 * m + 8) / 5 + d) % 7;
}
int main(int, char* [])
{
std::time_t today = std::time(0);
std::tm* todayTm = std::localtime(&today);
int count = 0;
int m = (todayTm->tm_mday <= 13) ? todayTm->tm_mon : todayTm->tm_mon + 1;
for(int y = todayTm->tm_year + 1900; y <= 2013; ++y)
{
while(m <= 12)
{
if(dayOfWeek(y, m ,13) == 5)
{
std::cout << y << "/" << m << "/13" << std::endl;
++count;
}
++m;
}
m = 1;
}
std::cout << "total: " << count << std::endl;
return 0;
}
|
LL Golf Hole 2 - 文字列に含まれる単語の最初の文字を大文字にする
(Nested
Flatten)
LLでないですし、ぜんぜん短くありませんし、多バイト文字のこと考えられてませんが、例示ということで。
標準入力から入力し、標準出力へ出力します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <cctype>
#include <string>
#include <iostream>
#include <iterator>
#include <algorithm>
std::string capitalize(const std::string& s)
{
std::string result(s);
if(result.size() > 0)
{
result[0] = std::toupper(result[0]);
}
return result;
}
int main(int, char* [])
{
std::istream_iterator<std::string> srcBegin(std::cin);
std::istream_iterator<std::string> srcEnd;
std::ostream_iterator<std::string> dst(std::cout, " ");
std::transform(srcBegin, srcEnd, dst, capitalize);
return 0;
}
|
2次元ランダムウォーク
(Nested
Flatten)
まずはシンプルなところで。 1 0 -1 2 0 0 3 0 1 4 -1 1 5 -2 1 6 -1 1 7 0 1 8 -1 1 9 -1 0 10 -1 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <cstdlib>
#include <complex>
#include <iostream>
#include <iomanip>
int main(int args, char* argv[])
{
std::complex<int> d[] =
{
std::complex<int>( 1, 0),
std::complex<int>( 0, 1),
std::complex<int>(-1, 0),
std::complex<int>( 0, -1)
};
std::complex<int> p(0, 0);
for(int i = 1; i <= 10; ++i)
{
p += d[std::rand() % 4];
std::cout << std::setw(4) << i
<< std::setw(4) << p.real()
<< std::setw(4) << p.imag()
<< std::endl;
}
return 0;
}
|
環境変数の取得
(Nested
Flatten)
ついでにC++とQtで。 QMapを返すものがあるのかとおもい、探してみましたけど、検索能力が低く、見つけることができませんでした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <QtCore>
#include <QtDebug>
#include <cstdlib>
int main(void)
{
QStringList env = QProcess::systemEnvironment();
QStringListIterator itr(env);
QMap<QString, QString> envMap;
while(itr.hasNext()) {
QString str = itr.next();
envMap[str.section('=', 0, 0)] = str.section('=', 1, 1);
}
qDebug() << envMap["PATH"];
return EXIT_SUCCESS;
}
|
比較しないソートの作成
(Nested
Flatten)
皆さんのコードを参考に実装してみましたが、イテレータのサンプルみたいになってしまいました orz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
template<typename InputIterator, typename OutputIterator>
void sort(int min, int max, InputIterator begin, InputIterator end, OutputIterator dst)
{
std::vector<int> counts(max - min + 1);
for(InputIterator i = begin; i != end; ++i)
{
++counts[*i - min];
}
for(std::size_t i = 0; i < counts.size(); ++i)
{
std::vector<int> c(counts[i], i + min);
std::copy(c.begin(), c.end(), dst);
}
}
int main(int, char* [])
{
static const int array[] = { -1, 9, 4, 8, 9, 6, 3, 9, 5, 2 };
std::vector<int> dst;
// ソート; dst に並べ替えられた値が入ります
sort(-1, 10, array, array + (sizeof(array) / sizeof(*array)), std::back_inserter(dst));
// 結果表示
std::copy(dst.begin(), dst.end(), std::ostream_iterator<int>(std::cout, ", "));
return 0;
}
|
設定ファイルから値を取得
(Nested
Flatten)
読み込みは手を抜いてしまいました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include <iostream>
#include <fstream>
#include <sstream>
#include <string>
struct Price
{
std::string name;
int cost;
};
Price loadPrice(std::istream& in)
{
Price result = { "", 0 };
std::string line;
while(std::getline(in, line))
{
std::string::size_type p = line.find("=");
std::string key = line.substr(0, p);
std::string value = line.substr(p + 1);
if(key == "ITEM_NAME")
{
result.name = value;
}
else if(key == "ITEM_COST")
{
std::stringstream ss;
ss << value;
ss >> result.cost;
}
};
return result;
}
void showPrice(const Price& price)
{
std::cout << "「" << price.name << "」は" << static_cast<int>(price.cost * 1.05) << "円(税込み)" << std::endl;
}
int main(int, char* [])
{
std::ifstream source("ShowPrice.ini");
if(source.good())
{
Price price = loadPrice(source);
showPrice(price);
}
return 0;
}
|
Boost.Spirit を使って。 Javaのpropertiesファイルみたいな KEY = VALUE KEY2 = VALUE2 : 形式のファイルを読み込みます。 #で始まる行はコメントとして読み飛ばします。 また、KEYに使えるのがアルファベット、数字、 アンダーバー、ハイフンのみという制約が あります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #include <iostream>
#include <map>
#include <string>
#include <stdexcept>
#include <fstream>
#include <boost/spirit.hpp>
#include <boost/spirit/actor/assign_actor.hpp>
#include <boost/spirit/actor/insert_at_actor.hpp>
#include <boost/algorithm/string/trim.hpp>
class PropertyFileReader
{
public:
//! key-value paired map type
typedef std::map<std::string, std::string> property_map_type;
public:
static property_map_type
read(
std::istream& is
);
};
PropertyFileReader::property_map_type
PropertyFileReader::read(
std::istream& is
)
{
using namespace boost::spirit;
property_map_type prop;
property_map_type::key_type prop_key;
rule<> comment_r = comment_p("#");
rule<> name_r = (alpha_p | ch_p('_')) >> *( alnum_p | ch_p('_') | ch_p('-'));
rule<> key_r = name_r[assign_a(prop_key)];
rule<> value_r = (*(anychar_p - eol_p))[insert_at_a(prop, prop_key)];
rule<> kvpair_r = (key_r >> *blank_p >> ch_p('=') >> *blank_p >> value_r);
rule<> commentline_r = *blank_p >> comment_r;
rule<> emptyline_r = *blank_p >> eol_p;
rule<> kvpairline_r = *blank_p >> kvpair_r >> eol_p;
rule<> prop_r = *( commentline_r || emptyline_r || kvpairline_r ) >> end_p;
// slurp stream
std::string content;
while ( !is.eof() ) {
std::string line;
std::getline(is,line);
content += line + "\n";
}
parse_info<> result = parse(content.c_str(), prop_r);
if ( !result.full ) {
throw std::runtime_error("couldn't parse properties");
}
// trim following white spaces in value
for ( property_map_type::iterator it = prop.begin(); it != prop.end(); ++it )
boost::algorithm::trim(it->second);
return prop;
}
int main(int c, char** v)
{
if ( c != 3 ) {
std::cout << "usage " << v[0] << " <property file> <key name>\n";
return 0;
}
try {
PropertyFileReader::property_map_type map(
PropertyFileReader().read(std::ifstream(v[1])) );
std::cout << v[2] << " = " << map[std::string(v[2])] << "\n";
}
catch ( const std::exception& e ) {
std::cerr << "ERROR: " << e.what() << "\n";
return 1;
}
return 0;
}
|
コメントの削除
(Nested
Flatten)
ストリームを使っているだけで実質Cですね…。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <iostream>
static void decomment(std::istream& in, std::ostream& out)
{
in.unsetf(std::ios::skipws);
char c;
char prev = 0;
while(in >> c)
{
if(c == '/')
{
prev = c;
in >> c;
if(c == '*')
{
do
{
while((in >> c) && (c != '*'))
{
if(c == '\n')
{
out << c;
}
}
} while((in >> c) && (c != '/'));
c = ' ';
}
else if(c == '/')
{
while((in >> c) && (c != '\n'))
; // NOP
}
else
{
out << prev;
}
}
else if((c == '"') && (prev != '\\') && (prev != '\''))
{
do
{
out << c;
if(c == '\\')
{
in >> c;
out << c;
}
} while((in >> c) && (c != '"'));
}
out << c;
prev = c;
}
}
int main(int, char*[])
{
decomment(std::cin, std::cout);
return 0;
}
|
C++で書いてみました。 が、C++を書いた気にならない... ちなみに、#if 0 ~ #endif は「コメント」ではないと思っているので対応していません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #include <iostream>
#include <fstream>
/* g++ -o decomment decomment.cpp */
// decomment
void decomment(
std::ostream& os,
std::istream& is
)
{
bool blc, olc; /* in block/one-line comment */
bool str, chr; /* in string/char literal */
blc=olc=str=chr=false;
char c,pc='\0';
while ( is.get(c) ) {
// escape
if ( c == '\\' ) {
if ( !olc && !blc ) {
if ( pc == '/' )
os.put('/');
os.put(c);
}
is.get(c);
if ( !olc && !blc )
os.put(c);
}
// end of one-line comment
else if ( olc && (c == '\n' || c == '\r') ) {
olc = false;
os.put(c);
pc = '\0';
continue;
}
// end of block comment
else if ( blc && pc == '*' && c == '/' ) {
blc = false;
pc = '\0';
continue;
}
// start of one-line comment
else if ( pc == '/' && c == '/' && !str && !chr && !blc ) {
olc = true;
pc = '\0';
continue;
}
// start of block comment
else if ( pc == '/' && c == '*' && !str && !chr && !olc ) {
blc = true;
pc = '\0';
}
// start/end of char literal
else if ( !olc && !blc && c == '\'' ) {
chr = !chr;
if ( pc == '/' )
os.put('/');
os.put(c);
}
// start/end of string literal
else if ( !olc && !blc && c == '\"' ) {
str = !str;
if ( pc == '/' )
os.put('/');
os.put(c);
}
else {
if ( pc == '/' && !olc && !blc )
os.put('/');
if ( c != '/' && !olc && !blc )
os.put(c);
}
pc = c;
}
}
namespace {
const char* test = "//\
" "/*" "hoge" "*/"
/* / * /* // */ "hige";
}
int main(int c, char** v)
{
(void)test;
if ( c < 2 ) {
std::cout << "usage: " << v[0] << " <C++ source file>\n";
return 0;
}
std::ifstream ifs(v[1]);
if ( !ifs ) {
std::cerr << "failed to open " << v[1] << "\n";
return 1;
}
decomment(std::cout, ifs);
return 0;
}
|
RFC 4180対応版 CSVレコードの分解
(Nested
Flatten)
変態的と名高い(?) Boost.Spirit で解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #include <vector>
#include <string>
#include <exception>
#include <stdexcept>
#include <boost/spirit.hpp>
#include <boost/spirit/actor/push_back_actor.hpp>
#include <boost/spirit/actor/clear_actor.hpp>
typedef std::vector<std::string> csv_elem_t;
std::vector<csv_elem_t>
parse_csv(
std::string lines
)
{
using namespace boost::spirit;
std::vector<csv_elem_t> csv;
csv_elem_t e;
rule<> element_r = *((anychar_p - ch_p('"')) | str_p("\"\""));
rule<> quoted_r = ch_p('"') >> element_r[push_back_a(e)] >> ch_p('"');
rule<> naked_r = (*(anychar_p - ch_p('"') - ch_p(',') - eol_p))[push_back_a(e)];
rule<> record_r = list_p((quoted_r|naked_r), ch_p(','));
rule<> csv_r = list_p(record_r[push_back_a(csv,e)][clear_a(e)], eol_p) >> end_p;
parse_info<> result = parse(lines.c_str(), csv_r);
if ( !result.full ) {
throw std::runtime_error("failed to parse");
}
typedef std::vector<csv_elem_t>::iterator csv_list_iter;
typedef csv_elem_t::iterator csv_iter;
for ( csv_list_iter clit = csv.begin(); clit != csv.end(); ++clit ) {
for ( csv_iter cit = clit->begin(); cit != clit->end(); ++cit ) {
std::string::size_type idx=0;
while ( (idx = cit->find("\"\"", idx)) != std::string::npos ) {
cit->replace(idx, 2, "\""); ++idx;
}
}
}
return csv;
}
int main()
{
try {
std::vector<csv_elem_t> csv =
parse_csv("\"aaa\",\"b\nbb\",\"ccc\",zzz,\"y\"\"Y\"\"y\",xxx");
std::cout << "total records: " << csv.size() << "\n";
typedef std::vector<csv_elem_t>::const_iterator csv_list_iter;
typedef csv_elem_t::const_iterator csv_iter;
int l = 1;
for ( csv_list_iter clit = csv.begin(); clit != csv.end(); ++clit,++l ) {
std::cout << "#" << l << "\n";
int i = 1;
for ( csv_iter cit = clit->begin(); cit != clit->end(); ++cit,++i ) {
std::cout << i << " => " << *cit << "\n";
}
}
}
catch ( std::exception& e ) {
std::cerr << e.what() << "\n";
}
return 0;
}
|




mattsan
#7228()
[
C++
]
Rating0/0=0.00
2進数限定、桁数固定です。
Rating0/0=0.00-0+
[ reply ]