├── README.md ├── Wagon-0 ├── 01. Submit your code │ ├── README.md │ └── github_champ.rb ├── 02. IRB-basics │ ├── README.md │ └── irb_basics.txt ├── 03. Experiment methods │ ├── OO-experiments.txt │ └── README.md ├── 04. Age in days │ ├── README.md │ └── age_in_days.rb ├── 05. What's your name ? │ ├── README.md │ └── introduce_yourself.rb ├── 06. Stupid coaching │ ├── README.md │ └── stupid_coaching.rb └── 07. Code-style Gym │ ├── README.md │ └── codestyle_gym.rb ├── Wagon-1 ├── 01. Simple looping │ ├── README.md │ └── simple_looping.rb ├── 02. Sorting the wagon │ ├── README.md │ └── wagon_sort.rb ├── 03. Beer song │ ├── README.md │ └── beer_song.rb ├── 04. Cookbook ToC │ ├── README.md │ └── cookbook_toc.rb ├── 05. Roman numerals │ ├── README.md │ └── roman_numerals.rb ├── 06. Shuffle │ ├── README.md │ └── shuffle.rb ├── 07. Enumerable │ ├── README.md │ └── enumerable.rb ├── 08. Destructive methods ! │ ├── README.md │ └── destructive_methods.rb ├── 09. Debug Gym │ ├── README.md │ └── bugged_concatenate.rb └── 10. Refactor Gym │ ├── README.md │ └── chain_unchain.rb ├── Wagon-2 ├── 01. Modeling with Hash │ └── README.md ├── 02. On symbols │ └── README.md ├── 03. Anagrams │ ├── README.md │ └── anagrams.rb ├── 04. Combine anagrams │ ├── README.md │ └── group_anagrams.rb ├── 05. Louchebem │ ├── README.md │ └── louchebem.rb ├── 06. Word frequency │ ├── README.md │ ├── source-text.txt │ └── word_frequency.rb ├── 07. Roman to integer │ ├── README.md │ └── roman_to_integer.rb ├── 08. About blocks │ ├── README.md │ └── block_gym.rb ├── 09. Storing blocks in Proc │ ├── README.md │ └── love_message.rb ├── 10. Blocks are closures │ ├── README.md │ └── welcome_closure.rb └── 11. Refactor Gym │ ├── README.md │ └── refactor_gym_tonic.rb ├── Wagon-3 ├── 01. Mail spotter │ ├── README.md │ └── parsing_mail.rb ├── 02. Provider grouping │ ├── README.md │ └── provider_grouping.rb ├── 03. A translation story │ ├── README.md │ └── translation.rb ├── 04. Phone regexp │ ├── README.md │ └── check_phone.rb ├── 05. csv parsing │ ├── README.md │ ├── parsing_recipes.rb │ └── recipes.csv ├── 06. Playing with strings │ ├── README.md │ └── palindrome.rb └── 07. Extend built-in classes │ ├── README.md │ └── extend_built-in.rb └── Wagon-4 ├── 01. Text Analyzer └── README.md ├── 02. RPS ├── README.md └── rps.rb ├── 03. Numbers and Letters ├── README.md └── game.rb ├── 04. Blogging with Jekyll └── README.md └── 05. Bad-ass DRY gym ├── README.md └── dry_gym.rb /README.md: -------------------------------------------------------------------------------- 1 | ruby 2 | ==== 3 | 4 | Ruby-beginners challenges 5 | -------------------------------------------------------------------------------- /Wagon-0/01. Submit your code/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beub/ruby/7d371b94972a2a5964c13cb59b5b2c862d251d71/Wagon-0/01. Submit your code/README.md -------------------------------------------------------------------------------- /Wagon-0/01. Submit your code/github_champ.rb: -------------------------------------------------------------------------------- 1 | puts "I am a github champ" -------------------------------------------------------------------------------- /Wagon-0/02. IRB-basics/README.md: -------------------------------------------------------------------------------- 1 | IRB is a [REPL](http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) for ruby. Basically, it works this way 2 | 3 | 1. It **R**eads the expression written by the user, which can be any valid ruby expression like `"Hello"`, `2+2`, `puts "Hello"`,... 4 | 2. It **E**valuates the result of this expression. 5 | 3. It **P**rints this result. 6 | 4. It **L**oops back to point 1, waiting for a new user input. 7 | 8 | Use [IRB](http://fr.wikipedia.org/wiki/Interactive_Ruby) to 9 | 10 | * define a variable `my_name` pointing to your name, as a String. 11 | 12 | * define a function `say_hi_to(name)`, that returns a personalized welcome message . For instance, `say_hi_to("Bob")` should return something like "Hello Bob ! welcome to the ouagon". 13 | 14 | * call this function giving it `my_name` as an argument 15 | 16 | Copy you IRB shell history and put it in the txt file for submission. Of course, you still have to follow the submission process (as in previous challenge), i.e. commit, push, and submit the URL of your *irb_basic.txt* file. 17 | -------------------------------------------------------------------------------- /Wagon-0/02. IRB-basics/irb_basics.txt: -------------------------------------------------------------------------------- 1 | irb(main):001:0> my_name= "benoit" 2 | => "benoit" 3 | irb(main):002:0> def say_hi_to(name) 4 | irb(main):003:1> puts "Hello Ben! Welcome to the ouagon!" 5 | irb(main):004:1> end 6 | => nil 7 | irb(main):005:0> 8 | irb(main):006:0* 9 | irb(main):007:0* 10 | irb(main):008:0* cke 11 | NameError: undefined local variable or method `cke' for main:Object 12 | from (irb):8 13 | from /usr/bin/irb:12:in `
' 14 | irb(main):009:0> say_hi_to 15 | ArgumentError: wrong number of arguments (0 for 1) 16 | from (irb):2:in `say_hi_to' 17 | from (irb):9 18 | from /usr/bin/irb:12:in `
' 19 | irb(main):010:0> my_name 20 | => "benoit" 21 | irb(main):011:0> say_hi_to(my_name) 22 | Hello Ben! Welcome to the ouagon! 23 | => nil 24 | irb(main):012:0> def say_hi_to(my_name) 25 | irb(main):013:1> puts "Hello #{my_name}! Welcome to the ouagon!" 26 | irb(main):014:1> end 27 | => nil 28 | irb(main):015:0> say_hi_to(my_name) 29 | Hello benoit! Welcome to the ouagon! 30 | => nil 31 | irb(main):016:0> prenom= "Chris" 32 | => "Chris" 33 | irb(main):017:0> say_hi_to(prenom) 34 | Hello Chris! Welcome to the ouagon! 35 | => nil 36 | irb(main):018:0> -------------------------------------------------------------------------------- /Wagon-0/03. Experiment methods/OO-experiments.txt: -------------------------------------------------------------------------------- 1 | // Copy some experiments you made on ruby String and Fixnum objects below ! 2 | // You choose pick 3 methods for String and 3 methods for Fixnum -------------------------------------------------------------------------------- /Wagon-0/03. Experiment methods/README.md: -------------------------------------------------------------------------------- 1 | ```ruby 2 | 3 + 7 # You might see this as basic addition with two parameters 3 and 7 3 | 3.+(7) # That's not an OO approach. Here's what's really at stake 4 | 3.send("+", 7) # Here is what's really happening in ruby stomach 5 | "Waou ".*(3) 6 | "Waou ".*(3).+(" !!!!") 7 | "A string object".class 8 | 19.class 9 | "A string object".upcase 10 | "A string object".methods # Try tro find the upcase instance method in the list 11 | String.instance_methods # Methods of an object = Instance methods of its class ! 12 | String.methods # Class may have other methods than instance ones 13 | "A string object".methods.class 14 | "A string object".class.class 15 | ``` 16 | 17 | * **Experiment these lines** on IRB. 18 | * Discuss with your pair the meaning of each expression and of its result. 19 | 20 | Here are some thoughts to help you a bit ! 21 | 22 | ## Some thoughts 23 | 24 | In ruby, everything (a text, an integer, a float, an array..) is an object, i.e. an instance (or realization) of a class. 25 | On this object, we can call methods defined at the class level, which are called **instance methods** as they can be called on instances of the class. 26 | 27 | How does this **method call** work exactly when we plunge into ruby code ? 28 | 29 | The object on which we call the method is called the **receiver**. We send a message to this receiver, containing 30 | * The name of the method (like the "+" method in our example above) 31 | * Additionnal parameters that this method takes as argument 32 | * Hereabove, when we run `3 + 7`, what we do is 33 | * We send the message "+" with parameter 7 to our object 3 34 | * This object 3 being an instance of the `Fixnum` class 35 | 36 | ## Experiment methods 37 | Find 3 different methods of the [String class](http://ruby-doc.org/core-2.1.0/String.html) and 3 methods of the [Fixnum class](http://www.ruby-doc.org/core-2.1.0/Fixnum.html) and apply them to String and Fixnum objects of your choice, using IRB of course. Copy these experiments in the txt file for submission. You can pickup exotic methods ! the idea is to learn how to quicly grasp a new method using the ruby doc. 38 | 39 | -------------------------------------------------------------------------------- /Wagon-0/04. Age in days/README.md: -------------------------------------------------------------------------------- 1 | Write a function `age_in_days(day, month, year)` that returns your age in days, given your day, month, and year of birth. It should work as follows 2 | 3 | * You give your day, month, year of birth as parameters (e.g. you will call the function like => `age_in_days(6, 11, 1985)`). 4 | * The function returns `"you have DD days buddy"`, where `DD` is the number of days in your age. 5 | 6 | ### Tips 7 | * You can use `Time.now.day`, `Time.now.month`, `Time.now.year` to have today's details. See [Time class](http://www.ruby-doc.org/core-2.0.0/Time.html) 8 | * Try to figure out how you would do that on a sheet of paper before going into the code. 9 | * Use the interactive ruby console (IRB) to make "live" experiments. -------------------------------------------------------------------------------- /Wagon-0/04. Age in days/age_in_days.rb: -------------------------------------------------------------------------------- 1 | def age_in_days(day, month, year) 2 | # your code goes here ! 3 | end 4 | 5 | 6 | # Testing your code 7 | puts age_in_days(6, 11, 1985) -------------------------------------------------------------------------------- /Wagon-0/05. What's your name ?/README.md: -------------------------------------------------------------------------------- 1 | Write a ruby program that works this way : 2 | * it asks for your first name and let you write it in the terminal 3 | * it asks for your middle name and let you write it in the terminal 4 | * it asks for your last name and let you write it in the terminal 5 | 6 | Then, let's assume you entered "Boris" then "Alexandre" and finally "Papillard", the program should print `"Hello, Boris Alexandre Papillard !"`. 7 | 8 | ## Concatenation or interpolation ? 9 | Code your programs 2 different ways: 10 | * using String concatenation with the `+` operator. 11 | * using String interpolation with `#{}` 12 | * What's the difference between using single-quotes `''` or double-quotes `""` when using string interpolation ? 13 | 14 | ## Tips 15 | * to read a user input from the terminal you should use gets. You will also need to chomp the resulting string. 16 | * to print question in the terminal, you should use puts 17 | 18 | ## Extra 19 | * Optionally, your program could also tell you the number of characters in your full name (for instance, "Boris Alexandre Papillard" has got 24 characters, including spaces). 20 | * It could also add a custom greeting at the end of the message like `"You're a good person"` in the case where you enter **your** full name, and **yours only**. 21 | 22 | 23 | -------------------------------------------------------------------------------- /Wagon-0/05. What's your name ?/introduce_yourself.rb: -------------------------------------------------------------------------------- 1 | # your code goes here, introduce yourself ! -------------------------------------------------------------------------------- /Wagon-0/06. Stupid coaching/README.md: -------------------------------------------------------------------------------- 1 | Write a program that models your relation with a personal coach. This coach is rather stupid and exhibits the following behavior 2 | 3 | 1. If you don't **ask** him something, but just **tell** him something (e.g. "I met a girl last night"), he will just answer back "I don't care son, get dressed and go to work !" 4 | 2. If you ask him something, he won't be of great help either and he will tell you "Silly question, get dressed and go to work !" 5 | 3. The only way to get rid of him is to tell him what he expects, "I am going to work right now SIR !" 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
Real worldCode world
Waking up Running the program personal_coaching.rb from the terminal
Speaking to your coachReading a string in the terminal with gets
Making your coach speakWriting a string in the terminal with puts
Asking a questionReading a string which ends with ?
Getting rid of your coachExiting the program
22 | 23 | Write a fonction `stupid_coaching` which models this interaction with your coach. 24 | 25 | ### Tips 26 | You can access each character of a string as if it was an array with [[] operator](http://ruby-doc.org/core-2.0.0/String.html#method-i-5B-5D). And you can iterate backward on the string giving a negative index to this operator. 27 | 28 | ### Go Further 29 | Try to invent new rules, here are some ideas 30 | 31 | * if you tell your coach "I am going to work", he tells you back "good boy ! Take the subway, it will be faster". And from this point 32 | 33 | * if you tell him something, he tells you back "I don't care son, take the subway and go to work !" 34 | * if you ask him something, he answers back "Silly question, take the subway and go to work !" 35 | 36 |
37 | * if you shout at him, he will always add "I can feel your motivation son !" before he usual answer. How would you model someone shouting ? the ruby `upcase`method should give you a hint :) 38 | -------------------------------------------------------------------------------- /Wagon-0/06. Stupid coaching/stupid_coaching.rb: -------------------------------------------------------------------------------- 1 | def stupid_coaching 2 | # your code goes here 3 | end 4 | 5 | # Calling the method 6 | stupid_coaching -------------------------------------------------------------------------------- /Wagon-0/07. Code-style Gym/README.md: -------------------------------------------------------------------------------- 1 | Re-write this code using good ruby coding conventions, especially, focus on these points : 2 | * naming conventions for variables, constants, class & method names 3 | * indent and inline rules when defining methods and classes 4 | * use of parentheses and spaces 5 | 6 | The [Ruby Style Guide](https://github.com/porecreat/ruby-style-guide/blob/master/README-frFR.md) is a good starting point to learn how to write clean ruby code. -------------------------------------------------------------------------------- /Wagon-0/07. Code-style Gym/codestyle_gym.rb: -------------------------------------------------------------------------------- 1 | class Player_moving 2 | Grid_POSITIONS = (1..100).to_a 3 | 4 | def initialize ( position ) 5 | @position = position ; @iterations = 0; 6 | raise "Position must be between 1 and 100" unless Grid_POSITIONS.include? @position 7 | end 8 | 9 | def move distanceInMeters 10 | @position += distanceInMeters 11 | end 12 | 13 | def play 14 | if( self.status_Player==:play ) 15 | if rand(1..100) < 50 ; move(rand(1..10)) 16 | else 17 | move(-rand(1..10)) 18 | end 19 | end 20 | end 21 | 22 | def cheat; @position = 101; end 23 | 24 | def status_Player 25 | if( @position > 100 ) 26 | :win 27 | elsif(@position<0) ; :loose 28 | else; :play 29 | end 30 | end 31 | 32 | def hasWon ; status_Player == :win ; end 33 | 34 | end 35 | 36 | player = Player_moving.new(50) 37 | player.play 38 | puts player.status_Player == :play # true 39 | player.cheat 40 | puts player.hasWon == true 41 | 42 | begin 43 | Player_moving.new(110) 44 | rescue RuntimeError => e 45 | puts e.to_s == "Position must be between 1 and 100" # true 46 | end -------------------------------------------------------------------------------- /Wagon-1/01. Simple looping/README.md: -------------------------------------------------------------------------------- 1 | A very simple exercise to learn how to do looping in ruby. 2 | 3 | ## Objectives 4 | 5 | Write a method in ruby that computes the sum of the integers between a min value and a max value. 6 | Ex: what is the sum of the integers between 1 and 100 ? 7 | 8 | Implement the function 2 different iterative ways using a `for` loop and a `while` loop 9 | 10 | ## Extra: enhance/refactor 11 | Try to implement the function in a recursive way. 12 | 13 | ## Resources 14 | http://www.tutorialspoint.com/ruby/ruby_loops.htm -------------------------------------------------------------------------------- /Wagon-1/01. Simple looping/simple_looping.rb: -------------------------------------------------------------------------------- 1 | # The objective is to create a function that computes the sum of the integers from a min value to a max value 2 | 3 | def sum(min,max) 4 | # your code here 5 | end 6 | 7 | # Testing your code 8 | 9 | min = 1 10 | max = 100 11 | sum = sum(1,100) 12 | puts sum == 5050 # => true -------------------------------------------------------------------------------- /Wagon-1/02. Sorting the wagon/README.md: -------------------------------------------------------------------------------- 1 | Sort an array of names typed into the command line. It should work like this 2 | 3 | ``` 4 | $ ruby wagon_sort.rb 5 | > Type a student: 6 | > felix 7 | > Type another student (or press enter to finish): 8 | > cedric 9 | > Type another student (or press enter to finish): 10 | > blandine 11 | > Type another student (or press enter to finish): 12 | > 13 | > Congratulations ! Your Wagon has 3 students: 14 | > blandine 15 | > cedric 16 | > felix 17 | ``` 18 | Make sure to test your program, both internally and from the command line (the user interface). Your program should : 19 | 1. Get every word inputed by the user and store it in a ruby array 20 | 2. When the user press `Enter`, sort this array and output each of its elements (ordered alphabetically) 21 | 3. Your program should ignore cases, e.g. put `blandine` before `Felix`. Still, it should print the two names with their original case ! 22 | 23 | ## Objectives 24 | * work with user input. 25 | * store data and access it in ruby data structures. 26 | * learn about [sorting algorithms](http://en.wikipedia.org/wiki/Sorting_algorithm). 27 | * learn to look for methods in the [ruby doc](http://ruby-doc.org/). 28 | 29 | ## Tips 30 | * You should be particularly interested in the `String` and `Array` classes in the ruby doc. 31 | * You should use the interactive ruby console (irb) to make "live" tests before coding you program. 32 | * If you are having a hard time finding the solution, go through [user input tutorial](http://www.ruby-doc.org/docs/Tutorial/part_02/user_input.html), but **it's far better if you find the solution alone !** 33 | -------------------------------------------------------------------------------- /Wagon-1/02. Sorting the wagon/wagon_sort.rb: -------------------------------------------------------------------------------- 1 | def wagon_sort( students_array ) 2 | # your code to sort the array and output students 3 | end 4 | 5 | # your code to interact with the user.. -------------------------------------------------------------------------------- /Wagon-1/03. Beer song /README.md: -------------------------------------------------------------------------------- 1 | Write a program that prints the lyrics of the song [99 Bottles of Beer](http://www.99-bottles-of-beer.net/lyrics.html). 2 | 3 | It will take as an argument the starting number of bottles, given through the command line when executing the program. This program should work this way. 4 | 5 | ``` 6 | > ruby beer_song.rb 5 7 | > 5 bottles of beer on the wall, 5 bottles of beer! 8 | > Take one down, pass it around, 4 bottles of beer on the wall! 9 | > 4 bottles of beer on the wall, 4 bottles of beer! 10 | > Take one down, pass it around, 3 bottles of beer on the wall! 11 | > 3 bottles of beer on the wall, 3 bottles of beer! 12 | > Take one down, pass it around, 2 bottles of beer on the wall! 13 | > 2 bottles of beer on the wall, 2 bottles of beer! 14 | > Take one down, pass it around, 1 bottle of beer on the wall! 15 | > 1 bottle of beer on the wall, 1 bottle of beer! 16 | > Take one down, pass it around, no more bottles of beer on the wall! 17 | ``` 18 | 19 | ### Hint 20 | * You can communicate arguments to your program from the command line using [ARGV](http://ruby.about.com/od/rubyfeatures/a/argv.htm) 21 | * I hope you noticed the change from bottles to bottle when only 1 bottle remains ! 22 | 23 | ### A bit of context on ARGV 24 | Any Ruby program you write runs inside another piece of software: the Ruby interpreter. And that interpreter is itself running inside another piece of software: your operating system. These software layers are called the environment and there are many ways you can exchange data between the environment and your program. 25 | 26 | One way is via the ARGV constant which comes pre-defined in every Ruby program. It is an Array of Strings representing the command line arguments. Consider this simple program 27 | 28 | **testing_argv.rb** 29 | ```ruby 30 | puts "*** Command line arguments ***" 31 | puts ARGV.inspect 32 | ```` 33 | Now run it in the terminal this ways 34 | ``` 35 | ~ $ ruby testing_argv.rb un deux trois 36 | *** Command line arguments *** 37 | ["un", "deux", "trois"] 38 | ~ $ ruby testing_argv.rb "un et deux" trois 39 | *** Command line arguments *** 40 | ["un et deux", "trois"] 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /Wagon-1/03. Beer song /beer_song.rb: -------------------------------------------------------------------------------- 1 | def beersong(nb_at_start) 2 | # your code goes here 3 | end 4 | 5 | beersong( ARGV[0] ) 6 | 7 | # output (if called with 5 beers) : 8 | 9 | # => 5 bottles of beer on the wall, 5 bottles of beer! 10 | # => Take one down, pass it around, 4 bottles of beer on the wall! 11 | # => 4 bottles of beer on the wall, 4 bottles of beer! 12 | # => Take one down, pass it around, 3 bottles of beer on the wall! 13 | # => 3 bottles of beer on the wall, 3 bottles of beer! 14 | # => Take one down, pass it around, 2 bottles of beer on the wall! 15 | # => 2 bottles of beer on the wall, 2 bottles of beer! 16 | # => Take one down, pass it around, 1 bottle of beer on the wall! 17 | # => 1 bottle of beer on the wall, 1 bottle of beer! 18 | # => Take one down, pass it around, no more bottles of beer on the wall! -------------------------------------------------------------------------------- /Wagon-1/04. Cookbook ToC/README.md: -------------------------------------------------------------------------------- 1 | You want to write a cook book that should be accessible from the terminal (you are so geek..). After having written all the recipes, you want to build a nice table of content for your book. You already have you book title, and the "plan" for the different sections, with corresponding pages. 2 | 3 | ```ruby 4 | title = 'Recettes de kiffeur' 5 | 6 | chapters = [ 7 | ['Materiel pour cuisiner', 1], 8 | ['Produits de saison', 8], 9 | ['Sauces et soupes', 19], 10 | ['Viandes et Gibiers', 38], 11 | ['Poissons et coquillages', 157] 12 | ] 13 | ```` 14 | 15 | Write a ruby program that will print the following output in the terminal 16 |
                       Recettes de kiffeur
17 | 
18 | Chapter 1 :  Materiel pour cuisiner                            page 1
19 | Chapter 2 :  Produits de saison                                page 8
20 | Chapter 3 :  Sauces et soupes                                 page 19
21 | Chapter 4 :  Viandes et Gibiers                               page 38
22 | Chapter 5 :  Poissons et coquillages                         page 157
23 | 
24 | 25 | 26 | ## Hints 27 | You should use String ruby methods like `rjust`, `ljust` and `center`. 28 | -------------------------------------------------------------------------------- /Wagon-1/04. Cookbook ToC/cookbook_toc.rb: -------------------------------------------------------------------------------- 1 | title = 'Recettes de kiffeur' 2 | 3 | chapters = [ 4 | ['Materiel pour cuisiner', 1], 5 | ['Produits de saison', 8], 6 | ['Sauces et soupes', 19], 7 | ['Viandes et Gibiers', 38], 8 | ['Poissons, coquillages et crustaces', 157] 9 | ] 10 | 11 | # You program goes here ! -------------------------------------------------------------------------------- /Wagon-1/05. Roman numerals/README.md: -------------------------------------------------------------------------------- 1 | ## Old school 2 | In the early days of Roman numerals, the Romans didn't bother with any of this new-fangled subtraction "IX" non-sense. No sir, it was straight addition, biggest to littlest, so 9 was written VIIII, and so on. 3 | * Write a method that when passed an integer between 1 and 3000 (or so) returns a string containing the proper old school Roman numeral. In other words, `old_roman_numeral(4)` should return 'IIII'. 4 | * Make sure to test your method on a bunch of different numbers. 5 | 6 | ## Hint 7 | Use the integer division and modulus methods ! For reference, these are the values of the letters used: 8 | * I = 1 9 | * V = 5 10 | * X = 10 11 | * L = 50 12 | * C = 100 13 | * D = 500 14 | * M = 1000 15 | 16 | ## Modern-style 17 | Eventually someone thought it would be terribly clever if putting a small number before a larger one meant you had to subtract the smaller one. As a result of this development, you must now suffer. Rewrite your previous method to return the new-style Roman numeral so when someone calls `roman_numeral(4)` , it should return 'IV'. 18 | -------------------------------------------------------------------------------- /Wagon-1/05. Roman numerals/roman_numerals.rb: -------------------------------------------------------------------------------- 1 | def old_roman_numeral(an_integer) 2 | # your code goese here 3 | end 4 | 5 | def roman_numeral(an_integer) 6 | # your code goese here for the new-style version 7 | end 8 | 9 | puts "My nice roman numeral tests" 10 | # Write a nice testing script herebelow ! -------------------------------------------------------------------------------- /Wagon-1/06. Shuffle/README.md: -------------------------------------------------------------------------------- 1 | Write a shuffle method that takes an array and returned a totally shuffled version. As always, you'll want to test it, but testing this one is trickier. How can you test to make sure you are getting a perfect shuffle ? What would you even say a perfect shuffle would be ? Now test for it. 2 | 3 | ## Hints 4 | * You should use ruby `rand` function 5 | * To write your algorithm, you are not authorized to use fancy Array methods like `sort_by` or `shuffle`! 6 | 7 | ## Write a 1-line function 8 | Once you have written your algorithm all by yourself, rewrite another version with only one line of code, this time using `Array#sort_by` ? -------------------------------------------------------------------------------- /Wagon-1/06. Shuffle/shuffle.rb: -------------------------------------------------------------------------------- 1 | def shuffle( array ) 2 | # your code goes here 3 | end 4 | 5 | sorted_array = (1..10).to_a 6 | 7 | # Testing your shuffle algorithm 8 | p shuffle(sorted_array) != shuffle(sorted_array) # => true -------------------------------------------------------------------------------- /Wagon-1/07. Enumerable/README.md: -------------------------------------------------------------------------------- 1 | Now it's the time to get familiar with the methods of the [Enumerable](http://ruby-doc.org/core-2.0.0/Enumerable.html) module. The Enumerable module is [mixed-in](http://ruby.about.com/od/beginningruby/a/mixin.htm) in most classes that are indeed enumerable as `String`, `Array`, `Hash`... Don't spend too much time on understanding ruby Mixin (because it's pretty advanced ruby). 2 | 3 | Let's just say that these Enumerable methods are very convenient to operate complicated tasks on enumerable objects in really few lines of code. 4 | 5 | You have to code each method in the template, so that it returns expected result. We tell you which `Enumerable#method` to use for each case, since we are nice buddies :) 6 | -------------------------------------------------------------------------------- /Wagon-1/07. Enumerable/enumerable.rb: -------------------------------------------------------------------------------- 1 | # TODO: Print the elements at indices 1, 3, 5, 7, etc. on separate lines. 2 | # You should make use of Enumerable#each_with_index 3 | def print_odd_indexed_integers(array) 4 | end 5 | 6 | # TODO: Return the odd numbers from a list of integers. 7 | # You should make use of Enumerable#select 8 | def odd_integers(array) 9 | end 10 | 11 | # TODO: Return the first number from an Array that is less than a particular number - 'limit.' 12 | # You should make use of Enumerable#find 13 | def first_under(array, limit) 14 | end 15 | 16 | # TODO: Take an Array of Strings and return a new Array with an exclamation point appended to each String. 17 | # You should make use of Enumerable#map 18 | def add_bang(array) 19 | end 20 | 21 | # TODO: Calculate the sum of an Array of numbers. 22 | # You should make use of Enumerable#reduce 23 | def sum(array) 24 | end 25 | 26 | # TODO: Reorganize an Array of the elements into groups of 3, and then sort each group alphabetically. 27 | # You should make use of Enumerable#each_slice 28 | def sorted_triples(array) 29 | end 30 | 31 | # Driver code... don't change this. 32 | print_odd_indexed_integers([2, 4, 6, 8, 10, 12]) # this should print "4\n8\n12" 33 | 34 | puts odd_integers([3, 4, 7, 9, 10, 16]) == [3, 7, 9] 35 | 36 | puts first_under([13, 21, 7, 0, 11, 106], 10) == 7 37 | 38 | puts add_bang(["hi", "mom"]) == ["hi!", "mom!"] 39 | 40 | puts sum([1, 1, 2, 3, 5]) == 12 41 | 42 | words = %w(the salted pork is particularly good) 43 | puts sorted_triples(words) == [["pork", "salted", "the"], 44 | ["good", "is", "particularly"]] -------------------------------------------------------------------------------- /Wagon-1/08. Destructive methods !/README.md: -------------------------------------------------------------------------------- 1 | * Choose some `Array` Enumerable method you like (or one you don't know, that's the occasion to learn something !). This method should have a **destructive version** ending with a bang (!), like `map` and `map!` or `select` and `select!` 2 | * Pick one method different from the one chosen by your pair. 3 | * Try to understand the difference between the original version and the bang-version. 4 | 5 | **Now code a program that clearly illustrates this difference**. Then show it to your friend and explain to him what you understood. 6 | 7 | You should submit your program which is supposed to illustrate the difference between `chosen_method` and `chosen_method!` -------------------------------------------------------------------------------- /Wagon-1/08. Destructive methods !/destructive_methods.rb: -------------------------------------------------------------------------------- 1 | # Find an example which illustrates the difference between chosen_method and chosen_method! 2 | # Copy / Paste this example here ! -------------------------------------------------------------------------------- /Wagon-1/09. Debug Gym/README.md: -------------------------------------------------------------------------------- 1 | This code has got some error. Try to fix it 2 | 3 | * **Read the error message** to understand the error type and at which line it occurs. 4 | * Then try to fix it. 5 | 6 | Now : 7 | * Read about [duck typing](http://fr.wikipedia.org/wiki/Duck_typing). Incen a very simple function that gives totally different results if given `String` objects or `Fixnum` object as arguments ? 8 | * Try to explain dynamic typing to another wagonner ! 9 | 10 | -------------------------------------------------------------------------------- /Wagon-1/09. Debug Gym/bugged_concatenate.rb: -------------------------------------------------------------------------------- 1 | def bugged_concatenate(array) 2 | # 2. fix the code: TypeError 3 | puts array.inject("") { |output, element| output + element }.upcase 4 | end 5 | 6 | 7 | # 1. fix the method call: ArgumentError 8 | bugged_concatenate( 1, "9", 84, " ", "George Orwell" ) -------------------------------------------------------------------------------- /Wagon-1/10. Refactor Gym/README.md: -------------------------------------------------------------------------------- 1 | Refactor this code ! Here is a rule of thumb 2 | 3 | * Use method chaining when it benefits to your code, makes it more concise, but still very understandable 4 | * Use intermediate variables when chaining makes your code unreadable 5 | -------------------------------------------------------------------------------- /Wagon-1/10. Refactor Gym/chain_unchain.rb: -------------------------------------------------------------------------------- 1 | def shuffle_word(a_word) 2 | # Ruby fonction to play to "Des chiffres et des lettres.." 3 | 4 | cap_word = a_word.upcase 5 | chars_enum = cap_word.chars 6 | array = chars_enum.to_a 7 | shuffle_array = array.shuffle 8 | 9 | return shuffle_array 10 | 11 | end 12 | 13 | 14 | def quote_prime_numbers(n) 15 | (1..n).find_all {|i| (2..i-1).select {|k| i % k == 0 }.count == 0 }.map{ |prime_num| "#{prime_num} is prime"} 16 | end 17 | 18 | 19 | puts shuffle_word("nabuchodonosor") 20 | puts quote_prime_numbers(30) -------------------------------------------------------------------------------- /Wagon-2/01. Modeling with Hash/README.md: -------------------------------------------------------------------------------- 1 | Let's say you want to stay fit but keep eating McDonalds... You have the brilliant idea to write a quick function that computes the number of calories in a McDonald meal. We consider the following products (with their respective number of calories). 2 | 3 | * Cheese Burger : 290 4 | * Big Mac : 300 5 | * Mc Bacon : 400 6 | * Royal Cheese : 130 7 | * French fries : 130 8 | * Potatoes : 130 9 | * Coca : 160 10 | * Sprite : 170 11 | 12 | => How would you do to write this function `calories_in(burger, side, beverage)` using arrays ? 13 | Just write the pseudocode for it ! 14 | => What if McDonald launches a new product like "Filet-of-Fish" ? What would you have to do to update your program ? 15 | 16 | Learn about ruby [hash](http://www.ruby-doc.org/core-2.0.0/Hash.html). They will be your best friends and you'll use them everywhere !How would you re-write your pseudo-code using a hash ? Isn't it more convenient ? 17 | 18 | Now let's say we are back in the day and McDonald launches its pre-set meals, like "Happy Meal", "Best Of Big Mac", etc.. How could you use a hash to represent these McDonald sets, and relate them to your product-calory hash. 19 | -------------------------------------------------------------------------------- /Wagon-2/02. On symbols/README.md: -------------------------------------------------------------------------------- 1 | ## Experiment 2 | In you ruby console, try this 3 | 4 | ```ruby 5 | harry = "Harry" 6 | harry << " meets Sally" 7 | harry_hash = :harry 8 | harry_hash << " meets Sally" 9 | harry_hash.to_s << " meets Sally" 10 | harry.object_id 11 | "Harry".object_id 12 | harry_hash.object_id 13 | :harry.object_id 14 | ``` 15 | 16 | ## Figure Out ! 17 | Try to answer the following questions and discuss them together. 18 | 19 | * what are the differences between Strings and Symbols ? 20 | * When is it more relevant to use one or the other class ? 21 | * In terms of memory, what's the behavior of each class ? 22 | 23 | ## Now understand more in-depth 24 | 25 | For ruby beginners, understanding symbols can be quite harsh.. A rule of thumb, symbols are "like" strings, but : 26 | 27 | * When you use a string not really for its textual content, but as a kind of unique identifier, you should consider using a Symbol 28 | * Hence many Hash keys are symbols, as they are more here to identify things than for their "text value". Consider for instance this hash `fox = { :color => "red", :specie => "mammal" }`. Here `:color` and `:specie` are more used as identifiers than for their actual content. Hence we used Symbols instead of Strings 29 | * Read [this article](http://www.robertsosinski.com/2009/01/11/the-difference-between-ruby-symbols-and-strings/) to understand more in-depth the subtle difference between Strings and Symbols (in terms of mutability & memory allocation). 30 | 31 | ## QCM 32 | For each example what should you use ? try to examine what each solution means, and whether it's licit or not ? 33 | 34 | * `{"temperature" => "10 deg Celsius", "pressure" => "10 bar"}` or `{:temperature => :"10 deg Celsius", :pressure => :"10 bar"}` or `{"temperature" => :"10 deg Celsius", "pressure" => :"10 bar"}` or `{:temperature => "10 deg Celsius", :pressure => "10 bar"}` or `{temperature => "10 deg Celsius", pressure => "10 bar"}` 35 | 36 | * `user_name = :bob` or `user_name = "bob"` or `"user_name" = "bob"` or `:user_name = :bob` 37 | 38 | * `{"action" => "show", controller => "users"}` or something else ? 39 | 40 | ## Warning 41 | The notation `{:symbol => "value"}` is doomed to disappear as symbol are nearly always used for hash keys. The new convention you should **systematically** use is `{symbol: "value"}`. -------------------------------------------------------------------------------- /Wagon-2/03. Anagrams/README.md: -------------------------------------------------------------------------------- 1 |
2 | Write 2 methods `anagrams?(a_string, another_string)` and `anagrams_on_steroids?(a_string, another_string)` that return whether or not two strings are anagrams. Anagrams are strings where only the order of the characters differs. 3 |
4 | #### Let's do some maths : 5 | 6 | * the first method `anagrams?` should use the ruby `sort` method. Given the length of the input words `n = a_string.length`, what's the complexity of this algorithm ? **You should write this complexity as a comment in your submitted code !** 7 | 8 | * use a ruby `Hash` to improve this complexity ? What's you new complexity ? Again, write it in you code as a comment 9 | 10 |
11 | #### Resources & Hints 12 | * First learn more about what [time complexity](http://en.wikipedia.org/wiki/Time_complexity) means 13 | * try to google the time-complexity of ruby native `sort` method 14 | * Learn more about [Hash](http://www.ruby-doc.org/core-2.0.0/Hash.html) as a data structure. How would you model the number of occurences of each character of a String using a ruby Hash ? What's the link with the anagrams problem ? -------------------------------------------------------------------------------- /Wagon-2/03. Anagrams/anagrams.rb: -------------------------------------------------------------------------------- 1 | def anagrams?( a_string, another_string ) 2 | # your code goes here 3 | end 4 | 5 | def anagrams_on_steroids?( a_string, another_string ) 6 | # your code goes here 7 | end 8 | 9 | # complexity = ? 10 | puts anagrams? "Monica Lewinsky", "Nice silky woman" # => true 11 | 12 | # complexity = ? 13 | puts anagrams_on_steroids? "Monica Lewinsky", "Nice silky woman" # => true -------------------------------------------------------------------------------- /Wagon-2/04. Combine anagrams/README.md: -------------------------------------------------------------------------------- 1 | An anagram is a word obtained by rearranging the letters of another word. For example, "rats", "tars" and "star" are an anagram group because they are made up of the same letters. 2 | 3 | Given an array of strings, write a method that groups them into anagram groups and returns the array of groups. Case doesn't matter in classifying string as anagrams (but case should be preserved in the output), and the order of the anagrams in the groups doesn't matter. 4 | 5 | ##### input 6 | ```ruby 7 | ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream'] 8 | ``` 9 | ##### output 10 | ```ruby 11 | [["cars", "racs", "scar"], ["four"], ["for"], ["potatoes"], ["creams", "scream"]] 12 | ``` 13 | 14 | ### Hint 15 | * You can quickly tell if two words are anagrams by sorting their letters, keeping in mind that upper vs lowercase doesn't matter ! 16 | * if you're curious (and patient) you can have a look at the different [sorting algorithms](http://en.wikipedia.org/wiki/Sorting_algorithm) and their associated time complexity. Also you can have a look at [this article](http://www.igvita.com/2009/03/26/ruby-algorithms-sorting-trie-heaps/) to know on which algorithm relies ruby `sort` method -------------------------------------------------------------------------------- /Wagon-2/04. Combine anagrams/group_anagrams.rb: -------------------------------------------------------------------------------- 1 | def group_anagrams(words) 2 | # your code here 3 | end 4 | 5 | # input: 6 | group_anagrams( ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream'] ) 7 | 8 | # output: 9 | # => [["cars", "racs", "scar"], ["four"], ["for"], ["potatoes"], ["creams", "scream"]] 10 | 11 | # HINT: you can quickly tell if two words are anagrams by sorting their 12 | # letters, keeping in mind that upper vs lowercase doesn't matter -------------------------------------------------------------------------------- /Wagon-2/05. Louchebem/README.md: -------------------------------------------------------------------------------- 1 | When having a drink with a french friend, he tells you "man, I've a great idea, I want to make people speak louchebem !" 2 | See how you can help him :) 3 | 4 | ## A bit of research 5 | * Read [this article](http://fr.wikipedia.org/wiki/Louch%C3%A9bem) to understand what is louchébem, initially spoken by french butchers. 6 | * Ask yourself what are the main issues for building your translator (choice of the final suffix, how to handle beginning of words, what are the different scenarios for a given word in input...) 7 | 8 | ## Write the pseudo-code 9 | Pseudocode is primarily used to communicate the essence of an algorithm without getting bogged down in language-specific syntax. A good programmer can take well-written pseudocode and translate it into functional code in the language of his choice. 10 | * Write the pseudo-code for you louchebem translator. 11 | * Start small with a program that can only translate a single french word in louchebem 12 | * Then try to extend it to sentences. 13 | 14 | Did you know that popular expressions like "larfeuille", "loufiah", "loucedé", or "loufoque" are louchébem expressions ! 15 | 16 | ## Best practice 17 | You pseudo code should follow [these principles](http://www.cs.cornell.edu/Courses/cs482/2003su/handouts/pseudocode.pdf) -------------------------------------------------------------------------------- /Wagon-2/05. Louchebem/louchebem.rb: -------------------------------------------------------------------------------- 1 | # the file is yours ! -------------------------------------------------------------------------------- /Wagon-2/06. Word frequency/README.md: -------------------------------------------------------------------------------- 1 | Write a program that takes a filename and a parameter n and prints the n most common words in the file, and the count of their occurrences, in descending order. This should work this way (taking the bible in input as an example): 2 | 3 | ```ruby 4 | most_common_words('bible.txt', 3) # prints => 5 | > 'lord': 8722 occurrences 6 | > 'God': 7380 occurrences 7 | > 'Jesus': 2617 occurrences 8 | ``` 9 | 10 | ## Get rid of the noise 11 | Add a filter to your method to get rid of common words as ("a", "the", "is", ...). Here is some help: 12 | * such common words are called stop-words. [Here](http://en.wikipedia.org/wiki/Stop_words) you can find some lists of English stop-words, which you can use to build a stop-words array that you will use in your program. 13 | 14 | ## Be creative 15 | Run your program on some original text (political speech, ferry tale, etc...) -------------------------------------------------------------------------------- /Wagon-2/06. Word frequency/source-text.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beub/ruby/7d371b94972a2a5964c13cb59b5b2c862d251d71/Wagon-2/06. Word frequency/source-text.txt -------------------------------------------------------------------------------- /Wagon-2/06. Word frequency/word_frequency.rb: -------------------------------------------------------------------------------- 1 | # the file is yours ! -------------------------------------------------------------------------------- /Wagon-2/07. Roman to integer/README.md: -------------------------------------------------------------------------------- 1 | Write a methods `roman_to_integer(roman_string)` which translates a roman string like 'IV' in its integer version 4. 2 | 3 | ## Tips 4 | Which data structure seems the most appropriate to map roman individual characters to integers ? 5 | -------------------------------------------------------------------------------- /Wagon-2/07. Roman to integer/roman_to_integer.rb: -------------------------------------------------------------------------------- 1 | def roman_to_integer(roman_string) 2 | # your code goes here 3 | end 4 | 5 | # testing your program 6 | puts roman_to_integer('IV') == 4 # => true 7 | puts roman_to_integer('XII') == 12 # => true 8 | puts roman_to_integer('XIX') == 19 # => true 9 | 10 | -------------------------------------------------------------------------------- /Wagon-2/08. About blocks/README.md: -------------------------------------------------------------------------------- 1 | Read and reproduce the following example to understand how we can attach a block of code to any method, and yield values to it. 2 | 3 | ### Basic block implicit call 4 | ```ruby 5 | def self_important 6 | puts "Listen to me now ! Cause I'm gonna say something brilliant" 7 | yield 8 | puts "You see it was brilliant !" 9 | end 10 | 11 | self_important { puts "Birds of a fleather flock together" } 12 | ``` 13 | This works the same way if the method has arguments. 14 | ```ruby 15 | def self_important(ego_power) 16 | puts "Listen to me now ! Cause I'm gonna say something #{"very "*ego_power} brilliant" 17 | yield 18 | puts "You see it was brilliant !" 19 | end 20 | 21 | self_important(3) { puts "Birds of a fleather flock together" } 22 | ``` 23 | 24 | ### Calling a block several times 25 | ```ruby 26 | def self_important_alzheimer(alzheimer_power) 27 | puts "Listen to me now ! Cause I'm gonna say something brilliant" 28 | alzheimer_power.times { yield } 29 | puts "You see it was brilliant !" 30 | end 31 | 32 | self_important_alzheimer(2) { puts "Birds of a fleather flock together... hmm" } 33 | ``` 34 | 35 | ### Yielding values to the block 36 | ```ruby 37 | def self_important_alzheimer(alzheimer_power) 38 | puts "Listen to me now ! Cause I'm gonna say something brilliant" 39 | yield(alzheimer_power) 40 | puts "You see it was brilliant !" 41 | end 42 | 43 | self_important_alzheimer(2) { |n| puts "Birds of a fleather flock together... hmm\n" * n } 44 | ``` 45 | ### Application 46 | #### Recode `inject` using `each` 47 | Write a method `inject(array, initial_value)` that has exactly the same behavior and return the same thing as the built-in `inject` iterator of the `Array` class. Code it using the `each` iterator and yielding the `array` values to the block. It should work this way 48 | ```ruby 49 | inject(1..100, 0) { |initial_value, element| element + initial_value } # => 5050 50 | ``` 51 | 52 | #### Block-timer 53 | Write a block-timer method than enables to track the duration of the execution of any given block. It should work this way. 54 | ```ruby 55 | timer_for do 56 | (1..100).each { |i| (1..100000).to_a.shuffle.sort } 57 | end 58 | # => Took you 3.39051 seconds 59 | ``` -------------------------------------------------------------------------------- /Wagon-2/08. About blocks/block_gym.rb: -------------------------------------------------------------------------------- 1 | # Recoding inject iterator 2 | 3 | def inject(array, initial_value) 4 | # your code goes here 5 | end 6 | 7 | puts inject(1..100, 0) { |initial_value, element| element + initial_value } == 5050 # true 8 | 9 | # Block timer 10 | 11 | def timer_for 12 | # your code goes here 13 | end 14 | 15 | timer_for do 16 | (1..100).each { |i| (1..100000).to_a.shuffle.sort } 17 | end 18 | 19 | # Should return around 2-3 seconds -------------------------------------------------------------------------------- /Wagon-2/09. Storing blocks in Proc/README.md: -------------------------------------------------------------------------------- 1 | There are two main ways to receive blocks in a method in Ruby : the first is to use the yield keyword like we just did. Sometimes, however we need to **store** the block in an object, either because we want to call it later or because the method that takes the block as an argument delegates to another method and needs to transfer the block to this sub-called method. 2 | 3 | Hopefully we can store blocks of ruby code in `Proc` objects. 4 | 5 | ## Ampersand block argument 6 | When prefixing the last argument in a method signature with an ampersand, it creates a `Proc` object from any block passed in. This object can then be executed with the `call` method like so: 7 | ```ruby 8 | def speak(&block) 9 | puts block.call 10 | end 11 | 12 | speak { "Hello" } 13 | # Hello 14 | # => nil 15 | ``` 16 | A `Proc` object will created from the given block any time the method is called 17 | 18 | ## Creating Proc objects 19 | You may also want to create your `Proc` objects by yourself and give them to the method as normal parameters like so: 20 | ```ruby 21 | def speak(block) 22 | puts block.call 23 | end 24 | 25 | message_block = Proc.new { "Hello" } 26 | speak (message_block) 27 | # Hello 28 | # => nil 29 | ``` 30 | ## Your turn ! 31 | Tell your mum how you love her ! Code the `tell` and `tell_mum` methods using either ampersand block argument or passing the `Proc` object explicitly. 32 | 33 | 34 | -------------------------------------------------------------------------------- /Wagon-2/09. Storing blocks in Proc/love_message.rb: -------------------------------------------------------------------------------- 1 | def tell(who, &message_block) 2 | # A new Proc object is created from the given message_block 3 | # Your code goes here... 4 | end 5 | 6 | def tell_mum(&message_block) 7 | #...and here (you should call the tell method of course) 8 | end 9 | 10 | tell_mum {"I love you"} # => "mum, I love you !" 11 | 12 | 13 | # Now create the block object by yourself 14 | def tell(who, message_blk) 15 | # The Proc object is created outside the method and passed as normal parameter 16 | # Your code goes here... 17 | end 18 | 19 | def tell_mum(message_blk) 20 | #...and here (you should call the tell method of course) 21 | end 22 | 23 | love_block = Proc.new {"I love you"} 24 | 25 | tell_mum(love_block) # => "mum, I love you !" -------------------------------------------------------------------------------- /Wagon-2/10. Blocks are closures/README.md: -------------------------------------------------------------------------------- 1 | The concept of closure may be quite hard to grasp for beginners but it makes a block's behavior really different from a method's behavior in ruby. Let's see what are the main difference between a block and a method in ruby : 2 | 3 | * first of all, a block can be passed as an argument (either through `yield`, as an ampersand final argument, or as an explicit `Proc` object given to the method) 4 | 5 | * Also, a block remembers the values of all the variables that were in scope when the function was created. It is then able to access those variables when it is called even though they may no longer be in scope. 6 | 7 | Study the following example : 8 | 9 | ```ruby 10 | def block_counter 11 | n = 0 12 | return Proc.new { n = n + 1 } 13 | end 14 | 15 | b = block_counter 16 | puts b.call 17 | puts b.call 18 | ``` 19 | What do you expect this program to print ? Try to figure it out and discuss together what happened in this program. 20 | 21 | ## Your turn 22 | Complete the given code template so that it welcomes all the Wagon's students and count them at the same time, to check that no one gave up :) As you code ask yourself : 23 | * How does the `count` value get linked to the block when the block is instantiated ? 24 | * How would a method behave if I used a method instead of a block ? 25 | * If I print the `count` variable after calling the block, what will be its value ? 26 | * If I print the `count` variable after calling the block, what will be its value ? 27 | 28 | ## Subtleties... 29 | Once your code runs let's try to insert a line as below : 30 | ```ruby 31 | welcome_blk.call("felix") 32 | welcome_blk.call("estelle") 33 | count = 10 34 | welcome_blk.call("cedric") 35 | welcome_blk.call("fred") 36 | ```` 37 | What will happen ? 38 | 39 | Now, with the former example, let's try this : 40 | ```ruby 41 | def block_counter 42 | n = 0 43 | return Proc.new { n = n + 1 } 44 | end 45 | 46 | b = block_counter 47 | puts b.call 48 | n = 10 49 | puts b.call 50 | ``` 51 | 52 | What will happen ? what's the difference with our welcome example her ? 53 | 54 | 55 | -------------------------------------------------------------------------------- /Wagon-2/10. Blocks are closures/welcome_closure.rb: -------------------------------------------------------------------------------- 1 | count = 0 2 | 3 | welcome_blk = Proc.new do |name| 4 | # your code goes here ! 5 | end 6 | 7 | welcome_blk.call("felix") # => Welcome felix, join your 0 friend 8 | welcome_blk.call("estelle") # => Welcome estelle, join your 1 friend 9 | welcome_blk.call("cedric") # => Welcome estelle, join your 2 friends 10 | welcome_blk.call("fred") # => Welcome fred, join your 3 friends 11 | -------------------------------------------------------------------------------- /Wagon-2/11. Refactor Gym/README.md: -------------------------------------------------------------------------------- 1 | Here is a ruby function to animate your gym training. Running this program you get the following result 2 | 3 | ```` 4 | hop! Encore une fois.. 5 | hop! hop! Encore une fois.. 6 | hop! hop! hop! Encore une fois.. 7 | hop! hop! hop! hop! Encore une fois.. 8 | hop! hop! hop! hop! hop! Encore une fois.. 9 | hop! hop! hop! hop! hop! hop! Encore une fois.. 10 | ``` 11 | 12 | The problem is that this code was written by a poor developer... It's got lots of useless parts and loops. 13 | 14 | **Try to refactor this code, and then compare your solution with your pair.** -------------------------------------------------------------------------------- /Wagon-2/11. Refactor Gym/refactor_gym_tonic.rb: -------------------------------------------------------------------------------- 1 | # Very dirty code to make some dirty gym... 2 | def hop_hop_hop(number_of_exercises) 3 | for i in (1..number_of_exercises) do 4 | counter = 0 5 | until counter == i do 6 | print "hop! " 7 | counter += 1 8 | end 9 | unless counter != i # Test if reaching the end of the current exercise. 10 | # Prints message in that case 11 | print 'Encore une fois..' + "\n" 12 | end 13 | # Reset counter to 0 for the next exercise 14 | counter = 0 15 | end 16 | end 17 | 18 | hop_hop_hop(6) 19 | -------------------------------------------------------------------------------- /Wagon-3/01. Mail spotter/README.md: -------------------------------------------------------------------------------- 1 | Read this [joke](http://theoatmeal.com/comics/email_address) and write a simple function `parse_mail` which parses an input email and gives you a custom message depending on your mail provider. For instance : 2 | 3 | ```ruby 4 | parse_mail("boris@lewagon.org") 5 | => "Well done boris, you're skilled and capable" 6 | parse_mail("jean-louis.alarue@yahoo.fr") 7 | => "Salut jean-louis alarue, tu m'as l'air a la rue.." 8 | ``` 9 | 10 | ## Specs 11 | of course you can invent your own jokes (the ones from the post are not very funny). Your program should : 12 | * Detect first name, last name and providers respecting this syntax `first_name.last_name@provider.com`` 13 | * If the mail does not respect this structure, your program will just consider the first part of the mail (before the `@` character) as the user's global name. 14 | * if the mail does not look like a mail, as `not_a@mail.at@all.com` your program should just return `"invalid input buddy"` 15 | 16 | ## Tips 17 | * Your jokes by provider will be given once and for all. They will not change. What kind of variable should you use to store them ? 18 | * Which data structure is the more adequate to model these jokes ? a String ? an Array ? a Hash ? 19 | 20 | -------------------------------------------------------------------------------- /Wagon-3/01. Mail spotter/parsing_mail.rb: -------------------------------------------------------------------------------- 1 | def parse_mail 2 | # 1. How do you model the jokes ? Pick up the adequate line 3 | $jokes = [["gmail", "you're an average but modern person"],["lewagon", "you're skilled and capable"]] 4 | jokes = "gmail,you're an average but modern person\nlewagon;you're skilled and capable" 5 | JOKES = {"gmail" => "you're an average but modern person", "lewagon" => "you're skilled and capable"} 6 | 7 | # 2. Don't hesitate to add jokes to this poor list.. 8 | 9 | # 3. Now you simply have to code the rest :) 10 | end 11 | 12 | parse_mail("boris@lewagon.org") # => "Well done boris, you're skilled and capable" -------------------------------------------------------------------------------- /Wagon-3/02. Provider grouping/README.md: -------------------------------------------------------------------------------- 1 | ### The context 2 | You can extract lots of information from someone's email address. There are even some [jokes on the topic](http://theoatmeal.com/comics/email_address). Let's say you have a user database with thousands of email, and you want to make some semantic analysis on these emails depending on their provider. 3 | 4 | ### The problem 5 | * In input, you have a ruby Array containing all your users' email. For instance 6 | 7 | ```ruby 8 | users = [ 9 | "bob@yahoo.fr", 10 | "roger57@hotmail.fr", 11 | "bigbox@yahoo.fr", 12 | "boris@lewagon.org", 13 | "monsieur.olivier@gmail.com", 14 | "monsieur.mack@gmail.com" 15 | ] 16 | ``` 17 | 18 | * You want to group these users depending on their mail provider (gmail, yahoo, hotmail,...), and put the result in a hash. 19 | 20 | ```ruby 21 | group_mails( users ) 22 | => { 23 | "yahoo" => ["bob@yahoo.fr", "bigbox@yahoo.fr"], 24 | "hotmail" => ["roger57@hotmail.fr"], 25 | "lewagon" => ["boris@lewagon.org"], 26 | "gmail" => ["monsieur.olivier@gmail.com", "monsieur.mack@gmail.com"] 27 | } 28 | ``` 29 | 30 | ### Improve your hash using symbols 31 | Change your function `group_mails` to use symbols instead of strings for keys. 32 | 33 | * Let's say you have new users in you array input. 34 | * If you group again the emails with this new input, what's the interest of using symbols as keys ? 35 | 36 | ### Add some functionality 37 | Write a method `has_provider?(user_array, provider)` which takes a provider name as input, and tells you whether or not you have emails from that provider in your user array. For instance, with or previous array 38 | 39 | ```ruby 40 | has_provider?(users, "gmail") # => true 41 | has_provider?(users, "lewagon") # => true 42 | has_provider?(users, "noos") # => false 43 | ```` 44 | You should write this method 2 different ways : 45 | * starting from the initial user array 46 | * using the hash resulting from your first provider grouping method, thhis should take **1line** using this method. 47 | 48 | *Be carefull, "john.gmail@hotmail.fr" has not the Gmail provider :)* 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Wagon-3/02. Provider grouping/provider_grouping.rb: -------------------------------------------------------------------------------- 1 | def group_mails( emails ) 2 | # your code goes here 3 | end 4 | 5 | users_emails = %w( bob@yahoo.fr 6 | roger57@hotmail.fr 7 | bigbox@yahoo.fr 8 | boris@lewagon.org 9 | monsieur.olivier@gmail.com 10 | monsieur.mack@gmail.com ) 11 | 12 | 13 | puts group_mails( users_emails ) 14 | 15 | # => {"yahoo" => ["bob@yahoo.fr", "bigbox@yahoo.fr"], 16 | # "hotmail" => ["roger57@hotmail.fr"], 17 | # "lewagon" => ["boris@lewagon.org"], 18 | # "gmail" => ["monsieur.olivier@gmail.com", 19 | # "monsieur.mack@gmail.com"]} 20 | -------------------------------------------------------------------------------- /Wagon-3/03. A translation story/README.md: -------------------------------------------------------------------------------- 1 | You have this global object: 2 | ```ruby 3 | $strings = { 4 | home: { 5 | intro: { 6 | en: 'Welcome on Le Wagon', 7 | fr: 'Bienvenue sur Le Wagon' 8 | }, 9 | content: { 10 | explanation: { 11 | en: 'This is an interesting exercise', 12 | fr: 'C\'est un exercice interessant', 13 | de: 'Es ist eine interesante Übung' 14 | }, 15 | goodbye: { 16 | en: 'Goodbye', 17 | fr: 'Au revoir', 18 | es: 'Adios' 19 | } 20 | } 21 | } 22 | } 23 | ```` 24 | 25 | Write a function `getTranslation` that handle translations the following way 26 | 27 | ```ruby 28 | > getTranslation('home.intro', 'fr') // => 'Bienvenue sur Le Wagon' 29 | > getTranslation('home.intro', 'es') // => 'Welcome on Le Wagon' 30 | > getTranslation('home.content.goodbye') // => 'Goodbye' 31 | > getTranslation('unvalid.path','en') // => '' 32 | ```` 33 | So the first argument is a string that describes the path through the keys separated by a dot (we assume no dots in keys), and the second argument is the language, which falls back to 'en' if it's not provided or it does not exist (we also assume that at the end of every branch, either the 'en' keys exists, or it is a single string like in home.content.contact). 34 | 35 | -------------------------------------------------------------------------------- /Wagon-3/03. A translation story/translation.rb: -------------------------------------------------------------------------------- 1 | $strings = { 2 | home: { 3 | intro: { 4 | en: 'Welcome on Le Wagon', 5 | fr: 'Bienvenue sur Le Wagon' 6 | }, 7 | content: { 8 | explanation: { 9 | en: 'This is an interesting exercise', 10 | fr: 'C\'est un exercice interessant', 11 | de: 'Es ist eine interesante Übung' 12 | }, 13 | goodbye: { 14 | en: 'Goodbye', 15 | fr: 'Au revoir', 16 | es: 'Adios' 17 | } 18 | } 19 | } 20 | } 21 | 22 | def getTranslation(a_string, a_language) 23 | # your code goes here 24 | end 25 | 26 | # testing your program 27 | 28 | getTranslation('home.intro', 'fr') == 'Bienvenue sur Le Wagon' # => true 29 | getTranslation('home.intro', 'es') == 'Welcome on Le Wagon' # => true 30 | getTranslation('home.content.goodbye') == 'Goodbye' # => true 31 | getTranslation('unvalid.path','en') == '' # => true -------------------------------------------------------------------------------- /Wagon-3/04. Phone regexp/README.md: -------------------------------------------------------------------------------- 1 | ## Objectives 2 | 3 | An exercise to learn how to use regular expressions in ruby. First learn more about [regular expressions](http://en.wikipedia.org/wiki/Regular_expression) 4 | 5 | 6 | Write a program that checks if a phone number is a valid french number. 7 | * A french phone number should contain 10 numbers starting with 0, or 12 numbers starting with +33 8 | * Also you can accept phone number with delimiters between numbers (space, or "-" ). 9 | 10 | ```ruby 11 | is_valid_phone_number("0665363636") 12 | => true 13 | 14 | is_valid_phone_number("06 65 36 36") 15 | => false 16 | ``` 17 | 18 | ## Help 19 | [http://rubular.com/](http://rubular.com/) -------------------------------------------------------------------------------- /Wagon-3/04. Phone regexp/check_phone.rb: -------------------------------------------------------------------------------- 1 | # Check your 06 2 | 3 | # Writes a program that checks if a phone number is a valid french number. 4 | # A french phone number should contain 10 numbers and starting with 0 or 12 numbers starting with +33 5 | # Also you can accept phone number with delimiters between numbers. 6 | 7 | # Objective 8 | # How to use regex 9 | 10 | 11 | # Help 12 | # http://rubular.com/ 13 | 14 | 15 | def is_valid_phone_number(phone_number) 16 | # your code here 17 | end 18 | 19 | 20 | 21 | # tests 22 | 23 | puts is_valid_phone_number("0665363636") # should output true 24 | puts is_valid_phone_number("06 65 36 36 36") # should output true 25 | puts is_valid_phone_number("06-65-36-36-36") # should output true 26 | puts is_valid_phone_number("+33 6 65 36 36 36") # should output true 27 | 28 | puts is_valid_phone_number("06 65 36 36") # should output false 29 | puts is_valid_phone_number("2336653636") # should output false -------------------------------------------------------------------------------- /Wagon-3/05. csv parsing/README.md: -------------------------------------------------------------------------------- 1 | To read in a csv file and extract its data you can use the csv package that comes with ruby standard library. 2 | 3 | ## Ruby Standard Library 4 | The [Ruby standard library](http://www.ruby-doc.org/stdlib-2.0.0/) includes all the convenient packages that come with your ruby installation. For instance the [cmath](http://www.ruby-doc.org/stdlib-2.0.0/libdoc/cmath/rdoc/index.html) package, if included in your ruby program, enables you to make computations on complex numbers. You include a package with `require` and then you can use its function 5 | 6 | ```ruby 7 | require "cmath" 8 | CMath.sqrt(-9) #=> 0+3.0i 9 | ``` 10 | You have very usefull ruby packages in the standard library to 11 | * read/write/parse files of different format (JSON, XML, CSV,...) 12 | * use custom and convenient data stucture as YAML 13 | * build HTTP server (webrick library) 14 | * and so on.. 15 | 16 | ## Back to our cookbook 17 | Write a program that takes the recipe file as input and works this way : 18 | ``` 19 | > ruby cookbookpro.rb 20 | We have recipes for : 21 | - Entree 22 | - Plat Principal 23 | - Dessert 24 | - Sauce 25 | 26 | Which category are you interested in ? 27 | 28 | > Plat Principal 29 | 30 | Here are the recipes of the category : Plat Principal 31 | - Poule au pot 32 | - Lotte a l'armoricaine 33 | - Bar roti 34 | - Boeuf bourguignon 35 | - Poulet basquaise 36 | - Pot-au-feu 37 | - Couteaux a la plancha 38 | 39 | Now which recipe ? 40 | 41 | > Pot-au-feu 42 | Pot-au-feu 43 | ************************************ 44 | difficulty : difficile 45 | preparation : 20 min 46 | cooking : 3h 47 | ************************************ 48 | ``` 49 | 50 | ## What if ? 51 | How will you handle the case of the user entering a wrong category/recipe (either typo, or category/recipe not existing..) ? 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Wagon-3/05. csv parsing/parsing_recipes.rb: -------------------------------------------------------------------------------- 1 | require 'csv' 2 | 3 | # your code goes here -------------------------------------------------------------------------------- /Wagon-3/05. csv parsing/recipes.csv: -------------------------------------------------------------------------------- 1 | Poule au pot,Plat Principal,20,90,1 2 | Lotte a l'armoricaine,Plat Principal,30,120,2 3 | Sauce hollandaise,Sauce,15,5,3 4 | Mayonnaise,Sauce,10,0,2 5 | Bar roti,Plat Principal,15,60,1 6 | Vinaigrette,Sauce,10,0,1 7 | Sauce cocktail,Sauce,10,0,2 8 | Boeuf bourguignon,Plat Principal,30,150,3 9 | Poulet basquaise,Plat Principal,20,60,1 10 | Pot-au-feu,Plat Principal,20,180,3 11 | Couteaux a la plancha,Plat Principal,0,5,3 12 | Charlotte aux fraises,Dessert,30,60,3 13 | Frisee aux lardons,Entree,10,10,1 14 | Îufs mimosa,Entree,10,0,1 -------------------------------------------------------------------------------- /Wagon-3/06. Playing with strings/README.md: -------------------------------------------------------------------------------- 1 | Write a method that determines whether a given word or phrase is a palindrome, that is, it reads the same backwards as forwards, ignoring case, punctuation, and nonword characters. A "nonword character" is defined for our purposes as "a character that Ruby regexps would treat as a nonword character". 2 | 3 | Source: [Ruby Calisthenic, A. Fox & D. Patterson](http://www.ebc.com.br/sites/default/files/hw1rubycalisthenics.pdf) 4 | 5 | ## Objectives 6 | 7 | ## Tips 8 | Methods you might find useful (which you'll have to look up in Ruby documentation, ruby-doc.org) include : `String#downcase, String#gsub, String#reverse` 9 | 10 | ## Enhance/Refactor 11 | Once you have your code working, consider making it more beautiful by using techniques like method chaining. 12 | 13 | ## Resources 14 | + ruby documentation : http://ruby-doc.org 15 | + To try out ruby regular expressions "live" : http://rubular.com -------------------------------------------------------------------------------- /Wagon-3/06. Playing with strings/palindrome.rb: -------------------------------------------------------------------------------- 1 | def palindrome?(a_string) 2 | # return true if a_string is a palindrome / false otherwise 3 | end 4 | 5 | 6 | # Testing palindrome? function 7 | puts "#{palindrome?("A man, a plan, a canal -- Panama")}" #=> true 8 | puts "#{palindrome?("Madam, I'm Adam!")}" # => true 9 | puts "#{palindrome?("Abracadabra")}" # => false -------------------------------------------------------------------------------- /Wagon-3/07. Extend built-in classes/README.md: -------------------------------------------------------------------------------- 1 | * Write a function `factorial( an_integer )` which returns the factorial of this integer. Remember what's a factorial ? 2 | 3 | ``` 4 | 6! = 6 x 5 x 4 x 3 x 2 x 1= 720 5 | ``` 6 | 7 | * Now re-write this as a method on the `Integer` class, so that you can call `6.factorial` instead of calling `factorial(6)`. 8 | 9 | ## Ask yourself ? 10 | 11 | * What's the "philosophical" difference between these two approaches ? what's the philosophy behind OOP ? You should read about [programming paradigms](http://en.wikipedia.org/wiki/Programming_paradigm) to understand such differences. 12 | 13 | * It feels that we re-defined the Integer class giving it a poor definition with just one factorial method in it.. What really happened ? Google "ruby open class" to understand what is at stake ! 14 | 15 | ## Extra 16 | Extend the `Array` class adding a shuffle method to it ! 17 | -------------------------------------------------------------------------------- /Wagon-3/07. Extend built-in classes/extend_built-in.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beub/ruby/7d371b94972a2a5964c13cb59b5b2c862d251d71/Wagon-3/07. Extend built-in classes/extend_built-in.rb -------------------------------------------------------------------------------- /Wagon-4/01. Text Analyzer/README.md: -------------------------------------------------------------------------------- 1 | You are going to develop a text analyzer. Your ruby program will read a text supplied in a separate file, analyze it for varous patterns and statistics, and print out the result for the user. It's not a fancy 3D application but text processing programs are the bread and butter of most application development. 2 | 3 | Ruby is well suited for text and document analysis with its regular expression features along with the eas of use of `scan` and `split`. You'll use these heavily in your application. 4 | 5 | ### Required features 6 | * character count (including **and** excluding spaces) 7 | * Line count 8 | * Word count 9 | * Sentence count 10 | * Paragraph count 11 | * Average number of words per sentence 12 | * Average number of sentences per paragraph 13 | In the two last cases, statistics are easily calculated from each other, giving the first counters. 14 | 15 | ### Build the application flow 16 | 1. Load the file containing the text document to analyze 17 | 2. As you load it keep a count of the number of lines there were 18 | 3. Put the text into a string and measure its length to get a character count 19 | 4. Temporarily remove white spaces and count characters excluding spaces 20 | 5. Split out all the whitespaces to find out how many words there are 21 | 6. Split out full stops to find out the nuber of sentences 22 | 7. Split out double newlnes to calculate number of paragraph 23 | 8. Work out the averages using all your counters. 24 | 25 | ### Testing data 26 | You can get some testing txt data on http://www.rubyinside.com/book/oliver.txt 27 | 28 | ### Adding Extra-features 29 | Your analyzer in not particularly interesting at the moment :( Let's add it some cool features. Line, paragraph and word count are useful statistics, but with the power of ruby you can perform much cooler analysis. The ony limit is your imagination ! 30 | 31 | * **percentage of "useful" words** : most written material contains insipid words as "the", "are",.. These are called stop-words and are often ignored by computer systems whose job is to analyze and search through text, because they aren't words most people are likely to be searching for (Google beign a perfect example of that). It can be argued that texts with a high ratio of "useful" words (as opposed with stop-words) are likely to be more interesting, this is a true debate :) Add a statistics in your analyzer to compute the percentage of "useful" words in the inputed text file. 32 | 33 | * **Interesting summary** : Word processors as Microsoft Word generally have summarization feature that can pick out the most meaningfull extract in a given page and produce an "at-glance" summary. One of the techniques to find the good extract is to pick up sentences that are of about average length and contains **nouns**. Tiny sentences are likely not to be very useful, and long sentences may be too long for a summary. To see if the sentences includes nouns you can look for words like "is" or "are" which are a good indicators ("There are x nouns", "Noun is", "Nouns are",...). **Tips** you should decide first which proportion of the original text you keep for your summary (for instance computed an the number of sentences). -------------------------------------------------------------------------------- /Wagon-4/02. RPS/README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | In a game of rock-paper-scissors, each player chooses to play Rock (R), Paper (P), or Scissors (S). The rules are: Rock beats Scissors, Scissors beats Paper, but Paper beats Rock. A rock-paper-scissors game is encoded as a list, where the elements are 2-element lists that encode a player’s name and a player’s strategy. 3 | ``` 4 | [ [ "Bob", "P" ], [ "Mack", "S" ] ] 5 | # => returns the list ["Mack", "S"] wins since S>P 6 | ``` 7 | 8 | Write a method `rps_game_winner` that takes a two-element list and behaves as follows: 9 | + If the number of players is not equal to 2, raise WrongNumberOfPlayersError 10 | + If either player's strategy is something other than "R", "P" or "S" (case-insensitive), raise NoSuchStrategyError 11 | + Otherwise, return the name and strategy of the winning player. If both players use the same strategy, the first player is the winner. 12 | 13 | A rock, paper, scissors tournament is encoded as a bracketed array of games - that is, each element can be considered its own tournament. 14 | ```ruby 15 | tournament = [ 16 | [ 17 | [ ["Bob", "P"], ["Mack", "S"] ], 18 | [ ["Olive", "R"], ["Ben", "S"] ] 19 | ], 20 | [ 21 | [ ["Mathieu", "S"], ["Romain", "P"] ], 22 | [ ["Wally", "R"], ["Marty", "P"] ] 23 | ] 24 | ] 25 | ``` 26 | Under this scenario, Mack would beat Bob (S>P), Olive would beat Ben (R>S), and then Mack and Olive would play (Olive wins since R>S); similarly, Mathieu would beat Romain, Marty would beat Wally, and Mathieu and Marty would play (Mathieu wins since S>P); and finally Olive would beat Mathieu since R>S, that is, continue until there is only a single 27 | winner. 28 | 29 | + Write a method rps_tournament_winner that takes a tournament encoded as a bracketed array and returns the winner (for the above example, it should return [“Olive”, “R”]). 30 | + Tournaments can be nested arbitrarily deep, i.e., it may require multiple rounds to get to a single winner. You can assume that the initial array is well formed (that is, there are 2^n players, and each one participates in exactly one match per round). 31 | 32 | ## Tip 33 | * Using recursion (http://en.wikipedia.org/wiki/Recursion_(computer_science)) is cleaner ! 34 | * Try to understand the conceptual difference between recursion and [iteration](http://en.wikipedia.org/wiki/Iteration#Computing). 35 | -------------------------------------------------------------------------------- /Wagon-4/02. RPS/rps.rb: -------------------------------------------------------------------------------- 1 | class WrongNumberOfPlayersError < StandardError ; end 2 | class NoSuchStrategyError < StandardError ; end 3 | 4 | def rps_game_winner(game) 5 | raise WrongNumberOfPlayersError unless game.length == 2 6 | # your code here 7 | "not implemented yet !" 8 | end 9 | 10 | 11 | def rps_tournament_winner(tournament) 12 | # your code here 13 | "not implemented yet !" 14 | end 15 | 16 | # Testing winner of a single game 17 | single_game = [ [ "Bob", "P" ], [ "Mack", "S" ] ] 18 | puts rps_game_winner(single_game) 19 | 20 | # Testing winner of the tournament ! 21 | tournament = [ 22 | [ 23 | [ ["Bob", "P"], ["Mack", "S"] ], 24 | [ ["Olive", "R"], ["Ben", "S"] ] 25 | ], 26 | [ 27 | [ ["Mathieu", "S"], ["Romain", "P"] ], 28 | [ ["Wally.", "R"], ["Marty", "P"] ] 29 | ] 30 | ] 31 | puts rps_tournament_winner(tournament) -------------------------------------------------------------------------------- /Wagon-4/03. Numbers and Letters/README.md: -------------------------------------------------------------------------------- 1 | I am sure you have already watched "Des chiffres et des lettres". The goal of this challenge is to write a simplified version of this game from the terminal where : 2 | 3 | * you are given a random word-grid. 4 | * you have to enter the longest english word you can find using only letters of this grid. 5 | * after typing your best shot, you get your score altogether with the french definition of the word you picked up. 6 | 7 | Here is how this should work 8 | 9 | ``` 10 | ******** Welcome to the longest word-game !!******** 11 | Here is your grid : 12 | Q E F G A J P S N 13 | ***************************************************** 14 | What's your best shot ? 15 | gaps 16 | ***************************************************** 17 | You took 11.010275 seconds to answer ! 18 | Your word 'gaps' means: trou 19 | 4 Points 20 | ***************************************************** 21 | ``` 22 | 23 | This challenge will let you access a web-API, and parse JSON data returned by this API !! Pas mal de fun en perspective :) 24 | 25 | ## Tools ! 26 | This challenge is deliberately not guided. Here are some elements that will help you 27 | * Write the pseudo code to figure out how to proceed before diving into the code 28 | * You should use the [word-reference](http://www.wordreference.com/docs/api.aspx) api to get word french translation, in JSON format. In our code canvas, we give you our API key but you can also create your own key very easily ! 29 | * You should use the `open-uri` package from ruby standard library to make requests to this API and get the JSON result 30 | * You should use the `json` package to parse returned JSON files. 31 | * You should use the `rand` method or the array `shuffle` method to generate a random grid 32 | 33 | ## Make it funnier and more robust 34 | * How do you deal with wrong user entries ? or non-english words ? 35 | * What about making a funnier game with several rounds ? 36 | * What about adding a time penalty ? Which rules to choose for this penalty ? 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Wagon-4/03. Numbers and Letters/game.rb: -------------------------------------------------------------------------------- 1 | # Split your main method into several small ones 2 | # Each sub-method should accomplish a single task 3 | 4 | def run_game 5 | # your code goes here 6 | end 7 | 8 | # Running the game ! 9 | run_game 10 | -------------------------------------------------------------------------------- /Wagon-4/04. Blogging with Jekyll/README.md: -------------------------------------------------------------------------------- 1 | ### What's a gem ? 2 | First read these two articles 3 | * this [stackoverflow question](http://stackoverflow.com/questions/5233924/what-is-a-ruby-gem) for the overall definition 4 | * this [rubygems doc](http://guides.rubygems.org/rubygems-basics/) to go into the details 5 | 6 | Remember the packages we used from ruby standard library (csv, open-uri..)? 7 | Well, the gem system enables anyone to create similar packages, host them on rubygems.org, and make them accessible for any other ruby developer very easily ! cool, isn't it ? 8 | 9 | As you might expect, a gem must then respect a standardize structure. Thanks to these standards, the gem is ready-to-use, but also easy to maintain and version (if the gem evolves). 10 | 11 | As you will see, **when you want to do something in ruby / Rails, and when you have no clues where to start, there's often a gem to do the job !** 12 | 13 | ### Cool gem examples 14 | * APIs and parsing : twitter / koala / nokogiri 15 | * Markdown : RedCarpet / GFM 16 | * Blog : jekyll 17 | * HTML form : SimpleForm 18 | 19 | See : http://tenmiles.com/blog/2012/06/25-ruby-on-rails-gems-for-rapid-prototyping/ 20 | 21 | ### Make your own blog with jekyll 22 | Use the [jekyll](http://jekyllrb.com/) gem to create your blog. 23 | 24 | ### Deploy it on Github pages 25 | Now you can really simply push it on [Github pages](https://help.github.com/articles/creating-project-pages-manually). From now on : 26 | * You don't need some un-customizable tumblr any more :) 27 | * you have your own simple blog, clean and usefull. 28 | * You can add posts easily (and from the source) using [Markdown](http://daringfireball.net/projects/markdown/syntax). 29 | * Your can enhance your design in your blog CSS. 30 | * It's deployed on Github pages, you just have to buy a custom domain name if you want, and link it to your Github pages URL. 31 | 32 | **For submission, you should show us your blog deployed on the web, and you should have written a first article using markdown on something you learned this week !** -------------------------------------------------------------------------------- /Wagon-4/05. Bad-ass DRY gym/README.md: -------------------------------------------------------------------------------- 1 | Here is a program that prints out the number of calories in a McDonald meal. But it's not very [DRY](http://fr.wikipedia.org/wiki/Ne_vous_r%C3%A9p%C3%A9tez_pas) ! How would you do to improve it ? 2 | 3 | Here are some thoughts that might be interesting. 4 | * First look at the parts that are repeated in the program. How can you do to factor these parts ? 5 | * If you decide to group these parts in one single function, what's the issue with the `calories` variable ? Learn about variable scope ! 6 | * Could you change this variable to a constant ? what will be the issue of such solution ? 7 | * Could you change it to a global variable ? Again, what will be the issue ? 8 | * You should then consider using a `Proc` object to store a ruby block of instruction. Learn about [closures](http://en.wikipedia.org/wiki/Closure) and try to understand the difference between a method and a Proc, and why a Proc is more adapted in that case. -------------------------------------------------------------------------------- /Wagon-4/05. Bad-ass DRY gym/dry_gym.rb: -------------------------------------------------------------------------------- 1 | # create a mapping between calories and McDonald products 2 | calories = { 3 | 'Cheese Burger' => 290, 4 | 'Big Mac' => 350, 5 | 'Mc Bacon' => 400, 6 | 'French fries' => 230, 7 | 'Potatoes' => 190, 8 | 'Coca' => 160, 9 | 'Sprite' => 170 10 | } 11 | 12 | meal = ['Cheese Burger','French fries','Sprite'] 13 | total_calories = meal.inject(0){ |cal, product| calories[product] + cal } 14 | puts "There are #{total_calories} calories in your meal : #{meal.join(" + ")}" 15 | 16 | # A new Burger ! The Filet-of-Fish 17 | calories['Filet of Fish'] = 100 # Let's add it 18 | meal[0] = 'Filet of Fish' # We want to taste it, so we replace our old cheap Cheese Burger 19 | total_calories = meal.inject(0){ |cal, product| calories[product] + cal } 20 | puts "There are #{total_calories} calories in your meal : #{meal.join(" + ")}" --------------------------------------------------------------------------------