Arc Forumnew | comments | leaders | submitlogin
1 point by map 6141 days ago | link | parent

Some explanation about the shorter Ruby program. Consider this line from the "script":

  [ /\bI was (.*)/i, ["Why were you 1?","I can't believe you were 1."]],
Regular expressions are usually enclosed in /.../. The "i" at the end makes it case insensitive, so the regex could just as well have contained "i was". "\b" means that "I" will match only at the beginning of a word; we don't want to match "cheri was in the room." The parentheses in the regex denote a "capture", the text of which can be recalled later. The dot (.) matches any single character; the star matches any number of the preceding item. So if "\bI was " is found,

  (.*)
will match the rest of the string.

I've slightly tweeked the "two lines" of the program and broken them into more lines. p, the programmer's print, has been used to show the state of some variables.

  (
    gets
Read a line from the keyboard; instead of assigning it to a variable, rely upon Ruby's assigning it to $_.

    sub( /[.!?,;\s]+$/, "" )
Since we don't say which string variable the sub should act upon, it acts on $_. We're removing puctuation and whitespace at the end of the user's input.

Assume the user typed "I was thinking."

    p $_   # "I was thinking"
The tail of the string has been sanitized.

    x = Array(
In the script, sometimes we have only 1 possible response by the computer (i.e., a string); sometimes we have more than 1 response (an array (list) of strings). Array( let's us easily normalize; it converts something that's not an array to an array of 1 element and leaves arrays untouched.

      S.find{|a|
Iterate through the script list and return the first item for which our code block returns true. a is the parameter of the code block that receives the value of each item.

        $m = $_.match(a[0])
a[0] is the regular expression; we save the match-data in $m.

      }[1]
[1] yields the last part of the script item, the computer's response or responses.

    )
    p x   # ["Why were you 1?", "I can't believe you were 1."]
Since the user typed "I was ...", the computer has 2 answers from which to choose.

    p $m.class   # MatchData
    p $m.to_a   # ["I was thinking", "thinking"]
.to_a converts match-data to an array. The first item is the complete match; the rest of the items are "captures".

    puts x[rand(x.size)].
Randomly choose the computers answer. The "." at the end means a method follows...

      gsub( /\d/ ){|s| $m.to_a[s.to_i] }   # Why were you thinking?
The .gsub finds every numeral (digit) in the string and replaces it with the corresponding item in the match-data array. "0" would be replaced by the entire match; "1" is replaced by the first capture.

  ) while 9
"while 0" would work as well. The only untrue things in Ruby are false and nil. You'll have to break out of the loop with a control-key combination.