Chuyển đổi khoảng thời gian có thể đọc được của con người thành các thành phần ngày


16

Thử thách

Viết chương trình ngắn nhất chuyển đổi khoảng thời gian có thể đọc được của con người thành các thành phần ngày có dạng:

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

Trường hợp mẫu

Mỗi trường hợp thử nghiệm là hai dòng, đầu vào theo sau là đầu ra:

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}

Quy tắc

  • Bạn không thể sử dụng strtotimehoặc bất kỳ chức năng tích hợp nào thực hiện toàn bộ công việc.
  • Mã ngắn nhất thắng (byte)
  • Bạn có thể in đầu ra của mình tới stdouthoặc một tệp, kết quả cũng có thể được trả về bởi một chức năng, tùy thuộc vào bạn
  • Mã thông báo có thể ở dạng số ít hoặc số nhiều.
  • Các thành phần có thể theo thứ tự ngẫu nhiên
  • Có thể không có khoảng trắng giữa số và mã thông báo
  • Dấu hiệu là tùy chọn khi khoảng thời gian là dương (đầu vào và đầu ra)
  • Nếu một thành phần xuất hiện nhiều hơn một lần thì các giá trị sẽ được thêm vào
  • Mỗi thành phần có dấu hiệu riêng
  • Các thành phần nên được xử lý riêng (ví dụ 80 minutesvẫn là 80 ở đầu ra)
  • Đầu vào được đảm bảo là chữ thường

Chúc bạn chơi golf vui vẻ!


2
Tôi thích thử thách này nhưng tôi gặp khó khăn khi nghĩ ra bất cứ thứ gì không dài và lộn xộn trong các ngôn ngữ không phù hợp với môn đánh gôn. : /
Alex A.

Định dạng đầu ra có vấn đề?
Tít

Sign is optional when the time interval is positiveĐiều đó có nghĩa là đầu vào có thể chứa các +dấu hiệu?
Tít

Câu trả lời:


3

CJam, 60 byte

Sau khi bị mắc kẹt trong thập niên 60 trong một thời gian dài, cuối cùng tôi cũng đã giảm được 60 byte. Đủ tốt! Gửi nó!

Dùng thử trực tuyến

Squished:

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

Mở rộng và bình luận:

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

Ban đầu tôi đã bắt đầu sử dụng một cách tiếp cận dựa trên mã thông báo, nhưng nó đã bị kẹt khá chắc chắn ở ... 61 byte. Thở dài. Vì vậy, tôi đã hoàn toàn thay đổi bánh răng và chuyển sang cách tiếp cận dựa trên nhân vật này, dù sao cũng thú vị hơn nhiều.

Phương pháp phân tích cú pháp của tôi hoạt động bằng cách thêm bất kỳ ký tự số hợp lệ nào đạt được ( 0- 9-) vào bộ đệm và phân tích bộ đệm dưới dạng số nguyên khi đạt đến một ký tự nhất định từ một trong các tên đơn vị thời gian. Những nhân vật y, t, d, h, i, vàc, tất cả đều thỏa mãn các điều kiện xuất hiện trong tên đơn vị thời gian và không xuất hiện trước ký tự nhận dạng trong bất kỳ tên đơn vị thời gian nào khác. Nói cách khác, khi đạt được một trong các ký tự nhận dạng đơn vị thời gian này, bộ đệm số sẽ được điền với số cuối cùng được nhìn thấy nếu điều này thực sự báo hiệu một đơn vị thời gian, hoặc bộ đệm số sẽ trống nếu điều này chỉ xuất hiện, nhưng không nên ' tín hiệu t, một số đơn vị thời gian khác. Trong cả hai trường hợp, bộ đệm số được phân tích cú pháp dưới dạng một số nguyên hoặc 0 nếu nó trống và điều này được thêm vào giá trị đơn vị thời gian tương ứng. Do đó, các ký tự nhận dạng xuất hiện trong các đơn vị thời gian khác sau khi ký tự nhận dạng của chúng không có hiệu lực.

Những vụ hack điên rồ khác bao gồm:

  • Lạm dụng các vòng lặp để các ký tự số được để lại trên ngăn xếp (hoạt động như bộ đệm ký tự số) "miễn phí".
  • Lặp lại một khối 0 hoặc nhiều lần thay vì có điều kiện vì vòng lặp nhỏ gọn hơn một câu lệnh if và các lần lặp sau lần đầu tiên không có hiệu lực.

Đối với bất kỳ ai tò mò về giải pháp dựa trên mã thông báo của tôi bị kẹt ở 61 byte, tôi cũng sẽ đăng nó ở đây. Tôi chưa bao giờ có xung quanh để mở rộng hoặc bình luận nó, mặc dù.

CJam, 61 byte

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

+1 Điều này chắc chắn giảm dần nhiều hơn.
oopbase

2
@ Forlan07 Cảm ơn bạn đã hỗ trợ. :) Nhưng tôi đã hơi muộn để trả lời, vì vậy nó không bất ngờ. Quá trình tạo ra câu trả lời này đã thỏa mãn đủ mọi cách.
Runer112

10

Perl: 61 ký tự

Cảm ơn @nutki.

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

Chạy mẫu:

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}

Những nỗ lực kém cỏi của tôi: 78 77 ký tự

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

1
Một số cải tiến tôi có thể tìm thấy:s/(-?\d+) *(..)/$$2+=$1/ge;$_="{ye|mo|da|ho|mi|se}";s/\w./${$&}+0/ge
nutki

1
4 ký tự khác:s/-?\d+ *(m.|.)/$$1+=$&/ge;$_="{y|mo|d|h|mi|s}";s/\w+/${$&}+0/ge
nutki

Ồ Thủ đoạn tuyệt vời, @nutki.
manatwork

1
Cũng được tìm thấy trong các giải pháp khác, (m.|.)-> m?(.)tiết kiệm thêm 4.
nutki

Doh. Đó là về để thử bây giờ. Vì vậy, nó hoạt động. :)
manatwork 9/2/2015

5

Ruby, 119 106 86 85 84 byte

Một byte được lưu nhờ Sp3000.

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

Đây là một hàm không tên, lấy đầu vào là một chuỗi và trả về kết quả (cũng là một chuỗi). Bạn có thể kiểm tra nó bằng cách gán nó vào f, nói và gọi nó như

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

5

Python 2, 99 byte

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

Đây là một hàm lambda có trong một chuỗi và chỉ cần sử dụng biểu thức chính quy để trích xuất các số cần thiết.

Cảm ơn Martin đã chỉ ra rằng \s*có thể chỉ là <space>*. Thật dễ dàng để quên rằng regex phù hợp với không gian theo nghĩa đen ...


4

JavaScript 100 105 112

Biên tập Thêm chuỗi mẫu (lần đầu tiên được thực hiện vào tháng 12 năm 2014, vì vậy hợp lệ cho thử thách này) - tại thời điểm tôi không biết về chúng

Chỉnh sửa Eureka, cuối cùng tôi đã hiểu ý nghĩa của m?tất cả các câu trả lời khác!

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

Kiểm tra

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 byte

Tôi nhận ra đây không phải là một mục cạnh tranh, tôi hầu như chỉ muốn đưa ra một giải pháp trong R. Bất kỳ trợ giúp nào rút ngắn điều này là tất nhiên được hoan nghênh.

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}

Giống như câu trả lời của Martin, đây là một chức năng không tên. Để gọi nó, gán nó cho fvà truyền một chuỗi.

Điều này khá là gớm ghiếc, vì vậy hãy xem xét một phiên bản không chơi gôn.

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

Chỉ dựa trên cấu trúc, thật dễ dàng để biết những gì đang diễn ra, ngay cả khi bạn không quá quen thuộc với R. Tôi sẽ giải thích một số khía cạnh nhìn lạ.

paste0() là cách R kết hợp các chuỗi không có dấu phân cách.

Các str_extract_all()chức năng đến từ stringrgói của Hadley Wickham . Việc xử lý các biểu thức chính quy trong gói cơ sở của R không được mong đợi nhiều, đó là nơi stringrxuất hiện. Hàm này trả về một danh sách các biểu thức khớp thông thường trong chuỗi đầu vào. Lưu ý cách regex được bao quanh trong một hàm perl()- đây chỉ là nói rằng regex là kiểu Perl, không phải kiểu R.

gsub()thực hiện tìm và thay thế bằng cách sử dụng biểu thức chính quy cho từng phần tử của vectơ đầu vào. Ở đây chúng tôi đang bảo nó thay thế mọi thứ không phải là số hoặc dấu trừ bằng một chuỗi trống.

Và bạn có nó rồi đấy! Giải thích thêm sẽ được cung cấp theo yêu cầu.


Tôi không nghĩ việc trích xuất chuỗi gia công sang gói bên ngoài là một ý tưởng hay. Nó không phải là một lỗ hổng khi một thư viện hỗ trợ cộng đồng bên ngoài được sử dụng? Ngay cả khi nó ổn, tại sao bạn không đưa library(stringr)vào nguồn của mình?
Andreï Kostyrka

2

Rắn hổ mang - 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 byte

Chỉnh sửa: cắt giảm 5 byte bằng cách sử dụng khai báo kiểu cũ thay vìauto.

Tôi biết người chiến thắng đã được chọn và đây sẽ là bài nộp dài nhất từ ​​trước đến nay, nhưng tôi chỉ phải đăng một giải pháp C ++, vì tôi cá là không ai mong đợi ai cả :)

Thành thật mà nói, tôi khá hài lòng với độ ngắn của nó (dĩ nhiên là bằng các phép đo C ++) và tôi chắc chắn rằng nó không thể rút ngắn được điều này (chỉ với một nhận xét, xem bên dưới) . Nó cũng là một bộ sưu tập khá nhiều tính năng mới cho C ++ 11/14.

Không có thư viện của bên thứ ba ở đây, chỉ có thư viện tiêu chuẩn được sử dụng.

Giải pháp là một dạng hàm lambda:

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

Ung dung:

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

Vì một số lý do, tôi đã phải viết

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

Thay vì chỉ

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

bởi vì iterator sẽ chỉ trả về một trận đấu nếu tôi vượt qua trong một đối tượng tạm thời. Điều này có vẻ không đúng với tôi, vì vậy tôi tự hỏi liệu có vấn đề gì với việc triển khai regex của GCC không.

Tệp thử nghiệm đầy đủ (được biên dịch với GCC 4.9.2 với -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;}
}

Đầu ra:

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

0

PHP, 141 byte

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

lấy đầu vào từ đối số dòng lệnh đầu tiên; sử dụng [,]cho đầu ra thay vì {|}. Chạy với -r.

phá vỡ

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]"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.