Code Golf - π jour


95

Le défi

Directives pour le code-golf sur SO

Le code le plus court par nombre de caractères pour afficher une représentation d'un cercle de rayon Rà l'aide du *caractère, suivi d'une approximation de π.

L'entrée est un seul nombre R,.

Comme la plupart des ordinateurs semblent avoir un rapport presque 2: 1, vous ne devez sortir que les lignes où cela yest impair. Cela signifie que lorsque Rc'est étrange, vous devez imprimer des R-1lignes. Il y a un nouveau test pour R=13clarifier.

par exemple.

Input
    5
Output      Correct                          Incorrect

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

Edit: En raison de la confusion généralisée causée par des valeurs impaires de R, toutes les solutions qui passent les 4 cas de test ci-dessous seront acceptées

L'approximation de π est donnée en divisant deux fois le nombre de *caractères par .
L'approximation doit être correcte à au moins 6 chiffres significatifs.
Zéros avant ou arrière sont autorisés, ainsi par exemple l' une des 3, 3.000000, 003est accepté pour les entrées 2et 4.

Le décompte des codes comprend l'entrée / la sortie (c'est-à-dire le programme complet).

Cas de test

Input
    2
Output
     *** 
     *** 
    3.0

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

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

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

Cas de test bonus

Input
    13
Output

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

Vous voudrez peut-être clarifier si "l'entrée" est sur la ligne de commande ou sur stdin.
Greg Hewgill

1
@Greg Hewgill, n'hésitez pas à choisir celle qui convient le mieux à la langue que vous utilisez :)
John La Rooy

@Greg Hewgill, Certaines implémentations de langage de programmation (c'est-à-dire très peu nombreuses) n'ont pas la notion de "ligne de commande".
Joey Adams

1
Je remarque que peu de réponses suivent la règle de ne placer que les lignes où y est impair. Étant donné une valeur impaire de r (non montrée dans les cas de test), la plupart produiront des lignes où y est pair!
MtnViewMark

6
Défi d'abus de règle: créez un code plus court que celui de n'importe qui d'autre en ne prenant en charge que les 4 cas de test requis.
Brian

Réponses:


15

En courant continu: 88 et 93 93 94 96102105129138141 caractères

Juste au cas où, j'utilise OpenBSD et certaines extensions supposées non portables à ce stade.

93 caractères. Ceci est basé sur la même formule que la solution FORTRAN (résultats légèrement différents des cas de test). Calcule X ^ 2 = R ^ 2-Y ^ 2 pour chaque Y

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

88 caractères. Solution itérative. Correspond aux cas de test. Pour chaque X et Y vérifie si 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

Pour courir dc pi.dc.

Voici une ancienne version annotée:

# 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
Ne fonctionne pas avec linux dc, mais je peux confirmer que cela fonctionne sur openbsd . Impressionnant!
John La Rooy

@Carlos, oui l' (opérateur est bien pratique. dommage que cela reste non implémenté dans le dc fourni avec linux
John La Rooy

@gnibbler - "Une réécriture complète de la commande dc à l'aide des routines bn (3) à grand nombre est apparue pour la première fois dans OpenBSD 3.5." Je ne savais pas ça. Quelques nouveaux opérateurs sympas sont inclus, mais ils sont marqués comme "extensions non portables".
Carlos Gutiérrez

Ouais, le (seul opérateur autorisé à perdre 6 coups!
Dan Andreatta

119

C: 131 caractères

(Basé sur la solution 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);}

(Remplacez le i|=-npar i-=npour supprimer la prise en charge des cas de nombres impairs. Cela réduit simplement le nombre de caractères à 130.)

En cercle:

      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
J'aime la façon dont vous avez ajouté des cercles au code pour le transformer en cercle. Est-ce que +000 serait préférable?
Potatoswatter

Félicitations, j * j ++ est un comportement indéfini
sellibitze

1
ne serait-ce pas seulement un personnage ...?
Ponkadoodle

1
Comment main()prend quatre intarguments?
David R Tribble

2
@Load: 5.1.2.2.1 / 1: La fonction appelée au démarrage du programme est nommée main. Il doit être défini… ou d'une autre manière définie par la mise en œuvre . C'est donc parce que l'implémentation peut accepter cette forme.
kennytm

46

XSLT 1.0

Juste pour le plaisir, voici une version XSLT. Pas vraiment du matériel de code-golf, mais il résout le problème d'une manière étrange-fonctionnelle-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>

Si vous souhaitez le tester, enregistrez-le sous pi.xsltet ouvrez le fichier XML suivant dans IE:

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

42
mes <eyes> </eyes>! Les lunettes, elles <do> rien </do>!
Jimmy

1
Dang! J'ai peur que vous ayez battu ma solution HyperCard pour l'unicité: D
Joey Adams

7
Je ne peux pas croire que vous ayez dit "ouvrir ... IE"
harpo

Heh, oui, à l'époque, nous n'avions que IE et XML avec XSLT était la solution à tous nos problèmes. Bon vieux temps! :)
Danko Durbić

XSL version 1.0 wow, je me souviens avoir hâte de la version 2, mais au moment où elle est sortie, j'avais déjà évolué.
gradbot

35

Perl, 95 96 99 106 109 110 119 personnages:

$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 nouvelle ligne peut être supprimée et n'est là que pour éviter une barre de défilement)

Yay! Version cercle!

    $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

Pour les non-initiés, la version longue:

#!/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
C'est de loin le code le plus illisible que j'ai vu de toute ma vie
Chris Marisic

13
Je suppose que vous n'avez jamais vu APL alors.
Peter Wone

5
@Chris Marisic: Avez-vous vérifié les autres questions / sujets marqués code-golf? :) J'ai vu des exemples beaucoup plus illisibles.
BalusC

3
@Peter: Contrairement à la plupart, j'ai vu et écrit APL. Il faut quelques semaines pour s'habituer à ses caractères spéciaux, mais après cela, il peut être tout à fait lisible. Même après quelques décennies à s'habituer, Perl est encore bien pire.
Jerry Coffin

1
111 chars,$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 caractères

$ 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

Attendez, je pensais que le formatage était important dans Fortran? Vous avez des lettres dans la colonne 1!
Joel

La plupart des gens sont toujours bloqués sur Fortan77 d'après ce que j'ai vu.
Joel

8
J'aime la façon dont la version circulaire ressemble à l'étoile de la mort.
mskfisher

22

Code machine x86: 127 octets

Assembleur Intel: 490 caractères

    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

Cette version gère également le cas de test bonus et fait 133 octets:

    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
J'adore StackOverflow!
zengr

2
Il est intéressant de noter que certaines des langues de haut niveau ont un nombre de caractères plus court que le binaire que cela produit.
Colin Valliant

3
@Alcari: Si vous incluiez tout le code dans les bibliothèques utilisées par les langages de niveau supérieur, leur nombre de caractères serait nettement plus élevé. En assembleur, faire printf("%f",a/b)n'est pas trivial, il n'y a pas d'instruction unique pour le faire, et mon implémentation ci-dessus suppose que 0 <= a / b <10 et que l'opération est une division et que a et b sont des entiers.
Skizz

19

Python: 101 104 107 110 caractères

Basé sur l'autre version 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édits à AlcariTheMad pour certains des calculs.


Ah, les impairs sont indexés avec zéro au milieu, explique tout.

Bonus Python: 115 caractères (rapidement piratés ensemble)

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, ouais, «+» bat -1 et, n'importe quel jour. Encore une autre technique que je mets hors de mon esprit car ce n'est presque jamais la bonne chose à faire :-)
Nicholas Riley

J'ai utilisé C dans le passé, et je n'ai même jamais regardé Python. Ces 104 caractères sont plus lisibles que le C ++ ci-dessus. Incroyable. Peut-être que je devrais apprendre Python ...
Dean Rather

@Dean: L'un des principaux objectifs de Python est d'être facile à lire et à écrire.
Colin Valliant

avez-vous pensé à utiliser exec avec votre réponse à 104 caractères? :)
John La Rooy

J'aurais besoin de rouler ma propre compression - zlib, marshalling, etc. tout est sorti plus grand que le code réel.
lunixbochs

12

Powershell, 119 113 109 caractères

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

et voici une version plus jolie:

( $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: J'espère que non, mais ça doit être la chose la plus moche que j'ai jamais écrite :)
Danko Durbić

3
Merci pour cette plus jolie version =)
Thor Hovden

10

HyperTalk: 237 caractères

L'indentation n'est ni requise ni comptée. Il est ajouté pour plus de clarté. Notez également que HyperCard 2.2 accepte les opérateurs relationnels non ASCII que j'ai utilisés.

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

Puisque HyperCard 2.2 ne prend pas en charge stdin / stdout, une fonction est fournie à la place.


1
Hypercard, monsieur Adams? Sérieusement? C'est très inattendu.
Kawa

1
@Kawa: C'est un peu la raison pour laquelle je l'ai posté :) De plus, le code golf est un bon moyen de construire une suite de tests au cas où je déciderais d'écrire un interpréteur HyperTalk à l'avenir.
Joey Adams

Hah! J'aimerais voir ça, XD
Kawa

Si jamais vous décidez d'écrire cet interprète, ou si vous souhaitez rejoindre le travail sur un interprète existant, faites le moi savoir et je pourrai en ajouter une mention sur hypercard.org et je serais curieux de savoir comment cela se passe :-)
uliwitness

10

C #: 209202201 caractères:

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

Non minimisé:

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

Je ne connais pas beaucoup C # mais ne devriez-vous pas pouvoir utiliser string[]aet 1-r(au lieu de -1+r)?
kennytm

@Kenny: Vous avez raison. :) Cela sauve trois personnages, puis j'ai réussi à m'en débarrasser de cinq autres.
Guffa

Repéré cette première chose, totalement raté sur le -r+1truc.
Dykam

4
Aussi, repéré x*xx+++y*yaussi, mais c'est une chose folle à disséquer au premier coup d'œil.
Dykam

J'ai pris la liberté d'éliminer un autre octet ;-)
Joey

10

Haskell 139 145 147 150 230 caractères:

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

Gestion des nombres impairs: 148 caractères:

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 caractères: (Basé sur la version 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 caractères:

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 if y> r puis print n else cn (-r) >> = l (y + 2)}; l (1-r`mod`2-r) 0}

Non minimisé:

main = do r <- lire `fmap` getLine
          soit p = putStr
              d = 2 / fromIntegral r ^ 2
              lyn = soit cmx = si x> r
                                  puis p "\ n" >> retourne m
                                  sinon si x * x + y * y <r * r
                                       puis p "*" >> c (m + d) (x + 1)
                                       sinon p "" >> cm (x + 1)
                      dans si y> r
                         puis imprimez n
                         sinon cn (-r) >> = l (y + 2)
          l (1-r`mod`2-r) 0

J'espérais un peu qu'il battrait certaines des versions impératives, mais je n'arrive pas à le compresser davantage à ce stade.


Coupé 2 autres en supprimant le "d" et en ajoutant 1 à la place de celui-ci, puis en imprimant "2 * n / fromIntegral r ^ 2"
Steve

Rasé 3 personnages via quelques astuces Haskell. J'adore le fait que dans Haskell, il n'y a souvent aucun coût pour plusieurs lignes (nouvelle ligne ou point-virgule) et donc notre code-golf est généralement lisible!
MtnViewMark

À proprement parler, la version 145 caractères ne fonctionne que si l'entrée est paire. Mais très bien de toute façon.
Steve

Raccourcissement de la ligne d'E / S. Il devrait toujours être possible de sauver quelques caractères supplémentaires en poussant la fonction defs dans un bloc main = do {... let {...} ...}, je pense.
comingstorm

@comingstorm: Cool! Je ne connaissais pas readLn. Cela aidera de nombreux golfeurs à code Haskell. @Steve: Ouais, j'essaie toujours de trouver le moyen le plus efficace de résoudre ce problème.
MtnViewMark

10

Rubis, 96 caractères

(basé sur la solution C # de 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 caractères (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('*')

Merci! Je suis gêné de voir à quel point Ruby peut être illisible ... :)
Mladen Jablanović

vous pouvez également utiliser à la p splace de puts s:)
John La Rooy

1
Belles idées fraîches là-dedans - J'aime que vous utilisiez g avec 2 tailles de pas différentes et le <=> pour éviter d'avoir du code à convertir de logique
John La Rooy

9

PHP: 117

Basé sur 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

Vous pensez trop dur.

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

8
Le nombre de caractères devient un peu incontrôlable, vous ne pensez pas? :)
John La Rooy

7
Ne s'adapte pas. Incontournable!
spoulson

J'ai essayé de compresser la triche du cas de test autant que possible et cela a quand même fini légèrement plus grand que ma solution réelle: P
lunixbochs

5
+1, faites toujours la chose la plus évidente en premier ... si quelqu'un n'aime pas ça, plaignez-vous bruyamment que les spécifications
n'étaient

Brian a eu une tentative semi-sérieuse de casse spéciale des cas de test, vous devriez voter pour le sien aussi si vous aimez cette réponse;) stackoverflow.com/questions/2457995
John La Rooy

7

J: 47 , 46 , 45

Même idée de base que les autres solutions, c'est-à-dire r ^ 2 <= x ^ 2 + y ^ 2 , mais la notation orientée tableau de J simplifie l'expression:

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

Vous appelleriez ça comme c 2ou c 8ou c 10etc.

Bonus: 49

Pour gérer les entrées impaires, par exemple 13, nous devons filtrer sur des coordonnées x de valeur impaire, plutôt que de simplement prendre toutes les autres lignes de sortie (car maintenant les indices peuvent commencer à un nombre pair ou impair). Cette généralisation nous coûte 4 caractères:

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

Version déminimisée:

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
)

Améliorations et généralisations dues à Marshall Lochbam sur les J Forums .


5

Python: 118 caractères

À peu près un portage simple de la version 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

Pour python2, vous pouvez simplement utiliserr=input()
John La Rooy

Vous n'avez pas besoin de l'espace entre printet' '
John La Rooy

OK, c'est effrayant, c'est plus court que la version Perl maintenant. (J'ai complètement mis "l'entrée" hors de mon esprit parce que c'est tellement dangereux d'ordinaire ...)
Nicholas Riley

4

C ++: 169 caractères

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

Non minimisé:

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

(Oui, utiliser std :: au lieu d' using namespace stdutiliser moins de caractères)

La sortie ici ne correspond pas aux cas de test dans l'article d'origine, alors en voici un qui le fait (écrit pour la lisibilité). Considérez cela comme une implémentation de référence (si Poita_ ne le dérange pas):

#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 caractères (avec la sortie que je crois correcte)

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

Le code boucle de -n à n, donc pour une entrée de par exemple 4, il affiche un diamètre de 9, et non de 7 comme indiqué dans les cas de test.
Guffa

Est-il obligatoire que votre cercle corresponde exactement aux PO ?
Peter Alexander

3
Vous voudrez peut-être le changer pour #include <iostream.h>ce qui est essentiellement #include <iostream> -- using namespace std;pour la compatibilité avec les anciens compilateurs C ++.
Earlz

1
@Carlos, je n'ai pas écrit ce bit en particulier, mais c'est un opérateur binaire AND. Il vérifie que le dernier bit est activé, ce qui équivaut à faire i%2, mais est "plus rapide". Ce n'est pas vraiment plus rapide car le compilateur le ferait de toute façon.
Peter Alexander

1
@Poita_: En fait, i% 2 et i & 1 se comportent différemment avec des nombres négatifs. (-1) & 1 vaut 1, ce que nous voulons ici. (-1)% 2 est -1 sur mon système, et ceci est conforme à C99. Ainsi, bien que if (i & 1) et if (i% 2) fassent la même chose, il faut faire attention avec if (i% 2 == 1), qui ne fonctionnera pas lorsque i est négatif.
Joey Adams

3

PHP: 126 132 138

(basé sur la solution 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;

Courant plein:

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;

Peut être sans @avant le premier $smais uniquement avec error_reporting défini sur 0 (les sorties de notification perturbent le cercle)


que fait le / $ r dans echo $ s * 2 / $ r / $ r;
davidosomething

Division OHH ... l'espacement m'a jeté, je pensais que c'était une sténographie d'opérateur que je n'avais jamais vue
davidosomething

3

Rubis 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

Courir avec $ ruby -p piday


Nice one, mais il n'imprime pas l'approximation pi
John La Rooy

Cela ne fonctionne pas dans la version 1.9.1 et imprime des guillemets doubles autour du cercle.
Mladen Jablanović

Il est normal que les programmes de golf ne fonctionnent pas sur des niveaux linguistiques très différents. Combien de cg Perl ou Python fonctionnent sur chaque version du langage? Il est intéressant, cependant, que la raison en est que Integer|Floatne contraint plus le flotteur à 1.9.
DigitalRoss

3

APL: 59

Cette fonction accepte un nombre et renvoie les deux éléments attendus. Fonctionne correctement dans les cas bonus.

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

Le dialecte est Dyalog APL, avec l'origine d'index par défaut. Le niveau de compétence est un débutant désemparé , donc si un gourou APL veut le ramener à 10 personnages, soyez mon invité!


Vous pouvez l'essayer en ligne sur Try APL , collez-le simplement et mettez un numéro après:

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

Bien que je ne connaisse pas APL, il est plus joli que la version J.
ahala

@ahala En effet. APL est beau, à la fois conceptuellement et esthétiquement. J'ai commencé à apprendre J, mais j'ai été éteint par la folie aléatoire ASCII. Une bonne âme a écrit un interpréteur APL open source pour Node.js (npm install apl) qui est plutôt bien. Il calcule le code ci-dessus avec juste un changement mineur (pas de monadique , 2e car.) Vous pouvez trouver une bonne documentation APL sur tous les sites de fournisseurs, tels que Dyalog.
Tobia

2

Et une entrée bash: 181 186 190 caractères

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

Courir avec par exemple bash py.sh 13


2

Python: 148 caractères.

Échec (c'est-à-dire pas assez court) tentative d'abuser des règles et coder en dur les cas de test, comme je l'ai mentionné en réponse au message original. En abuser avec un langage plus verbeux aurait pu être plus 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 caractères

Basé sur la version 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 nouvelle ligne après la dernière ligne ne peut pas être omise ici.)


1
127 caractères: 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

Le seul problème ici est qu'il échoue maintenant pour 0, mais selon les règles actuelles, c'est ok.
przemoc

2

JavaScript (SpiderMonkey) - 118 caractères

Cette version accepte les entrées de stdin et réussit les cas de 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)

Utilisation: cat 10 | js thisfile.js - jsbin preview ajoute un alias pour print / readline afin que vous puissiez voir dans le navigateur

Javascript: 213 163


Actualisé

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

Personne n'a dit qu'il devait être rendu correctement dans le navigateur - juste la sortie. En tant que tel, j'ai supprimé les balises pré et optimisé davantage. Pour afficher la sortie, vous devez afficher la source générée ou définir votre feuille de style en conséquence. Pi est moins précis de cette façon, mais il est maintenant conforme aux spécifications.


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

Non minimisé:

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

Non minimisé:

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

Pourrait probablement économiser ~ 50 caractères en réécrivant ceci dans scala
rwyland

1

GAWK: 136 , 132 , 126 , 125 caractères

Basé sur la version 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}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.