String sequences with Ruby: Cloning and duplicating - ruby

So I've wrote this code but I can't seem to figure out how to write out the last piece of logic for it to work as desired.
def accum(s)
s.upcase.split("").join("-")
end
#### pseudo #####
# for each character greater than x +1
# join using "-"
#capitalise the first letter
# print "MyStrings".methods.sort
Currently this is what my code returns:
Expected: "Z-Pp-Ggg-Llll-Nnnnn-Rrrrrr-Xxxxxxx-Qqqqqqqq-Eeeeeeeee-Nnnnnnnnnn-Uuuuuuuuuuu",
instead got: Z-P-G-L-N-R-X-Q-E-N-U
I've tried using .each_char and writing a block that adds +1 to chara but that didn't work =/.

This would work:
def accum(str)
str.each_char.with_index(1).map(&:*).map(&:capitalize).join('-')
end
Step by step:
'hello'
.each_char #=> ["h", "e", "l", "l", "o"]
.with_index(1) #=> [["h", 1], ["e", 2], ["l", 3], ["l", 4], ["o", 5]]
.map(&:*) #=> ["h", "ee", "lll", "llll", "ooooo"]
.map(&:capitalize) #=> ["H", "Ee", "Lll", "Llll", "Ooooo"]
.join('-') #=> "H-Ee-Lll-Llll-Ooooo"
It first retrieves each character along with its 1-based index. Next, the character-index pairs are combined via String#* to duplicate the characters ("l" * 3 becomes "lll"). Finally, each part is capitalized and joined by -.

Another method, you can use 'each_with_index'.
def accum(s)
s.upcase.split("").each_with_index.to_a.map{|x| x[0]+x[0].downcase*x[1]}.join("-")
end

s.split("").map{|x| "#{x.upcase}#{x.downcase*(s.index(x))}"}.join("-")
This is what I came up with. However it will not work if there's repeating characters in the string as .index(x) returns the index of the first instance of x.
I suppose I'll leave that for you to do

Related

Zip all array values of hash

I'd like to zip all the array values of a hash. I know there's a way to zip arrays together. I'd like to do that with the values of my hash below.
current_hash = {:a=>["k", "r", "u"],
:b=>["e", " ", "l"],
:c=>["d", "o", "w"],
:d=>["e", "h"]
}
desired_outcome = "keder ohulw"
I have included my desired outcome above.
current_hash.values.then { |first, *rest| first.zip(*rest) }.flatten.compact.join
An unfortunate thing with Ruby zip is that the first enumerable needs to be the receiver, and the others need to be parameters. Here, I use then, parameter deconstruction and splat to separate the first enumerable from the rest. flatten gets rid of the column arrays, compact gets rid of the nil (though it's not really necessary as join will ignore it), and join turns the array into the string.
Note that Ruby zip will stop at length of the receiver; so if :a is shorter than the others, you will likely have a surprising result. If that is a concern, please update with an example that reflects that scenario, and the desired outcome.
Here I'm fleshing out #Amadan's remark below the horizontal line in is answer. Suppose:
current_hash = { a:["k","r"], b:["e"," ","l"], c:["d","o","w"], d:["e", "h"] }
and you wished to return "keder ohlw". If you made ["k","r"] and [["e"," ","l"], ["d","o","w"], ["e", "h"]] zip's receiver and argument, respectively, you would get "keder oh", which omits "l" and "w". (See Array#zip, especially the 3rd paragraph.)
To include those strings you would need to fill out ["k","r"] with nils to make it as long as the longest value, or make zip's receiver an array of nils of the same length. The latter approach can be implemented as follows:
vals = current_hash.values
#=> [["k", "r"], ["e", " ", "l"], ["d", "o", "w"], ["e", "h"]]
([nil]*vals.map(&:size).max).zip(*vals).flatten.compact.join
#=> "keder ohlw"
Note:
a = [nil]*vals.map(&:size).max
#=> [nil, nil, nil]
and
a.zip(*vals)
#=> [[nil, "k", "e", "d", "e"],
# [nil, "r", " ", "o", "h"],
# [nil, nil, "l", "w", nil]]
One could alternatively use Array#transpose rather than zip.
vals = current_hash.values
idx = (0..vals.map(&:size).max-1).to_a
#=> [0, 1, 2]
vals.map { |a| a.values_at(*idx) }.transpose.flatten.compact.join
#=> "keder ohlw"
See Array#values_at. Note:
a = vals.map { |a| a.values_at(*idx) }
#=> [["k", "r", nil],
# ["e", " ", "l"],
# ["d", "o", "w"],
# ["e", "h", nil]]
a.transpose
#=> [["k", "e", "d", "e"],
# ["r", " ", "o", "h"],
# [nil, "l", "w", nil]]

How to understand the work flow in ruby enumerator chain

The code below produces two different results.
letters = %w(e d c b a)
letters.group_by.each_with_index { |item, index| index % 3 }
#=> {0=>["e", "b"], 1=>["d", "a"], 2=>["c"]}
letters.each_with_index.group_by { |item, index| index % 3 }
#=> {0=>[["e", 0], ["b", 3]], 1=>[["d", 1], ["a", 4]], 2=>[["c", 2]]}
I think the execution flow is from right to left, and the data flow is from the left to right. The block should be passed as parameter from right to left.
Using puts, I observed that the block is executed in the inner each.
In the first chain, group_by should ask each for data, each will return the result of index%3, and group_by should process the result and yield it to another block. But how is the block passed? If the block is executed in each, each would not pass two parameters item and index but only one parameter item.
In the second chain, in my understanding, each_with_index will receive the data from each method first; each yields to index%3. In that case, how can each_with_index process index%3?
It seems my understanding is somehow wrong. Can anyone illustrate theses two examples with details and give the general work flow in such cases?
Proxy objects
Both execution and data flows are from left to right, as with any method call in Ruby.
Conceptually, it can help to read Enumerators call chains from right to left, though, because they're a kind of a proxy object.
Called without block, they just remember in which order which method has been called. The method is then only really called when it's needed, for example when the Enumerator is converted back to an Array or the elements are printed on screen.
If no such method is called at the end of the chain, basically nothing happens:
[1,2,3].each_with_index.each_with_index.each_with_index.each_with_index
# #<Enumerator: ...>
[1,2,3].each_with_index.each_with_index.each_with_index.each_with_index.to_a
# [[[[[1, 0], 0], 0], 0], [[[[2, 1], 1], 1], 1], [[[[3, 2], 2], 2], 2]]
This behaviour makes it possible to work with very large streams of objects, without needing to pass huge arrays between method calls. If the output isn't needed, nothing is calculated. If 3 elements are needed at the end, only 3 elements are calculated.
The proxy pattern is heavily used in Rails, for example with ActiveRecord::Relation :
#person = Person.where(name: "Jason").where(age: 26)
It would be inefficient to launch 2 DB queries in this case. You can only know that at the end of the chained methods, though. Here's a related answer (How does Rails ActiveRecord chain “where” clauses without multiple queries?)
MyEnumerator
Here's a quick and dirty MyEnumerator class. It might help you understand the logic for the method calls in your question:
class MyEnumerator < Array
def initialize(*p)
#methods = []
#blocks = []
super
end
def group_by(&b)
save_method_and_block(__method__, &b)
self
end
def each_with_index(&b)
save_method_and_block(__method__, &b)
self
end
def to_s
"MyEnumerable object #{inspect} with methods : #{#methods} and #{#blocks}"
end
def apply
result = to_a
puts "Starting with #{result}"
#methods.zip(#blocks).each do |m, b|
if b
puts "Apply method #{m} with block #{b} to #{result}"
else
puts "Apply method #{m} without block to #{result}"
end
result = result.send(m, &b)
end
result
end
private
def save_method_and_block(method, &b)
#methods << method
#blocks << b
end
end
letters = %w[e d c b a]
puts MyEnumerator.new(letters).group_by.each_with_index { |_, i| i % 3 }.to_s
# MyEnumerable object ["e", "d", "c", "b", "a"] with methods : [:group_by, :each_with_index] and [nil, #<Proc:0x00000001da2518#my_enumerator.rb:35>]
puts MyEnumerator.new(letters).group_by.each_with_index { |_, i| i % 3 }.apply
# Starting with ["e", "d", "c", "b", "a"]
# Apply method group_by without block to ["e", "d", "c", "b", "a"]
# Apply method each_with_index with block #<Proc:0x00000000e2cb38#my_enumerator.rb:42> to #<Enumerator:0x00000000e2c610>
# {0=>["e", "b"], 1=>["d", "a"], 2=>["c"]}
puts MyEnumerator.new(letters).each_with_index.group_by { |_item, index| index % 3 }.to_s
# MyEnumerable object ["e", "d", "c", "b", "a"] with methods : [:each_with_index, :group_by] and [nil, #<Proc:0x0000000266c220#my_enumerator.rb:48>]
puts MyEnumerator.new(letters).each_with_index.group_by { |_item, index| index % 3 }.apply
# Apply method each_with_index without block to ["e", "d", "c", "b", "a"]
# Apply method group_by with block #<Proc:0x0000000266bd70#my_enumerator.rb:50> to #<Enumerator:0x0000000266b938>
# {0=>[["e", 0], ["b", 3]], 1=>[["d", 1], ["a", 4]], 2=>[["c", 2]]}

How to extract each individual combination from a flat_map?

I'm fairly new to ruby and it's my first question here on stackoverflow so pardon me if I'm being a complete noob.
The code which i am working with contains this line -
puts (6..6).flat_map{|n| ('a'..'z').to_a.combination(n).map(&:join)}
What the code does is that its starts printing each of the combinations starting from "abcdef" and continues till the end (which i have never seen as it has 26^6 combinations).
Of course having an array of that size (26^6) is unimaginable hence I was wondering if there is any way by which i can get next combination in a variable, work with it, and then continue on to the next combination ?
For example I calculate the first combination as "abcdef" and store it in a variable 'combo' and use that variable somewhere and then the next combination is calculated and "abcdeg" is stored in 'combo' and hence the loop continues ?
Thanks
(6..6).flat_map { |n| ... } doesn't do much. Your code is equivalent to:
puts ('a'..'z').to_a.combination(6).map(&:join)
To process the values one by one, you can pass a block to combination:
('a'..'z').to_a.combination(6) do |combo|
puts combo.join
end
If no block is given, combination returns an Enumerator that can be iterated by calling next:
enum = ('a'..'z').to_a.combination(6)
#=> #<Enumerator: ["a", "b", "c", ..., "w", "x", "y", "z"]:combination(6)>
enum.next
#=> ["a", "b", "c", "d", "e", "f"]
enum.next
#=> ["a", "b", "c", "d", "e", "g"]
enum.next
#=> ["a", "b", "c", "d", "e", "h"]
Note that ('a'..'z').to_a.combination(6) will "only" yield 230,230 combinations:
('a'..'z').to_a.combination(6).size
#=> 230230
As opposed to 26 ^ 6 = 308,915,776. You are probably looking for repeated_permutation:
('a'..'z').to_a.repeated_permutation(6).size
#=> 308915776
Another way to iterate from "aaaaaa" to "zzzzzz" is a simple range:
('aaaaaa'..'zzzzzz').each do |combo|
puts combo
end
Or manually by calling String#succ: (this is what Range#each does under the hood)
'aaaaaa'.succ #=> "aaaaab"
'aaaaab'.succ #=> "aaaaac"
'aaaaaz'.succ #=> "aaaaba"

How might I match a string in ruby without using regular expressions?

Currently, I'm doing this:
(in initialize)
#all = Stuff.all.each.map {|t| t.reference_date }
#uniques = #all.uniq
results = []
#uniques.each do |k|
i = 0
#all.each do |x|
i += 1 if x =~ %r{#{x}}
end
results << [k, i]
end
And that's fine. It's going to work. But I like to avoid regular expressions when I can. I think they are a bit feo. That's spanish for ugly.
EDIT--
actually, that's not working because ruby "puts" the date as a numbered format like 2012-03-31 when the date object is placed inside of a string (as a variable, here), but its really a date object, so this worked:
if x.month == k.month && x.day == k.day
i += 1
end
You can do it with just 1 line (if I got right the question of course):
array = %w(a b c d a b d f t z z w w)
# => ["a", "b", "c", "d", "a", "b", "d", "f", "t", "z", "z", "w", "w"]
array.uniq.map{|i|[i, array.count(i)]}
# => [["a", 2], ["b", 2], ["c", 1], ["d", 2], ["f", 1], ["t", 1], ["z", 2], ["w", 2]]
results = Hash.new(0)
#all.each{|t| results[t] += 1}
# stop here if a hash is good enough.
# if you want a nested array:
results = results.to_a
This is the standard way of getting the frequency of elements in an enumerable.
Something you can do to avoid the appearance of regular expressions, is to build them on the fly using Regexp.union. The reason you might want to do this is SPEED. A well constructed regex is faster than iterating over a list, especially a big one. And, by allowing your code to build the regex, you don't have to maintain some ugly (feo) thing.
For instance, here's something I do in different chunks of code:
words = %w[peer_address peer_port ssl ssl_protocol ssl_key_exchange ssl_cipher]
regex = /\b(?:#{ Regexp.union(words).source })\b/i
=> /\b(?:peer_address|peer_port|ssl|ssl_protocol|ssl_key_exchange|ssl_cipher)\b/i
That makes it trivial to maintain a regex. And, try a benchmark using that to find substrings in text against iterating and it'll impress you.
If wildcards will work for you, try File.fnmatch
From your code I sense you want to get the number of occurrence of each reference_date. This can be achieved much easier by using ActiveRecord and SQL directly instead of pulling the whole tale and then performing time consuming operations in Ruby.
If you are using Rails 2.x you can use something like this:
Stuff.find(:all, :select => "reference_date, COUNT(*)", :group => "reference_date")
or if you are using Rails 3 then you can simplify it to
Stuff.count(:group => "reference_date")

Determining if a prefix exists in a set

Given a set of strings, say:
"Alice"
"Bob"
"C"
"Ca"
"Car"
"Carol"
"Caroling"
"Carousel"
and given a single string, say:
"Carolers"
I would like a function that returns the smallest prefix not already inside the array.
For the above example, the function should return: "Caro". (A subsequent call would return "Carole")
I am very new to Ruby, and although I could probably hack out something ugly (using my C/C++/Objective-C brain), I would like to learn how to properly (elegantly?) code this up.
There's a little known magical module in Ruby called Abbrev.
require 'abbrev'
abbreviations = Abbrev::abbrev([
"Alice",
"Bob",
"C",
"Ca",
"Car",
"Carol",
"Caroling",
"Carousel"
])
carolers = Abbrev::abbrev(%w[Carolers])
(carolers.keys - abbreviations.keys).sort.first # => "Caro"
Above I took the first element but this shows what else would be available.
pp (carolers.keys - abbreviations.keys).sort
# >> ["Caro", "Carole", "Caroler", "Carolers"]
Wrap all the above in a function, compute the resulting missing elements, and then iterate over them yielding them to a block, or use an enumerator to return them one-by-one.
This is what is generated for a single word. For an array it is more complex.
require 'pp'
pp Abbrev::abbrev(['cat'])
# >> {"ca"=>"cat", "c"=>"cat", "cat"=>"cat"}
pp Abbrev::abbrev(['cat', 'car', 'cattle', 'carrier'])
# >> {"cattl"=>"cattle",
# >> "catt"=>"cattle",
# >> "cat"=>"cat",
# >> "carrie"=>"carrier",
# >> "carri"=>"carrier",
# >> "carr"=>"carrier",
# >> "car"=>"car",
# >> "cattle"=>"cattle",
# >> "carrier"=>"carrier"}
Your question still doesn't match what you are expecting as a result. It seems that you need prefixes, not the substrings (as "a" would be the shortest substring not already in the array). For searching the prefix, this should suffice:
array = [
"Alice",
"Bob",
"C",
"Ca",
"Car",
"Carol",
"Caroling",
"Carousel",
]
str = 'Carolers'
(0..str.length).map{|i|
str[0..i]
}.find{|s| !array.member?(s)}
I am not a Ruby expert, but I think you may want to approach this problem by converting your set into a trie. Once you have the trie constructed, your problem can be solved simply by walking down from the root of the trie, following all of the edges for the letters in the word, until you either find a node that is not marked as a word or walk off the trie. In either case, you've found a node that isn't part of any word, and you have the shortest prefix of your word in question that doesn't already exist inside of the set. Moreover, this would let you run any number of prefix checks quickly, since after you've built up the trie the algorithm takes time at most linear in the length of the string.
Hope this helps!
I'm not really sure what you're asking for other than an example of some Ruby code to find common prefixes. I'll assume you want to find the smallest string which is a prefix of the most number of strings in the given set. Here's an example implementation:
class PrefixFinder
def initialize(words)
#words = Hash[*words.map{|x|[x,x]}.flatten]
end
def next_prefix
max=0; biggest=nil
#words.keys.sort.each do |word|
0.upto(word.size-1) do |len|
substr=word[0..len]; regex=Regexp.new("^" + substr)
next if #words[substr]
count = #words.keys.find_all {|x| x=~regex}.size
max, biggest = [count, substr] if count > max
#puts "OK: s=#{substr}, biggest=#{biggest.inspect}"
end
end
#words[biggest] = biggest if biggest
biggest
end
end
pf = PrefixFinder.new(%w(C Ca Car Carol Caroled Carolers))
pf.next_prefix # => "Caro"
pf.next_prefix # => "Carole"
pf.next_prefix # => "Caroler"
pf.next_prefix # => nil
No comment on the performance (or correctness) of this code but it does show some Ruby idioms (instance variables, iteration, hashing, etc).
=> inn = ["Alice","Bob","C","Ca","Car","Carol","Caroling","Carousel"]
=> y = Array.new
=> str="Carolers"
Split the given string to an array
=> x=str.split('')
# ["C","a","r","o","l","e","r","s"]
Form all the combination
=> x.each_index {|i| y << x.take(i+1)}
# [["c"], ["c", "a"], ["c", "a", "r"], ["c", "a", "r", "o"], ["c", "a", "r", "o", "l"], ["c", "a", "r", "o", "l", "e"], ["c", "a", "r", "o", "l", "e", "r"], ["c", "a", "r", "o", "l", "e", "r", "s"]]
Using Join to concatenate the
=> y = y.map {|s| s.join }
# ["c", "ca", "car", "caro", "carol", "carole", "caroler", "carolers"]
Select the first item from the y thats not available in the input Array
=> y.select {|item| !inn.include? item}.first
You will get "caro"
Putting together all
def FindFirstMissingItem(srcArray,strtocheck)
y=Array.new
x=strtocheck.split('')
x.each_index {|i| y << x.take(i+1)}
y=y.map {|s| s.join}
y.select {|item| !srcArray.include? item}.first
end
And call
=> inn = ["Alice","Bob","C","Ca","Car","Carol","Caroling","Carousel"]
=> str="Carolers"
FindFirstMissingItem inn,str
Very simple version (but not very Rubyish):
str = 'Carolers'
ar = %w(Alice Bob C Ca Car Carol Caroling Carousel)
substr = str[0, n=1]
substr = str[0, n+=1] while ar.include? substr
puts substr

Resources