Notes to Tablature

9

Challenge

Given a list a notes, you must return the corresponding tablature.

Notes

The notes must be in the range of A to G inclusive and the octave range being 2 to 6 inclusive. The format is note-octave with # representing a sharp and b representing a flat. E.g: A7 or F#3.

Tabs

Tablature is a method of writing music, by diagrammatically representing the instrument. It is usually represented as five lines with numbers on them.

The numbers that are written on the lines represent the fret used to obtain the desired pitch. For example, the number 3 written on the top line of the staff indicates that the player should press down at the third fret on the high E (first string). Number 0 denotes the nut — that is, an open string.

Fret numbers may not be greater than 22 and the guitar is six string.

The tablature must be in the standard ASCII format. You must not include any technique indicators (hammer on, slide etc.). Separate each note by five dashes. In the case of double digits, reduce the number of dashes to four.

The beginning of the tab should look like this:

e |-----
B |-----
G |-----
D |-----
A |-----
E |-----

And the end should look like:

-----|

for all lines.


(source: justinguitar.com)

Example

Input: C3 C3 D3 E3 F3

Output:

e |-----------------------------------|
B |-----------------------------------|
G |-----------------------------------|
D |-----------------0-----2-----3-----|
A |-----3-----3-----------------------|
E |-----------------------------------|

Winning

The shortest code wins

Beta Decay

Posted 2014-10-13T18:16:35.813

Reputation: 21 478

Do we need to use appropriate strings in our output? What's to stop us from outputting tablature that only uses the E string? – danmcardle – 2014-10-13T18:37:32.607

@crazedgremlin You need to take into account the octaves. Only using the E string means that the note wouldn't be in the appropriate octave. – Beta Decay – 2014-10-13T18:39:48.853

To raise a note by one octave, we could add 12 frets to the fret value. Is there a rule to prevent this that I missed? – danmcardle – 2014-10-13T18:46:37.617

@crazedgremlin You may, but this only provides two octaves. – Beta Decay – 2014-10-13T18:47:58.823

I'm just being pedantic, but you never said I can't have a really long guitar with 1000 frets. – danmcardle – 2014-10-13T18:58:24.957

@crazedgremlin Haha I've edited that in, but I'd love to see a thousand fret guitar :) – Beta Decay – 2014-10-13T19:04:20.620

@steveverrill A double-neck guitar, combining a five string bass and standard tuning 24-fret guitar, could potentially span B0 to E6... – i alarmed alien – 2014-10-14T00:16:55.923

There were no close votes yesterday, when the question was being clarified. Would today's close voters care to explain what the problem is? I'm deleting my clarifications because as far as I am concerned the question is now pretty clear. The only things I can see wrong are that the range of a 22-fret guitar is exactly E2 to D6 (not complete octaves 2 and 6) and the I/O is not defined (I assume commandline,stdin,function argument are all acceptable, as well as stdout or function return.) – Level River St – 2014-10-14T21:13:07.357

Ok, there is another guitar tab question in the Related but it is completely different: it asks for chords, whereas this one asks for melody notes in specific octaves. This is not a duplicate of that one. Speak up before you closevote and these things can be clarified! – Level River St – 2014-10-14T23:14:13.863

I assume we need to use standard tuning? ;) – Valentin Grégoire – 2014-10-15T14:35:02.300

@ValentinGrégoire Yep :) – Beta Decay – 2014-10-15T14:36:04.390

Answers

8

Python 3 – 329 328 319 300

This is my first post on codegolf.se, and probably not nearly optimal; I have read a lot of posts here but did my first code golf ever maybe 50 hours ago. Wanted to try, though!

EDIT: Removed 1 byte, didn't need to output an extra dash there

EDIT 2: Removed 9 bytes, removed some spaces from the note string

EDIT 3: Removed 19 bytes by converting filter() to a generator

a,b='C B#oC#DboD oD#EboE FboF E#oF#GboG oG#AboA oA#BboB Cb',input().split()
for f in range(6):print('eBGDAE'[f]+' |-----'+''.join([((str(d[-1])if f==6-len(d)else'')+'-'*6)[:6]for d in[[c-d+9for d in b"%*/48="if c+9>=d]for c in[12*int(g[-1])+a[:a.index((g[:-1]+' ')[:2])].count('o')for g in b]]])+'|')

A bit ungolfed:

a='C B#oC#DboD oD#EboE FboF E#oF#GboG oG#AboA oA#BboB Cb' # string of notes
b=input().split()                                         # read user input
for f in range(6):                    # loop through the strings

  print('eBGDAE'[f] + ' |-----' +     # string identifier and start of string
  ''.join([                           # join notes of tablature
  ((str(d[-1])                        # highest string the note can be played on
  if f == 6 - len(d)                  # if this is the correct string print the fret
  else '')                            # if not then only dashes
  + '-' * 6)                          # print the dashes after the fret
  [:6]                                # but only until 6 chars per note

  for d in [                          # loop through strings
  [c - d                              # calculate fret number
  + 9                                 # add back the 9 (explained below)
  for d in b"%*/48="                  # string values increased by 9 as ASCII bytes
  if c + 9 >= d]                      # filter to remove too high-pitched strings

  for c in [                          # loop through note values
  12 * int(g[-1]) +                   # octave value
  a[:a.index(                         # part of note string before this note
  (g[:-1] + ' ')[:2])]                # unique note identifier
  .count('o')                         # o's (frets) between C and this note
  for g in b]]])                      # loop through notes

  + '|')                              # end tablature

PurkkaKoodari

Posted 2014-10-13T18:16:35.813

Reputation: 16 699

This is brilliant! :) – Beta Decay – 2014-10-20T16:54:54.243