Círculos de texto

10

Encontre uma maneira de fazer círculos de um determinado raio usando caracteres em um console. Especifique o nome e o tamanho da fonte. Além disso, forneça pelo menos um exemplo da saída.

Por exemplo:

Entrada:

3

Resultado:

   ******
 **      **
**        **
*          *
**        **
 **      **
   ******

... Bem, algo mais bonito do que aquele "círculo desenhado à mão" com um raio de 3.


Pergunta bônus: Elipses. :)

Mateen Ulhaq
fonte
Curiosamente, o meu círculo de raio-3 é exatamente idêntico ao seu, sem sequer tentar :)
mellamokb
Talvez a parte da fonte possa ser esclarecida. Copiadas aqui, todas as fontes serão iguais; o mesmo para o tamanho da fonte.
usuário desconhecido

Respostas:

5

Javascript (360)

function c(r){var f=1.83;var e=2*Math.PI/(r*r*r*r*r);var s=r*2+1;var g=Array(s);for(var i=0;i<s;i++){g[i]=Array(Math.round(s*f))};for(var i=0;i<=2*Math.PI;i+=e) {var x=Math.round(f*r*Math.cos(i)+f*r);var y=Math.round(r*Math.sin(i))+r;g[y][x]=1;}for(var j=0;j<g.length;j++){for(var i=0;i<g[j].length;i++)document.write((g[j][i]==1)?'*':' ');document.writeln()}}

http://jsfiddle.net/YssSb/3/ ( fé um fator de correção para a relação altura da linha / largura da fonte. Se você usar uma configuração de fonte quadrada, por exemplo, defina line-height = font-size, você poderá definir f = 1 e obtenha círculos "quadrados" ou defina farbitrariamente as elipses.)

Saída para 3 (de maneira interessante, acidentalmente exatamente da mesma forma que OP), 5, 15:

   ******    
 **      **  
**        ** 
*          * 
**        ** 
 **      **  
   ******    

     *********      
   ***       ****   
 ***            **  
**               ** 
*                 * 
*                 * 
*                 * 
**               ** 
 ***            **  
   ***       ****   
     *********      

                    ***************                      
               ******             ******                 
            ****                       *****             
          ***                              ***           
        ***                                  ***         
      ***                                      ***       
     **                                          **      
    **                                            **     
   **                                              **    
  **                                                **   
 **                                                  **  
 *                                                    *  
**                                                    ** 
*                                                      * 
*                                                      * 
*                                                      * 
*                                                      * 
*                                                      * 
**                                                    ** 
 *                                                    *  
 **                                                  **  
  **                                                **   
   **                                              **    
    **                                            **     
     **                                          **      
      ***                                      ***       
        ***                                  ***         
          ***                              ***           
            ****                       *****             
               ******             ******                 
                    ***************                      
mellamokb
fonte
Círculos bonitos que você tem. ;)
Mateen Ulhaq 15/03/11
6

um círculo de Bresenham em Scala (35)

O algoritmo Bresenham - possui 2 pontos principais:

  • trabalha sem pecado / cosina.
  • você calcula apenas ¼ * ½ círculo, os outros pontos são encontrados pelo espelhamento.

Como fazer isso:

       2 1  
     DCBABCD
   GFE EFG
  IJ y | ---- JI
 GJ / JG
 F / | F
DE r / | ED
C / | C
B 4 | / | B 3
A + ------- A
B 4 'x B 3'
CC
ATO
 FF
 GJ JG
  IJ JI
   GFE EFG
     DCBABCD
       2'1 ' 
  • Apenas calculamos os números de A no zenit para I.
    • O ponto I está em 45 °, definido por x == y.
    • O ponto zero é onde está o +.
    • OA no zenit é o ponto (x = 0, y = r), r = raio.
    • Para desenhar um círculo fechado, movemos no sentido horário (++ x), que é para a direita (x + = 1) ou para baixo até o próximo ponto (y- = 1).
    • todos os pontos (x, y) do círculo estão afastados do centro. Pitágoras diz, r² = x² + y².
    • Isso cheira a raiz quadrada e equações com 2 soluções, mas cuidado!
    • começamos em A e queremos saber se pintaremos o próximo ponto abaixo ou o ponto abaixo à direita.
  • calculamos para ambos os pontos (x² + y²) e construímos para ambos a diferença para r² (que permanece, é claro, constante).
    • Uma vez que a diferença pode ser negativa, tiramos os abdominais dela.
    • então olhamos qual ponto está mais próximo do resultado (r²) e o ipso menor.
    • dependendo disso, desenhamos o vizinho direito ou inferior.
  • o ponto tão encontrado
    • 1 x, y é espelhado
    • 2 -x, y para a esquerda
    • 3 y, x na diagonal
    • 4 -y, x daí para a esquerda
  • todos esses pontos são espelhados novamente para o sul
    • 1 'x, -y
    • 2 '-x, -y
    • 3 'y, -x
    • 4 '-y, -x pronto.

Isso não é código de golfe, mas todos esses números no topo das soluções existentes me fizeram pensar que era, então eu passei um tempo inútil jogando minha solução no golfe. Por isso, adicionei também um número inútil no topo. É 11 vezes o Pi arredondado.

object BresenhamCircle extends App {
    var count = 0
    val r = args(0).toInt
    // ratio > 1 means expansion in horizontal direction
    val ratio = args(1).toInt
    val field = ((0 to 2 * r).map (i=> (0 to 2 * r * ratio).map (j=> ' ').toArray)).toArray
    def square (x: Int, y: Int): Int = x * x + y * y
    def setPoint (x: Int, y: Int) {
        field (x)(y*ratio) = "Bresenham"(count)
        field (y)(x*ratio) = "Bresenham"(count)
    }
    def points (x: Int, y: Int)
    {
        setPoint (r + x, r + y)
        setPoint (r - x, r + y)
        setPoint (r + x, r - y)
        setPoint (r - x, r - y)
    }
    def bresenwalk () {
        var x = 0;
        var y = r;
        val rxr = r * r
        points (x, y);
        do 
        {
            val (dx, dy) = { if (math.abs (rxr - square ((x+1), y)) < math.abs (rxr - square (x, (y-1))))
                (1, 0)
            else
                (0, -1) 
            }
            count = (count + 1) % "Bresenham".length
            x += dx
            y += dy
            points (x, y)
        }while ((x <= y))
    }
    bresenwalk ()
    println (field.map (_.mkString ("")).mkString ("\n"))
}

A questão da fonte é decidida pelo servidor de sites e pelas configurações do seu navegador. Agora, que eu estou olhando, é

'Droid Sans Mono',Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif

O tamanho da fonte é 12 px. Informações bastante inúteis, se você me perguntar, mas quem faz?

Bônus: elipses e saída de amostra:

A invocação é

    scala BresenhamCircle SIZE RATIO

por exemplo

    scala BresenhamCircle 10 2
              s e r B r e s              
          h n e           e n h          
      e m a                   a m e      
    e r                           r e    
    m                               m    
  h a                               a h  
  n                                   n  
s e                                   e s
e                                       e
r                                       r
B                                       B
r                                       r
e                                       e
s e                                   e s
  n                                   n  
  h a                               a h  
    m                               m    
    e r                           r e    
      e m a                   a m e      
          h n e           e n h          
              s e r B r e s           

A ratio of 2 will print a circular shape for most fonts which happen to be about twice as tall than wide. To compensate for that, we widen by 2. 
# As smaller value than 2 only 1 is available: 

scala BresenhamCircle 6 1
    erBre    
  aes   sea  
 ah       ha 
 e         e 
es         se
r           r
B           B
r           r
es         se
 e         e 
 ah       ha 
  aes   sea  
    erBre    

# widening it has more freedom:

scala BresenhamCircle 12 5
                                             s    e    r    B    r    e    s                                             
                              a    h    n    e                             e    n    h    a                              
                         B    m                                                           m    B                         
                    e    r                                                                     r    e                    
               e    s                                                                               s    e               
          B    r                                                                                         r    B          
     a    m                                                                                                   m    a     
     h                                                                                                             h     
     n                                                                                                             n     
s    e                                                                                                             e    s
e                                                                                                                       e
r                                                                                                                       r
B                                                                                                                       B
r                                                                                                                       r
e                                                                                                                       e
s    e                                                                                                             e    s
     n                                                                                                             n     
     h                                                                                                             h     
     a    m                                                                                                   m    a     
          B    r                                                                                         r    B          
               e    s                                                                               s    e               
                    e    r                                                                     r    e                    
                         B    m                                                           m    B                         
                              a    h    n    e                             e    n    h    a                              
                                             s    e    r    B    r    e    s     

Eu restringi o parâmetro ratio para Int para simplificá-lo, mas ele pode ser facilmente ampliado para permitir flutuações.

Usuário desconhecido
fonte
sua contagem de caracteres (sem novas linhas desnecessários) é na verdade 34,557519189487725623089077216075 :) BTW: solução muito agradável, +1
Cristian Lupascu
4

Python (172)

172 caracteres, incluindo as duas novas linhas obrigatórias. Usa o algoritmo de Bresenham para curvas cônicas (sem divisões ou multiplicações); ele gera apenas círculos para fontes quadradas, mas deve ser isento de efeitos de escada ( ou seja, sempre tem a mesma largura).

y=input();t=[y*[' ']for x in range(y)];x=0;y-=1;p=3-2*y
while x<=y:t[x][y]=t[y][x]='*';n,y=((x-y+1,y-1),(x,y))[p<0];p+=4*n+6;x+=1
for s in t[::-1]+t:print"".join(s[::-1]+s)

Não é muito bonito, mas bem, pensei em tentar.

  ****
 *    *
*      *
*      *
*      *
*      *
 *    *
  ****

          ********
       ***        ***
      *              *
     *                *
    *                  *
   *                    *
  *                      *
 *                        *
 *                        *
 *                        *
*                          *
*                          *
*                          *
*                          *
*                          *
*                          *
*                          *
*                          *
 *                        *
 *                        *
 *                        *
  *                      *
   *                    *
    *                  *
     *                *
      *              *
       ***        ***
          ********

Editar : erro de digitação, substituído disso com divisão .

sam hocevar
fonte
3

Perl (92)

Eu fui para a “questão bônus” e a fiz explorar a proporção do personagem para desenhar elipses :)

($w)=@ARGV;for$x(-$w..$w){$p.=abs($x*$x+$_*$_-$w*$w)<$w?'*':$"for(-$w..$w);$p.=$/;}print $p;

Exemplo de saídas:

>perl circle.pl 3
  ***
 *   *
*     *
*     *
*     *
 *   *
  ***

>perl circle.pl 5
   *****
  *     *
 *       *
*         *
*         *
*         *
*         *
*         *
 *       *
  *     *
   *****

>perl circle.pl 8
      *****
    **     **
   *         *
  *           *
 *             *
 *             *
*               *
*               *
*               *
*               *
*               *
 *             *
 *             *
  *           *
   *         *
    **     **
      *****
Timwi
fonte
+1 em 3º lugar, mas as formas não parecem tão boas quanto nas outras respostas. (Ainda melhor do que o que eu poderia programar, é claro :).)
Mateen Ulhaq
3

Haskell ( 112 109)

g n=map(zipWith(?)f.repeat)f where x?y|abs(x^2+y^2-n^2)<n='*'|0<1=' ';f=[-n..n]
main=interact$unlines.g.read

Isso funciona verificando se x² + y² - r² <n para todos os pontos. Todos os pontos em que isso é verdade são estrelas, todos os outros são espaços em branco.

Exemplos:

$ eco 3 | runhaskell circ.hs
  ***  
 * * 
* *
* *
* *
 * * 
  ***  
$ eco 10 | runhaskell circ.hs
       *******       
     ** **     
    * *    
   * *   
  * *  
 * * 
 * * 
* *
* *
* *
* *
* *
* *
* *
 * * 
 * * 
  * *  
   * *   
    * *    
     ** **     
       *******       

Veja aqui um grande exemplo: http://www.ideone.com/t042u

FUZxxl
fonte
3

Python, 180 caracteres

Esse código faz círculos se a fonte for quadrada. É muito fácil modificar para gerar elipses nominais, se você conhece a proporção altura / largura da fonte.

import math
r=input()
d=2*r+1
c=[' '*d]*d
for a in xrange(9*d):f=math.pi*a/r/9; x=int(r+r*math.sin(f)+.5);y=int(r+r*math.cos(f)+.5);c[y]=c[y][:x]+'*'+c[y][x+1:]
for s in c:print s

Exemplos:

4:
  *****  
 **   ** 
**     **
*       *
*       *
*       *
**     **
 **   ** 
  *****  

7:
     *****     
   **     **   
  **       **  
 **         ** 
**           **
*             *
*             *
*             *
*             *
*             *
**           **
 **         ** 
  **       **  
   **     **   
     *****     
Keith Randall
fonte
Você poderia postar uma amostra?
Mateen Ulhaq 12/03/11
+1 Mas o 2º lugar ... Mas estava perto.
Mateen Ulhaq
0

C, 127 bytes, Nome da fonte: Arial Super Bold

#include<math.h>
main(){int r=10,c=r*2+1,q=c*c,d;for(;q--;)d=hypot(r-q%c,r-q/c),printf("%c%s",d>r-4&&d<=r?42:32,q%c?"":"\n");}

Resultado:

      *********      
    *************    
   ***************   
  *****************  
 ******       ****** 
 *****         ***** 
*****           *****
****             ****
****             ****
****             ****
****             ****
****             ****
****             ****
****             ****
*****           *****
 *****         ***** 
 ******       ****** 
  *****************  
   ***************   
    *************    
      *********      
Johan du Toit
fonte