Код гольфу - π день


95

Змагання

Вказівки щодо кодового гольфу на SO

Найкоротший код за підрахунком символів для відображення представлення кола радіуса з Rвикористанням *символу з наступним наближенням π.

Введення - одне число R,.

Оскільки, здається, більшість комп’ютерів мають співвідношення майже 2: 1, виводити слід лише рядки, де yнепарно. Це означає, що коли Rдивно, ви повинні надрукувати R-1рядки. Для R=13роз’яснення існує новий тестовий приклад .

напр.

Input
    5
Output      Correct                          Incorrect

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

Редагувати: Через широку плутанину, спричинену непарними значеннями R, приймаються будь-які рішення, які проходять 4 тестові випадки, наведені нижче

Наближення π дається діленням подвійної кількості *символів на .
Апроксимація повинна бути правильною щонайменше до 6 значущих цифр.
Провідні або кінцеві нулі дозволені, так, наприклад , будь-який з 3, 3.000000, 003приймається на входах 2і 4.

Кількість кодів включає введення / вихід (тобто повну програму).

Випробування

Input
    2
Output
     *** 
     *** 
    3.0

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

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

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

Бонусний тест

Input
    13
Output

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

Можливо, ви захочете пояснити, чи є "input" в командному рядку, або в stdin.
Грег Хьюгілл,

1
@Greg Hewgill, Не соромтеся вибирати, що є найбільш зручним для мови, якою ви користуєтесь :)
Джон Ла Рой

@Greg Hewgill, Деякі (тобто дуже мало) реалізації мови програмування не мають поняття "командний рядок".
Joey Adams

1
Я помічаю, що мало хто з відповідей дотримується правила лише виставляти рядки, де y непарна. Враховуючи непарне значення r (не показано в тестових випадках), більшість виведе рядки, де y парне!
MtnViewMark

6
Правило зловживання Задача: зробити код , який коротше , ніж хто - небудь інший код, ввівши його тільки підтримки 4 необхідних тестів.
Брайан,

Відповіді:


15

У постійному струмі: 88 та 93 93 94 96 102 105 129 138 141 символи

Про всяк випадок, я використовую OpenBSD та деякі нібито не портативні розширення на даний момент.

93 символи. Це базується на тій же формулі, що і розчин FORTRAN (трохи інші результати, ніж тестові випадки). Обчислює X ^ 2 = R ^ 2-Y ^ 2 для кожного Y

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

88 символів. Ітеративне рішення. Відповідає тестовим кейсам. Для кожного X та Y перевіряє, чи 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

Бігти dc pi.dc.

Ось старіша анотована версія:

# 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
Не працює з linux dc, але я можу підтвердити, що він працює на openbsd . Дивовижно!
Джон Ла Рой,

@Carlos, так, (оператор впевнений, зручний. шкода, що він залишається нездійсненим у постійному струмі, який поставляється з Linux
Джон Ла Рой,

@gnibbler - "Повний перепис команди постійного струму з використанням процедур великого числа bn (3) вперше з'явився в OpenBSD 3.5." Я цього не знав. Включено кілька приємних нових операторів, але вони позначені як "непереносні розширення".
Карлос Гутьєррес

Так, (оператору дозволено пролити 6 ударів!
Ден Андреатта,

119

C: 131 символ

(На основі рішення С ++ від Джої)

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

(Змініть значення, i|=-nщоб i-=nвидалити підтримку випадків непарних чисел. Це лише зменшує кількість символів до 130.)

Як коло:

      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
Мені подобається, як ви додали кола до коду, щоб перетворити його в коло. Чи буде переважно +000?
Potatoswatter

вітаю, j * j ++ - невизначена поведінка
sellibitze

1
хіба це не може бути лише один персонаж ...?
Ponkadoodle

1
Як main()взяти чотири intаргументи?
David R Tribble

2
@Load: 5.1.2.2.1 / 1: названа функція, що викликається під час запуску програми main. Це має бути визначено… або іншим способом, визначеним реалізацією . Отже, це тому, що імплементація може прийняти цю форму.
kennytm

46

XSLT 1.0

Для розваги, ось версія XSLT. Насправді це не матеріал для кодового гольфу, але він вирішує проблему дивним чином-функціонально-як 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>

Якщо ви хочете протестувати його, збережіть його як pi.xsltта відкрийте такий файл XML в IE:

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

42
мої <очі> </eyes>! Окуляри вони <do> нічого </do>!
Джиммі,

1
Боже! Боюсь, ви, можливо, перемогли моє рішення HyperCard за унікальність: D
Джої Адамс,

7
Я не можу повірити, що ви сказали "відкрити ... IE"
гарпо

Так, ще в той час у нас був лише IE, і XML із XSLT був рішенням усіх наших проблем. Старі добрі часи! :)
Данко Дурбіч,

XSL версії 1.0, вау, я пам’ятаю, що з нетерпінням чекав версії 2, але до моменту її виходу я вже рухався далі.
gradbot

35

Перл, 95 96 99 106 109 110 119 символи:

$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

(Новий рядок можна видалити, він є лише для того, щоб уникнути смуги прокрутки)

Так! Кругова версія!

    $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

Для непосвячених довга версія:

#!/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
Це, безумовно, найбільш нечитабельний код, який я бачив за все своє життя
Кріс Марісіч

13
Думаю, ви тоді ніколи не бачили APL.
Пітер Вон

5
@Chris Marisic: Ви перевіряли інші питання / теми, позначені тегом code-golf? :) Я бачив набагато більше нечитабельних прикладів.
BalusC

3
@Peter: На відміну від більшості, я бачив і писав APL. Потрібно пару тижнів, щоб звикнути до його особливих символів, але після цього це може бути цілком читабельним. Навіть через пару десятиліть, щоб звикнути, Perl все ще набагато гірше.
Джеррі Коффін

1
111 символів,$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
Гастуркун

25

FORTRAN - 101 знак

$ 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

Зачекайте, я хоч форматування було важливим у Fortran? У вас є листи в графі 1!
Джоел

Більшість людей все ще затримуються на Fortan77 від того, що я бачив.
Джоел

8
Мені подобається, як версія кола виглядає як Зірка Смерті.
mskfisher

22

машинний код x86: 127 байт

Асемблер Intel: 490 символів

    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

Ця версія також обробляє кейс із бонусним тестом і становить 133 байти:

    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
Я люблю StackOverflow!
zengr

2
Цікаво, що деякі мови високого рівня мають менший кількість символів, ніж двійковий файл, який це створює.
Колін Валліант,

3
@Alcari: Якби ви включили весь код у бібліотеки, які використовують мови вищого рівня, кількість їхніх символів була б значно більшою. В асемблері виконання printf("%f",a/b)не є тривіальним, немає єдиної інструкції для цього, і моя реалізація вище передбачає, що 0 <= a / b <10 і що операція є діленням, а a і b є цілими числами.
Skizz

19

Python: 101 104 107 110 символів

На основі іншої версії Python Ніколаса Райлі.

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

Подяки AlcariTheMad за деяку математику.


Ах, непарні з індексом дорівнюють нулю як середини, все пояснює.

Бонусний Python: 115 символів (швидко зламаний разом)

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

Ого, так, '+' б'є -1 і, будь-який день. Ще одну техніку, яку я викидаю з розуму, оскільки це майже ніколи не правильно робити :-)
Ніколас Райлі

Раніше я використовував С, і навіть навіть не дивився на Python. Ці 104 символи є більш читабельними, ніж C ++ вище. Дивовижний. Можливо, мені слід вивчити Python ...
Дін, швидше

@Dean: Однією з головних цілей Python є легко читати та писати.
Колін Валліант

Ви хоч і про те, щоб використовувати exec із вашою відповіддю 104 char? :)
Джон Ла Рой,

Мені потрібно було б прокрутити власну компресію - zlib, маршалінг тощо, і все вийшло більше, ніж фактичний код.
lunixbochs

12

Powershell, 119 113 109 символів

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

і ось краща версія:

( $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: Сподіваюсь, ні, але це, мабуть, найгірше, що я коли-небудь писав :)
Данко Дурбіч

3
Дякую за цю гарнішу версію =)
Тор Ховден

10

HyperTalk: 237 символів

Відступ не потрібно і не враховує. Це додано для наочності. Також зверніть увагу, що HyperCard 2.2 дійсно приймає ті реляційні оператори, що не є ASCII, я використовував.

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

Оскільки HyperCard 2.2 не підтримує stdin / stdout, натомість передбачена функція.


1
Гіперкарт, містере Адамс? Серйозно? Це дуже несподівано.
Кава

1
@Kawa: Ось чому я його опублікував :) Крім того, кодовий гольф - це хороший спосіб створити набір тестів на випадок, якщо я вирішу написати інтерпретатор HyperTalk у майбутньому.
Joey Adams

Ха-ха! Я хотів би це побачити, XD
Кава

Якщо ви коли-небудь вирішите написати такого перекладача або хочете приєднатися до роботи над вже існуючим, дайте мені знати, і я можу додати про нього на hypercard.org, і мені буде цікаво, як це відбувається :-)
uliwitness

10

C #: 209 202201 символів:

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

Немініфікований:

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

Я не дуже знаю C #, але чи не слід вам використовувати string[]aта 1-r(а не -1+r)?
kennytm

@Kenny: Ви маєте рацію. :) Це рятує трьох персонажів, і тоді мені вдалося позбутися ще п'яти.
Guffa

Помітив це перше, що зовсім пропустив -r+1.
Дикам

4
Також, плямистий x*xx+++y*yтеж, але це божевільна річ, щоб розтинати на перший погляд.
Дикам

Я взяв на себе свободу ліквідувати ще один байт ;-)
Джої

10

Haskell 139 145 147 150 230 символів:

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

Обробка непарних чисел: 148 символів:

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 символів: (На основі версії 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 символів:

main = do {r <-read`fmap`getLine; нехай {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, тоді p "*" >> c (m + d) (x + 1) ще p "" >> cm (x + 1), якщо y> r, тоді надрукуйте n ще cn (-r) >> = l (y + 2)}; l (1-r`mod`2-r) 0}

Немініфікований:

main = do r <- читати `fmap` getLine
          нехай p = putStr
              d = 2 / відIntegral r ^ 2
              lyn = нехай cmx = якщо x> r
                                  потім p "\ n" >> повернути m
                                  інакше якщо x * x + y * y <r * r
                                       тоді p "*" >> c (m + d) (x + 1)
                                       ще p "" >> см (x + 1)
                      в якщо y> r
                         потім надрукуйте n
                         ще cn (-r) >> = l (y + 2)
          l (1-r`mod`2-r) 0

Я сподівався, що це переможе деякі імперативні версії, але, здається, я не можу більше стискати це далі.


Відрубали ще 2, позбувшись "d" і додавши замість нього 1, а потім надрукувавши "2 * n / fromIntegral r ^ 2"
Стів

Зголено 3 символи за допомогою декількох хитрощів. Мені подобається, що в Haskell часто немає витрат на кілька рядків (новий рядок проти крапки з комою), а отже, наш код-гольф загалом читається!
MtnViewMark

Власне кажучи, версія із 145 символів працює лише в тому випадку, якщо введення є рівним. Але дуже приємно в будь-якому випадку.
Стів

Скорочено лінію вводу-виводу. Все ще має бути можливість зберегти ще кілька символів, натиснувши функцію defs у блок main = do {... let {...} ...}, я думаю.
гроза

@comingstorm: Класно! Я не знав про readLn. Це допоможе багатьом кодам-гольфу Haskell. @ Steve: Так, я все ще намагаюся з'ясувати найефективніший спосіб це виправити.
MtnViewMark

10

Рубін, 96 символів

(на основі рішення 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 символів (бонус):

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

Дякую! Мені соромно бачити, наскільки Рубі може бути нечитабельною ... :)
Младен Ябланович

Ви також можете використовувати p sзамість puts s:)
Джон Ла Рой

1
Приємні свіжі ідеї - мені подобається, що ви використовуєте g з 2 різними розмірами кроків та <=>, щоб уникнути коду для перетворення з логічного
Джон Ла Рой


8

Ви, хлопці, занадто сильно думаєте.

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

8
Кількість символів трохи виходить з-під контролю, вам не здається? :)
Джон Ла Рой

7
Не масштабується. Неможливо досягти!
spoulson

Я спробував максимально стиснути обман на тестовому прикладі, але він все-таки виявився трохи більшим, ніж моє фактичне рішення: P
lunixbochs

5
+1, завжди спочатку робіть найочевидніше ... якщо комусь це не подобається, голосно скаржтесь, що специфікація була недостатньо чіткою
Мізіпзор

Брайан мав напівсерйозну спробу спеціального обговорення тестових справ, вам також слід підтримати його, якщо вам подобається ця відповідь;) stackoverflow.com/questions/2457995
Джон Ла Рой,

7

J: 47 , 46 , 45

Така ж основна ідея, як і інші рішення, тобто r ^ 2 <= x ^ 2 + y ^ 2 , але орієнтована на масив нотація J спрощує вираз:

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

Ви б назвали це як c 2або c 8або c 10тощо.

Бонус: 49

Для обробки непарного введення, наприклад 13, нам доведеться фільтрувати координати x з непарними значеннями, а не просто брати кожен другий рядок результату (оскільки тепер індекси можуть починатися як із парного, так і з непарного числа). Це узагальнення коштує нам 4 символів:

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

Зменшена версія:

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
)

Покращення і узагальнення з - за Маршалл Lochbam на J форумі .


5

Python: 118 символів

Практично простий порт версії 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

Для python2 ви можете просто використовуватиr=input()
John La Rooy

Вам не потрібен простір між printі' '
Джон Ла Рой

Добре, це страшно, це коротше, ніж версія Perl зараз. (Я повністю відкидаю "введення", бо зазвичай це небезпечно ...)
Ніколас Райлі,

4

C ++: 169 символів

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

Немініфікований:

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

(Так, використання std :: замість того, щоб using namespace stdвикористовувати менше символів)

Вихідні дані тут не збігаються з тестовими кейсами в оригінальній публікації, тому ось такий, який відповідає (написаний для читабельності). Вважайте це еталонною реалізацією (якщо Poita_ не проти):

#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 символів (з результатом, який я вважаю правильним)

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

Код циклу від -n до n, тому для вводу, наприклад, 4, він відображає діаметр 9, а не 7, як показано в тестових випадках.
Guffa

Чи є вимога, щоб ваше коло точно відповідало OP ?
Петро Олександр

3
Можливо, ви захочете змінити його на той, #include <iostream.h>який в основному призначений #include <iostream> -- using namespace std;для сумісності зі старими компіляторами C ++.
Earlz

1
@Carlos, я не писав цей конкретний біт, але це двійковий оператор І. Він перевіряє, що встановлено останній біт, що еквівалентно виконанню i%2, але є "швидшим". Це насправді не швидше, тому що компілятор все одно зробив би це.
Петро Олександр

1
@Poita_: Насправді, i% 2 та i & 1 поводяться по-різному з від’ємними числами. (-1) & 1 дорівнює 1, саме цього ми хочемо тут. (-1)% 2 - -1 у моїй системі, і це відповідає C99. Таким чином, хоча if (i & 1) і if (i% 2) будуть робити те саме, слід бути обережним з if (i% 2 == 1), що не спрацює, коли i від’ємне.
Joey Adams

3

PHP: 126 132 138

(на основі рішення 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;

Повний струм:

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;

Може бути без @перед початком, $sале лише з повідомленням про помилку, встановлене на 0 (повідомлення про виведення заважає колу)


що робить / $ r в echo $ s * 2 / $ r / $ r;
davidosomething

OHH розділ ... інтервал мене відкинув, думав, що це скорочення оператора, якого я ніколи не бачив
davidosomething

3

Рубін 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

Біжи с $ ruby -p piday


Гарний, але він не роздруковує наближення пі
Джон Ла Рой,

Це не працює в 1.9.1, і друкує подвійні лапки по колу.
Младен Ябланович

Нормально, що програми для гольфу не працюють на дико різних рівнях мови. Скільки роботи Perl або Python cg над кожною версією мови? Цікаво, проте, виявляється, причина в тому, що Integer|Floatбільше не примушує поплавок на 1.9.
DigitalRoss,

3

APL: 59

Ця функція приймає число і повертає два очікувані елементи. Працює коректно в бонусних випадках.

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

Діалектом є Dyalog APL, із початковим початковим кодом індексу. Рівень майстерності - невідомий новачок , тому, якщо якийсь гуру APL хоче зменшити його до 10 символів, будьте моїм гостем!


Ви можете спробувати в Інтернеті на Спробувати APL , просто вставте його і поставте після нього номер:

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

Хоча я не знаю APL, він виглядає симпатичнішим за версію J.
ahala

@ahala Справді. APL прекрасний як в концептуальному, так і в естетичному плані. Я почав вивчати J, але був відключений випадковим божевіллям ASCII. Хороша душа написала інтерпретатор APL з відкритим кодом для Node.js (npm install apl), що досить добре. Він обчислює наведений вище код лише з незначними змінами (без монадичного , 2-го символу.) Ви можете знайти хорошу документацію APL на всіх веб-сайтах постачальників, таких як Dyalog.
Tobia

2

І запис баш: 181 186 190 символів

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

Запустити, наприклад bash py.sh 13


2

Python: 148 символів.

Невдала (тобто недостатньо коротка) спроба зловживання правилами та жорстке кодування тестових випадків, про що я вже згадував у відповіді на оригінальний пост. Можливо, зловживання нею більш детальною мовою було простіше:

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

до н.е.: 165 , 127 , 126 символів

На основі версії 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

(Новий рядок після останнього рядка тут не можна пропустити.)


1
127 символів: 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

Єдина проблема тут полягає в тому, що він тепер не має значення 0, але згідно з чинними правилами це нормально.
przemoc

2

JavaScript (SpiderMonkey) - 118 символів

Ця версія приймає введення від stdin і проходить бонусні тестові кейси

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)

Використання: cat 10 | js thisfile.js - Попередній перегляд jsbin додає псевдонім для лінії друку / читання, щоб ви могли переглядати його у браузері

Javascript: 213 163


Оновлено

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

Ніхто не сказав, що він повинен правильно відображатись у браузері - лише вихідні дані. Таким чином, я видалив попередні теги та оптимізував їх далі. Щоб переглянути вихідні дані, вам потрібно переглянути згенероване джерело або відповідно встановити таблицю стилів. Пі менш точна, але тепер це специфікація.


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

Немініфікований:

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

Немініфікований:

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

Можливо, міг би врятувати ~ 50 символів, переписавши це у Scala
Rwyland

1

GAWK: 136 , 132 , 126 , 125 символів

На основі версії 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}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.