第26回オフラインリアルタイムどう書く「三種類の境界線」の ruby と C++ による実装
問題 http://nabetani.sakura.ne.jp/hena/ord26tribo/
解答リンク集 http://qiita.com/Nabetani/items/8a973a47633558f54ba8
イベント http://yhpg.doorkeeper.jp/events/15316
当日お見せした実装。
まずは ruby から。
def solve(s)
positions = s.chars.map { |c| c.ord - 'a'.ord }.sort
bo = [positions.size] * 3
positions.each do |po|
h = Math.sqrt(po).floor
next if (po - h**2).even? # 上が尖った三角は無視
[-1, +1, -h * 2].each.with_index do |delta, ix|
bo[ix] -= 2 if positions.include?(po + delta)
end
end
bo.join(',')
end
DATA.map do |line|
id, src, expected = line.split(/\s+/)
actual = solve(src)
(actual == expected).tap do |ok|
puts '***NG*** : %s %s->%s ( %s )' % [id, src, actual, expected] unless ok
end
end.all?.tap { |r| puts(r ? 'ok' : 'NG') }
__END__
0 bdelmnouy 5,7,9
1 a 1,1,1
2 q 1,1,1
45 abcdefghijklmnoqrstuwxy 5,7,7
46 abcdeghijklmnopqrstuvwxy 6,6,6
いつも通り、テストデータの大半は省略。
実装戦略は。
- 線を数えていく。
- 隣にあるから線がないとかいうことを度外視して全部数えてから、ここは線がないよね、と、減らしていく。
の二通りがある。
あと、セルとセルの関係をどこまで算術的にやるのか、どこまでデータを持つのかという部分もいろいろある。
この実装の場合は、減らしていく方向で、全部算術的に求めている。
減らしていく境界線なのかどうかを判断する際、下向き三角だけを見るようにしている。
そうすると「bの左にはセルがない」という状況に対処する必要がなくなり、ちょっと楽になる。
で。
当日、C++ に移植した。
アルゴリズムはまったく同じ。
// clang++ -std=c++11 -Wall
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <algorithm>
#include <sstream>
using namespace std;
vector<int> get_positions( string const & src )
{
vector<int> positions;
for( auto ch : src ){
positions.push_back( ch - 'a' );
}
return positions;
}
string solve( string const & src )
{
vector<int> positions = get_positions( src );
int s = positions.size();
int borders[3]={s,s,s};
for( auto po : positions ){
int h = static_cast<int>( floor( sqrt( po ) ) );
if ( (po-h*h)%2==0 ){
continue;
}
for( int ix=0 ; ix<3 ; ++ix ){
int delta = (vector<int>{-1,1,-h*2})[ix];
if ( positions.end() != find( positions.begin(), positions.end(), po+delta ) ){
borders[ix] -= 2;
}
}
}
return (stringstream()<<borders[0]<<","<<borders[1]<<","<<borders[2] ).str();
}
void test( string const & src, string const & expected )
{
string actual = solve( src );
bool ok = actual==expected;
cout
<<( ok ? "ok " : "***NG*** " )<< src << " => " << actual;
if ( ! ok ){
cout << " != " << expected;
}
cout << endl;
}
void test_all()
{
/*0*/ test( "bdelmnouy", "5,7,9" );
/* 略 */
/*46*/ test( "abcdeghijklmnopqrstuvwxy", "6,6,6" );
}
int main()
{
test_all();
}
get_positions
が、STL をちゃんと使えばもっとシンプルになると思うんだけど、STL力が足りず、こんなところで。
行数では、ruby の 3倍ぐらいの感じ。そんなもんかな。
Author And Source
この問題について(第26回オフラインリアルタイムどう書く「三種類の境界線」の ruby と C++ による実装), 我々は、より多くの情報をここで見つけました https://qiita.com/Nabetani/items/cd131d3fabd14afd0b8b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .