Hitung berapa bulan memiliki 31 hari penuh dengan menghitung buku-buku jari

11

Berapa banyak dari Anda yang masih menggunakan buku jari Anda sendiri untuk menentukan apakah satu bulan memiliki 31 hari penuh atau kurang?

Tugas Anda adalah menulis sebuah program untuk menghitung berapa bulan, dalam rentang satu bulan, memiliki 31 hari penuh dan berapa banyak yang memiliki kurang dari 31 hari dengan "menghitung buku-buku jari".

Menghitung hari dalam sebulan dengan buku-buku jari

Courtesy: amsi.org.au


Memasukkan

Sepasang bulan, yang pertama tidak harus datang secara kronologis sebelum yang kedua, diberikan dalam format yang sesuai. Misalnya: 201703 201902- Maret 2017 hingga Februari 2019. Mohon jelaskan format input yang Anda pilih. Perhatikan bahwa input harus dapat mencakup semua tahun dari 1 hingga 9999. Kisaran bulan yang ditentukan mencakup bulan awal dan akhir.

Keluaran

Dua bilangan bulat: jumlah bulan dalam rentang yang diberikan dengan 31 hari dan jumlah bulan dalam kisaran dengan kurang dari 31 hari.

Contoh: 14 10- 14 buku jari, 10 alur (artinya dalam rentang bulan itu kita memiliki 14 bulan yang memiliki 31 hari penuh, dan 10 bulan yang memiliki kurang dari 31 hari).

Untuk input di mana bulan kedua dalam rentang datang secara kronologis sebelum yang pertama, misalnya 201612 201611, Anda harus mengeluarkan sepasang nol.

Contoh input dan output

| Input         | Output      |
|---------------|-------------|
| 201703 201902 | 14 10       |
| 201701 202008 | 26 18       |
| 000101 999912 | 69993 49995 |
| 201802 201803 | 1 1         |
| 201601 201601 | 1 0         |
| 201612 201611 | 0 0         |

Aturan

  • Anda dapat memilih bahasa apa pun yang Anda suka
  • Satu input per baris
  • Ini adalah , jadi kode terpendek dalam byte menang!
  • Pemenang akan dipilih pada 9 April
  • Celah standar berlaku
  • PS: ini pertanyaan pertamaku di PCG, mungkin ada beberapa ketidakkonsistenan. Jangan ragu untuk mengedit dan mengkonfirmasi apa yang tidak jelas untuk Anda.
Rizki Pratama
sumber
5
Anda mengatakan yang pertama dijamin datang secara kronologis sebelum yang kedua , tetapi ini salah untuk kasus uji 201612 201611.
Dennis
2
Ada kotak pasir di situs tempat Anda dapat mengeposkan pertanyaan semata-mata untuk menghilangkan semua keraguan.
ghosts_in_the_code
1
Tiga puluh hari telah September, April, Juni, dan November. Setelah Februari selesai, sisanya punya tiga puluh satu. Begitulah cara saya mengingatnya.
AdmBorkBork
@ AdmBorkBork Satu-satunya masalah dengan itu adalah perulangan tak terbatas (referensi xkcd wajib).
wizzwizz4
Saya kira Anda berniat menggunakan kalender Gregorian sepanjang rentang tanggal?
Dijeda sampai pemberitahuan lebih lanjut.

Jawaban:

7

Jelly , 21 byte

ḅ12r/ị7RḂṁ12¤żC$S×⁼Ṣ$

Mengambil input seperti [[y, m], [y, m]].

Cobalah online!

Bagaimana itu bekerja

ḅ12r/ị7RḂṁ12¤żC$S×⁼Ṣ$  Main link. Argument: [[a, b], [c, d]]

ḅ12                    Unbase 12; yield [x, y] := [ 12a + b, 12c + d].
   r/                  Reduce by range; yield [x, ..., y].
           ¤           Combine the five links to the left into a niladic chain.
      7                  Set the return value to 7.
       R                 Range; yield [1, 2, 3, 4, 5, 6, 7].
        Ḃ                Bit; yield [1, 0, 1, 0, 1, 0, 1].
         ṁ12             Mold 12; repeat the Booleans to create an array of length
                         12. Yields [1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1].
     ị                 At-index; yield the elements of the array to the right at 
                       the indices (1-based and modular) of the array to the left.
               $       Combine the two links to the left into a monadic chain.
              C          Complement; map t -> 1-t over the array.
             ż           Zip the original array with the complements.
                S      Take the sum of each column.
                    $  Combine the two links to the left into a monadic chain.
                  Ṣ      Sort [[a, b], [c, d]].
                   ⁼     Compare the result with [[a, b], [c, d]], yielding 1 if
                         the input is sorted, 0 if not.
                 ×     Multiply the results to both sides.
Dennis
sumber
5

JavaScript (ES6), 70 68 67 64 byte

Mengambil input sebagai dua bilangan bulat dalam yyyymmformat dalam sintaks currying (a)(b). Output array dua bilangan bulat [knuckles, grooves].

a=>g=(b,c=d=0)=>a>b?[c,d-c]:g(--b,c+!((b%=100)>11||b/.87&!!++d))

Diformat dan dikomentari

a =>                        // main function: takes start date (a) as input / returns g
  g = (                     // recursive function g, which takes:
        b,                  //   - b = end date
        c = d = 0           //   - c = number of knuckles
      ) =>                  // and also keeps track of: d = total number of months
    a > b ?                 // if a is greater than b:
      [ c, d - c ]          //   stop recursion and return the final result
    :                       // else:
      g(                    //   do a recursive call to g():
        --b,                //   - decrement the end date
        c +                 //   - increment the # of knuckles if
        !(                  //     both of these conditions are false:
          (b %= 100)        //     - the end month (now stored in b in 0-based indexing)
          > 11 ||           //       is greater than 11
          b / 0.87 & !!++d  //     - the number of days in this month is not 31
        )                   //       (at the same time, d is incremented if the first
      )                     //       condition is false)

Uji kasus

NB : Test case ketiga tidak termasuk dalam snippet ini, karena itu tidak akan berfungsi kecuali browser Anda telah mengaktifkan Tail Call Optimization.

Arnauld
sumber
5

Python 2 , 92 90 86 80 byte

lambda a,b,c,d:[(bin(2741)[2:]*(c+1-a))[b-1:-12+d or None].count(x)for x in'10']

Cobalah online!

6 lainnya dengan mengonversi ke lambda, dengan terima kasih kepada @math_junkie untuk idenya. Sekarang menampilkan daftar yang berisi dua angka.

Versi non-lambda sebelumnya (86 byte)

a,b,c,d=input()
for x in'10':print(bin(2741)[2:]*(c+1-a))[b-1:-12+d or None].count(x),

Cobalah online lama!

2 disimpan dengan terima kasih kepada @ovs karena telah membantu saya menyingkirkan len(k). Saya tidak berpikir untuk menggunakan None.

Input adalah daftar bilangan bulat dalam format y1,m1,y2,m2

Beberapa kredit karena @KeerthanaPrabhakaran yang didapat bin(2741)[2:]sebelum saya lakukan yang menghemat 1 byte lebih keras dari pengkodean string biner.

ElPedro
sumber
Mengesankan ... k = bin (2741) [2:] * (c + 1-a) mengejutkan saya
officialaimm
1
Ini lebih pendek 2 byte
ovs
Cemerlang! Saya sedang berusaha untuk mencangkul untuk menyingkirkan dari len(k)irisan terakhir. Terima kasih.
ElPedro
1
Anda dapat menyimpan 6 byte dengan menggunakan lambda: TIO
math junkie
4

PHP , 259 256 249 248 237 221 byte

Diungguli oleh aross : /codegolf//a/114512/38505

Masukkan format: yyyymm,yyyymm

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";foreach(new DatePeriod($_(Ym,$i[0]),new DateInterval(P1M),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))>30?++$x:++$y;
echo $x.' '.++$y;

Cobalah online!


Versi yang lebih lama

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_("Ym",$i[0]),new DateInterval('P1M'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.$y;

Cobalah online!

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_(Ym,$i[0]),DateInterval::createFromDateString('1 month'),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))>30?++$x:++$y;
echo $x.' '.$y;

Cobalah online!

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_(Ym,$i[0]),DateInterval::createFromDateString('1 month'),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))==31?++$x:++$y;
echo $x.' '.$y;

Cobalah online!

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";foreach(new DatePeriod($_("Ym",$i[0]),DateInterval::createFromDateString('1 month'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.++$y;

Cobalah online!

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_("Ym",$i[0]),DateInterval::createFromDateString('1 month'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.$y;

Cobalah online!

ʰᵈˑ
sumber
3

Batch, 93 byte

@set/ag=(y=%2/100-%1/100)*5+(x=%2%%100+6)*5/12-(w=%1%%100+5)*5/12,k=y*12+x-w-g
@echo %k% %g%

Menerima dua parameter dalam format ymm (yaitu 101 - 999912). Solusi berbasis loop 129-byte sebelumnya:

@set/al=%1-%1/100*88,u=%2-%2/100*88,k=g=0
@for /l %%i in (%l%,1,%u%)do @set/a"m=%%i%%12,k+=1451>>m&1,g+=2644>>m&1
@echo %k% %g%
Neil
sumber
Hasil yang salah untuk 000101 999912, mungkin karena batas ukuran bilangan bulat?
officialaimm
1
@officialaimm Format input salah, maaf - tahun seharusnya tidak memiliki nol di depan.
Neil
3

Python 3.5 ( 164 162 154 152 150 148 140 137 bytes)

n=int;a,b=input().split();t=k=0
for r in range(n(a[4:]),(n(b[:4])-n(a[:4]))*12+n(b[4:])+1):t+=1;k+=n('101010110101'[r%12-1])
print(k,t-k)

repl.it

mengambil input dalam bentuk yyyymm yyyymm

mencetak output sebagai number_of_knuckles number_of_grooves

  • disimpan 2 byte: Terima kasih kepada Cole
  • disimpan 8 byte: menghapus variabel yang tidak diinginkan
  • disimpan 2 byte: dikurangi t = 0; k = 0 karena t = k = 0
  • disimpan 2 byte: Terima kasih kepada Cole (saya telah melewatkan ini sebelumnya)
  • disimpan 2 byte: Terima kasih ke Keerthana
  • disimpan 8 byte: menghapus variabel yang tidak diinginkan
  • disimpan 3 byte: Berkat math_junkie (split ('') to split ())
officialaimm
sumber
1
Saya pikir Anda dapat mengurangi beberapa byte dengan melakukan n=intdan mungkin juga exectindakan gila-gilaan.
cole
1
Saya pikir Anda dapat melakukannya 2773&1<<r%12-1>0sebagai gantinyaint('101010110101'[r%12-1])
Loovjo
@ Loojo Saya mendapatkan kesalahan saat melakukannya!
officialaimm
1
menggunakan print([k,t-k])apa yang print(k,t-k)akan menghasilkan hasil yang diinginkan (k,g)sehingga mengurangi 2 byte!
Keerthana Prabhakaran
1
Saya yakin Anda bisa menggantinya split(' ')dengansplit()
pecandu matematika
3

Python 2 , 147 146 142 byte

def s(a,b):y=100;r=bin(2741)[2:];x=b/y-a/y;i=r*(x-1);return((0,0),map((i+r[a%y-1:]+r[:b%y]if i or x else r[a%y-1:b%y]).count,('1','0')))[a<=b]

Cobalah online!

  • Disimpan 4 byte - Terima kasih kepada @math_junkie untuk menyarankan klausa if-else dengan pencarian array!

Memecah kode,

def s(a,b):
 y=100
 r=bin(2741)[2:] #'101010110101'
 x=b/y-a/y #to get the difference between the two years
 i=r*(x-1)
 return((0,0),map((i+r[a%y-1:]+r[:b%y]if i or x else r[a%y-1:b%y]).count,('1','0')))[a<=b]
Keerthana Prabhakaran
sumber
1
Anda dapat menyimpan byte dengan mengganti if-elseklausa dengan pencarian array. Lihat posting ini untuk detail
pecandu matematika
Itu memang cara yang keren! Tidak tahu itu sebelumnya! Terima kasih!
Keerthana Prabhakaran
3

PHP, 120 103 97 96 byte

for($f=strtotime;$f($argv[2])>=$n=$f($argv[1].+$x++.month);)$k+=date(t,$n)>30;echo+$k,_,$x-1-$k;

Jalankan seperti ini:

php -nr 'for($f=strtotime;$f($argv[2])>=$n=$f($argv[1].+$x++.month);)$k+=date(t,$n)>30;echo+$k,_,$x-1-$k;' 0001-01 9999-12;echo
> 69993_49995

Penjelasan

for(
  $f=strtotime;          # Alias strtotime function which is called twice.
  $f($argv[2]) >=        # Create end date timestamp. Iterate until the end
                         # date is reached.
  $n=$f(
    $argv[1].+$x++.month # Create timestamp from start date + X months.
  );
)
  $k+=date(t,$n) > 30;   # If "t" of current date (days in month) is 31
                         # increment $k (knuckles).

echo+$k,_,$x-1-$k;       # Compute grooves (iterations - $k) and output,
                         # implicit cast to int to account for 0 count.

Tweaks

  • Disimpan 17 byte dengan menggunakan gaya cap waktu alih-alih gaya objek DateTime
  • Disimpan 6 byte dengan tidak menetapkan timestamp tanggal akhir untuk variabel $e, cukup bandingkan secara langsung
  • Disimpan 1 byte dengan tidak menyimpan hitungan alur, tetapi hanya menghitungnya setelah loop
aross
sumber
$x++alih-alih +$x++juga bekerja.
Titus
@Itus, saya punya itu pada awalnya, tetapi menyadari bahwa dengan $xtidak diinisialisasi string akan menjadi 2017-12month, yang merupakan format yang tidak dikenal dan hasil pada tahun 1970
aross
Jahat ... itu berhasil di suatu tempat. Cukup jahat meskipun itu bekerja tanpa literal +dalam string.
Titus
2

PowerShell , 96 byte

for($a,$b=[datetime[]]$args;$a-le$b;$a=$a.AddMonths(1)){$x++;$z+=$a.Month-in2,4,6,9,11};$x-$z;$z

Cobalah online!

Mengambil input sebagai formulir 2017-03. Menggunakan pustaka tanggal .NET bawaan dan loop dari input $ake $b, setiap iterasi menambah $x++dan menambahkan $zjika saat .Monthini -in 2,4,6,9,11(yaitu, bulan non-31 hari). Kemudian kami menampilkan total bulan kami dikurangi bulan non-31 hari $x-$z, dan bulan non-31 hari $z.

Tosses kesalahan pada 0001-01untuk 9999-12menguji kasus, karena .NET hanya mendukung tahun hingga 9999, sehingga final .AddMonths(1)menyebabkan overflow. Tetap menampilkan nilai yang benar, karena itu adalah kesalahan yang tidak berhenti; itu hanya menyebabkan loop keluar.

Mungkin akan lebih pendek untuk melakukan ini secara hitung, seperti jawaban Python atau JavaScript, tetapi saya ingin menunjukkan pendekatan menggunakan .NET built-in.

AdmBorkBork
sumber
2

Pesta , 113 byte

s="$1-1";e="$2-1";sort <(while [ "$s" \< "$e" ];do s=$(date +%F -d"$s+1month");date +%d -d"$s-1day";done)|uniq -c

Cobalah online!

membutuhkan golf ...

menerima input sebagai 2016-03 2018-10

output:

  1 28
  7 30
 12 31

ungolfed:

s="$1-1"
e="$2-1"                     # adds first day of month to the dates
sort <(                    
while [ "$s" \< "$e" ]; do   #iterates over dates
s=$(date +%F -d"$s+1month")  #adds one month to start date
date +%d -d"$s-1day"         #outputs last day of previous month
done) | uniq -c              #counts ocurrences of day number prevously sorted
marcosm
sumber
1

Cepat, 151 byte

let f={(m:[Int])->[Int] in var k=[0,0]
(m.min()!...m.max()!).map{$0%100}.filter{$0>0&&$0<13}.forEach{m in let n = m>7 ?m-7:m
k[(n%2+1)%2]+=1}
return k}

input adalah array dua bilangan bulat dalam format sesuai contoh

John McDowall
sumber