18
\$\begingroup\$

The zombie apocalypse has come, and the world is coming to an end. Suddenly, someone discovers a formula that takes the current hour, minute, and day, and spits out the perfect note to play on a piano that instantly kills every zombie that hears it. Unfortunately, there is only one piano player left in the world, and he has forgotten how to read notes, but he still knows how to read sheet music. Of course, this is a very time-sensitive thing, so it seems natural to have a computer do it.1

Your challenge is to take a note, such as G, and output the note placed on a staff (in treble clef), like this:

-----

-----
   |
---|-
   |
--O--

-----

Specification:

  • You must output a staff of alternating lines of ----- (5 dashes) and a blank line. There will be 5 -----s total. The note must be superimposed on top of this staff.
  • The input will specify where the note is located. The input will be:
    • an optional H or L, specifying "high" or "low"
    • a letter from A to G, specifying the pitch
    • an optional # or b, specifying sharp or flat.
  • The "note" is defined as:
    • One O (capital O) aligned to the middle of the staff, which is in the place of the note. (The top line is HF (high F), and the bottom line is E (a normal E).)
    • Three |s (vertical bars), the stem, which will be:
      • one space to the left of the note and going downwards (starting one space below the note) if the note is on the middle line (B) or above, or
      • one space to the right of the note and going upwards (starting one space above the note) if the note is below the middle line.
    • A # or b one space directly to the left of the note if specified in the input.
  • Ledger lines must be added if the note is too high or low. These lines will be --- (only 3 dashes in width, as opposed to 5) and will only appear if the note is on or above/below (for top/bottom ledger lines respectively) the ledger lines.
  • Extraneous spaces may be placed anywhere you want; for example, you could make the blank lines have spaces or have a space after the ledger lines if it helps you save any characters.

Here is a visualization, to understand the specification more easily, with all the note names next to the lines:

      HB
 ---  HA
      HG
----- HF
      HE
----- HD
      HC
----- B
      A
----- G
      F
----- E
      D
 ---  C
      LB
 ---  LA
      LG
 ---  LF
... (bottom cut off for brevity, you get the idea anyway)

Here are some more examples that you can use to test your program:

Input: HG#

 #O
-|---
 |
-|---

-----

-----

-----

Input: LAb

-----

-----

-----

-----

-----
   |
 --|
   |
 bO-

Input: HB

  O
 |--
 |
-|---

-----

-----

-----

-----

Input: C

-----

-----

-----

-----
   |
---|-
   |
 -O-

This is , so the shortest code in bytes will win!

1: most realistic exposition evar! :-P

\$\endgroup\$
15
  • 2
    \$\begingroup\$ It looks very strange to have # or b at the right of the note rather than at the left; is it really what is required? \$\endgroup\$ Commented Mar 23, 2014 at 21:16
  • 2
    \$\begingroup\$ What about B# and the like? 1. plot as-is; 2. reject; 3. silently convert to C? \$\endgroup\$ Commented Mar 23, 2014 at 22:42
  • 2
    \$\begingroup\$ It may be better to explicitly state that it should be in treble clef. \$\endgroup\$
    – user12205
    Commented Mar 24, 2014 at 3:10
  • 3
    \$\begingroup\$ Anyone up to attempting this in Fugue? \$\endgroup\$ Commented Mar 25, 2014 at 16:18
  • 3
    \$\begingroup\$ @AJM Yes, it has to be ASCII art. \$\endgroup\$
    – Doorknob
    Commented Mar 25, 2014 at 17:02

10 Answers 10

6
\$\begingroup\$

Ruby – 271 267 252 249 234 229 220 214 characters

I literally just learned Ruby for this. So there is certainly room for improvement in golfing it down. Or doing anything really. But I needed a language with mutable strings. :)

def f(n)s=[0]*20
s.fill{|i|i%2>0?i<3||i>11?" ---":?-*5:" "*5}
s[l=(3-n[(p="H_L".index n[0])?1:0].ord)%7+7*(p||1)][1,2]=("#b"[n[-1]]||s[l][1])+?O
s[l+3-2*o=l>7?3:1,3].map{|t|t[o]=?|}
puts s[[3,l].min..[11,l].max]end

Somewhat ungolfed:

def f(note)
  staff=[]
  0.step(20) {|i| staff[i] = " "*5}
  1.step(19,2) {|i| staff[i] = " ---"}
  3.step(11,2) {|i| staff[i] = "-"*5}
  level = 7
  if !(pos="HL".index note[i=0]).nil?
    level = 14*pos
    i += 1
  end
  level += (73-note[i].ord)%7
  staff[level][2] = "O"
  mark = note[-1]
  if !"#b".index(mark).nil?
    staff[level][1] = mark
  end
  offset = (level > 7) ? 3 : 1
  staff[level-2*offset+3,3].map {|line| line[offset] = "|"}
  first = [3,level].min
  last = [11,level].max
  puts s[first..last]
end

I can cut it by another 2 characters down to 212 characters if leading blank lines are allowed. This solution doesn't fill the lines that aren't printed anyway:

def f(n)s=[]
[3,l=(3-n[(p="H_L".index n[0])?1:0].ord)%7+7*(p||1)].min.step(l>11?l:11){|i|s[i]=i%2>0?i<3||i>11?" ---":?-*5:" "*5}
s[l][1,2]=("#b"[n[-1]]||s[l][1])+?O
s[l+3-2*o=l>7?3:1,3].map{|t|t[o]=?|}
puts s
end

Are lambda's fair game? Then I can get 210 characters with the first approach

f=->n{s=[0]*20
s.fill{|i|i%2>0?i<3||i>11?" ---":?-*5:" "*5}
s[l=(3-n[(p="H_L".index n[0])?1:0].ord)%7+7*(p||1)][1,2]=("#b"[n[-1]]||s[l][1])+?O
s[l+3-2*o=l>7?3:1,3].map{|t|t[o]=?|}
puts s[[3,l].min..[11,l].max]}

Or 207 characters with additional blank lines:

f=->n{s=[]
[3,l=(3-n[(p="H_L".index n[0])?1:0].ord)%7+7*(p||1)].min.step(l>11?l:11){|i|s[i]=i%2>0?i<3||i>11?" ---":?-*5:" "*5}
s[l][1,2]=("#b"[n[-1]]||s[l][1])+?O
s[l+3-2*o=l>7?3:1,3].map{|t|t[o]=?|}
puts s}

Of course, now you'd need to do f.call("HGb").

\$\endgroup\$
8
  • \$\begingroup\$ Ha, +1 for learning an entirely new language! ;-) Here's a tip: !x.nil? is equivalent to !x. And for one line ifs, if x;y;end; is equivalent to y if x. Also you can use a literal newline in that string. \$\endgroup\$
    – Doorknob
    Commented Mar 25, 2014 at 1:13
  • \$\begingroup\$ @Doorknob thanks, I'll try to work those in! \$\endgroup\$ Commented Mar 25, 2014 at 1:16
  • \$\begingroup\$ @Doorknob hm, I only got the if to work. If I use ?\n (if that's what you meant) I need to add a space, so I gain nothing. And removing the .nil?s didn't work at all (always evaluated to true). \$\endgroup\$ Commented Mar 25, 2014 at 1:28
  • \$\begingroup\$ I meant literally adding a newline between the two quotes. And I think you need extra parens when removing .nil?, but it's worth it in characters. \$\endgroup\$
    – Doorknob
    Commented Mar 25, 2014 at 1:29
  • \$\begingroup\$ @Doorknob ah, no !x.nil? is !!x. :) \$\endgroup\$ Commented Mar 25, 2014 at 1:36
2
\$\begingroup\$

Python, 329 309 295 286 280 277 characters

Golfed a bit more now. Still can be improved, but not sure if I can beat out the ruby or golfscript solutions with this approach.

R=range
N='J'+raw_input()+' '
X=N[1]>'G'
a,b,c=N[X:3+X]
z=266-ord(a)/2*7+(ord(b)-4)%7
Z=[list((' '*5,(' ---','-'*5)[8<r<18])[r%2])for r in R(21)]
Z[z][2]='o'
if' '<c:Z[z][1]=c
Q=(z<13)*2
for i in(1,2,3):Z[z+i*Q-i][Q+1]='|'
for r in R(max(17,z),min(z-1,8),-1):print''.join(Z[r])

Initially I was printing out line-by-line, but it turned out to take too much, so I generate a string grid and then fill in what needs be filled in. Input is from command line, e.g.:

>echo HG# | python note2_golf.py
 #o
-|---
 |
-|---

-----

-----

-----
\$\endgroup\$
2
  • \$\begingroup\$ In line 5 you can remove the space before the second comma \$\endgroup\$
    – user12205
    Commented Mar 24, 2014 at 6:47
  • \$\begingroup\$ @ace: Thanks, missed that one \$\endgroup\$
    – Claudiu
    Commented Mar 24, 2014 at 6:52
2
\$\begingroup\$

GolfScript - 243 232 228 227 characters

I translated my CoffeeScript answer into GolfScript, which is much more suited to the string manipulations.

EDIT: Saved six characters by properly using the increment operator, three by making good use of the stack, six more by irresponsibly redefining operators I'm not using, and one more by not printing the trailing space after grace lines.

Entirely golfed:

..0="HL"?2+3%:o)2%.@="CDEFGAB"?7o*+:`2%45 32if:r;
).2$,<{=}{;;r}if:&;
[" "5*:|" ---":g]4*[|"-"5*]5*+[|g|]+.
[`<~]\[`>([0=:^&79r^]''+\~]
+17`<`)18if<9`>`9if:j>:t 13`>.2*):x;
4,1>{`j-\2${+}{-}if}%\;
{.@<\t>(:v[x<'|'+x)v>+]\++:t}
/-1%n*

With comments:

# extract octave
..0="HL"?2+3%:o

# extract note
2%1\-.@="CDEFGAB"?7o*+:k

# line spacer
2%45 32if:r;

# extract accidental
1+.2$,<{=}{;;r}if:a;

# staff
[" "5*:|" --- ":g]4*[|"-"5*]5*+[|g|]+.

# lines below
[k<~]\

# note line and above
[k>([0=:w a 79r w]''+\~]+

# cut off just what we need
17k<1k+18if<
9k>k 9if:j>:t;

# and the note stem
13k>.2*1+:x;4,1>{k j-\2${+}{-}if}%\;

{
  .t<\
  t>(:v[x<'|'+1x+v>+]\++:t;
}/

# now output the note
t-1%n*
\$\endgroup\$
3
  • \$\begingroup\$ I would have been astonished if I could beat a GolfScript solution in a language that I have no experience in ;) \$\endgroup\$ Commented Mar 25, 2014 at 14:07
  • 1
    \$\begingroup\$ I'm no GolfScript expert but I think I've eked out just about all the characters I'm going to get out of this, so if you can find another two, you're golden! \$\endgroup\$
    – couchand
    Commented Mar 25, 2014 at 14:09
  • \$\begingroup\$ Try to type Go in it. it will output oo||| :) \$\endgroup\$
    – Jamie
    Commented Apr 26, 2014 at 9:17
1
\$\begingroup\$

Golfscript, 211 210 209 197 195 192 characters

Coming in for the (as of this post) win, a GolfScript version of my latest Python version:

"J"\+[0]+.1=71>>3<{}/@7*2/246-@3+7%-:z;:c;21,{..3z<3z
if<\11z>11z
if>|{;}{...2>\12<&\2%.{'-'' 'if}:Q~:9;&Q\.z={c!9{[c]''+}if}{..z>\4z+<&8z>&'|'9if}if\.z='o'9if\..z
4-\<\z<&7z<&'|'9if\;3$n}if}/

Test it out here (first 2 lines are user-input, normally it comes from stdin).

'Readable' version:

;"HCb"

"J"\+[0]+       #process input
.1=71>>3<       #first char is HJL, second is letter, third is #b or space
{}/             #spill chars onto stack, now we working with ints
@7*2/246-@3+7%- #convert HC/JD/LE etc to a number from 0 to 20
:z;:c;
21,{            #for r in range(21):
  ..3z<3z if<           #either out-of-bounds or process the line
  \11z>11z if>|
  {;}{
    ...2>\12<&\2%.{'-'' 'if}:Q~:9;&Q\        #1st char
    .z={c!9{[c]''+}if}                       #2nd char accidental
       {..z>\4z+<&8z>&'|'9if}if\            #2nd char stem or row
    .z='o'9if\                              #3rd char
    ..z 4-\<\z<&7z<&'|'9if\                 #4th char stem or row
    ;3$                                      #5th char=1st char
    n
  }if
}/
\$\endgroup\$
7
  • \$\begingroup\$ Aaaaaaand beaten by GolfScript again. :) ... \$\endgroup\$ Commented Mar 25, 2014 at 21:47
  • \$\begingroup\$ @m.buettner: Haha, it never ends.. surprisingly close though! \$\endgroup\$
    – Claudiu
    Commented Mar 25, 2014 at 21:49
  • 1
    \$\begingroup\$ Better! Now I only need to find 6/9 bytes to catch up :D (although I don't see how I would do that) \$\endgroup\$ Commented Mar 25, 2014 at 21:56
  • \$\begingroup\$ @m.buettner: Got 2 more bytes down! Each one is so brutal though... I might have to stop for now. Good luck! \$\endgroup\$
    – Claudiu
    Commented Mar 25, 2014 at 22:20
  • 2
    \$\begingroup\$ Oh bloody hell... just when I thought I had beaten your 209. I think I'm giving up. GolfScript prevails. ;) \$\endgroup\$ Commented Mar 25, 2014 at 23:41
1
\$\begingroup\$

Python, 250 245 242 235 characters

A very different approach which ended up beating out my other one! Input processing code is similar but that's about it.

M=' -'
N=raw_input()+M
a,b,c=('J'+N)[N>'G':][:3]
z=ord(a)*7/2-246-(ord(b)+3)%7
for r in range(21):
 L=M[r%2];F=M[2<r<12and r%2]
 if min(3,z)<=r<=max(11,z):print F+((L,'|')[8>z<r<z+4],(L,c)[M<c])[r==z]+(L,'o')[r==z]+(L,'|')[z-4<r<z>7]+F

I mapped out each character's value based on the row and column and then golfed the printing:

#given row r, with note on row n, how to print each char?
#rows are:
#       HB : 0
#  ---  HA : 1
#       HG : 2
# ----- HF : 3
#       HE : 4
# ----- HD : 5
#       HC : 6
# ----- B  : 7
#       A  : 8
# ----- G  : 9
#       F  : 10
# ----- E  : 11
#       D  : 12
#  ---  C  : 13
#       LB : 14
#  ---  LA : 15
#       LG : 16
#  ---  LF : 17
#       LE : 18
#  ---  LD : 19
#       LC : 20
#chars are:
# 0 | 1 | 2 | 3 | 4
#
# 0,4:
#    if r%2:
#      if 2<r<12: '-'
#      else ' '
#    else: ' '
# 1: ' -b#|'
#    if r==n:
#      if A: c
#      else: ' -'[r%2]
#    elif n<8 and n<r<n+4: '|'
#    else: ' -'[r%2]
# 2: ' -o'
#    if r==n: 'o'
#    else: ' -'[r%2]
# 3: ' -|'
#    if n>7 and n-4<r<n: '|'
#    else: ' -'[r%2]
\$\endgroup\$
1
  • \$\begingroup\$ +1, Last line seems more Perl's black magic than Pythonic stuff \$\endgroup\$ Commented Mar 26, 2014 at 13:14
1
\$\begingroup\$

Java - 921 907 863 characters

I build up each string seperately, storing each string in an array. Then loop through the array and print out each line.

public class D{public static void main(String[]a){char[]z=a[0].toCharArray();char[]y=new char[3];y[0]=('H'==z[0]||'L'==z[0])?z[0]:'N';int o=(y[0]=='N')?0:1;y[1]=z[o++];y[2]=z.length>o?z[o]:'!';int n=y[1]<'C'?((int)(y[1]-'A'))+6:((int)(y[1]-'C'))+1;n=(y[0]=='N')?n+7:(y[0]=='H'?n+14:n);String s="     ";String b=" --- ";String[]u=new String[22];for(int i=1;i<=21;i+=2){u[i]=s;}for(int i=10;i<=18;i+=2){u[i]="-----";}u[20]=n>19?b:s;u[2]=n<3?b:s;u[4]=n<5?b:s;u[6]=n<7?b:s;u[8]=n<9?b:s;char c=u[n].charAt(0);char e=u[n].charAt(1);char[]h=new char[]{c,y[2]=='!'?e:y[2],'O',e,c};u[n]=new String(h);for(int i=0;i<22;i++){if(n<14&&i-n<4&&i>n)u[i]=u[i]!=null?u[i].substring(0,3)+"|"+u[i].charAt(4):s;else if(n>13&&n-i<4&&n>i)u[i]=u[i]!=null?u[i].substring(0,3)+"|"+u[i].charAt(4):s;}for(int i=21;i>=0;i--)if(!(i>n&&i>18||i<n&&i<10))System.u.println((u[i]==null)?s:u[i]);}}

Oh please don't hate me, it's my first time. I coulnd't find any faq/introduction so I hope my posting format is ok. Not sure how serious people got about character counts.... normal version of the code - extra is linebreak/spaces (1313 characters):

public class DisplayNote
{
  public static void main(String[] args)
  {
    char[] z=args[0].toCharArray();
    char[] y=new char[3];
    y[0]=('H'==z[0]||'L'==z[0])?z[0]:'N';
    int o=(y[0]=='N')?0:1;
    y[1]=z[o++];
    y[2]=z.length>o?z[o]:'!';

    int noteValue=y[1]<'C'?((int) (y[1] - 'A')) + 6:((int) (y[1] - 'C')) + 1;
    noteValue=(y[0]=='N')?noteValue+7:(y[0]=='H'?noteValue+14:noteValue);
    String s="     ";
    String b=" --- ";
    String[] out=new String[22];
    for (int i=1;i<=21;i+=2){out[i]=s;}
    for (int i=10;i<=18;i+=2){out[i]="-----";}
    out[20]=noteValue>19?b:s;
    out[2]=noteValue<3?b:s;
    out[4]=noteValue<5?b:s;
    out[6]=noteValue<7?b:s;
    out[8]=noteValue<9?b:s;

    char c=out[noteValue].charAt(0);
    char e=out[noteValue].charAt(1);
    char[] h=new char[]{c,y[2]=='!'?e:y[2],'O',e,c};
    out[noteValue]=new String(h);
    for (int i=0;i<22;i++)
    {
      if (noteValue<14&&i-noteValue<4&&i>noteValue)
        out[i]=out[i]!=null?out[i].substring(0,3)+"|"+out[i].charAt(4):s;
      else if (noteValue>13&&noteValue-i<4&&noteValue>i)
        out[i]=out[i]!=null?out[i].substring(0,3)+"|"+out[i].charAt(4):s;        
    }

    for (int i=21;i>=0;i--)
      if (!(i>noteValue&&i>18||i<noteValue&&i<10))
        System.out.println((out[i]==null)?s:out[i]);
  }
}
\$\endgroup\$
6
  • \$\begingroup\$ I see tons of unnecessary whitespace (especially after semicolons and around operators and brackets and parens) and long variable names (like args). \$\endgroup\$
    – Doorknob
    Commented Mar 24, 2014 at 23:42
  • \$\begingroup\$ In the character counting submission: 921 characters, all whitespace is gone :P \$\endgroup\$
    – Will_61
    Commented Mar 24, 2014 at 23:43
  • \$\begingroup\$ The second submission with whitespace everywhere is to let people read the code, as I said it's my first time so not sure if we're meant to leave 1 submission and 1 where you try to reduce the character limit... or what? \$\endgroup\$
    – Will_61
    Commented Mar 24, 2014 at 23:44
  • \$\begingroup\$ No; I see an enormous amount of useless whitespace in that version. For example, spaces after semicolons, spaces around operators, spaces after [], spaces around parentheses, etc. \$\endgroup\$
    – Doorknob
    Commented Mar 24, 2014 at 23:44
  • \$\begingroup\$ Removed them all now (I think) Thanks :) \$\endgroup\$
    – Will_61
    Commented Mar 24, 2014 at 23:57
1
\$\begingroup\$

Haskell 377C

import Data.Char
(<.)=elem
n(c:r)|elem c"HL"=let(s,a)=n r in(s+case c of 'H'->7;_-> -7,a)|1<2=(mod(ord c-67)7-2,case r of[]->' ';[x]->x)
r(s,a)y x=c where d|s>4= -1|1<2=1;c|x<.[0,4]&&(y<0||y>8)=' '|x==2&&y==s='o'|y==s&&x==1&&' '/=a=a|x==2+d&&y<.[s+k*d|k<-[1..3]]='|'|1<2="- "!!mod y 2
g p@(s,a)=unlines$[map(r p y)[0..4]|y<-reverse[min 0 s..max 8 s]]
main=getLine>>=putStr.g.n

Ungolfed version:

import Data.Char

fromName ('H':s) = let (step, alter) = fromName s in ((step + 7), alter)
fromName ('L':s) = let (step, alter) = fromName s in ((step - 7), alter)
fromName (x:s) = (mod (ord x - 67) 7 - 2, if null s then ' ' else head s)

renderChar :: (Int, Char) -> Int -> Int -> Char
renderChar (step, alter) y x = let
    dir = if step >  4 then -1 else 1
    normal = "- "!!mod y 2
    stemYs = [step + k * dir | k <- [1..3]]
    c | elem x [0,4] && not(elem y [0,2,4,6,8]) = ' '
      | x == 2 && y == step = 'o'
      | y == step && x == 1 && alter /= ' ' = alter
      | elem y stemYs && x == 2 + dir = '|'
      | otherwise = normal
  in c

render :: (Int, Char)-> String
render (step, alter) = unlines [map (renderChar (step, alter) y) [0..4] | y <- ys] 
  where
    ys = reverse [min 0 step .. max 8 step]

main = getLine >>= (putStr.render.fromName)
\$\endgroup\$
0
\$\begingroup\$

Literate CoffeeScript - 497 527 characters

I'm sure there's a better way to build the grid but I can't figure it out.

One golf helper.

_=(q)->->q.split ""

A C major scale and staff.

s=_("CDEFGAB")()
l=_ "-----"
e=_ "     "
g=_ " --- "
t=->
  o=[e(),l(),e(),l(),e(),l(),e(),l(),e(),l(),e(),g(),e()]
  o.unshift e(),g() for [0..3]
  o

Our notation function will take the string representation of a note.

f=(i)->
  o=1
  m=t()

First we'll determine the octave.

  if /L|H/.test i[0]
    if i[0]=="L" then o=0 else o=2
    i=i[1..]

Then the note and accidental. Gotta love deconstructing assignment.

  [n,a]=i

Let's convert the note and octave to an index and plot the note.

  x=7*o+s.indexOf n

  m[x][1]=a if a
  m[x][2]='O'

Now we'll cut out only as much staff as we need.

  j=9
  k=17
  if x>17
    k=x
  else if x<9
    j=x
  u=x-j
  m=m[j..k]

And the note stem.

  if x<13
    m[x][3]='|' for x in [u+3...u]
  else
    m[x][1]='|' for x in [u-3...u]

Now let's output the results.

  m.map((p)->p.join '').reverse().join '\n'

Finally, we'll export the function for console testing. These characters don't count towards the total.

module.exports = f
\$\endgroup\$
2
  • \$\begingroup\$ Looking closer it seems like I screwed up when refactoring the note stem, so it produces illegal output at the moment. \$\endgroup\$
    – couchand
    Commented Mar 25, 2014 at 1:53
  • \$\begingroup\$ I fixed it, but it added 30 characters :-/ \$\endgroup\$
    – couchand
    Commented Mar 25, 2014 at 5:00
0
\$\begingroup\$

C, 325 304

Now 21 bytes shorter thanks to @ace!

i;j;c;n;main(t){char
x[133];for(i;i<132;i++){x[i]="-----\n     \n"[i%12];if((i<18||i>77)&&!((i%12)&11))x[i]=32;}for(;!n;){c=getchar();if(c>71)t=c^72?2:0;else
n=7*t+7-(c-4)%7;}x[i=n*6+2]=79;if((c=getchar())>32)x[i-1]=c;for(t=0,j=n<9?i+5:i-17;t<3;t++,j+=6)x[j]='|';x[n<13?77:n*6+5]=0;puts(x+(n>4?24:n*6));}

Output:

./a.out
HBb
 bO  
 |-- 
 |   
-|---

-----

-----

-----

-----


./a.out
LG#
-----

-----

-----

-----

-----

 --| 
   | 
 --| 
 #O  
\$\endgroup\$
3
  • \$\begingroup\$ Global variable are initialised to zero by default, so you don't need to initialise n and you can remove the i=0 in the first for loop. \$\endgroup\$
    – user12205
    Commented Mar 25, 2014 at 3:23
  • \$\begingroup\$ Also, in the first if statement, ((i%12)&11)==0 can be replaced with !((i%12)&11). \$\endgroup\$
    – user12205
    Commented Mar 25, 2014 at 3:26
  • \$\begingroup\$ Finally, ?: has a very lower precedence than ^ and <, so you can remove the brackets of the conditions before the ?. And you can replace printf("%s", with puts(. \$\endgroup\$
    – user12205
    Commented Mar 25, 2014 at 3:38
0
\$\begingroup\$

JavaScript 390 388

A bit of a challenge, I'll have to admit... I'm sure there's ways of reducing this further... I'm open to suggestions...

First Iteration

C=(a,x,o,c)=>{a[x]=a[x].substr(0,o)+c+a[x].substr(o+1)};l=7;s=[];for(i=21;i--;)s[i]="    ";for(j=1;19>j;j+=2)s[j]=" ---";for(k=3;12>k;k+=2)s[k]="-----";~(p="HL".indexOf((n=prompt())[i=0]))&&(l=14*p,i++);l+=(73-n.charCodeAt(i))%7;C(s,l,2,"O");m=n[n.length-1];"#"!=m&   "b"!=m||C(s,l,1,m);o=7<l?3:1;for(z=0;3>z;C(s,t=l-2*o+3+z++,o,"|"));S=s.splice(3<=l?3:l,11>=l?11:l);console.log(S.join("\n"))

Second Iteration (using n.slice(-1) instead of n[n.length-1]), shaves 2 bytes

C=(a,x,o,c)=>{a[x]=a[x].substr(0,o)+c+a[x].substr(o+1)};l=7;s=[];for(i=21;i--;)s[i]="    ";for(j=1;19>j;j+=2)s[j]=" ---";for(k=3;12>k;k+=2)s[k]="-----";~(p="HL".indexOf((n=prompt())[i=0]))&&(l=14*p,i++);l+=(73-n.charCodeAt(i))%7;C(s,l,2,"O");m=n.slice(-1);"#"!=m& "b"!=m||C(s,l,1,m);o=7<l?3:1;for(z=0;3>z;C(s,t=l-2*o+3+z++,o,"|"));S=s.splice(3<=l?3:l,11>=l?11:l);console.log(S.join("\n"))

Ungolfed version:

function C(a,x,o,c){
    a[x]=a[x].substr(0,o)+c+a[x].substr(o+1);
}
l=7;s=[];
for(i=21;i--;){
    s[i]="    ";
}
for(j=1;19>j;j+=2){
    s[j]=" ---";
}
for(k=3;12>k;k+=2){
    s[k]="-----";
}
i=0;n=prompt();
p="HL".indexOf(n[i]);
if(p>=0){
    l=14*p;i++;
}
l+=(73-n.charCodeAt(i))%7;
C(s,l,2,"O");
m=n.slice(-1);
if((m=="#")||m=="b"){
    C(s,l,1,m);
}
o=7<l?3:1;
for(z=0;3>z;z++){
    C(s,t=l-2*o+3+z,o,"|");
}
F=Math.min(3,l);
L=Math.max(11,l);
S=s.splice(F,L);
console.log(S.join("\n"));
\$\endgroup\$
2
  • \$\begingroup\$ Could you add an ungolfed (readable) version, please? \$\endgroup\$ Commented Mar 27, 2014 at 11:34
  • \$\begingroup\$ @m.buettner Done... I hope it helps give you a better understanding of what I've done :) \$\endgroup\$ Commented Mar 27, 2014 at 12:38

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.