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 code-golf so shortest code in bytes wins!
-10% Bonus: if your code chains digits
5 Answers 5
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))
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
)
-
1\$\begingroup\$ Using
\wwill fail with digits. Try '09' \$\endgroup\$edc65– edc652015年11月09日 14:35:53 +00:00Commented Nov 9, 2015 at 14:35 -
\$\begingroup\$ Save 1 char using charCodeAt() with no argument \$\endgroup\$edc65– edc652015年11月09日 21:45:12 +00:00Commented 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– edc652015年11月09日 22:26:11 +00:00Commented Nov 9, 2015 at 22:26 -
\$\begingroup\$ codegolf.stackexchange.com/questions/2682/… codegolf.stackexchange.com/questions/37624/… \$\endgroup\$edc65– edc652015年11月09日 22:33:00 +00:00Commented Nov 9, 2015 at 22:33
-
\$\begingroup\$ Thanks for the info! I'm still getting the hang of code golf. :) \$\endgroup\$user81655– user816552015年11月11日 01:25:36 +00:00Commented Nov 11, 2015 at 1:25
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>
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
adBshould transform toabcdCBbecause c is in the middle of d and b. \$\endgroup\$