Berechnen Sie den RFC 2550-Zeitstempel

26

RFC 2550 ist ein satirischer Vorschlag (veröffentlicht am 1. April 1999) für eine platzsparende ASCII-Darstellung von Zeitstempeln, die jedes Datum unterstützen können (auch solche vor dem Beginn des Universums und solche nach dem prognostizierten Ende des Universums). Der Algorithmus zur Berechnung eines RFC 2550 konforme Zeitstempel folgt wie (Anmerkung: alle Bereiche umfassen den Start , aber ausschließen das Ende - 0 bis 10.000 Mittel alle nwo 0 <= n < 10000):

  • Jahresformat
    • Jahre 0 bis 10.000: eine 4-stellige Dezimalzahl, links mit Nullen aufgefüllt.
    • Jahre 10.000 bis 100.000: eine 5-stellige Dezimalzahl mit vorangestelltem Buchstaben A.
    • Jahre 100.000 bis 10 30 : Die Dezimalzahl für das Jahr, vorangestellt mit dem ASCII-Großbuchstaben, dessen Index im englischen Alphabet der Anzahl der Stellen im Dezimaljahr entspricht, minus 5 (B für 6-stellige Jahre, C für 7) Jahre usw.).
    • Jahre 10 30 bis 10 56 : dasselbe Format wie 10.000 bis 10 30 , wobei die Buchstaben mit A beginnen und ^der Zeichenfolge zusätzlich ein Caret ( ) vorangestellt wird (also das Jahr 10 30 durch ^A1000000000000000000000000000000und das Jahr 10 31 durch dargestellt wird) von ^B10000000000000000000000000000000).
    • Jahre 10 56 bis 10 732 : Dem Jahr werden zwei Carets und zwei ASCII-Großbuchstaben vorangestellt. Die Großbuchstaben bilden eine Zahl zur Basis 26, die die Anzahl der Stellen im Jahr minus 57 darstellt.
    • Ab 10 732 Jahren: Es wird dasselbe Format für 10 56 bis 10 732 verwendet. Bei Bedarf werden ein zusätzliches Caret und ein Großbuchstabe hinzugefügt.
    • BCE-Jahre (vor Jahr 0): Berechnet die Jahreszeichenfolge des absoluten Wertes des Jahres. Ersetzen Sie dann alle Buchstaben durch das Basiskomplement 26 (A <-> Z, B <-> Y usw.) und alle Ziffern durch das Basiskomplement 10 (0 <-> 9, 1 <-> 8). usw.) und ersetzen Sie Carets durch Ausrufezeichen ( !). Wenn die Jahreszeichenfolge 4 Stellen oder weniger enthält (dh -1 bis -10.000), stellen Sie einen Schrägstrich ( /) voran . Wenn der Jahreszeichenfolge kein Schrägstrich oder Ausrufezeichen vorangestellt ist, stellen Sie ein Sternchen ( *) voran .
  • Monate, Tage, Stunden, Minuten und Sekunden : Da es sich bei diesen Werten immer nur um höchstens 2 Ziffern handelt, werden sie einfach in absteigender Reihenfolge der Signifikanz rechts von der Jahreszeichenfolge angehängt und bei Bedarf mit Nullen links aufgefüllt 2-stellige Zeichenfolge.
  • Zusätzliche Genauigkeit : Wenn eine zusätzliche Genauigkeit (in Form von Millisekunden, Mikrosekunden, Nanosekunden usw.) erforderlich ist, werden diese Werte mit Nullen bis zu drei Stellen links aufgefüllt (da jeder Wert 1/1000den vorherigen Wert hat und somit höchstens 999). und in absteigender Reihenfolge der Signifikanz an das Ende des Zeitstempels angehängt.

Dieses Format hat den Vorteil, dass die lexikalische Sortierung der numerischen Sortierung des entsprechenden Zeitstempels entspricht. Wenn Zeit A vor Zeit B liegt, liegt der Zeitstempel für A vor dem Zeitstempel für B, wenn die lexikalische Sortierung angewendet wird.

Die Herausforderung

Geben Sie bei einer beliebig langen Liste numerischer Werte (die beispielsweise Zeitwerten in absteigender Reihenfolge der Signifikanz [year, month, day, hour, minute, second, millisecond]entsprechen) den entsprechenden RFC 2550-Zeitstempel aus.

Regeln

  • Lösungen müssen für jede Eingabe funktionieren. Die einzigen Einschränkungen sollten die Zeit und der verfügbare Speicher sein.
  • Die Eingabe kann in jedem vernünftigen, praktischen Format erfolgen (z. B. eine Liste von Ziffern, eine Liste von Zeichenfolgen, eine Zeichenfolge, die durch ein einzelnes nichtstelliges Zeichen begrenzt ist, usw.).
  • Die Eingabe enthält immer mindestens einen Wert (das Jahr). Zusätzliche Werte sind immer in absteigender Reihenfolge der Signifikanz (z. B. enthält die Eingabe niemals einen Tageswert ohne einen Monatswert oder einen zweiten Wert, gefolgt von einem Monatswert).
  • Die Eingabe wird immer eine gültige Zeit sein (z. B. werden für den 30. Februar keine Zeitstempel angezeigt).
  • Builtins, die RFC 2550-Zeitstempel berechnen, sind verboten.

Beispiele

In diesen Beispielen wird die Eingabe als einzelne Zeichenfolge verwendet, wobei die einzelnen Werte durch Punkte ( .) getrennt sind.

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

Referenzimplementierung

#!/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
quelle
Sollte es -696443266.1.3.6.10.15.21.28doch sein *V3035567339896938984978971?
Neil
11
@Neil Bis wir negative Monate erfinden. Negember.
Mego
1
@TaylorScott Zusätzliche Genauigkeit : Wenn eine zusätzliche Genauigkeit (in Form von Millisekunden, Mikrosekunden, Nanosekunden usw.) erforderlich ist, werden diese Werte mit Nullen bis zu drei Ziffern links aufgefüllt.
Mego
2
Mir scheint, dass die in der Frage angegebene Spezifikation nicht mit RFC2550 übereinstimmt. Soweit ich weiß, sollte die Anzahl der Buchstaben nach drei Carets schneller zunehmen als nach drei Carets, da sie aus der Fibonacci-Reihe stammen (4 Carets bedeuten 5 Buchstaben, 5 Carets bedeuten 8 Buchstaben usw.) Nehmen wir an, wir sollten diesen Aspekt des RFC ignorieren?
James Holderness
1
@ JamesHolderness Du hast Recht, ich habe die Spezifikation durcheinander gebracht. Zum Korrigieren ist es jedoch zu spät, da bereits Antworten vorliegen, die ungültig werden würden.
Mego

Antworten:

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>

Schockierend lang.

Neil
quelle
Würde es Ihnen etwas ausmachen, ein Stack-Snippet zum einfachen Testen hinzuzufügen?
Mego
@Mego Fertig. Außerdem wurden einige Tippfehler behoben, die sich eingeschlichen haben (ich habe versehentlich einen Teil des Codes beim Kopieren und Einfügen gelöscht, weil mich der Zeilenumbruch verwirrt hat. Hoppla.)
Neil,
3

Befunge, 418 384 Bytes

Es ist schwer im Voraus zu sagen, wie groß ein Befunge-Programm voraussichtlich sein wird, und als ich anfing, daran zu arbeiten, dachte ich, dass es tatsächlich eine Chance hat, mitzumachen. Es stellte sich heraus, dass ich falsch lag.

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

Probieren Sie es online!

James Holderness
quelle
3

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

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

Probieren Sie es 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
Xcali
quelle
3

Java 8, 653 640 637 623 Bytes

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

Eingabe als String-array und Rückgabetyp als String.

Hat sich als ziemlich lang herausgestellt (wie erwartet), kann aber definitiv noch mehr golfen werden. Ich bin nur froh, dass es funktioniert, nachdem ich eine ganze Weile damit rumgespielt habe.

Probieren Sie es hier aus.

Erläuterung:

  • for(String p:s){: Schleifen Sie über die Teile
    • if(p.charAt(0)<46){p=p.substring(1);f=1;}: Bestimmen Sie, ob es negativ ist, und entfernen Sie das Minuszeichen, und setzen Sie ein Flag, um Bytes zu reduzieren
    • t=p.length();: Ermittelt die Anzahl der Ziffern
    • if(i++<1){: Wenn es die erste Zahl ist (das Jahr):
      • t<5?"000".substring(t-1): Wenn es 0-100.000 ist (exklusiv): Fügen Sie bei Bedarf führende Nullen hinzu
      • t<32?(char)(t+60): Wenn es 100.000-10 30 ist (exklusiv): Fügen Sie einen führenden Buchstaben hinzu
      • t<58?"^"+(char)(t+34): Wenn es 10 30 -10 732 (exklusiv) ist: Fügen Sie einen wörtlichen "^"+ führenden Buchstaben hinzu
      • if(t>57)for(r+="^^",u=675;u<t-57;u*=26)r+="^";: Addiere die entsprechende Menge an wörtlichen "^"+ x="";for(String c:Long.toString(t-57,26).toUpperCase().split(""))x+=z.charAt((y+q).indexOf(c));r+=x;: führenden Buchstaben (Basis-26 zur Alphabet-Konvertierung)
      • r+=p;: Addiere das Jahr selbst zum Ergebnis-String
      • if(f>0){: Wenn das Jahr negativ war:
        • x=t<5?"/":t<32?"*":r.replace("^","!").replaceAll("[^!]","");Erstellen Sie eine temporäre String: xmit dem richtigen /, *oder einem oder mehr!
        • for(char c c:r.toCharArray())x+=c>93?"":"ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210".charAt((z+y).indexOf(c));: Führen Sie die Konvertierung durch (AowntownZ, BowntownY, 0owntown9, 1owntown8 usw.)
        • r=x;: Und dann setzen Sie das Ergebnis auf diese temporäre Zeichenfolge x
    • else: Wenn es sich um Monat, Tage, Stunden, Minuten, Sekunden, Millisekunden, Mikrosekunden, Nanosekunden oder weniger handelt:
      • i>6?t<2?"00"+p:t<3?0+p:p: Wenn es Millisekunden oder weniger sind: Fügen Sie bei Bedarf führende Nullen hinzu
      • :t<2?0+p:p;: Andernfalls (Monat, Tage, Stunden, Minuten, Sekunden): Fügen Sie bei Bedarf eine einzelne führende Null hinzu
  • return r: Das Ergebnis zurückgeben
Kevin Cruijssen
quelle
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.).- Sie könnten Eingaben als eine Liste von Zahlen verwenden und die kostspielige Aufteilung und Konvertierung überspringen.
Mego
1
@Mego Leider sind Standardziffern ( longwobei 64 Bit die größten sind) in Java für einige Eingaben zu klein und daher Stringkürzer als java.math.BigInteger. Ich habe es allerdings in ein String-array geändert, sodass ich nicht die Aufteilung nach Punkten vornehmen muss, wodurch einige Bytes gespart wurden. Also danke.
Kevin Cruijssen
2

Excel VBA, 500 486 485 470 Bytes

Anonyme VBE-Sofortfensterfunktion

Die Funktion "Anonymes VBE-Sofortfenster", die Eingaben als Jahr von [A1], Monat von [B1], Tag von [C1], Stunde von [D1], Minute von [E1], Sekunde von [F1]und ein optionales Array mit zusätzlicher Genauigkeit von [G1:Z1]annimmt, berechnet den RFC2550-Zeitstempel und gibt sie an das VBE-Sofortfenster aus. Verwendet die unten angegebene Hilfsfunktion.

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

Hilfsfunktion

Deklarierte Hilfsfunktion, die eine eingegebene Nummer annimmt und diese Nummer in Basis 26 zurückgibt, so dass 1->Aund26->Z

Muss in einem öffentlichen Modul platziert werden.

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

Verwendung

Muss in einem klaren Modul verwendet werden, oder das Modul muß die Vars vor der Ausführung gelöscht werden j, ound pdavon ausgegangen werden in ihrem Standard, nicht initialisierten Zustand zu Beginn der Ausführung des Codes sein. Für j, die eine ist Variant\Integervariabel, dieser Standardwert ist 0und für ound p, welche Variant\StringVariablen Dieser Standardwert ist die leere Zeichenfolge ( "").

Die Eingabe, ein Array von Zeichenfolgen, wird aus 1:1dem ActiveSheet übernommen und in das VBE-Direktfenster ausgegeben.

Beispiel-E / A

[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

SubRoutine-Version

Deklarierte Subroutine, die Eingaben als Jahr von [A1], Monat von [B1], Tag von [C1], Stunde von [D1], Minute von [E1], Sekunde von [F1]und ein optionales Array mit zusätzlicher Genauigkeit von [G1:Z1]annimmt, berechnet den RFC2550-Zeitstempel und gibt diese in das VBE-Direktfenster aus.

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

Verwendung

Die Eingabe in den Bereich [A1:ZZ1]kann entweder manuell erfolgen, indem Sie nach Bedarf von links nach rechts in die Zellen tippen, oder indem Sie sie über das VBE-Direktfenster zuweisen.

Aufgrund der automatischen Konvertierung von Excel-Zahlen in wissenschaftliche Notation müssen Zahlen mit einer Basislänge von 10 oder mehr als 12 Stellen explizit als Text in die Zelle eingefügt werden, indem die Zelle entweder als Textzelle oder als Textzelle festgelegt wird indem Sie das Literal 'vor den Anfang des Zellenwerts stellen

Beispiel-E / A

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 und erklärt

''  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
quelle
2

Jelly , 165 126 Bytes

ḣ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

Probieren Sie es online!

In Zeile 4 wird die Jahresformatierung mit Hilfe der Zeilen 2 und 3 durchgeführt. In der ersten und letzten Zeile werden die Elemente der Eingabe auf die richtige Länge aufgefüllt und anschließend mit dem formatierten Jahr verkettet.

  • _µ‘l26Ċṗ@€ØAẎị@findet das Präfix der Basis 26. Es nimmt die kartesische Potenz des Alphabets ( ØA) für jede Zahl zwischen 1 und ceil (log 26 (floor (log 10 (year)) - n + 1)) (wobei n entweder 30 oder 4 ist) und erhält dann Indizes in diese Liste mit Boden (log 10 (Jahr)) - n ( ị@).
  • ç30;€”^UZF Formate Jahre> = 10 30 ( ®L>30¤?)
  • ç4⁶;Formate Jahre <10 30 . ( Bearbeiten : Speichern eines Bytes mit ⁶;anstelle von ;@⁶)
  • 1RḊ gibt ein leeres Präfix für Jahre <10 5 ( ®L>4¤?) an. Es nimmt die Liste der Ziffern und filtert dann jedes Element in sich heraus. Nur dies zu nutzen, um zu ergeben, []weil es hier nicht funktioniert. Dies wird nur zu ausgewertet []. und []arbeite hier nicht und ich konnte keine weiteren 2 Bytes finden, die eine leere Liste zurückgeben.
  • ;®AṾ€¤ Hängt das Jahr an das Präfix an und glättet es dann.
  • L=4”/xPräfixe a, /wenn die Länge des Jahres in der do-Anweisung von 4 ist ®S<0¤¡.
  • 2£FiЀ¹ị€2£UF¤nimmt die Komplemente A .. Z, 0 .. 9und ^ /*!wenn das Jahr negativ ist ( ®S<0¤¡). verweist auf den zweiten Link, ØD,“^ *!”,ØAder die Liste ist [['0' .. '9'], ['^',' ','/','*','!'], ['A' .. 'Z']]. Bei einem formatierten Jahr wie ^C125...diesem findet der Link den Index jedes Zeichens in der reduzierten Version und verwendet dann diese Indizes, um eine neue Zeichenfolge aus der reduzierten Version zu erstellen, in der jede Unterliste umgekehrt ist, dh ['9' .. '0','!','*','/',' ','^','Z' .. 'A']ergibt !X874.... /wird sich selbst zugeordnet, weil ihm ein Präfix vorangestellt wird, bevor das Komplement vollständig ist.
  • L=4a®S<0x@”/;fügt a /zu Beginn der negativen Jahre hinzu [-9999 .. -0001]. Ich vermute, dies kann verkürzt werden. Am Ende habe ich dies in die vorherige do-Anweisung ( ¡) aufgenommen und 7 Bytes gespart, weil ich dann nicht zweimal auf negative Jahre testen musste.

Es gibt viele Verwendungen von ¡in Zeile 4, und ich denke, sie könnten durch Verwendung von komprimiert werden, ?aber ich bin nicht sicher, wie ich diese zum Laufen bringen kann. Ich musste ?arbeiten und sparte ein paar Bytes.

James Holderness wies darauf hin, dass meine erste Einreichung Jahre mit 30 Ziffern nicht richtig handhabte. Es stellte sich heraus, dass der Fehler für jedes Jahr ein ZPräfix in der Basis 26 benötigte . Es stellte sich heraus, dass ich es nicht verwenden konnte, da es Ihnen [1,0]statt 26(duh) gibt, wenn Sie 26 in Basis 26 konvertieren . Stattdessen habe ich bestellte Paare mit Ersatz verwendet. Ich glaube nicht, dass es dafür ein Atom gibt, aber wenn ja, kann ich ein paar Bytes sparen. Die Behebung dieses Problems kostete mich ~ 40 Bytes. Auf jeden Fall mein bisher längstes Jelly-Programm. Bearbeiten : Es wurde ein kürzerer Weg gefunden, um das kartesische Produkt herzustellen. Mir wurde klar, dass ich nicht sicher war, ob der letzte für Präfixe mit mehr als zwei Buchstaben funktioniert, aber der neue Weg funktioniert.

Es tut mir leid, dass ich diesen Beitrag so oft bearbeitet habe, aber ich entdecke immer wieder Möglichkeiten, ihn zu verkürzen.

dylnan
quelle