Codegolf - Преобразование Удобочитаемого Интервала Времени В Компоненты Даты

  • Автор темы Tygras.mos
  • Обновлено
  • 18, Oct 2024
  • #1

Испытание

Напишите кратчайшую программу, которая преобразует удобочитаемый интервал времени в компоненты даты формы:

 
 80 minutes 

Примеры дел

Каждый тестовый пример состоит из двух строк, за входными данными следуют выходные данные:

stdout

Правила

  • Вы не можете использовать strtotime or any built-in function that does the whole job.
  • Выигрывает самый короткий код (байты)
  • Вы можете распечатать результат на 1 year 2 months 3 seconds {1|2|0|0|0|3} -2 day 5 year 8months {5|8|-2|0|0|0} 3day 9 years 4 seconds -5 minute 4 years 4 years -3seconds {17|0|3|0|-5|1} or a file, the result can also be returned by a function, it's up to you
  • Токен может иметь форму единственного или множественного числа.
  • Компоненты могут располагаться в случайном порядке.
  • Между числом и токеном не может быть пробелов.
  • Знак не является обязательным, если временной интервал положительный (вход и выход).
  • Если компонент появляется более одного раза, значения следует добавить.
  • Каждый компонент имеет свой знак
  • С компонентами следует обращаться отдельно (например, {±YEARS|±MONTHS|±DAYS|±HOURS|±MINUTES|±SECONDS} remains as 80 in the output)
  • Ввод гарантированно будет в нижнем регистре.

Удачной игры в гольф!

#код-гольф #строка #дата

Tygras.mos


Рег
30 Jan, 2007

Тем
87

Постов
214

Баллов
659
  • 26, Oct 2024
  • #2

Перл: 61 символ

Спасибо @nutki.

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 preg_match_all("#(.?\d+)\s*m?(.)#",$argv[1],$m);    # find intervals.
# (The initial dot will match the sign, the space before the number or a first digit.)
$r=[0,0,0,0,0,0];                   # init result
foreach($m[1]as$i=>$n)              # loop through matches

$r[strpos(yodhis,$m[2][$i])]+=$n;   # map token to result index, increase value
echo json_encode($r);               # print result: "[1,2,3,4,5,6]"
 

Пример запуска:

-r

Мои неудачные попытки: 78 77 символов

{|} ||answer||

Питон 2, 99 байт

[,]

Это лямбда-функция, которая принимает строку и просто использует регулярное выражение для извлечения необходимых чисел.

Спасибо Мартину за указание на это. preg_match_all("#(.?\d+)\s*m?(.)#",$argv[1],$m);$r=[0,0,0,0,0,0];foreach($m[1]as$i=>$n)$r[strpos(yodhis,$m[2][$i])]+=$n;echo json_encode($r); could just be {1|2|0|0|0|3} {5|8|-2|0|0|0} {17|0|3|0|-5|1} . Легко забыть, что регулярные выражения буквально соответствуют пробелам...

 

Bobyrich


Рег
24 May, 2006

Тем
73

Постов
185

Баллов
580
  • 26, Oct 2024
  • #3

Рубин, 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.

И вот оно. Дальнейшие объяснения будут с радостью предоставлены по запросу.

 

Chibiss61


Рег
17 Sep, 2019

Тем
69

Постов
191

Баллов
556
  • 26, Oct 2024
  • #4

Кобра - 165

'{ "Add '{' to output"; 0a6* "Initialize time to a list of 6 zeros"; q "Read the input"; [ "Open an empty numeric character buffer"; { "For each character in the input:"; _ "Append the character to the numeric character buffer"; A,s'-+#)! "Check if the character is not part of a number"; { "If so:"; "ytdhic"#:I "Remove the character from the numeric character buffer and convert it to the corresponding time unit index, or -1 if not recognized (Time units are recognized by a character in their name that does not appear before the recognition character in any other name)"; ){ "Repeat (time unit index + 1) times:"; ]'0+iA/ "Close the numeric character buffer and parse it as an integer (empty buffer is parsed as 0)"; I_3$=@+t "Add the integer to the value of the indexed time unit"; [ "Open an empty numeric character buffer"; }* "End repeat (This is used like an if statement, taking advantage of the fact that iterations after the first have no effect)"; }* "End if"; }/ "End for"; '|* "Insert a '|' between each time unit value (implicitly added to output)"; '} "Add '}' to output"; ||answer||

С++14, 234 229 байт

Редактировать: сократите 5 байт, используя объявление старого стиля вместо '{0a6*q[{_A,s'-+#)!{"ytdhic"#:I){]'0+iA/I_3$=@+t[}*}*}/'|*'} .

Я знаю, что победитель уже выбран и что это будет самая длинная заявка на данный момент, но мне просто нужно было опубликовать решение на C++, потому что, держу пари, никто его вообще не ожидал :)

Честно говоря, я очень доволен тем, насколько коротким он оказался (конечно, по меркам C++), и я уверен, что он не может стать короче этого (всего с одним замечанием, см. ниже). . Это также довольно хороший набор функций, новых для C++11/14.

Никаких сторонних библиотек здесь нет, используется только стандартная библиотека.

Решение находится в форме лямбда-функции:

F= s=>s.replace(/(-?\d+) *m?(.)/g,(a,b,c)=>o['yodhis'.search(c)]-=-b,o=[0,0,0,0,0,0])&&`{${o.join`|`}}` ;['1 year 2 months 3 seconds','-2 day 5 year 8months' ,'3day 9 years 4 seconds -5 minute 4 years 4 years -3seconds'] .forEach(i=>console.log(i,F(i)))

Негольфед:

s=>s.replace(/(-?\d+) *m?(.)/g,(a,b,c)=>o['yodhis'.search(c)]-=-b,o=[0,0,0,0,0,0])&&`{${o.join`|`}}`

По какой-то причине мне пришлось написать

m?

вместо того, чтобы просто

f["3day 9 years 4 seconds -5 minute 4 years 4 years -3seconds"]

потому что итератор вернет только одно совпадение, если я передам временный объект. Мне это кажется неправильным, поэтому мне интересно, есть ли проблема с реализацией регулярных выражений GCC.

Полный тестовый файл (скомпилированный с помощью GCC 4.9.2 с f ):

->i{?{+"yodhis".chars.map{|w|s=0;i.scan(/-?\d+(?= *m?#{w})/){|n|s+=n.to_i};s}*?|+?}}

Выход:

<space>* ||answer||

PHP, 141 байт

\s*

принимает входные данные из первого аргумента командной строки; использует import re f=lambda I:"{%s}"%"|".join(`sum(map(int,re.findall("(-?\d+) *m?"+t,I)))`for t in"yodhis") for output instead of s/([+-]?\d+) *(..)/$a{$2}+=$1/ge;$_="{ye|mo|da|ho|mi|se}";s/\w./$a{$&}||0/ge . Беги с bash-4.3$ perl -pe 's/-?\d+ *m?(.)/$$1+=$&/ge;$_="{y|o|d|h|i|s}";s/\w/${$&}+0/ge' <<< '1 year 2 months 3 seconds' {1|2|0|0|0|3} bash-4.3$ perl -pe 's/-?\d+ *m?(.)/$$1+=$&/ge;$_="{y|o|d|h|i|s}";s/\w/${$&}+0/ge' <<< '-2 day 5 year 8months' {5|8|-2|0|0|0} bash-4.3$ perl -pe 's/-?\d+ *m?(.)/$$1+=$&/ge;$_="{y|o|d|h|i|s}";s/\w/${$&}+0/ge' <<< '3day 9 years 4 seconds -5 minute 4 years 4 years -3seconds' {17|0|3|0|-5|1} .

авария

s/-?\d+ *m?(.)/$$1+=$&/ge;$_="{y|o|d|h|i|s}";s/\w/${$&}+0/ge
 

Presidentfish


Рег
10 Apr, 2020

Тем
90

Постов
176

Баллов
686
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно