ร้อยละของวันทำงานในหนึ่งเดือน


11

ให้ปีและเดือนหาเปอร์เซ็นต์ของวันทำงานในเดือนดังกล่าว วันทำงานคือวันจันทร์ถึงวันศุกร์โดยไม่คำนึงถึงวันหยุดหรือสิ่งพิเศษอื่น ๆ ใช้ปฏิทินเกรโกเรียน

อินพุต

ปีและเดือนในรูปแบบ 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 - เชลล์เป้าหมาย


2
ฉันเป็นนักศึกษาระดับบัณฑิตศึกษาดังนั้น ...echo 100
Amory

แม้แต่ผู้สำเร็จการศึกษาไม่สามารถหลีกหนีความหมายพื้นฐานในสายงาน และฉันกำหนดวันทำงานที่แตกต่างกัน ;-)
Joey

คำตอบ:


4

Perl แบบ 64 บิต, 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หากมีข้อสงสัย
  • ผลลัพธ์มีความบริสุทธิ์และมีรูปแบบที่ดี แต่มี "ขยะ" บน stderr ในเดือนที่สั้นกว่า 31 2> /dev/nullถ้าอารมณ์เสีย
  • ด้วยเหตุผลบางอย่างเวอร์ชันของฉันdateพิจารณา 2817-12 เดือนที่ไม่ถูกต้อง ใครจะรู้ว่าการเปิดเผยใหม่ของ GNU นั้นถึงกำหนดแล้ว! ต้องใช้ 64 dateบิวด์สำหรับวันหลังจากปี 2038 (ขอขอบคุณ Joey)

1
เห็นได้ชัดว่ามันถูกยกเลิกโดย "Siphous Hemes" ในระหว่างการปกครองของเขา ref "ประวัติใหม่ของพระคัมภีร์ไบเบิล"
Martin York

1
เป็นประจำทุกปีหลังจากปี 2038 หรือไม่ จากนั้นการเปลี่ยนบิวด์แบบ 64 บิตอาจช่วยได้เนื่องจากสมองบางส่วนมีการจัดการวันที่ ;-)
Joey

@ โจอี้นั่นแหละ ขอบคุณสำหรับทิป!
JB

JB: เป็นเพียงการเดาและจริง ๆ แล้วฉันไม่ได้คาดหวังอะไรเลยนอกจาก C จะยังคงใช้เลขจำนวนเต็ม 32 บิตเพียงอย่างเดียวที่นับวินาทีนับตั้งแต่ยุคแปลก แม้ว่าจะซื่อสัตย์ฉันใส่ข้อกำหนดเกี่ยวกับวันที่> 2038 ในที่นั่นเพื่อจุดประสงค์นี้ ;-)
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);
?>

สิ่งนี้เกิดขึ้นได้โดยอัลกอริทึมที่ง่ายมากในการคำนวณจำนวนวันทำงานในหนึ่งเดือน: ตรวจสอบวันทำงานของวันที่ 29, 30 และ 31 (ถ้าวันเหล่านั้นมีอยู่) และเพิ่ม 20


อัลกอริทึมที่ดีกอล์ฟที่ไม่ดี ใช้ร่วมสมัย 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; ดูขั้นตอนการเล่นกอล์ฟ
ติตัส

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

2

Python 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

Windows 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 ซึ่งเป็น»ปัดเศษเป็นเลขจำนวนเต็มคู่ที่ใกล้เคียงที่สุด« เพียงแค่พยายามที่จะออก: ทั้งสอง[int]1.5และอัตราผลตอบแทน[int]2.5 2พฤติกรรมที่แน่นอนนี้มักจะทำให้เกิดปัญหาในงานที่จำเป็นต้องมีการแบ่งพื้น (ซึ่งจำเป็นต้องมีการเสริม[Math]::Floor()) แต่ในกรณีนี้มันไม่เจ็บและ»ปัดไปถึง«ใช้กับตัวเลขที่สิ้นสุด.5ซึ่งไม่สามารถเกิดขึ้นได้ที่นี่
Joey

ถ้าคุณแน่ใจแล้วฉันเชื่อว่าคุณ ฉันคาดหวังว่ามันจะทำงานเหมือน C # แทนและฉันไม่มีเครื่อง Windows ที่จะทดสอบที่บ้าน
zneak

@zneak: ไม่แน่นอนไม่ทำงานใน C # สิ่งที่ชอบ[int]ใน PowerShell มักเป็นการแปลงมากกว่านักแสดง :-) สิ่งต่าง ๆ เช่น[int[]][char[]]'abc'ยังทำงานซึ่งคุณไม่สามารถทำงานในภาษาอื่น ๆ อีกมากมาย
Joey

Necrobump but $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

Python - 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.9 เนื่องจาก splatting ปีและเดือนก่อนที่ 1 "วัน" อาร์กิวเมนต์และสำหรับ?- "-"สำหรับ 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


เหตุใดคุณกำหนดวันที่ถึง D
Dogbert

@Dogbert อ๊ะ! โฮลด์จากช่วงเวลาที่ฉันมี Date.civils สอง; ขอบคุณ!
Phrogz

'-'สามารถเขียนได้?-ใน Ruby 1.9
Dogbert

@Dogbert Nice ฉันจะขว้างมันเข้าไปด้วย ฉันรู้สึกว่าต้องมีวิธีที่สั้นกว่าในการเลือกวันในสัปดาห์ แต่ฉันยังไม่พบ
Phrogz

e + 1 << 1 คือสามสั้นกว่า ee.day + 1
steenslag

1

PHP 5.2, 88 ไบต์

แม้ว่าฉันจะเล่นกอล์ฟโซลูชั่นของ zneakลงไปที่ 85 ไบต์ (ฉันเพิ่งพบอีกหนึ่ง), ที่นี่ของฉันเอง:
ฉันสงสัยว่าฉันสามารถบีบอีกสามไบต์ที่นี่

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

ใช้เวลาการป้อนข้อมูลจาก STDIN: echo <yyyy>-<mm> | php -nR '<code>'เรียกใช้ด้วย

สตริงจะ$aแมปวันต่อเดือน ( date(t)) และวันในสัปดาห์ของวันแรกของเดือน ( date(N): วันจันทร์ = 1, วันอาทิตย์ = 7) กับเปอร์เซ็นต์ของวันทำงาน -67strtotimeแปลงอินพุตเป็นเวลาประทับ UNIX; ส่วนที่เหลือของรหัสทำ hashing

1 ไบต์สำหรับเก่า PHP 5: แทนที่Nด้วยwและมี$a=_...; อีก 3 ไบต์สำหรับ PHP 4: แทรกหลัง$a="..."
.-1$argn

-5 ไบต์สำหรับ PHP 5.5 หรือสูงกว่า (postdates ท้าทาย):
ทุกอย่างก่อนที่จะเอาออกechoและแทนที่ด้วย$a"4444444255555236666304777411"


ดี ... หนึ่งไบต์: แทน%7 %28
ติตัส

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

Ungolfed:

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

วิธีการไม่ระบุชื่อซึ่งจะส่งกลับเปอร์เซ็นต์ที่ต้องการ

โปรแกรมเต็มรูปแบบพร้อมวิธีการแสดงความคิดเห็นที่ไม่ดีและกรณีทดสอบ:

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⊢ แทนที่อักขระตัวที่ 5 ( -) ด้วยช่องว่าง

 ดำเนินการเพื่อรับรายการองค์ประกอบสองอย่าง

cal เรียกฟังก์ชั่นปฏิทินที่

' ', เพิ่มคอลัมน์ของช่องว่างลงในช่องนั้น

¯2⌽ หมุนสองคอลัมน์สุดท้าย (วันเสาร์) ไปที่ด้านหน้า

⍺↓ ปล่อยจำนวนอาร์กิวเมนต์แถวซ้าย (2, ส่วนหัว) และคอลัมน์ (หากระบุ; 5 = Sat + Sun)

 แบ่งเมทริกซ์เป็นรายการของเส้น

 รูปแบบ (แบนด้วยการแทรกระยะห่างสองครั้ง)

 ดำเนินการ (เปลี่ยนตัวเลขวันที่เหลือเป็นรายการตัวเลขแบบคงที่)

 นับว่า

2÷/ หารแต่ละคู่ (มีเพียงอันเดียว)

100× คูณด้วยร้อย

.5+ เพิ่มครึ่งหนึ่ง

 ชั้น

ลองออนไลน์!


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.