Посчитайте, сколько месяцев у вас полные 31 день, считая костяшки пальцев.

12

Сколько из вас все еще использует свой сустав, чтобы определить, будет ли месяц иметь полные 31 день или меньше?

Ваша задача - написать программу, которая подсчитывает, сколько месяцев в месячном диапазоне имеют полные 31 день, а сколько - менее 31 дня, «считая суставы».

Подсчет дней месяца по костяшкам

Предоставлено: amsi.org.au


вход

Пара месяцев, первый из которых не обязательно должен быть в хронологическом порядке перед вторым, в любом подходящем формате. Например: 201703 201902- с марта 2017 года по февраль 2019 года. Пожалуйста, опишите формат ввода, который вы выбрали. Обратите внимание, что входные данные должны включать все годы от 1 до 9999. Указанный диапазон месяцев включает как начальный, так и конечный месяцы.

Выход

Два целых числа: количество месяцев в данном диапазоне с 31 днем ​​и количество месяцев в диапазоне с менее чем 31 днем.

Пример: 14 10- 14 суставов, 10 канавок (это означает, что в этом месячном диапазоне у нас есть 14 месяцев, которые имеют полные 31 день, и 10 месяцев, которые имеют менее 31 дня).

Например, для ввода, где второй месяц в диапазоне находится хронологически перед первым 201612 201611, вы должны вывести пару из нуля.

Примеры ввода и вывода

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

правила

  • Вы можете выбрать любой язык, который вам нравится
  • Один вход на строку
  • Это , поэтому выигрывает самый короткий код в байтах!
  • Победитель будет выбран 9 апреля
  • Применяются стандартные лазейки
  • PS: это мой первый вопрос в PCG, в нем могут быть некоторые несоответствия. Не стесняйтесь редактировать и подтверждать то, что вам непонятно.
Ризки Пратама
источник
5
Вы говорите, что первый из них гарантированно поступит в хронологическом порядке перед вторым , но это неверно для контрольного примера 201612 201611.
Деннис
2
На сайте существует песочница, где вы можете опубликовать вопрос исключительно, чтобы устранить все сомнения.
ghosts_in_the_code
1
Тридцать дней в сентябре, апреле, июне и ноябре. После февраля все остальные имеют тридцать один. Вот как я это помню.
AdmBorkBork
@AdmBorkBork Единственная проблема - бесконечный цикл (обязательная ссылка на xkcd).
wizzwizz4
Я полагаю, вы собираетесь использовать григорианский календарь во всем диапазоне дат?
Приостановлено до дальнейшего уведомления.

Ответы:

7

Желе , 21 байт

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

Принимает участие как [[y, m], [y, m]].

Попробуйте онлайн!

Как это работает

ḅ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.
Деннис
источник
5

JavaScript (ES6), 70 68 67 64 байта

Принимает ввод как два целых числа в yyyymmформате с синтаксисом каррирования (a)(b). Выводит массив из двух целых чисел [knuckles, grooves].

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

Отформатировано и прокомментировано

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)

Контрольные примеры

NB . Третий контрольный пример не включен в этот фрагмент, поскольку он не будет работать, если в вашем браузере не включена оптимизация Tail Call.

Arnauld
источник
5

Python 2 , 92 90 86 80 байт

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

Попробуйте онлайн!

Еще 6 путем преобразования в лямбду, спасибо @math_junkie за идею. Теперь выводит список, содержащий два числа.

Предыдущая не лямбда-версия (86 байт)

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

Попробуйте онлайн, старый!

2 сохранено благодаря @ovs за помощь в избавлении от len(k). Я не думал об использовании None.

Ввод представляет собой список целых чисел в формате y1,m1,y2,m2

Некоторая заслуга благодаря @KeerthanaPrabhakaran, который получил bin(2741)[2:]раньше, чем я, который экономит 1 байт по сравнению с жестким кодированием двоичной строки.

ElPedro
источник
Впечатляет ... k = bin (2741) [2:] * (c + 1-a) взорвал мой разум
officialaimm
1
Это на 2 байта короче
ovs
Brilliant! Я пытался отработать мотыгу, чтобы избавиться len(k)от последнего кусочка. Спасибо.
ElPedro
1
Вы можете сохранить 6 байтов, используя лямбду: TIO
математик-наркоман
4

PHP , 259 256 249 248 237 221 байт

Outgolfed по aross : /codegolf//a/114512/38505

Формат ввода: 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;

Попробуйте онлайн!


Старые версии

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

Попробуйте онлайн!

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

Попробуйте онлайн!

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

Попробуйте онлайн!

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

Попробуйте онлайн!

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

Попробуйте онлайн!

ʰᵈˑ
источник
3

Пакет, 93 байта

@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%

Принимает два параметра в формате ymm (т.е. 101 - 999912). Предыдущее 129-байтовое решение на основе цикла:

@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%
Нил
источник
Неверный результат для 000101 999912, возможно, из-за ограничения целого размера?
officialaimm
1
@officialaimm Неверный формат ввода, извините - год не должен иметь начальных нулей.
Нил
3

Python 3,5 ( 164 162 154 152 150 148 140 137 байт)

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

принимает входные данные в виде ггггмм ггггмм

выводит вывод в виде number_of_knuckles number_of_grooves

  • сэкономлено 2 байта: благодаря Коул
  • сохранено 8 байт: удалены нежелательные переменные
  • сохранено 2 байта: уменьшено t = 0; k = 0 при t = k = 0
  • спас 2 байта: спасибо Коулу (я пропустил это раньше)
  • сохранено 2 байта: благодаря Keerthana
  • сохранено 8 байт: удалены нежелательные переменные
  • сохранено 3 байта: благодаря math_junkie (split ('') для split ())
officialaimm
источник
1
Я думаю, что вы можете уменьшить некоторые байты, n=intа также, возможно, немного execдурачества.
Коул
1
Я думаю, что вы можете сделать 2773&1<<r%12-1>0вместоint('101010110101'[r%12-1])
Loovjo
@ Loovjo Я получаю ошибку при этом!
officialaimm
1
использование print([k,t-k])as print(k,t-k)приведет к желаемому результату, (k,g)уменьшая тем самым 2 байта!
Киртана Прабхакаран
1
Я считаю, что вы можете заменить split(' ')наsplit()
математика наркоман
3

Python 2 , 147, 146, 142 байта

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]

Попробуйте онлайн!

  • Сохранено 4 байта - Спасибо @math_junkie за предложение предложения if-else с поиском в массиве!

Сломать код,

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]
Кеертана Прабхакаран
источник
1
Вы можете сохранить байты, заменив if-elseпредложения поиском в массиве. См. Этот пост для деталей
математика наркоман
Это был действительно классный способ! Не знал этого раньше! Благодаря!
Киртана Прабхакаран
3

PHP, 120 103 97 96 байт

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

Запустите так:

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

объяснение

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

  • Сохранено 17 байт с использованием стиля временной метки вместо стиля объекта DateTime
  • Сохранено 6 байтов, не назначая метку времени окончания даты $e, просто сравните напрямую
  • Сохраненный 1 байт, не ведя подсчет канавок, а просто вычисляя его после цикла
aross
источник
$x++а не +$x++также работает.
Титус
@Titus, у меня было , что на первый, но понял , что с $xнеинициализированным строка будет 2017-12month, что неопознанный формат и результаты в 1970
aross
Злой ... это сработало где-то. Достаточно злой, хотя он работает без литерала +в строке.
Титус
2

PowerShell , 96 байт

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

Попробуйте онлайн!

Принимает ввод как форму 2017-03. Использует встроенные библиотеки дат .NET и выполняет циклический переход от входных данных $aк $b, увеличивая каждую итерацию $x++и добавляя ее, $zесли текущим .Monthявляется -in 2,4,6,9,11(т. Е. Месяц не является 31-дневным). Затем мы выводим наши общие месяцы за вычетом не 31-дневных месяцев $x-$zи не 31-дневных месяцев $z.

Выпускает ошибку 0001-01в 9999-12тестовом случае, потому что .NET поддерживает только годы 9999, поэтому окончательный .AddMonths(1)вариант вызывает переполнение. Тем не менее выводит правильные значения, потому что это не прекращающаяся ошибка; это просто приводит к выходу из цикла.

Вероятно, было бы короче сделать это арифметически, как в ответах на Python или JavaScript, но я хотел показать подход, использующий встроенные модули .NET.

AdmBorkBork
источник
2

Баш , 113 байт

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

Попробуйте онлайн!

нужен гольф ...

принимает входные данные как 2016-03 2018-10

выходы:

  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
источник
1

Swift, 151 байт

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 - это массив из двух целых чисел в формате согласно примеру

Джон МакДауэлл
источник