É uma tarefa anual, tudo bem

22

Dado um número 1≤n≤365, produza o enésimo dia do ano no formato "Dia número do mês". Por exemplo, dado 1, você deve exibir "1º de janeiro", sem "de".

O calendário gregoriano será usado e o programa não deve contabilizar anos bissextos; portanto, seu programa nunca deve exibir "29 de fevereiro" em nenhuma circunstância. Qualquer método pode ser usado, desde que siga o formato "Dia número do mês" mencionado anteriormente. Seu programa também deve produzir ordinais corretamente, o que significa que sempre deve gerar 1º, 2º, 3º, 1, 2 ou 3, respectivamente, os números dos dias de qualquer entrada. Espaços à esquerda ou outro recuo são permitidos.

Isso é código de golfe, então a solução mais curta por caracteres vence.

Casos de teste:

1 gives 1st January
2 gives 2nd January
3 gives 3rd January
365 gives 31st December
60 gives 1st March
11 gives 11th January
Andrew
fonte
4
Além disso, você precisa forçar uma mensagem de erro em números> 365? O programa pode simplesmente assumir que é uma entrada inválida e não precisará lidar com isso?
Rɪᴋᴇʀ
5
Como nem todos são falantes nativos de inglês, convém adicionar nesse dia os números 11, 12 e 13 get "th", números que terminam em "1" get "st", "2" get "nd", "3" get "rd" e todos os outros get "th".
Adám 13/03
9
Whoa, não aceite respostas tão rapidamente. Especialmente respostas erradas !
Adám 13/03
6
Você deve adicionar pelo menos 11(11 th janeiro) e 21(21 st janeiro) para os casos de teste.
Arnauld 13/03
1
E enquanto você estiver editando casos de teste, talvez especifique qual é exatamente o seu formato de caso de teste. Alguns respondedores pensaram que isso 123=fazia parte da saída necessária. Ou simplesmente edite seus casos de teste para ler algo como: 365gives31st December
Adám

Respostas:

9

PHP ,38. 40. 30 28 bytes

<?=date("jS F",86399*$argn);

Experimente online!

Executar com php -nFentrada é de STDIN. Exemplo (script acima nomeado y.php):

$ echo 1|php -nF y.php
1st January
$ echo 2| php -nF y.php
2nd January
$ echo 3| php -nF y.php
3rd January
$ echo 11|php -nF y.php
11th January
$ echo 21|php -nF y.php
21st January
$ echo 60|php -nF y.php
1st March
$ echo 365|php -nF y.php
31st December

Explicação

Construa um registro de data e hora da época para o dia desejado em 1970 (convenientemente não é um ano bissexto) multiplicando o day number * number of seconds per day(86400). No entanto, isso renderia um dia mais alto e, em vez disso, se multiplicaria por number of seconds in a day - 1(86399) que, para o intervalo de números de entrada (1≤n≤365), resultará no registro de data e hora do final de cada dia correto. Em seguida, basta usar a formatação de data interna do PHP para saída.

640KB
fonte
por que é -nnecessário?
Ven
@Ven pode não estar em todos os casos, mas apenas desabilita as configurações no php.ini local que podem criar um comportamento inconsistente.
640KB 13/03
6

Geléia ,  79 78  77 bytes

-1 corrigindo um bug :) (não deve pré-transpor para encontrar o índice, deve pós-inverter, mas depois podemos ajustar em vez de avançar)
-1 usando reflexão ( ⁽©ṅB+30_2¦2-> ⁽0ṗb4+28m0)

⁽0ṗb4+28m0SRṁRƲœiµṪȮ%30%20«4ị“nḄƲf⁷»s3¤Ṗ,ị“£ṢtẒ⁽ẹ½MḊxɲȧėAṅ ɓaṾ¥D¹ṀẏD8÷ṬØ»Ḳ¤$K

Um programa completo que imprime o resultado

Experimente online!

Quão?

atualizará isso mais tarde ...

⁽©ṅB+30_2¦2SRṁRƲZœiµḢȮ%30%20«4ị“nḄƲf⁷»s3¤Ṗ,ị“...»Ḳ¤$K - Main Link: integer, n
⁽©ṅB+30_2¦2SRṁRƲZœi - f(n) to get list of integers, [day, month]
⁽©ṅ                 - compressed literal 2741
   B                - to a list of binary digits -> [ 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1]
    +30             - add thirty                    [31,30,31,30,31,30,31,31,30,31,30,31]
         ¦          - sparse application...
        2           - ...to indices: [2]
       _  2         - ...action: subtract two       [31,28,31,30,31,30,31,31,30,31,30,31]
               Ʋ    - last four links as a monad - i.e. f(x):
           S        -   sum x                       365
            R       -   range                       [1..365]
              R     -   range x (vectorises)        [[1..31],[1..28],...]
             ṁ      -   mould like                  [[1..31],[32..59],...]
                Z   - transpose                     [[1,32,...],[2,33,...],...]
                 œi - 1st multi-dimensional index of n  -> [day, month]

µḢȮ%30%20«4ị“nḄƲf⁷»s3¤Ṗ,ị“...»Ḳ¤$K - given [day, month] format and print
µ                                  - start a new monadic chain - i.e. f(x=[day, month])
 Ḣ                                 - head -- get the day leaving x as [month])
  Ȯ                                - print it (with no newline) and yield it
   %30                             - modulo by thirty
      %20                          - modulo by twenty
         «4                        - minimum of that and four
                     ¤             - nilad followed by link(s) as a nilad:
            “nḄƲf⁷»                -   dictionary words "standard"+" the" = "standard the"
                   s3              -   split into threes = ["sta","nda","rd ","the"]
           ị                       - index into
                      Ṗ            - remove rightmost character
                               ¤   - nilad followed by link(s) as a nilad:
                         “...»     -   dictionary words "January"+" February"+...
                              Ḳ    -   split at spaces = ["January","February",...]
                        ị          - index into (vectorises across [month])
                       ,           - pair                  e.g. ["th", ["February"]]
                                K  - join with spaces           ["th ", "February"]
                                   - print (implicitly smashes)   th February
Jonathan Allan
fonte
4
O truque "padrão" é incrível.
Ven
Concordo com @Ven , ótimo truque! Ele também salvou um byte na minha resposta 05AB1E em comparação com a string compactada "thstndrd"dividida em partes do tamanho 2 ( .•oθ2(w•2ô), então, obrigado. :)
Kevin Cruijssen 15/03
1
Esse deve ser um dos mais longos programas de geléia que eu já vi.
JAD 15/03
6

C # (compilador interativo do Visual C #) , 115 113 109 98 bytes

g=>$"{f=(g=p.AddDays(g-1)).Day}{"tsnr"[f=f%30%20<4?f%10:0]}{"htdd"[f]} {g:MMMM}";DateTime p;int f;

Obrigado a alguém por salvar 9 bytes

Experimente online!

Modalidade de ignorância
fonte
1
@KevinCruijssen Eu tenho os módulos fora de ordem, devem ser corrigidos agora.
Modalidade de ignorância
.code.tio(2,22): error CS0165: Use of unassigned local variable 'p'Parece que a coisa struct não funciona.
JAD 15/03
var g=new DateTime().AddDays(n-1)funciona embora
JAD
@JAD erro da minha parte, corrigido
Modalidade de Ignorância
110 bytes eu acho
meu pronome é monicareinstate
5

Python 3.8 (pré-lançamento) , 112 bytes

lambda x:str(d:=(t:=gmtime(x*86399)).tm_mday)+'tsnrhtdd'[d%5*(d%30%20<4)::4]+strftime(' %B',t)
from time import*

Experimente online!

Por incrível que pareça, não preciso colocar parênteses d:=(t:=gmtime(~-x*86400), provavelmente porque o intérprete verifica apenas se há ()caracteres em torno da expressão de atribuição e não se a expressão em si está entre parênteses.

-2 graças a gwaugh .
-5 graças a xnor .

Erik, o Outgolfer
fonte
5

Perl 6 , 166 161 bytes

{~(.day~(<th st nd rd>[.day%30%20]||'th'),<January February March April May June July August September October November December>[.month-1])}o*+Date.new(1,1,1)-1

Experimente online!

Codifica todos os nomes dos meses, ocupando a maior parte do espaço. Cara, o Perl 6 realmente precisa de um formatador de data adequado.

Brincadeira
fonte
4

Hack, 115 59 39 bytes

$x==>date("jS F",mktime(0,0,0,1,$x));

Como o @gwaugh chegou à mesma solução que a minha enquanto jogava golfe, estou postando isso no Hack :).

Ven
fonte
Uau, grandes mentes pensam da mesma forma. :) +1 para você, senhor!
640KB 13/03
@ gwaugh haha, eu não sabia que poderia ter apenas um programa de nível superior. Vou editar meu para torná-lo de nível superior também, e encontrar uma maneira de obter uma melhor SCOR e ;-)
Ven
1
@gwaugh Feito meu hack em vez disso.
Ven
1
Você provavelmente desejará especificar um parâmetro de ano não bissexto para sua mktime()chamada, caso contrário, ele retornará a saída errada se for executado em um ano bissexto. (teve que fazer a minha resposta).
640KB 13/03
4

JavaScript (ES6),  117  113 bytes

Guardado 4 bytes graças a @tsh

d=>(n=(d=new Date(1,0,d)).getDate())+([,'st','nd','rd'][n%30%20]||'th')+' '+d.toLocaleString('en',{month:'long'})

Experimente online!

Comentado

d =>                     // d = input day
  ( n =                  //
    ( d =                // convert d to
      new Date(1, 0, d)  //   a Date object for the non leap year 1901
    ).getDate()          // save the corresponding day of month into n
  ) + (                  //
    [, 'st', 'nd', 'rd'] // ordinal suffixes
    [n % 30 % 20]        // map { 1, 2, 3, 21, 22, 23, 31 } to { 'st', 'nd', 'rd' }
    || 'th'              // or use 'th' for everything else
  ) + ' ' +              // append a space
  d.toLocaleString(      // convert d to ...
    'en',                // ... the English ...
    { month: 'long' }    // ... month name
  )                      //

Sem data incorporada, 188 bytes

f=(d,m=0)=>d>(k=31-(1115212>>m*2&3))?f(d-k,m+1):d+([,'st','nd','rd'][d%30%20]||'th')+' '+`JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember`.match(/.[a-z]*/g)[m]

Experimente online!

Arnauld
fonte
Falha no 11, 12, 13 de cada mês
Data
1
@ExpiredData Obrigado por denunciar isso. Corrigido agora.
Arnauld
Ignorar meu comentário, cometi um erro de ID10T.
asgallant 13/03
Não tenho certeza de como o nodejs lida com tags de idioma, mas parece que o uso 0funcionaria como o uso "en". E mudar para toLocaleStringeconomizaria 4 bytes. 110 bytes
tsh 14/03
@tsh Parece que toLocaleStringestá usando as configurações padrão do sistema quando é transmitida uma string não reconhecida ou um valor numérico. Então, pode ser qualquer coisa. Esse parâmetro é basicamente ineficaz em uma instância do TIO, porque apenas as localidades em inglês são instaladas de qualquer maneira.
Arnauld
4

Smalltalk, 126 bytes

d:=Date year:1day:n.k:=m:=d dayOfMonth.10<k&(k<14)and:[k:=0].o:={#st.#nd.#rd}at:k\\10ifAbsent:#th.m asString,o,' ',d monthName
Leandro Caniglia
fonte
1
Não conheço o Smalltalk, mas isso está correto 11th,12th,13th? Se eu ler corretamente, você divide o número inteiro por 10, mas isso significaria que isso resultaria 11st,12nd,13rd, a menos que algo mais no código corrija isso enquanto eu não o conheço.
Kevin Cruijssen 14/03
@KevinCruijssen Você está certo. Obrigado por chamar minha atenção para isso. Vou precisar gastar mais alguns bytes para corrigir isso.
Leandro Caniglia 14/03
1
@KevinCruijssen, Concluído. Obrigado novamente.
Leandro Caniglia 15/03
3

C # (compilador interativo do Visual C #) , 141 139 133 124 122 bytes

a=>{var d=s.AddDays(a-1);int x=d.Day,m=x%30%20;return x+"thstndrd".Substring(m<4?m*2:0,2)+d.ToString(" MMMM");};DateTime s

Agradecimentos a Arnauld pelo método mais rápido de remover 11,12,13th economizando 4 bytes

Experimente online!

Dados expirados
fonte
Usando o C # 8, isso pode ser reduzido para: a=>{var d=s.AddDays(a-1);int x=d.Day,m=x%30%20;return x+"thstndrd"[(m<4?m*2:0)..2]+$" {d:MMMM}";};DateTime s O compilador interativo parece não suportar a alteração de seu nível de idioma para "visualização" no momento.
Arcanox 13/03
116 bytes
Modalidade de ignorância
Tenho certeza que você deve adicionar um ponto-e-vírgula após oDataTime s
Modalidade de Ignorância
3

R , 158 134 bytes

-24 bytes @Nick Kennedy por jogar golfe em 'st', 'nd', 'rd' e 'th'. Obrigado!

f=format;paste0(a<-as.double(f(d<-as.Date(scan(,''),'%j'),'%e')),`if`((a-1)%%10>2|a%/%10==1,'th',c("st","nd","rd")[a%%10]),f(d,' %B'))

Experimente online!

CT Hall
fonte
Sim, preciso aprender `if`melhor. Obrigado.
CT Hall
3

MySQL, 47 45 42 bytes

SELECT DATE_FORMAT(MAKEDATE(1,n),"%D %M")

1901 pode ser substituído por qualquer ano que foi / não é um ano bissexto.

Editar: salvou dois bytes removendo espaços e outros três bytes alterando o ano para 1, graças a @Embodyment of Ignorance .

NicolasB
fonte
Você pode remover os espaços entre 1901, ne a string?
Modalidade de ignorância
@EmbodimentofIgnorance sim eu posso, obrigado!
NicolasB 14/03
Além disso, por que não substituir 1901 por um ano como 1? 1 não é um ano bissexto e é 3 bytes mais curto
Incorporação de Ignorância
@EmbodimentofIgnorance done and done :-)
NicolasB
3

05AB1E , 81 79 78 76 75 74 73 71 70 69 bytes

•ΘÏF•ºS₂+.¥-D0›©ÏθDT‰ć≠*4šß„—ÊØ3ôsè¨ð”……‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í”#®OèJ

-9 bytes graças a @Grimy .
-1 byte, graças ao standard thetruque de @ JonathanAllan th,st,nd,rd, que ele usou em sua resposta Jelly .

Experimente online ou verifique todos os casos de teste possíveis .

Explicação:

•ΘÏF        # Push compressed integer 5254545
     º       # Mirror it vertically: 52545455454525
      S      # Converted to a list of digits: [5,2,5,4,5,4,5,5,4,5,4,5,2,5]
       ₂+    # And 26 to each: [31,28,31,30,31,30,31,31,30,31,30,31,28,31]
             # (the additional trailing 28,31 won't cause any issues)
           # Undelta this list (with automatic leading 0):
             #  [0,31,59,90,120,151,181,212,243,273,304,334,365,393,424]
  -          # Subtract each from the (implicit) input-integer
   D0       # Duplicate the list, and check for each if it's positive (> 0)
      ©      # Store the resulting list in the register (without popping)
       Ï     # Only leave the values at those truthy indices
        θ    # And get the last value from the list, which is our day
D            # Duplicate this day
 T          # Take the divmod-10 of this day: [day//10, day%10]
   ć         # Extract the head; pop and push the remainder-list and head: [day%10], day//10
            # Check whether the day//10 is NOT 1 (0 if day//10 == 1; 1 otherwise)
     *       # Multiply that by the [day%10] value
      4š     # Prepend a 4 to this list
        ß    # Pop and push the minimum of the two (so the result is one of [0,1,2,3,4],
             # where the values are mapped like this: 1..3→1..3; 4..9→4; 10..19→0; 20..23→0..3; 24..29→4; 30,31→0,1)
 thŠØ       # Push dictionary string "th standards"
      3ô     # Split it into parts of size 3: ["th ","sta","nda","rds"]
        sè   # Swap and index the integer into this list (4 wraps around to index 0)
          ¨  # And remove the trailing character from this string
ð            # Push a space " "
”……‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í”
             # Push dictionary string "December January February March April May June July August September October November"
 #           # Split on spaces
  ®          # Push the list of truthy/falsey values from the register again
   O         # Get the amount of truthy values by taking the sum
    è        # Use that to index into the string-list of months (12 wraps around to index 0)
J            # Join everything on the stack together to a single string
             # (and output the result implicitly)

Veja esta minha dica 05AB1E para entender o porquê:

  • (seção Como usar o dicionário? ) ”……‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í”é"December January February March April May June July August September October November"
  • (seção Como usar o dicionário? ) …thŠØé"th standards"
  • (seção Como compactar números inteiros grandes? ) •ΘÏF•é5254545
Kevin Cruijssen
fonte
1
-2 bytes usando 5в28 + para compactação: TIO
Grimmy
1
Usar S é uma boa idéia, -1 byte novamente: TIO
Grimmy 14/03
1
@ Grimy Obrigado pelo byte de -1 •EË7Óæ•S₂+, mas o seu -3 de golfe não funciona infelizmente. A indexação é agrupada automaticamente em 05AB1E, portanto, isso 5st,6nd,7rd,25st,26nd,27rd,29stestará errado. PS: se tivesse funcionado, poderia ter sido por um -1 adicional. :)
Kevin Cruijssen 14/03
1
-1 novamente (usando "th th standards" em vez de "standard the" remove a necessidade de Á).
Grimmy 19/03
1
-1 ( •C.ñÒā•para •ΘÏF•º, os dígitos extras não importam)
Grimmy 20/03
2

bash, 82 80 bytes

-2 bytes graças a @ ASCII-only

a=(th st nd rd);set `printf "%(%e %B)T" $[$1*86399]`;echo $1${a[$1%30%20]-th} $2

TIO

data do bash + GNU, 77 bytes

a=(th st nd rd);set `date -d@$[$1*86399] +%e\ %B`;echo $1${a[$1%30%20]-th} $2
Nahuel Fouilleul
fonte
80?
somente ASCII
@ Somente ASCII, sim subtraindo 100s para cada dia, 100 * 365 = 36500s, que é menos de um dia (86400), funciona também com 86399 (subtrai 1s por dia)
Nahuel Fouilleul
: / ainda parece muito longo, mas ainda não encontrou uma maneira melhor
somente ASCII
2

Shell + coreutils, 112 90 bytes

date -d0-12-31\ $1day +%-dth\ %B|sed 's/1th/1st/;s/2th/2nd/;s/3th/3rd/;s/\(1.\).. /\1th /'

Experimente online! O link inclui casos de teste. Editar: salvou 22 bytes graças a @NahuelFouilleul. Explicação:

date -d0-12-31\ $1day

Calcule o número de dias após o primeiro dia anterior a um ano sem salto. (Infelizmente você não pode fazer cálculos de data relativa a partir de @-1.)

+%-dth\ %B|sed

Produza o dia do mês (sem zero à esquerda) the o nome completo do mês.

's/1th/1st/;s/2th/2nd/;s/3th/3rd/;

Arrumar 1st, 2nd, 3rd, 21st, 22nd, 23rde 31st.

s/\(1.\).. /\1th /'

Restaurar 11thpara 13th.

Neil
fonte
Eu vi essa resposta depois meu, poderia salvar 18bytes usando um comando sed, também sno dayspode ser removido, e 19em1969
Nahuel FOUILLEUL
@NahuelFouilleul Esse último usa um Bash-ism, portanto deve ser postado como uma resposta separada, mas obrigado pelas outras dicas!
Neil
2

Gelatina , 115 114 101 97 bytes

%30%20¹0<?4Ḥ+ؽị“thstndrd”ṭ
“5<Ḟ’b4+28ÄŻ_@µ>0T,>0$ƇZṪµ1ịị“£ṢtẒ⁽ẹ½MḊxɲȧėAṅ ɓaṾ¥D¹ṀẏD8÷ṬØ»Ḳ¤,2ịÇƊṚK

Experimente online!

Long por padrões de geléia, mas feito a partir dos primeiros princípios.

Agradecemos a JonathanAllan por salvar 13 bytes através de uma melhor compreensão da compactação de strings.

Nick Kennedy
fonte
“£ṢtẒ⁽ẹ½MḊxɲȧėAṅ ɓaṾ¥D¹ṀẏD8÷ṬØ»Ḳ¤economizaria 13 (o Compress.dictionary procura um espaço à esquerda e possui um tratamento especial).
Jonathan Allan
2

Planilhas Google, 118 103 86 bytes

=day(A1+1)&mid("stndrdth",min(7,1+2*mod(mod(day(A1+1)-1,30),20)),2)&text(A1+1," mmmm")

Como não consigo editar meu comentário , aqui está uma versão funcional do código do Planilhas Google.

Experimente Online!

Zylviij
fonte
1

Vermelho , 124 bytes

func[n][d: 1-1-1 + n - 1[rejoin[d/4 either 5 > t: d/4 % 30 % 20[pick[th st nd rd]t + 1]['th]]pick system/locale/months d/3]]

Experimente online!

Adiciona n- 1 dias a 1-1-1 (1 de janeiro de 2001) para formar uma data, que usa o método de Arnauld para indexar em sufixos de mês. Pena que o vermelho seja indexado em 1, isso requer ajustes adicionais. O bom é que Red sabe os nomes dos meses :)

Galen Ivanov
fonte
1

APL (NARS), 235 caracteres, 470 bytes

{k←↑⍸0<w←+\v←(1-⍵),(12⍴28)+13561787⊤⍨12⍴4⋄k<2:¯1⋄d←1+v[k]-w[k]⋄(⍕d),({d∊11..13:'th'⋄1=10∣d:'st'⋄2=10∣d:'nd'⋄3=10∣d:'rd'⋄'th'}),' ',(k-1)⊃(m≠' ')⊂m←'January February March April May June July August September October November December'}

13561787 é o número que pode ser somado na base 4 (12⍴28) para obter o comprimento de cada mês ... test:

  f←{k←↑⍸0<w←+\v←(1-⍵),(12⍴28)+13561787⊤⍨12⍴4⋄k<2:¯1⋄d←1+v[k]-w[k]⋄(⍕d),({d∊11..13:'th'⋄1=10∣d:'st'⋄2=10∣d:'nd'⋄3=10∣d:'rd'⋄'th'}),' ',(k-1)⊃(m≠' ')⊂m←'January February March April May June July August September October November December'}     
  ⊃f¨1 2 3 365 60 11
1st January  
2nd January  
3rd January  
31st December
1st March    
11th January 
RosLuP
fonte
0

C (gcc) , 174 155 bytes

i;char a[99],*b="thstndrd";f(long x){x--;x*=86400;strftime(a,98,"%d   %B\0",gmtime(&x));i=*a==49?0:a[1]-48;a[2]=b[i=i>3?0:i*2];a[3]=b[++i];x=*a==48?a+1:a;}

Experimente online!

GPS
fonte
-2

Python 3 , 95 bytes

Datetimed it: P

from datetime import *;f=lambda s:(datetime(2019,1,1)+timedelta(days=s-1)).strftime("%d of %B")

Experimente online!

Kerosenic
fonte
2
Isso não produz os sufixos ordinais e possui zeros à esquerda no número do dia. O oftambém é desnecessário
Jo King