Calcola il timestamp RFC 2550


26

RFC 2550 è una proposta satirica (pubblicata il 1 aprile 1999) per una rappresentazione ASCII efficiente nello spazio di timestamp in grado di supportare qualsiasi data (anche quelle precedenti all'inizio dell'universo e quelle oltre la fine prevista dell'universo). L'algoritmo per il calcolo di un timestamp conforme a RFC 2550 è il seguente (nota: tutti gli intervalli includono l'inizio ma escludono la fine - da 0 a 10.000 significa tutto ndove 0 <= n < 10000):

  • Formato anno
    • Anni da 0 a 10.000: un numero decimale di 4 cifre, imbottito a sinistra con zeri.
    • Anni da 10.000 a 100.000: un numero decimale di 5 cifre, preceduto dal carattere A.
    • Anni da 100.000 a 10 30 : il numero decimale per l'anno, preceduto dalla lettera ASCII maiuscola il cui indice nell'alfabeto inglese è uguale al numero di cifre nell'anno decimale, meno 5 (B per anni a 6 cifre, C per 7 -digit anni, ecc.).
    • Anni da 10 30 a 10 56 : lo stesso formato da 10.000 a 10 30 , ricominciando le lettere con A e aggiungendo inoltre un prefisso ( ^) alla stringa (quindi l'anno 10 30 è rappresentato da ^A1000000000000000000000000000000, e l'anno 10 31 è rappresentato di ^B10000000000000000000000000000000).
    • Anni da 10 56 a 10 732 : l'anno è preceduto da due punti e due lettere maiuscole ASCII. Le lettere maiuscole formano un numero di base 26 che rappresenta il numero di cifre dell'anno, meno 57.
    • Anni da 10 732 in poi: viene utilizzato lo stesso formato da 10 56 a 10 732 , estendendolo aggiungendo un punto di inserimento e una lettera maiuscola quando necessario.
    • Anni AC (prima dell'anno 0): calcola la stringa dell'anno del valore assoluto dell'anno. Quindi, sostituisci tutte le lettere con il loro complemento di base 26 (A <-> Z, B <-> Y, ecc.), Sostituisci tutte le cifre con il loro complemento di base 10 (0 <-> 9, 1 <-> 8, ecc.) e sostituisci i simboli con punti esclamativi ( !). Se la stringa dell'anno è di 4 cifre o meno (ovvero da -1 a -10.000), anteporre una barra ( /). Se la stringa dell'anno non è preceduta da una barra o da un punto esclamativo, anteporre un asterisco ( *).
  • Mesi, giorni, ore, minuti e secondi : poiché questi valori sono al massimo solo 2 cifre, vengono semplicemente aggiunti a destra della stringa dell'anno, in ordine decrescente di significato, riempiti a sinistra con zero se necessario per formare Stringhe di 2 cifre.
  • Precisione aggiuntiva : se è necessaria una precisione aggiuntiva (sotto forma di millisecondi, microsecondi, nanosecondi, ecc.), Tali valori vengono riempiti a sinistra con zeri a 3 cifre (poiché ogni valore è 1/1000del valore precedente e quindi è al massimo 999) e aggiunto alla fine del timestamp, in ordine decrescente di significato.

Questo formato ha il vantaggio che l'ordinamento lessicale è equivalente all'ordinamento numerico del corrispondente timestamp - se il tempo A precede il tempo B, allora il timestamp per A verrà prima del timestamp per B quando verrà applicato l'ordinamento lessicale.

La sfida

Dato un elenco arbitrariamente lungo di valori numerici (corrispondenti a valori temporali in ordine decrescente di significato, ad es. [year, month, day, hour, minute, second, millisecond]), Emette il corrispondente timestamp RFC 2550.

Regole

  • Le soluzioni devono funzionare per qualsiasi dato input. Le uniche limitazioni dovrebbero essere il tempo e la memoria disponibile.
  • L'input può essere preso in qualsiasi formato ragionevole e conveniente (come un elenco di numeri, un elenco di stringhe, una stringa delimitata da un singolo carattere non numerico, ecc.).
  • L'input conterrà sempre almeno un valore (l'anno). I valori aggiuntivi sono sempre in ordine decrescente di significato (ad esempio, l'input non conterrà mai un valore del giorno senza un valore del mese o un secondo valore seguito da un valore del mese).
  • L'immissione sarà sempre valida (ad es. Non ci saranno timestamp per il 30 febbraio).
  • Sono vietati i builtin che calcolano i timestamp RFC 2550.

Esempi

Questi esempi usano input come una singola stringa, con i singoli valori separati da punti ( .).

1000.12.31.13.45.16.8 -> 10001231134516008
12.1.5.1 -> 0012010501
45941 -> A45941
8675309.11.16 -> C86753091116
47883552573911529811831375872990.1.1.2.3.5.8.13 -> ^B478835525739115298118313758729900101020305008013
4052107100422150625478207675901330514555829957419806023121389455865117429470888094459661251.2.3.5.7.11 -> ^^BI40521071004221506254782076759013305145558299574198060231213894558651174294708880944596612510203050711
-696443266.1.3.6.10.15.21.28 -> *V3035567330103061015021028
-5342 -> /4657
-4458159579886412234725624633605648497202 -> !Q5541840420113587765274375366394351502797

Implementazione di riferimento

#!/usr/bin/env python

import string

# thanks to Leaky Nun for help with this
def base26(n):
    if n == 0:
        return ''
    digits = []
    while n:
        n -= 1
        n, digit = divmod(n, 26)
        digit += 1
        if digit < 0:
            n += 1
            digit -= 26
        digits.append(digit)
    return ''.join(string.ascii_uppercase[x-1] for x in digits[::-1])

year, *vals = input().split('.')

res = ""
negative = False

if year[0] == '-':
    negative = True
    year = year[1:]

if len(year) < 5:
    y = "{0:0>4}".format(year)
elif len(year) <= 30:
    y = "{0}{1}".format(string.ascii_uppercase[len(year)-5], year)
else:
    b26len = base26(len(year)-30)
    y = "{0}{1}{2}".format('^'*len(b26len), b26len, year)

if negative:
    y = y.translate(str.maketrans(string.ascii_uppercase+string.digits+'^', string.ascii_uppercase[::-1]+string.digits[::-1]+'!'))
    if len(year) == 4:
        y = '/' + y
    if y[0] not in ['/', '!']:
        y = '*' + y

res += y
for val in vals[:5]: #month, day, hour, minute, second
    res += '{0:0>2}'.format(val)

for val in vals[5:]: #fractional seconds
    res += '{0:0>3}'.format(val)

print(res)

Sicuramente -696443266.1.3.6.10.15.21.28dovrebbe essere *V3035567339896938984978971?
Neil,

11
@Neil Fino a quando non inventeremo mesi negativi. Negember.
Mego,

1
@TaylorScott Precisione aggiuntiva : se è necessaria una precisione aggiuntiva (sotto forma di millisecondi, microsecondi, nanosecondi, ecc.), Questi valori vengono riempiti a sinistra con zero da 3 a 3 cifre.
Mego

2
Mi sembra che le specifiche fornite nella domanda non corrispondano effettivamente a RFC2550. A quanto ho capito, una volta superati i tre punti, il numero di lettere dovrebbe aumentare più rapidamente rispetto ai punti, perché deriva dalla serie Fibonacci (4 punti significa 5 lettere, 5 punti significa 8 lettere, ecc.) È sicuro supponiamo che dovremmo ignorare quell'aspetto della RFC?
James Holderness,

1
@JamesHolderness Hai ragione, ho sbagliato le specifiche. Tuttavia, è troppo tardi per correggerlo, poiché ci sono già risposte che sarebbero invalidate.
Mego

Risposte:


5

JavaScript (ES6), 325 byte

f=
s=>s.split`.`.map((n,i)=>i?`00${n}`.slice(i>5?-3:-2):n<'0'?g(n.slice(1),'!','*','/').replace(/\w/g,c=>c>'9'?(45-parseInt(c,36)).toString(36):9-c):g(n),g=(n,c='^',d='',e='',l=n.length)=>l<5?e+`000${n}`.slice(-4):l<31?d+(l+5).toString(36)+n:h(l-30,c)+n,h=(n,c)=>n?c+h(--n/26|0,c)+(n%26+10).toString(36):'').join``.toUpperCase()
;
<input oninput=o.value=f(this.value);><input id=o>

Incredibilmente lungo.


Ti dispiacerebbe aggiungere uno snippet di stack per un facile test?
Mego,

@Mego Fatto. Risolti anche alcuni errori di battitura che si insinuavano (ho accidentalmente cancellato parte del codice durante la copia e incolla perché la linea che mi avvolgeva mi confondeva. Oops.)
Neil

3

Befunge, 418 384 byte

È difficile dire in anticipo quanto è probabile che finisca un programma Befunge e quando ho iniziato a lavorare su questo ho pensato che potesse effettivamente avere qualche possibilità di competere. Ho scoperto che mi sbagliavo.

~:59*-!:00p:2*1\-10p:9*68*+20p>0>#~$_v
68*-:0\`30p\>>:"P"%\"P"/9+p30g#v_1+:~>
0\`v`\0:\p04<<:+1g04-$<_\49+2*v>0>+#1:#\4#g\#0`#2_130p040p5-::01-`\49+2*-:
v:$_\50p\$:130g:1+30p:!^!:-1\*<>g*"A"++\49+2*/50g1-:
_$1+7g00g40g!**:!>_40g:!v!:\g8<^00*55*g01%*2+94:p05
|#9/"P"\%"P":<:_,#!>#:<$_1-00g^v3$\_\#`\0:>#g+
>10g*20g+,1+:^v\&\0+2`4:_@#`<0+<
/*v*86%+55:p00<_$$>:#,_$1+~0^
^!>+\55+/00g1-:^

Provalo online!


3

Perl 5 , 328 322 317 301 + 1 ( -a) = 302 byte

$_=shift@F;if(($l=y/-//c)<5){s/^/0 x(4-$l)/e}elsif($l<57){s/^/'^'x($l>30).chr 65+($l-5)%26/e}else{$l-=57;do{s/\^*\K/'^'.chr 65+$l%26/e}while$l=int$l/26;s/^\^\K\D-?\d/^A$&/}if(s/-//){s%^....$%/$&%;eval join'',reverse'!/',0..9,A..Z,"y/A-Z0-9^/";s%^[^!/]%*$&%}printf$_.'%02d'x(@F>5?5:@F).'%03d'x(@F-5),@F

Provalo online!

Ungolfed

$_=shift@F; # Store the year in the default variable for easier regex

if(($l=y/-//c)<5){      # if the length of the year is less than 5
    s/^/0 x(4-$l)/e         # pad with leading zeros to 4 digits
}elsif($l<57){          # if the length is less than 57
    s/^/'^'x($l>30).chr 65+($l-5)%26/e  # put a carat at the front if there are more than 30 characters
                        # and map the length minus 5 to A-Z
}else{
    $l-=57;         # offset the length by 57
    do{         
        s/\^*\K/'^'.chr 65+$l%26/e # put a carat at the front and map the length to base 26 (A-Z)
    }while$l=int$l/26;  # until the length is down to 0
    s/^\^\K\D-?\d/^A$&/ # insert an extra '^A' to pad the result to at least 2 characters if there was only 1
}
if(s/-//){          # if the year is negative
    s%^....$%/$&%;          # put a '/' in front of a 4 digit year
    eval join'',reverse'!/',0..9,A..Z,"y/A-Z0-9^/"; # map A-Z,0-9, and ^ to Z-A,9-0, and ! respectively
    s%^[^!/]%*$&%           # add a * at the front if there are no other indicators
}
printf$_.           # output the year
'%02d'x(@F>5?5:@F).             # followed by the month, day, hour, and minutes, padded to 2 digits
'%03d'x(@F-5),@F                # followed by fractional seconds, padded to three digits

3

Java 8, 653 640 637 623 byte

s->{String r="",q="ABCDEFGHIJKLMNOP",z=q+"QRSTUVWXYZ",y="0123456789",x;int i=0,f=0,t,u;for(String p:s){if(p.charAt(0)<46){p=p.substring(1);f=1;}t=p.length();if(i++<1){r+=(t<5?"000".substring(t-1):t<32?(char)(t+60):t<58?"^"+(char)(t+34):"");if(t>57){for(r+="^^",u=675;u<t-57;u*=26)r+="^";x="";for(String c:Long.toString(t-57,26).toUpperCase().split(""))x+=z.charAt((y+q).indexOf(c));r+=x;}r+=p;if(f>0){x=t<5?"/":t<32?"*":r.replace("^","!").replaceAll("[^!]","");for(char c:r.toCharArray())x+=c>93?"":"ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210".charAt((z+y).indexOf(c));r=x;}}else r+=i>6?t<2?"00"+p:t<3?0+p:p:t<2?0+p:p;}return r;}

Immettere come String-array e return-type come String.

Si è rivelato piuttosto lungo (come previsto), ma può sicuramente essere giocato a golf ancora un po '. Sono contento che funzioni dopo aver giocherellato per un po 'di tempo ..

Provalo qui.

Spiegazione:

  • for(String p:s){: Avvolgere le parti
    • if(p.charAt(0)<46){p=p.substring(1);f=1;}: Determina se è negativo e, se lo è, rimuove il segno meno e imposta un flag per ridurre i byte
    • t=p.length();: Ottieni la quantità di cifre
    • if(i++<1){: Se è il primo numero (l'anno):
      • t<5?"000".substring(t-1): Se è 0-100.000 (esclusivo): aggiungi zero iniziali se necessario
      • t<32?(char)(t+60): Se è 100.000-10 30 (esclusivo): aggiungi una lettera iniziale
      • t<58?"^"+(char)(t+34): Se è 10 30 -10 732 (esclusivo): aggiungi una "^"lettera + letterale
      • if(t>57)for(r+="^^",u=675;u<t-57;u*=26)r+="^";: Aggiungi la quantità appropriata di letterale "^"+ x="";for(String c:Long.toString(t-57,26).toUpperCase().split(""))x+=z.charAt((y+q).indexOf(c));r+=x;: lettere iniziali (da base 26 a conversione alfabetica)
      • r+=p;: Aggiungi l'anno stesso alla stringa del risultato
      • if(f>0){: Se l'anno è stato negativo:
        • x=t<5?"/":t<32?"*":r.replace("^","!").replaceAll("[^!]","");: Creare una stringa di temperatura xcon la corretta /, *o uno o più!
        • for(char c c:r.toCharArray())x+=c>93?"":"ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210".charAt((z+y).indexOf(c));: Esegui la conversione (A↔Z, B↔Y, 0↔9, 1↔8, ecc.)
        • r=x;: E quindi imposta il risultato su questa stringa temporanea x
    • else: Se è il mese, giorni, ore, minuti, secondi, millisecondi, microsecondi, nanosecondi o inferiore:
      • i>6?t<2?"00"+p:t<3?0+p:p: Se è millisecondi o inferiore: aggiungere zero iniziali se necessario
      • :t<2?0+p:p;: Altrimenti (mese, giorni, ore, minuti, secondi): aggiungere lo zero iniziale singolo, se necessario
  • return r: Restituisce il risultato

Input may be taken in any reasonable, convenient format (such as a list of numerics, a list of strings, a string delimited by a single non-digit character, etc.).- potresti inserire input come un elenco di numeri e saltare la divisione e la conversione costose.
Mego

1
@Mego Purtroppo i valori numerici predefiniti ( longcon 64 bit come il più grande) sono troppo piccoli in Java per alcuni input, quindi Stringè più breve di java.math.BigInteger. L'ho cambiato in un Stringarray però, quindi non ho bisogno di fare la divisione per punti, che ha salvato alcuni byte, quindi grazie.
Kevin Cruijssen il

2

Excel VBA, 500 486 485 470 byte

Anonimo VBE Funzione finestra immediata

La funzione di finestra immediata VBE anonima che accetta input come anno da [A1], mese da [B1], giorni da [C1], ore da [D1], minuti da [E1], secondi da [F1]e un array di precisione extra opzionale da [G1:Z1], calcola il timestamp RFC2550 e trasmette alla finestra immediata VBE. Utilizza la funzione di aiuto dichiarata di seguito.

n=Left([A1],1)="-":y=Mid([A1],1-n):l=Len(y):o=IIf(l<5,Right("000"&y,4),IIf(l<31,"",String(Len(b(l-30)),94))&B(l-IIf(l<31,4,30))&y):For Each c In[B1:Z1]:j=j+1:p=p+IIf(c,Format(c,IIf(j>5,"000","00")),""):Next:If n Then For i=1To Len(o):c=Asc(Mid(o,i,1)):Mid$(o,i,1)=Chr(IIf(c<60,105,155)-c):Next:?IIf(l<5,"/",IIf(InStr(1,o,"="),"","*"))Replace(o,"=","!")p:Else?o;p

Funzione di aiuto

Funzione di supporto dichiarata che accetta un numero di input e restituisce quel numero in base-26 tale che 1->Ae26->Z

Deve essere inserito in un modulo pubblico.

Function b(n)
While n
n=n-1
d=n Mod 26+1
n=Int(n/26)
d=d+26*(d<0):n=n-(d<0)
b=Chr(64+d)+b
Wend
End Function

uso

Deve essere utilizzato in un modulo chiaro, o il modulo deve essere cancellato prima dell'esecuzione come le var j, oe psi presume essere nel loro stato predefinito inizializzato all'inizio dell'esecuzione del codice. Per j, che è una Variant\Integervariabile, questo valore predefinito è 0e per oe p, che sono Variant\Stringvariabili, questo valore predefinito è la stringa vuota ( "").

L'input, un array di stringhe, viene prelevato dal 1:1foglio ActiveS e l'output è nella finestra immediata di VBE.

I / O di esempio

[A1:F1]=Split("4052107100422150625478207675901330514555829957419806023121389455865117429470888094459661251.2.3.5.7.11",".")
n=Left([A1],1)="-":y=Mid([A1],1-n):l=Len(y):o=IIf(l<5,Right("000"&y,4),IIf(l<31,"",String(Len(b(l-30)),94))&B(l-IIf(l<31,4,30))&y):For Each c In[B1:ZZ1]:j=j+1:p=p+IIf(c,Format(c,IIf(j>5,"000","00")),""):Next:If n Then For i=1To Len(o):c=Asc(Mid(o,i,1)):Mid$(o,i,1)=Chr(IIf(c<60,105,155)-c):Next:?IIf(l<5,"/",IIf(InStr(1,o,"="),"","*"))Replace(o,"=","!")p:Else?o;p
^^BI40521071004221506254782076759013305145558299574198060231213894558651174294708880944596612510203050711021028

Cells.Clear:j=0:o="":p="" '' clear the worksheet and vars
[A1:H1]=Array("-696443266","1","3","6","10","15","21","28")
n=Left([A1],1)="-":y=Mid([A1],1-n):l=Len(y):o=IIf(l<5,Right("000"&y,4),IIf(l<31,"",String(Len(b(l-30)),94))&B(l-IIf(l<31,4,30))&y):For Each c In[B1:ZZ1]:j=j+1:p=p+IIf(c,Format(c,IIf(j>5,"000","00")),""):Next:If n Then For i=1To Len(o):c=Asc(Mid(o,i,1)):Mid$(o,i,1)=Chr(IIf(c<60,105,155)-c):Next:?IIf(l<5,"/",IIf(InStr(1,o,"="),"","*"))Replace(o,"=","!")p:Else?o;p
*V3035567330103061015021028

Cells.Clear:j=0:o="":p="" '' clear the worksheet and vars
[A1]="45941"
n=Left([A1],1)="-":y=Mid([A1],1-n):l=Len(y):o=IIf(l<5,Right("000"&y,4),IIf(l<31,"",String(Len(b(l-30)),94))&B(l-IIf(l<31,4,30))&y):For Each c In[B1:ZZ1]:j=j+1:p=p+IIf(c,Format(c,IIf(j>5,"000","00")),""):Next:If n Then For i=1To Len(o):c=Asc(Mid(o,i,1)):Mid$(o,i,1)=Chr(IIf(c<60,105,155)-c):Next:?IIf(l<5,"/",IIf(InStr(1,o,"="),"","*"))Replace(o,"=","!")p:Else?o;p
A45941

Cells.Clear:j=0:o="":p="" '' clear the worksheet and vars
[A1:F1]=Split("4052107100422150625478207675901330514555829957419806023121389455865117429470888094459661251.2.3.5.7.11",".")
n=Left([A1],1)="-":y=Mid([A1],1-n):l=Len(y):o=IIf(l<5,Right("000"&y,4),IIf(l<31,"",String(Len(b(l-30)),94))&B(l-IIf(l<31,4,30))&y):For Each c In[B1:ZZ1]:j=j+1:p=p+IIf(c,Format(c,IIf(j>5,"000","00")),""):Next:If n Then For i=1To Len(o):c=Asc(Mid(o,i,1)):Mid$(o,i,1)=Chr(IIf(c<60,105,155)-c):Next:?IIf(l<5,"/",IIf(InStr(1,o,"="),"","*"))Replace(o,"=","!")p:Else?o;p
^^BI40521071004221506254782076759013305145558299574198060231213894558651174294708880944596612510203050711

SubVersione di routine

La subroutine dichiarata che accetta input come anno da [A1], mese da [B1], giorni da [C1], ore da [D1], minuti da [E1], secondi da [F1]e un array di precisione extra opzionale da [G1:Z1], calcola il timestamp RFC2550 e trasmette alla finestra immediata VBE.

Sub R(x)
a=x(0)
n=Left(a,1)="-"'<- that `"` is only there to make sure highlighting is correct
y=Mid(a,1-n)
l=Len(y)
o=IIf(l<5,Right("000"&y,4),IIf(l<31,"",String(Len(b(l-30)),94))&B(l-IIf(l<31,4,30))&y)
If n Then For i=1To Len(o):c=Asc(Mid(o,i,1)):Mid$(o,i,1)=Chr(IIf(c<60,105,155)-c):Next:o=IIf(l<5,"/",IIf(InStr(1,o,"="),"","*"))&Replace(o,"=","!")
For j=1To UBound(x)
o=o+IIf(x(j),Format(x(j),IIf(j>5,"000","00")),"")
Next
[A2]=o
End Sub
Function b(n)
While n
n=n-1
d=n Mod 26+1
n=Int(n/26)
d=d+26*(d<0):n=n-(d<0)
b=Chr(64+d)+b
Wend
End Function

uso

L'input all'intervallo [A1:ZZ1]può essere effettuato manualmente, digitando nelle celle, dall'estrema sinistra all'estrema destra, secondo necessità o assegnando dalla finestra immediata di VBE.

Da notare, a causa della conversione automatica di numeri di Excel in notazione scientifica, tutti i numeri che hanno una lunghezza base 10 uguale o maggiore di 12 cifre devono essere inseriti esplicitamente nella cella come testo impostando la cella come cella di testo o anteponendo il valore letterale 'all'inizio del valore della cella

I / O di esempio

r Split("4052107100422150625478207675901330514555829957419806023121389455865117429470888094459661251.2.3.5.7.11",".")
?[A2]  '' <- print output to VBE console
^^BI40521071004221506254782076759013305145558299574198060231213894558651174294708880944596612510203050711 ''  <- Output

r Array("47883552573911529811831375872990","1","1","2","3","5","8","13")
?[A2]
^B478835525739115298118313758729900101020305008013

r Array("-696443266","1","3","6","10","15","21","28")
?[A2]
*V3035567330103061015021028

r Array("45941")
?[A2]
A45941

Ungolfed e spiegato

''  Returns RFC2550 timestamp corresponding to passed vars
Public Function RFC2550(ByVal pYear As String, ParamArray Extra() As Variant) As String

    ''  Declare Vars
    Dim Negative As Boolean, _
        leny As Long, _
        i As Long, _
        c As Byte, _
        s As Variant, _
        out As String

    ''  Check if year is negative and store the absolute value of the year
    Let Negative = Left(pYear, 1) = "-"
    Let pYear = Mid(pYear, 1 - Negative)

    ''  Take the length of the year
    Let leny = Len(pYear)
    If leny < 5 Then
        ''  If the length is less than 5, pad the year left to 4 characters 
        ''  using zeros
        Let out = Format("0000", pYear)
    Else
        ''  If the length of the year is greater than 30, then set out to be 
        ''  as string comprised of length-30 instances of `^`
        Let out = IIf(leny < 31, "", String(Len(Base26(leny - 30)), 94)) 
        ''  append the Base26 representation of the length of the year,
        ''  minus 30, if the length is greater than 30
        Let out = out & Base26(leny - IIf(leny < 31, 4, 30)) 
        ''  append the year to out
        Let out = out & pYear
    End If


    If Negative Then
        ''  iterate across out
        For i = 1 To Len(out)
            ''  store the char code for the current char
            Let c = Asc(Mid(out, i, 1))
            ''  swap letter/number with its inverse (0->9,A->Z)
            Mid$(out, i, 1) = Chr(IIf(c < 60, 105, 155) - c)
        Next i

        ''  replace `=` (the inverse of `^`) with `!`
        Let out = Replace(out, "=", "!")
        ''  Prepend either `/`, `*`, or nothing depending on length and 
        ''  start of out
        Let out = IIf(leny < 5, "/", IIf(InStr(1, out, "!"), "", "*")) & out
    End If

    Let i = 1
    For Each s In Extra
        ''  append all of the extra precision data - padding to 2 chars for 
        ''  the first 5 elements in the array (month, day, hour, minute and 
        ''  second) and to 3 chars for all following elements (milli, micro, 
        ''  nano, pico, femto, atto, zepto, yocto - seconds) with the char 0
        Let out = out & IIf(s, Format(s, IIf(i > 5, "000", "00")), "")
        Let i = i + 1
    Next

    ''  return out
    Let RFC2550 = out 

End Function


''  returns non-standard base26 version of input number 
''  1->A, 2->B,... 26->Z
Function Base26(ByVal n As Long) As String

    ''  declare vars
    Dim out As String, _
        digit As Integer

    ''  init out, digit
    Let out = ""
    Let digit = 0

    ''  iterate through n 
    While n
        ''  Decrement, hold the value of the digit
        Let n = n - 1
        Let digit = n Mod 26 + 1

        ''  divide by 26
        Let n = Int(n / 26)

        ''  correct for negative numbers
        If digit < 0 Then Let n = n + 1: Let digit = digit - 26

        ''  prepend char corresponding to the digit to out
        Let out = Chr(64 + digit) & out
    Wend

    ''  return out
    Let Base26 = out
End Function

2

Gelatina , 165 126 byte

ḣ5ṫ€3
ØD,“^ /*!”,ØA
_µ‘l26Ċṗ@€ØAẎị@
Lµç30;€”^UZFµç4⁶;µ®L>30¤?µḟ®L>4¤?;®AṾ€¤µL=4”/x2£FiЀị€2£UF¤µ®S<0¤¡
4R¬+DU$UµḢ©Ç;Ñ;ṫ6ṫ€2$$F

Provalo online!

La riga 4 esegue la formattazione dell'anno con l'aiuto delle righe 2 e 3. La prima e l'ultima riga trattano lo zero riempiendo gli elementi dell'input con le loro lunghezze corrette concatenandoli con l'anno formattato.

  • _µ‘l26Ċṗ@€ØAẎị@trova il prefisso base 26. Prende il potere cartesiano dell'alfabeto ( ØA) per ogni numero compreso tra 1 e ceil (registro 26 (piano (registro 10 (anno)) - n + 1)) (dove n è 30 o 4) quindi ottiene gli indici in questo elenco con piano (log 10 (anno)) - n ( ị@).
  • ç30;€”^UZF formati anni> = 10 30 ( ®L>30¤?)
  • ç4⁶;formati anni <10 30 . ( Modifica : salvato un byte utilizzando ⁶;invece di ;@⁶)
  • 1RḊ fornisce un prefisso vuoto per anni <10 5 ( ®L>4¤?). Prende l'elenco delle cifre, quindi filtra ogni elemento in sé. Usando questo per cedere []perché non funziona qui. Questo solo valuta []. e []non funziona qui e non sono riuscito a trovare altri 2 byte che restituiscono un elenco vuoto.
  • ;®AṾ€¤ accoda l'anno al prefisso, quindi lo appiattisce.
  • L=4”/xprefissa a /se la lunghezza dell'anno è 4 nella dichiarazione do di ®S<0¤¡.
  • 2£FiЀ¹ị€2£UF¤prende i complementi di A .. Z, 0 .. 9e ^ /*!se l'anno è negativo ( ®S<0¤¡). si riferisce al secondo collegamento, ØD,“^ *!”,ØAche è l'elenco [['0' .. '9'], ['^',' ','/','*','!'], ['A' .. 'Z']]. Con un anno formattato come ^C125...questo link trova l'indice di ciascun carattere nella versione appiattita, quindi usa quegli indici per costruire una nuova stringa dalla versione appiattita di cui ogni sotto-elenco è invertito, cioè ['9' .. '0','!','*','/',' ','^','Z' .. 'A']cedendo !X874.... /è mappato a se stesso perché ha il prefisso prima che tutto venga preso in considerazione.
  • L=4a®S<0x@”/;aggiunge un /inizio agli anni negativi in [-9999 .. -0001]. La mia ipotesi è che questo può essere abbreviato. Ho finito per includerlo nella precedente istruzione do ( ¡) e ho salvato 7 byte perché non avevo bisogno di testare due volte per anni negativi.

Ci sono molti usi della ¡riga 4 e penso che potrebbero essere compressi usando ?invece, ma non sono sicuro di come farli funzionare. Ho avuto modo ?di lavorare e ho salvato qualche byte.

James Holderness ha sottolineato che la mia prima presentazione non ha gestito anni con 30 cifre corrette. Si è scoperto che il bug era per qualsiasi anno che necessitava di un Zprefisso base 26. Si scopre che non potrei usare perché quando converti 26 in base 26 ti dà [1,0]invece di 26(duh). Invece ho usato coppie ordinate con sostituzione. Non penso che ci sia un atomo per quello, ma se c'è posso salvare qualche byte. Risolvere questo problema mi è costato ~ 40 byte. Sicuramente il mio programma Jelly più lungo di sempre. Modifica : trovato un modo più breve per fare il prodotto cartesiano. Mi sono reso conto che non ero sicuro che l'ultimo funzionasse per i prefissi con più di due lettere comunque, ma il nuovo modo funziona.

Scusate per le molte volte che ho modificato questo post, continuo a scoprire modi per accorciarlo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.