in reply to Control Structure problem, mistake can't be found

As a general point this game isn't going to be easy, even if you know the expected answers, the:

if ($guess eq $correct[$i])
is requiring the guess to have the exact capitalisation of the answer and won't tolerate extra white-space or any other deviation from the expected string. Related to that is what FunkyMonk has already suggested, which is the possible presence of a newline on the end of $guess. Preprocessing $guess and/or using a form of regular expression to do the matching will definitely help.

In passing I notice:

@incorrect = (@incorrect, $guess);
which might be better written as:
push @incorrect, $guess ;
and also:
my $grade = 100 - length(my @incorrect) * 33.3;
which I rather doubt is what you meant. It sets $grade to 66.7, because length doesn't give the length of an array, it gives the length of a string in characters. So why does it give an answer at all when asked for the length of an array ?... well, length(my @incorrect) gives 1 because the value of my @incorrect is an empty array, which when evaluated in scalar context gives the number 0, which when converted to a string is '0', which is 1 character long... This is Perl all over :-)

To get the number of entries in an array you just evaluate the array in scalar context... so: scalar(@incorrect) is probably what you wanted.


Finally, at the risk of being presumptious, if you are new to programming in general, I'd really advise you to study another language.

It's true that you can hack about in Perl and do some wonderful stuff quite economically. But, not only is it possible to pick up some truely disgusting habits, you need a grounding in something more formal if you are to really understand what Perl is doing.

Look at it this way, compared to most languages English has apparently little structure and few rules. This makes it relatively easy to learn and use, at least to get by. However, it is also hard to really master the subtleties of English, with all its irreglarity, conventions, idioms and other oddities; and to do that you do need some grammer and some formal teaching. Perl is like that.

Replies are listed 'Best First'.
Re^2: Control Structure problem, mistake can't be found
by ww (Archbishop) on Aug 23, 2008 at 02:09 UTC
    ...not only is it possible to pick up some truely disgusting habits, you need a grounding in something more formal if you are to really understand what Perl is doing.

    ++, oshalla, for your other helpful advice, but not without taking exception to the quoted observation!

    I have no real quibble with your "possible" re "truly disgusting habits" (NB: in English there's no 'e' in 'truly.') except to note that's pretty much also "possible" to write effectively - if inelegantly - despite misspellings -- whether writing narrative or text. Conversly "proofs" of almost any proposition can be so badly conceived or structured as to be worthless despite having the appearance of proper form or even superficial plausibility.

    However, IMO, to suggest that it's not possible to understand "what Perl is doing" without formal study of another language for "grounding" is extreme, to say nothing of "unproven!"

      Yes, I can never correctly spell 'truly' (correction: I can seldom spell it). I am ashamed. What can I say: without the 'e' it just looks to me as if it's had an unfortunate accident with something sharp -- an object lesson in what happens when you run with scissors, perhaps ? It also looks almost as if it should be pronounced with a short 'u', but for that, I have to admit, two 'l's would be required -- as in 'cully'.

      Of course many other words that end in 'e' don't drop it when the adverb is formed -- 'insanely', 'obscenely', 'approximately', 'effectively'. But that may be because they don't end in two vowels. So there's 'brusquely' and 'opaquely', but I guess the 'u' isn't really a vowel in this context. What about 'eerily', and of course 'duly' -- the later is clearly of a piece with 'truly'. But, lest we conclude there's a simple rule here, there's 'vaguely' and 'freely' -- admittedly the sound of the 'ue' in 'vague' is quite different from that in 'true', which may (or may not) be significant. Similarly, in the case of 'free' it may be that the 'ee' is effectively a compound vowel ?

      English: what can I say ? Gosh, what a glorious mess !


      Anyway, returning to what I suppose is the real matter: I think that to "really understand what Perl is doing" you do need some more formal grounding -- highlighting the stress I intended on the "really".

      For instance, consider the following:

      my @rows = () ; while (my $line = <SHEET>) { chomp($line) ; my @columns = split /\s+/, $line ; push @rows, \@columns ; } ;
      What do we think is going on here ?
      1. declare the (one dimensional) array @rows and ensure it is initialised empty.
      2. run a while loop using various pieces of commonly used Perl magic to step line by line through the file referred to by SHEET, declaring the working variable $line for the duration of the while loop
      3. chomp($line) removes the line ending from the input line (unless you're running on a *nix type system and the file came from winders, in which case it tends to remove half the line ending, SO STAY AWAKE)
      4. declare the (one dimensional) array @columns for the remaining duration of the loop, and assign to it the result of splitting up the input line.
      5. push a reference to the array @columns onto the array @rows (we understand that in Perl arrays and lists are strongly related)
      The result is intended to be a two-dimensional array (or what passes for one in Perl) of cells. And, indeed that's what happens.

      Now, references are sophisticated, but just taking the code at face value, one might worry:

      • if @columns only exists for the duration of the enclosing block, what does the @rows array contain after the block ?
      • why does this work at all, given that it appears to push the same thing, \@columns, on to @rows each time around the loop ?
      So, we all know that this works because my @columns doesn't declare an array, it declares something that contains a pointer to a data structure which contains the actual array and which lives on a heap. The \@columns doesn't really return a reference to @columns, it returns a copy of the pointer it contains. What's more, each time around the while loop @columns is reset before the new split /\s+/, $line is assigned to it, so each \@columns is different and refers to a different data structure on the heap -- each of which persists after the block (leaving reference counting and garbage collection to one side, for the time being).

      Scanning back over the above, I observe it's hard to describe what's really going on, without using some fairly heavy computer science concepts. IMO, the study of more formal language(s) is the way to gain understanding of these and how they work.

      This is only one example, but I believe it illustrates a general point.

        I disagree with you re Perl as a first language. Perl has one thing that is missing in many other languages: a friendly and helpful community.

        You are right that in Perl, grokking references can be hard. I struggled for a while with building data structures. Different bracketing, and -> syntax and added to the confusion. Map was pretty hard to get as well. The Schwartzian transform just about caused a brain hemorrhage the first time I saw it.

        BASIC is easyish, but which version? Most modern basics are pretty OO in structure. Save the beginner from objects!

        Java? OO hell + verbosity that is puzzling to the newb, and frustrating to the experienced.

        C++? OO again. And...look at the size of that language! Back in the day, C++ was big and unwieldy and confusing enough, but I was still reasonable. I stopped watching it for a few years and the new standards made it more unreadable, and 20 times bigger and harder to tell what's going on. Do go in, it's a TRAP!!!!

        C? As a newb I got hung up on * vs & for the longest time because you use * to declare a pointer, but you use & to get one, and then you use * to dereference it! It is a very small language--hooray--but as a result you either have to memorize an API to do anything interesting or write your own libraries.

        Pascal might work out ok. But who uses it these days? One might as well suggest Logo. Also, array indexes start at 1--which will cause pain when switching to almost any other language.

        Any "serious" language will have it's good and bad bits for a new learner. (Befunge and BF are ALL BAD, thankfully one is not expected to use them for work.) But Perl shines for the simple fact that there is a large, craft-oriented community that is ready to provide friendly, prompt help. The help I got around here was worth way more to me than the "help" I got from a variety of professors and teaching assistants. The funny thing is, hacking Perl and reading Perlmonks straightened out lingering errors in comprehension that my formal education left behind.


        TGI says moo

        Your comment seems funny to me (in a good way, really!) because I would normally code your example as
        my @lines = map { chomp; [split] } <SHEET>;
        or, if I suspected that the "SHEET" could point to a very big file,
        my @lines; chomp, push @lines, [split] for <SHEET>;
        both of which do need a _lot_ of perl knowledge to be read, aside from the CS knowledge you mentioned...
        Update: obviously, blazar is right. and I should've written my examples as:
        my @lines = map [split], <$sheet>;
        and
        my @lines; push @lines, [split] while <$sheet>;
        because for was just wrong and because split already chomped the string...
        []s, HTH, Massa (κς,πμ,πλ)