Reducing Leibniz perl code in characters

7

1

This Perl code is supposed to calculate the Leibniz formula. The original problem is here.

The input format is:

T
<T test cases, each on their own line>

Each test case is a number < 10^7. The output format should be the same, minus the first line.

For example, an input:

2 
10 
20

And for output:

0.760459904732351
0.77290595166696

My first solutions, at 62 and 61 characters respectively.

for(1..<>){$s=0;map{$s+=($_&1||-1)/(2*$_-1)}1..<>;print"$s\n"}

for(1..<>){$s=0;$s+=($_&1||-1)/(2*$_-1)for 1..<>;print"$s\n"}

Edit: The best solution so far is 53 characters, by @teebee:

<>;print${\map$a-=(-1)**$_/(2*$_-1),1..$_},$a=$/for<>

Techmonk

Posted 2013-02-05T07:14:35.653

Reputation: 173

possible duplicate of Calculate pi to 5 decimals

– Peter Taylor – 2013-02-05T07:49:58.927

Why post the same question on two sites? I feel like it's either help or a puzzle, but not both. And as a puzzle it needs a puzzle-type ([tag:code-golf], [tag:coding-challenge]) and objective winning criteria. – luser droog – 2013-02-05T08:06:22.143

2I was recommended that this question belongs here more then stackoverflow so posted here. – Techmonk – 2013-02-05T08:16:15.263

Answers

3

Perl 55 bytes

<>;map($s-=(-1)**$_/(2*$_-1),1..$_),$s=!print$s,$/for<>

Without using any Perl non-standard features (such as say). 3 bytes are wasted removing the first value from the input.

Sample usage:

in.dat

2
10
20

$ perl leibniz.pl < in.dat
0.760459904732351
0.77290595166696

Alternative, also 55 bytes

map{$s-=(-1)**$_/($_*2-1)for 1..<>;$s=!print$s,$/}1..<>

The alternative may be run interactively, without requiring an input file. Which, as I understand, is what you meant by running indefinitely.

primo

Posted 2013-02-05T07:14:35.653

Reputation: 30 891

1That goes in an infinite loop, but using this notation for for can save 2 more bytes map($s-=(-1)**$_/(2*$_-1),1..<>),$s=!print$s.$/for 1..<> – Techmonk – 2013-02-05T08:58:35.380

It will only cause an 'infinite' loop if the input given contains an infinite amount of lines. The for<> construction will iterate over every line in input passed to STDIN exactly once, without needing to 'know' beforehand how many there are. – primo – 2013-02-05T09:07:35.770

5

Perl 53 bytes

You can save two more strokes:

<>;print${\map$a-=(-1)**$_/(2*$_-1),1..$_},$a=$/for<>

teebee

Posted 2013-02-05T07:14:35.653

Reputation: 51

Very clever. One would expect \map... to return a single array reference, and not a list of scalar references. – primo – 2013-06-10T09:28:03.920