Code Golf - π giorno


95

La sfida

Linee guida per il code-golf su SO

Il codice più breve per numero di caratteri per visualizzare una rappresentazione di un cerchio di raggio Rusando il *carattere, seguito da un'approssimazione di π.

L'input è un singolo numero R,.

Dal momento che la maggior parte dei computer sembra avere un rapporto quasi 2: 1, dovresti emettere solo le righe dove yè dispari. Ciò significa che quando Rè dispari dovresti stampare delle R-1righe. C'è un nuovo caso di prova per R=13chiarire.

per esempio.

Input
    5
Output      Correct                          Incorrect

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

Modifica: a causa della diffusa confusione causata da valori dispari di R, verranno accettate tutte le soluzioni che superano i 4 casi di test indicati di seguito

L'approssimazione di π è data dividendo il doppio del numero di *caratteri per .
L'approssimazione dovrebbe essere corretta per almeno 6 cifre significative.
Sono consentiti zeri iniziali o finali, così per esempio qualsiasi 3, 3.000000, 003è accettato per gli ingressi di 2e 4.

Il conteggio del codice include input / output (ovvero il programma completo).

Casi test

Input
    2
Output
     *** 
     *** 
    3.0

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

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

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

Caso di prova bonus

Input
    13
Output

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

Potresti voler chiarire se l '"input" si trova sulla riga di comando o su stdin.
Greg Hewgill

1
@Greg Hewgill, sentiti libero di scegliere quello che è più conveniente per la lingua che stai utilizzando :)
John La Rooy

@ Greg Hewgill, Alcune (cioè pochissime) implementazioni del linguaggio di programmazione non hanno la nozione di "riga di comando".
Joey Adams

1
Noto che poche delle risposte seguono la regola di mettere solo le linee dove y è dispari. Dato un valore dispari di r (non mostrato nei casi di test), la maggior parte produrrà linee in cui y è pari!
MtnViewMark

6
Sfida contro l'abuso delle regole: crea un codice più breve del codice di chiunque altro supportando solo i 4 casi di test richiesti.
Brian

Risposte:


15

In dc: 88 e 93 93 94 96102105129138141 caratteri

Per ogni evenienza, sto usando OpenBSD e alcune estensioni presumibilmente non portatili a questo punto.

93 caratteri. Questo si basa sulla stessa formula della soluzione FORTRAN (risultati leggermente diversi rispetto ai casi di test). Calcola X ^ 2 = R ^ 2-Y ^ 2 per ogni Y

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

88 caratteri. Soluzione iterativa. Corrisponde ai casi di test. Per ogni X e Y controlla 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

Per correre dc pi.dc.

Ecco una vecchia versione annotata:

# 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
Non funziona con linux dc, ma posso confermare che funziona su openbsd . Eccezionale!
John La Rooy

@Carlos, sì, l' (operatore è sicuramente a portata di mano. peccato che rimanga non implementato nel dc fornito con Linux
John La Rooy

@gnibbler - "Una riscrittura completa del comando dc utilizzando le routine bn (3) big number è apparsa per la prima volta in OpenBSD 3.5." Non lo sapevo. Alcuni simpatici nuovi operatori sono inclusi, ma sono contrassegnati come "estensioni non portatili".
Carlos Gutiérrez

Sì, l '(solo operatore ha permesso di perdere 6 colpi!
Dan Andreatta

119

C: 131 caratteri

(Basato sulla soluzione C ++ di 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);}

(Cambia il i|=-na i-=nper rimuovere il supporto dei casi di numero dispari. Questo riduce semplicemente il conteggio dei caratteri a 130.)

Come un cerchio:

      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
Mi piace il modo in cui hai aggiunto le cerchie al codice per trasformarlo in un cerchio. Sarebbe preferibile +000?
Potatoswatter

congratulazioni, j * j ++ è un comportamento indefinito
sellibitze

1
non sarebbe un solo personaggio ...?
Ponkadoodle

1
Come accetta main()quattro intargomenti?
David R Tribble

2
@Load: 5.1.2.2.1 / 1: La funzione chiamata all'avvio del programma è denominata main. Deve essere definito ... o in un altro modo definito dall'implementazione . Quindi è perché l'implementazione può accettare questo modulo.
kennytm

46

XSLT 1.0

Solo per divertimento, ecco una versione XSLT. Non proprio materiale da codice-golf, ma risolve il problema in un modo strano e funzionale-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 vuoi testarlo, salvalo come pi.xslte apri il seguente file XML in IE:

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

42
i miei <eyes> </eyes>! Gli occhiali, non <do> niente </do>!
Jimmy

1
Dang! Temo che tu possa aver battuto la mia soluzione HyperCard per unicità: D
Joey Adams

7
Non posso credere che tu abbia detto "apri ... IE"
arpione

Eh, sì, nel passato, avevamo solo IE e XML con XSLT era la soluzione a tutti i nostri problemi. Bei vecchi tempi! :)
Danko Durbić

XSL versione 1.0 wow, ricordo di aver aspettato con ansia la versione 2 ma quando è uscito ero già andato avanti.
gradbot

35

Perl, 95 96 99 106 109 110 119 personaggi:

$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

(La nuova riga può essere rimossa ed è lì solo per evitare una barra di scorrimento)

Sìì! Versione circolare!

    $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

Per chi non lo sapesse, la versione lunga:

#!/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
Questo è di gran lunga il codice più illeggibile che ho visto in tutta la mia vita
Chris Marisic

13
Immagino che tu non abbia mai visto APL allora.
Peter ha vinto il

5
@ Chris Marisic: Hai controllato le altre domande / argomenti contrassegnati code-golf? :) Ho visto esempi molto più illeggibili.
BalusC

3
@ Peter: A differenza della maggior parte, ho visto e scritto APL. Ci vogliono un paio di settimane per abituarsi ai suoi caratteri speciali, ma dopo può essere abbastanza leggibile. Anche dopo un paio di decenni per abituarsi, Perl è ancora molto peggio.
Jerry Coffin

1
111 caratteri,$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 caratteri

$ 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

Aspetta, pensavo che la formattazione fosse importante in Fortran? Hai lettere nella colonna 1!
Joel

La maggior parte delle persone è ancora bloccata su Fortan77 da quello che ho visto.
Joel

8
Mi piace come la versione circolare assomiglia alla Morte Nera.
mskfisher

22

x86 Codice macchina: 127 byte

Intel Assembler: 490 caratteri

    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

Questa versione gestisce anche il test case bonus ed è di 133 byte:

    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
Adoro StackOverflow!
zengr

2
È interessante notare che alcuni dei linguaggi di alto livello hanno un numero di caratteri più breve rispetto al binario che questo produce.
Colin Valliant,

3
@Alcari: se includessi tutto il codice nelle librerie utilizzate dai linguaggi di livello superiore, il loro numero di caratteri sarebbe significativamente più alto. In assembler, fare printf("%f",a/b)non è banale, non c'è una singola istruzione per farlo, e la mia implementazione sopra presuppone che 0 <= a / b <10 e che l'operazione sia una divisione e che aeb siano numeri interi.
Skizz

19

Pitone: 101 104 107 110 caratteri

Basato sull'altra versione di Python di 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

Crediti ad AlcariTheMad per alcuni calcoli.


Ah, quelli dispari sono indicizzati con lo zero al centro, spiega tutto.

Bonus Python: 115 caratteri (rapidamente hackerati insieme)

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

Wow, sì, "+" batte -1 e, ogni giorno. Ancora un'altra tecnica che ho messo fuori di testa perché non è quasi mai la cosa giusta da fare :-)
Nicholas Riley

Ho usato C in passato e non ho mai nemmeno guardato Python. Questi 104 caratteri sono più leggibili del C ++ sopra. Sorprendente. Forse dovrei imparare Python ...
Dean Rather

@Dean: Uno degli obiettivi principali di Python è essere facile da leggere e scrivere.
Colin Valliant

hai pensato di usare anche exec con la tua risposta di 104 caratteri? :)
John La Rooy

Avrei bisogno di eseguire il rollio della mia compressione: zlib, marshalling, ecc. Sono usciti tutti più grandi del codice effettivo.
lunixbochs

12

Powershell, 119 113 109 caratteri

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

ed ecco una versione più carina:

( $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: spero di no, ma questa deve essere la cosa più brutta che abbia mai scritto :)
Danko Durbić

3
Grazie per quella versione più carina =)
Thor Hovden

10

HyperTalk: 237 caratteri

Il rientro non è richiesto né conteggiato. Viene aggiunto per chiarezza. Si noti inoltre che HyperCard 2.2 accetta quegli operatori relazionali non ASCII che ho usato.

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

Poiché HyperCard 2.2 non supporta stdin / stdout, viene fornita una funzione.


1
Hypercard, signor Adams? Sul serio? Questo è altamente inaspettato.
Kawa

1
@Kawa: Questo è il motivo per cui l'ho postato :) Inoltre, il golf in codice è un buon modo per creare una suite di test nel caso in cui decidessi di scrivere un interprete HyperTalk in futuro.
Joey Adams

Ah! Mi piacerebbe vederlo, XD
Kawa

Se decidi di scrivere quell'interprete, o vuoi unirti al lavoro su uno esistente, fammelo sapere e posso aggiungerne una menzione su hypercard.org e sarei curioso di sapere come va :-)
uliwitness

10

C #: 209202201 caratteri:

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);}}

Unminified:

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);
  }
}

Non conosco molto C # ma non dovresti essere in grado di usare string[]ae 1-r(invece di -1+r)?
kennytm

@ Kenny: hai ragione. :) In questo modo vengono salvati tre personaggi, e poi sono riuscito a sbarazzarmene di altri cinque.
Guffa

Ho notato quella prima cosa, totalmente persa -r+1sull'oggetto.
Dykam

4
Inoltre, anche avvistato x*xx+++y*y, ma è una cosa folle da sezionare a prima vista.
Dykam

Mi sono preso la libertà di eliminare un altro byte ;-)
Joey

10

Haskell 139 145 147 150 230 caratteri:

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

Gestione dei numeri dispari: 148 caratteri:

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 caratteri: (basato sulla versione 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 caratteri:

main = do {r <-read`fmap`getLine; let {p = putStr; d = 2 / fromIntegral r ^ 2; lyn = let cmx = if x> r then p "\ n" >> return m else if x * x + y * y <r * r then p "*" >> c (m + d) (x + 1) else p "" >> cm (x + 1) in se y> r quindi stampa n else cn (-r) >> = l (y + 2)}; l (1-r`mod`2-r) 0}

Unminified:

main = do r <- leggi `fmap` getLine
          let p = putStr
              d = 2 / fromIntegral r ^ 2
              lyn = let cmx = if x> r
                                  quindi p "\ n" >> return m
                                  altrimenti se x * x + y * y <r * r
                                       quindi p "*" >> c (m + d) (x + 1)
                                       altrimenti p "" >> cm (x + 1)
                      in se y> r
                         quindi stampare n
                         altrimenti cn (-r) >> = l (y + 2)
          l (1-r`mod`2-r) 0

Speravo un po 'che avrebbe battuto alcune delle versioni imperative, ma a questo punto non riesco a comprimerlo ulteriormente.


Ne ho tagliati altri 2 eliminando la "d" e aggiungendone 1 al posto, quindi stampando "2 * n / fromIntegral r ^ 2"
Steve

Rasato 3 personaggi con alcuni trucchi Haskell. Mi piace il fatto che in Haskell spesso non ci siano costi per più righe (newline vs. punto e virgola) e quindi il nostro code-golf è generalmente leggibile!
MtnViewMark

A rigor di termini, la versione da 145 caratteri funziona solo se l'input è pari. Ma molto carino in ogni caso.
Steve il

Abbreviata la linea I / O. Dovrebbe essere ancora possibile salvare qualche altro carattere inserendo la funzione defs in un blocco main = do {... let {...} ...}, credo.
comingstorm

@comingstorm: Cool! Non sapevo di readLn. Questo aiuterà molti golfisti Haskell. @ Steve: Sì, sto ancora cercando di capire il modo più efficiente per risolverlo.
MtnViewMark

10

Rubino, 96 caratteri

(basato sulla soluzione C # di 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 caratteri (bonus):

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('*')

Grazie! Sono imbarazzato nel vedere quanto possa essere illeggibile Ruby ... :)
Mladen Jablanović

puoi anche usare al p sposto di puts s:)
John La Rooy

1
Ci sono belle idee fresche - Mi piace che tu stia usando g con 2 diverse dimensioni di passo e <=> per evitare di avere codice da convertire dal logico
John La Rooy

9

PHP: 117

Basato su dev-null-dweller

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

Ragazzi, state pensando troppo intensamente.

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

8
Il conteggio dei caratteri sfugge di mano, non credi? :)
John La Rooy

7
Non scala. Insostenibile!
spoulson

Ho provato a comprimere il più possibile il cheat del test case ed è risultato comunque leggermente più grande della mia soluzione effettiva: P
lunixbochs

5
+1, fai sempre prima la cosa più ovvia ... se a qualcuno non piace, si lamenta ad alta voce che le specifiche non erano abbastanza chiare
Mizipzor

Brian ha avuto un tentativo semi serio di inserire in casi speciali i casi di prova, dovresti votare anche il suo se ti piace questa risposta;) stackoverflow.com/questions/2457995
John La Rooy

7

J: 47 , 46 , 45

Stessa idea di base delle altre soluzioni, cioè r ^ 2 <= x ^ 2 + y ^ 2 , ma la notazione orientata all'array di J semplifica l'espressione:

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

Lo chiameresti come c 2o c 8o c 10ecc.

Bonus: 49

Per gestire l'input dispari, ad esempio 13, dobbiamo filtrare le coordinate x con valori dispari, piuttosto che prendere semplicemente ogni altra riga di output (perché ora gli indici potrebbero iniziare da un numero pari o dispari). Questa generalizzazione ci costa 4 caratteri:

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

Versione deminimizzata:

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
)

Miglioramenti e generalizzazioni a causa di Marshall Lochbam sulle J Forum .


5

Python: 118 caratteri

Praticamente un porting semplice della versione 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

Per python2 puoi semplicemente usarer=input()
John La Rooy

Non hai bisogno dello spazio tra printe' '
John La Rooy

OK, è spaventoso, ora è più breve della versione Perl. (Ho completamente eliminato "input" dalla mia mente perché è così pericoloso di solito ...)
Nicholas Riley

4

C ++: 169 caratteri

#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;}

Unminified:

#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;
}

(Sì, utilizzando std :: invece di using namespace stdutilizzare meno caratteri)

L'output qui non corrisponde ai casi di test nel post originale, quindi eccone uno che lo fa (scritto per leggibilità). Consideralo un'implementazione di riferimento (se a Poita_ non dispiace):

#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 caratteri (con output credo sia corretto)

#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;}

Il codice scorre da -n a n, quindi per un input di esempio 4 mostra un diametro di 9, non 7 come mostrato nei casi di test.
Guffa

È un requisito che la tua cerchia corrisponda esattamente a quella dell'OP ?
Peter Alexander

3
Potresti voler cambiare in #include <iostream.h>base #include <iostream> -- using namespace std;alla compatibilità con i vecchi compilatori C ++.
Earlz

1
@Carlos, non ho scritto quel particolare bit, ma è un operatore binario AND. Verifica che l'ultimo bit sia impostato, che equivale a fare i%2, ma è "più veloce". Non è molto più veloce perché il compilatore lo farebbe comunque.
Peter Alexander

1
@Poita_: In realtà, i% 2 e i & 1 si comportano diversamente con i numeri negativi. (-1) e 1 è 1, che è ciò che vogliamo qui. (-1)% 2 è -1 sul mio sistema e questo è conforme a C99. Pertanto, sebbene if (i & 1) e if (i% 2) faranno la stessa cosa, bisogna stare attenti a if (i% 2 == 1), che non funzionerà quando i è negativo.
Joey Adams

3

PHP: 126132138

(basato sulla soluzione 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;

Pieno corrente:

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;

Può essere senza @prima $sma solo con error_reporting impostato su 0 (gli output di avviso stanno rovinando il cerchio)


cosa fa / $ r in echo $ s * 2 / $ r / $ r;
davidosomething

Divisione OHH ... la spaziatura mi ha
spiazzato

3

Rubino 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

Corri con $ ruby -p piday


Bello, ma non stampa l'approssimazione pi
John La Rooy

Non funziona nella 1.9.1 e stampa le virgolette doppie attorno al cerchio.
Mladen Jablanović

È normale che i programmi di golf non funzionino su livelli linguistici completamente diversi. Quanti cg Perl o Python funzionano su ogni versione del linguaggio? È interessante, tuttavia, che il motivo sia perché Integer|Floatnon costringe più il galleggiante a 1.9.
DigitalRoss

3

APL: 59

Questa funzione accetta un numero e restituisce i due elementi previsti. Funziona correttamente nei casi bonus.

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

Il dialetto è Dyalog APL, con origine indice predefinita. Il livello di abilità è principiante senza tracce , quindi se un guru dell'APL vuole ridurlo a 10 caratteri, sii mio ospite!


Puoi provarlo online su Prova APL , incollalo e inserisci un numero dopo:

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

Anche se non conosco APL, sembra più carino della versione J.
ahala

@ahala Indeed. APL è bellissima, sia concettualmente che esteticamente. Ho iniziato a imparare J, ma sono stato spento dalla follia ASCII casuale. Una buona anima ha scritto un interprete APL open source per Node.js (npm install apl) che è abbastanza buono. Calcola il codice di cui sopra con solo una piccola modifica (non monadico , 2 ° carattere.) È possibile trovare una buona documentazione APL su tutti i siti dei fornitori, come Dyalog.
Tobia

2

E una voce bash: 181 186 190 caratteri

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

Corri con es bash py.sh 13


2

Python: 148 caratteri.

Tentativo fallito (cioè non abbastanza breve) di abusare delle regole e codificare i casi di test, come ho detto in risposta al post originale. Abusarne con un linguaggio più prolisso potrebbe essere stato più facile:

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 caratteri

Basato sulla versione 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

(La nuova riga dopo l'ultima riga non può essere omessa qui.)


1
127 caratteri: r = read (); for (i = 1; i <r * 2; scale = 6) {n = sqrt (2 * i r-i i); scale = 0; n = 1 + n / 1 * 2 ; i + = 2; j = rn / 2; t + = 2 * n; while (j--) ""; while (n -) "*"; ""}; t / r / r
Carlos Gutiérrez

L'unico problema qui è che ora fallisce per 0, ma secondo le regole attuali, va bene.
przemoc

2

JavaScript (SpiderMonkey) - 118 caratteri

Questa versione accetta input da stdin e supera i casi di test bonus

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)

Utilizzo: cat 10 | js thisfile.js - jsbin preview aggiunge un alias per print / readline in modo da poterlo visualizzare nel browser

Javascript: 213 163


Aggiornato

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))

Nessuno ha detto che doveva essere visualizzato correttamente nel browser, solo l'output. In quanto tale, ho rimosso i tag pre e ottimizzato ulteriormente. Per visualizzare l'output è necessario visualizzare la sorgente generata o impostare il foglio di stile di conseguenza. Pi è meno preciso in questo modo, ma ora è da specificare.


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>')

Unminified:

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);}}

Unminified:

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);
    }
}

Potrei probabilmente salvare ~ 50 caratteri riscrivendolo in scala
rwyland

1

GAWK: 136 , 132 , 126 , 125 caratteri

Basato sulla versione 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}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.