Oberon space
General Category => Общий раздел => Тема начата: ilovb от Декабрь 02, 2012, 03:18:53 pm
-
Дан текстовый файл (UTF-8 with BOM)
Содержит дерево строковых элементов. Подчиненность обозначена табами.
например:
Элемент1ПервогоУровня
Элемент1ВторогоУровня
Элемент2ВторогоУровня
Элемент1ТретьегоУровня
Элемент2ПервогоУровня
Элемент1ВторогоУровня
и т.д.
Нужно получить копию исходного файла, но с отсортированными в пределах подчинения строками.
Исходный и отсортированный файлы прилагаются.
И мое решение на Lua под паролем :)
ps Кодировка не важна. Можно конвертировать в подходящую.
-
А что должно быть в результате обработки такого:
z
x
a
y
f
b
a
-
В этом случае нужно ошибку выдать. Ибо это неправильный файл.
Я например запоминаю длину первого отступа и выдаю ошибку если встречается отступ меньшей длины.
-
В этом случае нужно ошибку выдать. Ибо это неправильный файл.
Я например запоминаю длину первого отступа и выдаю ошибку если встречается отступ меньшей длины.
А вот такое - тоже ошибка?
a
b
c
-
В этом случае можно либо ошибку выдать, либо считать что отступ b только на 1 больше отступа a (я делал так)
т.е. будто файл такой:
a
b
c
ps Блин, у себя уже ошибку нашел :)
-
В этом случае можно либо ошибку выдать, либо считать что отступ b только на 1 больше отступа a (я делал так)
т.е. будто файл такой:
a
b
c
ps Блин, у себя уже ошибку нашел :)
Ну, вообще можно и виртуальный безымянный (анонимный) узел же создавать.
a
z
x
y
d
c
b
-
Можно и так.
-
Ну, как-то так:
#include <iostream>
#include <map>
#include <vector>
#include <memory>
using namespace std;
struct node { multimap<string, shared_ptr<node>> childs; };
void print(const shared_ptr<node>& c, const size_t n)
{
for (auto p : c->childs) {
for (size_t i=0; i<n; i++) cout << '\t';
cout << p.first << "\n";
print(p.second, n+1);
}
}
int main()
{
vector<shared_ptr<node>> lasts;
lasts.push_back(make_shared<node>());
auto add = [&](string name) {
auto n = make_shared<node>();
lasts.back()->childs.insert({name, n});
lasts.push_back(n);
};
string line;
while (getline(cin, line)) {
auto first = line.find_first_not_of('\t');
while (lasts.size()>first+1) lasts.pop_back();
while (lasts.size()<first+1) add("");
add(string(line, first));
}
print(lasts.front(),0);
return 0;
}
Работает на однобайтовых кодировках.
-
Пипец я ничего не понял ;D
-
Пипец я ничего не понял ;D
Скорее ты не смог сделать над собой дОлжное усилие чтобы начать разбираться :-)
Примерно также я смотрю на код 1С и на всякое написанное кириллицей.
-
STD + новый стандарт делают код менее привычным. Особенно синтаксис анонимной функции.
-
STD + новый стандарт делают код менее привычным. Особенно синтаксис анонимной функции.
Ну, что я могу сказать? Пора привыкать к хорошему :-)
-
Я не понял даже где там сортировка. Коллекция это сама автоматом делает?
-
Я не понял даже где там сортировка. Коллекция это сама автоматом делает?
Да. Контейнер std::multimap сортирует по ключам. Красно-черное дерево (одна из возможных реализаций).
-
Особенно синтаксис анонимной функции.
Это которая add?
Это функция? :o ;D ;D ;D
Нда тяжеловат для восприятия cpp с наскоку... :D
-
Я не понял даже где там сортировка. Коллекция это сама автоматом делает?
Да. Контейнер std::multimap сортирует по ключам. Красно-черное дерево (одна из возможных реализаций).
Вот оно че! Теперь начинаю врубаться :)
Мне свой говнокод показывать или подождать?
-
Особенно синтаксис анонимной функции.
Это которая add?
Это функция? :o ;D ;D ;D
Нда тяжеловат для восприятия cpp с наскоку... :D
Это лямбда-функций а не функция :-)
Вообще, функциональность как бэ ощущается в использовании:
add(string(line, first));Я бы даже сказал что это лямбда-процедура :-D
Как будто во всяких Lua не то же самое с лямбдами.
-
Я не понял даже где там сортировка. Коллекция это сама автоматом делает?
Да. Контейнер std::multimap сортирует по ключам. Красно-черное дерево (одна из возможных реализаций).
Вот оно че! Теперь начинаю врубаться :)
Мне свой говнокод показывать или подождать?
Ну, я готов посмотреть. Но если есть желающие еще накодить, возможно стоит подождать. (С++ тут не слишком популярен, так что думаю что придумать свой алгоритм/реализацию народу не сложнее чем разобраться в моем коде :-) (особенно психологически) )
-
...думаю что придумать свой алгоритм/реализацию народу не сложнее чем разобраться в моем коде :-) (особенно психологически) )
;D
Удобно однако. И обфускатор не нужон ;D
-
...думаю что придумать свой алгоритм/реализацию народу не сложнее чем разобраться в моем коде :-) (особенно психологически) )
;D
Удобно однако. И обфускатор не нужон ;D
Нужен, если вокруг плюсовики :-)
Это как моя бабушка рассказывала, что когда её родители не хотели чтобы она понимала о чем они говорят, они беседовали на немецком.
-
Ладно вот моя обезьянка. Собсна скрывать нечего. Типичный говнокод :D
function print_tree(tree, indent)
indent = indent or 1
for _, branch in ipairs(tree.children) do
print(string.rep(' ', indent) .. branch.value)
if branch.children then
print_tree(branch, indent + 1)
end
end
end
function comp(a, b)
return a.value < b.value
end
function read(file)
local line = file:read()
if not line then
return nil
end
local _, indent = line:find('%s+')
local last = indent
local first = indent
local tree = {children = {}}
local branch
while line do
_, indent = line:find('%s+')
if indent < first then
print('error 001')
return nil
end
if indent > last then
tree = branch
tree.children = {}
last = last + 1
else
while indent < last do
table.sort(tree.children, comp)
tree = tree.parent
last = last - 1
end
end
branch = {parent = tree, value = line:sub(indent + 1)}
table.insert(tree.children, branch)
line = file:read()
end
while tree.parent do
table.sort(tree.children, comp)
tree = tree.parent
end
return tree
end
if arg[1] then
local file = io.open(arg[1])
if file and file:seek('set', 3) then
local tree = read(file)
if tree then
print_tree(tree)
else
print('epic fail...')
end
end
end
И даже ошибка есть (и даже наверно не одна), но мою конкретную задачу хорошо решает на тех файлах, что я прикладывал.
Работает из командной строки. Принимает один аргумент (путь к исходному файлу)
Вываливает в консоль результат. Вывод конечно можно в файл перенаправить.
ps пароль: oberspace
-
Да, моя программа все читает из stdin и выводит на stdout. Смысла в файлах не нашел :-)
-
valexey_u, а у тебя результат такой же как у меня?
Можешь выложить? Любопытно дифом пройтись :)
-
valexey_u, а у тебя результат такой же как у меня?
Можешь выложить? Любопытно дифом пройтись :)
Дифом не ходил, но на первый взгляд похоже.
-
Да, и вот скажи, зачем мне Lua, если на плюсах типичную "скриптовую" задачку получается написать быстрее, надежней, компактней и на более высоком уровне? ;-)
-
Диф показывает небольшие отличия. Но это потому что мы по разному решили обозначенные тобой выше проблемы.
А в общем одинаково.
-
Диф показывает небольшие отличия. Но это потому что мы по разному решили обозначенные тобой выше проблемы.
А в общем одинаково.
Кстати, твоя программа у меня падает на таком:
a
b
c
z
y
x
Ругается так:
lua.EXE: main.lua:27: attempt to compare nil with number
stack traceback:
main.lua:27: in function 'read'
main.lua:56: in main chunk
[C]: ?
-
Да да. Это та ошибка которую я нашел. На моих файлах просто всегда есть отступ хотя бы в 1 таб. И я на это не обратил внимания.
Если отступ нулевой то строчка:
local _, indent = line:find('%s+')
в indent помещает nil. А я это не обрабатываю.
-
И еще одна особенность моего алгоритма:
Я не сортирую первый уровень. Ибо не надо. На тех файлах всегда 1 корневой элемент.
-
Да, и вот скажи, зачем мне Lua, если на плюсах типичную "скриптовую" задачку получается написать быстрее, надежней, компактней и на более высоком уровне? ;-)
Ну тебе знающему cpp конеш ;)
А у меня выбора нет :P
-
И еще одна особенность моего алгоритма:
Я не сортирую первый уровень. Ибо не надо. На тех файлах всегда 1 корневой элемент.
А мне показалось, что проще написать без исключений из общего правила.
-
Еще любопытный момент:
То место где наши алгоритмы расходятся у тебя отрабатывает логически правильнее. Но мой вариант правильнее с точки зрения человека смотрящего в этот текст :)
И да, твое решение красивее. В Lua таких абстракций нет.
-
И еще одна особенность моего алгоритма:
Я не сортирую первый уровень. Ибо не надо. На тех файлах всегда 1 корневой элемент.
А мне показалось, что проще написать без исключений из общего правила.
Я конкретную задачу решал, на конкретном файле. Просто показалось интересным и решил создать тему. А доводить до общего решения было лень. Я и не тестировал даже. Сделал два прогона на своих файлах и остался удовлетворен результатом :)
ps Но довести до ума надо, да...
-
Еще любопытный момент:
То место где наши алгоритмы расходятся у тебя отрабатывает логически правильнее. Но мой вариант правильнее с точки зрения человека смотрящего в этот текст :)
И да, твое решение красивее. В Lua таких абстракций нет.
Думаю что на Lua так же сделать можно, то есть ничего не мешает ту же std::multimap реализовать на lua. Это же не вшито в язык у плюсов, это ж просто либа. Лямбды в луа есть. Функции высшего порядка тоже.
Единственное но - в Lua нет строгой статической типизации, соответственно все опечатки, ошибки и так далее, будут валиться не во время компиляции, а во время исполнения. И чем слоев абстракций больше, чем абстракции сложнее, тем больнее получить такую ошибку во время исполнения программы а не компиляции.
PS. Кстати, мою программу можно легко ускорить в несколько раз - достаточно заменить multimap на какой-нибудь vector - дело в том, что multimap сортирует по ключам при каждой вставке, что не здорово. А вектора пар можно будет отсортировать один раз непосредственно перед выводом.
-
Свои абстракции конечно можно замутить.
Но этого нет из коробки. В этом плане cpp выигрывает у Lua.
-
Слушай, valexey, а эту задачу можно решить стандартными юниксовыми утилитами?
-
Слушай, valexey, а эту задачу можно решить стандартными юниксовыми утилитами?
perl/awk/bash - это стандартные утилиты, ими можно? ;-)
В качестве экзотического решения: читаем файло, и по мере чтения создаем структуру каталогов, где названия каталогов - строки из файла. Затем делаем ls дл получившейся структуры каталогов :-D
-
Слушай, valexey, а эту задачу можно решить стандартными юниксовыми утилитами?
perl/awk/bash - это стандартные утилиты, ими можно? ;-)
Не, я имел ввиду grep, sort и т.д.
ps В sort я такой опции не нашел.
-
В качестве экзотического решения: читаем файло, и по мере чтения создаем структуру каталогов, где названия каталогов - строки из файла. Затем делаем ls дл получившейся структуры каталогов :-D
Прикольно у тебя фантазия работает :D
Я б до такого не допетрил ;D
-
valexey, я тут твою прогу скомпилил, и был несколько ошарашен ее размером.
1,39 МБ ! :o Чего я не так сделал?
А еще больше я удивился когда оказалось, что твоя прога работает не быстрее моей... Это как так?
-
valexey, я тут твою прогу скомпилил, и был несколько ошарашен ее размером.
1,39 МБ ! :o Чего я не так сделал?
Наверное забыл сделать strip дебажных символов. Примера ради можешь собрать hello world с теми же опциями - будут те же примерно 1.39 Мб.
А еще больше я удивился когда оказалось, что твоя прога работает не быстрее моей... Это как так?
Ну, во-первых для скорости хорошо бы оптимизацию воткнуть (O3), во-вторых бОльшую часть времени на этой задаче занимает ввод/вывод, а он от языка не шибко зависит. Ну и в третьих, по алгоритмике, я писал тут:
PS. Кстати, мою программу можно легко ускорить в несколько раз - достаточно заменить multimap на какой-нибудь vector - дело в том, что multimap сортирует по ключам при каждой вставке, что не здорово. А вектора пар можно будет отсортировать один раз непосредственно перед выводом.
Это естественно касается алгоритма обработки данных, на ввод-вывод это не повлияет. Ну и еще одно там место есть, где можно избежать копирования строк (достаточно добавить один символ в программу).
-
hello world 27 кибибайт всего
Ну а алгоритмы, оптимизации... это понятно. Но скрипт против cpp... Странно это.
Ввод-вывод не узкое место, ибо простое чтение пролетает у меня мгновенно.
-
Может в stdin дело?
-
Может в stdin дело?
Поковыряю на досуге (досуг случится после ужина ;-) )
-
Может в stdin дело?
Однако нет. У меня через stdin скорость осталась прежней
function print_tree(tree, indent)
indent = indent or 0
for _, branch in ipairs(tree.children) do
print(string.rep(' ', indent) .. branch.value)
if branch.children then
print_tree(branch, indent + 1)
end
end
end
function comp(a, b)
return a.value < b.value
end
function read(file)
local line = file:read()
if not line then
print('error 002')
return nil
end
local _, indent = line:find('%s+')
indent = indent or 0
local last = indent
local first = indent
local tree = {children = {}}
local branch
while line do
_, indent = line:find('%s+')
if indent < first then
print('error 001')
return nil
end
if indent > last then
tree = branch
tree.children = {}
last = last + 1
else
while indent < last do
table.sort(tree.children, comp)
tree = tree.parent
last = last - 1
end
end
branch = {parent = tree, value = line:sub(indent + 1)}
table.insert(tree.children, branch)
line = file:read()
end
while tree.parent do
table.sort(tree.children, comp)
tree = tree.parent
end
table.sort(tree.children, comp)
return tree
end
--if arg[1] then
--local file = io.open(arg[1])
local file = io.input()
if file and file:seek('set', 3) then
local tree = read(file)
if tree then
print_tree(tree)
else
print('epic fail...')
end
end
--end
ps Прилагаю файл на котором тестил (34 МБ)
-
Пока результаты такие (под linux'ом конечно же).
Версия gcc: 4.7.0
Версия Lua: Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
Опции компиляции: -O3 std=c++11
Размер бинарника: 20731 байт.
После strip'a: 14516 байт (то есть 14 Кб).
Производительность (твой конфиг на 30 метров):
$ time ./a.out < conf.txt > /dev/null
real 0m3.362s
user 0m3.224s
sys 0m0.128s
$ time lua ilovb.lua < conf.txt > /dev/null
real 0m4.167s
user 0m4.060s
sys 0m0.104s
Плюсы чутка быстрее (при том что в lua сортировка то один фиг сишная).
Попробую ускорить алгоритм методом выше описанным.
-
Посмотрел на твой код еще раз и вдруг вспомнил что в Lua управляющие символы как в Си :D
Короче заменил паттерн "%s+" на "\t+" и результат стал практически как у тебя.
Единственное отличие вот:
http://hostingkartinok.com/show-image.php?id=d2936c0638988e42f01e820c7902ec79
-
Пока результаты такие (под linux'ом конечно же).
У меня такие.
твоя прога (файл 20МБ ANSI) компиленная mingw в ST2 с настройками по умолчанию
ETime( 0:00:06.369 ) UTime( 0:00:06.084 ) KTime( 0:00:00.265 )
ITime( 0:00:00.000 )
моя прога (файл 34МБ UTF-8) компиленная luac:
ETime( 0:00:03.675 ) UTime( 0:00:03.260 ) KTime( 0:00:00.358 )
ITime( 0:00:00.000 )
-
Перекомпилил твою прогу с опциями -O3 -std=c++11
Бинарник стал на ~100КБ меньше
Время выполнения стало таким:
ETime( 0:00:05.406 ) UTime( 0:00:05.194 ) KTime( 0:00:00.202 )
ITime( 0:00:00.000 )
-
я тестил на utf8 в линуксе.
-
Тык она и на UTF-8 работает?! А говорил на однобайтовых...
Вот прогнал на UTF-8:
ETime( 0:00:08.679 ) UTime( 0:00:08.314 ) KTime( 0:00:00.327 )
ITime( 0:00:00.000 )
-
Но явно че то не то...
У меня компайлер GCC 4.7.2
бинарник с твоими опциями 1,31МБ получается...
а у тебя 20731 байт...
-
Тык она и на UTF-8 работает?! А говорил на однобайтовых...
Это зависит от локали. За винду ничего сказать не могу - она слишком загадочная.
-
Если что у меня вот эта хрень стоит:
http://nuwen.net/mingw.html
mingw-9.4-without-git.exe (19.4 MB) : This is smaller, if you've already installed git.
Lua вот эта:
http://code.google.com/p/luaforwindows/
-
Время замерял этим:
http://www.microsoft.com/en-us/download/details.aspx?id=17657
Ntimer.exe: Windows Program Timer
-
ntimer sort_conf2.exe < c:\ОтчетПоКонфигурации.txt > c:\ОтчетПоКонфигурации2_sort.txt
ntimer lua sort_conf.luac < c:\ОтчетПоКонфигурации.txt > c:\ОтчетПоКонфигурации_sort.txt
-
Отрезал у своей проги все кроме построчного чтения:
int main()
{
string line;
while (getline(cin, line)) {
}
return 0;
}
результат:
$ time ./a.out < conf.txt > /dev/null
real 0m2.535s
user 0m2.520s
sys 0m0.016s
Так что основной тормоз, как я и говорил, во вводе.
-
C:\sources>ntimer lua test.luac < c:\ОтчетПоКонфигурации.txt
file = io.input()
file:seek('set', 3)
for line in file:lines() do
--print(line)
end
ETime( 0:00:00.466 ) UTime( 0:00:00.421 ) KTime( 0:00:00.046 )
ITime( 0:00:00.000 )
-
C:\sources>ntimer lua test.luac < c:\ОтчетПоКонфигурации.txt
file = io.input()
file:seek('set', 3)
for line in file:lines() do
--print(line)
end
ETime( 0:00:00.466 ) UTime( 0:00:00.421 ) KTime( 0:00:00.046 )
ITime( 0:00:00.000 )
У меня те же цифры если использовать старый добрый scanf ;-)
-
Отрезал у своей проги все кроме построчного чтения:
int main()
{
string line;
while (getline(cin, line)) {
}
return 0;
}
результат:
$ time ./a.out < conf.txt > /dev/null
real 0m2.535s
user 0m2.520s
sys 0m0.016s
Так что основной тормоз, как я и говорил, во вводе.
Ога
ETime( 0:00:07.442 ) UTime( 0:00:07.394 ) KTime( 0:00:00.031 )
ITime( 0:00:00.000 )
размер бинаря 1,3МБ ;D
-
Странно. А почему так? Есть соображения?
-
Добрался до винды (замечу, это другая машина - в два-три раза примерно более шустрая чем линуксячья).
Значит так. Во-первых размер бинаря у меня 180 Кб где-то. Это собранное mingw.
Во-вторых там ввод таки тормоз - полторы секунды на девятимегабайтном файле.
Поэтому я сделал усилие и засунул свой код (не модифицированный) в студию. Пришлось поправить исходник, ибо студия все еще не держит даже элементарные вещи из стандарта. Однако ж собралось.
Результаты (изначальный файл - 9 Мб):
Lua:
ETime( 0:00:00.982 ) UTime( 0:00:00.873 ) KTime( 0:00:00.093 )
ITime( 0:00:00.000 )
C++:
ETime( 0:00:00.700 ) UTime( 0:00:00.624 ) KTime( 0:00:00.062 )
ITime( 0:00:00.000 )
Делаем выводы:
1) в стандартной гнутой (GNU) плюсовой либе getline сделан отвратительно с точки зрения скорости. Особенно под виндой - там оно тормозит так, что аж медленная lua начинает обгонять.
2) Со вводом в мелкомягкой плюсатой либе в этом месте все хорошо.
3) Неоптимальный плюсатый алгоритм (с постоянными сортировками) работает примерно в два раза быстрее чем более оптимальный на Lua (несмотря на то, что сортировка в Lua делается сишным кодом).
4) Студия пока стандарту не научилась.
-
Нашел :-)
Добавил одну ма-аленькую строчку кода и в линуксе стало так (начальный алгоритм):
c++
$ time ./a.out < conf.txt > /dev/null
real 0m0.890s
user 0m0.820s
sys 0m0.072s
lua:
$ time lua ilovb.lua < conf.txt~ > /dev/null
real 0m4.127s
user 0m4.052s
sys 0m0.072s
-
А вот что подвендой (подвинда у меня на более новом ноуте (куплен буквально пару-тройку недель назад), там модный i5 с этим, как его, Ivy Bridge, а линукс на старом ноуте которому уже 4 года - там просто мобильная версия Core2 Duo).
Все тесты проводились на том же файле что и в линуксе был выше (32 мегабайта). Никаких оптимизаций алгоритмических не было (относительно исходного варианта решения). Все кушали utf8.
С++ без магической строчки (mingw):
ETime( 0:00:10.686 ) UTime( 0:00:09.843 ) KTime( 0:00:00.842 )
ITime( 0:00:00.000 )
Lua:
ETime( 0:00:02.917 ) UTime( 0:00:02.667 ) KTime( 0:00:00.249 )
ITime( 0:00:00.000 )
С++ c магической строчкой (mingw):
ETime( 0:00:03.369 ) UTime( 0:00:02.152 ) KTime( 0:00:01.216 )
ITime( 0:00:00.000 )
С++ msvc:
ETime( 0:00:01.934 ) UTime( 0:00:01.809 ) KTime( 0:00:00.124 )
ITime( 0:00:00.000 )
-
Ах, да. Магическая строчка:
ios::sync_with_stdio(false);
-
Да, на старом ноуте все 32битное, на новом - 64х.
-
Вот теперь похоже на cpp :D
ps Прикрепил содержимое моего монструозного бинаря. Может так прояснится
-
Поправил еще одну ошибку и сделал чтобы убирались лишние отступы
function print_tree(tree, indent)
indent = indent or 0
for _, branch in ipairs(tree.children) do
print(string.rep('\t', indent) .. branch.value)
if branch.children then
print_tree(branch, indent + 1)
end
end
end
function comp(a, b)
return a.value < b.value
end
function read(file)
local line = file:read()
if not line then
print('error 002')
return nil
end
local _, indent = line:find('^\t+')
indent = indent or 0
local last = indent
local first = indent
local tree = {children = {}}
local branch
while line do
_, indent = line:find('^\t+')
if indent < first then
print('error 001')
return nil
end
if indent > last then
tree = branch
tree.children = {}
last = last + 1
else
while indent < last do
table.sort(tree.children, comp)
tree = tree.parent
last = last - 1
end
end
branch = {parent = tree, value = line:sub(indent + 1)}
table.insert(tree.children, branch)
line = file:read()
end
while tree.parent do
table.sort(tree.children, comp)
tree = tree.parent
end
table.sort(tree.children, comp)
return tree
end
--if arg[1] then
--local file = io.open(arg[1])
local file = io.input()
if file and file:seek('set', 3) then
local tree = read(file)
if tree then
print_tree(tree)
else
print('epic fail...')
end
end
--end
-
ntimer luajit.exe -O3 sort_conf.lua < c:\ОтчетПоКонфигурации.txt > c:\ОтчетПоКонфигурации_sort.txt
ETime( 0:00:02.325 ) UTime( 0:00:01.903 ) KTime( 0:00:00.405 )
ITime( 0:00:00.000 )
-
Вот теперь похоже на cpp :D
ps Прикрепил содержимое моего монструозного бинаря. Может так прояснится
Ты его чем-то расчленил что-ли?
Ну судя по потрохам, он у тебя действительно не стрипаный.
Попробуй:
strip sort_conf.exe
-
Уменьшился до ~600КБ
А потрошить TotalCommander умеет :)
-
Защупал под макосью.
Во-первых компилятор clang а не gcc. На удивление он скушал мой исходник без единого замечания. Ничего менять не пришлось.
Во-вторых результаты забега такие:
с++
$ time ./ilovb_task < conf.txt > /dev/null
real 0m2.954s
user 0m2.826s
sys 0m0.121s
Lua:
$ time lua ilovb.lua < conf.txt > /dev/null
real 0m2.935s
user 0m2.742s
sys 0m0.187s
Короче, одинаковые результаты :-) Впрочем, clang пока не может похвастать качественной оптимизацией кода. Он пока в начале пути. Но то что c++11 он уже достаточно хорошо держит (лучше студии) - очень радует.