language agnostic - woeusb - Code Golf: Build me an Arc
unable to locate package tree debian (12)
Reto
El programa más corto por número de caracteres que acepta la entrada estándar de la forma XY R
, con las siguientes garantías:
-
R
es un número decimal no negativo menor o igual a 8 -
X
eY
son ángulos no negativos dados en decimal como múltiplos de 45 ° (0
,45
,90
,135
, etc.) -
X
es menor queY
-
Y
no es360
siX
es0
Y produce en la salida estándar un "arco" ASCII desde el ángulo inicial X
hasta el ángulo final Y
del radio R
, donde:
- El vértice del arco está representado por
o
- Los ángulos de
0
y180
están representados por-
- Los ángulos de
45
y225
están representados por/
- Los ángulos de
90
y270
están representados por|
- Los ángulos de
135
y315
están representados por/
- El área poligonal delimitada por las dos líneas se rellena con un carácter que no es un espacio en blanco.
No se requiere que el programa produzca una salida significativa si se le da una entrada no válida. Se permiten soluciones en cualquier idioma, excepto, por supuesto, un lenguaje escrito específicamente para este desafío, o uno que haga un uso injusto de una utilidad externa. Se permiten espacios en blanco horizontales y verticales extraños en la salida siempre que el formato de la salida siga siendo correcto.
¡Feliz golf!
Numerosos ejemplos
Entrada:
0-45 8
Salida:
/ /x /xx /xxx /xxxx /xxxxx /xxxxxx /xxxxxxx o--------
Entrada:
0-135 4
Salida:
/xxxxxxxx /xxxxxxx /xxxxxx /xxxxx o----
Entrada:
180-360 2
Salida:
--o-- xxxxx xxxxx
Entrada:
45-90 0
Salida:
o
Entrada:
0-315 2
Salida:
xxxxx xxxxx xxo-- xxx/ xxxx/
C # - 325 319 caracteres
using System;class P{static void Main(){var s=Console.ReadLine().Split('' '');
var d=s[0].Split(''-'');int l=s[1][0]-48,x,y,r,a=int.Parse(d[0]),b=int.Parse(d[1]);
for(y=l;y>=-l;y--)for(x=-l;x<=l;)Console.Write((x==0&&y==0?''o'':a<=(r=((int)
(Math.Atan2(y,x)*57.3)+360)%360)&&r<b||r==b%360?
@"-/|/"[r/45%4]:'' '')+(x++==l?"/n":""));}}
Las líneas nuevas no son significativas.
Muestra de entrada / salida
45-180 8 /||||||||//////// //|||||||/////// ///||||||////// ////|||||///// /////||||//// //////|||/// ///////||// ////////|/ --------o
135-360 5 / // /// //// ///// -----o----- ----/|///// ---//||//// --///|||/// -////||||// /////|||||/
GNU BC, 339 caracteres
Gnu bc debido a read()
, else
y operadores lógicos.
scale=A
a=read()/45
b=read()/45
c=read()
for(y=c;y>=-c;y--){for(x=-c;x<=c;x++){if(x==0)if(y<0)t=-2else t=2else if(x>0)t=a(y/x)/a(1)else if(y<0)t=a(y/x)/a(1)-4else t=a(y/x)/a(1)+4
if(y<0)t+=8
if(x||y)if(t==a||t==b||t==b-8){scale=0;u=(t%4);scale=A;if(u==0)"-";if(u==1)"/";if(u==2)"|";if(u==3)"/"}else if(t>a&&t<b)"x"else" "else"o"};"
"}
quit
MATLAB, 188 caracteres :)
input '''';[wxr]=strread(ans,''%d-%d%d'');l=''-/|/-/|/-'';[XY]=meshgrid(-r:r);T=atan2(-Y,X)/pi*180;T=T+(T<=0)*360;T(T>w&T<x)=-42;T(T==w)=-l(1+w/45);T(T==x)=-l(1+x/45);T(r+1,r+1)=-''o'';char(-T)
Código comentado:
%%# Get the string variable (enclose in quotes, e.g. ''45-315 4'')
input ''''
%%# Extract angles and length
[w x r]=strread(ans,''%d-%d%d'');
%%# Store characters
l=''-/|/-/|/-'';
%%# Create the grid
[X Y]=meshgrid(-r:r);
%%# Compute the angles in degrees
T=atan2(-Y,X)/pi*180;
%%# Get all the angles
T=T+(T<=0)*360;
%# Negative numbers indicate valid characters
%%# Add the characters
T(T>w&T<x)=-42;
T(T==w)=-l(1+w/45);
T(T==x)=-l(1+x/45);
%%# Add the origin
T(r+1,r+1)=-''o'';
%%# Display
char(-T)
Mathematica 100 caracteres
Fuera de competición porque los gráficos son demasiado perfectos :)
f[x_-y_ z_]:=Graphics@Table[
{EdgeForm@Red,Disk[{0,0},r,{x °,y °}],{r,z,1,-1}]
SetAttributes[f,HoldAll]
Invocar con f [30-70 5]
Resultado
texto alt http://a.imageshack.us/img80/4294/angulosgolf.png
texto alternativo http://a.imageshack.us/img59/7892/angulos2.png
Nota
Los SetAttributes [f, HoldAll];
se necesita porque la entrada
f[a-b c]
se interpreta de otra manera como
f[(a-b*c)]
Perl, 235 211 225 211 207 196 179 177 175 168 160 156 146 caracteres
<>=~/-/d+/;for$y(@a=-$''..$''){print+(map$_|$y?!($t=8*($y>0)+atan2(-$y,$_)/atan2 1,1)&-$&/45==8|$t>=$`/45&$t<=-$&/45?qw(- / | //)[$t%4]:$":o,@a),$/}
Perl usando, por ejemplo, 161 149 139 caracteres.
$ echo -n ''<>=~/-/d+/;for$y(@a=-$''"''"''..$''"''"''){say map$_|$y?!($t=8*($y>0)+atan2(-$y,$_)/atan2 1,1)&-$&/45==8|$t>=$`/45&$t<=-$&/45?qw(- / | //)[$t%4]:$":o,@a}'' | wc -c
139
$ perl -E ''<>=~/-/d+/;for$y(@a=-$''"''"''..$''"''"''){say map$_|$y?!($t=8*($y>0)+atan2(-$y,$_)/atan2 1,1)&-$&/45==8|$t>=$`/45&$t<=-$&/45?qw(- / | //)[$t%4]:$":o,@a}''
Perl sin nueva línea, 153 143 caracteres
<>=~/-/d+/;for$y(@a=-$''..$''){print$/,map$_|$y?!($t=8*($y>0)+atan2(-$y,$_)/atan2 1,1)&-$&/45==8|$t>=$`/45&$t<=-$&/45?qw(- / | //)[$t%4]:$":o,@a}
Versión original comentada:
$_=<>;m/(/d+)-(/d+) (/d+)/;$e=$1/45;$f=$2/45; # parse angles and radius, angles are 0-8
for$y(-$3..$3){ # loop for each row and col
for$x(-$3..$3){
$t=atan2(-$y,$x)/atan2 1,1; # angle of this point
$t+=8if($t<0); # normalize negative angles
@w=split//,"-/|//"x2; # array of ASCII symbols for enclosing lines
$s.=!$x&&!$y?"o":$t==$e||$t==$f?$w[$t]:$t>$e&&$t<$f?"x":$";
# if it''s origin -> "o", if it''s enclosing line, get symbol from array
# if it''s between enclosing angles "x", otherwise space
}
$s.=$/;
}
print$s;
EDIT 1: Los operadores de sub, relacionales y de igualdad en línea devuelven 0 o 1.
EDITAR 2: Versión agregada con comentarios.
EDICIÓN 3: Línea de cerramiento fija a 360º. El conteo de Char aumentó significativamente.
EDITAR 4: Se agregó una versión más corta, doblando las reglas.
EDIT 5: Solución más inteligente para la línea de envolvente 360º. Además, utilice un número como relleno. Ambas cosas eran obvias. Meh, debería dormir más: /
EDITAR 6: Se eliminó una m
innecesaria del operador del partido. Se eliminaron algunos puntos y comas.
EDIT 7: regexp más inteligente. ¡Menos de 200 caracteres!
EDIT 8: Un montón de pequeñas mejoras:
- Inner for loop -> map (1 char)
- matriz de símbolos de cadena
split
-> qw (3 caracteres) - matriz de símbolos en línea (6 caracteres, junto con los 9 caracteres de mejora anteriores)
- Lógico o -> bitwise o (1 char)
- Mejora Regexp (1 char)
- Usa la aritmética para probar ángulos negativos, inspirada en la respuesta de Jacob (5 caracteres)
EDIT 9: Un poco de reordenamiento en los operadores condicionales guarda 2 caracteres.
EDITAR 10: usar palabras peladas para los personajes.
EDIT 11: Impresión movida dentro del bucle, inspirada en la respuesta de Lowjacker.
EDITAR 12: Versión añadida utilizando say
.
EDITAR 13: reutilizar los caracteres de los ángulos para el carácter de relleno, como lo hace la respuesta de Gwell. Sin embargo, la salida no es tan buena como la de Gwell, que requeriría 5 caracteres adicionales :) Además, el operador ... no necesita paréntesis.
EDITAR 14: Aplicar expresiones regulares directamente a <>. Asigne el operador de rango a una variable, según la sugerencia de Adrian a la respuesta de bta. Añadir versión sin la nueva línea final. Actualizado versión de say
.
EDITAR 15: más en línea. map {block} @a -> map expr, @ a.
Rubí, 292 276 186 caracteres.
x,y,r=gets.scan(//d+/).map{|z|z.to_i};s=(-r..r);s.each{|a|s.each{|b|g=Math::atan2(-a,b)/Math::PI*180/1%360;print a|b==0?''o'':g==x||g==y%360?''-/|//'[g/45%4].chr: (x..y)===g ?''*'':'' ''};puts}
Versión mejor formatada:
x, y, r = gets.scan(//d+/).map{|z| z.to_i}
s = (-r..r)
s.each {|a|
s.each {|b|
g = (((Math::atan2(-a,b) / Math::PI) * 180) / 1) % 360
print ((a | b) == 0) ? ''o'' :
(g == x || g == (y % 360)) ? ''-/|//'[(g / 45) % 4].chr :
((x..y) === g) ? ''*'' : '' ''
}
puts
}
Estoy seguro de que alguien que haya dormido más que yo puede condensarlo más ...
Edición 1: ¿ Cambió las sentencias if
en el bucle interno a anidadas ? :
? :
operador
Edición 2: rango almacenado a variable intermedia (gracias Adrian), usó stdin en lugar de parámetros de CLI (gracias a Jon por la aclaración), eliminó la matriz en favor de la salida directa, se corrigió un error donde un ángulo final de 360 no mostraría una línea eliminó algunos paréntesis innecesarios, usó la división para redondear en lugar de .round
, usó el módulo en lugar de la adición condicional
Ruby, 168 caracteres
Requiere Ruby 1.9 para trabajar
s,e,r=gets.scan(//d+/).map &:to_i;s/=45;e/=45;G=-r..r;G.map{|y|G.map{|x|a=Math.atan2(-y,x)/Math::PI*4%8;print x|y!=0?a==s||a==e%8?''-/|//'[a%4]:a<s||a>e ?'' '':8:?o};puts}
Versión legible:
start, _end, radius = gets.scan(//d+/).map &:to_i
start /= 45
_end /= 45
(-radius..radius).each {|y|
(-radius..radius).each {|x|
angle = Math.atan2(-y, x)/Math::PI * 4 % 8
print x|y != 0 ? angle==start || angle==_end%8 ? ''-/|//'[angle%4] : angle<start || angle>_end ? '' '' : 8 : ?o
}
puts
}
C (902 byte)
Esto no usa funciones trigonométricas (como la versión original de Perl), por lo que está bastante "hinchado". De todos modos, aquí está mi primer código de golf:
#define V(r) (4*r*r+6*r+3)
#define F for(i=0;i<r;i++)
#define C ;break;case
#define U p-=2*r+2,
#define D p+=2*r+2,
#define R *++p=
#define L *--p=
#define H *p=''|'';
#define E else if
#define G(a) for(j=0;j<V(r)-1;j++)if(f[j]==i+''0'')f[j]=a;
#define O(i) for(i=0;i<2*r+1;i++){
main(int i,char**v){char*p,f[V(8)];
int j,m,e,s,x,y,r;p=*++v;x=atoi(p);while(*p!=45)p++;
char*h="0123";y=atoi(p+1);r=atoi(*++v);
for(p=f+2*r+1;p<f+V(r);p+=2*r+2)*p=10;
*(p-2*r-2)=0;x=x?x/45:x;y/=45;s=0;e=2*r;m=r;p=f;O(i)O(j)
if(j>e)*p=h[0];E(j>m)*p=h[1];E(j>s)*p=h[2];else*p=h[3];p++;}
if(i+1==r){h="7654";m--;e--;}E(i==r){s--;}E(i>r){s--;e++;}
else{s++;e--;}p++;}for(p=f+V(r)/2-1,i=0;i<r;i++)*++p=48;
for(i=0;i<8;i++)if(i>=x&&i<y){G(64);}else G(32);
y=y==8?0:y;q:p=f+V(r)/2-1;*p=''o'';switch(x){
C 0:F R 45 C 1:F U R 47 C 2:F U H C 3:F U L 92
C 4:F L 45 C 5:F D L 47 C 6:F D H C 7:F D R 92;}
if(y!=8){x=y;y=8;goto q;}puts(f);}
Además, los #define
ven bastante feos, pero ahorran alrededor de 200 bytes, así que los mantuve, de todos modos. Es válido ANSI C89 / C90 y se recopila con muy pocas advertencias (dos sobre atoi
y atoi
y dos sobre la forma main
de lisiado).
Java - 304 caracteres
class A{public static void main(String[]a){String[]b=a[0].split("-");int e=new Integer(b[1]),r=new Integer(a[1]),g,x,y=r;for(;y>=-r;y--)for(x=-r;x<=r;)System.out.print((x==0&y==0?''o'':new Integer(b[0])<=(g=((int)(Math.atan2(y,x)*57.3)+360)%360)&g<e|g==e%360?"-/|//".charAt(g/45%4):'' '')+(x++<r?"":"/n"));}}
Versión más legible:
class A{
public static void main(String[]a){
String[]b=a[0].split("-");
int e=new Integer(b[1]),r=new Integer(a[1]),g,x,y=r;
for(;y>=-r;y--)for(x=-r;x<=r;)System.out.print((
x==0&y==0
?''o''
:new Integer(b[0])<=(g=((int)(Math.atan2(y,x)*57.3)+360)%360)&g<e|g==e%360
?"-/|//".charAt(g/45%4)
:'' ''
)+(x++<r?"":"/n"));
}
}
Lua, 259 caracteres
Abusa ligeramente de la cláusula de non-whitespace character
para producir una pantalla deslumbrante y, lo que es más importante, guardar trazos.
m=math i=io.read():gmatch("%d+")a=i()/45 b=i()/45 r=i()for y=r,-r,-1 do for x=-r,r do c=m.atan2(y,x)/m.pi*4 c=c<0 and c+8 or c k=1+m.modf(c+.5)io.write(x==0 and y==0 and''o''or c>=a and c<=b and(''-/|//-/|//-''):sub(k,k)or c==0 and b==8 and''-''or'' '')end print()end
Entrada: 45-360 4
///|||/// ///|||// ////|// --//|/ ----o---- --//|//-- ////|//// ///|||/// ///|||///
Capaz de manejar ángulos impares
Entrada: 15-75 8
|///// |////// |////// |////// /////// |//////- ////--- //- o
MATLAB 7.8.0 (R2009a) - 168 163 162 caracteres
Partiendo de la respuesta de Jacob e inspirado por el uso de Gwell de cualquier carácter que no sea un espacio en blanco para completar el arco, logré la siguiente solución:
[w x r]=strread(input('''',''s''),''%d-%d%d'');
l=''o -/|/-/|/-'';
X=meshgrid(-r:r);
T=atan2(-X'',X)*180/pi;
T=T+(T<=-~w)*360;
T(T>x|T<w)=-1;
T(r+1,r+1)=-90;
disp(l(fix(3+T/45)))
Y algunos resultados de prueba:
>> arc
0-135 4
/||||////
/|||///-
/||//--
/|/---
o----
Podría reducirlo aún más a 156 caracteres eliminando la llamada a disp
, pero esto agregaría un ans =
extra ans =
precede a la salida (lo que podría violar las reglas de formato de salida).
Aún así, siento que hay algunas maneras de reducir esto aún más. ;)
Perl - 388 caracteres
Como no sería justo plantear un desafío que no pude resolver yo mismo, aquí hay una solución que utiliza la sustitución de cadenas en lugar de las funciones trigonométricas, y hace un uso intensivo de la capacidad de Perl de su vecindario amigable para tratar las palabras desnudas como cadenas. Es necesariamente un poco largo, pero quizás interesante por el bien de la singularidad:
($x,$y,$r)=split//D/,<>;for(0..$r-1){$t=$r-1-$_;
$a.=L x$_.D.K x$t.C.J x$t.B.I x$_."/n";
$b.=M x$t.F.N x$_.G.O x$_.H.P x$t."/n"}
$_=$a.E x$r.o.A x$r."/n".$b;$x/=45;$y/=45;$S='' '';
sub A{$v=$_[0];$x==$v||$y==$v?$_[1]:$x<$v&&$y>$v?x:$S}
sub B{$x<=$_[0]&&$y>$_[0]?x:$S}
@a=!$x||$y==8?''-'':$S;
push@a,map{A$_,''//'.qw(- / | //)[$_%4]}1..7;
push@a,!$x?x:$S,map{B$_}1..7;
eval"y/A-P/".(join'''',@a)."/";print
Todas las nuevas líneas son opcionales. Es bastante sencillo:
- Agarra la entrada del usuario.
- Construye las partes superior (
$a
) e inferior ($b
) del patrón. - Construye el patrón completo (
$_
). - Defina una
sub A
para obtener el carácter de relleno para un ángulo. - Defina un
sub B
para obtener el carácter de relleno para una región. - Construye una matriz (
@a
) de caracteres de sustitución usandoA
yB
- Realice la sustitución e imprima los resultados.
El formato generado se ve así, para R
= 4:
DKKKCJJJB LDKKCJJBI LLDKCJBII LLLDCBIII EEEEoAAAA MMMFGHPPP MMFNGOHPP MFNNGOOHP FNNNGOOOH
Donde AH
denota ángulos y IP
denota regiones.
(Es cierto que probablemente esto podría ser un juego de golf adicional. Las operaciones en @a
me dieron una salida incorrecta cuando se escribía en una lista, probablemente teniendo algo que ver con la forma en que el map
juega con $_
).