Ruby programming Workshop
4 June 2016
Basics
Ruby is an interpreted programming language.
We write a program, and execute it from its source. There is no separate compilation step.
Basics
Create a file called hello.rb
Add the following code:
puts "Hello world"
ruby hello.rb
Save it,
Execute it from the command line:
Basics
Basics
## Example:
a = 2
b = 3
c = a + b
puts c
Basics
We use puts to print values to the standard output.
## Example:
a = "Hello Abhishek"
puts a
puts a, "How are you?"
Basics
Branching is done using the if statement.
if <condition>
# do something
end
If the condition gives a true value, the code within the if block is executed. There is also an else:
if <condition>
# do this
else
# do that
end
Basics
## Example:
a = 2
if a > 0
puts "Positive"
else
puts "Negative"
end
Basics
To group code that can be executed later, we use methods
A method can be defined with def keyword.
Methods are invoked from their names - placing parenthesis is optional.
The result of the last line is returned from a method
Basics
## Example:
def hello(a)
puts a
end
hello a
hello(a) # same
Basics
Basics
- Type irb in the shell
- It will show a prompt like this:
irb(main):001:0>
- Now type all the above examples line by line on it:
Basics
## In IRB:
puts "hello world"
a = 2
b = 3
c = a + b
puts c
def hello
puts "hello world"
end
hello
Loops
Loops are used when we need to execute something again and again.
Looping in Ruby is very different from C or Javascript.
We mainly use iterators
# Example:
5.times{ puts "hello world" }
The times method here is an iterator, and the code between the curly braces is a block. We are actually passing the block to the iterator.
Loops
The each iterator is available on array like objects.
It iterates through the array, and executes the block for each element.
In other words, the code between the curly-braces is executed again and again.
The above code loops through the array arr, and prints squares of all the numbers. And each time, it maintains the iterated value in the variable i.
The variable i here is the so called 'block argument'
arr = [1, 2, 3, 4]
arr.each{ |i|
square = i ** 2
puts square
}
Loops
loop gives us an infinite loop.
We'll have to set-up break and increments on our own.
The following is an equivalent of a for loop in C :
c = 0
loop {
puts "hello"
c += 1 # Increament like this. There's no ++ in Ruby
break if c >= 10 # Single line if is allowed
}
Loops
loop is more useful when we don't know the size of the input.
loop{
input = gets
input = input.chomp # Used to remote the \n at last
break if z == ""
puts input
}
Loops
Similar to the while loop in c:
c = 0
while c < 10
puts "hello"
c += 1
end
Loops
Range is a data structure similar to Array.
We can express a continuous list neatly using a range.
1..5 # Range of number 1 to 5: 1,2,3,4,5
'a'..'z' # Range of characters a to z
(1..5).to_a # => [1,2,3,4,5]
Ranges can be converted to arrays using `to_a` method
Both the starting and ending values are included in a range
File-IO
ARGV is an array that holds the arguments passed while the ruby program is invoked from command line.
# Example: sample.rb
puts ARGV
ruby sample.rb hello 12 #prints hello 12
Execute:
The program name and ruby are not counted
File-IO
Read as a big string:
str = File.read("sample")
Read as lines (most useful):
# lines = array of lines, separated by \n
lines = File.readlines("sample")
lines.each do |line|
## My code
end
File-IO
Open the file and read line by line:
(use when files are big)
File.open("sample", "r") do |f|
f.each_line do |line|
## My code
end
end
File-IO
ARGF is the file descriptor of the standard input.
To read from standard input, we can use:
This will block the program until STDIN comes up with something
ARGF.read
Array-String
Strings are independent data structures in Ruby - not like C where a string is treated as a list of characters.
Several methods for manipulations are provided by the standard library.
Documentation: String class
str = "abc"
str = 'xyz' # both same
Array-String
Splitting strings:
Using split method, we get an array of parts:
We can also get a list of all characters:
str = "/home/user/code/sample.rb"
str.split("/") #=> ["", "home", "user", "code", "sample.rb"]
str = "abc"
str.chars #=> ["a", "b", "c"]
Array-String
Joining/concatenating strings:
Using the join method, we can join an array of using a separator:
We can also concatenate using +
arr = ["", "home", "user", "code", "sample.rb"]
arr.join("/") #=> "/home/user/code/sample.rb"
str1 = "Hello"
str2 = "World"
str3 = str1 + str2 #=> "HelloWorld"
Array-String
We can insert a string within another one using interpolation:
We can interpolate numbers and other types of objects too:
name = "John"
str = "Hello #{name}" #=> "Hello John"
puts str
num = 3
str = "There were #{num} errors" #=> "There were 3 errors"
puts str
Array-String
We can read a string as if it were an array of characters:
str = "abcdef"
str[0] # => "a"
str[1] # => "b"
str[1..3] # => "bcd"
str[0..-2] # => "abcde" # negative indexes count backwards
Array-String
Other useful methods
"abc".length #=> 3 # length
"abc".upcase #=> "ABC" # upcase
"ABC".downcase #=> "abc" # downcase
"abc".capitalize #=> "Abc" # capitalize
"abc".reverse #=> "cba" # reverse
"abc\n".chomp #=> "abc" # chomp: removes \n from last if present
"abc" == "abc" #=> true # comparison
"hello world".gsub(" ", "-") #=> "hello-world" #Substitution
Array-String
Note that most of these methods don't perform in-place changes.
The original string is left unchanged, and a new string is returned with the changes.
Array-String
Array is a collection of objects. Objects can be related or unrelated.
Arrays are ordered and indexed.
arr = [1, "2", "hello", {"key" => "value"}, 1..5 ] # a valid array
Array-String
Adding to array:
Using <<
arr = [1,2,3]
arr << 4 #=> [1, 2, 3, 4]
Using push
arr = [1,2,3]
arr.push(4) #=> [1, 2, 3, 4]
Array-String
Accessing from Array:
Using index :
arr = [1, 2, 3, 4]
arr[0] #=> 1
arr[-1] #=> 4
arr[1..2] #=> [2, 3]
arr[100] #=> nil
Get the first few:
arr.take(2) #=> [1, 2]
Array-String
We can use the index method to get the index of an element
Or use detect method to get an element that matches a criteria
arr = [1, 2, 3, 4]
arr.index(3) # => 1
arr.detect{ |x| x > 3 } # => 4
arr.bsearch{ |x| x == 2 } # => 2 # uses binary search
Array-String
select method gets a sub array based on some condition:
arr = [10, 20, 30, 40]
arr.select{ |x| x > 25 } #=> [30, 40]
Array-String
Sorting is available within the library.
Implements the quick-sort algorithm, which generally quite efficient.
arr = [3, 10, 52, 0]
arr.sort # [0, 3, 10, 52] # gives sorted array
Using sort_by we can also sort on a property instead of the value:
arr = [-2, 10, -33, 20]
arr.sort_by{|x| x.abs } # [2, 10, 20, 33]
Array-String
If we need to transform the array to a different list using same logic on all elements, we can use `map`. For example -
# We can get squares of all elements:
arr = [1, 2, 3, 4]
arr.map{ |x| x**2 } #=> [1, 4, 9, 16]
# Or increament every value by 1
arr = [1, 2, 3, 4]
arr.map{ |x| x+1 } #=> [2, 5, 10, 17]
# Or we can convert string list to integers
arr = ['20', '30', '44']
arr.map{ |x| x.to_i } #=> [20, 30, 44] # to_i: string to integer
Array-String
#size:
[1, 2, 3].size #=> 3
#reverse:
[1, 2, 3].reverse #=> [3, 2, 1]
#join:
[1, 2, 3].join("-") #=> "1-2-3"
#max:
[1, 2, 3].max #=> 3
#uniq:
[1, 1, 2, 3].uniq #=> [1, 2, 3]
#compact:
[1, nil, 2].compact #=> [1, 2]
Other useful methods
Conclusion
Conclusion
O(n^2) example:
# Hypothetical: O(n^2)
lines = File.readlines(ARGV[0])
arr = lines.map{ |line| line.chomp.chars } # Its a square matrix
n = arr.size
n1 = n - 1
(0..n1).each do |i|
(0..n1).each do |j|
x = arr[i][j]
puts "Its: (#{i},#{j}) #{x}"
end
end
Conclusion
O(n^2) example:
# Selection sort: O(n^2)
arr = File.read(ARGV[0]).split(",")
n = arr.size
n.times do |start|
min = start
start.upto(n-1) do |i|
min = i if arr[i] < arr[min]
end
arr[start], arr[min] = arr[min], arr[start] # swap
end
Conclusion
Conclusion
Conclusion