Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I participated in a coding competition today, and I found that almost all of the command line input our programs needed to receive would start with an integer representing the amount of data sets to follow. There were 6 different problems, and they all started this way.

For example, one sample problem had: "Input to this problem will begin with a line containing a single integer N (1 <= N <= 100) indicating the number of data sets. Each data set consists of the following components:

  • A line containing a single integer W that specifies the number of wormholes
  • A series of W lines containing....
  • etc. "

Pretty much all the competition problems had this format, with the first integer representing the amount of data sets to follow.

My initial reaction (and the way I tried to solve the problem) was just using a vector of size N, where each element represented a data set. Trouble is, there are a whole bunch of things in these data sets. Using this approach often left me with a vector of vector of vectors (maybe an exaggeration but you get the idea) which was very hard to manage.

Another idea was looping through the entire program N times, but this doesn't always seem that applicable.

I realize this is a vague question, but that's because I'm looking for a general solution to this type of problem. What is the best approach to handling this type of input?

share|improve this question
    
Curious to know what competition it was. –  daniels Oct 30 '11 at 2:06
    
Well...it was a competition to be in a competition. Rather, it was tryouts to represent my school at ICPC. –  Casey Patton Oct 30 '11 at 2:07
    
Got it, thanks. –  daniels Oct 30 '11 at 2:19

4 Answers 4

up vote 1 down vote accepted

I don't think there's another option other than the ones you mentioned. You either:

a) iterate through all the the data sets and work on them as they come up

or

b) store everything (in some suitable data structure, like an array, hash table, tree, etc) and work on it later.

share|improve this answer

I would usually define a class to represent each problem instance, then add a class constructor that accepts a FileReader or istream. Actually, I solve problems like these in Perl, but the contest rules require Java or C++.

share|improve this answer
    
+1 with a caveat: I wouldn't do any kind of I/O in the constructor. There's trouble in those waters. Instead, I'd prefer some sort of Init(Stream) or Load(Stream) method on the object/struct. –  Steve Evers Oct 31 '11 at 0:30
    
@SnOrfus: What sort of trouble? It's ok for constructors to throw exceptions. Otherwise, between the constructor and the 'Init' you may have an unusable object. I hate unusable objects. What happens if the next method call is not Init(Stream) but calculateSomething() ? –  kevin cline Oct 31 '11 at 3:11
    
of course, the constructor should always return with the object in a valid state... that doesn't mean it has to be populated at all. calculateSomething() would return 0 (or whatever the value for an empty dataset would be). IMO, constructors need not throw exceptions unless there is a failure allocating memory or something to that effect. Callers of your code should be able to trust that the object can be newed up without error. I shiver thinking of a world where I'd have to wrap up every object instantiation in a try...catch. –  Steve Evers Oct 31 '11 at 13:14
    
@SnOrful: "Callers of your code should be able to trust that the object can be newed up without error." Maybe, but not when the constructor is reading a file. You have to catch those I/O errors somewhere, and in this case the constructor may be the best place. –  kevin cline Oct 31 '11 at 17:54
    
"... but not when the constructor is reading a file." That's what I'm getting at, and why I wouldn't advocate I/O in a constructor. –  Steve Evers Oct 31 '11 at 18:14

You're looking for a roughly generalized solution... so try some generalization. I'd look at creating a class or custom collection to represent the common requirements/functionality.

Something like:

static void Main(string[] args)
{
    int itemCount = int.Parse(Console.ReadLine());
    var samples = new SampleData<Sample<int>, int>();
    samples.Read(Console.In, itemCount);
}

public class SampleData<T, K> : List<T>
    where T : Sample<K>, new()
{
    public void Read(TextReader reader, int count)
    {
        for (int i = 0; i < count; i++)
        {
            T sample = new T();
            sample.LoadData(reader.ReadLine());

            this.Add(sample);
        }
    }
}

public class Sample<T>
{
    public List<T> dataPoints { get; set; }

    public Sample()
    {
        this.dataPoints = new List<T>();
    }

    public void LoadData(string data)
    {
        /* parse data and add to dataPoints */
    }
}
share|improve this answer

The common solution that I've used was to write a function that would read 1 data set from an input file, and solve that. Then, in the main loop, I'd read the first line, extract how many data sets there were, and call for(1..N) {Solve(inputfile);}

I didn't put all problems in a single data structure, because each data set was a standalone input. The fact that they're all in the same file is just a convenience.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.