Skip to content

Instantly share code, notes, and snippets.

@roschaefer
Last active May 24, 2016 14:05
Show Gist options
  • Save roschaefer/11a214c456dbbd2cc51d to your computer and use it in GitHub Desktop.
Save roschaefer/11a214c456dbbd2cc51d to your computer and use it in GitHub Desktop.
Challenges
#######################################################################
# Programming challenge 1: Christmas Tree #
# To solve this challenge you need to know how to iterate over arrays #
# Also, you need to know how to print with 'puts' or 'print' #
# And finally basic arithmetic operations like 1 * 2 or 1 + 2 #
#######################################################################
# TODO: Paint a christmas tree on the command line which is 'lines' long
# TODO: This is how the christmas tree looks like for 20 lines
#
# *
# ***
# *****
# *******
# *********
# ***********
# *************
# ***************
# *****************
# *******************
# *********************
# ***********************
# *************************
# ***************************
# *****************************
# *******************************
# *********************************
# ***********************************
# *************************************
# ***************************************
# ||
#
# TODO: You should be able to change only this variable to print a bigger tree
lines = 20
# TODO: To give you a starting point:
# TODO Let's say we have a number X
# TODO: Then you can run a code block X times like so
lines.times do
puts "Gets printed " + lines.to_s + " times"
end
# TODO: You can assign a variable |i| to get the current step counter
lines.times do |i|
puts "The current step is : " + i.to_s
end
#######################################################################
# Programming challenge 2: Guess my number #
# To solve this challenge you need to know how to use a 'while' loop #
# You need to know how to get user input from the command line #
# Also how to normalize the input (removing trailing whitespaces) #
# You should know about if-clauses and numeric comparisons, like '>' #
# How to write methods #
# And you should know what sequences are, e.g. 1..100 #
#######################################################################
class Chooser
def initialize(lower_bound, upper_bound)
@number = rand(lower_bound..upper_bound)
@steps = 0
end
def guess(number)
@steps = @steps + 1
if (@number == number)
puts "Congratulations, the number is #{@number} and you needed #{@steps} steps!"
return "correct"
elsif @number > number
return "greater"
else
return "smaller"
end
end
end
def ask_human(chooser, lower_bound, upper_bound)
response = ""
while response != "correct"
# TODO: ask the user for input!
# TODO: you can convert a string "42" to the number 42 by calling "42".to_i
end
end
def computer_search(chooser, lower_bound, upper_bound)
# TODO: implement a smarter solution than just guessing randomly
response = ""
while response != "correct"
# 'rand' generates a random number in a sequence
# you don't need to know how it works
# because you can replace it with sth. better
a_number = rand(lower_bound..upper_bound)
response = chooser.guess(a_number)
end
end
lower_bound = 1
upper_bound = 100
chooser = Chooser.new(lower_bound, upper_bound)
# TODO: implement and call 'ask_human'
#ask_human(chooser, lower_bound, upper_bound)
computer_search(chooser, lower_bound, upper_bound)
################################################################################
# Programming challenge 3: Advanced User Input #
# To solve this challenge you need to know about arrays and hashes #
# You should know how to use 'puts' and 'gets' #
# And you should know how to use blocks and certain methods like 'select' etc. #
################################################################################
group_template = {
:where => {:city => ["Berlin", "Potsdam", "Hamburg", "Munich"]},
:when => {:weekday => ["Mo", "Tue", "Wed","Thu","Fr"],
:time => ["18:30", "19:00", "19:30"],
}
}
# TODO: Add more groups to 'ruby_groups' from the website 'rorganize.it'
# TODO: http://rorganize.it/groups
ruby_groups = []
ruby_groups << {
:name => "Rubies-in-the-woods",
:where => {:city => "Potsdam"},
:when => {:weekday => "Tue",
:time => "18:30"}
}
ruby_groups << {
:name => "RubyMonstas",
:where => {:city => "Berlin"},
:when => {:weekday => "Mo",
:time => "19:00"}
}
ruby_groups << {
:name => "rubycorns",
:where => {:city => "Berlin"},
:when => {:weekday => "Tue",
:time => "19:00"}
}
def choose_from(hash, key)
hash[key].each_with_index do |option, index|
puts "#{index+1}. #{option}"
end
choosen = hash[key][Integer(gets.chomp)-1]
hash[key] = choosen
# NOTE: This function has side effects
# NOTE: because we change the argument 'hash' directly
end
preferred_options = group_template
puts "Hello lovely user! Do you want to learn programming with ruby?"
puts "There are many ruby learners groups out there, let's find one!"
puts "What's the city you live in?"
choose_from(preferred_options[:where], :city)
puts "Which day of the week do you prefer?"
choose_from(preferred_options[:when], :weekday)
puts "Now choose a time slot from below:"
choose_from(preferred_options[:when], :time)
puts "Thank you!"
matching_groups = []
#matching_groups = ???? TODO: find matching groups!
# TODO: First, see how the hash 'preferred_options' looks like
# TODO: E.g. with 'p preferred_options'
# TODO: The goal is to find groups that match the 'preferred_options' hash
# TODO: You can compare two hashes e.g. with '=='
# TODO: But if you do that, no group will match, because these hashes have the
# TODO: key :name, which is missing in the 'preferred_options' hash
# TODO: What can we do here?
# NOTE: As a tip: check out the documentation for 'Hash#reject'
# NOTE: http://ruby-doc.org/core-2.1.5/Hash.html#method-i-reject
puts "The following groups were found"
matching_groups.each_with_index do |group, index|
puts "#{index+1}. #{group[:name]}"
end
# TODO: Print a better message if no groups were found
################################################################################
# Programming challenge 5: Ruby regexes #
# For this programming exercise, you must know regular expressions #
# How to read and write to files #
# And how to get the first element of an array #
################################################################################
# This programming exercise is a real world example of ruby in action.
# A friend of mine, who is working as a journalist, spent nearly two hours
# manually replacing html tags on a website.
# His task was to copy html from one site to another and to fix the footnotes:
# http://isj.org.uk/the-internationalist-case-against-the-european-union/
# http://europeonthestrand.ideasoneurope.eu/
#
# In order to make the backlinks working, the links that looked like this:
# <a id="footnote-263-72-backlink" href="http://blabla/#footnote-263-72">72</a>
# Must be transformed to into two separate links that look like this:
# <a id="backlink-72"></a><a href="#72">[72]</a>
#
# We can solve this problem automatically with so called regular expressions:
# http://ruby-doc.org/core-2.1.1/Regexp.html
# https://en.wikipedia.org/wiki/Regular_expression
# TODO: Important! Before you run this script, you must save the whole website
# TODO: http://isj.org.uk/the-internationalist-case-against-the-european-union/
# TODO: into a file 'input.html' in the same directory!
# We open a certain file and read the content into a string called 'text'
text = File.open("input.html", 'rb') do |f|
f.read
end
# If we have the file opened with a block, it automatically closes the file
# after reading. See: http://ruby-doc.org/core-2.1.4/File.html#method-c-open
# Why is it important to close files? See: http://stackoverflow.com/q/8175827
# Here we initialize a regular expression in ruby:
pattern = %r{<a id="footnote-263-(\d+)-backlink" href=".*#footnote-263-\d+">\d+</a>}
# See: http://ruby-doc.org/core-2.1.1/Regexp.html
# There are two possible syntax variations for regular expressions:
# %r{ ... } or / ... / or you can use the explicit constructor: Regexp.new(...)
#
# What is the meaning of the special characters here? There is a nice online
# tester for ruby regular expressions: http://rubular.com/ wich also features an
# overview of all the special character groups.
# So in this case, \d means any decimal digit, \d+ means many decimal digits but
# at least one, .* means any character sequence (even the empty one) and
# everything between paranthesis (..) is a 'group'.
# Ruby strings have a method #gsub (global substitution) that expects a regular
# expression as a parameter and substitutes matches with the result of a block
result = text.gsub(pattern) do |footnote|
# Some debug output. The 'footnote' is the match of the pattern here.
puts "Footnote: "
puts footnote
# The method Regexp#match returns a matchdata object, that contains all the
# different groups of the matched regex.
match_data = pattern.match(footnote)
# You can use this line of code to have a look of the elements of it:
#puts match_data.to_a.inspect
# TODO: We want to extract the id of the backlink here:
number = '' #TODO: What element of the match data is our backlink id??
# TODO: After we extracted the number, we want to replace the whole match
# TODO: Create a string and put the number at the correct position!
# TODO: The final string should look somehow like this:
replacement = %{<a id="backlink-72"></a><a href="#72">[72]</a>}
# TODO: But of course '72' must be replaced with the extracted number
# NOTE: Ah, and %{...} is just another syntax for strings, so we don't have
# NOTE: to escape so many quotation marks with backslashes \"
# NOTE: https://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#Strings
# More debug output.
puts "Replacement"
puts replacement
puts # ----- empty line -----
replacement # last line of the block is the final replacement of the match
end
# Write the output to a file called 'output.html' and close it
File.open("output.html", 'w') do |f|
f.write(result)
end
#################################################################################
## Programming challenge 6: Rendering templates in Sinatra #
## For this programming exercise you should have created a 'hello world' #
## program in sinatra and you should know what routes are #
## Learn more about sinatra here: http://www.sinatrarb.com/intro.html #
## Short ERb overview: http://fireapp.kkbox.com/doc/tutorial_2.html #
#################################################################################
require 'sinatra'
class Person
attr_reader :first_name, :last_name, :phone_number # a person has these 3 methods
def initialize(name, phone_number)
@first_name, @last_name = name.split(" ")
@phone_number = phone_number
end
end
get '/' do
@participants = [
Person.new("Laura Liegener" , 999) ,
Person.new("Leo Eckwert" , 123) ,
Person.new("Meike Fischer" , 567) ,
]
erb :index
end
# TODO: Copy the following code into a file called views/index.erb
=begin
<table>
<tr>
<th> First Name </th>
<th> Last Name </th>
<th> Phone Number </th>
</tr>
<tr>
<td> TODO: Dynamically </td>
<td> create a row </td>
<td> for every entry in @participants! </td>
</tr>
<tr>
<td> How can you do that? </td>
<td> ... here is just one example: </td>
<td> <a href="https://teamtreehouse.com/community/loop-through-array-in-an-erb-template">Follow this link!</a> </td>
</tr>
<tr>
<td> E.g. display the first name </td>
<td> ... the last name here </td>
<td> ... and the phone number </td>
</tr>
</table>
=end
################################################################################
## Programming challenge 7: Using different routes for post and get requests ##
## The goal of this challenge is to use a post request to distinguish if the ##
## user has just visited the root page '/' or refreshed it, or if the user is ##
## attempting to solve the secret (she sends a character to the server). ##
## You will need to know how to handle post requests and redirect to a get ##
## request from there. Learn more about it: ##
## http://www.sinatrarb.com/intro.html#Routes ##
## http://www.sinatrarb.com/intro.html#Browser%20Redirect ##
################################################################################
require 'sinatra'
secret = "Erdbeermarmelade"
guesses = []
missed_guesses = 0
get("/") do
guesses << params["character"]
unless secret.chars.include? params["character"]
missed_guesses += 1
end
# TODO: How can we split this request to handle the delivered paramters in a
# 'post' route and render the :interface template in a get route?
# TODO: How can we immediately render the :interface template after processing
# the parameters?
@secret = secret
@missed_guesses = missed_guesses
@guesses = guesses
erb :interface
end
# TODO: put this code into a file called 'interface.erb' in folder 'views'
# TODO: What has to be changed in order to send the parameters as a post request
# instead of URL parameters?
# TODO: How can we limit the number of characters in the text input field?
# TODO: See http://www.w3schools.com/tags/att_input_size.asp
=begin
<body>
Missed guesses <%= @missed_guesses %>
<% if @missed_guesses <= 8 %>
<form action="/" method="get">
Guess a character: <input type="text" name="character"><br>
<input type="submit" value="Submit">
</form>
<% @secret.chars.each do |c| %>
<% if @guesses.include? c %>
<%= c %>
<% else %>
_
<% end %>
<% end %>
<% end %>
</body>
=end
################################################################################
# Programming challenge 8: Create a simple file server with Sinatra
# Sinatra serves static files by default in the /public folder
# However, as a toy example, you may want to serve static file from another
# folder
#
# Place your files in a folder /downloads
# If a user accesses your web-app, the path in the URL should be matched onto
# this /download folder, ie. http://localhost/to/some/file will be mapped to
# a location on your machine like
# /path/to/your/sinatra/app/downloads/to/some/file
#
# Read:
# http://www.sinatrarb.com/intro.html#Routes
# http://www.rubydoc.info/github/sinatra/sinatra/Sinatra%2FHelpers%3Asend_file
# http://ruby-doc.org/core-1.9.3/File.html#method-c-exists-3F
#
# Beware the security risks! Google for "Path traversal" and "Security"
# So don't deploy your server ;)
################################################################################
require 'sinatra'
# TODO: no template application here ;)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment