Code Golf - π hari


95

Tantangan

Panduan untuk kode-golf di SO

Kode terpendek menurut hitungan karakter untuk menampilkan representasi lingkaran jari-jari Rmenggunakan *karakter, diikuti dengan perkiraan π.

Input berupa angka tunggal R,.

Karena kebanyakan komputer tampaknya memiliki rasio hampir 2: 1, Anda seharusnya hanya mengeluarkan jalur yyang ganjil. Ini berarti ketika Rganjil Anda harus mencetak R-1garis. Ada kasus percobaan baru untuk R=13memperjelas.

misalnya.

Input
    5
Output      Correct                          Incorrect

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

Sunting: Karena kebingungan luas yang disebabkan oleh nilai ganjil R, solusi apa pun yang lolos dari 4 kasus uji yang diberikan di bawah ini akan diterima

Perkiraan π diberikan dengan membagi dua kali jumlah *karakter dengan .
Perkiraan harus benar hingga setidaknya 6 digit signifikan.
Terkemuka atau trailing nol diijinkan, jadi misalnya salah 3, 3.000000, 003diterima untuk masukan dari 2dan 4.

Hitungan kode termasuk input / output (yaitu, program penuh).

Kasus Uji

Input
    2
Output
     *** 
     *** 
    3.0

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

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

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

Kasus Uji Bonus

Input
    13
Output

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

Anda mungkin ingin mengklarifikasi apakah "input" ada di baris perintah, atau di stdin.
Greg Hewgill

1
@Greg Hewgill, Jangan ragu untuk memilih mana yang paling nyaman untuk bahasa yang Anda gunakan :)
John La Rooy

@ Greg Hewgill, Beberapa (yaitu, sangat sedikit) implementasi bahasa pemrograman tidak memiliki pengertian tentang "baris perintah".
Joey Adams

1
Saya perhatikan bahwa beberapa jawaban mengikuti aturan hanya meletakkan baris di mana y ganjil. Diberikan nilai ganjil r (tidak ditampilkan dalam kasus uji), sebagian besar akan menampilkan baris di mana y genap!
MtnViewMark

6
Tantangan penyalahgunaan aturan: Buat kode yang lebih pendek dari kode orang lain dengan hanya mendukung 4 kasus pengujian yang diperlukan.
Brian

Jawaban:


15

Dalam dc: 88 dan 93 93 94 96 102 105129 138 141 karakter

Untuk berjaga-jaga, saya menggunakan OpenBSD dan beberapa ekstensi yang seharusnya tidak portabel pada saat ini.

93 karakter. Ini didasarkan pada rumus yang sama dengan solusi FORTRAN (hasil yang sedikit berbeda dari kasus uji). Menghitung X ^ 2 = R ^ 2-Y ^ 2 untuk setiap Y

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

88 karakter. Solusi berulang. Cocok dengan kasus uji. Untuk setiap X dan Y periksa apakah 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

Untuk lari dc pi.dc.

Ini adalah versi beranotasi yang lebih lama:

# 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
Tidak berfungsi dengan linux dc, tetapi saya dapat memastikan bahwa ini berfungsi pada openbsd . Hebat!
John La Rooy

@Carlos, ya (operatornya pasti berguna. sayang sekali itu tetap tidak diterapkan di dc yang datang dengan linux
John La Rooy

@gnibbler - "Penulisan ulang lengkap dari perintah dc menggunakan rutin bn (3) angka besar pertama kali muncul di OpenBSD 3.5." Saya tidak tahu itu. Beberapa operator baru yang bagus disertakan, tetapi mereka ditandai sebagai "ekstensi non-portabel".
Carlos Gutiérrez

Ya, (hanya operator yang diizinkan untuk melepaskan 6 pukulan!
Dan Andreatta

119

C: 131 karakter

(Berdasarkan solusi C ++ oleh 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);}

(Ubah i|=-nmenjadi i-=nuntuk menghapus dukungan kasus angka ganjil. Ini hanya mengurangi jumlah karakter menjadi 130.)

Sebagai lingkaran:

      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
Saya suka cara Anda menambahkan lingkaran ke kode untuk mengubahnya menjadi lingkaran. Apakah +000 lebih disukai?
Potatoswatter

selamat, j * j ++ adalah perilaku tidak terdefinisi
sellibitze

1
bukankah itu hanya satu karakter ...?
Ponkadoodle

1
Bagaimana main()mengambil empat intargumen?
David R Tribble

2
@Load: 5.1.2.2.1 / 1: Fungsi yang dipanggil saat program startup dinamai main. Ini harus didefinisikan… atau dalam beberapa cara implementasi yang ditentukan lainnya . Itu karena pelaksana bisa menerima formulir ini.
kennytm

46

XSLT 1.0.2 Memperbarui

Hanya untuk bersenang-senang, inilah versi XSLT. Bukan materi kode-golf, tetapi memecahkan masalah dengan cara yang aneh-fungsional-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>

Jika Anda ingin mengujinya, simpan sebagai pi.xsltdan buka file XML berikut di IE:

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

42
<eyes> </eyes> saya! Kacamata, mereka <do> tidak ada </do>!
Jimmy

1
Sial! Saya khawatir Anda mungkin telah mengalahkan solusi HyperCard saya karena keunikan: D
Joey Adams

7
Saya tidak percaya Anda mengatakan "buka ... IE"
harpo

Heh, ya, dulu, kami hanya memiliki IE dan XML dengan XSLT adalah solusi untuk semua masalah kami. Masa lalu yang indah! :)
Danko Durbić

XSL versi 1.0 wow, saya ingat menantikan versi 2 tetapi pada saat keluar saya sudah pindah.
gradbot

35

Perl, 95 96 99 106 109 110 119 karakter:

$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

(Baris baru dapat dihapus dan hanya ada untuk menghindari scrollbar)

Yay! Versi lingkaran!

    $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

Untuk yang belum tahu, versi panjang:

#!/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
Sejauh ini, itu adalah kode yang paling tidak terbaca yang pernah saya lihat sepanjang hidup saya
Chris Marisic

13
Saya kira Anda belum pernah melihat APL saat itu.
Peter Wone

5
@ Chris Marisic: Apakah Anda memeriksa pertanyaan / topik lain yang diberi tag code-golf? :) Saya telah melihat contoh yang jauh lebih tidak terbaca.
BalusC

3
@ Peter: Tidak seperti kebanyakan, saya telah melihat dan menulis APL. Dibutuhkan beberapa minggu untuk membiasakan diri dengan karakter khususnya, tetapi setelah itu bisa sangat mudah dibaca. Bahkan setelah beberapa dekade menjadi terbiasa, Perl masih jauh lebih buruk.
Jerry Coffin

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

$ 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

Tunggu, saya pikir pemformatan itu penting di Fortran? Anda memiliki surat di kolom 1!
Joel

Kebanyakan orang masih terjebak di Fortan77 dari apa yang saya lihat.
Joel

8
Saya suka bagaimana versi lingkaran terlihat seperti Death Star.
mskfisher

22

Kode Mesin x86: 127 byte

Intel Assembler: 490 karakter

    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

Versi ini juga menangani kasus uji bonus dan berukuran 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
Saya suka StackOverflow!
zengr

2
Sangat menarik bahwa beberapa bahasa tingkat tinggi memiliki jumlah karakter yang lebih pendek daripada biner yang dihasilkannya.
Colin Valliant

3
@Alcari: Jika Anda menyertakan semua kode di perpustakaan yang digunakan bahasa tingkat yang lebih tinggi, jumlah karakter mereka akan jauh lebih tinggi. Dalam assembler, melakukan printf("%f",a/b)bukanlah hal sepele, tidak ada instruksi tunggal untuk melakukan itu, dan implementasi saya di atas mengasumsikan bahwa 0 <= a / b <10 dan bahwa operasi itu adalah sebuah divisi dan bahwa a dan b adalah bilangan bulat.
Skizz

19

Python: 101 104 107 110 chars

Berdasarkan versi Python lainnya oleh 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

Penghargaan untuk AlcariTheMad untuk beberapa matematika.


Ah, yang ganjil diindeks dengan nol sebagai tengah, menjelaskan semuanya.

Bonus Python: 115 karakter (dengan cepat diretas)

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, yeah, '+' mengalahkan -1 dan, kapan saja. Namun teknik lain yang saya keluarkan dari pikiran saya karena itu hampir tidak pernah menjadi hal yang benar untuk dilakukan :-)
Nicholas Riley

Saya telah menggunakan C di masa lalu, dan bahkan tidak pernah melihat Python. 104 karakter ini lebih mudah dibaca daripada C ++ di atas. Luar biasa. Mungkin aku harus belajar Python ...
Dean Agak

@Dean: Salah satu tujuan utama Python adalah mudah dibaca dan ditulis.
Colin Valliant

Pernahkah Anda berpikir tentang menggunakan exec dengan jawaban 104 karakter Anda juga? :)
John La Rooy

Saya perlu menggulung kompresi saya sendiri - zlib, marshalling, dll semuanya keluar lebih besar dari kode sebenarnya.
lunixbochs

12

Powershell, 119 113 109 karakter

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

dan inilah versi yang lebih cantik:

( $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: Saya harap tidak, tapi ini pasti hal paling jelek yang pernah saya tulis :)
Danko Durbić

3
Terima kasih untuk versi yang lebih cantik itu =)
Thor Hovden

10

HyperTalk: 237 karakter

Indentasi tidak diperlukan atau dihitung. Itu ditambahkan untuk kejelasan. Perhatikan juga bahwa HyperCard 2.2 menerima operator relasional non-ASCII yang saya gunakan.

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

Karena HyperCard 2.2 tidak mendukung stdin / stdout, fungsi disediakan sebagai gantinya.


1
Hypercard, Tn. Adams? Sungguh? Ini sangat tidak terduga.
Kawa

1
@Kawa: Itulah alasan mengapa saya mempostingnya :) Selain itu, golf kode adalah cara yang baik untuk membangun rangkaian pengujian jika saya memutuskan untuk menulis penerjemah HyperTalk di masa mendatang.
Joey Adams

Hah! Saya ingin melihat itu, XD
Kawa

Jika Anda pernah memutuskan untuk menulis penerjemah itu, atau ingin bergabung dengan penerjemah yang sudah ada, beri tahu saya dan saya dapat menambahkan
sebutannya

10

C #: 209 202.201 karakter:

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

Tidak diminimalkan:

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

Saya tidak tahu banyak tentang C # tetapi bukankah seharusnya Anda dapat menggunakan string[]adan 1-r(sebagai pengganti -1+r)?
kennytm

@Ken: Anda benar. :) Itu menghemat tiga karakter, dan kemudian saya berhasil menyingkirkan lima karakter lainnya.
Guffa

Melihat hal pertama itu, benar-benar melewatkan hal itu -r+1.
Dykam

4
Juga, terlihat x*xx+++y*yjuga, tetapi itu adalah hal gila untuk membedah pada pandangan pertama.
Dykam

Saya mengambil kebebasan untuk menghilangkan byte lain ;-)
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

Menangani angka ganjil: 148 karakter:

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 karakter: (Berdasarkan versi 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 karakter:

main = lakukan {r <-read`fmap`getLine; let {p = putStr; d = 2 / fromIntegral r ^ 2; lyn = let cmx = if x> r lalu p "\ n" >> kembalikan m else if x * x + y * y <r * r lalu p "*" >> c (m + d) (x + 1) else p "" >> cm (x + 1) in if y> r lalu cetak n lain cn (-r) >> = l (y + 2)}; l (1-r`mod`2-r) 0}

Tidak diminimalkan:

main = do r <- baca `fmap` getLine
          misalkan p = putStr
              d = 2 / dari Integral r ^ 2
              lyn = misalkan cmx = jika x> r
                                  lalu p "\ n" >> kembali m
                                  lain jika x * x + y * y <r * r
                                       lalu p "*" >> c (m + d) (x + 1)
                                       lain p "" >> cm (x + 1)
                      di if y> r
                         kemudian cetak n
                         lain cn (-r) >> = l (y + 2)
          l (1-r`mod`2-r) 0

Saya agak berharap ini akan mengalahkan beberapa versi imperatif, tetapi sepertinya saya tidak dapat mengompresnya lebih jauh pada saat ini.


Potong 2 lagi dengan menghilangkan "d" dan menambahkan 1 sebagai gantinya dan kemudian mencetak "2 * n / fromIntegral r ^ 2"
Steve

Mencukur 3 karakter melalui beberapa trik Haskell. Saya suka bahwa di Haskell sering kali tidak ada biaya untuk beberapa baris (baris baru vs. titik koma) dan karenanya kode-golf kami umumnya dapat dibaca!
MtnViewMark

Sebenarnya, versi 145 karakter hanya bekerja jika masukannya genap. Tapi bagaimanapun juga sangat bagus.
Steve

Mempersingkat jalur I / O. Seharusnya masih mungkin untuk menyimpan beberapa karakter lagi dengan mendorong fungsi defs ke dalam blok main = do {... let {...} ...}, saya kira.
badai datang

@comingorm: Keren! Saya tidak tahu tentang readLn. Ini akan membantu banyak kode-golf Haskell. @ Steve: Ya, saya masih mencoba mencari cara paling efisien untuk memperbaikinya.
MtnViewMark

10

Ruby, 96 karakter

(berdasarkan solusi C # 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 karakter (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('*')

Terima kasih! Saya malu melihat bagaimana Ruby yang tidak terbaca bisa ... :)
Mladen Jablanović

Anda juga dapat menggunakan p ssebagai pengganti puts s:)
John La Rooy

1
Ide segar yang bagus di sana - Saya suka Anda menggunakan g dengan 2 ukuran langkah yang berbeda dan <=> untuk menghindari kode yang akan diubah dari logika
John La Rooy

9

PHP: 117

Berdasarkan 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

Kalian berpikir terlalu keras.

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

8
Hitungan karakter menjadi sedikit di luar kendali, bukan begitu? :)
John La Rooy

7
Tidak berskala. Tak bisa dipertahankan!
spoulson

Saya mencoba mengompresi cheat kasus uji sebanyak mungkin dan hasilnya masih sedikit lebih besar dari solusi saya yang sebenarnya: P
lunixbochs

5
+1, selalu lakukan hal yang paling jelas dulu ... jika seseorang tidak menyukainya, dengan lantang mengeluh bahwa
speknya

Brian memiliki upaya semi-serius pada casing khusus kasus uji, Anda harus upvote juga jika Anda menyukai jawaban ini;) stackoverflow.com/questions/2457995
John La Rooy

7

J: 47 , 46 , 45

Ide dasar yang sama dengan solusi lain, yaitu r ^ 2 <= x ^ 2 + y ^ 2 , tetapi notasi berorientasi array J menyederhanakan ekspresi:

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

Anda akan menyebutnya seperti c 2atau c 8atau c 10dll.

Bonus: 49

Untuk menangani masukan ganjil, misalnya 13, kita harus memfilter pada koordinat x bernilai ganjil, daripada hanya mengambil setiap baris keluaran lainnya (karena sekarang indeks dapat dimulai dari bilangan genap atau ganjil). Generalisasi ini membutuhkan 4 karakter:

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

Versi yang dihilangkan:

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
)

Perbaikan dan generalisasi karena Marshall Lochbam di J Forums .


5

Python: 118 karakter

Cukup banyak port langsung dari versi 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

Untuk python2, Anda bisa menggunakanr=input()
John La Rooy

Anda tidak perlu spasi antara printdan' '
John La Rooy

Oke, itu menakutkan, ini lebih pendek dari versi Perl sekarang. (Saya benar-benar mengeluarkan "masukan" dari pikiran saya karena biasanya sangat tidak aman ...)
Nicholas Riley

4

C ++: 169 karakter

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

Tidak diminimalkan:

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

(Ya, menggunakan std :: daripada using namespace stdmenggunakan lebih sedikit karakter)

Keluarannya di sini tidak cocok dengan kasus uji di pos asli, jadi inilah yang cocok (ditulis agar mudah dibaca). Anggap saja sebagai implementasi referensi (jika Poita_ tidak keberatan):

#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 karakter (dengan keluaran yang saya yakini benar)

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

Kode loop dari -n ke n, jadi untuk input misalnya 4 menampilkan diameter 9, bukan 7 seperti yang ditunjukkan dalam kasus uji.
Guffa

Apakah itu persyaratan bahwa lingkaran Anda sama persis dengan OP ?
Peter Alexander

3
Anda mungkin ingin mengubahnya #include <iostream.h>yang pada dasarnya adalah #include <iostream> -- using namespace std;untuk kompatibilitas dengan kompiler C ++ lama.
Earlz

1
@Carlos, saya tidak menulis bit khusus itu, tetapi ini adalah operator DAN biner. Ia memeriksa bahwa bit terakhir disetel, yang setara dengan melakukan i%2, tetapi "lebih cepat". Ini tidak benar-benar lebih cepat karena kompiler akan tetap melakukannya.
Peter Alexander

1
@Poita_: Sebenarnya, i% 2 dan i & 1 berperilaku berbeda dengan bilangan negatif. (-1) & 1 adalah 1, yang kita inginkan di sini. (-1)% 2 adalah -1 di sistem saya, dan ini sesuai dengan C99. Jadi, meskipun jika (i & 1) dan jika (i% 2) akan melakukan hal yang sama, kita harus berhati-hati dengan if (i% 2 == 1), yang tidak akan berfungsi ketika i negatif.
Joey Adams

3

PHP: 126132138

(berdasarkan solusi 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;

Penuh saat ini:

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;

Bisa tanpa @before first $stetapi hanya dengan error_reporting disetel ke 0 (Output pemberitahuan mengacaukan lingkaran)


apa yang / $ r lakukan di echo $ s * 2 / $ r / $ r;
davidosomething

Divisi OHH ... jarak membuat saya
bingung

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

Jalankan dengan $ ruby -p piday


Bagus, tapi tidak mencetak perkiraan pi
John La Rooy

Ini tidak berfungsi di 1.9.1, dan mencetak tanda kutip ganda di sekitar lingkaran.
Mladen Jablanović

Adalah normal jika program golf tidak bekerja pada tingkat bahasa yang sangat berbeda. Berapa banyak Perl atau Python cg yang bekerja pada setiap versi bahasa? Menariknya, ternyata alasannya karena Integer|Floattidak lagi memaksa float di 1.9.
DigitalRoss

3

APL: 59

Fungsi ini menerima angka dan mengembalikan dua item yang diharapkan. Bekerja dengan benar dalam kasus bonus.

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

Dialeknya adalah Dyalog APL, dengan asal indeks default. Tingkat keahlian adalah pemula yang tidak mengerti , jadi jika ada guru APL yang ingin menurunkannya menjadi 10 karakter, jadilah tamu saya!


Anda dapat mencobanya secara online di Try APL , cukup tempel dan beri nomor setelahnya:

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

Meskipun saya tidak tahu APL, tampilannya lebih cantik dari versi J.
ahala

@ahala Memang. APL itu indah, baik secara konseptual maupun estetis. Saya mulai belajar J, tetapi dimatikan oleh kegilaan ASCII yang acak. Jiwa yang baik menulis interpreter APL open source untuk Node.js (npm install apl) yang cukup bagus. Ini menghitung kode di atas hanya dengan sedikit perubahan (tanpa monadik , karakter kedua.) Anda dapat menemukan dokumentasi APL yang bagus di semua situs vendor, seperti Dyalog.
Tobia

2

Dan entri 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

Jalankan dengan mis bash py.sh 13


2

Python: 148 karakter.

Gagal (yaitu tidak cukup pendek) mencoba untuk menyalahgunakan aturan dan hardcode kasus uji, seperti yang saya sebutkan di balasan posting asli. Menyalahgunakannya dengan bahasa yang lebih verbose mungkin lebih mudah:

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 karakter

Berdasarkan versi 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

(Baris baru setelah baris terakhir tidak dapat dihilangkan di sini.)


1
127 karakter: 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

Satu-satunya masalah di sini adalah sekarang gagal untuk 0, tetapi menurut aturan saat ini, tidak apa-apa.
przemoc

2

JavaScript (SpiderMonkey) - 118 karakter

Versi ini menerima masukan dari stdin dan lolos uji kasus 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)

Penggunaan: cat 10 | js thisfile.js - Pratinjau jsbin menambahkan alias untuk print / readline sehingga Anda dapat melihat di browser

Javascript: 213 163


Diperbarui

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

Tidak ada yang mengatakan itu harus merender dengan benar di browser - hanya outputnya. Karena itu saya telah menghapus tag awal dan mengoptimalkannya lebih lanjut. Untuk melihat output, Anda perlu melihat sumber yang dihasilkan atau mengatur stylesheet Anda sesuai. Pi kurang akurat dengan cara ini, tetapi sekarang untuk spesifikasi.


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

Tidak diminimalkan:

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

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

Tidak diminimalkan:

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

Mungkin bisa menghemat ~ 50 karakter menulis ulang ini dalam skala
rwyland

1

GAWK: 136 , 132 , 126 , 125 karakter

Berdasarkan versi 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}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.