Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
How can one generate a new list has all the elements of old-list except for some parts bracketted between line where f1(start_line) is true and f2(end_line) is true
Naive code
def remove_bracketted(orig_list)
ignore_flag = false
new_list = []
orig_list.each do |v|
if f1(v)
ignore_flag = true
elsif f2(v)
ignore_flag = false
else
new_list << v unless ignore_flag
end
end
end
For instance, with the following definitions of f1 and f2
def f1(v)
v == "{"
end
def f2(v)
v == "}"
end
when run on
foo(a,b)
{
s1
s2
s3
}
bar(a,b)
{
t1
t2
t3
}
Some other text
one should get
foo(a,b)
bar(a,b)
Some other text
Kindly note that f1 and f2 can be any function of type a -> Bool where list elements are all of type a and not just comparison to an open brace and close brace.
Edit:
I was looking for a solution like this which works if there is only one such pair
new_list = old_list.take_while(not(condition1)).concat(old_list.drop_while(not(condition2)))
This might be a place where the flip-flop operator would be useful:
def val1; '{' end
def val2; '}' end
p ['a','b','{','a','}','f','d','d'].reject{|x| true if (val1==x)..(val2==x)}
#=> ["a", "b", "f", "d", "d"]
p ['a','b','{','a','}','f','d','d'].select{|x| true if (val1==x)..(val2==x)}
#=> ["{", "a", "}"]
ScriptDevil, i guess some people won't like your way of making a question so i suggest asking it somewhat politer and not offer us a 'task' like we are in class. We are here to help and you should show us what you tried yourself.
Here is a way of doing what you want.
class String
def replace_between start, ending, replace_with
gsub(/#{start}[^#{ending}]*#{ending}/m, replace_with)
end
end
txt = %[
foo(a,b)
{
s1
s2
s3
}
bar(a,b)
{
t1
t2
t3
}
Some other text
]
puts txt.replace_between '{', '}', ''
# oo(a,b)
# bar(a,b)
# Some other text
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I want to find out what's the first, the second, and the third result, so that I can do if firstnumber==secondnumber && secondnumber==thirdnumber. How could I find those numbers on the results?
numbers = 3.times.map { Random.new.rand(0..10000) }
prizes = numbers.map do |x|
case x
when 1..3000
[ '7', 10000 ]
when 3001..6000
[ "Cherries", 500 ]
when 6001..10000
[ "Diamond", 400 ]
end
end
puts "Your results are: #{prizes.collect { |p| p[0] }.join(", ")}!
I tried to use p[0][0], but it gives the first letter instead.
Say if:
results = prizes.collect { |p| p[0] } #=> ["Diamond", "Cherries", "7"]
Then do the following to get at each result:
results[0] #=> "Diamond"
results[1] #=> "Cherries"
results[2] #=> "7"
You could also use results.first to get the first element. If you happen to be working in Rails you can even do the following:
results.second #=> "Cherries"
results.third #=> "7"
Here's a fine way to do this:
numbers = 3.times.map { Random.new.rand(0..10000) }
prizes = numbers.map do |x|
case x
when 1..3000
{ name: '7', val: 10000 }
when 3001..6000
{name: "Cherries", val: 10000 }
when 6001..10000
{name: "Diamond", val: 400 }
end
end
# You could replace 'map' with 'collect' here and have the same results
prizes_string = prizes.map { |p| "#{p[:name]}: #{p[:val]}" }.join(" and ")
puts "Your results are: #{prizes_string}!"
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
The to_chr function is supposed to return the encrypted array but converted to characters. I have tried many things and commented out the ones that didn't work.
class Encrypt
def initialize(code, string)
#code = code
#string = string
#encrypted = []
end
def to_byte
#string.each_byte do |c|
#encrypted.push(c + #code)
end
print #encrypted
end
def to_chr
n = #encrypted.length
# n.times do |i|
# #encrypted.push(i.chr)
# end
print #encrypted[0].chr
# #encrypted.each do |x|
# #encrypted.push(x.chr)
# end
# print #encrypted
end
end
goop = Encrypt.new(2, "hello")
goop.to_chr
#=> in `to_chr': undefined method `chr' for nil:NilClass (NoMethodError)
You create instance of Encrypted method, but you set #code = 2, #string = "Hello" and #encrypted = []. So if you call #encrypted[0], ruby return nil.
So you can modify your class like this:
class Encrypt
def initialize(code, string)
#code, #string, #encrypted = code, string, []
end
def to_byte
#string.each_byte { |c| #encrypted << c + #code }
end
def to_chr
to_byte if #encrypted.empty?
#encrypted.map(&:chr)
end
end
goop = Encrypt.new(2, "hello")
p goop.to_chr
# => ["j", "g", "n", "n", "q"]
I hope this helps
def to_chr
#encrypted.each do |i|
print i.chr
end
print "\n"
end
Make sure to call to_byte prior to to_chr
goop = Encrypt.new(2, "hello")
goop.to_byte
goop.to_chr
returns:
jgnnq
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am looking to update a construct on screen as the input changes. The construct will look like so:
puts " | | "
puts " | | "
puts "----+----+----"
puts "make an input (1/2/3/4/5/6)"
selection = gets.chomp
#process selection, returns value, value to be updated in construct.
I defined the spaces for the values as a 2x3 array. The value returned, for example, can be '2' to be stored in space [0][1] (row 1, col 2). The output should then look like:
| 2 |
| |
----+----+----
This needs to happen without re-printing the construct. When the user is prompted (in a loop) to make another selection, again the construct should be updated without re-printing.
May I interest you, fine gentleman, in the battle between good and evil? Heavily inspired by TTT:
require 'dispel'
class Lucky6
BOARD = <<-BOARD.gsub /^\s+/, ''
| X | X | X |
| X | X | X |
----+---+----
BOARD
attr_reader :position
def initialize
#fields = Array.new(6) { ' ' }
#position = 0
end
def board
index = -1
BOARD.gsub(" X ") do
index += 1
field = #fields[index]
#position == index ? "[#{field}]" : " #{field} "
end
end
def set(position)
#position = position.pred
#fields[#position] = position
end
end
def draw(l6)
[l6.board, "1..6=Set r=Reset q=Quit"].join("\n")
end
Dispel::Screen.open do |screen|
l6 = Lucky6.new
screen.draw draw(l6)
Dispel::Keyboard.output do |key|
case key
when ('1'..'6') then l6.set(key.to_i)
when "r" then l6 = Lucky6.new
when "q" then break
end
screen.draw draw(l6)
end
end
What you are asking is not possible using technique of \r, but you can use a trick of clearing the screen as shown below
matrix = [ ["", "", ""], ["", "", ""]]
pos_to_index = [[0, 0], [0, 1], [0, 2], [1,0], [1,1], [1,2]]
system("cls")
begin
print "make an input (1/2/3/4/5/6)\n"
selection = gets.chomp
system("cls")
if (selection.to_i <= pos_to_index.size)
pos = pos_to_index[selection.to_i - 1]
matrix[pos[0]][pos[1]] = selection
matrix.each { |a| a.each { |i| print " #{i.empty? ? ' ' : i} |" }; puts }
puts "---+---+----"
end
end while (not selection.empty?)
PS: system("cls") works on windows, if it does not work for you, try system("clear") as explained here
This question already has answers here:
How do I keep the delimiters when splitting a Ruby string?
(5 answers)
Closed 7 years ago.
This has been asked multiple times around here, but never got a generic answer, so here we go:
Say you have a string, any string, but let's go with "oruh43451rohcs56oweuex59869rsr", and you want to split it with a regular expression. Any regular expression, but let's go with a sequence of digits: /\d+/. Then you'd use split:
"oruh43451rohcs56oweuex59869rsr".split(/\d+/)
# => ["oruh", "rohcs", "oweuex", "rsr"]
That's lovely and all, but I want the digits. So for that we have scan:
"oruh43451rohcs56oweuex59869rsr".scan(/\d+/)
# => ["43451", "56", "59869"]
But I want it all! Is there, say, a split_and_scan? Nope.
How about I split and scan then zip them? Let me stop you right there.
Ok, so how?
If split's pattern contains a capture group, the group will be included in the resulting array.
str = "oruh43451rohcs56oweuex59869rsr"
str.split(/(\d+)/)
# => ["oruh", "43451", "rohcs", "56", "oweuex", "59869", "rsr"]
If you want it zipped,
str.split(/(\d+)/).each_slice(2).to_a
# => [["oruh", "43451"], ["rohcs", "56"], ["oweuex", "59869"], ["rsr"]]
I'm glad you asked… well, there's String#shatter from Facets. I don't love it because it's implemented using trickery (look at the source, it's cute clever trickery, but what if your string actually contains a "\1"?).
So I rolled my own. Here's what you get:
"oruh43451rohcs56oweuex59869rsr".unjoin(/\d+/)
# => ["oruh", "43451", "rohcs", "56", "oweuex", "59869", "rsr"]
And here's the implementation:
class Object
def unfold(&f)
(m, n = f[self]).nil? ? [] : n.unfold(&f).unshift(m)
end
end
class String
def unjoin(rx)
unfold do |s|
next if s.empty?
ix = s =~ rx
case
when ix.nil?; [s , ""]
when ix == 0; [$&, $']
when ix > 0; [$`, $& + $']
end
end
end
end
(verbosier version at the bottom)
And here are some examples of corner cases being handled:
"".unjoin(/\d+/) # => []
"w".unjoin(/\d+/) # => ["w"]
"1".unjoin(/\d+/) # => ["1"]
"w1".unjoin(/\d+/) # => ["w", "1"]
"1w".unjoin(/\d+/) # => ["1", "w"]
"1w1".unjoin(/\d+/) # => ["1", "w", "1"]
"w1w".unjoin(/\d+/) # => ["w", "1", "w"]
And that's it, but here's more…
Or, if you don't like mucking with the built-in classes… well, you could use Refinements… but if you really don't like it, here it is as functions:
def unfold(x, &f)
(m, n = f[x]).nil? ? [] : unfold(n, &f).unshift(m)
end
def unjoin(s, rx)
unfold(s) do |s|
next if s.empty?
ix = s =~ rx
case
when ix.nil?; [s , ""]
when ix == 0; [$&, $']
when ix > 0; [$`, $& + $']
end
end
end
It also occurs to me that it may not always be clear which are the separators and which are the separated bits, so here's a little addition that lets you query a string with #joint? to know what role it played before the split:
class String
def joint?
false
end
class Joint < String
def joint?
true
end
end
def unjoin(rx)
unfold do |s|
next if s.empty?
ix = s =~ rx
case
when ix.nil?; [s, ""]
when ix == 0; [Joint.new($&), $']
when ix > 0; [$`, $& + $']
end
end
end
end
and here it is in use:
"oruh43451rohcs56oweuex59869rsr".unjoin(/\d+/)\
.map { |s| s.joint? ? "(#{s})" : s }.join(" ")
# => "oruh (43451) rohcs (56) oweuex (59869) rsr"
You can now easily reimplement split and scan:
class String
def split2(rx)
unjoin(rx).reject(&:joint?)
end
def scan2(rx)
unjoin(rx).select(&:joint?)
end
end
"oruh43451rohcs56oweuex59869rsr".split2(/\d+/)
# => ["oruh", "rohcs", "oweuex", "rsr"]
"oruh43451rohcs56oweuex59869rsr".scan2(/\d+/)
# => ["43451", "56", "59869"]
And if you hate match globals and general brevity…
class Object
def unfold(&map_and_next)
result = map_and_next.call(self)
return [] if result.nil?
mapped_value, next_value = result
[mapped_value] + next_value.unfold(&map_and_next)
end
end
class String
def unjoin(regex)
unfold do |tail_string|
next if tail_string.empty?
match = tail_string.match(regex)
index = match.begin(0)
case
when index.nil?; [tail_string, ""]
when index == 0; [match.to_s, match.post_match]
when index > 0; [match.pre_match, match.to_s + match.post_match]
end
end
end
end
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have the following code:
class A
end
class B
end
a1 = A.new
a2 = A.new
b1 = B.new
b2 = B.new
array = [a1, a2, b1, b2]
hash = {}
array.each do |obj|
if hash[obj.class] = nil
hash[obj.class] = []
else
hash[obj.class] << obj
end
end
I want hash to be equal to
{ A => [a1,a2], B => [b1,b2] }
but it's telling me I can't use the << operator.
Let's sum it up.
if hash[obj.class] = nil
↑ you are resetting your pair every time your condition runs because of the unique equal that set hash[obj.class] to nil instead of testing its nillity. Use == instead.
Then, you are doing
array.each do |obj|
if hash[obj.class] == nil
hash[obj.class] = [] # if nil, initialize to new array
else # but because of the else, you are not...
hash[obj.class] << obj # doing this so you don't register the first object of each class.
end
end
Conclusion
array.each do |obj|
hash[obj.class] ||= [] # set hash[obj.class] to [] if nil (or false)
hash[obj.class] << obj
end
I think Enumerable#group_by is what you're looking for:
# ...
array = [a1, a2, b1, b2]
hash = array.group_by(&:class)
# => {A=>[#<A:0x0000000190dbb0>, #<A:0x000000018fa470>],
# B=>[#<B:0x000000018e5fe8>, #<B:0x000000018daa80>]}
(And as noted in the comments, the error you're getting is because you're setting hash[obj.class] to nil when you meant to test for equality with ==.)