Ruby - permutation program in one line - ruby

just started ruby :)
I am creating a small ruby program where a user inputs a string of letters and it prints all the possible permutations.
I am trying to write a function that is only 1 line long, but im having trouble getting it to run
Any help please :)
puts "Enter phrase:"
input_string = gets.split("")
#function
print input_string.permutation().to_a

Try calling chomp() before calling split():
puts "Enter phrase:"
input_string = gets.chomp().split("")
print input_string.permutation().to_a, "\n"
Example Usage:
Enter phrase:
ABC
[["A", "B", "C"], ["A", "C", "B"], ["B", "A", "C"], ["B", "C", "A"], ["C", "A", "B"], ["C", "B", "A"]]
Try it out here.

In Ruby, you can always write any program on one line, because line breaks are always optional. They can always be replaced with an expression separator (i.e. semicolon ;), a keyword (e.g. then, do), or sometimes just whitespace (e.g. def foo() 42 end).
In your case, that would look like this:
puts "Enter phrase:"; input_string = gets.split(""); print input_string.permutation().to_a
However, focusing on the number of lines is generally not a good idea as it does not necessarily increase readability. We use multiple lines in text to improve readability, so why should the same not also be true for code? Or do you think that writing this paragraph on one line has improved anything?

Related

String sequences with Ruby: Cloning and duplicating

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

Ruby - how to pop a specific element from an array

What would be the easiest way in Ruby to pop a specific element from an array, similar to the .delete method of
a.delete(element)
rather than popping the first/last element or using .slice?
To make this more specific: for example, I can do
case names.sample when "John", "Dave", "Sam"
a.delete(names.sample)
end
to delete one of those names from a when it appears as a sample from names
However, I intend to use multiple samples and using a.delete()will remove all elements at once, rather than in succession like the result produced from shuffle!.pop where elements are popped in succession, so that the name can no longer be selected as a sample from a after the same name has been selected as a name.sample
I was wondering what the easiest way would be in Ruby to pop off these elements in succession, or if it is even possible at all in this context.
The Array class defines a pop method. It returns and deletes the last element in the array.
a = ["a", "b", "c"]
puts a.pop #=> "c"
puts a #=> ["a", "b"]
You can optionally pass an argument to pop that specifies how many elements to pop off.
a = ["a", "b", "c"]
puts a.pop(2) #=> ["b", "c"]
puts a #=> ["a"]
Addressing your last comment, you can use include?, index, and delete_at methods to achieve this. Assuming you're checking for "b" in an array:
a = ["a", "b", "c"]
value_index = a.index("b") #Returns the first occurring index of "b"
has_value = a.include?("b") #Returns whether "b" is in the list
a.delete_at(a.index("b")) if has_value #Removes "b" from the list
In this sample, "has_value" will be whether the a array contains the value "b", and "value_index" will be the first occurrence of "b". This will also delete the value "b" from the list.
If you want to remove all occurrences of "b", you can use include?, index, and delete_at with a while loop:
a = ["a", "b", "c", "a", "b", "c"]
while a.include?("b")
a.delete_at(a.index("b"))
end
#a will now be ["a", "c", "a", "c"]
See also the documentation for Array.
[..] intend to use multiple samples and using a.delete() will remove all elements at once, rather than in succession like the result produced from shuffle!.pop where elements are popped in succession, so that the name can no longer be selected as a sample from a after the same name has been selected as a name.sample[..]
Maybe you are looking something like this?
names = ["John", "Dave", "Sam"]
names.size.times { p names.delete(names.sample) }
#=> "Sam"
#=> "John"
#=> "Dave"

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")

Why does the Array allocation my_arr[0,3] work while my_arr[3,0] fails?

I want to pull two values out from an array based on their index.
Unfortunately this fails when the last index is zero and I don't undertand why.
my_array = ["a", "b", "c", "d", "e", "f", "g"]
my_array[1,2]
# => ["b", "c"]
my_array[0,2]
# => ["a", "b"]
my_array[2,0]
# => []
Why does the last allocation fail to pull out elements 2 and 0?
I suspect my operation is not in fact doing what I think at all since adding a third index makes the whole thing fail:
my_array[1,2,3]
# => ArgumentError: wrong number of arguments (3 for 1..2)
What am I actually doing with the array[var1, var2] syntax and what should I be doing?
my_array[start,length][docs] is the slice syntax:
returns a subarray starting at start and continuing for length elements
This is a short syntax for my_array.slice(start, length);
You should do this instead:
my_array.values_at(2, 0)
=> ["c", "a"]
See Array#values_at and Array#slice

Resources