12
\$\begingroup\$

URLs are getting too long. So, you must implement an algorithm to shorten a URL.

i. The Structure of a URL

A URL has 2 main parts: a domain and a path. A domain is the part of the URL before the first slash. You may assume that the URL does not include a protocol. The path is everything else.

ii. The Domain

The domain of a URL will be something like: xkcd.com meta.codegolf.stackexcchhannnge.cooom. Each part is period-seperated, e.g. in blag.xkcd.com, the parts are "blag", "xkcd", and "com". This is what you will do with it:

  • If it contains more than two parts, put the last two aside and concatenate the first letter of the rest of the parts.

  • Then, concatenate that to the first letter to the second-to-last part.

  • Add a period and the second and third letter of the second-to-last part.

  • Discard the last part.

iii. The Path

The path will be like: /questions/2140/ /1407/. As before, "parts" are seperated by slashes. For each part in the path, do:

  • Add a slash

  • If it is completely made of base-ten digits, interpret it as a number and convert to a base-36 integer.

  • Otherwise, add the first letter of the part.

At the end, add a slash.

iv. Misc.

  • This is , so shortest code wins.
  • The path can be empty, but the URL will always end with a slash.
  • There will not be a protocol (e.g. http://, file:///)
  • There will never be less than two parts in the domain.
  • Standard loopholes apply.

Examples

In: xkcd.com/72/
Out: x.kc/20/

In: math.stackexchange.com/a/2231/
Out: ms.ta/a/1pz/

In: hello.org/somecoolcodeintrepreteriijjkk?code=3g3fzsdg32,g2/
Out: h.el/s/

\$\endgroup\$
  • \$\begingroup\$ In your last example, doesn't the path end at kk and everything starting with ? is a query string, which shouldn't end with a slash? Also not all URLs will end with a slash /, like www.something.com/path. Or is this irrelevant for the purpose of this challenge? \$\endgroup\$ – insertusernamehere Jan 22 '16 at 8:57
  • \$\begingroup\$ That is irrelevant. \$\endgroup\$ – ev3commander Jan 24 '16 at 20:07
0
\$\begingroup\$

Pyth, 93 85 bytes

Lsm@+jkUTGdjb36J<zxz\/KP>zhxz\/=cJ\.pss[mhd<J_2hePJ\.<tePJ2\/;=cK\/sm+?-djkUThdysd\/K

Hand-compiled to pythonic pseudocode:

                z = input()                     # raw, unevaluated
                G = "abcdefghijklmnopqrstuvwxyz"
                k = ""
                T = 10
L               def y(b):                       # define y as base10to36
 sm                 join(map(lambda d:
  @+jkUTGd            (join(range(T),interleave=k)+G)[d],
                                                # the join(..)+G makes "0...9a...z"
  jb36                 convert(b,36)            # returns a list of digit values in base10
J<zxz\/         J = z[:z.index("\/")]           # domain portion
KP>zhxz\/       K = z[1+z.index("\/"):][:-1]    # path portion
=cJ\.           J = J.split(".")                # splits domain into parts
pss[            no_newline_print(join(join[     # 1 join yields a list, the other a string
 mhd<J_2            map(lambda d:d[0],J[:-2]),
 hePJ               J[:-1][-1][1],
 \.                 ".",
 <tePJ2             J[:-1][-1][1:][:2],
 \/                 "\/"
;               ])
=cK\/           K = K.split("\/")
sm              print(join(map(lambda d:
 +?-djkUThdysd\/    "\/"+(d[0] if filterOut(d,join(range(T),interleave=k)) else y(int(d))),
                    # the filter will turn pure number into empty string, which is False
 K                  K)))

Finally, the excruciation ends...

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

JavaScript (ES6), 149 bytes

u=>u.split`/`.map((p,i)=>i?/^\d+$/.test(p)?(+p).toString(36):p[0]:(d=p.split`.`).slice(0,-1).map((s,j)=>s[l=j,0]).join``+"."+d[l].slice(1,3)).join`/`

Explanation

I made this independent of @Neil's solution but it ended up looking very similar.

u=>
  u.split`/`.map((p,i)=>       // for each part p at index i
    i?                         // if this is not the first part
      /^\d+$/.test(p)?         // if p is only digits
        (+p).toString(36)      // return p as a base-36 number
      :p[0]                    // else return the first letter
    :
      (d=p.split`.`)           // d = domain parts
      .slice(0,-1).map((s,j)=> // for each domain part before the last
        s[l=j,0]               // return the first letter, l = index of last domain part
      ).join``
      +"."+d[l].slice(1,3)     // add the 2 letters as the final domain
  )
  .join`/`                     // output each new part separated by a slash

Test

var solution = u=>u.split`/`.map((p,i)=>i?/^\d+$/.test(p)?(+p).toString(36):p[0]:(d=p.split`.`).slice(0,-1).map((s,j)=>s[l=j,0]).join``+"."+d[l].slice(1,3)).join`/`
<input type="text" id="input" value="math.stackexchange.com/a/2231/" />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>

\$\endgroup\$
1
\$\begingroup\$

JavaScript ES6, 157 bytes

u=>u.split`/`.map((p,i)=>i?/^\d+$/.test(p)?(+p).toString(36):p[0]:p.split`.`.reverse().map((h,i)=>i--?i?h[0]:h[0]+'.'+h[1]+h[2]:'').reverse().join``).join`/`

Edit: Saved 4 bytes thanks to Doᴡɴɢᴏᴀᴛ.

\$\endgroup\$
  • \$\begingroup\$ You should be able to make .split('/') and .split('.') into string templates \$\endgroup\$ – Downgoat Jan 21 '16 at 21:32
  • \$\begingroup\$ @Doᴡɴɢᴏᴀᴛ Bah, I remembered on join as well! \$\endgroup\$ – Neil Jan 21 '16 at 21:39
1
\$\begingroup\$

Python 2, 378 365 Bytes

Update

Golfed it down by a bit. The ~150 Bytes for the base36-function are annoying, but I can't get rid of it until python has a builtin for that...

def b(n):
 a=abs(n);r=[];
 while a :
    r.append('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'[a%36]);a//=36
 if n<0:r.append('-')
 return''.join(reversed(r or'0'))
u=raw_input();P=u.split("/")[0].split(".")
print"".join([p[0] for p in P[0:-2]]+[P[-2][0]]+["."]+list(P[-2])[1:3]+["/"]+[b(int(p))+"/"if p.isdigit()else p[0]+"/" for p in u.split(".")[-1].split("/")[1:-1]])

Old version

def b(n):
 a=abs(n)
 r=[]
 while a:
    r.append('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'[a%36])
    a//=36
 if n<0:r.append('-')
 return''.join(reversed(r or'0'))
u=raw_input()
P=u.split("/")[0].split(".")
s=""
if len(P)>2:
 for p in P[:-2]:s+=p[0]
s+=P[-2][0]+"."+P[0][1:3]
P=u.split(".")[-1].split("/")[1:-1]
for p in P:
 s+="/"+(b(int(p)) if p.isdigit() else p[0])
print s+"/"

Since Python does not have a builtin way to convert ints to a base36-String, I took the implementation from numpy and golfed it down. Rest is pretty straightforward, I will golf it down more after work. Suggestions always appreciated in the meantime!

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

Pyhton 2, 336 329 bytes

update

fixed and shorter thanks to webwarrior

def b(a):
 r=''
 while a:
  r+=chr((range(48,58)+range(65,91))[a%36])
  a//=36
 return ''.join(reversed(r or '0'))
u=raw_input()
P=u.split('/')[0].split('.')
s=''
if len(P)>2:
 for p in P[:-2]: s+=p[0]
s+=P[-2][0]+'.'+P[0][1:3]
P=u.split('.')[-1].split('/')[1:]
for p in P: s+='/'+(b(int(p)) if p.isdigit() else p[0])
print s+'/'

original

DenkerAffe's version with some mods : correctly handle "foo/bar?baz" scheme, plus, no need for negative case in the base36 conversion function.

 def b(a):
 r=''
 while a:
  r+=('0123456789ABCDEFGHUKLMNOPQRSTUVWXYZ'[a%36])
  a//=36
 return ''.join(reversed(r or '0'))
u=raw_input()
P=u.split('/')[0].split('.')
s=''
if len(P)>2:
 for p in P[:-2]: s+=p[0]
s+=P[-2][0]+'.'+P[0][1:3]
P=u.split('.')[-1].split('/')[1:]
for p in P: s+='/'+(b(int(p)) if p.isdigit() else p[0])
print s+'/'
\$\endgroup\$
  • \$\begingroup\$ There's error in your lookup string, and also the whole line can be shorter: r+=chr((range(48,58)+range(65,91))[a%36]) \$\endgroup\$ – webwarrior Jan 23 '16 at 22:05

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.