Membuat tab gitar?

24

Tulis program terpendek yang menghasilkan tab gitar untuk akord yang diberikan sebagai input.

Agar gitaris di antara Anda tidak memiliki keunggulan, dan untuk membuatnya deterministik (dan mungkin lebih mudah untuk dikodekan), berikut adalah satu - satunya bentuk akord yang diotorisasi:

Major chords:

  E   F   F#  G   G#  A   A#  B   C   C#  D   D#
e 0---1---2---3---4---0---1---2---3---4---5---6---
B 0---1---2---3---4---2---3---4---5---6---7---8---
G 1---2---3---4---5---2---3---4---5---6---7---8---
D 2---3---4---5---6---2---3---4---5---6---7---8---
A 2---3---4---5---6---0---1---2---3---4---5---6---
E 0---1---2---3---4---0---1---2---3---4---5---6---

Minor chords:

  Em  Fm  F#m Gm  G#m Am  A#m Bm  Cm  C#m Dm  D#m
e 0---1---2---3---4---0---1---2---3---4---5---6---
B 0---1---2---3---4---1---2---3---4---5---6---7---
G 0---1---2---3---4---2---3---4---5---6---7---8---
D 2---3---4---5---6---2---3---4---5---6---7---8---
A 2---3---4---5---6---0---1---2---3---4---5---6---
E 0---1---2---3---4---0---1---2---3---4---5---6---

Perhatikan bahwa 5 akord pertama dan 7 akord terakhir dari setiap seri memiliki bentuk yang berbeda.

Semua akor adalah akord mayor atau minor sederhana (tidak ada 7 atau variasi lainnya).

Anda harus merawat flat juga. Peringatan:

A# = Bb
C# = Db
D# = Eb
F# = Gb
G# = Ab

B#, Cb, E# and Fb are not used

Keluaran harus menyertakan kolom pertama dengan nama kabel, seperti yang ditunjukkan di atas. Itu tidak harus menyertakan nama chord di atas. Akord harus dipisahkan oleh 3 -seperti yang ditunjukkan di atas. 3 final -adalah opsional.

Input adalah string yang terdiri dari nama akor, dipisahkan oleh spasi.

Contoh input adalah:

Bm Gb A E G D Em F#

dan output yang sesuai adalah:

e 2---2---0---0---3---5---0---2---
B 3---2---2---0---3---7---0---2---
G 4---3---2---1---4---7---0---3---
D 4---4---2---2---5---7---2---4---
A 2---4---0---2---5---5---2---4---
E 2---2---0---0---3---5---0---2---
Jules Olléon
sumber
... dan pertanyaan sampingan: apa contoh lagunya? :)
Jules Olléon
5
Hotel California: P
Matthew Baca
Yap, kamu menang! :)
Jules Olléon
Ide keren Seandainya aku punya waktu untuk bermain!
Igby Largeman

Jawaban:

9

JavaScript, 297 277 262 235 223 karakter

Tidak ada carriage return dalam versi golf yang signifikan; mereka ada hanya untuk membuat jawaban itu bisa dibaca. Titik koma adalah signifikan.

Sunting: Mengganti bagian luar mapdengan loop sementara dan suntingan lainnya. Akhirnya dalam 2 × ukuran versi Golfscript (untuk saat ini)!

Sunting: Mengganti indexOfdengan matematika, memecah tabel pencarian, perbaikan kecil lainnya.

Sunting: Lain mapke fordan dimasukkan ke dalam final \nsaya tidak perlu makan. Akhirnya di dalam versi Python Jules.

i=prompt(o='').split(' ');for(r=6;o+=' EADGBe'[r]+' ',r--;o+='\n')
for(j=0;n=i[j++];o+=(([84,13,52,5][2*/m/.test(n)+x]*8>>2*r&3)+y-7*x)+'---')
y=n.charCodeAt(0),y=(2*y-(y>66)-(y>69)+(n[1]<'$')-(n[1]=='b')+2)%12,x=y>6;alert(o)

Output tidak lagi mengambil keuntungan dari trailing ---menjadi opsional seperti:

e 2---2---0---0---3---5---0---2---
B 3---2---2---0---3---7---0---2---
G 4---3---2---1---4---7---0---3---
D 4---4---2---2---5---7---2---4---
A 2---4---0---2---5---5---2---4---
E 2---2---0---0---3---5---0---2---
DocMax
sumber
Sial, saya punya javascript peen-iri saya pikir. Bagus sekali.
kekekela
7

Golfscript, 136 karakter

[["eBGDAE"{[]+" "+}/]]\" "/{.-2\{"bm#A B C D E F G"?.)!!*(+}/14%.3>-.8>-.7/@109?0>2*+[963 780 882 753]{3base(;}%=\7%{+'---'+}+%}%+zip n*

Sepenuhnya 23 karakter (17,5%) berurusan dengan dua karakter di awal setiap baris output.

Output sampel, menguji kasus tepi:

$ golfscript.rb tabs.gs <<<"E G# Ab A Db D# Em G#m Abm Am D#m"
e 0---4---4---0---4---6---0---4---4---0---5---
B 0---4---4---2---6---8---0---4---4---1---6---
G 1---5---5---2---6---8---0---4---4---2---7---
D 2---6---6---2---6---8---2---6---6---2---7---
A 2---6---6---0---4---6---2---6---6---0---5---
E 0---4---4---0---4---6---0---4---4---0---5---

Saya hanya menghabiskan sekitar satu jam untuk ini, jadi mungkin bisa dikurangi setidaknya 5 hingga 10 karakter. Secara konseptual ternyata sangat mirip dengan solusi DocMax: tabel pencarian untuk empat kasus, kemudian ditambahkan oleh offset dan bergabung dengan string dalam urutan yang benar.

Peter Taylor
sumber
+1: Laki-laki Saya suka Golfscript! Beberapa kali hari ini saya telah menemukan tempat untuk memangkas kode saya, tetapi tidak sampai 50%! Saya tidak punya juru bahasa: apakah mengembalikan D # untuk Eb?
DocMax
BTW, catatan terakhir dalam sampel Anda cocok dengan C # m meskipun baris perintah menunjukkan D # m. Kesalahan ketik atau bug?
DocMax
@ DocMax, bug. Saya tidak mengerti mengapa ini hanya mempengaruhi D # m dan bukan D # - ini akan menarik untuk di-debug. Saya menyusun ulang hal-hal karena nyaman untuk memiliki blok 7 pertama, jadi Eb tidak benar-benar kasus tepi.
Peter Taylor
Ternyata yang terakhir mendapatkan \ n termasuk, yang tidak berada di tabel pencarian menurunkan nilai dengan setara dengan huruf.
Peter Taylor
4

Setelah mengkodekan ini, saya menyadari saya bisa melakukan ini jauh lebih pintar ... mungkin saya akan membuat entri lain. Semoga saja saya mendapatkan poin karena menjadi yang tercepat!

Bagaimanapun, ada 962 karakter Perl.

%c =(B=>{E=>0,F=>1,Gb=>2,G=>3,Ab=>4,A=>2,Bb=>3,B=>4,C=>5,Db=>6,D=>7,Eb=>8,Em=>0,Fm=>1,Gbm=>2,Gm=>3,Abm=>0,Am=>1,Bbm=>2,Bm=>3,Cm=>4,Dbm=>5,Dm=>6,Ebm=>7},G=>{E=>1,F=>2,Gb=>3,G=>4,Ab=>5,A=>2,Bb=>3,B=>4,C=>5,Db=>6,D=>7,Eb=>8,Em=>0,Fm=>1,Gbm=>2,Gm=>3,Abm=>4,Am=>2,Bbm=>3,Bm=>4,Cm=>5,Dbm=>6,Dm=>7,Ebm=>8},D=>{E=>2,F=>3,Gb=>4,G=>5,Ab=>6,A=>2,Bb=>3,B=>4,C=>5,Db=>6,D=>7,Eb=>8,Em=>2,Fm=>3,Gbm=>4,Gm=>5,Abm=>6,Am=>2,Bbm=>3,Bm=>4,Cm=>5,Dbm=>6,Dm=>7,Ebm=>8},A=>{E=>2,F=>3,Gb=>4,G=>5,Ab=>6,A=>0,Bb=>1,B=>2,C=>3,Db=>4,D=>5,Eb=>6,Em=>2,Fm=>3,Gbm=>4,Gm=>5,Abm=>6,Am=>0,Bbm=>1,Bm=>2,Cm=>3,Dbm=>4,Dm=>5,Ebm=>6},E=>{E=>0,F=>1,Gb=>2,G=>3,Ab=>4,A=>0,Bb=>1,B=>2,C=>3,Db=>4,D=>5,Eb=>6,Em=>0,Fm=>1,Gbm=>2,Gm=>3,Abm=>4,Am=>0,Bbm=>1,Bm=>2,Cm=>3,Dbm=>4,Dm=>5,Ebm=>6});
%b=('A#'=>'Bb','C#'=>'Db','D#'=>'Eb','F#'=>'Gb','G#'=>'Ab');
foreach(qw(e B G D A E)){p($_,@ARGV)}
sub p{$s = shift;print "$s ";$s = uc($s);foreach(@_){while(($h,$f)=each(%b)){s/$h/$f/}print "$c{$s}->{$_}---"}print "\n"}

Berikut adalah output yang sesuai.

dhrasmus:Desktop standage$ perl guitar Bm Gb A E G D Em F#
e 2---2---0---0---3---5---0---2---
B 3---2---2---0---3---7---0---2---
G 4---3---2---1---4---7---0---3---
D 4---4---2---2---5---7---2---4---
A 2---4---0---2---5---5---2---4---
E 2---2---0---0---3---5---0---2---
Daniel Standage
sumber
4

Karena solusi yang lebih pendek telah diberikan (Sialan GolfScript!), Inilah milik saya:

Python, 229 karakter

s=[("E EmF FmF#GbG GmG#AbA AmA#BbB BmC CmC#DbD DmD#Eb".find("%-02s"%s[:2])/4,s[-1]!='m')for s in raw_input().split()]
for c in range(6):
 l='eBGDAE'[c]+' '
 for(i,M)in s:x=i>4;l+=`i-5*x+2*(2<c+x<5)+(M+x)*(c==2-x)`+"---"
 print l

Keluaran:

> echo "Bm Gb A E G D Em F#" | python guitar.py
e 2---2---0---0---3---5---0---2---
B 3---2---2---0---3---7---0---2---
G 4---3---2---1---4---7---0---3---
D 4---4---2---2---5---7---2---4---
A 2---4---0---2---5---5---2---4---
E 2---2---0---0---3---5---0---2---
Jules Olléon
sumber
3

Python, 449 karakter

z=int
f=str
r=range
j=''.join
n='E F F# G G# A A# B C C# D D#'.split()
n+=[x+'m'for x in n]
c=[j([f(z(x)+i)for x in'001220'])for i in r(5)]+[j([f(z(x)+i)for x in'022200'])for i in r(7)]
c+=[x[:2]+f(z(x[2])-1)+x[3:]for x in c[:5]]+[x[0]+f(z(x[1])-1)+x[2:]for x in c[5:]]
a=[c[n.index((chr(ord(i[0])-1)+'#'+i[2:]).replace('@','G')if len(i)-1 and i[1]=='b'else i)]for i in raw_input().split()] 
for i in r(6):print'eBGDAE'[i],j([x[i]+'-'*3 for x in a])
Fernando Martin
sumber
3

C99 - 231 karakter

Akor diberikan pada baris perintah, satu argumen per akor, dan tentu saja tidak ada validasi input dalam bentuk apa pun.

#include<stdio.h>
int main(int c,char**v){for(char*o="e0)B2)G2*D2+A0+E0)",i,m;*o;o+=3,v-=c,puts(""))for(printf("%c ",*o);*++v;printf("%c---",i-(i>2)-i/9+o[1+i/8]-(*o-66-i/8*5?0:m?m+2[*v]>99:0)))m=1[*v],i=(**v*2-4+m/35-m/98*3)%14;}

Contoh dijalankan:

$ ./a.out Bm Gb A E G D Em F#
e 2---2---0---0---3---5---0---2---
B 3---2---2---0---3---7---0---2---
G 4---3---2---1---4---7---0---3---
D 4---4---2---2---5---7---2---4---
A 2---4---0---2---5---5---2---4---
E 2---2---0---0---3---5---0---2---

Tidak bermain golf

#include<stdio.h>
int main(int c,char**v){
     // o points to three characters per output line:
     //   string name, number for A, adjusted number for E (ASCII code minus 7)
     char* o="e0)B2)G2*D2+A0+E0)",
          i, // chord: A=0, A#=1, ..., G#=13, allowing also 3="E#" and 9="B#"
          m; // second character in chord name
     for (; *o; o+=3) {
          printf("%c ", *o);
          for (; *++v; ) {
               m = 1[*v],
               i = (**v*2-4+m/35-m/98*3)%14; // parse & adjust for sharp, flat
               printf("%c---",
                      i-(i>2)-i/9 // eliminate "E#", "B#"
                      +o[1+i/8] // get the number for a major chord
                      // adjust for minor...
                      -(*o-66-i/8*5
                        ? 0
                        : m ? m+2[*v]>99 : 0));
          }
          v -= c; // rewind argument pointer
          puts("");
     }
}

C - 206 karakter tidak standar

Jika kita tidak peduli dengan spesifikasi bahasa, GCC dapat mengkompilasi one-liner berikut ke dalam biner fungsional, meskipun ia mencampur deklarasi variabel C99 dengan deklarasi argumen gaya K&R (dan deklarasi printf secara implisit).

main(c,v)char**v;{for(char*o="e0)B2)G2*D2+A0+E0)",i,m;*o;o+=3,v-=c,puts(""))for(printf("%c ",*o);*++v;printf("%c---",i-(i>2)-i/9+o[1+i/8]-(*o-66-i/8*5?0:m?m+2[*v]>99:0)))m=1[*v],i=(**v*2-4+m/35-m/98*3)%14;}
han
sumber
2

C ++, 432

#include <cmath>
#include <iostream>
F(int c){c-=65;return c*1.6+sin(c/5.+.3);}
T(int a,int s){if(s)return(a=(T(a,s-1)+2)%3)-=(a==1&s>2);return(a<7)*2;}
#define c(a,b) while(*(++j)==a)b;--j; 
#define O std::cout<<
main(int a,char*p[]){
int P=2;for(int i=-1;++i<6;P=2){O p[1][i];O" ";while(P<a){char*j=p[P++];
int f=F(*j);c('#',++f)c('b',--f)
int t=T(f,i)*3.5;if(*(++j)!='m'){--j;t+=(t==3);}
O(f-F(p[1][i])+t+24)%12;O"---";
}O'\n';}}

Perhatikan bahwa ini membutuhkan penyetelan gitar sebagai parameter pertama. (Kebanyakan penyetelan non-standar akan memberi Anda hasil fingerbreak yang konyol, tapi saya rasa Anda puas dengan penyetelan standar.)

Untuk Hotel California, Anda bisa melakukannya $./a.out EBGDAE Cbm Gb Bbb Fb G D Em F# Bm F# G## D## F## C## D##m E##. Hasil:

E 2---2---0---0---3---5---0---2---2---2---5---0---3---5---0---2---
B 3---2---2---0---3---7---0---2---3---2---5---0---3---7---0---2---
G 4---3---2---1---4---7---0---3---4---3---6---1---4---7---0---3---
D 4---4---2---2---5---7---2---4---4---4---7---2---5---7---2---4---
A 2---4---0---2---5---5---2---4---2---4---7---2---5---5---2---4---
E 2---2---0---0---3---5---0---2---2---2---5---0---3---5---0---2---
berhenti untuk memutar balik
sumber
Menyetel empat senar teratas menjadi sepertiga minor membuatnya sangat mudah untuk memainkan akord tiga dan empat senar dalam banyak inversi, tanpa senar terbuka, dan tanpa harus meletakkan jari "di atas" senar tanpa menyentuhnya. Menggunakan string DFG # B, urutan akor seperti "Bbm F Bbm Gb Db Ebm Db F Bbm F F7 Bbm" (Lagu Mermaid) bekerja dengan sangat mudah. Hanya perlu menggeser ke atas dan ke bawah satu fret. Ada perubahan kunci setengah langkah, tapi itu hanya berarti bergerak resah. Belum tahu apa yang terbaik untuk dilakukan dengan dua string lainnya.
supercat
@supercat: menarik, saya akan mencoba ini pada gitar saya besok ...
berhenti mengubah counterclockwis
Saya ingin mendengar pendapat Anda. Saya mengambil gitar beberapa kali, bertahun-tahun terpisah, dan terus menyerah karena jari-jarinya tampak sewenang-wenang dan canggung. Lalu aku mulai berpikir tentang apa yang akan memungkinkan tuning sederhana. Karena akor bentuk tertutup memiliki interval yang berkisar dari sepertiga minor hingga keempat sempurna, senar tuning hingga sepertiga minor berarti setiap string akan teredam pada titik yang tidak lebih rendah dari string di bawah ini. Jika saya dapat mencoba gitar kidal, saya mungkin mencoba yang sempurna keempat dengan urutan string terbalik, karena itu harus sama.
supercat
Karena itu, menyetel ke sepertiga minor berarti bahwa untuk setiap posisi jari pertama pada senar terendah, akan ada tiga inversi akor utama dan tiga inversi akor minor yang tersedia. Anda juga dapat memainkan akord ketujuh dengan menempatkan jari kedua di tiga senar teratas. Untuk Mermaid Song, mulailah dari fret ketiga dan mainkan F-Bb-DF (dengan jari 1-3-3-4). Maka F adalah FACF (1-2-2-4). Gb adalah fret, meraba 1-2-2-4 (seperti F). Db kembali khawatir, 1-3-4-4. Ebm kembali bangkit, 1-2-4-4.
supercat
Saya hanya perlu beberapa jam untuk sampai pada titik di mana saya bisa dengan lancar memainkan beberapa lagu (termasuk Mermaid Song yang disebutkan sebelumnya) setelah berolahraga dengan bantuan keyboard seperti apa yang seharusnya dicatat dengan akor yang tepat. Setelah saya mencoba gaya ini, rasanya luar biasa alami, dan saya sangat suka cara orang dapat menggunakan ketiga inversi dari setiap akord mayor dan minor. Jika seseorang hanya menginginkan akor mayor dan minor, penyetelan seperti F-Ab-B-Eb-Gb-D secara teoritis dapat memungkinkan akord mayor dan minor enam jari dengan jari mudah (1-2-2-3-4-4 atau 1 -1-2-3-3-4) tetapi tanpa inversi.
supercat
2

390 345 340 Catatan tambahan

Disederhanakan menjadi pendekatan gitar-pragmatis (bentuk E hanyalah variasi dari bentuk A, digeser ke bawah string, dengan perubahan satu jari). Meminjam ide string yang disandikan dari jawaban lain.

[/p{print}/x{exch}/e{cvx exec}/d{dup 0
get}/f{forall}(A0#1B2C3D5E7F8G:b;){}forall/m{dup
4 2 copy get 1 sub put}109{m 48}/+{[3 1 roll x{1
index add x}f]}/*{[0 0 2 2 2 0 0]x{load e 48 sub
+}f d 12 gt{-12 +}if d 6 gt{m -7 + 1}{0}ifelse 6
getinterval}>>begin[ARGUMENTS{*}f][(E)(A)(D)(G)(B)(e)]6{[x
e p( )p]x[x{[x e( )cvs p(---)p]}f]x()=}repeat

Sebelumnya:

450 442 418 Catatan tambahan

Saya memperbaiki format output dengan yang ini juga. (Versi sebelumnya mulai "E ---" daripada "e".)

<</i{index}/a{add}/p{pop}/x{exch}/g{getinterval}/r{print}/f{forall}/e{exec}>>begin<<65[0
2 3 5 -5 -4 -2]{1 i 1 a}f p 35{1 a}98{1 sub}109{x dup
4 20 put x}>>begin[ARGUMENTS{[x[0 5 12 17 21 24 29
0]x{load e}f x{1 i a x}f]dup 0 get 0 ge{0}{1}ifelse 7
g[0 -5 -10 -15 -19 -24 -29]0 1 6{2 copy get 3 i 2 i
get a 3 copy put p p}for x p 0 6
g}f][(E)(A)(D)(G)(B)(e)]6{[x cvx e r( )r]x[x{[x cvx
e( )cvs r(---)r]}f]x(\n)r}repeat

Cara menjalankannya: gsnd -q -- tab.ps Bm Gb A E G D Em F\#(sembunyikan tajam dari cangkang).

Versi un-golfed hampir lebih sulit daripada versi golf. Tetapi saya berusaha untuk teliti. Sunting: beberapa komentar lagi pada bits-tricky.

%!PS
<<    %axioms and operations
/t{2 2 1}    %major tetrachord
/m{t t 2}    %mixolydian mode
/u{2 1 2}    %minor tetrachord
/a{u u}      %aolian mode
/s{m m t}    %2.5-octave mixolydian intervals
/r{3 1 roll}
/${[exch 0 exch{1 index add}forall]}    %running sum: convert (relative)intervals to (abstract)fretstops
/+{[r exch{1 index add exch}forall pop]}    %scale array by scalar
/@{[r{2 copy get r pop}forall pop]}    %select array elements from array of indices
/&{0 1 3 index length 1 sub{    %array2 += array1
    2 copy get 3 index 2 index get add 3 copy put pop pop}for exch pop}
>>begin<<    %map ascii values to scaling functions
65[a]$    %generate fretstops of the A aolian scale to assign scalars to note names
[0 0 0 0 -12 -12 -12]&    %drop E F and G down an octave
{[exch/+ cvx]cvx 1 index 1 add}forall pop    %generate the pairs 'A'->{0 +}, 'B'->{2 +}
35{1 +}     %'#'-> scale up by one
98{-1 +}    %'b'-> scale down by one
109{dup 4 2 copy get 1 sub put}     %'m'-> tweak the 'third' down by one
%generate chord pattern from (string)
/*{[s]$       %generate fretstops of the E mixolydian scale
  [1 4 8 11 13 15 18]    %A-shape figured bass: IV chord of E mixolydian
  -1 +       %convert scale degrees to array indices
  @       %generate chord template by selecting indices from mixolydian scale
  exch{load exec}forall       %execute ascii values, scaling the pattern
  dup 0 get 0 ge{0}{1}ifelse 6 getinterval    %discard first note if it has fallen off the bottom
  [0 -5 -10 -15 -19 -24]&}    %subtract the string offsets
>>begin    %activate definitions
%(A)* pstack()= clear    %[0 0 2 2 2 0]
%(B)* pstack()= clear    %[2 2 4 4 4 2]
%(F#)* pstack()= clear    %[2 4 4 3 2 2]
%(Abm)* pstack()=    %[4 6 6 4 4 4]
[ARGUMENTS{*}forall]    %convert array of strings to array of patterns
[(E)(A)(D)(G)(B)(e)]    %array of string names
6{    %for each "string"
    [exch cvx exec print( )print]    %pop string name and print with space
    exch       %put names behind numbers
    [exch{     %for each "chord"
        [exch cvx exec( )cvs print(---)print]    %pop number, convert, print with trailing hyphens
    }forall]    %zip up chord array for next iteration
    ()=         %print a newline
    exch        %put numbers behind names
}repeat

Dan bagaimana dengan House of the Rising Sun sebagai ujian?

04:51 PM:~ 0> gsnd -q -- tabb.ps Em G A C Em G B B Em G A C Em B Em B|sed 's/^/    /'
e 0---3---0---3---0---3---2---2---0---3---0---3---0---2---0---2---
B 0---3---2---5---0---3---4---4---0---3---2---5---0---4---0---4---
G 0---4---2---5---0---4---4---4---0---4---2---5---0---4---0---4---
D 2---5---2---5---2---5---4---4---2---5---2---5---2---4---2---4---
A 2---5---0---3---2---5---2---2---2---5---0---3---2---2---2---2---
E 0---3---0---3---0---3---2---2---0---3---0---3---0---2---0---2---
luser droog
sumber
Saya menulis komentar tentang kode ini di jawaban lain di sini .
luser droog