Here is working code:
p = (10..14).map { |a|
(a..14).map { |b|
a * b
}
flatten.select { |p|
p.to_s == p.to_s.reverse
}
But I want to keep the information about 'a' and 'b' which produced 'a * b':
p = (10..14).map { |a|
(a..14).map { |b|
[a, b, a * b, '=']
}
}.select { |v|
v[2].to_s == v[2].to_s.reverse
}
puts p
This code print not palindromic number. I guess that reason is a Array flatten. How do I need to change code to get palindromic number?
You want to flatten only one level, so use flatten(1) instead.
(10..14).map { |a|
(a..14).map { |b|
[a, b, a * b, '=']
}
}.flatten(1).select { |v|
v[2].to_s == v[2].to_s.reverse
}
Alternatively, replace your outer map by flat_map:
(10..14).flat_map { |a|
(a..14).map { |b|
[a, b, a * b, '=']
}
}.select { |v|
v[2].to_s == v[2].to_s.reverse
}
Note: flatten takes an argument since Ruby 1.8.7. flat_map is new to Ruby 1.9.2. Make sure you have the right version, or require "backports/1.9.2/enumerable/flat_map" or require "backports/1.8.7/array/flatten".
Yes, since you don't call flatten in the second version, the array is too nested and the select doesn't work because v is a row of elements, not a single elements. However if you'd just call flatten like in the first version, the resulting array would be too flat.
There are multiple ways to solve this:
In 1.9.2 you can replace the outer call to ´mapwithflat_mapwhich works likemap`, but automatically produces a flat array.
In 1.8.7+ you can call flatten(1) instead of flatten, which will flatten the array by exactly one level of nesting, resulting in the structure you want.
Instead of an array you could define a class to represent a number, which avoids the problem of accidentally flattening the inner arrays lets you access the properties of the number more meaningfully.
Option 3 could look like this:
Product = Struct.new(:factor1, :factor2) do
def product
factor1 * factor2
end
def to_s
"#{factor1} * #{factor2} = #{product}"
end
end
products = (10..14).map { |a|
(a..14).map { |b|
Product.new(a,b)
}
}.flatten.select { |prod|
prod.product.to_s == prod.product.to_s.reverse
}
puts products
palindromes = []
(10..14).each do |a|
(a..14).each do |b|
p = (a * b).to_s
palindromes << [a,b] if p == p.reverse
end
end
puts palindromes.join(',')
wesbailey#feynman:~/code_katas> ruby palindrome.rb
11,11
Related
I have a Hash h and want to have an Array of those keys, where their values fulfil a certain condition. My naive approach is:
result = h.select { |_, val| val.fulfils_condition? }.keys
This works, of course, but looks unnecessarily inefficient to me, as it requires an intermediate Hash to be constructed, from which then the result Array is calculated.
Of course I could do an explicit loop:
result = []
h.each do
|key, val|
result << key if val.fulfils_condition?
end
but this I consider ugly due to the explicit handling of result. I also was contemplating this one:
result = h.reduce([]) do
|memo, pair|
memo << pair.first if pair.last.fulfils_condition?
memo
end
but this is not really more readable, and requires the construction of the intermediate pair arrays, each holding a key-value-pair.
Is there an alternative approach, which is compact, and does not need to calculate a temporary Hash?
Given:
h = {}; (1..100).each {|v| h[v.to_s] = v }
You can use the memory_profiler gem to measure allocations. Use something like MemoryProfiler.report { code }.total_allocated.
If memory allocations are really at a premium here, your approach of preallocating the result and then enumerating with #each is what you want. The reason for this is that Ruby optimizes Hash#each for blocks with an arity of 2, so that a new array isn't constructed per loop. The only allocation in this approach is the results array.
MemoryProfiler.report { r = [] ; h.each {|k, v| r << k if v > 1 } }.total_allocated
# => 1
Using #reduce, OTOH, results in an allocation per loop because you break the arity rule:
MemoryProfiler.report { h.reduce([]) {|agg, (k, v)| agg << k if v > 1 ; agg } }.total_allocated
# => 101
If you want something more "self-contained" and are willing to sacrifice an extra allocation, you'll want to use #each_key (which does create an intermediate array of keys) and then index into the hash to test each value.
h.each_key.select {|k| h[k] > 1 }
Simple is best I think. How about this?
h.keys.select { |k| k.meets_condition }
I love #ChrisHeald solution
h.each_key.filter_map { |k| k if condition(h[k]) }
I would have gone with a more verbose
h.each_with_object([]) { |(k, v), arr| arr < k if condition(v) }
or even
h.map { |k, v| k if condition(v) }.compact
which are clearly constructing more than needed, but are still quite clear.
Riffing off Peter Camilleri's proposal, I think the following does what you want:
h = {:a => 1, :b => -1, :c => 2, :d => -2}
h.keys.select { |k| h[k] < 0 } # [:b, :d]
So I've been trying to solve a Leetcode Question, "Given a string, find the length of the longest substring without repeating characters."
For example
Input: "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Currently I optimized my algorithm when it comes to figuring out if the substring is unique by using a hash table. However my code still runs in O(n^2) runtime, and as a result exceeds the time limit during submissions.
What i try to do is to essentially go through every single possible substring and check if it has any duplicate values. Am I as efficient as it gets when it comes to the brute force method here? I know there's other methods such as a sliding window method but I'm trying to get the brute force method down first.
# #param {String} s
# #return {Integer}
def length_of_longest_substring(s)
max_length = 0
max_string = ""
n = s.length
for i in (0..n-1)
for j in (i..n-1)
substring = s[i..j]
#puts substring
if unique(substring)
if substring.length > max_length
max_length = substring.length
max_string = substring
end
end
end
end
return max_length
end
def unique(string)
hash = Hash.new(false)
array = string.split('')
array.each do |char|
if hash[char] == true
return false
else
hash[char] = true
end
end
return true
end
Approach
Here is a way of doing that with a hash that maps characters to indices. For a string s, suppose the characters in the substring s[j..j+n-1] are unique, and therefore the substring is a candidate for the longest unique substring. The next element is therefore e = s[j+n] We wish to determine if s[j..j+n-1] includes e. If it does not we can append e to the substring, keeping it unique.
If s[j..j+n-1] includes e, we determine if n (the size of the substring) is greater than the length of the previously-known substring, and update our records if it is. To determine if s[j..j+n-1] includes e, we could perform a linear search of the substring, but it is faster to maintain a hash c_to_i whose key-value pairs are s[i]=>i, i = j..j_n-1. That is, c_to_i maps the characters in the substring to their indices in full string s. That way we can merely evaluate c_to_i.key?(e) to see if the substring contains e. If the substring includes e, we use c_to_i to determine its index in s and add one: j = c_to_i[e] + 1. The new substring is therefore s[j..j+n-1] with the new value of j. Note that several characters of s may be skipped in this step.
Regardless of whether the substring contained e, we must now append e to the (possibly-updated) substring, so that it becomes s[j..j+n].
Code
def longest_no_repeats(str)
c_to_i = {}
longest = { length: 0, end: nil }
str.each_char.with_index do |c,i|
j = c_to_i[c]
if j
longest = { length: c_to_i.size, end: i-1 } if
c_to_i.size > longest[:length]
c_to_i.reject! { |_,k| k <= j }
end
c_to_i[c] = i
end
c_to_i.size > longest[:length] ? { length: c_to_i.size, end: str.size-1 } :
longest
end
Example
a = ('a'..'z').to_a
#=> ["a", "b",..., "z"]
str = 60.times.map { a.sample }.join
#=> "ekgdaxxzlwbxixhlfbpziswcoelplhobivoygmupdaexssbuuawxmhprkfms"
longest = longest_no_repeats(str)
#=> {:length=>14, :end=>44}
str[0..longest[:end]]
#=> "ekgdaxxzlwbxixhlfbpziswcoelplhobivoygmupdaexs"
str[longest[:end]-longest[:length]+1,longest[:length]]
#=> "bivoygmupdaexs"
Efficiency
Here is a benchmark comparison to #mechnicov's code:
require 'benchmark/ips'
a = ('a'..'z').to_a
arr = 50.times.map { 1000.times.map { a.sample }.join }
Benchmark.ips do |x|
x.report("mechnicov") { arr.sum { |s| max_non_repeated(s)[:length] } }
x.report("cary") { arr.sum { |s| longest_no_repeats(s)[:length] } }
x.compare!
end
displays:
Comparison:
cary: 35.8 i/s
mechnicov: 0.0 i/s - 1198.21x slower
From your link:
Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
That means you need first non-repeated substring.
I suggest here is such method
def max_non_repeated(string)
max_string = string.
each_char.
map.with_index { |_, i| string[i..].split('') }.
map do |v|
ary = []
v.each { |l| ary << l if ary.size == ary.uniq.size }
ary.uniq.join
end.
max
{
string: max_string,
length: max_string.length
}
end
max_non_repeated('pwwkew')[:string] #=> "wke"
max_non_repeated('pwwkew')[:length] #=> 3
In Ruby < 2.6 use [i..-1] instead of [i..]
a = [1,2,3]
b = [4,5 ]
What I want is to iterate these two collection at same time and do something with iterator, the pseudo code would be like:
for i in a
for j in b
collect i * j
when one collection runs out of element, the loop stops.
the result will be [4, 10]
What I have is this:
a = [1,2,3]
b = [4,5 ]
a.zip(b).reject { |c| c.any? { |d| d.nil? } }.map { |e| e.reduce(&:*) }
Any better solution? Thanks!
And The perfect solution I am looking for is to match the intent of my pseudo code.
You can do this:
a, b = b, a if b.length < a.length
a.zip(b).map { |ia, ib| ia * ib }
# => [4, 10]
The first line makes sure that array a has at most the same number of elements as array b. This is because zip creates an array of arrays of the length of the called array. Having a as the shortest array makes sure that there would be no nils.
Here is another way to do it:
[a.length, b.length].min.times.map {|i| a[i]*b[i] }
The idea is that you take the shorter of the two array lengths, [a.length, b.length].min, and you iterate that many times over an integer, i, which you use as an index into the arrays.
I would love to set three variables a, b and c from a single gets line. For example, user entering a line of space-delimited numbers "1 2.2 -3.14" would set a to 1, b to 2.2 and c to -3.14 respectively. I achieve this like so:
input = gets.strip.split
a,b,c = input[0].to_f,input[1].to_f,input[2].to_f
Is there a more elegant way to assign array entries to a range of variables? Perhaps something with a splat and a cycle?
input.each {|entry| *(a..z) = entry }
a,b,c = "1 2.2 -3.14".split.map(&:to_f)
# => [1.0, 2.2, -3.14]
b
# => 2.2
str = "scan may be 1 useful if 2.2 the string may contain -3.14 other stuff"
arr = []
str.scan(/-?\d*(?:\d|\.\d|\d\.)\d*/) { |s| arr << s.to_f }
arr #=> [1.0, 2.2, -3.14]
The regex extracts the embedded numbers that have zero or one decimal points.
Considering that you are using gets to obtain str, I've chosen to use arr = rather than a,b,c = so I can make sure the correct number of floats have been returned:
if arr.size == 3
a,b,c = arr
else
<raise exception>
end
With v1.9+ you could save a line (just saying, not advocating) by using Object#tap:
arr = [].tap { |a| str.scan(/-?\d*(?:\d|\.\d|\d\.)\d*/) { |s| a << s.to_f } }
I built this method to find the longest word in an array, but I'm wondering if there's a better way to have done it. I'm pretty new to Ruby, and just did this as an exercise for learning the inject method.
It returns either the longest word in an array, or an array of the equal longest words.
class Array
def longest_word
# Convert array elements to strings in the event that they're not.
test_array = self.collect { |e| e.to_s }
test_array.inject() do |word, comparison|
if word.kind_of?(Array) then
if word[0].length == comparison.length then
word << comparison
else
word[0].length > comparison.length ? word : comparison
end
else
# If words are equal, they are pushed into an array
if word.length == comparison.length then
the_words = Array.new
the_words << word
the_words << comparison
else
word.length > comparison.length ? word : comparison
end
end
end
end
end
I would do
class Array
def longest_word
group_by(&:size).max.last
end
end
Ruby has a standard method for returning an element in a list with the maximum of a value.
anArray.max{|a, b| a.length <=> b.length}
or you can use the max_by method
anArray.max_by(&:length)
to get all the elements with the maximum length
max_length = anArray.max_by(&:length).length
all_with_max_length = anArray.find_all{|x| x.length = max_length}
Here's one using inject (doesn't work for an empty array):
words.inject(['']){|a,w|
case w.length <=> a.last.length
when -1
a
when 0
a << w
when 1
[w]
end
}
which can be shortened to
words.inject(['']){|a,w|
[a + [w], [w], a][w.length <=> a.last.length]
}
for those who like golf.
A two liner:
vc = ['asd','s','1234','1235'].sort{|a,b| b.size <=> a.size}
vc.delete_if{|a| a.size < vc.first.size}
#Output
["1235", "1234"]
or if you want use inject, this use your idea, but its more short.
test_array.inject{ |ret,word|
ret = [ret] unless ret.kind_of?(Array)
ret << word if word.size == ret.first.size
ret = [word] if word.size > ret.first.size
ret
}
module Enumerable
def longest_word
(strings = map(&:to_s)).
zip(strings.map(&:length)).
inject([[''],0]) {|(wws, ll), (w, l)|
case l <=> ll
when -1 then [wws, ll]
when 1 then [[w], l]
else [wws + [w], ll]
end
}.first
end
end
This method only depends on generic Enumerable methods, there's nothing Array specific about it, therefore we can pull it up into the Enumerable module, where it will also be available for Sets or Enumerators, not just Arrays.
This solution uses the inject method to accumulate the longest strings in an array, then picks the ones with the highest length.
animals = ["mouse", "cat", "bird", "bear", "moose"]
animals.inject(Hash.new{|h,k| h[k] = []}) { |acc, e| acc[e.size] << e; acc }.sort.last[1]
This returns:
["mouse", "mouse"]