Наступне державне свято


18

Австралійці люблять державні свята та пиття. Вчора, 26 січня, був день Австралії, який є державним святом. Я був радий, що не був учора на роботі, і хотів дізнатися наступного разу, коли я отримаю державне свято! На жаль, я випив трохи забагато, і я не в змозі це зробити для себе.

Напишіть програму, яка буде вводити дату в австралійських позначеннях дати / часу (дд / мм) і вводити кількість днів до наступного державного свята. Оскільки я житель штату Квінсленд (QLD), мене цікавлять лише державні свята, які впливають на Квінслендер :

25/03 | Страсна п’ятниця
26/03 | Великодня субота
28/03 | Великодній понеділок
25/04 | День Анзака
02/05 | День праці
03/10 | День народження королеви
25/12 | Різдво
26/12 | День боксу
27/12 | Свято Різдва

Зверніть увагу на таке:

Свято Різдва

Додаткове державне свято, яке слід додати, коли Новий рік, Різдво чи День боксу припадає на вихідні.

Оскільки день Різдва в неділю, є додаткове державне свято. День Різдва все ще є державним святом.

Оскільки я людина вранці, вам слід включити поточну дату як день (оскільки це найімовірніший раз, коли я перевірю вашу програму на наступне державне свято). Тобто, якщо введено дату святкового дня, ваш результат повинен бути 0; якщо за день до вступу на державне свято, ваш результат буде 1.

Мене цікавлять лише дати, які відбудуться зараз (27/01) до кінця року. Кінцева дата, яку вам потрібно буде врахувати, - 31/12, де буде ваш результат 1(на день Нового року).

Стандартні лазівки заборонені.

Вхідні дані

  • Вхід завжди буде 5 символів: 4 літери, розділені дефісом -або косою рисою/
  • Введіть лише дату між 27/01 та 31/12

Вихід

  • Число днів до наступного святкового дня в Квінсленді Австралії, включаючи дату введення: має бути число між 0і 153(найдовший зазор)
  • Ніяких нових рядків чи помилок

Приклади

01-05 = 1  
02-05 = 0  
03-05 = 153  
25/12 = 0
26-12 = 0
27/12 = 0
30/12 = 2
31-12 = 1

Сподіваємось, це зрозуміло і нічого не пропущено; однак це моє друге питання, тому я буду вдячний за будь-який зворотній зв'язок і докладу всіх зусиль, щоб якнайшвидше вирішити проблеми.


@insertusernamehere Дякую за чудову пропозицію! Я додав дати до запитання
Tas

@ Ти впевнений, що ці дати точні? Приклади, наведені в прикладах, не відповідають ціні, і обидва вони не відповідають веб-сайту.
Адам Мартін

@AdamMartin Дякую за вказівку на це. Я неправильно вказав грудні дати. Наведені в прикладі - це будь-які дати, не характерні для державних свят. Вони - лише приклади дат, які можна було б ввести, і яким повинен бути результат. Наведені з них повинні (і , сподіваюся , у) збігаються з тими , з веб - сайту.
Тас

Ви святкуєте день народження королеви в жовтні в Квінсленді? Це так дивно, але здається правильним за посиланням.
Рівень річки Св.

Вау, хлопці, у вас немає свят з червня по вересень? Це грубо.
Джо З.

Відповіді:


2

Піта , 98 84 62 67 байт

Оновлення: збережено 14 байт шляхом скорочення списку кількості днів за всі 12 місяців для обчислення числа дня. Не знайшли хорошого способу стиснути інший список тхо, все ще намагаючись!

Update2: Збережено ще 22 байти шляхом енкодування списку номерів днів у вигляді рядка base256.

J30KhJ=Yc:z"\W"dd=N+s<[KtJKJKJKKJKJK)tseYshY-hfgTNCMc"UVXt{ĕŨũŪů"1N

Спробуйте в Інтернеті!

Той самий алгоритм, як і у моїй відповіді Python. І жодного вбудованого, щоб отримати день року, тому мені довелося це зробити самому. Створення цих 2 списків для розрахунку на день року та для днів канікул досить дорого ... Погляньте на це ще раз і спробую генерувати їх у меншій кількості байтів.


Здається, не подобається введення, розділене дефісом, але в іншому випадку це чудово
Tas

@Tas Дякую за підказку, повністю перечитайте цю частину ... Виправлено це вартістю ще 5 байт. Можливо, вам слід додати кілька дефісів до тестів, оскільки ви хочете, щоб вони охоплювали всі можливі варіанти введення.
Денкер

5

Visual Basic для додатків, 155 або 118 байт

Версія 1 - незалежна від локалі, 155 байт

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-DateSerial(16,Val(Right(d,2)),Val(Left(d,2)))
If h>=0Goto 9
Next
9 End Function

Версія 2 - залежна від локалі, 118 байт

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-CDate(d)
If h>=0Goto 9
Next
9 End Function

Кількість байтів призначена для остаточного файлу .BAS, включаючи символи передачі рядків. Відредагований поза стандартним редактором VBA (оскільки він накладає додаткові пробіли та багатослівні форми деяких ключових слів) - але імпортує та працює безперебійно на будь-який додаток Office (для тестового типу, наприклад ? h("10/08"), у прямому вікні або в Excel, безпосередньо у формулі комірки).

(РЕДАКТИРОВАНО) Спочатку я вирішив використовувати, DateSerialщоб зробити функцію безпечною для локальної роботи (версія 1). Оскільки я живу в Бразилії, і тому моя система налаштована на використання формату "dd / mm / yy" для дат (як і в Австралії), я можу написати ще меншу версію, використовуючи CDateнатомість (версія 2). CDateвикористовує інформацію про локальну систему для перетворення тексту в дату. У цій версії я також припускав, що код буде виконуватися лише протягом 2016 року (якщо рік опущений (-6 байт) CDateпередбачає поточний рік за системними тактовими годинниками).

Число 42454 на третьому рядку - це сума 42450, що є числовим представленням 01.01.2016 по VBA, а 84 - день року для першого відпустки. Масив містить день року за кожним святом (включаючи 01.01.2017), зміщеним на -84, оскільки це забирає кілька цифр. Використання 16 замість 2016 року DateSerialзабирає ще два байти.

Створення ідентичного масиву дев'ять разів всередині ітерації - це "поганий" код, але він працює і зберігає ще 3 байти (один для імені масиву і один для зовнішнього циклу знаку рівності, і ще один для посилання на масив всередині циклу).

Пропуски "відсутні" між 0 та наступним ключовим словом у другому та четвертому рядках не потрібні, оскільки вони автоматично вводяться VBE при імпорті модуля. Використовується застарілий, але байт-дешевий, If <...> Goto <linenumber>щоб вийти з циклу (обидва If <...> Then Exit Forта If <...> Then Exit Functionвикористовувати більше символів).

Також скористався тим, що ім'я функції в VBA поводиться як локальна змінна, а її значення автоматично повертається функцією в кінці виконання.


Ласкаво просимо до PPCG! Тут ми визначаємо мову програмування за допомогою інтерпретатора, тому цілком прийнятно вимагати певної мови.
lirtosiast

Спасибі! Відредаговано, щоб додати меншу версію, що залежить від місця.
день

4

JavaScript (ES6), 131 128 байт

d=>[56,57,59,87,94,248,331,332,333,338].map(n=>r=r||(q=1454e9+n*864e5-new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`))>=0&&q/864e5,r=0)|r

Пояснення

Використовує вбудований Dateконструктор JavaScript для перетворення вхідного рядка в число мілісекунд з епохи, а потім порівнює це з кількістю мілісекунд для кожного державного свята.

Це робиться шляхом зберігання державних свят у масиві як кількість днів з моменту опорної дати. Я вибрав 2016-01-29для опорної дати, оскільки кількість мілісекунд з моменту епохи може бути скорочена найменше для цієї дати. Будь-яка кількість мілісекунд між цим днем ​​і наступним працює, оскільки результат округлюється вниз, а збереження числа в середині дозволяє уникнути літнього часу (хоча часовий пояс ОП не забезпечує економію денного світла). Число цього дня є, 1453986000000а округлення його до 1454000000000(додавання пари годин) означає, що його можна записати як 1454e9.

d=>
  [56,57,59,87,94,248,331,332,333,338]             // list of day offsets from 01/29
  .map(n=>                                         // for each public holiday offset n
    r=r||                                          // if r is already set, do nothing
      (q=                                          // q = approximate difference in ms
        1454e9+n*864e5                             // time of public holiday
        -new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`)    // time of input date
      )
      >=0&&                                        // if q >= 0
        q/864e5,                                   // r = q in days
    r=0                                            // r = result
  )
  |r                                               // floor and return r

Тест

Це рішення залежить від часового поясу користувача. Це працює у часовому поясі ОП (і мій) (GMT +1000). Якщо ви хочете перевірити його в іншому часовому поясі, додавання numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000до номера опорної дати має спрацювати. (наприклад, GMT +0430 буде -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)


Це завжди дає 0, коли дата відокремлена дефісом. Я вже попросив ОП відрегулювати його тести, тому що всі вони є косою рисою.
Денкер

@DenkerAffe О, я думав, він мав на увазі, що ми можемо вибрати роздільник. До речі, зробивши його роздільником-амбівалентним, врятувало мені 3 байти, тож спасибі!
користувач81655

1
Здається, що правило separated with a hyphen - or slash /трохи неоднозначне. Для мене це означає, що ми маємо мати справу з обома, але я точно можу побачити вашу сторону. Здогадайтесь, ОП повинна це прояснити.
Денкер

3

T-SQL, 210 , 206 , 194 байт

(Перший пост тут, сподіваюся, це нормально, але будь ласка, приємно :)

Вхід йде в @i, задовольняє як /і -роздільник. Я в Австралії, тому мій формат дати такий же, як і @Tas

DECLARE @i CHAR(5)='23-09';DECLARE @c INT=DATEPART(dy,CAST(REPLACE(@i,'-','/')+'/2016' AS DATE))-1;SELECT MIN(b)-@c FROM(VALUES(84),(85),(87),(115),(122),(276),(359),(360),(361))a(b)WHERE b>=@c;

Оновити varchar доchar зберігає 3 байт плюс видалив пробіл :)

Оновлення 2 оголосити @cта призначити без вибору


2

T-SQL, 296 байт

Створено як табличну функцію

create function d(@ char(5))returns table return select min(o)o from(select datediff(day,cast('2016'+right(@,2)+left(@,2)as date),cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1)o from(values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231))d(d))d where 0<=o

Використовується наступним чином

SELECT *
FROM (
    VALUES
        ('01/05') --= 1  
        ,('02/05') --= 0  
        ,('03/05') --= 153  
        ,('25/12') --= 0
        ,('26/12') --= 0
        ,('27/12') --= 0
        ,('30/12') --= 2
        ,('31/12') --= 1
    )testData(i)
    CROSS APPLY (
        SELECT * FROM d(t)
    ) out

i     o
----- -----------
01/05 1
02/05 0
03/05 153
25/12 0
26/12 0
27/12 0
30/12 2
31/12 1

(8 row(s) affected)

Коротке пояснення

create function d(@ char(5)) returns table  -- function definition
return 
select min(o)o -- minimum set value
from(
    select datediff( -- date difference
        day, -- day units
        cast('2016'+right(@,2)+left(@,2)as date), -- convert input parameter to date
        cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1 -- convert int values into datetimes and add a day
        )o 
    from(
        values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231) -- integers representing the day before public holidays
        )d(d)
    )d 
where 0<=o -- only for values >= 0

2

JavaScript (ES6), 134 байти

x=>[0,1,3,31,38,192,275,276,277,282].find(z=>z>=(q=x[0]+x[1]- -[...'20212122121'].slice(0,x[3]+x[4]-1).reduce((a,b)=>+b+a+29,0)-85))-q

user81655 все ще мене побили на 3 байти, але я не можу знайти більше ніде, щоб вичавити звідси щось. Працює, обчислюючи кількість минулих днів, а не використовуючи дату, а потім порівнюючи її з масивом компенсацій відпусток.


2

Пітон 2, 204 185 165 166 байт

Оновлення: Розмістив його на ~ 20 байт, вирахувавши день у році сам. Більше не потрібно довго імпортувати :)

Оновлення 2: Ще 20 байт вниз, зрозумівши, що я можу ставитися до нових років так само, як день 367, і внісши деякі інші невеликі корективи.

def f(d):d=[d[:2],d[3:]];y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0]);return filter(lambda n:n>=y,[85,86,88,116,123,277,360,361,362,367])[0]-y

Спробуйте в Інтернеті!

Безголівки:

def f(d):
    l=[85,86,88,116,123,277,360,361,362,367]
    d=[d[:2],d[3:]]
    y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0])
    f=filter(lambda n:n>=y,l)
    return f[0]-y

Працює, зберігаючи в списку число днів року відпусток, фільтруючи ті, що знаходяться до зазначеної дати, бере перший елемент у цьому відфільтрованому списку і віднімає день року, який отримано підрахунок із вхідних даних.


1

PHP, 116 байт

Досить прямий підхід вперед. У ньому зберігаються дні року до свят та з’являються їх доти, доки вони були в минулому. Нарешті запитуваний день року віднімається.

for($x=[366,361,360,359,276,122,115,87,85,84];($a=date(z,strtotime($argv[1].'-2016')))>$t=array_pop($x););echo$t-$a;

Минулі всі тестові справи. Запускається з командного рядка та приймає введення за допомогою дефісу, наприклад:

$ php holidays.php "12-05"

1

рубін 1.9.3, 155 153 байт

Після свята Різдва, нам потрібен наш супер-особливий день 366! Схожий випадок, як @DenkerAffe.

require'date'
c=(Date.strptime(ARGV[0],'%d/%m')-Date.parse('01/01')).to_i
print [84,85,87,115,122,276,359,360,361,366].map{|i|(i-c)}.select{|i|i>=0}.min

Використання:

$ ruby i_want_to_break_free.rb "03/05"

Я мало знаю про Ruby, але я думаю, що ви можете зберегти 3 байти, видаливши пробіли в рядках 1 і 3. Також слід вказати, який метод введення ви використовуєте, оскільки це не так очевидно у вашому коді. Ви можете зберегти деякі байти, визначивши функцію, щоб ви могли взяти вхід як аргумент і використовувати повернене значення як вихід.
Денкер

@DenkerAffe Дуже дякую! Я зберег 2 байти, але думаю, що функція збільшить кількість. Я оновив відповідь на прикладі використання.
Тарод

0

05AB1E , 45 байт

•9JRt€ª´Q®Ië•368вDI„-/S¡`•Σ₁t•ºS₂+s<£O+©@Ïн®-

Можливо, це вже не 2016 рік, але все-таки ..;) Все ж передбачається, що 2016 рік є високосним 29для лютого.

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

9JRt€ª´Q®Ië•  # Push compressed integer 10549819042671399072072399
  368в         # Converted to base-368 as list: [85,86,88,116,123,277,360,361,362,367]
      D        # Duplicate this list
I              # Take the input
 „-/S¡         # Split it on ["-","/"]
      `        # Push both integer separated to the stack
•Σ₁t          # Push compressed integer 5354545
     º         # Mirror it without overlap: 53545455454535
      S        # Converted to a list of digits: [5,3,5,4,5,4,5,5,4,5,4,5,3,5]
       ₂+      # Add 26 to each: [31,29,31,30,31,30,31,31,30,31,30,31,29,31]
         s     # Swap to get the month-integer
          <    # Decrease it by 1
           £   # Only leave the first month-1 values from the integer-list
            O  # Sum that sublist
             + # And add it to the day-integer (so we now have the N'th day of the year)
©              # Save this in the register (without popping)
 @             # Do a >= check with each integer in the first (duplicated) list we created
  Ï            # Only leave the truthy values from the list
   н           # Then pop this sublist and only leave its first value
    ®-         # And subtract the integer we saved in the register (N'th day of the year)
               # (after which the result is output implicitly)

Ознайомтеся з цією підказкою 05AB1E (розділи Як стиснути великі цілі числа? Та Як стиснути цілі списки? ), Щоб зрозуміти, чому •9JRt€ª´Q®Ië•це 10549819042671399072072399; •9JRt€ª´Q®Ië•368вє [85,86,88,116,123,277,360,361,362,367]; і •Σ₁t•є 5354545.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.