Code Golf - dzień π


95

Wyzwanie

Wytyczne dotyczące code-golfa na SO

Najkrótszy kod według liczby znaków do wyświetlenia reprezentacji okręgu o promieniu Rza pomocą *znaku, po którym następuje przybliżenie π.

Wejście jest jeden numer, R.

Ponieważ większość komputerów ma stosunek prawie 2: 1, powinieneś wypisywać tylko linie tam, gdzie yjest nieparzyste. Oznacza to, że kiedy Rjest dziwne, powinieneś wydrukować R-1linie. R=13Do wyjaśnienia jest nowy przypadek testowy .

na przykład.

Input
    5
Output      Correct                          Incorrect

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

Edycja: Ze względu na powszechne zamieszanie spowodowane nieparzystymi wartościami R, wszelkie rozwiązania, które przejdą poniższe 4 przypadki testowe, zostaną zaakceptowane

Przybliżenie liczby π oblicza się, dzieląc dwukrotnie liczbę *znaków przez .
Przybliżenie powinno być poprawne do co najmniej 6 cyfr znaczących.
Początkowe i końcowe zera są dozwolone, więc na przykład każdy z 3, 3.000000, 003została przyjęta do wejść 2i 4.

Liczba kodów obejmuje wejście / wyjście (tj. Pełny program).

Przypadki testowe

Input
    2
Output
     *** 
     *** 
    3.0

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

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

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

Dodatkowy przypadek testowy

Input
    13
Output

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

Możesz chcieć wyjaśnić, czy "wejście" znajduje się w linii poleceń, czy na stdin.
Greg Hewgill

1
@Greg Hewgill, Nie krępuj się wybrać tego, który jest najwygodniejszy dla używanego języka :)
John La Rooy

@Greg Hewgill, Niektóre (to znaczy bardzo nieliczne) implementacje języków programowania nie mają pojęcia „wiersza poleceń”.
Joey Adams,

1
Zauważyłem, że niewiele odpowiedzi jest zgodnych z zasadą umieszczania tylko linii, w których y jest nieparzysta. Biorąc pod uwagę nieparzystą wartość r (nie pokazaną w przypadkach testowych), większość wyświetli wiersze, w których y jest parzyste!
MtnViewMark

6
Wyzwanie związane z nadużyciem reguł: stwórz kod krótszy niż kod kogokolwiek innego, obsługując tylko 4 wymagane przypadki testowe.
Brian

Odpowiedzi:


15

W dc: 88 i 93 93 94 96 102 105 129 138 141 znaków

Na wszelki wypadek używam w tym momencie OpenBSD i niektórych rzekomo nieprzenośnych rozszerzeń.

93 znaków. Jest to oparte na tej samej formule co rozwiązanie FORTRAN (wyniki nieco inne niż w przypadku testów). Oblicza X ^ 2 = R ^ 2-Y ^ 2 dla każdego Y

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

88 znaków. Rozwiązanie iteracyjne. Pasuje do przypadków testowych. Dla każdego X i Y sprawdza, czy 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

Biegać dc pi.dc.

Oto starsza wersja z adnotacjami:

# 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
Nie działa z linux dc, ale mogę potwierdzić, że działa na openbsd . Niesamowite!
John La Rooy,

@Carlos, tak, (operator z pewnością jest przydatny. szkoda, że ​​pozostaje nie zaimplementowany w DC, który jest dostarczany z Linuksem
John La Rooy

@gnibbler - "Całkowite przepisanie polecenia dc przy użyciu procedur dużych liczb bn (3) pojawiło się po raz pierwszy w OpenBSD 3.5." Nie wiedziałem tego. Dołączono kilka ładnych nowych operatorów, ale są one oznaczone jako „nieprzenośne rozszerzenia”.
Carlos Gutiérrez

Tak, (sam operator pozwolił rzucić 6 uderzeń!
Dan Andreatta

119

C: 131 znaków

(W oparciu o rozwiązanie C ++ autorstwa Joey'a)

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

(Zmień na, i|=-naby i-=nusunąć obsługę przypadków nieparzystych. Zmniejsza to tylko liczbę znaków do 130).

W kręgu:

      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
Podoba mi się, jak dodałeś kręgi do kodu, aby przekształcić go w okrąg. Czy +000 byłoby lepsze?
Potatoswatter

gratulacje, j * j ++ to niezdefiniowane zachowanie
sellibitze

1
czy to nie byłaby tylko jedna postać ...?
Ponkadoodle

1
Jak main()przyjmuje się cztery intargumenty?
David R Tribble

2
@Load: 5.1.2.2.1 / 1: Nazwa funkcji wywoływana podczas uruchamiania programu main. Powinien zostać określony… lub w inny sposób określony w ramach realizacji . To dlatego, że implementacja może zaakceptować ten formularz.
kennytm

46

XSLT 1.0

Dla zabawy, oto wersja XSLT. Niezupełnie materiał kodujący golfa, ale rozwiązuje problem w dziwnie funkcjonalny sposób w stylu 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>

Jeśli chcesz to przetestować, zapisz go jako pi.xslti otwórz następujący plik XML w IE:

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

42
moje <eyes> </eyes>! Gogle, one <do> nic </do>!
Jimmy

1
Cholera! Obawiam się, że mogłeś pobić moje rozwiązanie HyperCard pod względem wyjątkowości: D
Joey Adams

7
Nie mogę uwierzyć, że powiedziałeś „otwórz ... IE”
harpo

Hej, tak, kiedyś mieliśmy tylko IE i XML, a XSLT był rozwiązaniem wszystkich naszych problemów. Stare dobre czasy! :)
Danko Durbić

XSL w wersji 1.0 wow, pamiętam, że nie mogłem się doczekać wersji 2, ale zanim się pojawiła, już przeszedłem.
gradbot

35

Perl, 95 96 99 106 109 110 119 postacie:

$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

(Nowa linia może zostać usunięta i jest tam tylko po to, aby uniknąć paska przewijania)

Yay! Wersja Circle!

    $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

Dla niewtajemniczonych długa wersja:

#!/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
To zdecydowanie najbardziej nieczytelny kod, jaki widziałem w całym moim życiu
Chris Marisic,

13
Chyba nigdy nie widziałeś wtedy APL.
Peter wygrał

5
@Chris Marisic: Czy sprawdziłeś inne otagowane pytania / tematy code-golf? :) Widziałem dużo więcej nieczytelnych przykładów.
BalusC

3
@Peter: W przeciwieństwie do większości, widziałem i pisałem APL. Przyzwyczajenie się do znaków specjalnych zajmuje kilka tygodni, ale potem może być całkiem czytelne. Nawet po kilku dekadach przyzwyczajania się, Perl jest nadal znacznie gorszy.
Jerry Coffin

1
111 znaków,$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 znaków

$ 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

Czekaj, myślałem, że formatowanie było ważne w Fortranie? Masz litery w kolumnie 1!
Joel

Z tego, co widziałem, większość ludzi wciąż utknęła na Fortan77.
Joel

8
Podoba mi się, jak wersja koła wygląda jak Gwiazda Śmierci.
mskfisher

22

Kod maszynowy x86: 127 bajtów

Intel Assembler: 490 znaków

    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

Ta wersja obsługuje również bonusowy przypadek testowy i ma 133 bajty:

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

2
Interesujące jest to, że niektóre języki wysokiego poziomu mają mniejszą liczbę znaków niż liczba binarna, którą tworzy.
Colin Valliant

3
@Alcari: Jeśli umieścisz cały kod w bibliotekach używanych przez języki wyższego poziomu, ich liczba znaków byłaby znacznie wyższa. W asemblerze robienie printf("%f",a/b)nie jest trywialne, nie ma jednej instrukcji, aby to zrobić, a moja powyższa implementacja zakłada, że ​​0 <= a / b <10 i że operacja jest dzieleniem, a aib są liczbami całkowitymi.
Skizz

19

Python: 101 104 107 110 znaków

Oparty na innej wersji Pythona autorstwa Nicholasa Rileya.

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

Kredyty dla AlcariTheMad za część matematyki.


Ach, nieparzyste są indeksowane z zerem jako środkiem, wyjaśnia wszystko.

Bonus Python: 115 znaków (szybko zhakowane razem)

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, tak, „+” bije -1 i każdego dnia. Kolejna technika, o której zapomniałem, ponieważ prawie nigdy nie jest to właściwe :-)
Nicholas Riley

Używałem C w przeszłości i nigdy nawet nie spojrzałem na Pythona. Te 104 znaki są bardziej czytelne niż powyższe C ++. Niesamowity. Może powinienem nauczyć się Pythona ...
Dean Rather

@Dean: Jednym z głównych celów Pythona jest łatwość czytania i pisania.
Colin Valliant

czy myślałeś o używaniu exec z odpowiedzią na 104 znaki? :)
John La Rooy

Musiałbym skręcić własną kompresję - zlib, marshalling itp.Wszystko wyszło większe niż rzeczywisty kod.
lunixbochs

12

Powershell, 119 113 109 znaków

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

a oto ładniejsza wersja:

( $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: Mam nadzieję, że nie, ale to chyba najbrzydsza rzecz, jaką kiedykolwiek napisałem :)
Danko Durbić

3
Dzięki za tę ładniejszą wersję =)
Thor Hovden

10

HyperTalk: 237 znaków

Wcięcia nie są wymagane ani liczone. Jest dodawany dla przejrzystości. Zauważ również, że HyperCard 2.2 akceptuje te operatory relacyjne inne niż ASCII, których użyłem.

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

Ponieważ HyperCard 2.2 nie obsługuje stdin / stdout, zamiast tego dostarczana jest funkcja.


1
Hypercard, panie Adams? Poważnie? To jest wysoce nieoczekiwane.
Kawa,

1
@Kawa: Właśnie dlatego to opublikowałem :) Ponadto golf kodu to dobry sposób na zbudowanie zestawu testów na wypadek, gdyby w przyszłości zdecydował się napisać tłumacza HyperTalk.
Joey Adams,

Hah! Chciałbym to zobaczyć, XD
Kawa

Jeśli kiedykolwiek zdecydujesz się napisać do tego tłumacza lub zechcesz przyłączyć się do pracy nad już istniejącym, daj mi znać, a mogę dodać wzmiankę o tym na hypercard.org i byłbym ciekawy jak to idzie :-)
uliwitness

10

C #: 209 202 201 znaków:

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

Niezminifikowane:

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

Nie znam języka C # za bardzo, ale czy nie powinieneś móc używać string[]ai 1-r(zamiast -1+r)?
kennytm

@Kenny: Masz rację. :) To oszczędza trzy postacie, a potem udało mi się pozbyć kolejnych pięciu.
Guffa

Zauważyłem tę pierwszą rzecz, całkowicie przegapioną -r+1.
Dykam,

4
Również zauważony x*xx+++y*y, ale na pierwszy rzut oka rozbiórka jest szalona.
Dykam

Pozwoliłem sobie wyeliminować kolejny bajt ;-)
Joey

10

Haskell 139 145 147 150 230 znaków:

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

Obsługa liczb nieparzystych: 148 znaków:

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 znaków: (na podstawie wersji 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 znaków:

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

Niezminifikowane:

main = do r <- przeczytaj `fmap` getLine
          niech p = putStr
              d = 2 / fromIntegral r ^ 2
              lyn = niech cmx = jeśli x> r
                                  następnie p "\ n" >> powrót m
                                  inaczej, jeśli x * x + y * y <r * r
                                       następnie p "*" >> c (m + d) (x + 1)
                                       else p "" >> cm (x + 1)
                      jeśli y> r
                         następnie wydrukuj n
                         else cn (-r) >> = l (y + 2)
          l (1-r`mod`2-r) 0

Miałem nadzieję, że pokona niektóre imperatywne wersje, ale w tym momencie nie mogę go bardziej skompresować.


Odciąłem jeszcze 2, usuwając „d” i dodając 1 zamiast niego, a następnie wypisując „2 * n / fromIntegral r ^ 2”
Steve

Ogoliłem 3 postacie za pomocą kilku sztuczek Haskella. Uwielbiam to, że w Haskell często nie ma kosztu wielu wierszy (znak nowej linii lub średnika), a zatem nasz kodowy golf jest ogólnie czytelny!
MtnViewMark

Ściśle mówiąc, wersja 145-znakowa działa tylko wtedy, gdy dane wejściowe są parzyste. Ale tak czy inaczej bardzo miło.
Steve

Skrócono linię I / O. Wydaje mi się, że nadal powinno być możliwe uratowanie kilku dodatkowych znaków przez umieszczenie funkcji defs w bloku main = do {... let {...} ...}.
nadchodząca burza

@comingstorm: Super! Nie wiedziałem o readLn. Pomoże to wielu golfistom z kodem Haskell. @Steve: Tak, wciąż próbuję znaleźć najbardziej skuteczny sposób, aby to naprawić.
MtnViewMark

10

Ruby, 96 znaków

(w oparciu o rozwiązanie Guffa w C #):

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

Dzięki! Wstydzę się zobaczyć, jak nieczytelny może być Ruby ... :)
Mladen Jablanović

możesz też użyć p szamiast puts s:)
John La Rooy

1
Są tam fajne, świeże pomysły - podoba mi się, że używasz g z 2 różnymi rozmiarami kroków i <=>, aby uniknąć konieczności konwersji kodu z logicznego
John La Rooy

9

PHP: 117

Na podstawie 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

Myślicie zbyt mocno.

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

8
Liczba znaków wymyka się spod kontroli, nie sądzisz? :)
John La Rooy

7
Nie skaluje się. Nie do utrzymania!
spoulson

Próbowałem skompresować
kod

5
+1, zawsze najpierw rób najbardziej oczywistą rzecz ... jeśli komuś się to nie podoba, głośno narzekaj, że specyfikacja nie jest wystarczająco jasna
Mizipzor

Brian podjął półpoważną próbę specjalnego opisania przypadków testowych, ty też powinieneś zagłosować za jego, jeśli podoba ci się ta odpowiedź;) stackoverflow.com/questions/2457995
John La Rooy

7

J: 47 , 46 , 45

Taka sama podstawowa idea jak inne rozwiązania, tj. R ^ 2 <= x ^ 2 + y ^ 2 , ale notacja J zorientowana na tablicę upraszcza wyrażenie:

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

Można by nazwać to jak c 2albo c 8czy c 10itd.

Bonus: 49

Aby obsłużyć na przykład nieparzyste dane wejściowe, 13musimy filtrować według nieparzystych współrzędnych x, zamiast po prostu pobierać co drugi wiersz danych wyjściowych (ponieważ teraz indeksy mogą zaczynać się od liczby parzystej lub nieparzystej). To uogólnienie kosztuje nas 4 znaki:

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

Wersja zminimalizowana:

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
)

Ulepszenia i uogólnienia powodu Marshall Lochbam na forach J .


5

Python: 118 znaków

Dość prosty port wersji Perla.

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

W przypadku pythona2 możesz po prostu użyćr=input()
John La Rooy

Nie potrzebujesz spacji między printa' '
John La Rooy

OK, to przerażające, jest teraz krótsze niż wersja Perla. (Całkowicie zapomniałem o „wkładzie”, ponieważ zazwyczaj jest to niebezpieczne ...)
Nicholas Riley,

4

C ++: 169 znaków

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

Niezminifikowane:

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

(Tak, używając std :: zamiast using namespace stdużywa mniej znaków)

Wynik tutaj nie pasuje do przypadków testowych w oryginalnym poście, więc oto taki, który tak (napisany dla czytelności). Potraktuj to jako implementację referencyjną (jeśli Poita_ nie ma nic przeciwko):

#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 znaków (wydaje mi się, że dane wyjściowe są poprawne)

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

Kod zapętla się od -n do n, więc dla wejścia na przykład 4 wyświetla średnicę 9, a nie 7, jak pokazano w przypadkach testowych.
Guffa

Czy wymagane jest, aby Twój krąg dokładnie pasował do OP ?
Peter Alexander

3
Możesz chcieć to zmienić na #include <iostream.h>zasadniczo #include <iostream> -- using namespace std;dla zgodności ze starymi kompilatorami C ++.
Earlz

1
@Carlos, nie napisałem tego konkretnego bitu, ale jest to operator binarny AND. Sprawdza, czy ustawiono ostatni bit, co jest równoważne wykonaniu i%2, ale jest „szybsze”. Nie jest to szybsze, ponieważ kompilator i tak by to zrobił.
Peter Alexander

1
@Poita_: W rzeczywistości i% 2 oraz i & 1 zachowują się inaczej z liczbami ujemnymi. (-1) i 1 to 1, czyli właśnie tego chcemy tutaj. (-1)% 2 to -1 w moim systemie i jest to zgodne z C99. Tak więc, chociaż jeśli (i & 1) i jeśli (i% 2) zrobią to samo, należy zachować ostrożność z if (i% 2 == 1), które nie zadziała, gdy i jest ujemne.
Joey Adams,

3

PHP: 126 132 138

(w oparciu o rozwiązanie 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;

Bieżące pełne:

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;

Może być bez @przed, $sale tylko z error_reporting ustawionym na 0 (Zwróć uwagę, że wyjścia zakłócają okrąg)


co robi / $ r w echo $ s * 2 / $ r / $ r;
davidosomething

Oddział OHH ... odstępy mnie wyrzuciły, myślałem, że to jakiś operator stenograficzny, którego nigdy nie widziałem
davidosomething

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

Biegnij z $ ruby -p piday


Niezły, ale nie drukuje przybliżenia pi
John La Rooy

Nie działa w wersji 1.9.1 i wyświetla podwójne cudzysłowy wokół koła.
Mladen Jablanović

To normalne, że programy golfowe nie działają na bardzo różnych poziomach językowych. Ile cg w Perlu lub Pythonie działa w każdej wersji języka? Co ciekawe, okazuje się, że powodem jest to, że Integer|Floatnie wymusza już float na 1.9.
DigitalRoss

3

APL: 59

Ta funkcja przyjmuje liczbę i zwraca dwie oczekiwane pozycje. Działa poprawnie w przypadkach bonusowych.

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

Dialekt to Dyalog APL, z domyślnym początkiem indeksu. Poziom umiejętności nie ma pojęcia, nowicjusz , więc jeśli jakikolwiek guru APL chce obniżyć go do 10 postaci, bądź moim gościem!


Możesz wypróbować go online na Try APL , po prostu wklej go i umieść po nim numer:

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

Chociaż nie znam APL, wygląda ładniej niż wersja J.
ahala

@ahala Rzeczywiście. APL jest piękny, zarówno pod względem koncepcyjnym, jak i estetycznym. Zacząłem się uczyć J, ale wyłączyło mnie przypadkowe szaleństwo ASCII. Dobra dusza napisała interpreter APL typu open source dla Node.js (npm install apl), który jest całkiem niezły. Oblicza powyższy kod z niewielką zmianą (bez monadycznego , drugiego znaku). Dobrą dokumentację APL można znaleźć na stronach wszystkich dostawców, takich jak Dyalog.
Tobia,

2

I wpis bash: 181 186 190 znaków

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

Biegnij z np bash py.sh 13


2

Python: 148 znaków.

Nieudana (tj. Niewystarczająco krótka) próba nadużycia zasad i zakodowania przypadków testowych, jak wspomniałem w odpowiedzi na oryginalny post. Nadużywanie go w bardziej rozwlekłym języku mogło być łatwiejsze:

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 znaków

Oparty na wersji Pythona.

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

(Nie można tutaj pominąć nowej linii po ostatniej linii).


1
127 znaków: 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

Jedynym problemem jest to, że teraz kończy się niepowodzeniem dla 0, ale zgodnie z obowiązującymi zasadami jest w porządku.
przemoc

2

JavaScript (SpiderMonkey) - 118 znaków

Ta wersja akceptuje dane wejściowe ze standardowego wejścia i przechodzi dodatkowe przypadki testowe

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)

Sposób użycia: cat 10 | js thisfile.js - podgląd jsbin dodaje alias dla print / readline, dzięki czemu można przeglądać w przeglądarce

Javascript: 213 163


Zaktualizowano

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

Nikt nie powiedział, że musi poprawnie renderować się w przeglądarce - tylko wyjście. W związku z tym usunąłem tagi wstępne i zoptymalizowałem je dalej. Aby zobaczyć wynik, musisz wyświetlić wygenerowane źródło lub odpowiednio ustawić arkusz stylów. W ten sposób liczba Pi jest mniej dokładna, ale teraz jest zgodna ze specyfikacją.


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

Niezminifikowane:

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

Niezminifikowane:

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

Prawdopodobnie mógłby zaoszczędzić ~ 50 znaków przepisując to w scala
rwyland

1

GAWK: 136 , 132 , 126 , 125 znaków

Oparty na wersji Pythona.

{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}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.