Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
A String s comprised of numbers from 0-9 contains a perfect substring if all the elements within a substring occurs exactly k times. Calculate the number of perfect substrings in s.
EXAMPLE
s = '1102021222'
k = 2
Here s contains 6 substrings:
11
0202
110202
102021
22
22
Can anyone help me with the solution to this in Ruby with the least complexity?
TIA..
Code
def count_em(str, k)
enum = str.each_char
(k..str.size).step(k).sum do |n|
enum.each_cons(n).count do |a|
a.tally.all? { |_k,v| v == k }
end
end
end
Examples
str = '1102021222'
count_em(str, 1) #=> 18 ( 1, 1, 0, 2, 0, 2, 1, 2, 2, 2,
# 10, 02, 20, 02, 21, 12, 102, 021
count_em(str, 2) #=> 6 (11, 22, 22, 0202, 110202, 102021)
count_em(str, 3) #=> 1 (102021)
count_em(str, n) #=> 0 for n > 3
Explanation
Enumerable#tally made its debut in Ruby v2.7. To support earlier versions of Ruby replace tally with
each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }
Enumerable#sum was new in Ruby 2.4. To support earlier versions of Ruby replace sum with
reduce(:+)
See also Enumerable#each_cons, Enumerable#count and Enumerable#all? and Hash::new.
Note that no strings having k instances of all unique digits contained in the string could be produced for values of n that are not multiples of k. It is for that reason that step(k) is present.
The easiest way to explain the calculations is to salt the method with puts statements and run it.
def count_em(str, k)
puts "k = #{k}"
enum0 = str.each_char
puts "enum0 = #{enum0}"
(k..str.size).step(k).sum do |n|
puts "n = #{n}"
enum1 = enum0.each_cons(n)
puts " enum1.to_a = #{enum1.to_a}"
enum1.count do |a|
puts " a = #{a}"
h = a.tally
puts " a.tally = #{h}"
puts " a.tally.all? {|_k,v| v == k} = #{h.all? {|_k,v| v==k}}"
h.all? { |_k,v| v==k }
end
end
end
The line puts " enum1.to_a = #{enum1.to_a}" merely displays the values that will be generated by the enumerator enum1 and passed to count's block.
Try it for k = 2:
count_em(str, 2)
#=> 6
displays the following:
k = 2
enum0 = #<Enumerator:0x00007f9467ab60f0>
n = 2
enum1.to_a = [["1", "1"], ["1", "0"], ["0", "2"], ["2", "0"],
["0", "2"], ["2", "1"], ["1", "2"], ["2", "2"],
["2", "2"]]
a = ["1", "1"]
a.tally = {"1"=>2}
a.tally.all? {|_k,v| v == k} = true
a = ["1", "0"]
a.tally = {"1"=>1, "0"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["0", "2"]
a.tally = {"0"=>1, "2"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["2", "0"]
a.tally = {"2"=>1, "0"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["0", "2"]
a.tally = {"0"=>1, "2"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["2", "1"]
a.tally = {"2"=>1, "1"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["1", "2"]
a.tally = {"1"=>1, "2"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["2", "2"]
a.tally = {"2"=>2}
a.tally.all? {|_k,v| v == k} = true
a = ["2", "2"]
a.tally = {"2"=>2}
a.tally.all? {|_k,v| v == k} = true
n = 4
enum1.to_a = [["1", "1", "0", "2"], ["1", "0", "2", "0"],
["0", "2", "0", "2"], ["2", "0", "2", "1"],
["0", "2", "1", "2"], ["2", "1", "2", "2"],
["1", "2", "2", "2"]]
a = ["1", "1", "0", "2"]
a.tally = {"1"=>2, "0"=>1, "2"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["1", "0", "2", "0"]
a.tally = {"1"=>1, "0"=>2, "2"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["0", "2", "0", "2"]
a.tally = {"0"=>2, "2"=>2}
a.tally.all? {|_k,v| v == k} = true
a = ["2", "0", "2", "1"]
a.tally = {"2"=>2, "0"=>1, "1"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["0", "2", "1", "2"]
a.tally = {"0"=>1, "2"=>2, "1"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["2", "1", "2", "2"]
a.tally = {"2"=>3, "1"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["1", "2", "2", "2"]
a.tally = {"1"=>1, "2"=>3}
a.tally.all? {|_k,v| v == k} = false
n = 6
enum1.to_a = [["1", "1", "0", "2", "0", "2"], ["1", "0", "2", "0", "2", "1"],
["0", "2", "0", "2", "1", "2"], ["2", "0", "2", "1", "2", "2"],
["0", "2", "1", "2", "2", "2"]]
a = ["1", "1", "0", "2", "0", "2"]
a.tally = {"1"=>2, "0"=>2, "2"=>2}
a.tally.all? {|_k,v| v == k} = true
a = ["1", "0", "2", "0", "2", "1"]
a.tally = {"1"=>2, "0"=>2, "2"=>2}
a.tally.all? {|_k,v| v == k} = true
a = ["0", "2", "0", "2", "1", "2"]
a.tally = {"0"=>2, "2"=>3, "1"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["2", "0", "2", "1", "2", "2"]
a.tally = {"2"=>4, "0"=>1, "1"=>1}
a.tally.all? {|_k,v| v == k} = false
a = ["0", "2", "1", "2", "2", "2"]
a.tally = {"0"=>1, "2"=>4, "1"=>1}
a.tally.all? {|_k,v| v == k} = false
n = 8
enum1.to_a = [["1", "1", "0", "2", "0", "2", "1", "2"],
["1", "0", "2", "0", "2", "1", "2", "2"],
["0", "2", "0", "2", "1", "2", "2", "2"]]
a = ["1", "1", "0", "2", "0", "2", "1", "2"]
a.tally = {"1"=>3, "0"=>2, "2"=>3}
a.tally.all? {|_k,v| v == k} = false
a = ["1", "0", "2", "0", "2", "1", "2", "2"]
a.tally = {"1"=>2, "0"=>2, "2"=>4}
a.tally.all? {|_k,v| v == k} = false
a = ["0", "2", "0", "2", "1", "2", "2", "2"]
a.tally = {"0"=>2, "2"=>5, "1"=>1}
a.tally.all? {|_k,v| v == k} = false
n = 10
enum1.to_a = [["1", "1", "0", "2", "0", "2", "1", "2", "2", "2"]]
a = ["1", "1", "0", "2", "0", "2", "1", "2", "2", "2"]
a.tally = {"1"=>3, "0"=>2, "2"=>5}
a.tally.all? {|_k,v| v == k} = false
Given the expression
1 * 2 / 3 + 4
I'm trying to write out all possible variants of the equation when implementing order of operations. Such as:
(1 * 2) / 3) + 4
and
(1 * (2 / 3)) + 4
This is what I have now:
expression = [1.0, "+", 2.0, "+", 3.0, "+", 4.0]
storage = []
exp1 = expression #Make new object because insert method will overwrite expression object
storage << exp1.insert(0, "((").insert(4, ")").insert(7, ")")
But exp1's changes reflect in expression as well. I even made them in separate methods but the changes keep reflecting on expression.
How do I keep the expression object unchanged? I need to configure the original expression 5 times in total, but I'm struggling to keep it clean when I use insert. Reading the Ruby docs, the insert method is the only one suitable to what I'm doing.
Do I have to use a different data structure to store 1 * 2 / 3 + 4 other than an array?
Consider using #dup so that you don't alter the original set:
expression.dup.insert(0, "((").insert(4, ")").insert(7, ")")
Code
def all_equations(expression)
nums = expression.select { |o| o.kind_of? Numeric }.map(&:to_s)
ops = expression.select { |o| o.is_a? String }.uniq
ops.permutation(ops.size).to_a.map { |ao|
([nums.first] + ao.zip(nums[1..-1]).map(&:join)).join }
end
Examples
all_equations [1.0, "*", 2.0, "/", 3.0, "+", 4.0]
#=> ["1.0*2.0/3.0+4.0", "1.0*2.0+3.0/4.0", "1.0/2.0*3.0+4.0",
# "1.0/2.0+3.0*4.0", "1.0+2.0*3.0/4.0", "1.0+2.0/3.0*4.0"]
a = all_equations [1.0, "*", 2.0, "/", 3.0, "+", 4.0, "-", 4.0, "**", 5.0]
#=> ["1.0*2.0/3.0+4.0-4.0**5.0", "1.0*2.0/3.0+4.0**4.0-5.0",
# ...
# "1.0*2.0+3.0**4.0/4.0-5.0", "1.0*2.0+3.0**4.0-4.0/5.0",
# ...
# "1.0**2.0-3.0+4.0*4.0/5.0", "1.0**2.0-3.0+4.0/4.0*5.0"]
a.size
#=> 120
Explanation
The steps are as follows.
expression = [1.0, "*", 2.0, "/", 3.0, "*", 3.0] # note `"*"` appears twice
nums = expression.select { |o| o.kind_of? Numeric }.map(&:to_s)
#=> ["1.0", "2.0", "3.0", "3.0"]
ops = expression.select { |o| o.is_a? String }
#=> ["*", "/", "*"]
a = ops.uniq
#=> ["*", "/"]
b = a.permutation(a.size)
#=> #<Enumerator: ["*", "/"]:permutation(2)>
c = b.to_a
#=> [["*", "/"], ["/", "*"]]
c.map { |ao| ([nums.first] + ao.zip(nums[1..-1]).map(&:join)).join }
#=> ["1.0*2.0/3.0", "1.0/2.0*3.0"]
uniq has effect only when ops contains duplicates.
Extension
The following permits the numbers to be reordered as well. (I initially thought this was a requirement, which is the only reason I am offering this modification.)
expression = [1.0, "*", 2.0, "/", 3.0, "+", 4.0]
nums = expression.select { |o| o.kind_of? Numeric }.map(&:to_s)
#=> ["1.0", "2.0", "3.0", "4.0"]
ops = expression.select { |o| o.is_a? String }
#=> [["*", "/", "+"], ["*", "+", "/"], ["/", "*", "+"],
# ["/", "+", "*"], ["+", "*", "/"], ["+", "/", "*"]]
anums, aops = nums.permutation(nums.size).to_a.uniq, ops.permutation(ops.size).to_a.uniq
anums
#=> [["1", "2", "3", "4"], ["1", "2", "4", "3"], ["1", "3", "2", "4"],
# ["1", "3", "4", "2"], ["1", "4", "2", "3"], ["1", "4", "3", "2"],
# ["2", "1", "3", "4"], ["2", "1", "4", "3"], ["2", "3", "1", "4"],
# ["2", "3", "4", "1"], ["2", "4", "1", "3"], ["2", "4", "3", "1"],
# ["3", "1", "2", "4"], ["3", "1", "4", "2"], ["3", "2", "1", "4"],
# ["3", "2", "4", "1"], ["3", "4", "1", "2"], ["3", "4", "2", "1"],
# ["4", "1", "2", "3"], ["4", "1", "3", "2"], ["4", "2", "1", "3"],
# ["4", "2", "3", "1"], ["4", "3", "1", "2"], ["4", "3", "2", "1"]]
aops
#=> [["*", "/", "+"], ["*", "+", "/"], ["/", "*", "+"],
# ["/", "+", "*"], ["+", "*", "/"], ["+", "/", "*"]]
a = anums.product(aops).map { |an,ao|
([an.first] + ao.zip(an[1..-1]).map(&:join)).join }
#=> ["1*2/3+4", "1*2+3/4", "1/2*3+4",..., "4/3+2*1", "4+3*2/1", "4+3/2*1"]
a.size
#=> 144
I'm having some issues trying to sort a list of structs in Elixir...
I can't find out what I'm doing wrong.
IO.puts "########### MY TOP 5 #############"
IO.inspect mytop5
IO.puts "================================="
sorted = Enum.sort_by(mytop5, &(&1.count))
IO.inspect sorted
IO.puts "------------------------"
Here's the result
iex(67)> ########### MY TOP 5 #############
iex(67)> [%{count: "3", from: "AUD", rate: 0.64536947, to: "EUR"},
%{count: "10", from: "USD", rate: 1.3876, to: "AUD"},
%{count: "11", from: "USD", rate: 0.89726335, to: "EUR"}]
iex(67)> =================================
iex(67)> [%{count: "3", from: "AUD", rate: 0.64536947, to: "EUR"},
%{count: "11", from: "USD", rate: 0.89726335, to: "EUR"},
%{count: "10", from: "USD", rate: 1.3876, to: "AUD"}]
iex(67)> ------------------------
while :
iex(3)> [%{plop: "aze", count: 5, name: "a"}, %{plop: "aze", count: 1, name: "p"}, %{plop: "aze", count: 45, name: "e"}] |> Enum.sort_by(&(&1.count))
[%{count: 1, name: "p", plop: "aze"}, %{count: 5, name: "a", plop: "aze"},
%{count: 45, name: "e", plop: "aze"}]
This is sorting based on count being a string:
Enum.sort(["3", "10", "5"])# ["10", "3", "5"]
Enum.sort([3, 10, 5]) # [3, 5, 10]
This is because "10" < "3" is true due to the first character:
Enum.sort(["30", "9", "10", "1", "100", "3"])
# ["1", "10", "100", "3", "30", "9"]
You can use String.to_integer/1 to convert it:
Enum.sort_by(mytop5, &(String.to_integer(&1.count)))
I have two arrays like this:
["1","7","8","10"]
and
["1","2","3","6","9","11"]
These arrays represents ids from a class called Place that a user selected. I want to select the places ids with most votes. I tried transpose but as the arrays have different sizes, they cannot be transposed.
The expected output for this example is:
{ "1" => 2, "7" => 1, "8" => 1, "10" => 1, "2" => 1, "3" => 1, "6" => 1, "9" => 1, "11" => 1 }
You can join all arrays and calculate the number of identical elements like this:
arrays = [["1","7","8","10"], ["1","2","3","6","9","11"]].reduce(:+)
arrays.inject(Hash.new(0)) { |memo, e| memo.update(e => memo[e] + 1) }
# "{ "1" => 2, "7" => 1, "8" => 1, "10" => 1, "2" => 1, "3" => 1, "6" => 1, "9" => 1, "11" => 1 }"
Once you have this intermediate result use max_by to select the key with the max value from the hash:
arrays = [["1","7","8","10"], ["1","2","3","6","9","11"]].reduce(:+)
arrays.inject(Hash.new(0)) { |memo, e| memo.update(e => memo[e] + 1) }
.max_by { |_, count| count }[0]
#=> "1"
This is another way:
arr = [["1","7","8","10"], ["1","2","3","6","9","11"], ["1","2","7"]]
h = arr.flatten.sort_by(&:to_i).group_by(&:itself)
h.update(h) { |_,v| v.size }
#=> {"1"=>3, "2"=>2, "3"=>1, "6"=>1, "7"=>2, "8"=>1, "9"=>1, "10"=>1, "11"=>1}
The steps:
a = arr.flatten
#=> ["1", "7", "8", "10", "1", "2", "3", "6", "9", "11", "1", "2", "7"]
b = a.sort_by(&:to_i)
#=> ["1", "1", "1", "2", "2", "3", "6", "7", "7", "8", "9", "10", "11"]
h = b.group_by(&:itself)
#=> {"1"=>["1", "1", "1"], "2"=>["2", "2"], "3"=>["3"], "6"=>["6"],
# "7"=>["7", "7"], "8"=>["8"], "9"=>["9"], "10"=>["10"], "11"=>["11"]}
If you are using a version of Ruby prior to 2.2 (when Object#itself was introduced) you will need to instead write:
h = b.group_by { |s| s }
Lastly:
h.update(h) { |_,v| v.size }
#=> {"1"=>["1", "1", "1"], "2"=>["2", "2"], "3"=>["3"], "6"=>["6"],
# "7"=>["7", "7"], "8"=>["8"], "9"=>["9"], "10"=>["10"], "11"=>["11"]}
This uses the form of Hash#update (aka merge!) that employs a block (here { |_,v| v.size }) to determine the values of keys that are present in both hashes being merged (which in this case is all of the keys).
Update: the method Hash#transform_values made its debut in Ruby v2.4. This allows us to write the following.
arr.flatten.
sort_by(&:to_i).
group_by(&:itself).
transform_values(&:size)
How would I go about generating a sequential alphanumeric string?
Each string should only be 8 characters.
The characters possible for each position are:
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "B", "C", "D", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "V", "W", "X", "Y", "Z"]
Also, If possible I would like to choose the starting point of the sequence.
For example:
00000001
00000002
00000003
00000005
...
0000L3FH
0000L3FJ
0000L3FK
0000L3FL
0000L3FM
0000L3FN
0000L3FP
...
0000L4FP
0000L4FQ
0000L4FR
0000L4FS
...
0000M000
0000M001
0000M002
That is a permutation with repetition. Arrays can do that out of the box.
chars = %w(0 1 2 B C)
sequencer = chars.repeated_permutation(chars.size) #OP:replace chars.size by 8
10.times{p sequencer.next}
#["0", "0", "0", "0", "0"]
#["0", "0", "0", "0", "1"]
#["0", "0", "0", "0", "2"]
#["0", "0", "0", "0", "B"]
#["0", "0", "0", "0", "C"]
#["0", "0", "0", "1", "0"]
#["0", "0", "0", "1", "1"]
#["0", "0", "0", "1", "2"]
#["0", "0", "0", "1", "B"]
#["0", "0", "0", "1", "C"]
p sequencer.next
#["0", "0", "0", "2", "0"]
This one allows for setting the starting point:
dial = %w(0 1 2 A B)
start_position = %w(A B 0) #for instance.
p clock = start_position.map{|char| dial.rotate(dial.index(char))}
#[["A","B","0","1","2"], ["B","0","1","2","A"], ["0","1","2","A","B"]]
# start ticking:
clock.shift.product(*clock){|tick|p tick}
#["A", "B", "0"]
#["A", "B", "1"]
#["A", "B", "2"]
#["A", "B", "A"]
#["A", "B", "B"]
#["A", "0", "0"]
#...