Calculer l'horodatage RFC 2550

26

La RFC 2550 est une proposition satirique (publiée le 1er avril 1999) pour une représentation ASCII à faible encombrement des horodatages qui peuvent prendre en charge n'importe quelle date (même celles antérieures au début de l'univers et celles passées avant la fin prévue de l'univers). L'algorithme de calcul d'un horodatage conforme à la RFC 2550 est le suivant (remarque: toutes les plages incluent le début mais excluent la fin - 0 à 10 000 signifie tout n0 <= n < 10000):

  • Format de l'année
    • Années 0 à 10 000: un nombre décimal à 4 chiffres, rempli à gauche de zéros.
    • Années 10 000 à 100 000: un nombre décimal à 5 ​​chiffres, précédé du caractère A.
    • Années 100 000 à 10 30 : le nombre décimal de l'année, préfixé par la lettre ASCII majuscule dont l'index de l'alphabet anglais est égal au nombre de chiffres de l'année décimale, moins 5 (B pour les années à 6 chiffres, C pour 7 - années chiffres, etc.).
    • Années 10 30 à 10 56 : le même format que 10 000 à 10 30 , en commençant les lettres par A et en préfixant en plus un caret ( ^) à la chaîne (donc l'année 10 30 est représentée par ^A1000000000000000000000000000000, et l'année 10 31 est représentée par ^B10000000000000000000000000000000).
    • Années 10 56 à 10 732 : l'année est préfixée par deux carets et deux lettres majuscules ASCII. Les lettres majuscules forment un nombre en base 26 représentant le nombre de chiffres dans l'année, moins 57.
    • À partir de 10 732 ans: le même format est utilisé pour 10 56 à 10 732 , en le prolongeant en ajoutant un caret et une lettre majuscule si nécessaire.
    • Années BCE (avant l'année 0): calculez la chaîne d'année de la valeur absolue de l'année. Ensuite, remplacez toutes les lettres par leur complément en base 26 (A <-> Z, B <-> Y, etc.), remplacez tous les chiffres par leur complément en base 10 (0 <-- 9, 1 <-> 8, etc.) et remplacez les points d'insertion par des points d'exclamation ( !). Si la chaîne de l'année est de 4 chiffres ou moins (c'est-à-dire -1 à -10 000), ajoutez une barre oblique ( /). Si la chaîne de l'année n'est pas précédée d'une barre oblique ou d'un point d'exclamation, ajoutez un astérisque ( *).
  • Mois, jours, heures, minutes et secondes : comme ces valeurs ne sont que de 2 chiffres au maximum, elles sont simplement ajoutées à droite de la chaîne de l'année, par ordre décroissant de signification, complétées à gauche par des zéros si nécessaire pour former Chaînes à 2 chiffres.
  • Précision supplémentaire : si une précision supplémentaire (sous forme de millisecondes, microsecondes, nanosecondes, etc.) est nécessaire, ces valeurs sont remplies à gauche avec des zéros à 3 chiffres (car chaque valeur est 1/1000de la valeur précédente, et donc au maximum 999) et ajouté à la fin de l'horodatage, par ordre décroissant d'importance.

Ce format présente l'avantage que le tri lexical est équivalent au tri numérique de l'horodatage correspondant - si l'heure A précède l'heure B, alors l'horodatage pour A viendra avant l'horodatage pour B lorsque le tri lexical est appliqué.

Le défi

Étant donné une liste arbitrairement longue de valeurs numériques (correspondant à des valeurs temporelles dans un ordre décroissant de signification, par exemple [year, month, day, hour, minute, second, millisecond]), émettez l'horodatage RFC 2550 correspondant.

Règles

  • Les solutions doivent fonctionner pour toute entrée donnée. Les seules limitations devraient être le temps et la mémoire disponible.
  • L'entrée peut être prise dans n'importe quel format raisonnable et pratique (comme une liste de chiffres, une liste de chaînes, une chaîne délimitée par un seul caractère non numérique, etc.).
  • L'entrée contiendra toujours au moins une valeur (l'année). Les valeurs supplémentaires sont toujours en ordre décroissant de signification (par exemple, l'entrée ne contiendra jamais une valeur de jour sans valeur de mois, ou une deuxième valeur suivie d'une valeur de mois).
  • L'entrée sera toujours une heure valide (par exemple, il n'y aura pas d'horodatage pour le 30 février).
  • Les buildins qui calculent les horodatages RFC 2550 sont interdits.

Exemples

Ces exemples utilisent l'entrée comme une seule chaîne, les valeurs individuelles étant séparées par des points ( .).

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

Implémentation de référence

#!/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)
Mego
la source
Devrait sûrement l' -696443266.1.3.6.10.15.21.28être *V3035567339896938984978971?
Neil
11
@Neil Jusqu'à ce que nous inventions des mois négatifs. Negember.
Mego
1
@TaylorScott Précision supplémentaire : si une précision supplémentaire (sous forme de millisecondes, microsecondes, nanosecondes, etc.) est nécessaire, ces valeurs sont remplies à gauche avec des zéros à 3 chiffres.
Mego
2
Il me semble que la spécification donnée dans la question ne correspond pas réellement à RFC2550. Si je comprends bien, une fois que vous avez dépassé les trois carets, le nombre de lettres devrait augmenter plus rapidement que les carets, car il est dérivé de la série Fibonacci (4 carets signifie 5 lettres, 5 carets signifie 8 lettres, etc.). supposons que nous devrions ignorer cet aspect de la RFC?
James Holderness
1
@JamesHolderness Vous avez raison, j'ai foiré la spécification. Cependant, il est trop tard pour le corriger, car il existe déjà des réponses qui seraient invalidées.
Mego

Réponses:

5

JavaScript (ES6), 325 octets

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>

Étonnamment long.

Neil
la source
Pourriez-vous ajouter un extrait de pile pour un test facile?
Mego
@Mego Done. Correction de quelques fautes de frappe qui se sont glissées (j'ai accidentellement supprimé une partie du code lors de la copie et du collage parce que le retour à la ligne m'a dérouté. Oups.)
Neil
3

Befunge, 418 384 octets

Il est difficile de dire à l'avance à quel point un programme Befunge est susceptible de se terminer, et quand j'ai commencé à travailler sur ce sujet, je pensais qu'il pourrait avoir une chance de participer. Il s'avère que j'avais tort.

~: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-:^

Essayez-le en ligne!

James Holderness
la source
3

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

$_=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

Essayez-le en ligne!

Non golfé

$_=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
Xcali
la source
3

Java 8, 653 640 637 623 octets

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

Entrez as String-array et return-type as String.

Il s'est avéré être assez long (comme prévu), mais peut certainement être joué au golf encore plus. Je suis juste content que ça marche après avoir joué avec ça pendant un bon moment ..

Essayez-le ici.

Explication:

  • for(String p:s){: Boucle sur les pièces
    • if(p.charAt(0)<46){p=p.substring(1);f=1;}: Déterminez si c'est négatif, et si c'est le cas, supprimez le signe moins et définissez un indicateur pour réduire les octets
    • t=p.length();: Obtenir le nombre de chiffres
    • if(i++<1){: Si c'est le premier chiffre (l'année):
      • t<5?"000".substring(t-1): Si c'est 0-100 000 (exclusif): ajoutez des zéros non significatifs si nécessaire
      • t<32?(char)(t+60): Si c'est 100 000-10 30 (exclusif): Ajoutez une lettre principale
      • t<58?"^"+(char)(t+34): S'il est 10 30 -10 732 (exclusif): Ajouter un littéral "^"+ lettre principale
      • if(t>57)for(r+="^^",u=675;u<t-57;u*=26)r+="^";: Ajoutez la quantité appropriée de littéral "^"+ x="";for(String c:Long.toString(t-57,26).toUpperCase().split(""))x+=z.charAt((y+q).indexOf(c));r+=x;: lettres principales (conversion de la base 26 en alphabet)
      • r+=p;: Ajouter l'année elle-même à la chaîne de résultats
      • if(f>0){: Si l'année a été négative:
        • x=t<5?"/":t<32?"*":r.replace("^","!").replaceAll("[^!]","");: Créer une chaîne temporaire xavec le bon /, *ou un ou plusieurs!
        • for(char c c:r.toCharArray())x+=c>93?"":"ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210".charAt((z+y).indexOf(c));: Faites la conversion (A↔Z, B↔Y, 0↔9, 1↔8, etc.)
        • r=x;: Et puis définissez le résultat sur cette chaîne temporaire x
    • else: Si c'est le mois, les jours, les heures, les minutes, les secondes, les millisecondes, les microsecondes, les nanosecondes ou moins:
      • i>6?t<2?"00"+p:t<3?0+p:p: Si elle est inférieure ou égale à quelques millisecondes: Ajoutez des zéros non significatifs si nécessaire
      • :t<2?0+p:p;: Sinon (mois, jours, heures, minutes, secondes): Ajouter un zéro de début unique si nécessaire
  • return r: Retourner le résultat
Kevin Cruijssen
la source
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.).- vous pouvez prendre la saisie comme une liste de chiffres et ignorer le fractionnement et la conversion coûteux.
Mego
1
@Mego Malheureusement, les valeurs numériques par défaut ( long64 bits étant le plus grand) sont trop petites en Java pour certaines entrées, elles sont donc Stringplus courtes que java.math.BigInteger. StringCependant, je l'ai changé en un tableau, donc je n'ai pas besoin de faire la division par points, ce qui a économisé quelques octets, alors merci.
Kevin Cruijssen
2

Excel VBA, 500 486 485 470 octets

Fonction de fenêtre immédiate VBE anonyme

La fonction de fenêtre immédiate VBE anonyme qui prend les entrées comme année de [A1], mois de [B1], jours de [C1], heures de [D1], minutes de [E1], secondes de [F1]et un tableau de précision supplémentaire en option de [G1:Z1], calcule l'horodatage RFC2550 et les sorties vers la fenêtre immédiate VBE. Utilise la fonction d'assistance déclarée ci-dessous.

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

Fonction d'assistance

Fonction d'assistance déclarée qui prend un nombre d'entrée et renvoie ce nombre en base-26 tel que 1->Aet26->Z

Doit être placé dans un module public.

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

Usage

Doit être utilisé dans un module clair, ou le module doit être effacé avant l' exécution que les vars j, oet psont supposés être dans leur état par défaut, non initialisée au début de l' exécution du code. Pour j, qui est une Variant\Integervariable, cette valeur par défaut est 0et pour oet p, qui sont des Variant\Stringvariables, cette valeur par défaut est la chaîne vide ( "").

L'entrée, un tableau de chaînes, est extraite de 1:1l'ActiveSheet et la sortie est vers la fenêtre immédiate VBE.

Exemple d'E / S

[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

SubVersion de routine

La sous-routine déclarée qui prend les entrées comme année de [A1], mois de [B1], jours de [C1], heures de [D1], minutes de [E1], secondes de [F1]et un tableau de précision supplémentaire en option de [G1:Z1], calcule l'horodatage RFC2550 et les sorties vers la fenêtre immédiate 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

Usage

La saisie dans la plage [A1:ZZ1]peut être effectuée soit manuellement, en tapant dans les cellules, de l'extrême gauche à l'extrême droite, selon les besoins, soit en l'affectant à partir de la fenêtre immédiate du VBE.

À noter, en raison de la conversion automatique des nombres Excel en notation scientifique, tout nombre dont la longueur en base 10 est égale ou supérieure à 12 chiffres doit être inséré explicitement dans la cellule sous forme de texte, soit en définissant la cellule comme une cellule de texte, soit en ajoutant le littéral 'au début de la valeur de la cellule

Exemple d'E / S

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

Non golfé et expliqué

''  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
Taylor Scott
la source
2

Gelée , 165126 octets

ḣ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

Essayez-le en ligne!

La ligne 4 effectue le formatage de l'année à l'aide des lignes 2 et 3. La première et la dernière ligne traitent du remplissage nul des éléments de l'entrée à leur longueur appropriée, puis les concaténent avec l'année formatée.

  • _µ‘l26Ċṗ@€ØAẎị@trouve le préfixe de base 26. Il prend la puissance cartésienne de l'alphabet ( ØA) pour chaque nombre entre 1 et ceil (log 26 (étage (log 10 (année)) - n + 1)) (où n est soit 30 soit 4), puis obtient des index dans cette liste avec plancher (log 10 (année)) - n ( ị@).
  • ç30;€”^UZF formats années> = 10 30 ( ®L>30¤?)
  • ç4⁶;formats années <10 30 . ( Modifier : enregistré un octet en utilisant ⁶;au lieu de ;@⁶)
  • 1RḊ donne un préfixe vide pour les années <10 5 ( ®L>4¤?). Il prend la liste des chiffres puis filtre chaque élément en lui-même. Il suffit de l'utiliser pour céder, []car cela ne fonctionne pas ici. Cela ne fait qu'évaluer []. et []ne fonctionnent pas ici et je n'ai pas pu trouver 2 autres octets qui retournent une liste vide.
  • ;®AṾ€¤ ajoute l'année au préfixe puis l'aplatit.
  • L=4”/xpréfixe a /si la longueur de l'année est 4 dans la déclaration do de ®S<0¤¡.
  • 2£FiЀ¹ị€2£UF¤prend les compléments de A .. Z, 0 .. 9et ^ /*!si l'année est négative ( ®S<0¤¡). fait référence au deuxième lien, ØD,“^ *!”,ØAqui est la liste [['0' .. '9'], ['^',' ','/','*','!'], ['A' .. 'Z']]. Avec une année formatée comme ^C125...ce lien, trouve l'index de chaque caractère dans la version aplatie de puis utilise ces indices pour construire une nouvelle chaîne à partir de la version aplatie de l' endroit où chaque sous-liste est inversée, c'est ['9' .. '0','!','*','/',' ','^','Z' .. 'A']-à- dire le rendement !X874.... /mappe sur lui-même car il est préfixé avant que tout ne soit pris en compte.
  • L=4a®S<0x@”/;ajoute un /début d'année négative [-9999 .. -0001]. Je suppose que cela peut être raccourci. J'ai fini par l'inclure dans l'instruction do précédente ( ¡) et j'ai économisé 7 octets car je n'avais pas besoin de tester les années négatives deux fois.

Il y a beaucoup d'utilisations de la ¡ligne 4 et je pense qu'elles pourraient être compressées en utilisant à la ?place, mais je ne sais pas comment les faire fonctionner. Je me suis mis ?au travail et j'ai économisé quelques octets.

James Holderness a souligné que ma première soumission ne traitait pas des années avec 30 chiffres corrects. Il s'est avéré que le bug était pour n'importe quelle année qui avait besoin d'un Zpréfixe de base 26. Il s'avère que je ne pouvais pas utiliser parce que lorsque vous convertissez 26 en base 26, cela vous donne [1,0]au lieu de 26(duh). Au lieu de cela, j'ai utilisé des paires commandées avec remplacement. Je ne pense pas qu'il y ait un atome pour ça mais s'il y en a je peux économiser quelques octets. La résolution de ce problème m'a coûté environ 40 octets. Certainement mon plus long programme Jelly à ce jour. Edit : Trouvé un moyen plus court de faire le produit cartésien. J'ai réalisé que je n'étais pas sûr que le dernier fonctionnait pour les préfixes avec plus de deux lettres de toute façon, mais la nouvelle méthode fonctionne.

Désolé pour les nombreuses fois où j'ai édité ce post, je continue de découvrir des moyens de le raccourcir.

dylnan
la source