Вычислить временную метку RFC 2550


26

RFC 2550 - это сатирическое предложение (опубликовано 1 апреля 1999 г.) для представления меток времени в формате ASCII с эффективным использованием пространства, которое может поддерживать любую дату (даже те, которые предшествуют началу вселенной и те, которые прошли после предсказанного конца вселенной). Алгоритм вычисления временной метки, соответствующей RFC 2550, следующий (примечание: все диапазоны включают начало, но исключают конец - от 0 до 10000 означают все nгде 0 <= n < 10000):

  • Формат года
    • Годы от 0 до 10000: четырехзначное десятичное число, дополненное нулями.
    • Годы от 10 000 до 100 000: пятизначное десятичное число с префиксом символа А.
    • Годы от 100 000 до 10 30 : десятичное число для года с префиксом буквы ASCII в верхнем регистре, индекс которого в английском алфавите равен количеству цифр в десятичном году, минус 5 (B для 6-значных лет, C для 7 лет и т. д.).
    • Годы с 10 30 по 10 56 : тот же формат, что и с 10 000 до 10 30 , начиная буквы с буквы A и дополнительно добавляя ^к строке символ вставки ( ) (таким образом, год 10 30 обозначен ^A1000000000000000000000000000000, а год 10 31 представлен по ^B10000000000000000000000000000000).
    • Годы с 10 56 по 10 732 : году предшествуют две строчные буквы и две заглавные буквы ASCII. Заглавные буквы образуют число из 26 цифр, обозначающее количество цифр в году, минус 57.
    • Года 10 732 и далее: тот же формат 10 56 10 732 используются, расширяя его путем добавления дополнительной каретки и прописными букв , когда это необходимо.
    • Годы до н.э. (до года 0): вычислите строку года абсолютного значения года. Затем замените все буквы их дополнением к основанию-26 (A <-> Z, B <-> Y и т. Д.), Замените все цифры их дополнением к основанию-10 (0 <-> 9, 1 <-> 8, и т. д.) и замените каретки восклицательными знаками ( !). Если строка года состоит из 4 цифр или менее (то есть от -1 до -10 000), добавьте косую черту ( /). Если строка года не имеет префикс перед косой чертой или восклицательный знак, добавьте звездочку ( *).
  • Месяцы, дни, часы, минуты и секунды : поскольку эти значения не более 2 цифр, они просто добавляются справа от строки года, в порядке убывания значимости, с добавлением нуля слева при необходимости для формирования 2-значные строки.
  • Дополнительная точность : если требуется дополнительная точность (в виде миллисекунд, микросекунд, наносекунд и т. Д.), Эти значения дополняются слева от нуля до 3 цифр (поскольку каждое значение имеет 1/1000предыдущее значение и, следовательно, самое большее 999) и добавляется в конце метки времени в порядке убывания значимости.

Преимущество этого формата заключается в том, что лексическая сортировка эквивалентна числовой сортировке соответствующей временной метки - если время A предшествует времени B, тогда временная метка для A будет предшествовать временной метке для B, когда применяется лексическая сортировка.

Соревнование

Учитывая произвольно длинный список числовых значений (например, соответствующих значениям времени в порядке убывания значимости [year, month, day, hour, minute, second, millisecond]), выведите соответствующую временную метку RFC 2550.

правила

  • Решения должны работать для любого данного входа. Единственными ограничениями должны быть время и доступная память.
  • Ввод может быть сделан в любом удобном и удобном формате (например, список чисел, список строк, строка, разделенная одним нецифровым символом и т. Д.).
  • Ввод всегда будет содержать хотя бы одно значение (год). Дополнительные значения всегда в порядке убывания значимости (например, входные данные никогда не будут содержать значения дня без значения месяца или второго значения, за которым следует значение месяца).
  • Ввод всегда будет действительным временем (например, 30 февраля не будет временных отметок).
  • Встроенные функции, которые вычисляют временные метки RFC 2550, запрещены.

Примеры

В этих примерах ввод используется как одна строка с отдельными значениями, разделенными точкой ( .).

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

Ссылочная реализация

#!/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)

Наверняка -696443266.1.3.6.10.15.21.28должно быть *V3035567339896938984978971?
Нил

11
@Neil Пока мы не изобретаем отрицательные месяцы. Negember.
Мего

1
@TaylorScott Дополнительная точность : если требуется дополнительная точность (в виде миллисекунд, микросекунд, наносекунд и т. Д.), Эти значения дополняются слева от нуля до 3 цифр.
Mego

2
Мне кажется, что спецификации, приведенные в вопросе, на самом деле не соответствуют RFC2550. Насколько я понимаю, после того, как вы пройдете три каретки, количество букв должно увеличиваться быстрее, чем каретки, потому что оно получено из серии Фибоначчи (4 каретки означают 5 букв, 5 кареток означают 8 букв и т. Д.) Безопасно ли Предположим, мы должны игнорировать этот аспект RFC?
Джеймс Холдернесс

1
@JamesHolderness Ты прав, я испортил спецификацию. Тем не менее, уже слишком поздно, чтобы исправить это, поскольку уже есть ответы, которые будут признаны недействительными.
Мего

Ответы:


5

JavaScript (ES6), 325 байт

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>

Шокирующе долго.


Не могли бы вы добавить фрагмент стека для простого тестирования?
Мего

@ Мего Готово. Также исправлены некоторые опечатки, которые закрались (я случайно удалил часть кода при копировании и вставке, потому что перенос строки сбил меня с толку. Упс.)
Нил

3

Befunge, 418 384 байта

Трудно сказать заранее, насколько велика может быть программа Befunge, и когда я начал работать над этим, я подумал, что у нее действительно есть шанс на конкуренцию. Оказывается, я был неправ.

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

Попробуйте онлайн!


3

Perl 5 , 328, 322, 317, 301 + 1 ( -a) = 302 байта.

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

Попробуйте онлайн!

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 байта

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

Введите как String-array и тип возврата как String.

Оказалось, довольно долго (как и ожидалось), но определенно можно играть в гольф еще немного. Я просто рад, что это работает после того, как возился с ним довольно долго ...

Попробуй это здесь.

Объяснение:

  • for(String p:s){: Петля по частям
    • if(p.charAt(0)<46){p=p.substring(1);f=1;}: Определите, является ли он отрицательным, и если это так, удалите знак минус и установите флажок для уменьшения байтов
    • t=p.length();: Получить количество цифр
    • if(i++<1){: Если это первый номер (год):
      • t<5?"000".substring(t-1): Если это 0-100000 (исключение): добавьте ведущие нули, если необходимо
      • t<32?(char)(t+60): Если это 100 000-10 30 (эксклюзив): добавьте начальную букву
      • t<58?"^"+(char)(t+34): Если это 10 30 -10 732 (эксклюзив): добавить буквальное "^"+ начальную букву
      • 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;: начальные буквы (от 26 к алфавиту)
      • r+=p;: Добавьте год к строке результата
      • if(f>0){Если год был отрицательным
        • x=t<5?"/":t<32?"*":r.replace("^","!").replaceAll("[^!]","");Создайте временную строку xс правильным /, *или один или несколько!
        • for(char c c:r.toCharArray())x+=c>93?"":"ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210".charAt((z+y).indexOf(c));: Выполнить преобразование (A↔Z, B↔Y, 0↔9, 1↔8 и т. Д.)
        • r=x;: И затем установите результат в эту временную строку x
    • elseЕсли это месяц, дни, часы, минуты, секунды, миллисекунды, микросекунды, наносекунды или меньше:
      • i>6?t<2?"00"+p:t<3?0+p:p: Если это миллисекунды или меньше: добавьте начальные нули, если необходимо
      • :t<2?0+p:p;: Остальное (месяц, дни, часы, минуты, секунды): при необходимости добавьте одиночный начальный ноль
  • return r: Вернуть результат

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.).- вы можете взять ввод в виде списка чисел и пропустить дорогостоящее разделение и преобразование.
Mego

1
@Mego К сожалению, числовые значения по умолчанию ( longс 64- битными значениями являются самыми большими) в Java слишком малы для некоторых входных данных, поэтому они Stringкороче java.math.BigInteger. Я изменил его на String-array, так что мне не нужно делать разбиение по точкам, что позволило сэкономить несколько байтов, так что спасибо.
Кевин Круйссен

2

Excel VBA, 500 486 485 470 байт

Anonymous VBE Immediate Window Function

Функция анонимного непосредственного окна VBE, которая принимает входные данные из года [A1], месяца [B1], дней [C1], часов [D1], минут [E1], секунд [F1]и дополнительного массива с дополнительной точностью [G1:Z1], вычисляет временную метку RFC2550 и выводит ее в окно немедленного VBE. Использует объявленную вспомогательную функцию ниже.

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

Вспомогательная функция

Объявленная вспомогательная функция, которая принимает входной номер и возвращает этот номер в base-26, так что 1->Aи26->Z

Должен быть помещен в публичный модуль.

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

использование

Должен использоваться в модуле очистки, или модуль должен быть очищен перед выполнением в качестве переменных j, oи pпредполагается, что он находится в их неинициализированном состоянии по умолчанию в начале выполнения кода. Для j, который является Variant\Integerпеременной, это значение по умолчанию равно 0и для oи p, которые являются Variant\Stringпеременными, это значение по умолчанию является пустой строкой ( "").

Input, массив строк, берется из 1:1ActiveSheet, а вывод - в непосредственное окно VBE.

Образец ввода / вывода

[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

Subрутинная версия

Объявленная подпрограмма, которая принимает входные данные как год от [A1], месяц с [B1], дни с [C1], часы с [D1], минуты с [E1], секунды с [F1]и необязательный массив дополнительной точности с [G1:Z1], вычисляет временную метку RFC2550 и выводит ее в непосредственное окно 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

использование

Ввод в диапазон [A1:ZZ1]может быть сделан либо вручную, путем ввода в ячейки, слева направо, по мере необходимости, либо путем назначения из непосредственного окна VBE.

Следует отметить, что из-за автоматического преобразования чисел Excel в научную нотацию любые числа, длина основания которых равна 12 или превышает 12 цифр, должны быть явно вставлены в ячейку в виде текста либо путем установки ячейки в текстовую ячейку, либо добавляя литерал 'к началу значения ячейки

Образец ввода / вывода

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

Неуправляемый и объясненный

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

Желе , 165 126 байтов

ḣ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

Попробуйте онлайн!

Строка 4 выполняет форматирование года с помощью строк 2 и 3. Первая и последняя строка имеют дело с нулевым заполнением элементов ввода до их надлежащей длины, а затем объединяют их с форматированным годом.

  • _µ‘l26Ċṗ@€ØAẎị@находит префикс базы 26 Он принимает декартову степень алфавита ( ØA) для каждого числа от 1 до ceil (log 26 (floor (log 10 (year)) - n + 1)) (где n равно 30 или 4), затем получает индексы в этот список с полом (бревно 10 (год)) - n ( ị@).
  • ç30;€”^UZF форматы лет> = 10 30 ( ®L>30¤?)
  • ç4⁶;Форматы лет <10 30 . ( Изменить : сохранить байт, используя ⁶;вместо ;@⁶)
  • 1RḊ дает пустой префикс для лет <10 5 ( ®L>4¤?). Он берет список цифр, а затем отфильтровывает каждый элемент сам по себе. Просто используя это, чтобы уступить, []потому что здесь не работает. Это только оценивает []. и []не работает здесь, и я не смог найти еще 2 байта, которые возвращают пустой список.
  • ;®AṾ€¤ добавляет год к префиксу, а затем выравнивает его.
  • L=4”/xпрефиксы a, /если длина года равна 4 в операторе do ®S<0¤¡.
  • 2£FiЀ¹ị€2£UF¤принимает дополнения A .. Z, 0 .. 9а ^ /*!если год отрицательный ( ®S<0¤¡). ссылается на вторую ссылку, ØD,“^ *!”,ØAкоторая является списком [['0' .. '9'], ['^',' ','/','*','!'], ['A' .. 'Z']]. С форматированным годом, подобным ^C125...этой ссылке, находит индекс каждого символа в сглаженной версии, а затем использует эти индексы для построения новой строки из сглаженной версии, в которой каждый подсписок обращен, то есть ['9' .. '0','!','*','/',' ','^','Z' .. 'A']дает !X874.... /сопоставляется с самим собой, потому что он имеет префикс, прежде чем все будет принято его дополнение.
  • L=4a®S<0x@”/;добавляет /к началу отрицательных лет в [-9999 .. -0001]. Я думаю, это можно сократить. В итоге я включил это в предыдущую инструкцию do ( ¡) и сохранил 7 байтов, потому что тогда мне не нужно было проверять отрицательные годы дважды.

В ¡строке 4 есть много применений, и я думаю, что их можно сжать, используя ?вместо этого, но я не уверен, как заставить их работать. Я получил ?работу и сэкономил несколько байтов.

Джеймс Холдернесс отметил, что в моем первом представлении не было написано лет с правильными 30 цифрами. Оказалось, что ошибка была для любого года, который нуждался Zв префиксе base 26. Оказывается, я не мог использовать, потому что когда вы конвертируете 26 в базу 26, это дает вам [1,0]вместо 26(дух). Вместо этого я использовал заказанные пары с заменой. Я не думаю, что для этого есть атом, но если он есть, я могу сэкономить несколько байтов. Исправление этого стоило мне ~ 40 байт. Определенно моя самая длинная программа желе еще. Изменить : Нашел более короткий способ сделать декартово произведение. Я понял, что не уверен, что последний работает для префиксов с более чем двумя буквами, но новый способ работает.

Извините за то, что много раз редактировал этот пост, я просто продолжаю находить способы его сокращения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.