language agnostic - Código Golf: Notas musicales
language-agnostic code-golf (12)
F #, 458 caracteres
Razonablemente corto, y aún más legible:
let s=Array.init 10(fun _->new System.Text.StringBuilder())
System.Console.ReadLine().Split([|'' ''|])
|>Array.iter(fun n->
for i in 0..9 do s.[i].Append(if i%2=1 then"----"else" ")
let l=s.[0].Length
let i=68-int n.[0]+if n.[0]>''D''then 7 else 0
s.[i+3].[l-3]<-''O''
if n.Length>1 then
for j in i..i+2 do s.[j].[l-2]<-''|''
for j in i..i-1+(match n.[2]with|''4''->0|''8''->1|''1''->2|_->3)do s.[j].[l-1]<-''//')
for x in s do printfn"%s"(x.ToString())
Con un breve comentario:
// create 10 stringbuilders that represent each line of output
let s=Array.init 10(fun _->new System.Text.StringBuilder())
System.Console.ReadLine().Split([|'' ''|])
// for each note on the input line
|>Array.iter(fun n->
// write the staff
for i in 0..9 do s.[i].Append(if i%2=1 then"----"else" ")
// write note (math so that ''i+3'' is which stringbuilder should hold the ''O'')
let l=s.[0].Length
let i=68-int n.[0]+if n.[0]>''D''then 7 else 0
s.[i+3].[l-3]<-''O''
// if partial note
if n.Length>1 then
// write the bar
for j in i..i+2 do s.[j].[l-2]<-''|''
// write the tails if necessary
for j in i..i-1+(match n.[2]with|''4''->0|''8''->1|''1''->2|_->3)do s.[j].[l-1]<-''//')
// print output
for x in s do printfn"%s"(x.ToString())
El reto
El código más corto por recuento de caracteres, que generará notación musical en función de la entrada del usuario.
La entrada estará compuesta por una serie de letras y números: las letras representarán el nombre de la nota y el número representará la longitud de la nota. Una nota está hecha de 4 columnas verticales. La cabeza de la nota será una O
mayúscula, tallo, si está presente será de 3 líneas de altura, hecho a partir del carácter de la tubería |
, y la (s) bandera (s) se harán desde una barra /
.
Las notas válidas son ninguna, 1/4 de una nota, 1/8 de una nota, 1/16 de una nota y 1/32 de una nota.
| |/ |/ |/
| | |/ |/
| | | |/
O O O O O
1 1/4 1/8 1/16 1/32
Las notas son lugares del Staff, de acuerdo con el nombre de su nota:
----
D ----
C
B ----
A
G ----
F
E ----
Se puede suponer que todas las entradas son válidas y sin errores: cada nota se separa con un espacio en blanco en una sola línea, con al menos una nota válida.
Casos de prueba
Input:
B B/4 B/8 B/16 B/32 G/4 D/8 C/16 D B/16
Output:
|/
--------------------------|---|/--------
| |/ |/ |/ | |/ |/
------|---|---|/--|/-----O----|--O----|/
| | | |/ | O |
-O---O---O---O---O----|--------------O--
|
---------------------O------------------
----------------------------------------
Input:
E/4 F/8 G/16 A/32 E/4 F/8 G/16 A/32
Output:
--------------------------------
--------------|/--------------|/
|/ |/ |/ |/
------|/--|/--|/------|/--|/--|/
| | | O | | | O
--|---|--O--------|---|--O------
| O | O
-O---------------O--------------
Input:
C E/32 B/8 A/4 B F/32 B C/16
Output:
------------------------------|/
|/ |/
----------|---|---------------|-
O | | O
---------O----|--O----|/-O------
|/ O |/
------|/--------------|/--------
|/ O
-----O--------------------------
El recuento de códigos incluye entrada / salida (es decir, programa completo).
C 196 caracteres <<o>>
Pedir prestado algunas ideas de extravagante. Las características interesantes incluyen el operador n+++1
"triple +" y el operador <<o>>
"evil eye"
#define P,putchar
N[99];*n=N;y;b;main(o){for(;scanf(" %c/%d",n,n+1)>0;n+=2);for(;y<11;)
n=*n?n:(y++P(10),N)P(b=y&1?32:45)P((o=10-(*n+++1)%7-y)?b:79)P(0<o&o<4&&*n?''|'':b)
P(*n++<<o>>6&&0<o&o<4?92:b);}
C - 293 caracteres
Todavía necesita más compresión, y toma los argumentos en la línea de comandos en lugar de leerlos ...
i,j,k,l;main(c,v)char **v;{char*t;l=4*(c-1)+2;t=malloc(10*l)+1;for(i=0;i<10;i
++){t[i*l-1]=''/n'';for(j=0;j<l;j++)t[i*l+j]=i&1?''-'':'' '';}t[10*l-1]=0;i=1;while
(--c){j=''G''-**++v;if(j<3)j+=7;t[j*l+i++]=''O'';if(*++*v){t[--j*l+i]=''|'';t[--j*l
+i]=''|'';t[--j*l+i]=''|'';if(*++*v!=''4''){t[j++*l+i+1]=''//';if(**v!=''8''){t[j++*l+
i+1]=''//';if(**v!=''1''){t[j++*l+i+1]=''//';}}}}i+=3;}puts(t);}
editar: solucionó el E
editar: hasta 293 caracteres, incluidas las nuevas líneas ...
#define X t[--j*l+i]=''|''
#define Y t[j++*l+i+1]=92
i,j,k,l;main(c,v)char**v;{char*t;l=4*(c-1)+2;t=malloc(10*l)+1;for(i=10;i;)t[--i*
l-1]=10,memset(t+i*l,i&1?45:32,l-1);t[10*l-1]=0;for(i=1;--c;i+=3)j=71-**++v,j<3?
j+=7:0,t[j*l+i++]=79,*++*v?X,X,X,*++*v-52?Y,**v-56?Y,**v-49?Y:0:0:0:0;puts(t);}
168 caracteres en Perl 5.10
Mi solución original fue de 276 caracteres, pero muchos ajustes la redujeron en más de 100 caracteres.
$_=<>;
y#481E-GA-D62 #0-9#d;
s#.(/(.))?#$"x(7+$&).O.$"x($k=10).($1?"|":$")x3 .$"x(10-$2)."//"x$2.$"x(9-$&)#ge;
s#(..)*?/K (.)#-$2#g;
print$/while--$k,s#.{$k}/K.#!print$&#ge
Si tiene una sugerencia menor que mejora esto, siéntase libre de simplemente editar mi código.
C89 (186 caracteres)
#define P,putchar(
N[99];*n=N;y;e=45;main(q){for(;scanf(" %c/%d",n,n+1)>0;n
+=2);for(;y<11;q=y-(75-*n++)%7 P+q-4?e:79)P*n&&q<4&q>0?
124:e)P*n++/4>>q&&q?92:e))*n||(e^=13,n=N,y++P+10))P+e);}
Soporte de media nota (+7 caracteres)
#define P,putchar(
N[99];*n=N;y;e=45;main(q){for(;scanf(" %c/%d",n,n+1)>0;n
+=2);for(;y<11;q=y-(75-*n++)%7 P+q-4?e:v<4?79:64)P*n&&q<4&q>0?
124:e)P*n++/4>>q&&q?92:e))*n||(e^=13,n=N,y++P+10))P+e);}
Python 178 caracteres
El 167 era una falsa alarma, olvidé suprimir los tallos en las notas completas.
R=raw_input().split()
for y in range(10):
r=""
for x in R:o=y-(5-ord(x[0]))%7;b=" -"[y&1]+"O/|";r+=b[0]+b[o==3]+b[-(-1<o<3and''''<x[1:])]+b[2*(-1<o<":862".find(x[-1]))]
print r
Python 167 caracteres (Roto)
No hay lugar para el mal de ojo en este caso, aunque hay 2 personajes de relleno allí, así que agregué un emoticono. Esta técnica aprovecha la singularidad del último carácter de las longitudes de las notas, tan afortunada para mí que no hay 1/2 notas ni 1/64 de notas.
R=raw_input().split()
for y in range(10):
r=""
for x in R:o=y-(5-ord(x[0]))%7;b=" -"[y&1]+"O/|";r+=b[0]+b[o==3]+b[-(-1<o<3)]+b[2*(-1<o<":862".find(x[-1]))]
print r
Python 186 caracteres <<o>>
Python utiliza el operador <<o>>
evil eye con gran efecto aquí. El método find()
devuelve -1 si el elemento no se encuentra, por lo que D no necesita aparecer en las notas.
R=raw_input().split()
for y in range(10):
r=""
for x in R:o=''CBAGFE''.find(x[0])+4;B=" -"[y%2];r+=B+(B,''O'')[o==y]+(x[2:]and
y+4>o>y and"|"+(B,''//')[int(x[2:])<<o>>6+y>0]or B*2)
print r
11 bytes adicionales dan una versión con medias notas
R=raw_input().split()
for y in range(10):
r=""
for x in R:t=''CBAGFE''.find(x[0])+4;l=x[2:];B=" -"[y%2];r+=B+(B,''@O''[l
in''2''])[t==y]+(l and y+4>t>y and"|"+(B,''//')[int(l)>>(6+y-t)>0]or B*2)
print r
$ echo B B/2 B/4 B/8 B/16 B/32 G/4 D/8 C/16 D B/16| python notes.py
|/
------------------------------|---|/--------
| | |/ |/ |/ | |/ |/
------|---|---|---|/--|/-----@----|--O----|/
| | | | |/ | @ |
-O---O---@---@---@---@----|--------------@--
|
-------------------------@------------------
--------------------------------------------
159 caracteres de Ruby
n=gets.split;9.downto(0){|p|m=''- ''[p%2,1];n.each{|t|r=(t[0]-62)%7;g=t[2..-1]
print m+(r==p ?''O''+m*2:p>=r&&g&&p<r+4?m+''|''+(g.to_i>1<<-p+r+5?''//':m):m*3)}
puts}
Perl, 126 caracteres (115/122 con interruptores)
Perl en 239 226 218 216 183 180 178 172 157 142 136 133 129 128 126 caracteres
Esta solución de 126 caracteres en Perl es el resultado de una larga colaboración entre yo y A. Rex.
@o=($/)x10;$/=$";map{m[/];$p=4+(5-ord)%7;
$_.=--$p?!($p&~3)*$''?16<$p*$''?" |//":" | ":$/x4:" O ",
$|--&&y@ @-@for@o}<>;print@o
A. Rex también propone una solución para ejecutar con el conmutador perl -ap
. Con 111 (!) Caracteres en esta solución más 4 golpes para el cambio de línea de comando adicional, esta solución tiene una puntuación total de 115.
$/="$:
"x5;$p=4+(5-ord)%7,s#..##,$/=~s#(.)/K$#--$p?
$_*!($p&~3)?"$1|".(16<$p*$_?"//":$1).$1:$1x4:O.$1x3#gemfor@F
La primera nueva línea en esta solución es significativa.
O 122 caracteres que incorporan los interruptores en la línea shebang:
#!perl -ap
$/="$:
"x5;$p=4+(5-ord)%7,s#..##,$/=~s#(.)/K$#--$p?$_*!($p&~3)?"$1|".(16<$p*$_?
"//":$1).$1:$1x4:O.$1x3#gemfor@F
(las dos primeras líneas nuevas son significativas).
Las notas medias se pueden respaldar con 12 caracteres adicionales:
@o=($/)x10;$/=$";map{m[/];$p=4+(5-ord)%7;
$_.=--$p?!($p&~3)*$''?16<$p*$''?" |//":" | ":$/x4:$''>2?" @ ":" O ",
$|--&&y@ @-@for@o}<>;print@o
Ruby 136
n=gets;10.times{|y|puts (b='' -''[y&1,1])+n.split.map{|t|r=y-(5-t[0])%7
(r==3?''O'':b)+(t[1]&&0<=r&&r<3?''|''<<(r<t[2,2].to_i/8?92:b):b+b)}*b}
Ruby 139 (Tweet)
n=gets;10.times{|y|puts (b='' -''[y&1,1])+n.split.map{|t|r=y-(5-t[0])%7
(r==3?''O'':b)+(t[1]&&0<=r&&r<3?''|''<<(r<141>>(t[-1]&7)&3?92:b):b+b)}*b}
Ruby 143
n=gets.split;10.times{|y|puts (b='' -''[y&1,1])+n.map{|t|r=y-(5-t[0])%7;m=t[-1]
(r==3?''O'':b)+(m<65&&0<=r&&r<3?''|''<<(r<141>>(m&7)&3?92:b):b+b)}*b}
Ruby 148
Aquí hay otra forma de calcular las banderas,
donde m=ord(last character)
, #flags=1+m&3-(1&m/4)
y otra forma #flags=141>>(m&7)&3
, que guarda un byte más
n=gets.split;10.times{|y|b='' -''[y&1,1];n.each{|t|r=y-(5-t[0])%7;m=t[-1]
print b+(r==3?''O'':b)+(m<65&&0<=r&&r<3?''|''<<(r<141>>(m&7)&3?92:b):b+b)}
puts}
Ruby 181
El primer intento es una transliteración de mi solución de Python
n=gets.split;10.times{|y|r="";n.each{|x|o=y-(5-x[0])%7
r+=(b=" -"[y&1,1]+"O//|")[0,1]+b[o==3?1:0,1]+b[-1<o&&o<3&&x[-1]<64?3:0,1]+b[-1<o&&o<(":862".index(x[-1]).to_i)?2:0,1]}
puts r}
Golfscript (112 caracteres)
'' ''%:A;10,{):y;A{2/.0~|1=~:r;0=0=5/- 7%
4y@--:q'' '''' O''if-4q&!q*r*{16q/r<''|//'
''| ''if}'' ''if+{.32=y~&{;45}*}%}%n}%
Lua, 307 Personajes
b,s,o="//",io.read("*l"),io.write for i=1,10 do for n,l in
s:gmatch("(%a)/?(%d*)")do x=n:byte() w=(x<69 and 72 or 79)-x
l=tonumber(l)or 1 d=i%2>0 and" "or"-"o(d..(i==w and"O"or
d)..(l>3 and i<w and i+4>w and"|"or d)..(l>7 and i==w-3
and b or l>15 and i==w-2 and b or l>31 and i==w-1 and b or
d))end o"/n"end
LilyPond - 244 bytes
Técnicamente hablando, esto no cumple con la especificación de salida, ya que la salida es un PDF muy bien grabado en lugar de un pobre sustituto de texto ASCII, pero pensé que el problema era simplemente pedir una solución LilyPond. De hecho, puede eliminar "/ autoBeamOff / cadenzaOn / stemUp" para que se vea aún mejor formateado. También puede agregar "/ midi {}" después de "/ layout {}" para obtener un archivo MIDI para escuchar.
o=#(open-file"o""w")p=#ly:string-substitute
#(format o"~(~a"(p"2''1""2"(p"4''1""4"(p"6''1""6"(p"8''1""8"(p"/""''"(p"C""c''"(p"D""d''"(p" ""/1"(p"
"" "(ly:gulp-file"M")))))))))))#(close-port o)/score{{/autoBeamOff/cadenzaOn/stemUp/include"o"}/layout{}}
Uso: lilypond thisfile.ly
Notas:
- La entrada debe estar en un archivo llamado "M" en el mismo directorio que el programa.
- El archivo de entrada debe terminar en una nueva línea. (O ahorre 9 bytes haciendo que termine en un espacio).
- El resultado es un PDF llamado "thisfile.pdf", donde "thisfile.ly" es el nombre del programa.
- Probé esto con LilyPond 2.12.2; otras versiones podrían no funcionar.
No he hecho mucho en LilyPond, así que no estoy seguro de que esta sea la mejor manera de hacerlo, ya que tiene que convertir la entrada al formato LilyPond, escribirlo en un archivo auxiliar y luego leerlo. Actualmente no puede hacer funcionar el analizador / evaluador LilyPond incorporado. :(
Ahora trabajando en una solución de salida ASCII ... :)