28
\$\begingroup\$

RFC 2550 is a satirical proposal (published on April 1, 1999) for a space-efficient ASCII representation of timestamps that can support any date (even those prior to the beginning of the universe and those past the predicted end of the universe). The algorithm for computing a RFC 2550-compliant timestamp is as follows (note: all ranges include the start but exclude the end - 0 to 10,000 means all n where 0 <= n < 10000):

  • Year format
    • Years 0 to 10,000: a 4-digit decimal number, left-padded with zeroes.
    • Years 10,000 to 100,000: a 5-digit decimal number, prefixed with the character A.
    • Years 100,000 to 1030: the decimal number for the year, prefixed with the uppercase ASCII letter whose index in the English alphabet is equal to the number of digits in the decimal year, minus 5 (B for 6-digit years, C for 7-digit years, etc.).
    • Years 1030 to 1056: the same format as 10,000 to 1030, starting the letters over with A, and additionally prefixing a caret (^) to the string (so the year 1030 is represented by ^A1000000000000000000000000000000, and the year 1031 is represented by ^B10000000000000000000000000000000).
    • Years 1056 to 10732: the year is prefixed by two carets and two ASCII uppercase letters. The uppercase letters form a base-26 number representing the number of digits in the year, minus 57.
    • Years 10732 onwards: the same format for 1056 to 10732 is used, extending it by adding an additional caret and uppercase letter when necessary.
    • BCE years (prior to Year 0): compute the year string of the absolute value of the year. Then, replace all letters by their base-26 complement (A <-> Z, B <-> Y, etc.), replace all digits by their base-10 complement (0 <-> 9, 1 <-> 8, etc.), and replace carets with exclamation marks (!). If the year string is 4 digits or less (i.e. -1 to -10,000), prepend a forward slash (/). If the year string is not prefixed by a forward slash or an exclamation mark, prepend an asterisk (*).
  • Months, days, hours, minutes, and seconds: since these values are only ever 2 digits at the most, they are simply appended to the right of the year string, in decreasing order of significance, left-padded with zeroes if necessary to form 2-digit strings.
  • Additional precision: if additional precision (in the form of milliseconds, microseconds, nanoseconds, etc.) is needed, those values are left-padded with zeroes to 3 digits (because each value is 1/1000 of the previous value, and thus is at most 999) and appended to the end of the timestamp, in decreasing order of significance.

This format has the benefit of lexical sorting being equivalent to numeric sorting of the corresponding timestamp - if time A comes before time B, then the timestamp for A will come before the timestamp for B when lexical sorting is applied.

The challenge

Given an arbitrarily-long list of numeric values (corresponding to time values in decreasing order of significance, e.g. [year, month, day, hour, minute, second, millisecond]), output the corresponding RFC 2550 timestamp.

Rules

  • Solutions must work for any given input. The only limitations should be time and available memory.
  • 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.).
  • The input will always contain at least one value (the year). Additional values are always in decreasing order of significance (e.g. the input will never contain a day value without a month value, or a second value followed by a month value).
  • Input will always be a valid time (e.g. there won't be any timestamps for February 30th).
  • Builtins which compute RFC 2550 timestamps are forbidden.

Examples

These examples use input as a single string, with the individual values separated by periods (.).

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

Reference implementation

#!/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)
\$\endgroup\$
13
  • \$\begingroup\$ Surely -696443266.1.3.6.10.15.21.28 should be *V3035567339896938984978971? \$\endgroup\$ – Neil May 30 '16 at 20:46
  • 13
    \$\begingroup\$ @Neil Until we invent negative months. Negember. \$\endgroup\$ – user45941 May 30 '16 at 22:53
  • 1
    \$\begingroup\$ @TaylorScott Additional precision: if additional precision (in the form of milliseconds, microseconds, nanoseconds, etc.) is needed, those values are left-padded with zeroes to 3 digits. \$\endgroup\$ – user45941 Jan 4 '18 at 22:44
  • 2
    \$\begingroup\$ It looks to me like the spec given in the question doesn't actually match RFC2550. As I understand it, once you get past three carets the number of letters should increase faster than the carets do, because it's derived from the Fibonacci series (4 carets means 5 letters, 5 carets means 8 letters, etc.) Is it safe to assume we should be ignoring that aspect of the RFC? \$\endgroup\$ – James Holderness Jan 8 '18 at 3:34
  • 1
    \$\begingroup\$ @JamesHolderness You're right, I messed up the spec. However, it's too late to correct it, as there are already answers that would be invalidated. \$\endgroup\$ – user45941 Jan 8 '18 at 4:58
5
\$\begingroup\$

Befunge, 418 384 bytes

It's hard to tell in advance how large a Befunge program is likely to end up, and when I started working on this I thought it might actually have some chance of competing. Turns out I was wrong.

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

Try it online!

\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 325 bytes

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>

Shockingly long.

\$\endgroup\$
2
  • \$\begingroup\$ Would you mind adding a Stack Snippet for easy testing? \$\endgroup\$ – user45941 May 31 '16 at 6:25
  • \$\begingroup\$ @Mego Done. Also fixed some typos that crept in (I accidentally deleted some of the code when copying and pasting because the line wrapping confused me. Oops.) \$\endgroup\$ – Neil May 31 '16 at 7:53
3
\$\begingroup\$

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

Try it 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
\$\endgroup\$
0
3
+75
\$\begingroup\$

Java 11, 653 640 637 623 618 595 589 bytes

s->{String e="",r=e,q="ABCDEFGHIJKLMNOP",z=q+"QRSTUVWXYZ",y="0123456789",x;int i=0,f=0,t,u,v;for(var p:s){p=p.charAt(v=0)<46?p.substring(f=1):p;t=p.length();if(i++<1){r+=(t<5?"0".repeat(4-t):t<32?(char)(t+60):t<58?"^"+(char)(t+33+(v=1)):e);if(t>57){for(v=2,u=675;u<t-57;u*=26)v++;r+="^".repeat(v);x=e;for(var c:Long.toString(t-57,26).toUpperCase().split(e))x+=z.charAt((y+q).indexOf(c));r+=x;}r+=p;if(f>0){x=t<5?"/":t<32?"*":"!".repeat(v);for(int c:r.getBytes())x+=c>93?e:new StringBuffer(y+z).reverse().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;}

Input as String-array and return-type as String.

Turned out to be quite long (as expected), but can definitely be golfed some more. I'm just glad it works after fiddling with it for quite a while..
-5 bytes thanks to @ceilingcat.

Try it here.

Explanation:

  • for(var p:s){: Loop over the parts
    • p=p.charAt(0)<46?p.substring(f=1):p;: Determine if it's negative, and if it is, remove the minus sign and set a flag to reduce bytes
    • t=p.length();: Get the amount of digits
    • if(i++<1){: If it's the first number (the year):
      • t<5?"0".repeat(4-t): If it's in the range \$[0, 100000)\$: add leading zeroes if necessary
      • t<32?(char)(t+60): If it's in the range \$[100000, 10^{30})\$: Add a leading letter
      • t<58?"^"+(char)(t+33+(v=1)): If it's in the range \$[10^{30}, 10^{732})\$: Add a literal "^" (and set v to 1) + leading letter
      • if(t>57)for(v=2,u=675;u<t-57;u*=26)v++;r+="^".repeat(v): Add the appropriate amount of literal "^" (and set v to that amount), plus x=e;for(var c:Long.toString(t-57,26).toUpperCase().split(e))x+=z.charAt((y+q).indexOf(c));r+=x;: leading letters (base-26 to alphabet conversion)
      • r+=p;: Add the year itself to the result-String
      • if(f>0){: If the year was negative:
        • x=t<5?"/":t<32?"*":"!".repeat(v);: Create a temp String x with the correct /, * or v amount of !
        • for(int c:r.getBytes())x+=c>93?e:new StringBuffer(y+z).reverse().charAt((z+y).indexOf(c));: Do the conversion (A↔Z, B↔Y, 0↔9, 1↔8, etc.)
        • r=x;: And then set the result to this temp String x
    • else: If it's the month, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, or smaller:
      • i>6?t<2?"00"+p:t<3?0+p:p: If it's milliseconds or smaller: Add leading zeroes if necessary
      • :t<2?0+p:p;: Else (month, days, hours, minutes, seconds): Add single leading zero if necessary
  • return r: Return the result
\$\endgroup\$
4
  • \$\begingroup\$ 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.). - you could take input as a list of numerics, and skip the costly splitting and conversion. \$\endgroup\$ – user45941 Jan 4 '18 at 22:45
  • 1
    \$\begingroup\$ @Mego Unfortunately default numerics (long with 64 bits being the largest) are too small in Java for some of the inputs, so String is shorter than java.math.BigInteger. I did change it to a String-array though, so I don't need to do the split by dots, which saved some bytes, so thanks. \$\endgroup\$ – Kevin Cruijssen Jan 5 '18 at 7:48
  • \$\begingroup\$ What. The. F. Is the magic going on here... \$\endgroup\$ – null Aug 27 '20 at 13:16
  • \$\begingroup\$ @HighlyRadioactive There is an explanation ;p Although without reading the challenge description it would indeed make zero sense, haha. Btw, I've just ported my Java answer to 05AB1E, which is even less readable and probably closer to magic if you're not familiar with the language. ;) \$\endgroup\$ – Kevin Cruijssen Aug 27 '20 at 13:58
2
\$\begingroup\$

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

Try it online!

Line 4 does the year formatting with help from lines 2 and 3. The first and last line deal with zero padding the elements of the input to their proper lengths then concatenating them with the formatted year.

  • _µ‘l26Ċṗ@€ØAẎị@ finds the base 26 prefix. It takes the cartesian power of the alphabet (ØA) for each number between 1 and ceil(log26(floor(log10(year))-n+1)) (where n is either 30 or 4) then gets indexes into this list with floor(log10(year))-n (ị@).
  • ç30;€”^UZF formats years >= 1030 (®L>30¤?)
  • ç4⁶; formats years < 1030. (Edit: Saved a byte by using ⁶; instead of ;@⁶)
  • 1RḊ gives an empty prefix for years < 105 (®L>4¤?). It takes the list of digits then filters out every element in itself. Just using this to yield [] because doesn't work here. This just evaluates to []. and [] don't work here and I couldn't find another 2 bytes that return an empty list.
  • ;®AṾ€¤ appends the year to the prefix then flattens it.
  • L=4”/x prefixes a / if the length of the year is 4 in the do statement of ®S<0¤¡.
  • 2£FiЀ¹ị€2£UF¤ takes the complements of A .. Z, 0 .. 9 and ^ /*! if the year is negative (®S<0¤¡). refers to the second link, ØD,“^ *!”,ØA which is the list [['0' .. '9'], ['^',' ','/','*','!'], ['A' .. 'Z']]. With a formatted year like ^C125... this link finds the index of each character in the flattened version of then uses those indices to construct a new string from the flattened version of where each sublist is reversed, i.e. ['9' .. '0','!','*','/',' ','^','Z' .. 'A'], yielding !X874.... / maps to itself because it is prefixed before everything has its complement taken.
  • L=4a®S<0x@”/; adds a / to the beginning of negative years in [-9999 .. -0001]. My guess is this can be shortened. I ended up including this in the previous do statement (¡) and saved 7 bytes because then I didn't need to test for negative years twice.

There are a lot of uses of ¡ in line 4 and I think they could be compressed by using ? instead but I'm not sure how to get those to work. I got ? to work and saved a few bytes.

James Holderness pointed out that my first submission didn't handle years with 30 digits correct. It turned out the bug was for any year that needed a Z in the base 26 prefix. It turns out I couldn't use because when you convert 26 to base 26 it gives you [1,0] instead of 26 (duh). Instead I used ordered pairs with replacement. I don't think there is an atom for that but if there is I can save a few bytes. Fixing this ended up costing me ~40 bytes. Definitely my longest Jelly program yet. Edit: Found a shorter way to do the cartesian product. I realized that I wasn't sure that the last one worked for prefixes with more than two letters anyway but the new way does work.

Sorry for the many times I've edited this post, I just keep discovering ways of shortening it.

\$\endgroup\$
0
2
\$\begingroup\$

Excel VBA, 500 486 485 461 Bytes

Anonymous VBE Immediate Window Function

Anonymous VBE immediate window function that takes input as year from [A1], month from [B1], days from [C1], hours from [D1], minutes from [E1], seconds from [F1] and an optional extra precision array from [G1:Z1], calculates the RFC2550 timestamp and outputs to the VBE immediate window. Makes use of the declared helper function below.

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

Helper Function

Declared helper function that takes an input number and returns that number in base-26 such that 1->A and 26->Z

Must be placed into a public module.

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

Usage

Must be used in a clear module, or the module must be cleared before execution as the vars j, o and p are assumed to be in their default, uninitialized state at the beginning of execution of the code. For j, which is a Variant\Integer variable, this default value is 0 and for o and p, which are Variant\String variables, this default value is the empty string ("").

Input, an array of strings, is taken from 1:1 on the ActiveSheet and output is to the VBE immediate window.

Sample 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
\$\endgroup\$
0
\$\begingroup\$

05AB1E, 104 bytes

εþNĀiN6@Ìjð0:ëg©Ž¾S₃в@DUO0®4α×®60+ç®34+ç'^ì®57-D<₂®Ým675*@OÌ'^×sAuÅвJ«)ćèyÄ«y0‹ižK'^ìžL'!쇄/*õªX2£Oèì]J

Input as a list of integers.

Based on my Java answer.

Try it online or verify all test cases.

Explanation:

ε                          # Map over each integer `y` of the (implicit) input-list
 þ                         #  Only leave digits (same as absolute value `Ä`, but results in a string)
  NĀi                      #  If the 0-based map-index is NOT 0 (so not the year):
     N6@                   #   Check if the map-index is >= 6 (1 if truthy; 0 if falsey),
                           #   thus milliseconds or smaller
        Ì                  #   Increase that by 2
         j                 #   Add leading spaces to abs(y) to make the length (N>=6)+2 long
                           #   (note that builtin `j` requires the first argument to be a string,
                           #    hence the use of `þ` over `Ä` earlier)
          ð0:              #   And replace those leading spaces with 0s
    ë                      #  Else (the map-index is 0, thus the year):
     g                     #   Pop the absolute value, and push its length
      ©                    #   Store this length in variable `®` (without popping)
       Ž¾S                 #   Push compressed integer 48223
          ₃в               #   Convert it to base-95 as list: [5,32,58]
            @              #   Check for each if they're >= the length (1 if truthy; 0 if falsey)
             DU            #   Store a copy of those checks in variable `X`
               O           #   Sum the checks to get the amount of truthy values
      ®                    #   Push the length from `®` again
       4α                  #   Take its absolute difference with 4
     0   ×                 #   Repeat 0 that many times as string
     ®                     #   Push the length `®` again
      60+                  #   Add 60
         ç                 #   Convert it to an ASCII character with this codepoint
     ®                     #   Push the length `®` again
      34+                  #   Add 34
         ç                 #   Convert it to an ASCII character with this codepoint
          '^ì             '#   Prepend "^"
     ®                     #   Push the length `®` again
      57-                  #   Subtract 57
         D                 #   Duplicate it
          <                #   Decrease it by 1 (thus `®`-58)
            ®Ý             #   Push a list in the range [0,`®`]
           ₂  m            #   Take 26 to the power of each value in this list
               675*        #   Multiply each by 675
                   @       #   Check for each if the `®`-58 is >= the value
                    O      #   Sum those checks
                     Ì     #   Increase it by 2
                      '^× '#   Have that many "^"
      s                    #   Swap so `®`-57 is at the top of the stack again
       AuÅв                #   Convert it to base-"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                           #   basically convert it to base-26 and index it into the alphabet
           J               #   And join those characters together to a single string
            «              #   After which we'll append it to the "^"-string
     )                     #   Wrap all values on the stack into a list
      ć                    #   Extract head; pop and push remainder-list and the first item separated,
                           #   where the first item is the sum of truthy values we calculated earlier
       è                   #   Use that to 0-based index into the remainder-list
        yÄ                 #   Push the absolute value of integer `y` again
          «                #   And append it to the string
     y0‹i                  #   If integer `y` is negative:
         žK                #    Push string "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
           '^ì            '#    Prepend a leading "^"
         žL                #    Push string "zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA9876543210"
           '!ì            '#    Prepend a leading "!"
              ‡            #    Transliterate all characters in the string
         „/*               #    Push string "/*"
            õª             #    Convert it to a list of characters, and append "": ["/","*",""]
              X            #    Push the list of checks we saved in variable `X`
               2£          #    Only leave the first two checks
                 O         #    Sum those
                  è        #    Use it to 0-based index into the ["/","*",""]
                   ì       #    And prepend it in front of the string
]                          # Close all if-statements and the map
 J                         # And join all mapped strings together
                           # (after which the result is output implicitly)

See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand why Ž¾S is 48223; Ž¾S₃в is [5,32,58]; and is.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ I'm however much more familiar with 05AB1E than Java, I learned it as my first golfing language... \$\endgroup\$ – null Aug 27 '20 at 14:00
  • 1
    \$\begingroup\$ @HighlyRadioactive Ah nice. 05AB1E is my first golfing language as well. Before that I answered all challenges mostly in Java. :) \$\endgroup\$ – Kevin Cruijssen Aug 27 '20 at 14:05
  • \$\begingroup\$ Write a 05AB1E to Java transpiler. Or better, write a Java to 05AB1E transpiler. \$\endgroup\$ – null Aug 27 '20 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy