Leibniz golf in C#

7

1

I'm starting with golf code. But im only do C# so I know wont be a breaking record, but I want give it a try. Leibniz

Challenge is here

The first line contains the number of test cases (N) which is less than 100. Each additional line is a test case for a positive integer value (T) less than 10^7.

I format the code to easy the reading, removing spaces I reduce it to 210 chars. The best code submit for this problem is 54 char, but For C# lenguaje the best is 172 chars.

My guess is should remove reading the N, but couldn't make it stop properly.

using System;
class S
{
    static void Main()
    {
        int n=Convert.ToInt32(Console.ReadLine()),i=0;
        for (;i++<n;)
        {
            double r=0,t=Convert.ToInt32(Console.ReadLine()),j=0;
            for(;j<t;)
                r+=(1-j%2*2)/(2*j+++1);
            Console.WriteLine(r);
        }
    }
}

NOTE

Mono C# compiler 3.2.8.0 .NET 4.0 CLR
So using C=System.Console doesn't work.

Juan Carlos Oropeza

Posted 2015-04-22T16:39:52.023

Reputation: 513

This isn't an appropriate question for this site. Questions here are challenges for people to compete on (and a few other things like language tips). If you need help, submit your code as an answer to the challenge, and ask for help in the comments of your answer. – Sparr – 2015-04-22T17:24:30.550

2

@Sparr this is an old challenge, you can see this question was already here for Python. http://codegolf.stackexchange.com/questions/10716/solve-the-codesprint4-leibniz-code-golf-challenge-in-python-in-66-characters , and is +2 years old, same challenge I just ask for a diferent lenguaje. Im not trying to get any prize, just trying to learn.

– Juan Carlos Oropeza – 2015-04-22T17:30:58.097

10

@Sparr Asking for golfing advice is definitely on topic, and has been officially for almost a year. Also see the help centre.

– Martin Ender – 2015-04-22T17:47:10.390

1It's not clear to me whether you want help golfing the code in the question or solving the Hacker Rank challenge. The code in the question doesn't meet the spec for the Hacker Rank challenge. Consider e.g. that the correct output for 100000 is 0.785395663397448. – Peter Taylor – 2015-04-22T18:33:24.273

@PeterTaylor My request is for help golfing the code, especially the first FOR and try reading the number of cases. But you are right for that case doesn't work. As I say in the description Im new with this and I considere my program correct because pass the test case. Didnt consider have to try all the cases by myself. Do you think this is because a wrong data type, or is something wrong with my code logic? – Juan Carlos Oropeza – 2015-04-22T18:55:52.167

It's a logic problem. One of the basic rules of applied numerical analysis is that when adding a list you should process the numbers in order of increasing absolute value. – Peter Taylor – 2015-04-22T19:03:16.147

So should I run the calculation in inverse order? – Juan Carlos Oropeza – 2015-04-22T19:11:39.037

@PeterTaylor, I invert the order of calculation and for 100000 now i got 0.785400663372449 need to polish a litle bit more. – Juan Carlos Oropeza – 2015-04-22T19:17:16.133

Answers

7

As I suggested in a comment on VisualMelon's answer, the second for loop is being underutilised. By changing some variable scopes it's possible to use the fors in such a way that we save one set of curly brackets and one variable, and perform the sum in the correct order, fixing the bug in the supplied code.

Golfed:

using C=System.Console;class S{static void Main(){for(double n=int.Parse(C.ReadLine()),r,t;n-->0;C.WriteLine(r))for(r=0,t=2*int.Parse(C.ReadLine());t>0;t--)r-=(1-t%4)/--t;}}

Online demo

Ungolfed:

using C = System.Console;
class S {
    static void Main() {
        for (double n=int.Parse(C.ReadLine()), r, t; n-- > 0; C.WriteLine(r))
            for (r=0, t=2*int.Parse(C.ReadLine()); t>0; t--)
                r -= (1-t%4) / --t;
    }
}

Peter Taylor

Posted 2015-04-22T16:39:52.023

Reputation: 41 901

I've heard that a double can perfectly represent an Int32, but I never quite believed it (too lazy to find a good source more than anything else), I was holding back on suggesting collapsing t/j as well, this is considerably better than my job. – VisualMelon – 2015-04-22T19:22:41.950

A double can perfectly represent any integer up to 2^51 or 2^52 (can't quite remember offhand and don't feel like looking it up). – Peter Taylor – 2015-04-22T19:25:51.880

Setting all variables and printing result in the same for very cleaver. But you lose me on the second for. You move the 2* to t assignment and then you have t-- and --t. I think i will have to run it step by step to see what is doing. – Juan Carlos Oropeza – 2015-04-22T19:49:38.480

3

Couple of simple things that apply in lots of places:

  1. You've got a free semi-colon in your first for loop which you can make use of

  2. You keep track of i against n, but you as you never use the value of n, you can use it as the counter itself.

  3. As someone else said, you can use int.Parse (or double.Parse) instead of the Convert namespace/class/whatever it is - this makes your using System directive less helpful, and you are better of using the classic using C=System.Console (unless C# 6 has come out, I can't say I'm sure, in which case you can using System.Console directly)

  4. There is an unneeded space after the first for (not sure if you'd accounted for this or not)

I haven't tested this code, but hopefully it will at least help:

using C=System.Console; // 3

class S
{
    static void Main()
    {
        for(int n=int.Parse(C.ReadLine()); // 1, 3, 4
            n-->0;) // 2
        {
            double r=0,t=int.Parse(C.ReadLine()),j=0; // 3
            for(;j<t;)
                r+=(1-j%2*2)/(2*j+++1);
            C.WriteLine(r); // 3
        }
    }
}

Is it possible that the shorter C# solution disregards the first line, and just assumes the input is clean? May well be cheaper to do that if it is allowed.

This is just a quick reply, I might have a better bash at this tomorrow when I have less going on.

VisualMelon

Posted 2015-04-22T16:39:52.023

Reputation: 3 810

Point 1 applies to the second for loop too. – Peter Taylor – 2015-04-22T19:03:40.247

@PeterTaylor unfortunately it doesn't seem to pay to move the doubles outside of the for loop, and you need access to r below (which you don't have if you define it in the for loop initial expression) – VisualMelon – 2015-04-22T19:04:54.817

Yes, That part I try putting the variable inside the loop and couldnt access outside. – Juan Carlos Oropeza – 2015-04-22T19:06:52.207

Looks like I cant use using C=System.Console; Say `System.Console' is a type not a namespace – Juan Carlos Oropeza – 2015-04-22T19:10:16.550

1There's no reason why n can't be a double... See my answer. – Peter Taylor – 2015-04-22T19:20:37.897

@JuanCarlosOropeza that's irritating, I wonder if it's an ancient version of C# or something (or maybe it's mono and it does more than reject perfectly valid uses of goto). In that case, I have a one-byte longer version without it (I'll write this up properly some other time): using System;class S{static void Main(){Func<int>L=()=>int.Parse(Console.ReadLine());for(int n=L();n-->0;){double r=0,t=L(),j=0;for(;j<t;)r+=(1-j%2*2)/(2*j+++1);Console.WriteLine(r);}} – VisualMelon – 2015-04-22T19:21:09.920

You are right Mono C# compiler 3.2.8.0 .NET 4.0 CLR. But dont worry about it, I learn a lot. Thanks – Juan Carlos Oropeza – 2015-04-22T19:28:46.417

2

  • Instead of Convert.ToInt32, use int.Parse; it saves a few characters.
  • Unless you really need a double, use a float; it's one char shorter than double.

ProgramFOX

Posted 2015-04-22T16:39:52.023

Reputation: 8 017

Thanks, I was using Math.power() that is why I need double, but i replace it for r+=(1-j%2*2), so no need it anymore. – Juan Carlos Oropeza – 2015-04-22T17:22:50.147

I went back to double, Need 15 decimals precision. :( – Juan Carlos Oropeza – 2015-04-22T17:27:01.450

1

172 Characters

The permanent version of the challenge can be found here. I have the shortest solution for C#, which is 172 characters.

Golfed

using R=System.Console;class C{static void Main(){R.ReadLine();for(double s,n,j;;){for(s=0,n=int.Parse(R.ReadLine()),j=0;j<n;){s+=(j%2<1?1:-1)/(2*j+++1);}R.WriteLine(s);}}}

Ungolfed

using R=System.Console;
class C
{
    static void Main()
    {
        R.ReadLine();
        for(double s,n,j;;)
        {
            for(s=0,n=int.Parse(R.ReadLine()),j=0;j<n;)
            {
                s+=(j%2<1?1:-1)/(2*j+++1);
            }
            R.WriteLine(s);
        }
    }
}

It does error out on the last loop, but it's after outputting all test cases.

Edit

Seeing it ungolfed like this, just realized I can inline the for loop.

170 characters

Golfed

using R=System.Console;class C{static void Main(){R.ReadLine();for(double s,n,j;;){for(s=0,n=int.Parse(R.ReadLine()),j=0;j<n;)s+=(j%2<1?1:-1)/(2*j+++1);R.WriteLine(s);}}}

Ungolfed

using R=System.Console;
class C
{
    static void Main()
    {
        R.ReadLine();
        for(double s,n,j;;)
        {
            for(s=0,n=int.Parse(R.ReadLine()),j=0;j<n;)
                s+=(j%2<1?1:-1)/(2*j+++1);
            R.WriteLine(s);
        }
    }
}

Edit 2

@PeterTaylor's answer has some fantastic logic. Cleaned it up a bit, and I'm still using exceptions for control flow.

155 characters

Golfed

using R=System.Console;class C{static void Main(){R.ReadLine();for(double s,n;;R.WriteLine(s))for(s=0,n=2*int.Parse(R.ReadLine());n>0;n--)s-=(1-n%4)/--n;}}

Ungolfed

using R = System.Console;
class C
{
    static void Main()
    {
        R.ReadLine();
        for(double s, n;; R.WriteLine(s))
            for(s = 0, n = 2 * int.Parse(R.ReadLine()); n > 0; n--)
                s -= (1 - n % 4) / --n;
    }
}

I really wish I could get rid of the extra ReadLine().

lordcheeto

Posted 2015-04-22T16:39:52.023

Reputation: 111