Google Code Jam 2011 Language Usage

Timon Gehr timon.gehr at gmx.ch
Sun May 8 13:04:23 PDT 2011


Andrew Wiley wrote:
> I was one of the D users, although I wasn't really worried about competing.
> I just wanted to see how D would compare after doing so many programming
> contests in Java.
> The main thing that frustrated me was that getting input in D wasn't
> anywhere near as straightforward as it is in Java. For the first problem,
> I'd do something like this in Java:
> Scanner in = new Scanner(System.in);
> int numTests = in.nextInt();
> for(int test = 0; test < numTests; tests++) { //need the test index for
> output
> int numSteps = in.nextInt();
> for(; numSteps < 0; numSteps--)
> char robot = in.nextChar();
> int button = in.nextInt();
> //solve the problem!
> }
> //print the output!
> }


Well, I don't like D's readf either (I use scanf, 2-3x faster and better
whitespace handling). That said, you really made my day.
The problem is not that reading input in D is less straightforward than in Java,
the problem is, that you are used to Java's way of doing IO. (which I pretty much
dislike, I guess it is a matter of taste)

You do not actually have to bother with string handling at all when doing IO in
C/C++/D.

Reading array of integers:

int[100000] array; //somewhere in static storage, faster
...
scanf("%d",&n);
foreach(ref x;array) scanf("%d",&x);

Or, some heap activity involved, and actually more keystrokes, but some people
like this way:
readf("%s",&n);//read number of items

int[] array=to!(int[])(split(strip(readln())));


How I would have written your example in D.
int numTests; scanf("%d", &numTests);
foreach(test;0..numTests){
    int numSteps; scanf("%d", &numSteps);
    foreach(step;0..numSteps){ //you have a bug in this line of your Java code
introducing a looooong loop
        char robot; scanf("%c", &robot);
        int button; scanf("%d", &button);
        //solve the problem!
    }
    //print the output
}

>
>
> In D, that looked like this:
> string line;
> int num;
> stdin.readln(line);
> formattedRead(line, "%s", &num);
> for(int casen = 0; casen < num; casen++) {
>
> ...
>
> In a few places, I could have used stdin.readf instead of
> readln/formattedRead, but not many because the number of items within a test
> is on the same line as the items.

That is not a problem at all, you can read the first few elements with readf and
the rest of the line with readln

> I could have just been missing something, but something that was trivial in
> Java became brittle in D because I had to exactly match the whitespace for

I actually think Java's way is brittle. You have to instantiate a class just to
read IO.

> things to work. I suppose I could have read a line and used splitter to
> split on whitespace, but that would make me have to watch more state and
> would wind up looking like this:
> string line;
> stdin.readln(line);
> auto split = split(line);
> int num = to!int(split[0]);
> split = split[1..$];

I don't get this.

>
> ...
>
> Actually... now that I'm looking at that, if I wrote a Scanner-like class
> based on this, is there any chance it could go into Phobos? Seems like
> between split and to, we could get something much less brittle working.

No chance, that is not the way D/Phobos works. You do not have a class for
everything that would not need one. (just like Phobos does not have a writer class
for output)

However I agree that Phobos has to provide some better input handling, since using
possibly unsafe C functions is the best way to do it by now. (I think readf is
severely crippled) I may try to implement a meaningful "read" function.


Timon


More information about the Digitalmars-d mailing list