Code Golf - π dia


95

O desafio

Diretrizes para código-golfe em SO

O código mais curto por contagem de caracteres para exibir uma representação de um círculo de raio Rusando o *caractere, seguido por uma aproximação de π.

A entrada é um único número R,.

Como a maioria dos computadores parece ter uma proporção de quase 2: 1, você só deve produzir linhas onde yfor estranho. Isso significa que quando Rfor estranho, você deve imprimir R-1linhas. Há um novo caso de teste para R=13esclarecer.

por exemplo.

Input
    5
Output      Correct                          Incorrect

        3    *******                    4      *******
        1   *********                   2     *********
       -1   *********                   0    ***********
       -3    *******                   -2     *********
           2.56                        -4      *******
                                            3.44

Editar: devido à confusão generalizada causada por valores ímpares de R, quaisquer soluções que passarem nos 4 casos de teste fornecidos abaixo serão aceitas

A aproximação de π é dada dividindo duas vezes o número de *caracteres por .
A aproximação deve ser correta para pelo menos 6 dígitos significativos.
Esquerda ou à direita zeros são permitidas, de modo que, por exemplo, qualquer uma das 3, 3.000000, 003é aceite para as entradas de 2e 4.

A contagem de códigos inclui entrada / saída (ou seja, programa completo).

Casos de teste

Input
    2
Output
     *** 
     *** 
    3.0

Input
    4
Output
      *****  
     ******* 
     ******* 
      *****  
    3.0

Input
    8
Output
         *******     
      *************  
     *************** 
     *************** 
     *************** 
     *************** 
      *************  
         *******     
    3.125

Input
    10
Output
          *********      
       ***************   
      *****************  
     ******************* 
     ******************* 
     ******************* 
     ******************* 
      *****************  
       ***************   
          *********      
    3.16

Caso de teste bônus

Input
    13
Output

           *************       
        *******************    
       *********************   
      ***********************  
     ************************* 
     ************************* 
     ************************* 
     ************************* 
      ***********************  
       *********************   
        *******************    
           *************                                          
    2.98224852071

Você pode querer esclarecer se a "entrada" está na linha de comando ou em stdin.
Greg Hewgill

1
@Greg Hewgill, Sinta-se à vontade para escolher o que for mais conveniente para o idioma que você está usando :)
John La Rooy

@Greg Hewgill, Algumas (ou seja, muito poucas) implementações de linguagem de programação não têm noção de "linha de comando".
Joey Adams,

1
Percebo que poucas das respostas seguem a regra de apenas colocar linhas onde y é estranho. Dado um valor ímpar de r (não mostrado nos casos de teste), a maioria produzirá linhas onde y é par!
MtnViewMark

6
Desafio de abuso de regra: Faça um código mais curto do que o código de qualquer outra pessoa, suportando apenas os 4 casos de teste necessários.
Brian,

Respostas:


15

In dc: 88 e 93 93 94 96 102 105 129 138 141 chars

Por precaução, estou usando OpenBSD e algumas extensões supostamente não portáteis neste momento.

93 chars. Isso é baseado na mesma fórmula da solução FORTRAN (resultados ligeiramente diferentes dos casos de teste). Calcula X ^ 2 = R ^ 2-Y ^ 2 para cada Y

[rdPr1-d0<p]sp1?dsMdd*sRd2%--
[dd*lRr-vddlMr-32rlpxRR42r2*lpxRRAP4*2+lN+sN2+dlM>y]
dsyx5klNlR/p

88 chars. Solução iterativa. Corresponde a casos de teste. Para cada X e Y verifica se X ^ 2 + Y ^ 2 <= R ^ 2

1?dsMdd*sRd2%--sY[0lM-[dd*lYd*+lRr(2*d5*32+PlN+sN1+dlM!<x]dsxxAPlY2+dsYlM>y]
dsyx5klNlR/p

Para correr dc pi.dc.

Aqui está uma versão anotada mais antiga:

# Routines to print '*' or ' '. If '*', increase the counter by 2
[lN2+sN42P]s1
[32P]s2
# do 1 row
# keeping I in the stack
[
 # X in the stack
 # Calculate X^2+Y^2 (leave a copy of X)
 dd*lYd*+ 
 #Calculate X^2+Y^2-R^2...
 lR-d
 # .. if <0, execute routine 1 (print '*')
 0>1
 # .. else execute routine 2 (print ' ')
 0!>2 
 # increment X..
 1+
 # and check if done with line (if not done, recurse)
 d lM!<x
]sx
# Routine to cycle for the columns
# Y is on the stack
[
  # push -X
  0lM- 

  # Do row
  lxx 
  # Print EOL
  10P
  # Increment Y and save it, leaving 2 copies
  lY 2+ dsY 
  # Check for stop condition
  lM >y
]sy
# main loop
# Push Input value
[Input:]n?
# Initialize registers
# M=rows
d sM
# Y=1-(M-(M%2))
dd2%-1r-sY
# R=M^2
d*sR
# N=0
0sN
[Output:]p
# Main routine
lyx
# Print value of PI, N/R
5klNlR/p

1
Não funciona com o Linux DC, mas posso confirmar que funciona no openbsd . Impressionante!
John La Rooy,

@Carlos, sim o (operador com certeza é útil. pena que permanece sem implementação no dc que vem com o linux
John La Rooy

@gnibbler - "Uma reescrita completa do comando dc usando as rotinas de grande número bn (3) apareceu pela primeira vez no OpenBSD 3.5." Eu não sabia disso. Alguns bons novos operadores estão incluídos, mas eles estão marcados como "extensões não portáteis".
Carlos Gutiérrez

Sim, o (só o operador tem permissão para eliminar 6 AVCs!
Dan Andreatta

119

C: 131 caracteres

(Baseado na solução C ++ de Joey)

main(i,j,c,n){for(scanf("%d",&n),c=0,i|=-n;i<n;puts(""),i+=2)for(j=-n;++j<n;putchar(i*i+j*j<n*n?c++,42:32));printf("%g",2.*c/n/n);}

(Altere i|=-npara i-=npara remover o suporte de casos de número ímpar. Isso apenas reduz a contagem de caracteres para 130.)

Como um círculo:

      main(i,j,
   c,n){for(scanf(
  "%d",&n),c=0,i=1|
 -n;i<n;puts(""),i+=
 0x2)for(j=-n;++j<n;
 putchar(i*i+j*j<n*n
 ?c++,0x02a:0x020));
  printf("%g",2.*c/
   n/n);3.1415926;
      5358979;}

1
Gosto de como você adicionou círculos ao código para transformá-lo em um círculo. +000 seria preferível?
Potatoswatter

parabéns, j * j ++ é um comportamento indefinido
sellibitze

1
não seria apenas um personagem ...?
Ponkadoodle

1
Como você main()recebe quatro intargumentos?
David R Tribble,

2
@Load: 5.1.2.2.1 / 1: A função chamada na inicialização do programa é nomeada main. Deve ser definido ... ou de alguma outra maneira definida pela implementação . Isso porque a implementação pode aceitar este formulário.
kennytm

46

XSLT 1.0

Apenas por diversão, aqui está uma versão XSLT. Não é realmente um material de código de golfe, mas resolve o problema de uma maneira estranha e funcional do tipo XSLT :)

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" >
  <xsl:output method="html"/>

  <!-- Skip even lines -->
  <xsl:template match="s[@y mod 2=0]">
    <xsl:variable name="next">
      <!-- Just go to next line.-->
      <s R="{@R}" y="{@y+1}" x="{-@R}" area="{@area}"/>
    </xsl:variable>
    <xsl:apply-templates select="msxsl:node-set($next)"/>
  </xsl:template>

  <!-- End of the line?-->
  <xsl:template match="s[@x &gt; @R]">
    <xsl:variable name="next">
      <!-- Go to next line.-->
      <s R="{@R}" y="{@y+1}" x="{-@R}" area="{@area}"/>
    </xsl:variable><!-- Print LF-->&#10;<xsl:apply-templates 
      select="msxsl:node-set($next)"/>
  </xsl:template>

  <!-- Are we done? -->
  <xsl:template match="s[@y &gt; @R]">
    <!-- Print PI approximation -->
    <xsl:value-of select="2*@area div @R div @R"/>
  </xsl:template>

  <!-- Everything not matched above -->
  <xsl:template match="s">
    <!-- Inside the circle?-->
    <xsl:variable name="inside" select="@x*@x+@y*@y &lt; @R*@R"/>
    <!-- Print "*" or " "-->
    <xsl:choose>
      <xsl:when test="$inside">*</xsl:when>
      <xsl:otherwise>&#160;</xsl:otherwise>
    </xsl:choose>

    <xsl:variable name="next">
      <!-- Add 1 to area if we're inside the circle. Go to next column.-->
      <s R="{@R}" y="{@y}" x="{@x+1}" area="{@area+number($inside)}"/>
    </xsl:variable>
    <xsl:apply-templates select="msxsl:node-set($next)"/>
  </xsl:template>

  <!-- Begin here -->
  <xsl:template match="/R">
    <xsl:variable name="initial">
      <!-- Initial state-->
      <s R="{number()}" y="{-number()}" x="{-number()}" area="0"/>
    </xsl:variable>
    <pre>
      <xsl:apply-templates select="msxsl:node-set($initial)"/>
    </pre>
  </xsl:template>
</xsl:stylesheet>

Se você quiser testá-lo, salve-o pi.xslte abra o seguinte arquivo XML no IE:

<?xml version="1.0"?> 
<?xml-stylesheet href="pi.xslt" type="text/xsl" ?> 
<R> 
  10 
</R> 

42
meus <eyes> </eyes>! Os óculos não <do> nada </do>!
Jimmy,

1
Droga! Receio que você tenha vencido minha solução HyperCard para exclusividade: D
Joey Adams

7
Não acredito que você disse "abra ... IE"
harpo

Heh, sim, antigamente tínhamos apenas IE e XML com XSLT era a solução para todos os nossos problemas. Bons velhos tempos! :)
Danko Durbić

XSL versão 1.0 uau, lembro-me de esperar ansiosamente pela versão 2, mas quando ela saiu, eu já tinha seguido em frente.
gradbot,

35

Perl, 95 96 99 106 109 110 119 personagens:

$t+=$;=1|2*sqrt($r**2-($u-2*$_)**2),say$"x($r-$;/2).'*'x$;for 0..
($u=($r=<>)-1|1);say$t*2/$r**2

(A nova linha pode ser removida e existe apenas para evitar uma barra de rolagem)

Yay! Versão do círculo!

    $t+=$;=
 1|2*sqrt($r**
2-($u-2*$_)**2)
,say$"x($r-$;/2
).'*'x$;for 0..
($u=($r=<>)-1|1
 );$pi=~say$t*
    2/$r**2

Para os não iniciados, a versão longa:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

# Read the radius from STDIN
my $radius = <>;

# Since we're only printing asterisks on lines where y is odd,
# the number of lines to be printed equals the size of the radius,
# or (radius + 1) if the radius is an odd number.
# Note: we're always printing an even number of lines.
my $maxline = ($radius - 1) | 1;

my $surface = 0;

# for ($_ = 0; $_ <= $maxline; $_++), if you wish
for (0 .. $maxline) {
    # First turn 0 ... N-1 into -(N/2) ... N/2 (= Y-coordinates),
    my $y = $maxline - 2*$_;

    # then use Pythagoras to see how many stars we need to print for this line.
    # Bitwise OR "casts" to int; and: 1 | int(2 * x) == 1 + 2 * int(x)
    my $stars = 1 | 2 * sqrt($radius**2-$y**2);
    $surface += $stars;    

    # $" = $LIST_SEPARATOR: default is a space,
    # Print indentation + stars 
    # (newline is printed automatically by say)
    say $" x ($radius - $stars/2) . '*' x $stars;
}

# Approximation of Pi based on surface area of circle:
say $surface*2/$radius**2;

6
Esse é de longe o código mais ilegível que já vi em toda a minha vida
Chris Marisic,

13
Acho que você nunca viu o APL então.
Peter Wone

5
@Chris Marisic: Você checou as outras questões / tópicos marcados code-golf? :) Eu vi muito mais exemplos ilegíveis.
BalusC de

3
@Peter: Ao contrário da maioria, eu vi e escrevi APL. Demora algumas semanas para se acostumar com seus caracteres especiais, mas depois disso pode ser bastante legível. Mesmo depois de algumas décadas para se acostumar, o Perl ainda é muito pior.
Jerry Coffin,

1
111 caracteres,$r=<>;$t+=$n=1+2*int sqrt($r**2-($u-2*$_)**2),print$"x($r-$n/2).'*'x$n.$/for(0..($u=$r-1+$r%2));print$t*2/$r**2
Hasturkun

25

FORTRAN - 101 caracteres

$ f95 piday.f95 -o piday && echo 8 | ./piday


READ*,N
DO I=-N,N,2
M=(N*N-I*I)**.5
PRINT*,(' ',J=1,N-M),('*',J=0,M*2)
T=T+2*J
ENDDO
PRINT*,T/N/N
END


    READ*,N
  K=N/2*2;DO&
 I=1-K,N,2;M=&
(N*N-I*I)**.5;;
PRINT*,(' ',J=&
1,N-M),('*',J=&
0,M*2);T=T+2*J;
 ENDDO;PRINT*&
  ,T/N/N;END;
    !PI-DAY

Espere, achei que a formatação fosse importante no Fortran. Você tem letras na coluna 1!
Joel

A maioria das pessoas ainda está presa no Fortan77 pelo que vi.
Joel

8
Eu gosto de como a versão circular se parece com a Estrela da Morte.
mskfisher de

22

Código de máquina x86: 127 bytes

Intel Assembler: 490 chars

    mov si,80h
    mov cl,[si]
    jcxz ret
    mov bx,10
    xor ax,ax
    xor bp,bp
    dec cx
  a:mul bx
    mov dl,[si+2]
    sub dl,48
    cmp dl,bl
    jae ret
    add ax,dx
    inc si
    loop a
    mov dl,al
    inc dl
    mov dh,al
    add dh,dh
    mov ch,dh
    mul al
    mov di,ax
  x:mov al,ch
    sub al,dl
    imul al
    mov si,ax
    mov cl,dh
  c:mov al,cl
    sub al,dl
    imul al
    add ax,si
    cmp ax,di
    mov al,32
    ja y
    or al,bl
    add bp,2
  y:int 29h
    dec cl
    jnz c
    mov al,bl
    int 29h
    mov al,13
    int 29h
    sub ch,2
    jnc x
    mov ax,bp
    cwd
    mov cl,7
  e:div di
    cmp cl,6
    jne z
    pusha
    mov al,46
    int 29h
    popa
  z:add al,48
    int 29h
    mov ax,bx
    mul dx
    jz ret
    dec cl
    jnz e
    ret

Esta versão também lida com o caso de teste bônus e tem 133 bytes:

    mov si,80h
    mov cl,[si]
    jcxz ret
    mov bx,10
    xor ax,ax
    xor bp,bp
    dec cx
  a:mul bx
    mov dl,[si+2]
    sub dl,48
    cmp dl,bl
    jae ret
    add ax,dx
    inc si
    loop a
    mov dl,al
    rcr dl,1
    adc dl,dh
    add dl,dl
    mov dh,dl
    add dh,dh
    dec dh
    mov ch,dh
    mul al
    mov di,ax
  x:mov al,ch
    sub al,dl
    imul al
    mov si,ax
    mov cl,dh
  c:mov al,cl
    sub al,dl
    imul al
    add ax,si
    cmp ax,di
    mov al,32
    jae y
    or al,bl
    add bp,2
  y:int 29h
    dec cl
    jnz c
    mov al,bl
    int 29h
    mov al,13
    int 29h
    sub ch,2
    jnc x
    mov ax,bp
    cwd
    mov cl,7
  e:div di
    cmp cl,6
    jne z
    pusha
    mov al,46
    int 29h
    popa
  z:add al,48
    int 29h
    mov ax,bx
    mul dx
    jz ret
    dec cl
    jnz e
    ret

12
Eu amo StackOverflow!
Zengr

2
É interessante que algumas das linguagens de alto nível têm contagens de caracteres mais curtas do que o binário que isso produz.
Colin Valliant,

3
@Alcari: Se você incluísse todo o código nas bibliotecas que as linguagens de nível superior usam, a contagem de caracteres seria significativamente maior. Em assembler, fazer printf("%f",a/b)não é trivial, não há uma única instrução para fazer isso, e minha implementação acima assume que 0 <= a / b <10 e que a operação é uma divisão e que a e b são inteiros.
Skizz de

19

Python: 101 104 107 110 caracteres

Baseado na outra versão do Python de Nicholas Riley.

r=input()
t=0
i=1
exec"n=1+int((2*i*r-i*i)**.5)*2;t+=2.*n/r/r;print' '*(r-n/2)+'*'*n;i+=2;"*r
print t

Créditos a AlcariTheMad por um pouco de matemática.


Ah, os ímpares são indexados com o zero no meio, explica tudo.

Python bônus: 115 caracteres (rapidamente hackeados)

r=input()
t=0
i=1
while i<r*2:n=1+int((2*i*r-i*i)**.5)*2;t+=2.*n/r/r;print' '*(r-n/2)+'*'*n;i+=2+(r-i==2)*2
print t

Uau, sim, '+' bate -1 e, qualquer dia. Mais uma técnica que tirei da cabeça porque quase nunca é a coisa certa a fazer :-)
Nicholas Riley

Eu usei C no passado e nunca olhei para Python. Esses 104 caracteres são mais legíveis do que o C ++ acima. Surpreendente. Talvez eu deva aprender Python ...
Dean Rather,

@Dean: um dos principais objetivos do Python é ser fácil de ler e escrever.
Colin Valliant

Você já pensou em usar exec com sua resposta de 104 caracteres também? :)
John La Rooy,

Eu precisaria lançar minha própria compressão - zlib, marshalling, etc, tudo saiu maior do que o código real.
lunixbochs

12

Powershell, 119 113 109 caracteres

($z=-($n=$args[($s=0)])..$n)|?{$_%2}|%{$l="";$i=$_
$z|%{$l+=" *"[$i*$i+$_*$_-lt$n*$n-and++$s]};$l};2*$s/$n/$n

e aqui está uma versão mais bonita:

( $range = -( $R = $args[ ( $area = 0 ) ] ) .. $R ) | 
  where { $_ % 2 } |
  foreach {
    $line = ""
    $i = $_
    $range | foreach {
        $line += " *"[ $i*$i + $_*$_ -lt $R*$R -and ++$area ]
    }
    $line
 }
 2 * $area / $R / $R

@Thor: Espero que não, mas deve ser a coisa mais feia que já escrevi :)
Danko Durbić

3
Obrigado por essa versão mais bonita =)
Thor Hovden

10

HyperTalk: 237 caracteres

O recuo não é necessário nem contado. É adicionado para maior clareza. Observe também que o HyperCard 2.2 aceita os operadores relacionais não ASCII que usei.

function P R
  put""into t
  put 0into c
  repeat with i=-R to R
    if i mod 2≠0then
      repeat with j=-R to R
        if i^2+j^2≤R^2then
          put"*"after t
          add 1to c
        else
          put" "after t
        end if
      end repeat
      put return after t
    end if
  end repeat
  return t&2*c/R/R
end P

Como o HyperCard 2.2 não suporta stdin / stdout, uma função é fornecida em seu lugar.


1
Hypercard, Sr. Adams? Seriamente? Isso é altamente inesperado.
Kawa

1
@Kawa: Foi por isso que o postei :) Além disso, o code golf é uma boa maneira de construir uma suíte de testes caso eu decida escrever um interpretador HyperTalk no futuro.
Joey Adams,

Hah! Eu gostaria de ver isso, XD
Kawa

Se você decidir escrever para esse intérprete, ou se quiser trabalhar em um já existente, me avise e posso acrescentar uma menção sobre isso no hypercard.org e eu ficaria curioso para saber como vai ser :-)
uliwitness

10

C #: 209 202 201 caracteres:

using C=System.Console;class P{static void Main(string[]a){int r=int.Parse(a[0]),s=0,i,x,y;for(y=1-r;y<r;y+=2){for(x=1-r;x<r;s+=i)C.Write(" *"[i=x*x+++y*y<=r*r?1:0]);C.WriteLine();}C.Write(s*2d/r/r);}}

Não minimizado:

using C = System.Console;
class P {
  static void Main(string[] arg) {
    int r = int.Parse(arg[0]), sum = 0, inside, x, y;
    for (y = 1 - r; y < r; y += 2) {
      for (x = 1 - r; x < r; sum += inside)
        C.Write(" *"[inside = x * x++ + y * y <= r * r ? 1 : 0]);
      C.WriteLine();
    }
    C.Write(sum * 2d / r / r);
  }
}

Não conheço muito C #, mas você não deveria conseguir usar string[]ae 1-r(em vez de -1+r)?
kennytm

@Kenny: Você está certo. :) Isso salva três personagens, e então consegui me livrar de mais cinco.
Guffa

Avistei aquela primeira coisa, perdi totalmente a -r+1coisa.
Dykam

4
Além disso, manchado x*xx+++y*ytambém, mas é uma coisa louca de dissecar à primeira vista.
Dykam

Tomei a liberdade de eliminar outro byte ;-)
Joey

10

Haskell 139 145 147 150 230 chars:

x True=' ';x _='*'
a n=unlines[[x$i^2+j^2>n^2|j<-[-n..n]]|i<-[1-n,3-n..n]]
b n=a n++show(sum[2|i<-a n,i=='*']/n/n)
main=readLn>>=putStrLn.b

Lidando com os números ímpares: 148 caracteres:

main=do{n<-readLn;let{z k|k<n^2='*';z _=' ';c=[[z$i^2+j^2|j<-[-n..n]]|i<-[1,3..n]];d=unlines$reverse c++c};putStrLn$d++show(sum[2|i<-d,i=='*']/n/n)}

150 caracteres: (com base na versão C.)

a n=unlines[concat[if i^2+j^2>n^2then" "else"*"|j<-[-n..n]]|i<-[1-n,3-n..n]]
main=do n<-read`fmap`getLine;putStr$a n;print$2*sum[1|i<-a n,i=='*']/n/n

230 caracteres:

main = faça {r <-read`fmap`getLine; deixe {p = putStr; d = 2 / fromIntegral r ^ 2; lyn = deixe cmx = if x> r then p "\ n" >> retorne m else se x * x + y * y <r * r então p "*" >> c (m + d) (x + 1) else p "" >> cm (x + 1) in if y> r então imprime n else cn (-r) >> = l (y + 2)}; l (1-r`mod`2-r) 0}

Não minimizado:

main = do r <- leia `fmap` getLine
          deixe p = putStr
              d = 2 / fromIntegral r ^ 2
              lyn = deixe cmx = se x> r
                                  então p "\ n" >> retornar m
                                  senão se x * x + y * y <r * r
                                       então p "*" >> c (m + d) (x + 1)
                                       senão p "" >> cm (x + 1)
                      em se y> r
                         então imprima n
                         senão cn (-r) >> = l (y + 2)
          l (1-r`mod`2-r) 0

Eu estava meio que esperando que superasse algumas das versões imperativas, mas não consigo compactá-lo ainda mais neste momento.


Cortei mais 2 removendo o "d" e adicionando 1 em vez dele e, em seguida, imprimindo "2 * n / fromIntegral r ^ 2"
Steve

Eliminou 3 personagens por meio de alguns truques de Haskell. Eu adoro o fato de que em Haskell geralmente não há custo para várias linhas (nova linha vs. ponto-e-vírgula) e, portanto, nosso código-golfe é geralmente legível!
MtnViewMark

Estritamente falando, a versão de 145 caracteres só funciona se a entrada for par. Mas muito bom de qualquer maneira.
Steve,

Encurtou a linha de E / S. Deve ser possível salvar mais alguns caracteres empurrando a função defs em um bloco principal = do {... let {...} ...}, eu acho.
próxima tempestade de

@comingstorm: Legal! Eu não sabia sobre readLn. Isso ajudará a muitos jogadores de código de Haskell. @Steve: Sim, ainda estou tentando descobrir a maneira mais eficiente de consertar isso.
MtnViewMark

10

Ruby, 96 caracteres

(com base na solução C # da Guffa):

r=gets.to_f
s=2*t=r*r
g=1-r..r
g.step(2){|y|g.step{|x|putc' * '[i=t<=>x*x+y*y];s+=i}
puts}
p s/t

109 caracteres (bônus):

r=gets.to_i
g=-r..r
s=g.map{|i|(g.map{|j|i*i+j*j<r*r ?'*':' '}*''+"\n")*(i%2)}*''
puts s,2.0/r/r*s.count('*')

Obrigado! Estou envergonhado de ver como Ruby pode ser ilegível ... :)
Mladen Jablanović

você também pode usar em p svez de puts s:)
John La Rooy

1
Boas ideias novas aí - gosto que você esteja usando g com 2 tamanhos de etapas diferentes e <=> para evitar que o código seja convertido de lógico
John La Rooy,

9

PHP: 117

Baseado em dev-null-morador

for($y=1-$r=$argv[1];$y<$r;$y+=2,print"\n")for($x=1-$r;$x<$r;$x++)echo$r*$r>$x*$x+$y*$y&&$s++?'*':' ';echo$s*2/$r/$r;

8

Vocês estão pensando muito.

switch (r) {
   case 1,2:
      echo "*"; break;
   case 3,4:
      echo " ***\n*****\n ***"; break;
   // etc.
}

8
A contagem de personagens fica um pouco fora de controle, você não acha? :)
John La Rooy,

7
Não escala. Insustentável!
spoulson

Eu tentei comprimir o cheat do caso de teste o máximo possível e ainda acabou um pouco maior do que minha solução real: P
lunixbochs

5
+1, sempre faça a coisa mais óbvia primeiro ... se alguém não gostar, reclame em voz alta que a especificação não estava clara o suficiente
Mizipzor

Brian fez uma tentativa semi-séria de criar casos especiais para os casos de teste, você também deve votar a favor dele, se gostar desta resposta;) stackoverflow.com/questions/2457995
John La Rooy

7

J: 47 , 46 , 45

Mesma ideia básica de outras soluções, ou seja, r ^ 2 <= x ^ 2 + y ^ 2 , mas a notação orientada a matriz de J simplifica a expressão:

c=:({&' *',&":2*+/@,%#*#)@:>_2{.\|@j./~@i:@<:

Você chamaria de c 2ou c 8ou c 10etc.

Bônus: 49

Para lidar com a entrada ímpar, por exemplo 13, temos que filtrar em coordenadas x de valor ímpar, em vez de simplesmente pegar todas as outras linhas de saída (porque agora os índices podem começar em um número par ou ímpar). Essa generalização nos custa 4 caracteres:

c=:*:({&' *'@],&":2%(%+/@,))]>(|@j./~2&|#])@i:@<:

Versão desminimizada:

c =: verb define
  pythag   =. y > | j./~ i:y-1    NB.  r^2 > x^2 + y^2
  squished =. _2 {.\ pythag       NB.  Odd rows only
  piApx    =. (2 * +/ , squished) %  y*y
  (squished { ' *') , ": piApx
)

Melhorias e generalizações devido a Marshall Lochbam no J Forums .


5

Python: 118 caracteres

Praticamente uma porta direta da versão Perl.

r=input()
u=r+r%2
t=0
for i in range(u):n=1+2*int((r*r-(u-1-2*i)**2)**.5);t+=n;print' '*(r-n/2-1),'*'*n
print 2.*t/r/r

Para python2, você pode simplesmente usarr=input()
John La Rooy,

Você não precisa do espaço entre printe' '
John La Rooy

OK, isso é assustador, é mais curto do que a versão Perl agora. (Eu tirei completamente a "entrada" da minha mente porque normalmente é tão inseguro ...)
Nicholas Riley

4

C ++: 169 caracteres

#include <iostream>
int main(){int i,j,c=0,n;std::cin>>n;for(i=-n;i<=n;i+=2,std::cout<<'\n')for(j=-n;j<=n;j++)std::cout<<(i*i+j*j<=n*n?c++,'*':' ');std::cout<<2.*c/n/n;}

Não minimizado:

#include <iostream>
int main()
{
    int i,j,c=0,n;
    std::cin>>n;
    for(i=-n;i<=n;i+=2,std::cout<<'\n')
        for(j=-n;j<=n;j++)
            std::cout<<(i*i+j*j<=n*n?c++,'*':' ');
    std::cout<<2.*c/n/n;
}

(Sim, usando std :: em vez de using namespace stdusa menos caracteres)

A saída aqui não corresponde aos casos de teste na postagem original, então aqui está um que corresponde (escrito para facilitar a leitura). Considere-a uma implementação de referência (se Poita_ não se importar):

#include <iostream>
using namespace std;

int main()
{
    int i, j, c=0, n;
    cin >> n;
    for(i=-n; i<=n; i++) {
        if (i & 1) {
            for(j=-n; j<=n; j++) {
                if (i*i + j*j <= n*n) {
                    cout << '*';
                    c++;
                } else {
                    cout << ' ';
                }
            }
            cout << '\n';
        }
    }
    cout << 2.0 * c / n / n << '\n';
}

C ++: 168 caracteres (com saída acredito estar correta)

#include <iostream>
int main(){int i,j,c=0,n;std::cin>>n;for(i=-n|1;i<=n;i+=2,std::cout<<"\n")for(j=-n;j<=n;j++)std::cout<<" *"[i*i+j*j<=n*n&&++c];std::cout<<2.*c/n/n;}

O código faz um loop de -n para n, portanto, para uma entrada de, por exemplo, 4, ele exibe um diâmetro de 9, não 7, como mostrado nos casos de teste.
Guffa

É um requisito que seu círculo corresponda exatamente aos OPs ?
Peter Alexander

3
Você pode desejar alterá-lo para, #include <iostream.h>basicamente, #include <iostream> -- using namespace std;para compatibilidade com compiladores C ++ antigos.
Earlz

1
@Carlos, não escrevi esse bit em particular, mas é um operador AND binário. Ele verifica se o último bit está definido, o que é equivalente a fazer i%2, mas é "mais rápido". Não é realmente mais rápido porque o compilador faria isso de qualquer maneira.
Peter Alexander

1
@Poita_: Na verdade, i% 2 ei & 1 se comportam de maneira diferente com números negativos. (-1) & 1 é 1, que é o que queremos aqui. (-1)% 2 é -1 em meu sistema e está em conformidade com C99. Assim, embora if (i & 1) e if (i% 2) façam a mesma coisa, deve-se ter cuidado com if (i% 2 == 1), que não funcionará quando i for negativo.
Joey Adams

3

PHP: 126 132 138

(baseado na solução Guffa C #)

126:

for($y=1-($r=$argv[1]);$y<$r;$y+=2,print"\n")for($x=1-$r;$x<$r;$s+=$i,++$x)echo($i=$x*$x+$y*$y<=$r*$r)?'*':' ';echo$s*2/$r/$r;

132:

for($y=1-($r=$argv[1]);$y<$r;$y+=2){for($x=1-$r;$x<$r;@$s+=$i,++$x)echo($i=$x*$x+$y*$y<=$r*$r?1:0)?'*':' ';echo"\n";}echo$s*2/$r/$r;

138:

for($y=1-($r=$argv[1]);$y<$r;$y+=2){for($x=1-$r;$x<$r;@$s+=$i){$t=$x;echo($i=$t*$x++ +$y*$y<=$r*$r?1:0)?'*':' ';}echo"\n";}echo$s*2/$r/$r;

Atual completo:

for( $y = 1 - ( $r = $argv[1]); $y < $r; $y += 2, print "\n")
    for( $x = 1-$r; $x < $r; $s += $i, ++$x)
        echo( $i = $x*$x + $y*$y <= $r*$r) ? '*' : ' ';
echo $s*2 /$r /$r;

Pode ser sem @antes, $smas apenas com error_reporting definido como 0 (as saídas de aviso estão bagunçando o círculo)


o que o / $ r faz no echo $ s * 2 / $ r / $ r;
davidosalgo

Divisão OHH ... o espaçamento me
confundiu

3

Ruby 1.8.x, 93

r=$_.to_f
q=0
e=r-1
(p(('*'*(n=1|2*(r*r-e*e)**0.5)).center r+r)
q+=n+n
e-=2)while-r<e
p q/r/r

Correr com $ ruby -p piday


Boa, mas não imprime a aproximação de pi
John La Rooy,

Não funciona no 1.9.1 e imprime aspas duplas ao redor do círculo.
Mladen Jablanović,

É normal que os programas de golfe não funcionem em níveis de linguagem totalmente diferentes. Quantos Perl ou Python cg funcionam em cada versão da linguagem? É interessante, porém, descobrir que a razão é porque Integer|Floatnão coage mais o float em 1.9.
DigitalRoss

3

APL: 59

Esta função aceita um número e retorna os dois itens esperados. Funciona corretamente em casos de bônus.

{⍪(⊂' *'[1+m]),q÷⍨2×+/,m←(2|v)⌿(q←⍵*2)>v∘.+v←2*⍨⍵-⍳1+2×⍵-1}

O dialeto é Dyalog APL, com origem do índice padrão. O nível de habilidade é um novato sem noção , então se algum guru do APL quiser reduzir para 10 caracteres, fique à vontade!


Você pode experimentá-lo online em Try APL , basta colá-lo e inserir um número depois dele:

   {⍪(⊂' *'[1+m]),q÷⍨2×+/,m←(2|v)⌿(q←⍵*2)>v∘.+v←2*⍨⍵-⍳1+2×⍵-1} 13
      *************
   *******************
  *********************
 ***********************
*************************
*************************
*************************
*************************
 ***********************
  *********************
   *******************
      *************
2.98225

Embora eu não conheça o APL, parece mais bonito que a versão J.
ahala

@ahala Certamente. APL é lindo, tanto conceitualmente quanto esteticamente. Comecei a aprender J, mas fui desligado pela loucura ASCII aleatória. Uma boa alma escreveu um interpretador APL de código aberto para Node.js (npm install apl) que é muito bom. Ele calcula o código acima com apenas uma pequena alteração (sem monádico , segundo caractere). Você pode encontrar uma boa documentação de APL em todos os sites de fornecedores, como o Dyalog.
Tobia

2

E uma entrada bash: 181 186 190 chars

for((y=-(r=$1,r/2*2);y<=r;y+=2));do for((x=-r;x<=r;++x));do((x*x+y*y<r*r))&&{((++n));echo -n '*';}||echo -n " ";((x<r))||echo;done;done;((s=1000,p=n*2*s/r/r,a=p/s,b=p%s));echo $a.$b

Corra com por exemplo bash py.sh 13


2

Python: 148 caracteres.

Tentativa falhada (ou seja, não curta o suficiente) de abusar das regras e codificar os casos de teste, como mencionei na resposta ao post original. Abusá-lo com uma linguagem mais prolixa pode ter sido mais fácil:

a=3.0,3.125,3.16
b="1","23","3677","47899"
r=input()
for i in b[r/3]+b[r/3][::-1]:q=1+2*int(i);print ' '*(int(b[r/3][-1])-int(i))+'*'*q
print a[r/5]

2

bc: 165 , 127 , 126 caracteres

Baseado na versão Python.

r=read()
for(i=-1;r*2>i+=2;scale=6){n=sqrt(2*i*r-i*i)
scale=0
n=1+n/1*2
j=r-n/2
t+=2*n
while(j--)" "
while(n--)"*"
"
"}
t/r/r

(A nova linha após a última linha não pode ser omitida aqui.)


1
127 caracteres: r = ler (); para (i = 1; i <r * 2; escala = 6) {n = sqrt (2 * i r-i i); escala = 0; n = 1 + n / 1 * 2 ; i + = 2; j = rn / 2; t + = 2 * n; enquanto (j--) ""; enquanto (n -) "*"; ""}; t / r / r
Carlos Gutiérrez

O único problema aqui é que agora falha para 0, mas de acordo com as regras atuais, está tudo bem.
przemoc

2

JavaScript (SpiderMonkey) - 118 caracteres

Esta versão aceita entrada de stdin e passa nos casos de teste bônus

r=readline()
for(t=0,i=-r;i<r;i++)if(i%2){for(s='',j=-r;j<r;j++){t+=q=i*i+j*j<r*r
s+=q?'*':' '}print(s)}print(t*2/r/r)

Uso: cat 10 | js thisfile.js - jsbin preview adiciona um alias para print / readline para que você possa ver no navegador

Javascript: 213 163


Atualizada

r=10;m=Math;a=Array;t=0;l=document;for(i=-r;i<r;i+=2){w=m.floor(m.sqrt(r*r-i*i)*2);t+=w*2;l.writeln(a(m.round(r-w/2)).join(' ')+a(w).join('*'));}l.writeln(t/(r*r))

Ninguém disse que precisava renderizar corretamente no navegador - apenas a saída. Como tal, removi as tags pré e otimizei ainda mais. Para visualizar a saída, você precisa visualizar o código-fonte gerado ou definir sua folha de estilo de acordo. Pi é menos preciso dessa forma, mas agora está de acordo com as especificações.


r=10;m=Math;a=Array;t=0;s='';for(i=-r;i<r;i++){w=m.floor((m.sqrt(m.pow(r,2)-m.pow(i,2)))*2);t+=w;if(i%2){z=a(m.round(r-w/2)).join(' ')+a(w).join('*');s+=z+'\n';}}document.write('<pre>'+(s+(t/m.pow(r,2)))+'</pre>')

Não minimizado:

r=10;
m=Math;
a=Array;
t=0;
s='';
for(i=-r;i<r;i++){
    w=m.floor((m.sqrt(m.pow(r,2)-m.pow(i,2)))*2);
    t+=w;
    if(i%2){
    z=a(m.round(r-w/2)).join(' ')+a(w).join('*');
    s+=z+'\n';
    }
}
document.write('<pre>'+(s+(t/m.pow(r,2)))+'</pre>');

1

Java: 234

class C{public static void main(String[] a){int x,y,s=0,r=Integer.parseInt(a[0]);for(y=1-r;y<r;y+=2){for(x=1-r;x<r;++x){boolean b=x*x+y*y<=r*r;s+=b?1:0;System.out.print(b?'*':' ');}System.out.println();}System.out.println(s*2d/r/r);}}

Não minimizado:

class C{
    public static void main(String[] a){
        int x,y,s=0,r=Integer.parseInt(a[0]); 
        for(y=1-r;y<r;y+=2){
            for(x=1-r;x<r;++x) {
                boolean b=x*x+y*y<=r*r;
                s+=b?1:0;
                System.out.print(b?'*':' ');
            }
            System.out.println();
        }
        System.out.println(s*2d/r/r);
    }
}

Provavelmente poderia salvar cerca de 50 caracteres reescrevendo isso em scala
rwyland

1

GAWK: 136 , 132 , 126 , 125 caracteres

Baseado na versão Python.

{r=$1
for(i=-1;r*2>i+=2;print""){n=1+int((2*i*r-i*i)**.5)*2
t+=2*n/r/r
printf"%*s",r-n/2,""
while(n--)printf"%c","*"}print t}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.