사람이 읽을 수있는 시간 간격을 날짜 구성 요소로 변환


16

도전

사람이 읽을 수있는 시간 간격을 양식의 날짜 구성 요소로 변환하는 가장 짧은 프로그램을 작성하십시오.

{±YEARS|±MONTHS|±DAYS|±HOURS|±MINUTES|±SECONDS}

샘플 사례

각 테스트 케이스는 두 개의 라인으로, 입력과 출력이 이어집니다

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}

규칙

  • strtotime전체 작업을 수행하거나 내장 기능을 사용할 수 없습니다 .
  • 최단 코드 승 (바이트)
  • 출력을 stdout파일이나 파일 로 인쇄 할 수 있으며 결과는 함수에 의해 반환 될 수도 있습니다.
  • 토큰은 단수 또는 복수 형태 일 수있다.
  • 구성 요소는 임의 순서로있을 수 있습니다.
  • 숫자와 토큰 사이에 공백이 없을 수 있습니다
  • 시간 간격이 양수인 경우 부호는 선택 사항입니다 (입력 및 출력).
  • 구성 요소가 두 번 이상 나타나면 값을 추가해야합니다
  • 각 구성 요소에는 자체 기호가 있습니다
  • 구성 요소는 별도로 처리해야합니다 (예 : 80 minutes출력에서 80으로 유지).
  • 입력은 소문자로 보장됩니다

행복한 골프!


2
나는이 도전을 좋아하지만 코드 골프에 적합하지 않은 언어로 길고 지저분하지 않은 것을 생각해내는 데 어려움을 겪고 있습니다. : /
Alex A.

출력 형식이 중요합니까?
Titus

Sign is optional when the time interval is positive입력에 +기호 가 포함되어있을 수 있습니까?
Titus

답변:


3

CJam, 60 바이트

60 년대에 오랫동안 갇힌 후 마침내 이것을 60 바이트로 압축했습니다. 충분하다! 배송 해주세요!

온라인으로 사용해보십시오

박살 :

'{0a6*q[{_A,s'-+#)!{"ytdhic"#:I){]'0+iA/I_3$=@+t[}*}*}/'|*'}

확장 및 의견 :

'{              "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";

나는 처음에 토큰 기반 접근법을 사용하기 시작했지만 61 바이트에 꽤 단단히 붙어있었습니다. 한숨. 그래서 저는 기어를 완전히 바꾸고이 캐릭터 기반 접근 방식으로 바 꾸었습니다.

내 구문 분석 방법은 유효한 숫자 문자 ( 0- 9-)를 버퍼에 추가하고 시간 단위 이름 중 하나의 특정 문자에 도달하면 버퍼를 정수로 구문 분석하여 작동합니다. 그 문자입니다 y, t, d, h, i, 및c모든 시간 단위 이름에 표시되는 조건을 충족하고 다른 시간 단위 이름의 인식 문자 앞에 표시되지 않습니다. 다시 말해, 이러한 시간 단위 인식 문자 중 하나에 도달하면 숫자 버퍼가 실제로 시간 단위를 표시하는 경우 표시되는 마지막 숫자로 채워지거나, 이것이 표시되는 경우 숫자 버퍼가 비어 있지만 t 신호, 다른 시간 단위. 두 경우 모두 숫자 버퍼가 정수로 구문 분석되거나 비어있는 경우 0이되고 이는 해당 시간 단위 값에 추가됩니다. 따라서 인식 문자 다음에 다른 시간 단위로 나타나는 인식 문자는 효과가 없습니다.

다른 미친 해킹은 다음과 같습니다.

  • 루프를 남용하여 숫자가 "무료로"스택에 남아있게합니다 (숫자 버퍼로 작동).
  • 루프가 if 문보다 콤팩트하고 첫 번째 이후의 반복은 효과가 없으므로 조건부 대신 블록을 0 번 또는 여러 번 반복합니다.

61 바이트로 멈춘 토큰 기반 솔루션에 대해 궁금한 분은 여기에도 게시하겠습니다. 그래도 확장하거나 주석을 달지 못했습니다.

CJam, 61 바이트

'{0a6*q'm-'{,64/~m*{:X/XS**}/S%2/{~0="yodhis"#_3$=@i+t}/'|*'}

+1 이것은 확실히 더 많은지지를 제공합니다.
oopbase

2
@ Forlan07 지원해 주셔서 감사합니다. :) 그러나 대답하기에는 약간 늦었으므로 예상치 못한 것이 아닙니다. 이 답변을 작성하는 과정은 어쨌든 충분히 만족 스럽습니다.
Runer112

10

펄 : 61 자

@nutki에게 감사합니다.

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

나의 열악한 노력 : 78 77 자

s/([+-]?\d+) *(..)/$a{$2}+=$1/ge;$_="{ye|mo|da|ho|mi|se}";s/\w./$a{$&}||0/ge

1
내가 찾을 수있는 몇 가지 개선 사항 :s/(-?\d+) *(..)/$$2+=$1/ge;$_="{ye|mo|da|ho|mi|se}";s/\w./${$&}+0/ge
nutki

1
다른 4 개의 문자 :s/-?\d+ *(m.|.)/$$1+=$&/ge;$_="{y|mo|d|h|mi|s}";s/\w+/${$&}+0/ge
nutki

와. 훌륭한 요령, @nutki.
manatwork

1
다른 솔루션에서도 찾아 볼 수 있습니다 (m.|.).-> m?(.)추가로 4를 절약합니다.
nutki

도 그것은 지금 시도하려고했습니다. 그래서 작동합니다. :)
manatwork

5

루비, 119 106 86 85 84 바이트

Sp3000 덕분에 1 바이트가 절약되었습니다.

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

이것은 이름없는 함수로, 입력을 문자열로 받아서 결과 (문자열)를 반환합니다. 에 할당하고 f말하고 다음과 같이 호출 하여 테스트 할 수 있습니다.

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

5

파이썬 2, 99 바이트

import re
f=lambda I:"{%s}"%"|".join(`sum(map(int,re.findall("(-?\d+) *m?"+t,I)))`for t in"yodhis")

이것은 문자열을 가져오고 간단히 정규 표현식을 사용하여 필요한 숫자를 추출하는 람다 함수입니다.

그것을 지적 해준 Martin에게 감사 \s*합니다 <space>*. 정규 표현식은 문자 그대로 공백과 일치한다는 것을 잊어 버릴 수 있습니다 ...


4

자바 스크립트 100 105 112

편집하다 템플릿 문자열 추가 (2014 년 12 월에 처음 구현되었으므로이 문제에 대해 유효 함)

유레카 편집 , 마침내 나는 m?다른 모든 대답에서 의미를 얻었습니다 !

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

테스트

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)))


3

R, 197 바이트

나는 이것이 전혀 경쟁적인 입장이 아니라는 것을 깨달았다. 나는 대부분 R의 해결책을 생각해 내고 싶었다.

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}

Martin의 대답과 마찬가지로 이것은 명명되지 않은 기능입니다. 전화를하려면f 문자열 하고 전달하십시오.

이것은 꽤 끔찍한 일이므로 골프 용 버전을 살펴 보겠습니다.

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)
}

구조만으로도 R에 익숙하지 않더라도 무슨 일이 일어나고 있는지 쉽게 알 수 있습니다. 나는 낯선 외모에 대해 자세히 설명 할 것입니다.

paste0() R이 문자열을 구분 기호없이 결합하는 방법입니다.

str_extract_all()기능은 Hadley Wickham의 stringr패키지 에서 제공 됩니다. 기본 패키지에서 R의 정규 표현식 처리는 원하는 부분을 많이 남겨두고 있습니다 stringr.이 함수는 입력 문자열에서 정규 표현식 일치 목록을 리턴합니다. 정규식이 함수로 어떻게 둘러싸여 있는지 주목하십시오. 이것은 정규식이 perl()R 스타일이 아니라 Perl 스타일이라는 것을 의미합니다.

gsub()입력 벡터의 각 요소에 대한 정규식을 사용하여 찾기 및 바꾸기를 수행합니다. 여기서는 숫자 나 빼기 부호가 아닌 모든 것을 빈 문자열로 바꾸라고 지시합니다.

그리고 거기 있습니다. 추가 설명은 요청에 따라 기꺼이 제공 될 것입니다.


문자열 추출을 외부 패키지로 아웃소싱하는 것은 좋은 생각이라고 생각하지 않습니다. 외부 커뮤니티 지원 라이브러리를 사용할 때 허점이 아닌가? 괜찮더라도 library(stringr)소스에 포함하지 않은 이유는 무엇입니까?
Andreï Kostyrka

2

코브라-165

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('|')]}'

2

C ++ 14, 234 229 바이트

편집하다: 대신 기존 스타일 선언을 사용하여 5 바이트를 줄입니다 auto.

나는 승자가 이미 선택되었으며 이것이 지금까지 가장 긴 제출 일 것이라는 것을 알고 있지만 아무도 아무도 기대하지 않았기 때문에 C ++ 솔루션을 게시해야했습니다. :)

솔직히 말해서 (물론 C ++ 측정에 의해) 얼마나 짧아 졌는지에 매우 만족합니다. . 또한 C ++ 11 / 14에 새로 추가 된 기능들도 상당히 훌륭합니다.

여기에는 타사 라이브러리가 없으며 표준 라이브러리 만 사용됩니다.

해결책은 람다 함수의 형태입니다.

[](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;};

언 골프 드 :

[](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;
}

어떤 이유로 나는 글을 써야했다

regex g("-?\\d+\\s*"s+t);
decltype(e)i(begin(s),end(s),g);

그냥 대신

decltype(e)i(begin(s),end(s),regex("-?\\d+\\s*"s+t));

임시 객체를 전달하면 반복자가 일치하는 항목을 하나만 반환하기 때문입니다. 이것은 나에게 옳지 않은 것 같아서 GCC의 정규식 구현에 문제가 있는지 궁금합니다.

전체 테스트 파일 (GCC 4.9.2로 컴파일 -std=c++14) :

#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;}
}

산출:

{1|2|0|0|0|3}
{5|8|-2|0|0|0}
{17|0|3|0|-5|1}

0

PHP, 141 바이트

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);

첫 번째 명령 행 인수에서 입력을받습니다. [,]대신 출력에 사용 합니다 {|}. 로 실행하십시오 -r.

고장

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]"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.