13
\$\begingroup\$

Across the alphabet

In this challenge, you have trouble remembering the letters of the alphabet. To circumvent this, you go up and down the alphabet, till you get to the letter.

Because you want your code to be portable, you'll be writing it with letter blocks. You have a limited amount of letter blocks because most of them got stolen so you need to make sure your code is as short as possible.

Examples

Input / Output pairs are separated by a blank line:

Ac
ABc

Ad
ABcd

fA
fedCBA

adB
abcdcB


Hello, World!
HGfefghijkllmno, WVUTSrqpopqrqponmlkjihgfed!

Challenge

Your goal is to chain adjacent letters with all the intermediate letters of the alphabet (A-Za-z) between them. If capitalization differs, the capitalization should be transformed in the middle. If capitalization cannot be evenly transformed in the middle, it broken up after the middle. If a character isn't an alphabetical character, no transformation should be done.

Winning

This is so shortest code in bytes wins!

-10% Bonus: if your code chains digits

\$\endgroup\$
17
  • 1
    \$\begingroup\$ What do you mean by letter blocks? \$\endgroup\$ Commented Nov 7, 2015 at 21:38
  • \$\begingroup\$ @LegionMammal978 Letter blocks. Not really relevant to the challenge, just a random reason I came up with for short code \$\endgroup\$
    – Downgoat
    Commented Nov 7, 2015 at 21:40
  • \$\begingroup\$ Okay, just wondering if you meant restricted-source. \$\endgroup\$ Commented Nov 7, 2015 at 21:41
  • \$\begingroup\$ By your rules, dont you think adB should transform to abcdCB because c is in the middle of d and b. \$\endgroup\$
    – geokavel
    Commented Nov 7, 2015 at 22:02
  • \$\begingroup\$ Pretty similar to my Alphabet Between Encryption, but this already has twice the votes so I'll just flag mine. \$\endgroup\$
    – jado
    Commented Nov 9, 2015 at 7:38

5 Answers 5

4
+100
\$\begingroup\$

Pyth, 40 bytes

+sm?-rdZGhd+hdsrVc2jktr.*rdZm!}kGd.:z2ez

Try it online.

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

Python 2, 303 291 288 282 276 261 253 bytes

This is a completely different algorithm than Hannes Karppila's, and after lots of golfing, I've managed a substantial improvement in length. I think this algorithm might allow for one of the shortest codes in other languages too, especially languages with do-while loops and built-in signum functions. Suggestions for further improvement welcome. (Something tells me that whole inner loop should be rewritten as a list comprehension.)

l=map(ord,list(raw_input()));f=q=1
while q:
 q=0;m=~-f/2;c=m
 while abs(c)<len(l)-1:
  u=c+f;d=(l[u]-96)%32-(l[c]-96)%32
  if chr(l[c]).isalpha()*chr(l[u]).isalpha()*(d*d>1):l[:u-m]+=[l[c]+d/abs(d)];u+=f;q=1
  c=u
 f=-f
print "".join(map(chr,l))
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 198 197 194 bytes

f=s=>(o="",a=u=0,[...s].map(c=>{j=c.toUpperCase();p=j==c;b=j<"A"|j>"Z"?0:j.charCodeAt();for(i=0,m=a<b?b-a:a-b;a&&b&&++i<m;)o+=String.fromCharCode(i*(a<b||-1)+a+32*!(i>m/2?p:u));a=b;u=p;o+=c}),o)

Usage

f("Hello, World!")
=> "HGfefghijkllmno, WVUTSrqpopqrqponmlkjihgfed!"

Explanation

f=s=>(
  o="",                                   // o = output string
  a=                                      // a = previous character code (or 0 if symbol)
    u=0,                                  // u = 1 if previous character was upper-case
  [...s].map(c=>{                         // iterate through each letter of input

    // Get information about the current character
    j=c.toUpperCase();                    // j = current character in upper-case
    p=j==c;                               // p = current character is upper-case
    b=j<"A"|j>"Z"?0:j.charCodeAt();       // b = current character code (or 0 if symbol)

    // Interpolate characters (unless A or B is a symbol)
    for(i=0,m=a<b?b-a:a-b;a&&b&&++i<m;)   // loop for each character between A and B
      o+=String.fromCharCode(             // add interpolated character to output
        i*(a<b||-1)+a+                    // interpolate character code
          32*!(i>m/2?p:u)                 // apply case of the nearest character
      );

    // Set character A values to B for the next character
    a=b;
    u=p;
    o+=c                                  // add B itself to the output

  }),
  o                                       // return the output
)
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Using \w will fail with digits. Try '09' \$\endgroup\$
    – edc65
    Commented Nov 9, 2015 at 14:35
  • \$\begingroup\$ Save 1 char using charCodeAt() with no argument \$\endgroup\$
    – edc65
    Commented Nov 9, 2015 at 21:45
  • \$\begingroup\$ And save 2 chars avoiding Math.abs a>b?a-b:b-a ... and there are more other 'standard' tricks to shorten javascript. With your interpolation method you could beat my score. Check the hints in this site \$\endgroup\$
    – edc65
    Commented Nov 9, 2015 at 22:26
  • \$\begingroup\$ codegolf.stackexchange.com/questions/2682/… codegolf.stackexchange.com/questions/37624/… \$\endgroup\$
    – edc65
    Commented Nov 9, 2015 at 22:33
  • \$\begingroup\$ Thanks for the info! I'm still getting the hang of code golf. :) \$\endgroup\$
    – user81655
    Commented Nov 11, 2015 at 1:25
1
\$\begingroup\$

JavaScript ES6, 168 (186-10%) 176 193

Edit Modified to get the 10% bonus

Test running the snippet below using an EcmaScript 6 compliant browser (I use FireFox)

f=s=>[...s].map(c=>{a=parseInt(c,36),m=(a-q)/(d=a>q?1:-1);for(n=1;m&&(a>9)==(q>9)&&(q+=d)!=a;n+=2)r=q.toString(36),o+=n<m&p<'a'|n>=m&c<'a'?r.toUpperCase():r;p=c,q=a,o+=c},o='',p=q=-f)&&o

// Explained
U=s=>(
  o = '', // initialize output
  p = '', // provious char, initialize to none
  q = NaN, // previous char code, initialize to none
  [...s].map( c => { // for each char 
    a = parseInt(c,36), // convert digit/letter to numeric code, case invariant, NaN if invalid
    d = a > q ? 1 : -1, // sign of difference (if not equal)
    m = (a - q) / d; // absolute value of difference or NaN 
    if (m && (a>9)==(q>9)) // if current and prev are different and both alpha or both digits  
      for( n = 1; 
          (q += d) != a; // loop from prev char (not included) to current (not included)
           n += 2)
        r=q.toString(36),
        // add intermediate char to output
        // upcase if: left side & prev is upcase or right side and current is upcase
        o+= n<m&p<'a'|n>=m&c<'a'?r.toUpperCase():r;
    p = c, // copy current to previous
    q = a, // copy current to previous
    o += c // add current char to ouput
  }),
  o
)  

// test
console.log=(...x)=>O.innerHTML+=x+'\n'

;['Ac','Ad','fA','adB','04aQ27','Hello World!'].
forEach(x=>console.log(x + ' -> ' + f(x)))
<pre id=O></pre>

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

Python 2, 349 bytes

It's way too long, but at least it's first.

f=lambda p:ord(p.lower())
u=lambda p:"".join(p).upper()
s=raw_input()
w=s[0]
r=w
for q in s[1:]:
 o=q+w
 if q==w:o=""
 if o.isalpha():
  m=(f(w)<f(q))*2-1
  e=map(chr,range(f(w)+m,f(q)+m,m))
  if o==u(o):e=u(e)
  elif q==u(q):e[len(e)/2:]=u(e[len(e)/2:])
  elif -o.islower()+1:e[:len(e)/2]=u(e[:len(e)/2])
  r+="".join(e)
 else:
  r+=q
 w=q
print r
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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