Tỷ lệ ngày làm việc trong một tháng


11

Cho một năm và một tháng, tìm ra tỷ lệ phần trăm ngày làm việc trong tháng nói trên. Ngày làm việc là từ thứ Hai đến thứ Sáu, không liên quan đến ngày lễ hoặc những điều đặc biệt khác. Lịch Gregorian được sử dụng.

Đầu vào

Một năm và tháng ở định dạng ISO 8601 (YYYY-MM). Năm luôn có bốn chữ số, tháng luôn có hai chữ số. Năm nhất định sẽ không trước năm 1582.

Đầu ra

Đầu ra là tỷ lệ phần trăm của ngày làm việc (theo định nghĩa trên) trong tháng nhất định, được làm tròn thành một số nguyên. Không có dấu phần trăm hoặc chữ số phân số theo sau.

Mẫu 1

Input                Output

2010-05              68

Mẫu 2

Input                Output

2010-06              73

Mẫu 3

Input                Output

1920-10              68

Mẫu 4

Input                Output

2817-12              68

Một tuần đã trôi qua, một câu trả lời đã được chấp nhận. Đối với những người tò mò, kích thước của bài dự thi chúng tôi nhận được trong cuộc thi của mình:

129 - Vỏ Z
174 - VB.NET
222 - C
233 - C
300 - C

Cũng như các giải pháp (không được xếp hạng) của chúng tôi:

  75 - PowerShell
  93 - Ruby
112 - Vỏ Bourne


2
Tôi là một sinh viên tốt nghiệp, vì vậy ...echo 100
Amory

Ngay cả học sinh tốt nghiệp cũng không thể thoát khỏi các định nghĩa cơ bản trong dòng công việc của họ. Và tôi đã xác định ngày làm việc khác nhau ;-)
Joey

Câu trả lời:


4

Perl 64 bit, 67 68

Perl 5.10 trở lên, chạy với perl -E 'code here'hoặcperl -M5.010 filename

map{$d++,/^S/||$w++if$_=`date -d@ARGV-$_`}1..31;say int.5+100*$w/$d

Các nhượng bộ về kích thước mã:

  • nhạy cảm với địa phương: được tính là ngày làm việc những ngày mà dateđầu ra không bắt đầu bằng vốn S. Chạy theo LC_ALL=Cnếu nghi ngờ.
  • đầu ra là thuần túy và được định dạng tốt, nhưng có "rác" trên stderr vào các tháng ngắn hơn 31. 2> /dev/nullnếu buồn.
  • vì một số lý do, phiên bản của tôi datecoi 2817-12 là một tháng không hợp lệ. Ai biết được, ngày tận thế GNU mới là do! Yêu cầu xây dựng 64 bit datecho các ngày sau năm 2038. (Cảm ơn Joey)

1
Rõ ràng nó đã bị bãi bỏ bởi "Siphous Heme" trong thời gian cai trị của mình. ref "Một lịch sử mới của Kinh thánh"
Martin York

1
Là mỗi năm sau năm 2038 bị phá vỡ? Sau đó, chuyển đổi bản dựng 64 bit của chúng tôi có thể giúp ích do một số bản lĩnh xử lý ngày ;-)
Joey

@Jey đó chính xác là nó. Cảm ơn vì tiền hỗ trợ!
JB

JB: Đó chỉ là một phỏng đoán và tôi thực sự không mong đợi bất cứ điều gì ngoài C vẫn chỉ sử dụng các số nguyên 32 bit, tính cả giây kể từ một kỷ nguyên kỳ lạ. Mặc dù, thành thật mà nói, tôi đặt yêu cầu về ngày> 2038 vào đó cho chính xác mục đích này ;-)
Joey

3

PHP - 135

Tôi đã thực hiện nó trong PHP bởi vì tôi có một vấn đề tương tự để điều trị vài ngày trước.

<?php $a=array(2,3,3,3,2,1,1);$t=strtotime($argv[1]);$m=date(t,$t);echo round((20+min($m-28,$a[date(w,strtotime('28day',$t))]))/$m*100)

(Một phần nào đó) rõ ràng hơn và không có thông báo về các hằng số được sử dụng làm chuỗi:

<?php
date_default_timezone_set('America/New_York');
$additionalDays = array(2, 3, 3, 3, 2, 1, 1);
$timestamp = strtotime($argv[1]);
$daysInMonth = date('t', $timestamp);
$limit = $daysInMonth - 28;
$twentyNinthDayIndex = date('w', strtotime("+28 days", $timestamp));
$add = $additionalDays[$twentyNinthDayIndex];
$numberOfWorkDays = 20 + min($limit, $add);
echo round($numberOfWorkDays / $daysInMonth * 100);
?>

Điều này được thực hiện bằng một thuật toán rất đơn giản để tính toán số ngày làm việc trong một tháng: kiểm tra các ngày trong tuần của ngày 29, 30 và 31 (nếu những ngày đó tồn tại) và thêm 20.


Thuật toán tuyệt vời, chơi golf kém. Sử dụng PHP 5.3.5 hiện đại và -Rcách tiếp cận này có thể được giảm xuống còn 86 byte (63,7%): $a="2333211";echo.5+min(-8+$m=date(t,$t=strtotime($argn)),20+$a[date(w,$t)])/$m*100|0; Xem các bước chơi gôn.
Tít

80 byte:<?=.5+min(-8+$m=date(t,$t=strtotime($argn)),20+(5886>>date(w,$t)*2&3))/$m*100|0;
Tít

2

Python 152 ký tự

from calendar import*
y,m=map(int,raw_input().split('-'))
c=r=monthrange(y,m)[1]
for d in range(1,r+1):
 if weekday(y,m,d)>4:c-=1
print '%.f'%(c*100./r)


2

Windows PowerShell, 80

$x=$args;1..31|%{"$x-$_"|date -u %u -ea 0}|%{$a++
$b+=!!($_%6)}
[int]($b*100/$a)

Bạn có chắc chắn [int]thực sự tròn? Tôi có xu hướng tin rằng nó sàn.
zneak

@zneak: PowerShell không phải là ngôn ngữ C hoặc ngôn ngữ có nguồn gốc C. Nó sử dụng chế độ làm tròn mặc định của .NET là »làm tròn đến số nguyên chẵn gần nhất«. Chỉ cần thử nó: Cả hai [int]1.5[int]2.5năng suất 2. Hành vi chính xác này thường gây ra sự cố trong các nhiệm vụ trong đó phân chia thả nổi là cần thiết (sau đó yêu cầu thêm [Math]::Floor()), nhưng trong trường hợp này, nó không bị tổn thương và »làm tròn ngay cả« chỉ áp dụng cho các số kết thúc .5không thể xảy ra ở đây.
Joey

Nếu bạn chắc chắn thì tôi tin bạn. Tôi chỉ mong nó hoạt động như C # và tôi không có máy Windows nào để thử nghiệm ở nhà.
zneak

@zneak: Không, chắc chắn không hoạt động như trong C #. Một cái gì đó giống như [int]trong PowerShell thường là một chuyển đổi nhiều hơn so với diễn viên :-). Những thứ như [int[]][char[]]'abc'cũng hoạt động mà bạn không thể làm việc bằng nhiều ngôn ngữ khác.
Joey

Necrobump nhưng $input-> $argslưu một byte.
Veskah

1

D: 186 ký tự

auto f(S)(S s){auto d=Date.fromISOExtendedString(s~"-28"),e=d.endOfMonth;int n=20;while(1){d+=dur!"days"(1);if(d>e)break;int w=d.dayOfWeek;if(w>0&&w<6)++n;}return rndtol(n*100.0/e.day);}

Dễ đọc hơn:

auto f(S)(S s)
{
    auto d = Date.fromISOExtendedString(s ~ "-28"), e = d.endOfMonth;
    int n = 20;

    while(1)
    {
        d += dur!"days"(1);

        if(d > e)
            break;

        int w = d.dayOfWeek;

        if(w > 0 && w < 6)
            ++n;
    }

    return rndtol(n * 100.0 / e.day);
}

1

Con trăn - 142

from calendar import*
y,m=map(int,raw_input().split('-'))
f,r=monthrange(y,m)
print'%.f'%((r-sum(weekday(y,m,d+1)>4for d in range(r)))*100./r)

Cảm ơn fR0DDY cho bit lịch.


1

Ruby, 124 119 111

require 'date'
e=Date.civil *$*[0].split(?-).map(&:to_i),-1
p ((e+1<<1..e).count{|d|d.cwday<6}*1e2/e.day).round

Yêu cầu Ruby 1.9 do ghép nối năm và tháng trước đối số -1 "ngày" và ?-cho "-". Đối với Ruby 1.8, chúng ta phải thêm 2 ký tự:

require 'date'
e=Date.civil *$*[0].split('-').map(&:to_i)<<-1
p ((e+1<<1..e).count{|d|d.cwday<6}*1e2/e.day).round

Chỉnh sửa : Cạo năm ký tự dựa trên trợ giúp của @ Dogbert.
Chỉnh sửa : Cạo thêm tám ký tự dựa trên sự giúp đỡ của @ steenslag.


Tại sao bạn lại gán ngày cho D?
Dogbert

@Dogbert Rất tiếc! Tiếp quản từ thời tôi có hai Date.civils; cảm ơn!
Phrogz

'-'có thể được viết như ?-trong Ruby 1.9
Dogbert

@Dogbert Đẹp. Tôi cũng sẽ ném nó vào. Tôi cảm thấy phải có một cách ngắn hơn để chọn các ngày trong tuần, nhưng tôi chưa tìm thấy nó.
Phrogz

e + 1 << 1 ngắn hơn ba lần so với ee.day + 1
steenslag

1

PHP 5.2, 88 byte

Mặc dù tôi đã đánh golf giải pháp zneaks xuống còn 85 byte (tôi chỉ tìm thấy một giải nữa), ở đây, bản thân tôi:
Tôi nghi ngờ rằng tôi có thể ép thêm ba byte ở đây.

$a=_4444444255555236666304777411;echo$a[date(t,$t=strtotime($argn))%28*7+date(N,$t)]+67;

lấy đầu vào từ STDIN: Chạy với echo <yyyy>-<mm> | php -nR '<code>'.

Chuỗi $aánh xạ ngày mỗi tháng ( date(t)) và ngày trong tuần của ngày đầu tiên của tháng ( date(N): Thứ hai = 1, Chủ nhật = 7) theo tỷ lệ phần trăm của ngày làm việc-67; strtotimechuyển đổi đầu vào thành dấu thời gian UNIX; phần còn lại của mã làm băm.

+1 byte cho PHP 5 cũ hơn: Thay thế Nbằng w$a=_...;bằng $a="...".
+3 byte khác cho PHP 4: chèn .-1sau $argn.

-5 byte cho PHP 5.5 trở lên (hoãn thử thách):
Xóa mọi thứ trước đó echovà thay thế $abằng "4444444255555236666304777411".


Chà ... một byte: %7thay vì %28.
Tít

0

Nổi loạn - 118 113

w: b: 0 o: d: do join input"-01"while[d/2 = o/2][if d/7 < 6[++ w]++ b d: o + b]print to-integer round w / b * 100

Ung dung:

w: b: 0 
o: d: do join input "-01"
while [d/2 = o/2] [
    if d/7 < 6 [++ w]
    ++ b
    d: o + b
]
print to-integer round w / b * 100

0

C #, 158 byte

s=>{var d=DateTime.Parse(s);int i=0,t=DateTime.DaysInMonth(d.Year,d.Month),w=0;while(i<t)w-=-(int)d.AddDays(i++).DayOfWeek%6>>31;return Math.Round(1e2*w/t);};

Phương thức ẩn danh trả về tỷ lệ phần trăm cần thiết.

Chương trình đầy đủ với phương pháp vô căn cứ, nhận xét và trường hợp thử nghiệm:

using System;

class WorkingDayPercentage
{
    static void Main()
    {
        Func <string, double> f =
        s =>
        {
            var d = DateTime.Parse(s);                      // extracts a DateTime object from the supplied string
            int i = 0,                                      // index variable
                t = DateTime.DaysInMonth(d.Year, d.Month),  // number of total number of days in the specified month
                w = 0;                                      // number of working days in the month

            while (i < t)                                   // iterates through the days of the month
                w -= -(int)d.AddDays(i++).DayOfWeek%6 >> 31;// d.AddDays(i) is the current day
                                                            // i++ increments the index variable to go to the next day
                                                            // .DayOfWeek is an enum which hold the weekdays
                                                            // (int)..DayOfWeek gets the days's index in the enum
                                                            // note that 6 is Saturday, 0 is Sunday, 1 is Monday etc.
                                                            // (int)DayOfWeek % 6 converts weekend days to 0
                                                            // while working days stay strictly positive
                                                            // - changes the sign of the positive numbers
                                                            // >> 31 extracts the signum
                                                            // which is -1 for negative numbers (working days)
                                                            // weekend days remain 0
                                                            // w -= substracts the negative numbers
                                                            // equivalent to adding their modulus

            return Math.Round(1e2 * w / t);                 // the Math.round function requires a double or a decimal
                                                            // working days and total number of days are integers
                                                            // also, a percentage must be returned
                                                            // multiplying with 100.0 converts the expression to a double
                                                            // however, 1e2 is used to shorten the code
        };

        // test cases:
        Console.WriteLine(f("2010-05")); // 68
        Console.WriteLine(f("2010-06")); // 73
        Console.WriteLine(f("1920-10")); // 68
        Console.WriteLine(f("2817-12")); // 68
    }
}

Hàm thay thế, bổ sung các giá trị âm vào số ngày làm việc, thay đổi dấu hiệu trả lại mà không phải trả thêm chi phí byte:

s=>{var d=DateTime.Parse(s);int i=0,t=DateTime.DaysInMonth(d.Year,d.Month),w=0;while(i<t)w+=-(int)d.AddDays(i++).DayOfWeek%6>>31;return-Math.Round(1e2*w/t);};

0

Oracle SQL, 110 byte

select round(100*sum(1-trunc(to_char(x+level-1,'d')/6))/sum(1))from dual,t connect by level<=add_months(x,1)-x

Nó hoạt động với một giả định rằng dữ liệu đầu vào được lưu trữ trong một bảng bằng cách sử dụng datekiểu dữ liệu, ví dụ

with t as (select to_date('2010-06','yyyy-mm') x from dual)

0

APL (Dyalog Unicode) , 55 byte SBCS

Chức năng tiền tố ẩn danh.

.5+100×2÷/(2 5)2{≢⍎⍕↓⍺↓¯2' ',cal' '@5⊢⍵⊣⎕CY'dfns'}¨⊂

 kèm theo ngày để coi nó như một toàn thể

(2 5)2{...  áp dụng các chức năng sau trên đó, nhưng với những lập luận trái [2,5]2:

⎕CY'dfns' sao chép thư viện "dfns"

⍵⊣ loại bỏ các báo cáo có lợi cho ngày

' '@5⊢ thay thế ký tự thứ 5 ( -) bằng dấu cách

 thực hiện điều đó để có được danh sách hai yếu tố

cal gọi chức năng lịch trên đó

' ', thêm một cột khoảng trắng vào đó

¯2⌽ xoay hai cột cuối cùng (thứ bảy) ra phía trước

⍺↓ giảm số lượng đối số bên trái của hàng (2, tiêu đề) và cột (nếu được chỉ định; 5 = Sat + Sun)

 chia ma trận thành danh sách các dòng

 định dạng (làm phẳng với chèn khoảng cách kép)

 thực hiện (biến các số ngày còn lại thành một danh sách số phẳng)

 kiểm đếm những

2÷/ chia mỗi cặp (chỉ có một)

100× nhân với một trăm

.5+ thêm một nửa

 sàn nhà

Hãy thử trực tuyến!


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.