Hitung cap waktu RFC 2550

26

RFC 2550 adalah proposal satiris (diterbitkan pada 1 April 1999) untuk representasi ASCII yang efisien ruang dari cap waktu yang dapat mendukung tanggal apa pun (bahkan yang sebelum permulaan alam semesta dan yang melewati akhir alam semesta yang diprediksi). Algoritma untuk menghitung stempel waktu yang kompatibel dengan RFC 2550 adalah sebagai berikut (catatan: semua rentang mencakup awal tetapi mengecualikan akhir - 0 hingga 10.000 berarti semua ntempat 0 <= n < 10000):

  • Format tahun
    • Tahun 0 hingga 10.000: angka desimal 4 digit, diisi dengan angka nol.
    • Tahun 10.000 hingga 100.000: angka desimal 5 digit, diawali dengan karakter A.
    • Tahun 100.000 hingga 10 30 : angka desimal untuk tahun tersebut, diawali dengan huruf ASCII huruf besar yang indeksnya dalam alfabet bahasa Inggris sama dengan jumlah digit pada tahun desimal, minus 5 (B untuk tahun 6-digit, C untuk 7 -digit tahun, dll.).
    • Tahun 10 30 hingga 10 56 : format yang sama dengan 10.000 hingga 10 30 , mulai huruf-hurufnya dengan A, dan tambahan awalan tanda sisipan ( ^) ke string (sehingga tahun 10 30 diwakili oleh ^A1000000000000000000000000000000, dan tahun 10 31 diwakili oleh oleh ^B10000000000000000000000000000000).
    • Tahun 10 56 hingga 10 732 : tahun diawali oleh dua tanda sisipan dan dua huruf besar ASCII. Huruf besar membentuk angka basis-26 yang mewakili jumlah digit pada tahun tersebut, minus 57.
    • Tahun 10 732 dan seterusnya: format yang sama untuk 10 56 hingga 10 732 digunakan, memperpanjangnya dengan menambahkan tanda sisipan dan huruf besar tambahan bila perlu.
    • Tahun SM (sebelum Tahun 0): hitung string tahun dari nilai absolut tahun tersebut. Kemudian, ganti semua huruf dengan komplemen base-26 mereka (A <-> Z, B <-> Y, dll.), Ganti semua digit dengan komplemen base-10 mereka (0 <-> 9, 1 <-> 8, dll.), dan ganti caret dengan tanda seru ( !). Jika string tahun adalah 4 digit atau kurang (yaitu -1 hingga -10.000), tambahkan garis miring ( /). Jika string tahun tidak diawali dengan garis miring ke depan atau tanda seru, tambahkan tanda bintang ( *).
  • Bulan, hari, jam, menit, dan detik : karena nilai-nilai ini hanya 2 digit paling banyak, mereka hanya ditambahkan ke kanan string tahun, dalam urutan penurunan signifikansi, berlapis kiri dengan nol jika perlu untuk membentuk String 2 digit.
  • Tambahan presisi : jika presisi tambahan (dalam bentuk milidetik, mikrodetik, nanodetik, dll.) Diperlukan, nilai-nilai tersebut dibiarkan dengan nol hingga 3 digit (karena setiap nilai 1/1000dari nilai sebelumnya, dan dengan demikian paling banyak 999) dan ditambahkan ke akhir timestamp, dalam urutan signifikansi yang menurun.

Format ini memiliki manfaat penyortiran leksikal yang setara dengan penyortiran numerik cap waktu yang sesuai - jika waktu A datang sebelum waktu B, maka timestamp untuk A akan datang sebelum timestamp untuk B ketika penyortiran leksikal diterapkan.

Tantangan

Diberikan daftar panjang nilai numerik yang sewenang-wenang (sesuai dengan nilai waktu dalam urutan signifikansi yang menurun, misalnya [year, month, day, hour, minute, second, millisecond]), mengeluarkan stempel waktu RFC 2550 yang sesuai.

Aturan

  • Solusi harus bekerja untuk setiap input yang diberikan. Satu-satunya batasan harus waktu dan memori yang tersedia.
  • Input dapat diambil dalam format yang wajar dan nyaman (seperti daftar angka, daftar string, string yang dibatasi oleh karakter non-digit tunggal, dll.).
  • Input akan selalu mengandung setidaknya satu nilai (tahun). Nilai tambahan selalu dalam urutan signifikansi yang menurun (mis. Input tidak akan pernah berisi nilai hari tanpa nilai bulan, atau nilai kedua diikuti oleh nilai bulan).
  • Input akan selalu menjadi waktu yang valid (mis. Tidak akan ada cap waktu untuk 30 Februari).
  • Builtin yang menghitung cap waktu RFC 2550 dilarang.

Contohnya

Contoh-contoh ini menggunakan input sebagai string tunggal, dengan nilai-nilai individual dipisahkan oleh titik ( .).

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

Implementasi referensi

#!/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
sumber
Tentunya -696443266.1.3.6.10.15.21.28seharusnya begitu *V3035567339896938984978971?
Neil
11
@Neil Sampai kami menemukan bulan negatif. Negember.
Mego
1
@TaylorScott Presisi tambahan : jika presisi tambahan (dalam bentuk milidetik, mikrodetik, nanodetik, dll.) Diperlukan, nilai-nilai tersebut dibiarkan berlapis dengan nol hingga 3 digit.
Mego
2
Bagi saya sepertinya spesifikasi yang diberikan dalam pertanyaan tidak benar-benar cocok dengan RFC2550. Seperti yang saya pahami, setelah Anda melewati tiga caret, jumlah huruf akan meningkat lebih cepat daripada caret, karena itu berasal dari seri Fibonacci (4 caret berarti 5 huruf, 5 caret berarti 8 huruf, dll.) Apakah aman untuk anggap kita harus mengabaikan aspek RFC itu?
James Holderness
1
@ JamesHolderness Kau benar, aku mengacaukan spek. Namun, sudah terlambat untuk memperbaikinya, karena sudah ada jawaban yang akan dibatalkan.
Mego

Jawaban:

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>

Sangat panjang.

Neil
sumber
Maukah Anda menambahkan Stack Snippet untuk pengujian mudah?
Mego
@Mego Done. Juga memperbaiki beberapa kesalahan ketik yang merayap masuk (saya tidak sengaja menghapus beberapa kode ketika menyalin dan menempel karena pembungkus baris membingungkan saya. Ups.)
Neil
3

Befunge, 418 384 byte

Sulit untuk mengatakan sebelumnya seberapa besar program Befunge kemungkinan akan berakhir, dan ketika saya mulai bekerja pada ini saya pikir itu mungkin benar-benar memiliki peluang untuk bersaing. Ternyata saya salah.

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

Cobalah online!

James Holderness
sumber
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

Cobalah online!

Tidak disatukan

$_=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
sumber
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;}

Masukkan as String-array dan ketik kembali sebagai String.

Ternyata cukup panjang (seperti yang diharapkan), tetapi pasti bisa bermain golf lagi. Aku hanya senang itu bekerja setelah mengutak-atiknya cukup lama ..

Coba di sini.

Penjelasan:

  • for(String p:s){: Loop bagian-bagian
    • if(p.charAt(0)<46){p=p.substring(1);f=1;}: Tentukan apakah itu negatif, dan jika ya, hapus tanda minus dan atur bendera untuk mengurangi byte
    • t=p.length();: Dapatkan jumlah digit
    • if(i++<1){: Jika ini angka pertama (tahun):
      • t<5?"000".substring(t-1): Jika 0-100.000 (eksklusif): tambahkan nol terkemuka jika perlu
      • t<32?(char)(t+60): Jika 100.000-10 30 (eksklusif): Tambahkan surat terkemuka
      • t<58?"^"+(char)(t+34): Jika 10 30 -10 732 (eksklusif): Tambahkan huruf literal "^"+ terkemuka
      • if(t>57)for(r+="^^",u=675;u<t-57;u*=26)r+="^";: Tambahkan jumlah huruf "^"+ x="";for(String c:Long.toString(t-57,26).toUpperCase().split(""))x+=z.charAt((y+q).indexOf(c));r+=x;: utama yang tepat (basis-26 ke konversi alfabet)
      • r+=p;: Tambahkan tahun itu sendiri ke String-hasil
      • if(f>0){: Jika tahun itu negatif:
        • x=t<5?"/":t<32?"*":r.replace("^","!").replaceAll("[^!]","");: Buat String temp xdengan benar /, *atau satu atau beberapa!
        • for(char c c:r.toCharArray())x+=c>93?"":"ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210".charAt((z+y).indexOf(c));: Lakukan konversi (A↔Z, B↔Y, 0↔9, 1↔8, dll.)
        • r=x;: Dan kemudian atur hasilnya ke String temp ini x
    • else: Jika bulan, hari, jam, menit, detik, milidetik, mikrodetik, nanodetik, atau lebih kecil:
      • i>6?t<2?"00"+p:t<3?0+p:p: Jika milidetik atau lebih kecil: Tambahkan nol terkemuka jika perlu
      • :t<2?0+p:p;: Lain-lain (bulan, hari, jam, menit, detik): Tambahkan nol memimpin tunggal jika perlu
  • return r: Kembalikan hasilnya
Kevin Cruijssen
sumber
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.).- Anda dapat mengambil input sebagai daftar angka, dan melewati pemisahan dan konversi yang mahal.
Mego
1
@Mego Sayangnya angka default ( longdengan 64 bit sebagai yang terbesar) terlalu kecil di Jawa untuk beberapa input, jadi Stringlebih pendek dari java.math.BigInteger. Saya mengubahnya menjadi String-array, jadi saya tidak perlu melakukan split dengan titik-titik, yang menyelamatkan beberapa byte, jadi terima kasih.
Kevin Cruijssen
2

Excel VBA, 500 486 485 470 Bytes

Fungsi Jendela Segera VBE Anonim

Fungsi jendela langsung VBE anonim yang mengambil input dari tahun [A1], bulan dari [B1], hari dari [C1], jam dari [D1], menit dari [E1], detik dari [F1]dan array presisi ekstra opsional dari [G1:Z1], menghitung cap waktu RFC2550 dan output ke jendela langsung VBE. Manfaatkan fungsi pembantu yang dinyatakan di bawah ini.

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

Fungsi Penolong

Deklarasi fungsi pembantu yang mengambil nomor input dan mengembalikan nomor itu di base-26 sedemikian rupa sehingga 1->Adan26->Z

Harus ditempatkan dalam modul publik.

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

Pemakaian

Harus digunakan dalam modul yang jelas, atau modul harus dibersihkan sebelum eksekusi sebagai vars j, odan pdiasumsikan dalam keadaan default dan tidak diinisialisasi pada awal pelaksanaan kode. Untuk j, yang merupakan Variant\Integervariabel, nilai default ini adalah 0dan untuk odan p, yang merupakan Variant\Stringvariabel, nilai default ini adalah string kosong ( "").

Input, array string, diambil dari 1:1pada ActiveSheet dan output ke jendela langsung VBE.

Contoh I / O

[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

SubVersi rutin

Menyatakan Subrutin yang mengambil input dari tahun [A1], bulan dari [B1], hari dari [C1], jam dari [D1], menit dari [E1], detik dari [F1]dan array presisi ekstra opsional dari [G1:Z1], menghitung cap waktu RFC2550 dan output ke jendela langsung 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

Pemakaian

Input ke kisaran [A1:ZZ1] dapat dilakukan secara manual, dengan mengetik ke dalam sel, dari paling kiri ke paling kanan, sesuai kebutuhan atau dengan menetapkan dari jendela langsung VBE.

Sebagai catatan, karena angka konversi otomatis Excel menjadi notasi ilmiah, angka apa pun yang memiliki panjang basis-10 sama dengan atau lebih besar dari 12 digit harus dimasukkan ke dalam sel secara eksplisit sebagai teks baik dengan mengatur sel menjadi sel teks atau dengan menambahkan awal literal 'ke awal nilai sel

Contoh I / O

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

Tidak Dijelaskan Dan Dijelaskan

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

Jelly , 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

Cobalah online!

Baris 4 melakukan pemformatan tahun dengan bantuan dari baris 2 dan 3. Baris pertama dan terakhir berurusan dengan nol yang mengisi elemen input dengan panjang yang sesuai kemudian menggabungkannya dengan tahun yang diformat.

  • _µ‘l26Ċṗ@€ØAẎị@menemukan awalan base 26. Dibutuhkan kekuatan kartesius dari alfabet ( ØA) untuk setiap angka antara 1 dan langit-langit (log 26 (lantai 10 (tahun 10 )) - n +1)) (di mana n adalah 30 atau 4) kemudian mendapat indeks ke dalam daftar ini dengan lantai (log 10 (tahun)) - n ( ị@).
  • ç30;€”^UZF format tahun> = 10 30 ( ®L>30¤?)
  • ç4⁶;format tahun <10 30 . ( Edit : Menyimpan byte dengan menggunakan ⁶;alih-alih ;@⁶)
  • 1RḊ memberikan awalan kosong selama bertahun-tahun <10 5 ( ®L>4¤?). Dibutuhkan daftar digit kemudian memfilter setiap elemen itu sendiri. Hanya menggunakan ini untuk menghasilkan []karena tidak berfungsi di sini. Ini hanya mengevaluasi []. dan []tidak bekerja di sini dan saya tidak dapat menemukan 2 byte lain yang mengembalikan daftar kosong.
  • ;®AṾ€¤ menambahkan tahun ke awalan kemudian meratakannya.
  • L=4”/xawalan a /jika panjang tahun adalah 4 pada pernyataan do dari ®S<0¤¡.
  • 2£FiЀ¹ị€2£UF¤mengambil pelengkap A .. Z, 0 .. 9dan ^ /*!jika tahun itu negatif ( ®S<0¤¡). merujuk ke tautan kedua, ØD,“^ *!”,ØAyang merupakan daftar [['0' .. '9'], ['^',' ','/','*','!'], ['A' .. 'Z']]. Dengan tahun yang diformat seperti ^C125...tautan ini menemukan indeks setiap karakter dalam versi yang diratakan kemudian menggunakan indeks tersebut untuk membuat string baru dari versi yang diratakan di mana setiap sublist dibalik, yaitu ['9' .. '0','!','*','/',' ','^','Z' .. 'A']menghasilkan !X874.... /peta itu sendiri karena diawali sebelum semuanya diambil komplemennya.
  • L=4a®S<0x@”/;menambahkan a /ke awal tahun negatif di [-9999 .. -0001]. Dugaan saya, ini bisa dipersingkat. Saya akhirnya memasukkan ini dalam pernyataan do ( ¡) sebelumnya dan menyimpan 7 byte karena saya tidak perlu menguji untuk tahun negatif dua kali.

Ada banyak kegunaan ¡pada baris 4 dan saya pikir mereka dapat dikompres dengan menggunakan ?sebagai gantinya, tetapi saya tidak yakin bagaimana cara membuatnya agar berfungsi. Saya mulai ?bekerja dan menyimpan beberapa byte.

James Holderness menunjukkan bahwa pengajuan pertama saya tidak menangani tahun dengan 30 digit benar. Ternyata bug itu untuk setiap tahun yang membutuhkan Zawalan base 26. Ternyata saya tidak bisa menggunakan karena ketika Anda mengkonversi 26 ke basis 26 itu memberi Anda [1,0]alih-alih 26(ya). Sebagai gantinya saya menggunakan pasangan yang dipesan dengan pengganti. Saya tidak berpikir ada atom untuk itu tetapi jika ada saya dapat menyimpan beberapa byte. Memperbaiki ini berakhir dengan biaya saya ~ 40 byte. Pasti program Jelly terlama saya. Sunting : Menemukan cara yang lebih singkat untuk melakukan produk kartesius. Saya menyadari bahwa saya tidak yakin bahwa yang terakhir bekerja untuk awalan dengan lebih dari dua huruf, tetapi cara baru itu berhasil.

Maaf untuk berkali-kali saya mengedit posting ini, saya terus mencari cara untuk memperpendeknya.

dylnan
sumber