Рубин, 119 106 86 85 84 байта
Один байт сэкономлен благодаря Sp3000.
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
string arr[] = {"1 year 2 months 3 seconds",
"-2 day 5 year 8months",
"3day 9 years 4 seconds -5 minute 4 years 4 years -3seconds"};
for_each(begin(arr), end(arr), [](auto&s){sregex_iterator e;auto r="{"s;for(auto&t:{"y","mo","d","h","mi","s"}){int a=0;auto g=regex("-?\\d+ *"s+t);decltype(e)i(begin(s),end(s),g);for_each(i,e,[&](auto&b){a+=stoi(b.str());});r+=to_string(a)+"|";}r.back()='}';s=r;});
for(auto &s : arr) {cout << s << endl;}
}
Это безымянная функция, которая принимает входные данные в виде строки и возвращает результат (также в виде строки). Вы можете протестировать его, назначив его -std=c++14
, say, and calling it like
decltype(e)i(begin(s),end(s),regex("-?\\d+\\s*"s+t));
||answer||
JavaScript 100 105 112
Редактировать Добавление строк шаблона (впервые реализовано в декабре 2014 года, поэтому подходит для этой задачи) — тогда я о них не знал
Редактировать Эврика, наконец-то я понял смысл слова regex g("-?\\d+\\s*"s+t);
decltype(e)i(begin(s),end(s),g);
in all the other answers!
[](auto&s)
{
sregex_iterator e;
auto r="{"s;
for(auto&t:{"y","mo","d","h","mi","s"})
{
int a=0;
regex g("-?\\d+\\s*"s+t);
decltype(e)i(begin(s),end(s),g);
for_each(i,e,[&](auto&b)
{
a+=stoi(b.str());
});
r+=to_string(a)+"|";
}
r.back()='}';
s=r;
}
Тест
[](auto&s){sregex_iterator e;auto r="{"s;for(auto&t:{"y","mo","d","h","mi","s"}){int a=0;regex g("-?\\d+ *"s+t);decltype(e)i(begin(s),end(s),g);for_each(i,e,[&](auto&b){a+=stoi(b.str());});r+=to_string(a)+"|";}r.back()='}';s=r;};
||answer||
CJam, 60 байт
После длительного пребывания в 60-х годах мне наконец удалось сжать это значение до 60 байт. Достаточно хорошо! Отправьте это!
Попробуйте онлайн
Сплющено:
auto
Расширено и прокомментировано:
def f(s='')
l=int[](6)
for i in 6,for n in RegularExpressions.Regex.matches(s,'(-?\\d+) *m?['yodhis'[i]]'),l[i]+=int.parse('[n.groups[1]]')
print'{[l.join('|')]}'
Сначала я начал использовать подход на основе токенов, но он довольно прочно застрял на... 61 байте. Вздох. Поэтому я полностью изменил подход и переключился на подход, основанный на персонажах, который в любом случае гораздо интереснее.
Мой метод синтаксического анализа работает путем добавления любых допустимых числовых символов ( gsub()
- perl()
и stringr
) to a buffer and parsing the buffer as an integer when a certain character from one of the time unit names is reached. Those characters are stringr
, str_extract_all()
, paste0()
, function(x) {
s <- "{"
for (c in strsplit("yodhis", "")[[1]]) {
matches <- str_extract_all(x, perl(paste0("(-?\\d+) *m?", c)))[[1]]
nums <- gsub("[^0-9-]", "", matches)
y <- sum(as.numeric(nums))
s <- paste0(s, ifelse(c == "y", "", "|"), y)
}
s <- paste0(s, "}")
return(s)
}
, f
, и function(x){s="{";for(c in strsplit("yodhis","")[[1]])s=paste0(s,ifelse(c=="y","","|"),sum(as.numeric(gsub("[^0-9-]","",str_extract_all(x,perl(paste0("(-?\\d+) *m?",c)))[[1]]))));s=paste0(s,"}");s}
, which all satisfy the conditions that they appear in a time unit name and don't appear before the recognition character in any other time unit name. In other words, when one of these time unit recognition characters is reached, the numeric buffer will be filled with the last number seen if this actually signals a time unit, or the numeric buffer will be empty if this just appears in, but shouldn't signal, some other time unit. In either case, the numeric buffer is parsed as an integer, or 0 if it was empty, and this is added to the corresponding time unit value. Thus recognition characters appearing in other time units after their recognition character have no effect.
Другие сумасшедшие хаки включают в себя:
- Злоупотребление циклами, при которых числовые символы остаются в стеке (который действует как буфер числовых символов) «бесплатно».
- Повторение блока ноль или несколько раз вместо условного, поскольку цикл более компактен, чем оператор if, и итерации после первой не имеют никакого эффекта.
Для тех, кому интересно мое решение на основе токенов, которое застряло на 61 байте, я также опубликую его здесь. Однако я так и не удосужился расширить или прокомментировать это.
CJam, 61 байт
'{0a6*q'm-'{,64/~m*{:X/XS**}/S%2/{~0="yodhis"#_3$=@i+t}/'|*'}
||answer||
Р, 197 байт
Я понимаю, что это вообще не конкурентная заявка, я просто хотел найти решение на R. Любая помощь в сокращении, конечно, приветствуется.
c
Как и ответ Мартина, это безымянная функция. Чтобы вызвать его, назначьте его i
and pass a string.
Это довольно отвратительно, так что давайте посмотрим на версию без гольфа.
h
Основываясь только на структуре, легко понять, что происходит, даже если вы не слишком хорошо знакомы с R. Я остановлюсь на некоторых странных аспектах.
d
is how R combines strings with no separator.
t
function comes from Hadley Wickham's y
упаковка. Обработка регулярных выражений в базовом пакете R оставляет желать лучшего, и именно здесь -
comes in. This function returns a list of regular expression matches in the input string. Notice how the regex is surrounded in a function 9
-- это просто говорит о том, что регулярное выражение выполнено в стиле Perl, а не в стиле R.
0
does a find-and-replace using a regex for each element of the input vector. Here we're telling it to replace everything that isn't a number or minus sign with an empty string.
И вот оно. Дальнейшие объяснения будут с радостью предоставлены по запросу.