한 달의 근무일 비율


11

1 년 1 개월이 주어진 경우 해당 월의 근무일 비율을 찾으십시오. 공휴일 또는 기타 특별한 사항에 관계없이 월요일부터 금요일까지 근무일입니다. 그레고리력이 사용됩니다.

입력

ISO 8601 형식 (YYYY-MM)의 연도 및 월 연도에는 항상 네 자리 숫자가 있고 월에는 항상 두 자리 숫자가 있습니다. 주어진 연도는 1582 년 이전이 아닙니다.

산출

출력은 주어진 달의 근무일 비율 (위의 정의에 따라)이며 정수로 반올림됩니다. 뒤에 백분율 부호 나 소수가 없습니다.

샘플 1

Input                Output

2010-05              68

샘플 2

Input                Output

2010-06              73

샘플 3

Input                Output

1920-10              68

샘플 4

Input                Output

2817-12              68

일주일이 지났는데 답이 받아 들여졌습니다. 궁금한 점은 컨테스트에 제출 된 제출물의 크기입니다.

129 – Z 쉘
174 – VB.NET
222 – C
233 – C
300 – C

당사의 자체 (비 랭킹) 솔루션 :

  75 – PowerShell
  93 – Ruby
112 – Bourne 쉘


2
저는 대학원생입니다.echo 100
Amory

대학원생조차도 업무 라인의 기본 정의를 벗어날 수 없습니다. 그리고 나는 근무일을 다르게 정의했다 ;-)
Joey

답변:


4

64 비트 Perl, 67 68

Perl 5.10 이상 perl -E 'code here'또는perl -M5.010 filename

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

코드 크기에 대한 양보 :

  • 로케일 구분 : date출력이 대문자 S로 시작하지 않는 날을 작업 일로 계산 LC_ALL=C합니다. 의심스러운 경우 실행 합니다.
  • 출력은 순수하고 형식이 양호하지만 31 2> /dev/null일 보다 짧은 달에 stderr에 "쓰레기"가 있습니다.
  • 어떤 이유로 내 버전은 date2817-12를 유효하지 않은 달로 간주합니다. 누가 새로운 GNU 묵시록이 나올지 알았습니다! date2038 이후의 날짜 에는 64 비트 빌드가 필요합니다. (Joy 감사합니다)

1
그의 통치 기간 동안 "Siphous Hemes"에 의해 폐지 된 것 같습니다. ref "성서의 새로운 역사"
Martin York

1
2038 년 이후 매년 고장입니까? 그런 다음 64 비트 빌드를 전환하면 날짜 처리와 함께 약간의 뇌사로 인해 도움이 될 수 있습니다 ;-)
Joey

@Joey 바로 그거야. 팁 고마워!
JB

JB : 단지 추측에 지나지 않았지만 실제로 C 이외의 어떤 것도 여전히 이상한 시대 이후 초를 세는 32 비트 정수만 사용할 것으로 기대하지 않았습니다. 솔직히 말해서 정확히 20-> 날짜에 대한 요구 사항을 정확히이 목적으로 넣었습니다. ;-)
Joey

3

PHP-135

며칠 전에 비슷한 문제 가 있었기 때문에 PHP로 만들었습니다 .

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

(일부) 문자열로 사용되는 상수에 대한 통지없이 더 명확하게 :

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

이것은 매우 간단한 알고리즘으로 한 달에 작업 일수를 계산할 수 있습니다.


훌륭한 알고리즘, 열악한 골프. 최신 PHP 5.3.5 및을 사용하면 -R이 방법을 86 바이트 (63.7 %)로 줄일 수 있습니다 $a="2333211";echo.5+min(-8+$m=date(t,$t=strtotime($argn)),20+$a[date(w,$t)])/$m*100|0; . 골프 단계를 참조하십시오.
Titus

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

2

파이썬 152 문자

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

배쉬 + coreutils, 82 바이트

f()(cal -NMd$1|sed -n "s/^$2.//p"|wc -w)
dc -e`f $1 "[^S ]"`d`f $1 S`+r200*r/1+2/p

2

윈도우 PowerShell, 80

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

당신은 확실 [int]정말 라운드? 나는 그것이 바닥을 믿는 경향이 있습니다.
zneak

@zneak : PowerShell은 C 또는 C 파생 언어가 아닙니다. .NET의 기본 반올림 모드 인»round to 가장 가까운 짝수 정수«를 사용합니다. 시도해보십시오 : Both [int]1.5and [int]2.5yield 2. 이 정확한 동작은 바닥 분할이 필요한 작업에서 문제를 발생시키는 경우가 [Math]::Floor()많지만 (이 경우 추가가 필요함 )이 경우에는 아프지 않고 "둥근에서 짝수"까지 끝나지 .5않는 숫자에만 적용됩니다 .
Joey

당신이 확실하다면 나는 당신을 믿습니다. 방금 C #과 같이 작동 할 것으로 예상했으며 집에서 테스트 할 Windows 컴퓨터가 없습니다.
zneak

@zneak : 아니요, C # 에서처럼 작동하지 않습니다. [int]PowerShell에서 와 같은 것은 일반적으로 캐스트 :-)보다 더 많은 변환입니다. 상황이 좋아 [int[]][char[]]'abc'도 당신이 많은 다른 언어로 작업을 얻을 수없는 일을.
Joey

Necrobump이지만 $input-> $args는 바이트를 저장합니다.
Veskah

1

D : 186 자

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

더 읽기 :

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

파이썬-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)

달력 비트에 대한 fR0DDY 덕분입니다.


1

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

-1 "day"인수 전 및 월에 ?-대해 "-". 및 루팅으로 인해 Ruby 1.9가 필요합니다 . Ruby 1.8의 경우 2자를 추가해야합니다.

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

편집 : @Dogbert의 도움에 따라 다섯 글자를 면도합니다.
편집 : @steenslag의 도움에 따라 8자를 더 면도 하십시오 .


왜 날짜를 D에 할당합니까?
Dogbert

@Dogbert Whoops! 내가 두 개의 Date.civils를 가지고 있었던 때부터 이월; 감사!
Phrogz

'-'?-Ruby 1.9에서 와 같이 작성 될 수 있음
Dogbert

@Dogbert Nice. 저도 넣을 것입니다. 요일을 선택하는 더 짧은 방법이 있어야한다고 생각하지만 아직 찾지 못했습니다.
Phrogz

e + 1 << 1은 ee.day + 1보다 3이 짧습니다.
steenslag

1

PHP 5.2, 88 바이트

이미 zneak의 솔루션 을 85 바이트로 낮추었 지만 (단지 하나 더 찾았습니다) 여기 내 자신의
것이 있습니다. 여기에서 3 바이트를 더 짜낼 수 있을지 의심됩니다.

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

STDIN에서 입력 : Run with echo <yyyy>-<mm> | php -nR '<code>'.

이 문자열 $a은 매월 1 일 ( date(t)) 및 주 1 일 ( date(N): Monday = 1, Sunday = 7)을 작업 일 -67의 백분율로 매핑합니다 . strtotime입력을 UNIX 타임 스탬프로 변환합니다. 나머지 코드는 해싱을 수행합니다.

오래된 PHP 5에 대한 1 바이트 : 교체 Nw$a=_...;함께 $a="...".
PHP 4의 다른 +3 바이트 : .-1after after $argn.

-5 PHP 5.5 바이트 이상 (도전 postdates) :
제거 모든 이전 echo및 교체 $a와 함께 "4444444255555236666304777411".


음 ... 1 바이트 : %7대신 %28.
Titus

0

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

언 골프 드 :

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 바이트

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

필요한 백분율을 반환하는 익명 메서드

ungolfed, commented 방법 및 테스트 케이스가있는 전체 프로그램 :

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

대체 기능-작업 일수에 음수 값을 추가하여 추가 바이트 비용없이 반환 부호를 변경합니다.

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 바이트

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

입력 데이터가 date데이터 형식 을 사용하여 테이블에 저장되어 있다고 가정합니다.

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

0

APL (Dyalog Unicode) , 55 바이트 SBCS

익명의 암묵적 접두사 기능.

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

 그것을 전체로 취급하기 위해 날짜를 동봉

(2 5)2{ 다음 함수를 왼쪽 인수 [2,5]와 함께 적용하십시오 2.

⎕CY'dfns' "dfns"라이브러리를 복사하십시오

⍵⊣ 날짜에 찬성하여 보고서를 폐기

' '@5⊢ 다섯 번째 문자 ( -)를 공백으로 바꾸십시오

 두 요소 목록을 얻으려면 실행하십시오.

cal 그 달력 기능을 호출

' ', 공백을 열 앞에 추가하십시오

¯2⌽ 마지막 두 열 (토요일)을 앞으로 회전

⍺↓ 왼쪽 인수 개수의 행 (2, 헤더) 및 열 삭제 (지정된 경우 5 = Sat + Sun)

 행렬을 줄 목록으로 나누기

 형식 (이중 간격 삽입으로 평평함)

 실행 (나머지 날짜 수를 플랫 숫자 목록으로 변환)

 그 집계

2÷/ 각 쌍을 나눕니다 (단 하나만 있습니다)

100× 백을 곱하다

.5+ 반을 더하다

 바닥

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


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