I have written ruby function that checks each word in a sentence and returns longest word with its length.
My question is I only want it to return word. I do not want it to return both word and it's length.
Please help and explain how can I make it better.
Thank you
def longest_word(sentence)
words = sentence.split(" ")
frequencies = Hash.new(0)
words.each {|x| frequencies[x] = x.length}
frequencies.max_by{|k,v| v}
end
puts longest_word("short longest")
max_by is the correct idea, but your method can be simpler:
def longest_word(sentence)
sentence.split(/\s+/).max_by(&:size)
end
def longest_word(sentence)
sentence.split.max{|a,b| a.length <=> b.length }
end
puts longest_word("short longest longerer longer")
def longest_word(sentence)
longest_word = ''
sentence.split(' ').each do |word|
if word.length > longest_word.length
longest_word = word
end
end
longest_word
end
def longest_word(sentence)
words = sentence.split(" ").sort_by(&:length)[-1]
end
sentence = %w{I have longest word}
def longest_word(sentence)
longest_word = ''
sentence.each do |word|
longest_word = word if longest_word.length < word.length
end
puts longest_word
end
longest_word(sentence)
=> longest
Related
First of all I beg your pardon if this question already exists, I deeply searched for a solution here but I've been able to find it, nevertheless I feel it's a problem so common that is seems so strange to not find anything here...
My struggle is the following: given an hash, I need to return all the PATHS to each leaf as an array of strings; so, for example:
{:a=> 1} gives ['a']
{:a=>{:b=>3, :c=>4} returns an array with two results: ["a.b", "a.c"]
{:a=>[1, {:b=>2}]} will result in ["a.0", "a.1.b"]
and so on...
I have found only partial solutions to this and with dozens of codelines. like this
def pathify
self.keys.inject([]) do |acc, element|
return acc if element.blank?
if !(element.is_a?(Hash) || element.is_a?(Array))
if acc.last.is_a?(Array)
acc[acc.size-1] = acc.last.join('.')
else
acc << element.to_s
end
end
if element.is_a?(Hash)
element.keys.each do |key|
if acc.last.is_a?(Array)
acc.last << key.to_s
else
acc << [key.to_s]
end
element[key].pathify
end
end
if element.is_a?(Array)
acc << element.map(&:pathify)
end
acc
end
end
But it does not work in all cases and is extremely inefficient. Summarizing: is there any way to "pathify" an hash to return all the paths to each leaf in form of array of strings?
Thank you for the help!
Edited
Adding some specs
for {} it returns []
for {:a=>1} it returns ["a"]
for {:a=>1, :b=>1} it returns ["a", "b"]
for {:a=>{:b=>1}} it returns ["a.b"] (FAILED - 1) got: ["a"]
for {:a=>{:b=>1, :c=>2}} it returns ["a.b", "a.c"] (FAILED - 2) got: ["a"]
for {:a=>[1]} it returns ["a.0"] (FAILED - 3) got: ["a"]
for {:a=>[1, "b"]} it returns ["a.0", "a.1"] (FAILED - 4) got: ["a"]
def show(key, path)
if path.is_a? Array
path.map {|p| "#{key}.#{p}"}
else
path == "" ? key.to_s : "#{key}.#{path}"
end
end
def pathify(input)
if input.is_a? Hash
input.map do |k,v|
sub_path = pathify(v)
show(k, sub_path)
end.flatten
elsif input.is_a? Array
input.map.with_index do |v, i|
sub_path = pathify(v)
show(i, sub_path)
end.flatten
else
""
end
end
def leaf_paths(enum)
return unless [Hash, Array].include? enum.class
[].tap do |result|
if enum.is_a?(Hash)
enum.each { |k, v| result = attach_leaf_paths(k, v, result) }
elsif enum.is_a?(Array)
enum.each_with_index { |elem, index| result = attach_leaf_paths(index, elem, result) }
end
end
end
def attach_leaf_paths(key, value, result)
if (children = leaf_paths(value))
children.each { |child| result << "#{key}.#{child}" }
else
result << key.to_s
end
result
end
This is very similar to https://github.com/wteuber/yaml_normalizer/blob/b85dca7357df00757c471acb5dadb79a53dd27c1/lib/yaml_normalizer/ext/namespaced.rb
So I tweaked the code a bit to fit your needs:
module Leafs
def leafs(namespace = [], tree = {})
each do |key, value|
child_ns = namespace.dup << key
if value.instance_of?(Hash)
value.extend(Leafs).leafs child_ns, tree
elsif value.instance_of?(Array)
value.each.with_index.inject({}) {|h, (v,k)| h[k]=v; h}.extend(Leafs).leafs child_ns, tree
else
tree[child_ns.join('.')] = value
end
end
tree.keys.to_a
end
end
Here is how to use it:
h = {a: [1, "b"], c: {d:1}}
h.extend(Leafs)
h.leafs
# => ["a.0", "a.1", "c.d"]
I hope you find this helpful.
def pathify(what)
paths = []
if what.is_a?(Array)
what.each_with_index do | element, index |
paths+= pathify(element).map{|e| index.to_s + '.' + e.to_s}
end
elsif what.is_a?(Hash)
what.each do |k,v|
paths+= pathify(v).map{|e| k.to_s + '.' + e.to_s}
end
else
paths.append('')
end
paths.map{|e| e.delete_suffix('.')}
end
I am currently developing a small modified version of Hangman in Rails for children. The game starts by randomly generating a word from a text file and the user has to guess the word by entering a four letter word. Each word is the split by each character for example "r", "e", "a", "l" and returns a message on how they are to the word.
Random Generated word is "real"
Input
rlax
Output
Correct, Close, Correct, Incorrect
I have tried other things which I have found online but haven't worked and I am fairly new to Ruby and Rails. Hopefully someone can guide me in the right direction.
Here is some code
def letterCheck(lookAtLetter)
lookAHead = lookAtLetter =~ /[[:alpha:]]/
end
def displayWord
$ranWordBool.each_index do |i|
if($ranWordBool[i])
print $ranWordArray[i]
$isWin += 1
else
print "_"
end
end
end
def gameLoop
turns = 10
turnsLeft = 0
lettersUsed = []
while(turnsLeft < turns)
$isWin = 0
displayWord
if($isWin == $ranWordBool.length)
system "cls"
puts "1: Quit"
puts "The word is #{$ranWord} and You Win"
puts "Press any key to continue"
return
end
print "\n" + "Words Used: "
lettersUsed.each_index do |looper|
print " #{lettersUsed[looper]} "
end
puts "\n" + "Turns left: #{turns - turnsLeft}"
puts "Enter a word"
input = gets.chomp
system "cls"
if(input.length != 4)
puts "Please enter 4 lettered word"
elsif(letterCheck(input))
if(lettersUsed.include?(input))
puts "#{input} already choosen"
elsif($ranWordArray.include?(input))
puts "Close"
$ranWordArray.each_index do |i|
if(input == $ranWordArray[i])
$ranWordBool[i] = true
end
if($ranWordBool[i] = true)
puts "Correct"
else
puts "Incorrect"
end
end
else
lettersUsed << input
turnsLeft += 1
end
else
puts "Not a letter"
end
end
puts "You lose"
puts "The word was #{$ranWord}"
puts "Press any key to continue"
end
words = []
File.foreach('words.txt') do |line|
words << line.chomp
end
while(true)
$ranWord = words[rand(words.length) + 1]
$ranWordArray = $ranWord.chars
$ranWordBool = []
$ranWordArray.each_index do |i|
$ranWordBool[i] = false
end
system "cls"
gameLoop
input = gets.chomp
shouldQuit(input)
end
Something like that:
# Picking random word to guess
word = ['open', 'real', 'hang', 'mice'].sample
loop do
puts "So, guess the word:"
input_word = gets.strip
if word == input_word
puts("You are right, the word is: #{input_word}")
break
end
puts "You typed: #{input_word}"
# Split both the word to guess and the suggested word into array of letters
word_in_letters = word.split('')
input_in_letters = input_word.split('')
result = []
# Iterate over each letter in the word to guess
word_in_letters.each_with_index do |letter, index|
# Pick the corresponding letter in the entered word
letter_from_input = input_in_letters[index]
if letter == letter_from_input
result << "#{letter_from_input} - Correct"
next
end
# Take nearby letters by nearby indexes
# `reject` is here to skip negative indexes
# ie: letter 'i' in a word "mice"
# this will return 'm' and 'c'
# ie: letter 'm' in a word "mice"
# this will return 'i'
letters_around =
[index - 1, index + 1]
.reject { |i| i < 0 }
.map { |i| word_in_letters[i] }
if letters_around.include?(letter_from_input)
result << "#{letter_from_input} - Close"
next
end
result << "#{letter_from_input} - Incorrect"
end
puts result.join("\n")
end
I am working on an events application where i want to filter events depending on the 3 parameters location or starts_at or ends_at in the query string. There can be any one, two or all the parameters in the query string. In i use if-else statement i need to make 6 cases which will make my code clumsy. Rather i am thinking to implement something this way:
class EventsController < ApplicationController
def index
unless params.empty?
unless params[:location].nil?
#events = Event.where("location = ?", params[:location])
end
unless params[:starts_at].nil?
unless #events.empty?
#events = #events.where("start_date = ?", params[:start_date])
else
#events = Event.where("Date(starts_at) = Date(?)", params[:starts_at])
end
end
unless params[:ends_at].nil?
unless #events.empty?
#events = #events.where("end_date = ?", params[:end_date])
else
#events = Event.where("Date(ends_at) = Date(?)", params[:ends_at])
end
end
end
end
end
But this code doesnt work since where query doen not work on an array. Can someone suggest me some solution for this..
You should be able to pass your params hash directly to where, and it will form the correct SQL based on the keys and values of that hash:
Event.where(params)
An example in the console:
1.9.3p194 :001 > puts Example.where(:location => 'here', :started_at => '2012-08-13').to_sql
SELECT "examples".* FROM "examples" WHERE "examples"."location" = 'here' AND "examples"."started_at" = '2012-08-13'
Try Following
def index
unless params.empty?
where_array, arr = [], []
if params[:location]
where_array << "location = ?"
arr << params[:location]
end
if params[:starts_at]
where_array << "start_date = ?"
arr << params[:starts_at]
end
if params[:ends_at]
where_array << "end_date = ?"
arr << params[:ends_at]
end
#events = arr.blank? ? [] : Event.where([where_array.join(" AND "), *arr])
end
end
I wanted to check if a string is palindrome or not using ruby code.
I am a starter in ruby so not too aquainted with the string methods in ruby
If you are not acquainted with Ruby's String methods, you should have a look at the documentation, it's very good. Mithun's answer already showed you the basic principle, but since you are new to Ruby, there's a couple more things to keep in mind:
*) If you have a predicate method, it's customary to name it with a trailing question mark, e.g. palindrome?.
*) Boolean expressions evaluate to a boolean, so you don't need to explicitly return true or false. Hence a short idiomatic version would be
def palindrome?(str)
str == str.reverse
end
*) Since Ruby's classes are open, you could add this to the string class:
class String
def palindrome?
self == self.reverse
end
end
*) If you don't want to monkey-patch String, you can directly define the method on single object (or use a module and Object#extend):
foo = "racecar"
def foo.palindrome?
self == self.reverse
end
*) You might want to make the palindrome check a bit more complex, e.g. when it comes to case or whitespace, so you are also able to detect palindromic sentences, capitalized words like "Racecar" etc.
pal = "Never a foot too far, even."
class String
def palindrome?
letters = self.downcase.scan(/\w/)
letters == letters.reverse
end
end
pal.palindrome? #=> true
def check_palindromic(variable)
if variable.reverse == variable #Check if string same when reversed
puts "#{ variable } is a palindrome."
else # If string is not the same when reversed
puts "#{ variable } is not a palindrome."
end
end
The recursive solution shows how strings can be indexed in Ruby:
def palindrome?(string)
if string.length == 1 || string.length == 0
true
else
if string[0] == string[-1]
palindrome?(string[1..-2])
else
false
end
end
end
If reading the Ruby string documentation is too boring for you, try playing around with the Ruby practice questions on CodeQuizzes and you will pick up most of the important methods.
def is_palindrome(value)
value.downcase!
# Reverse the string
reversed = ""
count = value.length
while count > 0
count -= 1
reversed += value[count]
end
# Instead of writing codes for reverse string
# we can also use reverse ruby method
# something like this value == value.reverse
if value == reversed
return "#{value} is a palindrom"
else
return "#{value} is not a palindrom"
end
end
puts "Enter a Word"
a = gets.chomp
p is_palindrome(a)
class String
def palindrome?
self.downcase == self.reverse.downcase
end
end
puts "racecar".palindrome? # true
puts "Racecar".palindrome? # true
puts "mississippi".palindrome? # false
str= gets.chomp
str_rev=""
n=1
while str.length >=n
str_rev+=str[-n]
n+=1
end
if str_rev==str
puts "YES"
else
puts "NO"
end
> first method
a= "malayalam"
if a == a.reverse
puts "a is true"
else
puts "false"
end
> second one
a= "malayalam"
a=a.split("")
i=0
ans=[]
a.count.times do
i=i+1
k=a[-(i)]
ans << k
end
if a== ans
puts "true"
else
puts "false"
end
def palindrome?(string)
string[0] == string[-1] && (string.length <= 2 || palindrome?(string[1..-2]))
end
**Solution 1** Time complexity = O(n), Space complexity = O(n)
This solution does not use the reverse method of the String class. It uses a stack(we could use an array that only allows entry and exit of elements from one end to mimic a stack).
def is_palindrome(str)
stack = []
reversed_str = ''
str.each_char do |char|
stack << char
end
until stack.empty?
reversed_str += stack.pop
end
if reversed_str == str
return true
else
return false
end
end
` Solution 2: Time complexity = O(n), Space complexity = O(1)
def inplace_reversal!(str)
i =0
j = str.length - 1
while i < j
temp = str[i]
str[i] = str[j]
str[j] = temp
i+=1
j-=1
end
return str
end
def palindrome?(str)
return "Please pass the string" if str.nil?
str = str.downcase
str_array = str.split('')
reverse_string = str_array.each_index{ |index| str_array[str_array.count - index - 1 ] end
return ("String #{str} is not a palindrome") unless str == reverse_string.join('')
"String #{str} is palindrome"
end
I would like to enumerate all the URLs in a text string, for example:
text = "fasòls http://george.it sdafsda"
For each URL found, I want to invoke a function method(...) that transforms the string.
Right now I'm using a method like this:
msg = ""
for i in text.split
if (i =~ URI::regexp).nil?
msg += " " + i
else
msg+= " " + method(i)
end
end
text = msg
This works, but it's slow for long strings. How can I speed this up?
I think "gsub" is your friend here:
class UrlParser
attr_accessor :text, :url_counter, :urls
def initialize(text)
#text = parse(text)
end
private
def parse(text)
#counter = 0
#urls = []
text.gsub(%r{(\A|\s+)(http://[^\s]+)}) do
#urls << $2
"#{$1}#{replace_url($2)}"
end
end
def replace_url(url)
#counter += 1
"[#{#counter}]"
end
end
parsed_url = UrlParser.new("one http://x.com/url two")
puts parsed_url.text
puts parsed_url.urls
If you really need extra fast parsing of long strings, you should build a ruby C extension with ragel.