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

도전

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

{±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으로 유지).
  • 입력은 소문자로 보장됩니다

행복한 골프!



답변

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 바이트에 꽤 단단히 붙어있었습니다. 한숨. 그래서 저는 기어를 완전히 바꾸고이 캐릭터 기반 접근 방식으로 바 꾸었습니다.

내 구문 분석 방법은 유효한 숫자 문자 ( 09-)를 버퍼에 추가하고 시간 단위 이름 중 하나의 특정 문자에 도달하면 버퍼를 정수로 구문 분석하여 작동합니다. 그 문자입니다 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}/'|*'}

답변

펄 : 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

답변

루비, 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"]

답변

파이썬 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>*. 정규 표현식은 문자 그대로 공백과 일치한다는 것을 잊어 버릴 수 있습니다 …


답변

자바 스크립트 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)))

답변

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

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


답변

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