9
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ Do we need to use appropriate strings in our output? What's to stop us from outputting tablature that only uses the E string? \$\endgroup\$ – danmcardle Oct 13 '14 at 18:37
  • \$\begingroup\$ @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. \$\endgroup\$ – Beta Decay Oct 13 '14 at 18:39
  • \$\begingroup\$ 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? \$\endgroup\$ – danmcardle Oct 13 '14 at 18:46
  • \$\begingroup\$ @crazedgremlin You may, but this only provides two octaves. \$\endgroup\$ – Beta Decay Oct 13 '14 at 18:47
  • \$\begingroup\$ I'm just being pedantic, but you never said I can't have a really long guitar with 1000 frets. \$\endgroup\$ – danmcardle Oct 13 '14 at 18:58
8
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ This is brilliant! :) \$\endgroup\$ – Beta Decay Oct 20 '14 at 16:54

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.