Jump to content
New account registrations are disabed. This website is now an archive. Read more here.
kellessdee

Learning Ruby -- Master Topic

Recommended Posts

This is mainly a reposting of my blog entries. You can find my blog here: http://www.rmxpunlim...llessdees-blog/ kellessdee here, I have been teetering on verge of writing a full tutorial on ruby scripting for a while, and have had difficulty deciding how to tie this into learning RGSS as well. In the end, I decided that one should not skip out on thoroughly learning Ruby prior to jumping into RPG Maker scripting. Ruby has a lot to offer, and I feel a lot of people try to jump too far ahead, jumping right into RGSS. While I understand the feeling of wanting to learn something NOW, but if you really take the time to learn, you'll find there are a great number of resources available in Ruby's core library that can aid in RPG Maker development greatly. I have decided that I am going to do this tutorial as a series of mini-tutorials, releasing one per week. This tutorial will be categorized into "lessons." In each lesson, I will first go over the topic of that lesson (mixing in some examples and demonstrations - to try and balance theory and practical application) and I will try to finish off with a few practice problems (where possible/applicable). In the following lesson, I will touch on any practice problems I presented. These tutorials are going to be geared towards someone with no programming background, although if you do have some kind of programming background (even RPG Maker XP eventing knowledge helps!) it will help greatly. However, it is not necessary. The lesson plan will be outlined in the table of contents entry (next entry), and I will use that entry to post links to each lesson that has been released. Please note, that this plan is subject to change. I do not claim to be a ruby expert, however, I do feel that I know enough about it to attempt to teach it. If you need me to elaborate on something, leave a comment and I will try to answer your question to the best of my ability. Likewise, if you feel I am wrong about something, feel free to correct me in the comments as well. I am only human, so by posting any errors I make will help improve the quality of these lessons for everyone. As always, if you have any questions or concerns, feel free to leave a comment, send me a PM, or email: kellessdee@gmail.com

Learning Ruby - Table of Contents
Lesson 1: Installing Ruby
http://www.rmxpunlim...by-environment/
Lesson 2: Objects, Objects, Objects aka Ruby Data Types
http://www.rmxpunlim...bys-data-types/
Lesson 3: Arithmetic Operators
http://www.rmxpunlim...etic-operators/
Lesson 4: Variables, User Input and Type Conversion
http://www.rmxpunlim...ype-conversion/
Lesson 8: Ruby Objects In-Depth
Lesson 8a: Strings to be released
Lesson 8b: Arrays and Hashes to be released
Lesson 8c: Structs to be released
Lesson 9: Methods
Lesson 10: Classes
Lesson 11: Modules
Lesson 12: Error Handling - Raise, Rescue
Lesson 13: Advanced Flow Control - Throw, Catch
Lesson 1: Setting up a Ruby Environment
In these lessons, I will be working with the official Ruby interpreter. However, if you'd rather work through RPG Maker, that is definitely possible and for that reason, I will tell you how to do both.
Personally, I think everyone interested in really getting into Ruby (whether for use in RPG Maker or not) should get the official interpreter. This will allow you to quickly test code outside of an RPG Maker environment, as well as the interpreter comes with a interactive ruby shell, so you can test code in a live environment, without even having to write a script first. **I will use these notes for little "asides" that I have throughout the lessons. These will contain information that is not necessary in the learning process, and for the most part be more "techy" stuff.
Ruby: The Ruby Way
Windows Users

Step 1: Download and Install the Interpreter First, we will need the actual Ruby interpreter, in order to execute Ruby scripts that we create. You can head over to: http://www.ruby-lang.org/en/downloads/ There are a few ways to install Ruby, however, if you are in a Windows environment, the easiest and most painless way is to use the RubyInstaller: http://rubyinstaller.org/downloads/ The version you get isn't overly important. RPG Maker XP/VX use (I believe) version 1.8.4 If you plan to go beyond RPG Maker scripting, I would personally choose 1.9.3 (latest version) Once you have downloaded rubyinstaller, run the installer. IMPORTANT: Ensure you have "Add Ruby executables to your PATH" In this tutorial I will be mostly working with ruby from the command prompt, and this will help that process immensely. I would suggest associating .rb/.rbw files with this interpreter (assuming this is the only interpreter you have installed). This will allow you to run ruby scripts by double clicking on them. tk/tcl is NOT necessary for this tutorial. tk (toolkit) is the main GUI library for ruby, and I will not be teaching that. If you wish to learn to build GUI applications with ruby, I would advise learning tk: http://www.tkdocs.co...al/onepage.html Step 2: Confirm Installation Simply open up a command prompt Go to Start > Program Files > Accessories > Command Prompt or Go to Start > Run Type in "cmd" (without quotes) Click ok Once you have a command prompt open, type:

ruby -v

The output *should* be something similar to this:

ruby 1.9.3p0 (2011-10-30) [i386-mingw32]

The exact details may vary, but if ruby -v displays a message, then everything went correctly.

Linux Users

If you are in a Linux based environment, you could use your package manager to get ruby. ex. Aptitude Package Manager

sudo apt-get install ruby

You could also download the source code, and compile it yourself: http://www.ruby-lang.org/en/downloads/ Or, what I use is, RVM - the ruby version manager http://beginrescueend.com/rvm/basics/ This program allows you to seamlessly use and install multiple ruby interpreters side-by-side, follow the website's directions. If you need help, I can help walk you through it in more detail. Then to verify everthing went well: open a terminal, type:

ruby -v

The output *should* be something similar to this:

ruby 1.9.3p0 (2011-10-30) [i386-mingw32]

Ruby: The RPG Maker Way

I would HIGHLY advise you actually use the Ruby way. This entire tutorial is done in that way, and it achieves quicker results
Step 1: Create a new Project Open RPG Maker (XP or VX) and create a new project. Step 2: Setup Scripts Open the script editor (F11 or Tools > Script Editor), and then delete EVERY SINGLE SCRIPT. IMPORTANT: In this tutorial, when I redirect output to the console I mainly use `puts`. Unfortunately, RPG Maker does not use a console, and puts will do nothing for you. To get around this, either replace puts with `p` this will redirect the output to a Windows Message box. Or, add this script to the script editor (above any tutorial code you write) http://forum.chaos-p...hp?topic=7816.0 CREDITS AND THANKS to ForeverZer0 for this script.

And voila! We have a working ruby environment.

Ruby is, as you may know or have noticed, an interpreted language. In programming, there are two main types of languages - compiled and interpreted. What does this mean? Well, computers-as you may know-are inherently stupid. In actuality, they really only understand machine code (which is essentially numeric instructions). However, it would quite a headache to try and code in say, strictly binary or hexadecimal so, programming languages were invented. However, in order for the computer to understand these languages, the code must first be translated into machine code before the computer can understand it. Compiled languages mean the code is translated into machine code, then stored for later execution. Interpreted languages are compiled real-time (each line is translated or interpreted into machine code and executed on run-time). So, this means compiled languages (naturally) are much, much faster than interpreted languages. However, with an interpreted language, one has room for a much higher level of abstraction and allow for much more dynamic code (ex. changing an objects functionality during run-time). This also means faster development. As you can see, each have their ups and downs
Wait, that hardly seemed like a lesson.... Oh, I forgot to mention, this week you get a few small lessons to begin your journey into ruby biggrin.png I will provide you with enough to get you thinking and prepared for next week.
Lesson 2: Objects, Objects, Objects aka Ruby's Data Types
You've probably heard people talk about "object-oriented" languages or programming (and you may even know what this means already). Well then, what is an object-oriented language? It simply refers to a programming language that is based around the object model and it's concepts. So, it's probably better to start at: What is an object? Well, this may seem cheesy, but: ob·ject/'äbj?kt/ Noun: A material thing that can be seen and touched. (google search) So how does this apply to computers? Now, you may have gone ahead and googled the answer for yourself (if you did, I applaud you for doing so. Never forget that google can be the best resource if ever get stuck.), but I'll try to explain nonetheless. So, obviously, in programming, objects are not a material thing. We need to look at what an object is, in a more abstract/conceptual manner. Let's focus on this: An object is anything that can be seen or touched. An Object can be seen. If something can be seen, it would be safe to say it could be described as well, no? Well, in order to describe something, one usually lists off certain/unique characteristics or properties. An Object can be touched. If an object can be touched, that means something can be done with that object. So, in programming, an object is simply a structure that has properties or attributes, and carries some kind of functionality-it can do things. The object model and it's applications will make more sense as we progress; but I felt that since technically everything in Ruby is an object, and that I would be throwing the word around a lot, it would only be fair to give you some idea on at least what an object is. So, when I say everything in ruby is an object, I mean everything in ruby is a data structure with attributes and methods (functions, it can do something). With that in mind, I'd like to go over some of ruby's core data types. Integers Integers are simply whole numbers:
-1 0 1 2 3 999

Floats Floats are decimal point numbers:

-0.5 0.1 5.985

Strings Strings are any kind and any number of characters:

"hello, world!" "this is a string" "&^$123"

Boolean You can think of a boolean as a switch, with only 2 possible values: on or off. These values are represented by the ruby keywords:

true false

Nil Nil is a special data type, it is actually a representation of no value, or nothing. This value (or lack there of) is represented by the ruby keyword:

nil

if you have a background in another programming language, you probably have encountered the data type "null." In ruby, nil is conceptually the same as null.
I will touch on more as we progress, but this should be enough for now. I promise, in the next lesson we will actually write some code.
Lesson 3: Arithmetic Operators
Arithmetic Operations are going to be the first methods you learn about in these lessons. Just like the name implies, arithmetic operations are simple mathematical operations: adding, subtracting, multiplying, dividing, etc. These are method calls that can be invoked on various data types (mainly numeric types, like floats or integers)
Ruby Arithmetic Operators
+ Addition
- Subtraction
/ Division
* Multiplication
% Modulus
** Exponents
Okay, time to put these to use! Open up a command prompt, and type
irb

IF YOU OPTED OUT OF INSTALLING RUBY, SIMPLY PUT MY EXAMPLES INTO THE SCRIPT EDITOR AND ADD

p

BEFORE EACH EXAMPLE AND TEST PLAY (if you added foreverZer0's console script, you can use puts instead of p)

irb is that interactive Ruby shell I was talking about earlier
If Ruby was installed correctly, you should get a new prompt that looks like this:
irb(main):001:0>

Let's try some out.

irb(main):001:0> 1 + 1 => 2

1 + 1 = 2. Good, it seems to be working correctly. Now, you can use irb as a calculator! Let's play around with this a bit! The best way to learn (IMO) is to experiment on your own. So feel free to try different operations than me.

irb(main):002:0> 10000+250 
=> 10250 
irb(main):003:0> 10 * 100 
=> 1000 
irb(main):004:0> 100 / 10 
=> 10 
irb(main):005:0> 30 - 100 
=> -70 
irb(main):006:0> 10.5 + 0.777 
=> 11.277 
irb(main):007:0> 10 + 10 * 2 
=> 30

Now, wait a second... 10 + 10 = 20, 20 * 2 = 40... How come 30? You probably already guessed it...but, remember bedmas or order of precedence? That's right, bedmas applies to programming as well. Let me refresh your memory: 1. Brackets 2. Exponents 3. Division 4. Multiplication 5. Addition 6. Subtraction So, it would be interpreted as 10 * 2 = 20, 20 + 10 = 30. Now what if we want ruby to read it the other way? Well, brackets work here too:

irb(main):008:0> (10 + 10) * 2 => 40

How about this?

irb(main):009:0> 3 / 2 => 1

Wait, 3 divided by 2 is NOT 1. Here is a little quirk you need to know about programming: Integer numbers and Floating point numbers are 2 distinct numeric types. They can be used together (adding, dividing, etc), however, if you divide and integer by an integer, you will ALWAYS get an integer back.

irb(main):010:0> 3 / 2.0 => 1.5

So what does this mean? Well, if operate between integers and floats, you should know that you will always get back a float. Operating with just integers will send back integers, and of course, floats if you are operating with just floats.

irb(main):011:0> 1.5+1 
=> 2.5 
irb(main):012:0> 1.02 * 5 
=> 5.1

What about modulus? You may know what modulus is, but just in case: Modulus is a form a division (therefore, it falls into the same area of precedence as multiplication and division). How it works, is modulus divides 2 numbers and returns the remainder. I included the division operation in these examples, to help give you a full understanding of how it works:

irb(main):001:0> 3 / 2 
=> 1 
irb(main):002:0> 3 % 2 
=> 1

2 goes into 3: 1 time, with 1 leftover

irb(main):003:0> 1 / 1 
=> 1 
irb(main):004:0> 1 % 1 
=> 0

1 goes into 1: 1 time, with 0 leftover

irb(main):005:0> 1 / 5 
=> 0 
irb(main):006:0> 1 % 5 
=> 1

5 goes into 1: 0 times, with 1 leftover What happens when you add strings together? Or multiply them with integers?

irb(main):008:0> "hello" + ", world!" 
=> "hello, world!" 
irb(main):009:0> "*" * 25 
=> "*************************"

Lesson 4: Variables, User Input and Type Conversion
So, upto this point, we have only been working with literal values. A literal value, is a static value; hardcoded by the programmer. For example:
1 2 10.5 "String" 

are all literals. But, what if you aren't sure what the final value should be? Or if the value is chosen by the user? Well, as you may know, we have variables to do that. Variables are the programmers direct access to a computer's memory (RAM). Any object can be stored in variables for later use, or for whatever reason storing an object in memory may be. Anyways, let's try it on for size:

irb(main):001:0> variable = 10 
=> 10 
irb(main):002:0> puts variable 10 
=> nil

Yup, it's almost that simple. variable_name = value value can be anything from a literal value to a method that returns a value to even another variable. Now, that was the simple part. The not so simple part (but still quite simple) are variable naming rules. variables, by rule, MUST start with a lowercase letter or underscore, and can contain letters, numbers and underscores. Also, you should know that variables cannot share the same name as ANY ruby keyword or reserved word. Ruby keywords are as follows:

alias  and    BEGIN begin break case   class  def    defined? 
do     else   elsif END   end   ensure false  for    if 
in     module next  nil   not   or     redo   rescue retry 
return self   super then  true  undef  unless until  when 
while  yield

there are some exceptions to these rules, however to avoid confusion, we will go over these exceptions later. (There are however, NO exceptions to using keywords as variable names) Another thing that you should know about variables, is that although you can name a variable anything you would like; it is much better practice to give variables distinct, meaningful names. This however, is called coding convention--it is not necessary to run a program correctly, however it makes the code MUCH easier to read, and so you don't forget what each variable is later down the road. Another coding convention, is the style we use to write out our variables. The two most popular types are camel casing and snake casing. A camel-cased variable name would begin with a lowercase letter, and any sequential words begin with a capital:

thisIsACamelCasedVariableName = nil

A snake-cased variable name (which you will find much more popular in the ruby community) Snake casing means each word is separated by an underscore `_`:

this_is_a_snake_cased_variable_name = nil

Whichever way you prefer is upto you. I personally find snake casing easier to read, and all my lessons will reflect that convention. Note that it is good practice to choose a neat and consistent style. Now, back to the actual coding. So, you should understand the basic concept of what an object is, but what does this mean for programming? Well, as I said, everything is an object in ruby. To use an object, we must first create an instance of an object type. Whenever you store something in a variable, you are essentially storing an instance of an object in memory to be called upon and used. So, let's look at this example:

variable = 10

What we are doing here, is creating an instance of the Fixnum object (which is an integer type), which is initialized to have the value 10, and storing it into the variable called `variable.` This means, you can now call any method or function belonging to the Fixnum object.

irb(main):001:0> variable = 10 
=> 10 
irb(main):002:0> variable.to_s 
=> "10" 

Whoa, what happened here? What I have done here, is called the `to_s` method from variable. To call methods/attributes from a variable (or any instance of an object) in ruby, we use what is called "dot notation" object_instance dot method/attribute name. The method then returns a value (as defined by the method, in this case a string). What I mean by the method "returning a value" is that whenever a line of code is executed it sends back a value to the program. In this case, we didn't do anything with that value, but if we wanted to, we could store that value in another variable:

other_variable = variable.to_s

and in case you were wondering, to_s is simply a method that returns a string representation of the object that to_s was called from (all objects have this method) (to_s means "to string") The concept of converting objects in Ruby is called coercing.

In other languages, this term is known as "casting" or "parsing"(in terms of extracting data types from strings)
There are many different methods for converting data types, one more I will teach you, is the to_i method.
irb(main):001 > "5".to_i 
=> 5 
irb(main):002 > "5".to_i + 10 
=> 15 
irb(main):003 > "hello".to_i 
=> 0

The to_i method attempts to convert the object to an integer. In this case, an integer is extracted from a string. Alright, with that said let's make our first script! Open up a command prompt, and create a folder for our scripts: Windows:

C:\> mkdir learnruby 
C:\> cd learnruby 
C:\> notepad hello.rb

Linux:

~$ mkdir learnruby 
~$ cd learnruby 
~$ vi hello.rb

Of course, you can use any text editor that you like, it just so happens that these two editors ship with windows/linux. Now, enter this code:

 # The obligatory Hello, world program
puts("Hello, world!")

Now, let's test it out. Save the code, head back to the prompt/terminal and enter:

ruby hello.rb

This invokes the ruby interpreter on `hello.rb` (The script we made) If everything went well we should see:

ruby hello.rb 
Hello, world!

As you should know, puts writes text to the screen (or standard output)

# The obligatory Hello, world program

This however, is a comment. Any line preceded by a pound sign `#` will be ignored by the interpreter. Comments are like little signs to either help you or other programmers understand what you are doing. For long comments, you can do a `block comment`

=begin 
 Anything between the begin and 
 end is one large comment
=end

Alright, well that was fairly anti-climatic. Let's make this program a little more interesting. Let's make a greeting program, that will take the user's name, then display a personalized greeting. First, I will teach you how to get input from the user.

gets

gets is a function that, when called, gets a string from the standard input (from the user).

# First we will need to get a name from the user 
# We should store that name in a variable, for later use 
name = gets

gets always returns a string, so we can take that value and store it in a variable. Now, that we have the name, we need to display the greeting. There are a couple of ways we can do this. The first way: concatenating strings If you remember, earlier we tried adding strings together:

"Hello," + " World!"

This is called concatenation, and it works the same way with variables that hold a string:

"Hello, " + name + "!"

And of course, we can pass that to puts:

# Display our personalized greeting puts("Hello, " + name + "!")

Another way we can do this is:

"Hello, #{name}!"

This is called embedded expressions. This tells the interpreter to take the value of the expression within the `#{}` and call its to_s method and place it within the string. You can use any kind of expression, such as addition, subtraction and even call methods from within those tags. It is important however, to know that the `#{}` is only available in strings defined with the double-quotes `""`, strings defined with single-quotes `''` will interpret the #{name} literally and display #{name}. So, this will be our new hello.rb script:

# Prompt the user for input puts("Please enter your name:") # Get user's name name = gets # Display personalized greeting puts("Hello, #{name}!") 

Alright, let's call the ruby interpreter on this script again:

ruby hello.rb Please enter you name: kellessdee Hello, kellessdee !

Wait a minute, why is that explanation mark on a different line than the greeting? Well, allow me to explain. Like its counterpart puts, which prints a new-line after the string, gets also reads in the new line character. So how do we get rid of it? The simplest way, would be to invoke the "strip" method on the string:

puts("Hello, #{name.strip}")

Now lets try it:

ruby hello.rb Please enter you name: kellessdee Hello, kellessdee!

Ah, much better. We are almost finished with this lesson. This was probably a lot more to take in than the previous lessons, so let it soak in, play around with everything I have given you. Before I let you go however, I would like to mention a few other things: I was talking about a "new-line character" earlier, now you may not have gave it much thought, but I would like to point this out. With computers, to represent certain characters (such as backspaces, tabs, returns, etc) it uses a different kind of symbol. For example, the New-line escape character is:

"\n"

If you put this in a puts,

irb(main):001 > puts "Hello,\nWorld!" Hello, World! => nil

you can see that the interpreter puts the rest of the string on a new line. This can be useful when, say, building a long multi-line string, etc. Other escape characters include:

\t tab \s space \b backspace \\ backslash \" double quote \' single quote (only used within single-quote strings) 

It is important to note, that like the `#{}` escape characters only work within `""` (except for the case of `\'`) strings. In `''` strings, they will be interpreted literally. I suggest you test this out, to see what I mean. Coding Challenge: 1. Write a script, that takes two numbers from the users, and performs some kind of mathematic operation on them. 2. Write a script, that takes the users first and last name, and creates an e-mail address for them, in the format: lastname.firstname@pretendwebsite.extension firstname should be the user's inputted first name lastname should be the user's inputted last name pretendwebsite.extension can be any website name you wish Last, but not least: If you wish to learn more about the avaible objects and methods ruby provides, visit: http://www.ruby-doc.org/core-1.9.3/ This is the english documentation for the ruby api. Here it describes all of ruby's built-in objects and describes all of their methods. Please note that "classes" are a term for objects that can be created. If you don't know what that means, do not worry for now, I will explain that later. For now, you should explore the String class and the Numeric class. It will give you all the actions that can be performed on those objects, and it will give you a feel for the ruby documentation. I promise, one day it will be your best friend. Finally, don't let me stop you from learning from other places on your own if you wish to do so. In fact, if you really want to learn ruby, I ENCOURAGE you to do so.

Additional Content

Bob has brought to my attention that the whole "puts" and "p" might be a little confusing, and I admit, it really is. So, I am going to try and clarify how it works:
1.9.2p290 :001 > p "hello" "hello" => "hello"

This is the p method. This method calls the `inspect` method of the object (in this case "hello") and prints it to the console. It also appends a new-line character to the string.

1.9.2p290 :002 > print "hello" hello => nil

This is the print method. This method will print the object, and if it is not a string, call the `to_s` method from the object. This method does not append any new lines.

1.9.2p290 :006 > printf "hello" hello => nil 

This method is the printf (print formatted) method. It can be used to format your output. I will explain this method in more detail later. (feel free to look it up)

irb(main):003 > puts "hello" hello => nil 

Puts works exactly like print, except it appends a new line character. You can also specify multiple objects:

irb(main):011 > puts "hello", "world" hello world => nil 

irb(main):004 > putc "hello" h => "hello" irb(main):005 > putc "h" h => "h" irb(main):009 > putc "A" A => "A" irb(main):010 > putc 65 A => 65 

Putc essentially means put character. It reads the first character (or byte/numeric value) and prints it as a character. I hope that clears things up. I am not sure how their functionality works in rpg maker xp, however p works well.

I'd like to take the time to explain something, while on the subject of `strip` if you were to look at the ruby core documentation, you would notice two methods for the string object: `strip` and `strip!` The exclamation, or bang, is a convention on ruby signifying that the method modify's the caller. For example,
irb(main):001 > str = "hello \n" => "hello \n" 

Here we make a string with some whitespace

irb(main):002 > print str.strip hello => nil 

Here we print the string without whitespace

irb(main):003 > str => "hello \n" 

str has not changed

irb(main):004 > print str.strip! hello => nil 

here we print the string without whitespace again

irb(main):005 > str => "hello" 

this time, str no longer has any whitespace. So, when you see a method with a `!` at the end, it usually means that the method in question modifies the object that called the method.

Lesson 5: Intro to Boolean Logic
You may remember from Lesson 2 (Data types) the "Boolean" data type. If you don't, that's okay; we didn't do much with them. But after this lesson, I promise: you will be on your way to becoming a boolean master. Money back guarantee! (yes, I do know you aren't paying anything for this...MUAHAHAHA!!! err, ahem..) So, like I mentioned before, a boolean is either "true" or "false" in ruby. Really though, all a boolean is, is a representation of two possible values: true or false, on or off, 0 or 1, etc.
For you RPG Maker users, you might notice a boolean is quite similar to a switch. In fact, they are the same thing.
Fun Fact: In older, and more lower-level languages (ex. C) boolean types actually do not exist, and rather than being represented by an abstract "true" or "false," booleans were represented by integers: 0 or 1. Additionally, to show where this comes from, computers at the lowest level, really only understand binary (0s and 1s), a single Binary Digit (or bit) is either 1 (on) or 0(off).
So, how are booleans useful? Well, as you will learn, booleans and boolean logic is very useful in determining a program's state and can be used in decision making. However, before we get into that, I would like you to know how boolean logic works. I apologize that this lesson will be a little more conceptual than the previous lesson, but it is necessary you understand boolean logic before we begin the next lesson. If you can master boolean logic, you will be ahead of the game. So, let's begin. Now, we know that a boolean represents two values: true and false. But where do these values come from? First, we must look at boolean expressions, expression that generate a boolean value. You can think of a boolean expression, almost like a question, or more specifically: a boolean question. A question could be: "How are you today?" "What is your name?" These questions, however, could have many answers. A boolean question, would ask something more specific: "Are you 18 years of age?" "Do you own a computer?" "Is your name Kellessdee?" These questions, although in real life we may answer these in different ways, ultimately are looking for one answer, either "yes" or "no." But how do we ask these kinds of questions in ruby? Well, in programming, rather than looking at the question as a whole, you have to look at what data is really being tested. "Is age equal to 18?" "Is number of computers greater than 0?" "Is name equal to 'Kellessdee'?" While computers are terrible at interpreting human language, computers are REALLY good at comparing data or values. To write these comparisons into a program, the language in question will provide us with various comparative operators. We can create boolean expressions with these operators, which will evaluate to boolean values. In ruby's case:
> - Greater than >= - Greater than or equal to < - Less than <= - Less than or equal to == - Equal to != - Not equal to

There are other ruby comparison operators, however those are usually special operators, and I will explain them in later lessons
You can use these operators with nearly any object. Some of these may behave differently depending on the object, and for now I will only go over Numeric values and String values. So back on those previous questions; how might we represent them in ruby?
irb(main):001 > age = 18 => 18 irb(main):002 > age == 18 => true irb(main):003 > number_of_computers = 0 => 0 irb(main):004 > number_of_computers > 0 => false irb(main):005 > name = 'kellessdee' => "kellessdee" irb(main):006 > name == 'Kellessdee' => false

So, as you can see, we use a variable to store the value, and we can compare that value based on the question we are asking.

You do not need to use a variable, and can compare literal values:
irb(main):007 > "hello" == "hello" => true

However, you should never do this. There is no sense in using the computer's resources to compare values that are already known to the programmer. We will use variables, to simulate a value that could be any value

You might be wondering why the last expression evaluated to false. Well, as you may have known or guessed by now, when comparing strings, ruby compares each character and if all are equal, then the string is equal. Each character is actually represented by an integer (ASCII value), and thus, 'k' and 'K' are not the same. Luckily, ruby strings have a useful method we can use to get around this - string.upcase and string.downcase These methods convert each character in a string to it's upper-case or lower-case equivalent, and returns the new string. So, if you wanted to check the equality of two strings, but not depend on the case:
irb(main):008 > name = "KeLlEsSdEe" => "KeLlEsSdEe" irb(main):009 > name.downcase == "kellessdee" => true

or

irb(main):010 > name = "KELLESSDEE" => "KELLESSDEE" irb(main):011 > other = "kellessdee" => "kellessdee" irb(main):012 > name.downcase == other.downcase => true irb(main):013 > name.upcase == other.upcase => true

Another thing to remember about comparing strings, if you use the >, >=, <, <= to compare strings, ruby will compare the LENGTH (number of characters) of the two strings.

irb(main):017 > "one" < "three" => true

"one" is 3 characters, and "three" is 5 characters: 3 < 5 == true A few other tips to keep in mind: Be careful with > and >= or < and <= when two values are compared with >= or <=, if they are equal, the expression will return true. With < or >, if they are equal the expression will return false. So there we have it. We can now ask ruby simple questions, and receive boolean answers. Now, for the hard part. What if we want to ask ruby a more complex question? "Is your name kellessdee and are you over 18?" In reality, this is two questions. However, there is still only one answer. Yes or No. In my case, my name is kellessdee (well, username teehee) and I am 22, which means I am over 18. So, I would answer yes. Easy enough for us to simply process...but what about a computer? Well, think about it this way. There are actually two individual questions, with individual answers: name == kellessdee? Yes. age > 18? Yes. So really, the answer is Yes and yes. or true and true. So, we could make two separate comparisons, and go from there, or we could use ruby's (conveniently) built-in "logical" operators. They are:

&& - logical AND || - logical OR ! - logical NOT and - logical AND or - logical OR not - logical NOT

So you have a couple options here to join simple boolean expressions, to form complex boolean expressions. Most RPG Maker scripts use the English versions "and" "or" and "not". Because of this, and that these versions are easier to read, I will teach you with the English versions.

Due to the way ruby handles the order of precedence, "and" "or" and "not" actually do not behave the same way as "&&" "||" and "!". In order of precedence, ! > && > ||, like it should be...however, not = and = or. The English operators have the same precedence in ruby. To be safe, always use parentheses to group your expressions in the order you want them to be evaluated. I will follow this tactic in my lessons. If you are comfortable with &&, ||, !; I would advise to use this form, as they work how they should.
AND and returns true if all expressions are true, otherwise returns false
irb(main):018 > true and true => true irb(main):019 > true and false => false irb(main):020 > false and false => false

OR or returns true if one expression is true, and false only if all expressions are false

irb(main):021 > true or true => true irb(main):022 > true or false => true irb(main):023 > false or false => false

NOT not is special, it is a unary operator (meaning it only operates on one value), and simply inverses the result of the expression or returns the opposite.

irb(main):024 > not true => false irb(main):025 > not false => true

So, lets try the complex question again:

irb(main):026 > name = "Kellessdee" => "Kellessdee" irb(main):027 > age = 22 => 22 irb(main):028 > (age > 18) and (name.downcase == "kellessdee") => true

And that, is the basics of boolean logic. Now, the problem with this, is it's one thing to explain and read about boolean logic, but it is harder to practice. It will be easier to understand once we apply it to decision-making, but for now, I would like to leave you with some practice questions (try to get the answer without putting these into IRB or a script). 1. true or (false and (true and false)) ANSWER

true

2. false and (true or false) ANSWER

false

3. false or (true and false) or (true and (false or (true and (false or false)))) ANSWER

false

4. (true or (false and true) or false) and (true or (false and false)) ANSWER

true

5. (true and (true or false)) and (true or (true and (true and (false or false))) or true ANSWER

true

Quick Technical Info on and/or

One thing every programmer should know about and, or; is that they are what we would refer to as "short-circuiting." If you may have noticed, with and, if any of the expressions are FALSE the entire expression will be false. With or on the other hand, if any expression is TRUE, the entire expression will be true. Therefore, the ruby interpreter will evaluate the expressions, from left to right - if it finds an OR expression and hits a true, it will stop evaluating that expression - it already knows the entire expression will be true. Same goes for AND...when it hits a false value, it will stop evaluating because it knows the entire expression will be false. With that in mind, with any complex AND expression - you should test the values MOST likely to be false first (false most of the time) and with any complex OR expression - you should test the values MOST likely to be true first (true most of time)
Lesson 6: Flow Control - Decision Making
In the previous lesson, I taught you about boolean logic. Hopefully, you have a good basis to the concept. This lesson will actually put that logic to good, practical use. This lesson is the first part in the series on Flow Control. Now, for the obligatory "What is flow control...?" At this point, all your programs have had a very basic flow, just execute each line, one by one. However, when you start making real applications/programs, you'll find that this one directional program flow is too simple for your application. This is where flow control comes in, we want to be able to control the flow of the program. The most basic form of flow control is decision making. In programming, decision making is possible through the use of `if` statements. An if statement is what we use to make our boolean expressions do something. "if this, then do that." So, in ruby...
if  # What we want to do end

where is an expression. note that an if statement must be closed with the "end" keyword.

The code we embed within the "if clause" or "if statement" is tabbed, or by ruby's conventions, 2 spaces from the left margin. This is not necessary for the code to run, but as a coding convention this makes your code much easier to read and understand.
What happens when the Ruby interpreter reaches an if statement? The interpreter will first evaluate , if evaluates to true, the code inside the statement will be executed. If the is false, the code inside the statement will be ignored, and the interpreter will continue from the line with "end" What about this?
if 1 puts "1 is true" end

If you were to run this code, the output would be:

1 is true

But why? 1 is not a boolean! Well, this is because of how ruby handles boolean expressions. When the interpreter gets to the "if ..." it assumes the expression to be a boolean expression, and with ruby, anything except nil and false is interpreted as true, and nil and false interpreted as false. So, when the interpreter gets to "if 1", it evaluates the expression, in this case 1 returns 1, and since the value is not nil and not false (1), the code within the if statement is executed. So, let's try an example. I want you to create a script this time, call it "age.rb" So let's do some decision handling. We are going to make a program that takes the user's age, and tells them if they can buy alcohol. In Canada, where I live, you need to be 19 or older. You can incorporate your local age limit for drinking into the program if you'd like.

 # Prompt the user to enter their age # we use print as that does not append a new line character print ("Enter your age: ") # Now we should get the users age # and convert to an integer: age = gets.to_i # Lets see if the user is old enough if (age >= 19) # They are of age! puts ("You are old enough to buy alcohol.") end 

So, why not try it out!

ruby age.rb

Upon running your script, you will notice, unless you enter 19 or greater, the script will just end. Only if you enter age greater than or equal to 19, you will get "You are old enough to buy alcohol." Well, we should let the user know if they aren't old enough to buy alcohol as well...and hey, why not let them know how many more years until they can? The next part of the "if" statement, is the "else" clause.

if  # Code if condition true else # Code if condition not true end

The block of code in the "else" clause will only be executed if the original block or any other block within the if statement is NOT executed. In this case, if the is false, the first block will not be executed. Because of this, the second block under "else" will be executed instead.

if (age >= 19) # They are of age! puts ("You are old enough to buy alcohol.") else # They are not of age! years_left = 19 - age # How many years until they can buy alcohol puts ("You are not old enough. Come back in #{years_left} years!") end

If you add that to your age.rb script, you will notice if you enter an age less than 19, the program will print out "You are not old enough. Come back in X years!" So now, you can test a value, and can act based upon whether or not that test is true. But, what if we want to act depending on several possibilities? This is where "elsif" come into play. The "elsif" clause allows us to create multi-sided responses, based on multiple conditions.

if  # Code elsif  # Code else # Code end

The ruby interpreter will first enter the if statement at "if ," if that condition is true, it will execute the following block of code, then jump to the "end." If that condition is false, the interpreter will then move to the first "elsif ." If that condition is true, the interpreter will execute the block of code within the elsif clause, then jump to the "end." If false, the interpreter will continuously check any following "elsif" and if none are true, finally the "else" block will be executed instead. So, this means you could have any arbitrary number of elsifs:

if  # Code elsif  # Code elsif  # Code elsif  # Code else # Code end

With the if statement, you can have as many elsif clauses as you'd like, however you can only have ONE if clause, and ONE else clause. You should also know, that the else clause is optional, whereas the if clause is NOT optional
Be careful, if you have programmed in other languages, you may notice that the "elsif" equivalent may be represented differently, ex. else if © or elif (python), in ruby it is "elsif"
So, why might you need to test multiple conditions? Well, let's try this example: Let's pretend we want to make a guessing game. The Game will have a set number, and the user will try to guess which number is set. If they guess too low, the program will say: "Too low!" and if the number is too high, the program will say: "Too high!", and if the number is equal, the computer will say "Wow! You got it!"
We will not be making this guessing game fully functional just yet, in a real guessing game, you'd want the number to be different each time, and probably want the program to run until the user quits. We will finish this game in later lessons
So, how would we do this?
# Set a number to guess number = 10 # Prompt the user to guess what number it is: print ("I am thinking of a number. What is it? ") # Get the guess guess = gets.to_i if guess < number puts ("Too low!") elsif guess > number puts ("Too high!") else puts ("Wow! You got it!") end

Try putting this in a script called "guessinggame.rb" and running it.

As you may have noticed, the if statement could have also been written like this:
if guess < number elsif guess > number elsif guess == number end

This would work exactly the same. However, I chose to catch that in an else clause, as we know that if guess is NOT less than number, and NOT greater than number, it HAS to be equal to number. So, it would be more efficient to group that code under an else clause. In order to determine whether to execute a block under an if/elsif, the interpreter has to execute and evaluate the condition. With else, that condition is not executed, saving us some CPU processing.

Let's try another example. Let's make a program that gets the current month as a number, and prints out the English name of that month.
# Get month: prints ("Please enter the current month as a number: ") month = gets.to_i if month == 1 puts ("January") elsif month == 2 puts ("February") elsif month == 3 puts ("March") elsif month == 4 puts ("April") elsif month == 5 puts ("May") elsif month == 6 puts ("June") elsif month == 7 puts ("July") elsif month == 8 puts ("August") elsif month == 9 puts ("September") elsif month == 10 puts ("October") elsif month == 11 puts ("November") elsif month == 12 puts ("December") end

Whew, that was a lot of work. It works, but that seems like an awful a lot for a simple translation. As you can see, in some cases you may want to test for a specific value, and each value could represent something specific. Well, thankfully, ruby has a much more elegant way of doing this, with "switch" or "case" statements.

case  when value then #code when value then #code when value then #code else #code end

So how does this work? The case statement takes then tests that variable against each value, testing if they are equal to each other. The first value that matches, it's corresponding code is executed. You can have an arbitrary number of when clauses, and else works exactly like in if. If no other values are equal to then else will be executed. Like in the if statements, else is optional here as well.

The "then" part of "when value then" is optional, as long as you have the block of code on a new line.
when value # Code must be here

However, with the "then" portion, you can actually put the block on the same line:

when value then # Code could be here

Also, I would like to point out that the "else" portion SHOULD NEVER have a "then," if you want to put the else block on the same line, use a semi-colon (wink.png (ruby interprets this as a line terminator)

else; # Code could be here

So, lets fix our nasty if statement:
case month when 1 then puts ("January") when 2 then puts ("February") when 3 then puts ("March") when 4 then puts ("April") when 5 then puts ("May") when 6 then puts ("June") when 7 then puts ("July") when 8 then puts ("August") when 9 then puts ("September") when 10 then puts ("October") when 11 then puts ("November") when 12 then puts ("December") end

Well, that looks much neater. It's still long, but neater and a little less typing. However, I feel that the output is too "hard coded." What if later, we decide we want to put the month into a variable, for later usage? We'd have to change each "puts" to "variable =." With modern IDEs, this would be a simple task, but still unnecessary. One major rule of the ruby community (or even any programming community) is "Don't Repeat Yourself", and I feel both "puts" or "variable =" that many times, is repeating yourself. Conveniently, we can get around this. Remember how everything in ruby is an object? And every expression returns an object? Well, case is no different. case will "return" (or send back what the block returns) whichever block of code passes the test. In this case, it sends back "puts ("month")". Well, as you may know, the line of code "string" will return a string object, with the value "string." So what about this:

puts case month when 1 then "January" when 2 then "February" when 3 then "March" when 4 then "April" when 5 then "May" when 6 then "June" when 7 then "July" when 8 then "August" when 9 then "September" when 10 then "October" when 11 then "November" when 12 then "December" end

Now, that, is much neater. Normally, we would want to put the block of code in a when ... clause on the next line, but in the case where we are simply returning a single string, I find it actually more readable like this. Then, if we wanted to change it to store the month in a variable:

# Get month prints ("Please enter the current month as a number: ") month_no = gets.to_i month_word = case month when 1 then "January" when 2 then "February" when 3 then "March" when 4 then "April" when 5 then "May" when 6 then "June" when 7 then "July" when 8 then "August" when 9 then "September" when 10 then "October" when 11 then "November" when 12 then "December" end puts ("The month is #{month_word}.")

Now we only had to change one line of code, rather than 12 lines of code. You'll probably find yourself using "if" statements MUCH more than case/switch statements; however for certain things, especially menus (where you have several choices, and the current choice is stored in a single variable) case statements are much easier to employ.

The case/switch statement is mainly used to test a single variable against multiple different values, however it IS possible to use it like an if...elsif statement:
case when variable == 5 when other_variable < 5 end

However, this isn't often used, as if...elsif would be preferred in this case.

The case/switch statement uses the === operator to test the variable against when value rather than the == operator. For the most part, === works EXACTLY like ==. The reason for this is so one can define their own object's "case" behavior. I will explain how one can take advantage of this in later lessons; so do not worry about it for now. I just wanted to give you a heads up, in case you might be learning with other tutorials as well.
One last thing I would like to teach you, is the "conditional assignment operator." As you start writing your own programs, you may find yourself in a situation where you only wish to assign a variable a certain value, depending on one condition, otherwise, set it to something else. This is called conditional assignment. For example, what if we want the absolute (non-negative) value of a number? We could do something like this:
if number < 0 absolute = -number else absolute = number end

That works, and is neat; but it's a lot of extra typing. This is where the conditional assignment operator comes in. It's a little bit trickier than if statements, but can save a lot of typing.

variable =  ?  : 

is any boolean expression is the value assigned to variable if is true is the value assigned to variable if is false The important things to watch for is, MUST be followed by a `?` and must be separated by spaces. The true / false values MUST be separated by `:` So, let's try our example:

absolute = number < 0 ? -number : number

So, if number is less than 0, give absolute the value of -number (which would be positive, since number is < 0) otherwise, just give absolute the value of number. Now, it looks a bit neater, and much less typing.

You do not NEED to use conditional assignment. However, if you are comfortable with using it, I would suggest doing so, as it can save you a lot of typing in the long run.
There are also other "forms" of conditional assignment, that are used less often. I will leave those out for now, and include them at another time. So, that's it for now. Before I go, I would like to leave you with a few practice coding challenges:
The following challenges are borrowed from "Practical C Programming" by Steve Oulline. I feel these are vary practical and challenging uses of decision making, and couldn't think of anything better sad.png (and I wanted you to have a lot more practice at this point) (By the way, they are actually easier to solve in ruby than in C)
1. Write a program that takes a student's grade as a number/percentage, and prints out their letter grade.
Grade Table
Letter Grade Numeric Grade
F 0-60
D 61-70
C 71-80
B 81-90
A 91-100
(HINT: Remember how the interpreter executes an if statement) 2. Modify the previous program, to also display a + or - after the letter. The +/- modifier is based on the last digit of the numeric grade:
Grade Modifications
Last Digit Modifier
1-3 -
4-7 [/td]
+
ex. 81 = B-, 94 = A, 68 = D+. Remember, and F is only an F, you cannot get an F- (HINT: Remember the modulus operator? `%` ? EVEN BIGGER HINT:

irb(main):001 > 1 % 10 => 1 irb(main):002 > 11 % 10 => 1 irb(main):003 > 21 % 10 => 1

3. Given an amount of money (less than $1.00), compute the number of quarters, dimes, nickels, and pennies needed. 4. A leap year is any year divisible by 4, unless the year is divisible by 100, but not 400. Write a program to tell if a year is a leap year. 5. Write a program that, given the number of hours an employee worked and the hourly wage, computes the employee's weekly pay. Count any hours over 40 as overtime at time and a half. 6. EXTRA HOMEWORK CHALLENGE: If the previous challenges did not satisfy you, here's the REAL challenge. For this challenge, you will need to go out and learn about Ruby's "Range" data type. Do not worry, I will teach you about this data type in the future. http://www.ruby-doc.....9.3/Range.html Now, the challenge will be to redo the first 2 challenges, using the Range class. HINTS

To create a Range data type, the shorthand is:

variable = 0..5 variable = 0...5

0 is the (minimum) starting number 5 is the (maximum) ending number .. means 0 to 5 inclusive (0, 1, 2, 3, 4, 5) ... means 0 to 5 exclusive (0, 1, 2, 3, 4) To solve this new challenge, you will need to find out how Ranges behave within a case statement (HINT: look up the === method)

MORE ON IF STATEMENTS:
The following is a few extra points about "if" statements. These are non-essentially to learning if statements, but you may find them QUITE useful (I know I do). I left them out of the main lesson because I didn't want to overload you with too much. I would advise that you first ensure you are comfortable with using if statements, before learning these.

Unless...elsif...else...end
For almost every ruby statement, there is an opposite to that statement. For example, puts/gets. puts prints a string and adds a new-line; gets takes a string and adds a new-line. For if, we have "unless."
unless variable == 5 # Do this end

That would be the same as writing:

if variable != 5 # Do this end

or, more specifically

if !(variable == 5) # Do this end

Unless works exactly like if, except you cannot use "elsif", and of course, it evaluates the then inverses the result. Unless works best with single sided-decisions, and statement modifiers (easiest to read), so, be careful, as unless can get confusing fast, especially when testing complex statements, like:

unless (true and false) or true puts "false" else puts "true" end

The output would be:

true

This is because (true and false) or true is true, (true and false) = false, (false or true) = true, then unless executes the else block, because the condition was true. So,

unless !(true and false or true) puts "false" else puts "true" end

would produce:

false

Confusing? It can be. Use your discretion when using the unless statement.

Statement Modifiers
Sometimes, we only need do execute one line of code, based on a specific condition, ex.
if  variable = 0 end

However, ruby provides us a simple, neat way to write this in one line of code:

variable = 0 if 

this Works EXACTLY like the previous statement. With statement modifiers, you can ONLY have a one-sided decision, and can ONLY have one line that is executed. This also works for unless statements:

variable = 0 unless 

Technically, you can have more than one line of code executed, with use of parentheses and semi-colons, ex.
(puts variable; variable = 0) if variable != 0

However, this is not preferable. It makes the code more difficult to read. But, nonetheless, in some cases it might be okay to do this, just do what feels best for you.

Lesson 7: Flow Control - Looping

 

Ah, looping. Loops, in my opinion, are what separate a "script" from a "program." So, here comes the obligatory...

 

What is a loop?

 

Think of the word loop, in the terms of a song loop -- we say a song is looping when it repeats, once it reaches the end.

A loop in programming, is generally a block of code that is repeated any arbitrary number of times.

For example, at its very essence, all a video game is, is a huge loop continuously taking input and reacting based on the input and the game's current state, until the player quits the game.

So how does it work? Well, in ruby, there are actually many ways to "loop" or iterate -- as it's commonly referred to as -- let's start with the while loop.

while condition do
 # Loop block
end

The `do` portion of the while - loop syntax is optional --

while condition
 # Loop block
end

works as well.

 

So, "while" the "condition" evaluates to true (anything except false or nil), execute block. The while loop will continuously repeat until condition is false or nil.

Be Careful -- Endless loops. Endless loops refer to a loop that never ends. This happens because the condition never becomes false. If you get stuck in an endless loop, usually CTRL + C will break the loop.

As a programmer, we need to have some kind of control over how long a program repeats its statements.

One common method of loop control, is through use of a counter:

i = 0
while i < 5
 puts "Hello!"
 i += 1
end

the output would be:

Hello!
Hello!
Hello!
Hello!
Hello!

How did this happen?

The interpreter sets a variable, `i`, to 0. It then enters the loop:

Is i less than 5? yes, display "Hello". i is now 1

Is i less than 5? yes, display "Hello". i is now 2

Is i less than 5? yes, display "Hello". i is now 3

Is i less than 5? yes, display "Hello". i is now 4

Is i less than 5? yes, display "Hello". i is now 5

Is i less than 5? no, i is equal to 5, stop looping.

We can use a variable as a counter, and use an arbitrary maximum number of iterations and then by counting the number of iterations we can determine when to stop executing the block.

Here's a better example:

"In mathematics, the factorial of a non-negative integer n, denoted by n!, is the product of all positive integers less than or equal to n. For example, 5! = 5 x 4 x 3 x 2 x 1 = 120 " (http://en.wikipedia.org/wiki/Factorial) (Yea, I was lazy and they had a better explanation......)

Er, let's translate this to our code!

Let's say we want a program that takes a number from the user, and calculates that number's factorial.

# Calculate the factorial
print("Enter a number: ")
number = gets.to_i
# Get first number
factorial = number
print("#{number}!\n#{number}")
while number > 1 
 # move to next number
 number -= 1
 # get product of n..n-1
 factorial *= number
 print(" * #{number} ")
end
puts("= #{factorial}")

Test:

Enter a number: 5
5!
5 * 4  * 3  * 2  * 1 = 120

Looks good! As you can see, counters can decrement as well. How you do it, will mostly depend on the situation (remember, you don't always have to increment/decrement by 1, either.)

 

Of course, condition can be ANY expression, and is also used to loop based on a program's "current state."

Let's go back to the guessing game we created. Wouldn't it be much better if we let the user keep guessing until they quit or guess the number?

# Set a number to guess
number = 10
# define the current "state"
game_over = false
while !game_over
 # Prompt the user to guess what number it is:
 print("I am thinking of a number. What is it? (Type q to quit) ")
 # Get the guess
 guess = gets.strip
 if guess.upcase == "Q"
   puts("Goodbye!")
   # Change current "state"
   game_over = true
 elsif guess.to_i < number
   puts("Too low!")
 elsif guess.to_i > number
   puts("Too high!")
 elsif guess.to_i == number
   puts("Wow! You got it!")
   # Won the game, change state
   game_over = true
 end
end

 

Now, our simple guessing game is actually a game! Well, mostly. We'd want to randomize the number to make it more of a game, but I will go over random number generation another time. For now, it does what we need. The game will now continuously prompt the user until the variable game_over is true. Notice that, we could have instead made a variable, say, game_playing, and set it to true. Then, while game_playing is true, prompt the user -- either way would work.

 

Before we finish, I'd like to introduce to another form of looping, and some more loop control methods.

The next loop you will learn about, is called the "for" loop. The for loop can be considered a special type of iterator, but for now, just think of it as a loop with very specific bounds. (I will go over more about for and iterators, in a later lesson)

 

Let's go back to the factorial program we made. If you notice, a factorial always loops a very specific number of times. The number of times it loops may be dependant on the input, but it will always be a set value. This is where for loops come in.

for i in 0..5
 puts i
end

produces:

0
1
2
3
4
5

So how does this work?

Well, the syntax is:

for variable in set
 # Block
end

For loops, will iterate through each item in a "set" (for now, we will only discuss ranges), and store the current object in the set, in the variable 'i'.

So what happened in the above loop? Well, in Ruby, a Range object (denoted by min..max or min...max), is actually a representation of a set of numbers from min to max.

Be careful with ranges, 0..5 means 0 to 5 inclusive, while 0...5 means 0 to 5 exclusive:

0..5 => 0, 1, 2, 3, 4, 5

0...5 => 0, 1, 2, 3, 4

Then, based on this analysis, i is first set to 0 (first item in the set), then we print i in the block. When we move to the next item/iteration, i is then set to 1, and we print it. The loop continues this pattern, until we reach the last item, then when there are no items left to be stored in i, we break out of the loop.

Why is this useful? Well, let's put this to more practical use. Let's go back to the factorial program -- like I promised.

# Calculate the factorial
print("Enter a number: ")
number = gets.to_i
factorial = number
for i in 1...number # 

factorial *= i

end

puts("#{number}! = #{factorial}")[/code]Note, that unfortunately, ranges don't work in reverse. For example, 5...1 is not 5,4,3,2. It will not work. There are ways to reverse ranges, but that would be treading into an area I want to save for another lesson.

 

Ahem, any who, carrying on... (I apologize for a larger amount of "later..."s, I would like, for this lesson, to focus on the concept of loops, without worrying too much about extra technical details, at least not yet)

 

Another good use of for loops, is for generating rows and columns of display. Say, we want to generate a pattern like this:

***************
***************

We could simply hard code a couple puts, and it would work...but what if we want to be able to draw any size?

# Get rows and columns
print("Enter number of rows: ")
rows = gets.to_i
print("Enter number of columns: ")
cols = gets.to_i
# Display pattern
for i in 0...rows
 for j in 0...cols
   print("*")
 end
 print("\n")
end

could produce:

Enter number of rows: 2
Enter number of columns: 15 
***************
***************

It may seem silly, but if you can grasp this concept of nested for loops, you will find it VERY useful later on. But what exactly happens?

 

So, rows == 2 and cols == 15.

 

We enter the first loop at i = 0, and the second loop at j = 0.

 

Then j will become 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 (remember, 0...cols is 0 to cols exclusive) and on each iteration, the interpreter will print a `*` on a single line.

 

When we break out of the nested loop, ruby prints a \n (newline character), then i becomes 1.

 

We then reach the nested loop again, and it does the exact same thing, printing 15 `*`s on the next line (notice, 0-14 inclusive or 0-15 exclusive, is 15 different numbers).

 

We break, print a new line, i runs out of numbers (0...rows exclusive => 0, 1) and therefore break from the outerloop, and stop looping altogether.

 

This concept will become very useful, when looping through grid-based data structures. (A single for loop, if you noticed, is meant/really good at looping through list-based data structures).

 

Finally, before I finish loops, I would like to teach you a couple useful control statements for loops -- break, and next.

 

loop do
 # Prompt the user to guess what number it is:
 print("I am thinking of a number. What is it? (Type q to quit) ")
 # Get the guess
 guess = gets.strip
 if guess.upcase == "Q"
   puts("Goodbye!")
   break
 end

 guess = guess.to_i

 if guess < number
   puts("Too low!")
   next
 end

 if guess > number
   puts("Too high!")
   next
 end

 if guess == number
   puts("Wow! You got it!")
   break
 end
end

So, this is a slightly modified version of our guessing game. If you try it out, you might notice it works exactly the same! Let's analyze what I changed.

Firstly, the loop is no longer a while loop...

loop do
 # Code
end

This is just another form of loop that ruby has, that represents an infinite loop -- when the interpreter finds this, it will continuously loop the block of code. (This is useful for if you need to loop, but not based on a certain state/condition).

 

Now, when a guess is made, if the guess is 'Q' or the right number, the loop will "break." break is a keyword in ruby, and is also a special function. It will "break out" of the current, immediate loop, and stop looping (Note, if you use break in a nested loop, it will only break out of the loop it is called from, not all loops).

 

We also, use `next` if the number is incorrect. next is like break (a special function for controlling loops), but what it does, is tell the ruby interpreter to skip to the "next" iteration, meaning next will skip the rest of the block of code, and restart the loop. If used in a for loop, this also means i becomes the next item in the list.

 

Well, that's all for today's lesson! I apologize for taking so long this time. Things are getting busy for me again, and I may take a little bit longer to finish each lesson. I will try my best, however, to keep the lessons coming once a week!

 

Now, I will leave you with a few more challenges:

 

1. Make a simple "menu" script, that will continuously prompt the user to enter a numeric selection, and display a different message based on the input. If the user types "q" or "Q" the menu should stop.

 

2. Write a script that will generate this output:

*
**
***
****
*****
******
*******
********
*********
**********

or, if you're feeling really creative, try making it look like this:

     *
   ***
  *****
 *******
*********
***********

(Kinda late for christmas isn't it????)

 

3. The formula for converting degrees celsius to degrees fahrenheit is:

F = C * 9 / 5 + 32

Write a script that will display a Celsius -> Fahrenheit conversion table

from -10 celsius to 40 celsius.

i.e

-10C = 14F
-9C = 15.8F
-8C = 17.6F
-7C = 19.4F
...etc.

Share this post


Link to post
Share on other sites

-Fixed some spelling/grammatical errors (thank you bob for pointing these out)

-Fixed error with incorrect method name `trim` (it is actually `strip` damn you java xD)

-Added additional content (explanations of p, print, printf, putc, puts, putc and bang `!` methods)

Share this post


Link to post
Share on other sites

+1 for you kell, in this wall of usefullness clap.gifalright.gifbiggrin_002.gif

 

There's also some books out that can help as well. I havent gotten to read it yet but the one I have virtually on my computer is:

Eloquent Ruby by Russ Olsen.

 

Keep out the good work.

Share this post


Link to post
Share on other sites

I will definitely make use of this in the (not so near) future when I'm more advanced at RMXP and ready to take on scripting. Thanks for posting!

Share this post


Link to post
Share on other sites

Thanks for the feedback guys :) I hope to get this into a full-blown discussion, so as to help those starting off in ruby.

I hope this helps, and ANY feedback you have, let me know.

 

@bigace: That sounds like a nice book, I will have to check it out.

 

Here's some links, for anyone who wishes to look outside of the current lessons (or even, look deeper into things I have mentioned)

Ruby Home Page

http://www.ruby-lang.org/en/

 

Ruby Tutorials, etc.

http://www.ruby-lang.org/en/documentation/

 

Ruby API

http://ruby-doc.org/core-1.9.3/

 

Cool Interactive tutorial (Marked posted this a little while back):

http://rubymonk.com/

 

Advanced Ruby Concepts

http://blog.rubybestpractices.com/

 

Personally, I think, while starting out in any programming language, to find a tutorial that works for you best and stick with that tutorial. Learning from too many different sources can cause confusion, as everyone has a different view on how a programming language should be taught, and of course everyone has a different methods to teaching, and different target audiences. For example, If you have a background in Programming, my tutorial may be a little slow to start for you (0 previous knowledge is assumed). So, I am going to try and share as many places for anyone who wishes to learn, and I suggest even taking a look around at what's available. Find which tutorial best suits your learning style, and go from there.

Share this post


Link to post
Share on other sites

Any type of tutorial to try and convert between XP and VX. I always find cool codes but there always on VX, and I always have trouble converting them to XP. So thats why I'm asking.

 

@bigace: That sounds like a nice book, I will have to check it out.

If you want I can send you the ebook, but you'll need to get the Mobipocket Reader or something equivenlet to it in order to read it.

Edited by bigace

Share this post


Link to post
Share on other sites

Hmm, I was panning having a tutorial about RGSS/RGSS2/RGSS3 after these sets of lessons, however I can see why anyone would want a tutorial on converting between libraries. What I could do, is write a separate tutorial on conversions on the side. I want to keep RGSS out of my ruby lessons, to avoid confusion.

 

Converting scripts in this way, is probably a lot more ambiguous, however I think I could write up a basic tutorial to get you/anyone else started.

 

I'm gonna look for this book myself to pick up. If I cannot find it however, I may be dropping you a PM.

(I need to add more nerd books to my collection, PM if you want any, I think I have a few ruby already, plus countless others)

Share this post


Link to post
Share on other sites

Added 2 new lessons:

 

- Lessons 5: Intro to boolean Logic

- Lessons 6: Flow Control - Decision Making

 

Will hopefully be adding:

 

- Solutions to last week's challenges

- Intro to the Ruby Interpreter

- Coding Convention

 

Later today.

Share this post


Link to post
Share on other sites

Are you asking about this week's challenges? Or Last Week's?

 

Or was that joke to imply they weren't challenging enough? lol spiteful.gif

 

Although, in this topic they may be harder to find, considering it's all buried. If you use my blog, it's probably easier to read through. Last week's challenges were in Lesson 4, and this week's are in Lesson 6. (I just realized, it took me a bit to find them in my own topic xD)

 

So here ya go. You are probably ahead of these lessons Bigace, but I think working out a word problem is always good practice.

So if you, or anyone is looking for more challenges (or harder ones) let me know. I got a lot lying around I could put to use :3

 

Also, I am not sure if I have said this before, but:

If ANYONE feels like the current explanation of something or lesson is lacking (meaning, you still don't get what I am trying to say or I just sucked at explaining or whichever way you think it might be lacking) PLEASE LET ME KNOW. I want to create a beginner-friendly (so non-programmer) tutorial to work with, while still allowing them to learn exactly what they are doing.

 

I notice, that *MOST* of the time, when someone teaches a language (online or offline) they tend to do a good job of teach one what to do or how to do something...but ALWAYS fail to teach WHY or what is REALLY happening when you do that. I believe, that to become REALLY good or master a language, one needs to know how it works. And, I found that the main difficulty people I've met have had with programming, is that they don't know why they're doing these things, so it doesn't stick; and causes later problems.

 

I mean, ruby is open source, and one could say "Oh, if you wanna know -- just read the source code!" But, that doesn't benefit those just learning the language, or especially not those who have no previous programming knowledge. I think most teachers fail to recognize the fact that knowing how a language really works is just as important as knowing how to use it. EVEN for those just beginning, if not moreso!

 

Whoa, that rant was not orginally intended to be so rant-y xD HERE's the challenges lol.

 

Last Week's Challenges:

 

Coding Challenge:

 

1. Write a script, that takes two numbers from the users, and performs some kind of mathematic operation on them.

 

2. Write a script, that takes the users first and last name, and creates an e-mail address for them, in the format:

lastname.firstname@pretendwebsite.extension

firstname should be the user's inputted first name

lastname should be the user's inputted last name

pretendwebsite.extension can be any website name you wish

 

This Week's Challenges:

 

So, that's it for now. Before I go, I would like to leave you with a few practice coding challenges:

 

The following challenges are borrowed from "Practical C Programming" by Steve Oulline. I feel these are vary practical and challenging uses of decision making, and couldn't think of anything better sad.png (and I wanted you to have a lot more practice at this point) (By the way, they are actually easier to solve in ruby than in C)

 

1. Write a program that takes a student's grade as a number/percentage, and prints out their letter grade.

Grade Table
Letter Grade Numeric Grade
F 0-60
D 61-70
C 71-80
B 81-90
A 91-100

(HINT: Remember how the interpreter executes an if statement)

 

2. Modify the previous program, to also display a + or - after the letter. The +/- modifier is based on the last digit of the numeric grade:

Grade Modifications
Last Digit Modifier
1-3 -
4-7 <blank>
8-0 +

ex. 81 = B-, 94 = A, 68 = D+. Remember, and F is only an F, you cannot get an F-

(HINT: Remember the modulus operator? `%` ?

EVEN BIGGER HINT:

 

irb(main):001 > 1 % 10
=> 1
irb(main):002 > 11 % 10
=> 1
irb(main):003 > 21 % 10
=> 1

 

 

3. Given an amount of money (less than $1.00), compute the number of quarters, dimes, nickels, and pennies needed.

 

4. A leap year is any year divisible by 4, unless the year is divisible by 100, but not 400. Write a program to tell if a year is a leap year.

 

5. Write a program that, given the number of hours an employee worked and the hourly wage, computes the employee's weekly pay. Count any hours over 40 as overtime at time and a half.

 

6. EXTRA HOMEWORK CHALLENGE:

If the previous challenges did not satisfy you, here's the REAL challenge. For this challenge, you will need to go out and learn about Ruby's "Range" data type. Do not worry, I will teach you about this data type in the future.

http://www.ruby-doc.....9.3/Range.html

 

Now, the challenge will be to redo the first 2 challenges, using the Range class.

HINTS

 

To create a Range data type, the shorthand is:

variable = 0..5
variable = 0...5

0 is the (minimum) starting number

5 is the (maximum) ending number

.. means 0 to 5 inclusive (0, 1, 2, 3, 4, 5)

... means 0 to 5 exclusive (0, 1, 2, 3, 4)

To solve this new challenge, you will need to find out how Ranges behave within a case statement (HINT: look up the === method)

 

 

Share this post


Link to post
Share on other sites

No, actually I didn't know where the challenge was. sweatdrop.gif I probaby seen it, but know how blind cool.png I am, I probabl missed it.

Edited by bigace

Share this post


Link to post
Share on other sites
Programming Challenge Solutions


Alright, some of these are kind of late, but before I release the next lesson on looping, I'd like to go over the solutions to the challenges I presented to you.

These challenges could be tackled in MANY different ways, my solutions are just one way to do it -- the key to really knowing if you solved the problem is a major concept in programming: Does the ACTUAL output MATCH the EXPECTED results. In other words, if the program does what it is supposed to -- it works.


Coding Challenges (A):

1. Write a script, that takes two numbers from the user, and performs some kind of mathematic operation on them.

So this is simple enough, our input will be two numbers (from the user), and the output will be a mathematic operation.
I gave you a bit of freedom to work with (choose any operation), but I will show you all!

The code:

# First let's prompt the user to enter a number:
print("Enter a number: ")
first_num = gets.to_i # Get input, than convert to a number. to_f would work as well
# Prompt for another number
print("Enter another number: ")
second_num = gets.to_i
# Now, lets perform some operations!
puts("#{first_num} + #{second_num} = #{first_num + second_num}") # Addition
puts("#{first_num} - #{second_num} = #{first_num - second_num}") # Subtraction
puts("#{first_num} * #{second_num} = #{first_num * second_num}") # Multiplication
# This will no necessarily be precise, remember the issue with dividing integers?
puts("#{first_num} / #{second_num} = #{first_num / second_num}") # Division
puts("#{first_num} % #{second_num} = #{first_num % second_num}") # Modulus
puts("#{first_num} ** #{second_num} = #{first_num ** second_num}") # Exponents



The output:

Enter a number: 10
Enter another number: 5
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
10 / 5 = 2
10 % 5 = 0
10 ** 5 = 100000



2. Write a script, that takes the users first and last name, and creates an e-mail address for them, in the format:
lastname.firstname@pretendwebsite.extension
firstname should be the user's inputted first name
lastname should be the user's inputted last name
pretendwebsite.extension can be any website name you wish

So, in this case, we create a fake email for the user. If you wanted to, the email carrier could have been user inputted as well. The main purpose of this excercise was to practice using strings. There are many ways to do this, but I will use string math to do it.
So, we need to get the users first name/last name, then build a string which will be their e-mail, and tell the user what it is:

The code:

# Prompt user for name
print("Enter your first name: ")
first_name = gets.strip # we use the strip method, in order to remove any trailing/leading whitespace
print("Enter your last name: ")
last_name = gets.strip
# Build email address
email = last_name + "." + first_name + "@gmail.com"
puts("Your email is: #{email}")



The output:

Enter your first name: kellen
Enter your last name: holmes
Your email is: holmes.kellen@gmail.com



Coding Challenges (B)

I did not include the solution to the extra challenge. The reason I did not include this solution, is as I would like to teach you about ranges in a later lesson, in more detail. The challenge was more to give you practice learning about other objects ruby has to offer, through the documentation on your own. If you did attempt it, and wanted to know the solution -- shoot me a message


1. Write a program that takes a student's grade as a number/percentage, and prints out their letter grade.
Grade Table
Letter Grade Numeric Grade
F 0-60
D 61-70
C 71-80
B 81-90
A 91-100

Ah, the dreaded school grades. I always hated bringing home report cards. *Ahem* anyways, let's make a program that figures out the letter grade based on the percentage.
So first, we need the input - the studen't grade as a percentage.

# Prompt user:
print("Enter your current grade percent: ")
grade_num = gets.to_i[code]
Now we have the users grade. How do we tell them their letter?
Well, based on the requirements, if the number is between 0 and 60, its an F. From 61 to 70, its a D, etc.
We could start off, if number is less than or equal to 60, its an F. Then, we should work our way up; using elsif. However, when we move past the 'F', we need to add and extra test, to make sure the the number isn't part of the next letter.
elsif grade_num > 60 and grade_num <= 70 for D... But, if we get past the if grade_num <= 60, we already know the number is greater than 60 right (other wise, it would've skipped the rest of the if statement), therefore, we only really need to check that the number is <= the max of the letter.
[code]if grade_num <= 60
 grade_char = "F"
elsif grade_num <= 70
 grade_char = "D"
elsif grade_num <= 80
 grade_char = "C"
elsif grade_num <= 90
 grade_char = "B"
elsif grade_num <= 100
 grade_char = "A"
else
 # Here is only executed if grade_num > 100
 # note: string.to_i will convert non-numeric characters to 0
 puts("Are you telling the truth? Did you really get #{grade_num}?")
end
# Here is an extra test, if no grade_char has been assigned, don't print anything.
# An un-initialized variable will ALWAYS return `nil`
# Remember, nil/false are considered FALSE - everything else is TRUE
if grade_char # grade_char has a value
 puts("You got an #{grade_char}!")
end



The output:

Enter your current grade percent: 50
You got an F!

Enter your current grade percent: 60
You got an F!

Enter your current grade percent: 65
You got an D!

Enter your current grade percent: 85
You got an B!

Enter your current grade percent: 100
You got an A!

Enter your current grade percent: 250
Are you telling the truth? Did you really get 250?



2. Modify the previous program, to also display a + or - after the letter. The +/- modifier is based on the last digit of the numeric grade:

Grade Modifications
Last Digit Modifier
1-3 -
4-7 <blank>
8-0 +

ex. 81 = B-, 94 = A, 68 = D+. Remember, and F is only an F, you cannot get an F-

So, this is just a modification of the previous program. Luckily, we can easily squeeze in a test, to see what sign they get with their letter! Once we have their letter (and it's not nil), then we should compute the sign.
Let's look at the last if:

if grade_char # grade_char has a value
 puts("You got an #{grade_char}!")
end


So, we should put our computation in this if statement. But how do we figure out what the last digit is? There are a couple approaches, but let's use my favourite (sorry, I am biased) -- modulus.
In this case, we are working with ranges of multiples of 10 - 61 to 70, 71 to 80 etc. And our largest range is from 0 to 100.
So, in the case where a multiple of 10 is divided by 10, the remainder is 0. Everything in between, the remainder would be 1 to 9...which would be our last digit!
Modulus does exactly what we need. It gets the remainder of the division, rather than the result. Let's see:
71 % 10 = 1
72 % 10 = 2
...
79 % 10 = 9
Perfect. Now let's apply it!

if grade_char # grade_char has a value
 if grade_num > 60 # not an F
   # Now let's check the last digit
   last_digit = grade_num % 10
   if last_digit >= 1 and last_digit <= 3 # Check if between 1 and 3 inclusive
     grade_char += "-"
   elsif last_digit >= 8 or last_digit == 0 # Check if greater than 8, or equal to 0
     grade_char += "+"
   end
 end
 puts("You got an #{grade_char}!")
end



the output:

Enter your current grade percent: 75
You got an C!

Enter your current grade percent: 78
You got an C+!

Enter your current grade percent: 81
You got an B-!



3. Given an amount of money (less than $1.00), compute the number of quarters, dimes, nickels, and pennies needed.

Alright, next problem. This time, we want to find out the number of specific coins that make up less than $1.00
I actually just realized, that this may not necessarily be the same division of money as where you live... D'Oh.
I also just realized that this isn't really an exercise for if statements. It could be...but that would be way over complicating it (in my opinion)... Double d'oh.

Anyways, a quarter is $0.25, a dime is $0.10, a nickel is $0.05 and a penny is $0.01.

Now, while we could work with the float type numeric - it will be much cleaner if we just use integers to represent the number of cents (afterall, in this context we cannot have half a penny)

How do we determine what coins make up an amount of money? Well, let's try out an algorithm here.
Let's say we have 99 cents.
First, how many quarters?
99 / 25 = 3 r 24 > 3 quarters
Now we have 24 cents, how many dimes?
24 / 10 = 2 r 4 > 2 dimes
Now we have 4 cents, how many nickels?
4 / 5 = 0 r 4 > 0 nickels
We still have 4 cents, how many pennies?
Well 4 of course! any number divided by 1 is that number.

So there's our algorithm

Take total number of cents,
divide by the largest coin,
use the quotient for the number of coins,
use the remainder for the new total number of cents.
Repeat for each type of coin.

Now, the code:

print("Enter an amount of money, in cents: ")
total_cents = gets.to_i # No half-a-penny here!
# Get number of quarters:
quarters = total_cents / 25
pennies = total_cents % 25 # Modulus for remainder!
# Get number of dimes:
dimes = pennies / 10
pennies %= 10
# Get number of nickels:
nickels = pennies / 5
pennies %= 5
# Remaining is number of pennies
# no further computation is necessary
puts("To make #{total_cents}, you need:",
    "#{quarters} quarters",
    "#{dimes} dimes",
    "#{nickels} nickels",
    "#{pennies} pennies")



Et voila! (Pardon my french)
Anyone catch that terrible pun at the end ;) (I swear it was accidental!)

I could have just use total_cents %= value, but I wanted to keep the original input to display to the user.
I named the remainder variable "pennies" because I knew it would be eventually used as the remaining number of pennies.

The output:

Enter an amount of money, in cents: 99
To make 99, you need:
3 quarters
2 dimes
0 nickels
4 pennies



Cool, it worked! That was the amount of coins I had predicted for 99 cents!



4. A leap year is any year divisible by 4, unless the year is divisible by 100, but not 400. Write a program to tell if a year is a leap year.

Ugh leap years. I never really got them to be honest...oh well, if we know how to figure it out - we just need to tell the computer how. The rest, is rocket science...err computer science.
So, lets work this out
if (year can be divided by 4) and not(divided by 100 and not 400), its a leap year!
Okay, that's kind of confusing. Let's try a different approach:

year can be divided by 4?
No: not a leap year
Yes:
can that year be divided by 100?
No: is a leap year
Yes:
can that year be divided by 400?
No: is a leap year
Yes: not a leap year

That's a bit easier to see. So, in case you haven't noticed modulus works here again (I told you I love modulus!!! :D). If a number can be divided evenly by another number, the remainder will always be 0.
The code:

print("Enter a year: ")
year = gets.to_i
if year % 4 == 0 # Year is divisible by 4
 if year % 100 == 0 # Year is divisible by 100
   if year % 400 == 0 # Year is divisible by 400
     leap = true
   end
 else
   leap = true
 end
end
if leap
 puts("#{year} is a leap year!")
else
 puts("#{year} is not a leap year!")
end


It works...but it's kinda messy. Really, all those nested if statements could be combined into one boolean expression:

print("Enter a year: ")
year = gets.to_i
if (year % 4 == 0) and not (year % 100 == 0 and year % 400 != 0)
 puts("#{year} is a leap year!")
else
 puts("#{year} is not a leap year!")
end


MUCH neater. Well, I think so anyways.
The output:

Enter a year: 2011
2011 is not a leap year!

Enter a year: 2012
2012 is a leap year!


Next year is a leap year??
*googles*
Hey! according to this: http://www.timeanddate.com/date/leap-day.html our program worked! Sweet :D



5. Write a program that, given the number of hours an employee worked and the hourly wage, computes the employee's weekly pay. Count any hours over 40 as overtime at time and a half.

So, you may have seen a bit of a pattern on how I solve these problems...I determine what the output should be, what input I use to get that output -- then with those bits of information, I determine how to turn that input into the desired output.
This process is what some may call an "IPO" chart. Input, Processing, Ouput. So let's try filling it in.
Input -
Employee's hourly wage, and the hours worked

Processing -
weekly wage =
hours worked (upto 40) times hourly wage
PLUS
hours worked (over 40) times 1.5 times hourly wage

Output -
Employee's weekly wage

The code:

print("Enter the hourly wage: ")
hourly_wage = gets.to_f # This could have a cents portion!
print("Enter the total hours worked: ")
hours_worked = gets.to_f # We could work for half an hour!
# Let's determine any overtime!
overtime = hours_worked - 40
if overtime > 0
 total_wage = (40 * hourly_wage) + (overtime * 1.5 * hourly_wage)
else
 total_wage = hours_worked * hourly_wage
end
puts("For #{hours_worked} hours at $#{hourly_wage} per hour:",
    "Total pay = $#{total_wage}")



The output:

Enter the hourly wage: 12.50
Enter the total hours worked: 55
For 55.0 hours at $12.5 per hour:
Total pay = $781.25

Enter the hourly wage: 12.50
Enter the total hours worked: 40
For 40.0 hours at $12.5 per hour:
Total pay = $500.0


So...did it work? Well, I guess we'll have to work it out in hour head.
12.50 * 40 = 500.00
Okay, so that's fine, how about the overtime?
12.50 * (15 * 1.5) = 281.25

500 + 281.25 = 781.25!

Aha it worked! :D (as if I didn't test these before bringing you the solutions teehee :3)



And there you have it. Those are the solutions for each coding challenge thus far, save the extra challenges using "Ranges."
I know right now, these little programs don't seem very practical (or maybe you do), but what I really want you to get out of these challenges, is learning how to take an english word problem, and turn it into instructions that a computer can follow.
Computers are inherently stupid, and must be told every little detail along the way - as it can only understand simple instructions.

To get you thinking about how computers process instructions, I have a little exercise I'd love for you to try out. This doesn't involve any code writing - all I want from you, is some instructions on HOW to make a peanut butter sandwich. Yup, that's right - give me some instructions on how to make a peanut butter sandwich.</blank>

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Polraudio
      Terrain Tags



      By: Polraudio


       
      Welcome to the Terrain Tag Tutorial. This tutorial is to teach you all the useful things you can do with the Terrain Tags. Few things I will be covering in this tutorial is healing tiles, damaging tiles.
       
       
      STEP 1: Tileset Editor
      First lets set some terrain tags in the tileset editor. For this demonstration we will be using the grass and the rocks.
      Open your database and go to tilesets and the Grassland tileset then click on Terrain Tag.
      Set the Rocks for 1 and the Grass for 2 like the example below.
       

       
      We are going to use rocks to damage the player and the grass to heal the player.
      Hit ok on the database to ensure the tags are set.
      The next step will be to make the event to track what terrain tag the player is currently on and heal or damage the player.
       
       
      STEP 2: The Event
      Make a new event without a graphic and set the Trigger to Parallel Process.
      Create a control variables event and name it something like Terrain Tag. Set the Operand to Character, Player's, Terrain Tag. So it should look like this.
       

       
      Now we want to setup how the rocks and grass interact with the player. Create a Conditional Branch right under the Variable you just made. Set it to Variable and the variable you just made. Set it to Equal to and Constant 1. So it should look like this.
       

       
      If you remember from the tileset we set the terrain tag of rocks to 1. When the player is on the rocks the terrain tag will be set to 1 and when the player is over the grass it will be set to 2.
      Now we will make the part where it hurts the player when they are on the rocks. Note: i will hurt the player as long as they are on the rocks. Even when not moving.
       
      Right in the conditional branch above else we will want to make it so it hurts the player. Go to page 3 and Change HP .... Here you can set it to harm or heal the player but in this case we want to hurt the whole party so click on Decrease then set the operand to constant and whatever number you want. i will be using 50 for this example. So it should look like this.
       

       
      Now you can play test and enjoy.
       
      But wait... Something's wrong my party dies almost instantly. Why is that?
       
      The problem is because we forgot to set a wait time after each time the players party gets hurt so they get hurt 40 times a second because rpg maker xp runs at 40 frames a second. To fix this we will need to add a wait after the party gets hurt.
       
      After the change hp command add a wait for 40 frames. Why 40 frames? Cause rpg maker xp runs at 40 frames a second so they will only be getting hurt every second instead of 40 times a second.
       
      Now as you noticed after play testing again everything's working right except you have no clue when your getting hurt. To fix that add a screen flash right above the wait command. On the 2nd page click Screen Flash .... Set the sliders for green and blue to 0 while keeping red at 255 and strength at 255. Set the time for 2 frames. Any lower than 2 frames and it will not show sometimes cause rpg maker xp is not a constant 40 frames per second and sometimes is 39 frames per second so it will be skipped sometimes unless you have it set to 2 frames. So it should look like this.
       

       
      Now that we got the screen flashing we also need to make a noise when the party gets hit. It doesn't matter where you place it as long as its before the wait command. Make a play se ... command and set it for whatever sound you want.
       
      After everything's done your event should look like this.
       

       
      Congratulations you now know how to make a hurting and a healing event using terrain tags without using tons of events to get the same effect.
       
      Now your saying to yourself "But... we didn't go over healing the player!" but we did go over healing the player. It may not seem like we did but we did. To make it heal is the same way as making it hurt except we use change the variable, set it to increase party HP, change the screen flash to blue and change the sound. I will show you how to add healing in the pic below.
       

       
      Download: http://www.gdunlimit...in-tags-521.zip
       
      Hope you enjoyed this little tutorial and as always. Thanks for reading :D.
      If you want to request an event tutorial for me to do with rpg maker(any version) just shoot me a private message.
       
      Note: This tutorial is a GDU exclusive and shouldn't be posted anywhere else!
    • By Luz
      I'm not quite sure where to put this so if this is in the wrong place, please move it.
       
      Anyway, since I haven't been able to use RMXP I've been making some characters. As for facesets, I'm usually fine with using face maker but for main characters I like to edit the face sets using paint.net (which can be downloaded for free from here: http://www.getpaint.net/download.html ) to give them more personality and set them apart from the NPC's. The way I edit them doesn't take much skill either.
       
      So, I thought I'd give a tutorial on how I go about editing a character with paint.net.
       
      How to edit eyes:
       
       
       
       
      How to edit eyes onto a face set:
       
      Forward Facing Face:
       
       
      Face that's at an angle:
       
       
      Face Profile:
       
       
      I'll add a tutorial on editing hair and skin soon.
    • By Calvinchun
      A condition tutorial i made for scotty.. There is no screenshot for a moment.. Sorry
    • By kellessdee
      Lesson 7: Flow Control - Looping  
      Ah, looping. Loops, in my opinion, are what separate a "script" from a "program." So, here comes the obligatory...
       
      What is a loop?
       
      Think of the word loop, in the terms of a song loop -- we say a song is looping when it repeats, once it reaches the end.
      A loop in programming, is generally a block of code that is repeated any arbitrary number of times.
      For example, at its very essence, all a video game is, is a huge loop continuously taking input and reacting based on the input and the game's current state, until the player quits the game.
      So how does it work? Well, in ruby, there are actually many ways to "loop" or iterate -- as it's commonly referred to as -- let's start with the while loop.
      while condition do # Loop block end The `do` portion of the while - loop syntax is optional --
      while condition # Loop block end works as well.
       
      So, "while" the "condition" evaluates to true (anything except false or nil), execute block. The while loop will continuously repeat until condition is false or nil.
      Be Careful -- Endless loops. Endless loops refer to a loop that never ends. This happens because the condition never becomes false. If you get stuck in an endless loop, usually CTRL + C will break the loop.
      As a programmer, we need to have some kind of control over how long a program repeats its statements.
      One common method of loop control, is through use of a counter:
      i = 0 while i < 5 puts "Hello!" i += 1 end the output would be:
      Hello! Hello! Hello! Hello! Hello! How did this happen?
      The interpreter sets a variable, `i`, to 0. It then enters the loop:
      Is i less than 5? yes, display "Hello". i is now 1
      Is i less than 5? yes, display "Hello". i is now 2
      Is i less than 5? yes, display "Hello". i is now 3
      Is i less than 5? yes, display "Hello". i is now 4
      Is i less than 5? yes, display "Hello". i is now 5
      Is i less than 5? no, i is equal to 5, stop looping.
      We can use a variable as a counter, and use an arbitrary maximum number of iterations and then by counting the number of iterations we can determine when to stop executing the block.
      Here's a better example:
      "In mathematics, the factorial of a non-negative integer n, denoted by n!, is the product of all positive integers less than or equal to n. For example, 5! = 5 x 4 x 3 x 2 x 1 = 120 " (http://en.wikipedia.org/wiki/Factorial) (Yea, I was lazy and they had a better explanation......)
      Er, let's translate this to our code!
      Let's say we want a program that takes a number from the user, and calculates that number's factorial.
      # Calculate the factorial print("Enter a number: ") number = gets.to_i # Get first number factorial = number print("#{number}!\n#{number}") while number > 1 # move to next number number -= 1 # get product of n..n-1 factorial *= number print(" * #{number} ") end puts("= #{factorial}") Test:
      Enter a number: 5 5! 5 * 4 * 3 * 2 * 1 = 120 Looks good! As you can see, counters can decrement as well. How you do it, will mostly depend on the situation (remember, you don't always have to increment/decrement by 1, either.)
       
      Of course, condition can be ANY expression, and is also used to loop based on a program's "current state."
      Let's go back to the guessing game we created. Wouldn't it be much better if we let the user keep guessing until they quit or guess the number?
      # Set a number to guess number = 10 # define the current "state" game_over = false while !game_over # Prompt the user to guess what number it is: print("I am thinking of a number. What is it? (Type q to quit) ") # Get the guess guess = gets.strip if guess.upcase == "Q" puts("Goodbye!") # Change current "state" game_over = true elsif guess.to_i < number puts("Too low!") elsif guess.to_i > number puts("Too high!") elsif guess.to_i == number puts("Wow! You got it!") # Won the game, change state game_over = true end end
       
      Now, our simple guessing game is actually a game! Well, mostly. We'd want to randomize the number to make it more of a game, but I will go over random number generation another time. For now, it does what we need. The game will now continuously prompt the user until the variable game_over is true. Notice that, we could have instead made a variable, say, game_playing, and set it to true. Then, while game_playing is true, prompt the user -- either way would work.
       
      Before we finish, I'd like to introduce to another form of looping, and some more loop control methods.
      The next loop you will learn about, is called the "for" loop. The for loop can be considered a special type of iterator, but for now, just think of it as a loop with very specific bounds. (I will go over more about for and iterators, in a later lesson)
       
      Let's go back to the factorial program we made. If you notice, a factorial always loops a very specific number of times. The number of times it loops may be dependant on the input, but it will always be a set value. This is where for loops come in.
      for i in 0..5 puts i end produces:
      0 1 2 3 4 5 So how does this work?
      Well, the syntax is:
      for variable in set # Block end For loops, will iterate through each item in a "set" (for now, we will only discuss ranges), and store the current object in the set, in the variable 'i'.
      So what happened in the above loop? Well, in Ruby, a Range object (denoted by min..max or min...max), is actually a representation of a set of numbers from min to max.
      Be careful with ranges, 0..5 means 0 to 5 inclusive, while 0...5 means 0 to 5 exclusive:0..5 => 0, 1, 2, 3, 4, 5
      0...5 => 0, 1, 2, 3, 4
      Then, based on this analysis, i is first set to 0 (first item in the set), then we print i in the block. When we move to the next item/iteration, i is then set to 1, and we print it. The loop continues this pattern, until we reach the last item, then when there are no items left to be stored in i, we break out of the loop.Why is this useful? Well, let's put this to more practical use. Let's go back to the factorial program -- like I promised.
      # Calculate the factorial print("Enter a number: ") number = gets.to_i factorial = number for i in 1...number #
      factorial *= i
      end
      puts("#{number}! = #{factorial}")[/code]Note, that unfortunately, ranges don't work in reverse. For example, 5...1 is not 5,4,3,2. It will not work. There are ways to reverse ranges, but that would be treading into an area I want to save for another lesson.
       
      Ahem, any who, carrying on... (I apologize for a larger amount of "later..."s, I would like, for this lesson, to focus on the concept of loops, without worrying too much about extra technical details, at least not yet)
       
      Another good use of for loops, is for generating rows and columns of display. Say, we want to generate a pattern like this:
      *************** *************** We could simply hard code a couple puts, and it would work...but what if we want to be able to draw any size?
      # Get rows and columns print("Enter number of rows: ") rows = gets.to_i print("Enter number of columns: ") cols = gets.to_i # Display pattern for i in 0...rows for j in 0...cols print("*") end print("\n") end could produce:
      Enter number of rows: 2 Enter number of columns: 15 *************** *************** It may seem silly, but if you can grasp this concept of nested for loops, you will find it VERY useful later on. But what exactly happens?
       
      So, rows == 2 and cols == 15.
       
      We enter the first loop at i = 0, and the second loop at j = 0.
       
      Then j will become 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 (remember, 0...cols is 0 to cols exclusive) and on each iteration, the interpreter will print a `*` on a single line.
       
      When we break out of the nested loop, ruby prints a \n (newline character), then i becomes 1.
       
      We then reach the nested loop again, and it does the exact same thing, printing 15 `*`s on the next line (notice, 0-14 inclusive or 0-15 exclusive, is 15 different numbers).
       
      We break, print a new line, i runs out of numbers (0...rows exclusive => 0, 1) and therefore break from the outerloop, and stop looping altogether.
       
      This concept will become very useful, when looping through grid-based data structures. (A single for loop, if you noticed, is meant/really good at looping through list-based data structures).
       
      Finally, before I finish loops, I would like to teach you a couple useful control statements for loops -- break, and next.
       

      loop do # Prompt the user to guess what number it is: print("I am thinking of a number. What is it? (Type q to quit) ") # Get the guess guess = gets.strip if guess.upcase == "Q" puts("Goodbye!") break end guess = guess.to_i if guess < number puts("Too low!") next end if guess > number puts("Too high!") next end if guess == number puts("Wow! You got it!") break end end So, this is a slightly modified version of our guessing game. If you try it out, you might notice it works exactly the same! Let's analyze what I changed.
      Firstly, the loop is no longer a while loop...
      loop do # Code end This is just another form of loop that ruby has, that represents an infinite loop -- when the interpreter finds this, it will continuously loop the block of code. (This is useful for if you need to loop, but not based on a certain state/condition).
       
      Now, when a guess is made, if the guess is 'Q' or the right number, the loop will "break." break is a keyword in ruby, and is also a special function. It will "break out" of the current, immediate loop, and stop looping (Note, if you use break in a nested loop, it will only break out of the loop it is called from, not all loops).
       
      We also, use `next` if the number is incorrect. next is like break (a special function for controlling loops), but what it does, is tell the ruby interpreter to skip to the "next" iteration, meaning next will skip the rest of the block of code, and restart the loop. If used in a for loop, this also means i becomes the next item in the list.
       
      Well, that's all for today's lesson! I apologize for taking so long this time. Things are getting busy for me again, and I may take a little bit longer to finish each lesson. I will try my best, however, to keep the lessons coming once a week!
       
      Now, I will leave you with a few more challenges:
       
      1. Make a simple "menu" script, that will continuously prompt the user to enter a numeric selection, and display a different message based on the input. If the user types "q" or "Q" the menu should stop.
       
      2. Write a script that will generate this output:
      * ** *** **** ***** ****** ******* ******** ********* **********
      or, if you're feeling really creative, try making it look like this:
      * *** ***** ******* ********* ***********
      (Kinda late for Christmas isn't it????)
       
      3. The formula for converting degrees celsius to degrees fahrenheit is:
      F = C * 9 / 5 + 32
      Write a script that will display a Celsius -> Fahrenheit conversion table
      from -10 celsius to 40 celsius.
      i.e
      -10C = 14F -9C = 15.8F -8C = 17.6F -7C = 19.4F ...etc.
×
×
  • Create New...