Generate all way of arranging a given number of elements - ruby

I would like to generate all possible way of arranging of a certain number of elements number_of_elements. For now, I just want to print every possibility up to the possibility upto.
Edit: Say number_of_elements is 3, then I want all possible ways of arranging 0, 1 and 2. A number can appear 0 or many times, and order is important. So 0 != 00 != 01 != 10 != 11.
For example, all_combinations(3, 14) should print:
0
1
2
00
01
02
10
11
12
20
21
22
000 # updated. I originally put 100 here by mistake.
001
...
I tried this:
def all_combinations(number_of_elements, upto)
0.upto upto do |n|
puts n.to_s(number_of_elements)
end
end
all_combinations(3, 10)
My idea is to get all integers, convert them to base number_of_elements and interpret that number as the possibilities.
It almost works, except that I am missing some elements.
(This is the output I get with the code above) :
0
1
2
# 00 missing
# 01 missing
# 02 missing
10
11
12
20
21
22
# 0.. elements missing
100
101
...
Any idea or other simple method to get those?

Confer this question. The following is a slight modification of my answer there.
class Numeric
def sequence b
s, q = "", self
(q, r = (q - 1).divmod(b)) && s.prepend(r.to_s) until q.zero?
s
end
end
def foo(number_of_elements, upto)
1.upto upto do |n|
puts n.sequence(number_of_elements)
end
end
foo(3, 14)
Result:
0
1
2
00
01
02
10
11
12
20
21
22
000
001

You can do this using Array#repeated_permuation:
def all_combinations(nbr, upto)
(1..nbr).each_with_object([]) do |n, arr|
arr.concat(('0'...nbr.to_s).to_a
.repeated_permutation(n)
.to_a) if arr.size < upto
end.first(upto).each { |e| puts e.join }
end
all_combinations(3, 14)
0
1
2
00
01
02
10
11
12
20
21
22
000
001
If number_of_elements is large, this approach has the disadvantage that a substantial number of permutations may be added to the array arr, but not used. One alternative is to create an enumerator object which can be used to enumerate repeated permutations using Enumerator#next and Enumerator#peek, enumerating exactly upto values. I showed how to do that for permutation here and explained how it would be even easier for repeated_permutation.

Probably the cleanest way to attack this is--unfortunately, if you're not versed in recursion--with a recursive method.
You want to try every possible digit in every possible place, basically.
def all_combinations(s, number_of_elements, upto)
if number_of_elements < 1
puts s
return
end
0.upto upto - 1 do |n|
all_combinations(s + n.to_s, number_of_elements - 1, upto)
end
end
all_combinations("", 3, 10)
The premise is that, wherever you've gotten to in the process (s; imagine it's 12), you want to append all possible digits to it and continue. But, we don't want to go forever, and each digit we place gets us closer, so reduce number_of_elements; when number_of_elements is zero, we have nothing else to do, so it's time to print.
A couple of issues:
- upto doesn't know how big it is. If you call all_combinations("", 3, 500), you'll get badly-formed strings.
- As mentioned, if you're just learning programming, recursion might not be the best place to dive in.
- Likewise, if this is for homework and you haven't covered recursion, this would be a good sign that you're asking random people on the Internet for help, which may not result in an ideal grade.
With those caveats, though, I think this is the most straightforward approach. Everything else that comes to mind requires keeping track of positions and recent outputs manually, which...ick.

Here is a concise way of doing it using repeated_permutations:
def all_combinations(number_of_elements, upto)
elements = (0...number_of_elements).map(&:to_s)
combinations = (1..1.0/0).lazy.flat_map do |i|
elements.repeated_permutation(i).map do |permutation|
permutation.join
end
end
puts combinations.take(upto).to_a
end
all_combinations(3, 14)
0
1
2
00
01
02
10
11
12
20
21
22
000
001

Here's another way of doing this, using String#to_i and Fixnum#to_s, each with the argument base (which defaults to 10) set equal to the "number of elements":
def all_combinations(n_elements, upto)
s = '10'
upto.times.with_object([]) do |_,arr|
arr << s
candidate = (s.to_i(n_elements)+1).to_s(3)
(candidate = '1'+'0' * s.size) unless candidate[0] == '1'
s = candidate
end.map { |str| str[1..-1] }
end
all_combinations(3, 15)
#=> ["0", "1", "2",
# "00", "01", "02",
# "10", "11", "12",
# "20", "21", "22",
# "000", "001", "002"]

Related

How to pass a specific value to each thread of a pool in Ruby?

Disclaimer: I'm terrible at coding and not a native speaker!
In the following piece of code, when order = 4, check method gets called as and when a new cCycle is generated. The puts currCycle in check method prints 0 1 2 4 9 3 6 13 10 5 11 7 15 but when I print the same in getData method of a thread, it prints 1 1 3 3 9 9 13 13 5 11 7 7 15. I'm not completely sure why this is happening.
I need each thread to perform some operations on the currCycle value that was passed to it.
I have tried to clone/dup the currCycle object so that each thread works on one specific value rather than multiple threads operating on the same value and skipping few. (I'm guessing this has something to do with shared memory or race condition)
require 'thread/pool'
$cycle = ""
$order = 4
def debruijn($order)
# ....
loop {
#....
# cCycle values in each iteration {0, 0001, 0011, 01, 0111, 1}
check(cCycle)
#....
}
# ....
end
def check(cCycle)
$cycle = $cycle + cCycle # append cCycle to left over subsequence from previous iteration
pool = Thread.pool(1,8)
while $cycle.length >= $order do
# Get first n (=order) bits from cycle
currCycle = $cycle[0...$order].to_i(2).to_s # binary string to integer string
# pop the first char from cycle
$cycle = $cycle[1..-1]
puts currCycle
pool.process {
getData(currCycle)
}
end
while !pool.done? do
sleep(2)
end
pool.shutdown
end
def getData(currCycle)
puts currCycle
# perform operations on currCycle
end
# ....
I'm working on a personal research project that generates a De Bruijn Sequence. For example, debruijn(order=4) would produce 0000100110101111. This sequence contains all possible 4 bit subsequences from 0000 to 1111 if you traverse from left to right 4 bits at a time and append bits from the beginning when you reach the end (a cyclic sequence). {0000, 0001, 0010, ...., 1111, 1110, 1100, 1000}
The algorithm that generates this sequence, in each iteration, generates a string (cCycle) either of length 1, 2 or 4 like 1, 10 or 1011. Since I'm working with higher orders (order=128+, sequenceLength = 2**order), saving the entire sequence is impractical and unnecessary.

Returning the highest and lowest numbers in a string: Ruby

Not sure what I'm doing incorrect but I seem to be getting it woefully wrong.
The question is, you are given a string of space separated numbers, and have to return the highest and lowest number.
Note:
All numbers are valid Int32, no need to validate them.
There will always be at least one number in the input string.
Output string must be two numbers separated by a single space, and highest number is first.
def high_and_low(numbers)
# numbers contains a string of space seperated numbers
#return the highest and lowest number
numbers.minmax { |a, b| a.length <=> b.length }
end
Output:
`high_and_low': undefined method `minmax' for "4 5 29 54 4 0 -214 542 -64 1 -3 6 -6":String
minmax is not implemented for a string. You need to split your string into an array first. But note that split will return an array of strings, not numbers, you will need to translate the strings to integers (to_i) in the next step.
Because minmax returns the values in the opposite order than required, you need to rotate the array with reverse and then just join those numbers with whitespace for the final result.
numbers = "4 5 29 54 4 0 -214 542 -64 1 -3 6 -6"
def high_and_low(numbers)
numbers.split.minmax_by(&:to_i).reverse.join(' ')
end
high_and_low(numbers)
#=> "542 -214"
How about:
numbers_array = numbers.split(' ')
"#{numbers_array.max} #{numbers_array.min}"
If you're starting with a string of numbers you may have to cast the .to_i after the call to split.
In that case:
numbers_array = numbers.split(' ').map { |n| n.to_i }
"#{numbers_array.max} #{numbers_array.min}"
As you're starting with a String, you must turn it into an Array to cast minmax on it.
Also, make sure to compare Integers by casting .map(&:to_i) on the Array; otherwise you'd compare the code-point instead of the numerical value.
def get_maxmin(string)
string.split(' ')
.map(&:to_i)
.minmax
.reverse
.join(' ')
end
There is no need to convert the string to an array.
def high_and_low(str)
str.gsub(/-?\d+/).
reduce([-Float::INFINITY, Float::INFINITY]) do |(mx,mn),s|
n = s.to_i
[[mx,n].max, [mn,n].min]
end
end
high_and_low "4 5 29 54 4 0 -214 542 -64 1 -3 6 -6"
#=> [542, -214]
Demo
This uses the form of String#gsub that has one argument and no block, so it returns an enumerator that I've chained to Enumerable#reduce (a.k.a. inject). gsub therefore merely generates matches of the regular expression /-?\d+/ and performs no substitutions.
My solution to this kata
def high_and_low(numbers)
numbers.split.map(&:to_i).minmax.reverse.join(' ')
end
Test.assert_equals(high_and_low("4 5 29 54 4 0 -214 542 -64 1 -3 6 -6"), "542 -214")
#Test Passed: Value == "542 -214"
Some docs about methods:
String#split Array#map Array#minmax Array#reverse Array#join
More about Symbol#to_proc
numbers.split.map(&:to_i) is same as number.split.map { |p| p.to_i }
But "minmax_by(&:to_i)" looks better, for sure I guess.

Find all natural numbers which are multiplies of 3 and 5 recursively

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.
def multiples_of(number)
number = number.to_f - 1.0
result = 0
if (number / 5.0) == 1 || (number / 3.0) == 1
return result = result + 5.0 + 3.0
elsif (number % 3).zero? || (number % 5).zero?
result += number
multiples_of(number-1)
else
multiples_of(number-1)
end
return result
end
p multiples_of(10.0)
My code is returning 9.0 rather than 23.0.
Using Core Methods to Select & Sum from a Range
It's not entirely clear what you really want to do here. This is clearly a homework assignment, so it's probably intended to get you to think in a certain way about whatever the lesson is. If that's the case, refer to your lesson plan or ask your instructor.
That said, if you restrict the set of possible input values to integers and use iteration rather than recursion, you can trivially solve for this using Array#select on an exclusive Range, and then calling Array#sum on the intermediate result. For example:
(1...10).select { |i| i.modulo(3).zero? || i.modulo(5).zero? }.sum
#=> 23
(1...1_000).select { |i| i.modulo(3).zero? || i.modulo(5).zero? }.sum
#=> 233168
Leave off the #sum if you want to see all the selected values. In addition, you can create your own custom validator by comparing your logic to an expected result. For example:
def valid_result? range_end, checksum
(1 ... range_end).select do |i|
i.modulo(3).zero? || i.modulo(5).zero?
end.sum.eql? checksum
end
valid_result? 10, 9
#=> false
valid_result? 10, 23
#=> true
valid_result? 1_000, 233_168
#=> true
There are a number of issues with your code. Most importantly, you're making recursive calls but you aren't combining their results in any way.
Let's step through what happens with an input of 10.
You assign number = number.to_f - 1.0 which will equal 9.
Then you reach the elsif (number % 3).zero? || (number % 5).zero? condition which is true, so you call result += number and multiples_of(number-1).
However, you're discarding the return value of the recursive call and call return result no matter what. So, your recursion doesn't have any impact on the return value. And for any input besides 3 or 5 you will always return input-1 as the return value. That's why you're getting 9.
Here's an implementation which works, for comparison:
def multiples_of(number)
number -= 1
return 0 if number.zero?
if number % 5 == 0 || number % 3 == 0
number + multiples_of(number)
else
multiples_of(number)
end
end
puts multiples_of(10)
# => 23
Note that I'm calling multiples_of(number) instead of multiples_of(number - 1) because you're already decrementing the input on the function's first line. You don't need to decrement twice - that would cause you to only process every other number e.g. 9,7,5,3
explanation
to step throgh the recursion a bit to help you understand it. Let's say we have an input of 4.
We first decrement the input so number=3. Then we hits the if number % 5 == 0 || number % 3 == 0 condition so we return number + multiples_of(number).
What does multiples_of(number) return? Now we have to evaluate the next recursive call. We decrement the number so now we have number=2. We hit the else block so now we'll return multiples_of(number).
We do the same thing with the next recursive call, with number=1. This multiples_of(1). We decrement the input so now we have number=0. This matches our base case so finally we're done with recursive calls and can work up the stack to figure out what our actual return value is.
For an input of 6 it would look like so:
multiples_of(6)
\
5 + multiples_of(5)
\
multiples_of(4)
\
3 + multiples_of(3)
\
multiples_of(2)
\
multiples_of(1)
\
multiples_of(0)
\
0
The desired result can be obtained from a closed-form expression. That is, no iteration is required.
Suppose we are given a positive integer n and wish to compute the sum of all positive numbers that are multiples of 3 that do not exceed n.
1*3 + 2*3 +...+ m*3 = 3*(1 + 2 +...+ m)
where
m = n/3
1 + 2 +...+ m is the sum of an algorithmic expression, given by:
m*(1+m)/2
We therefore can write:
def tot(x,n)
m = n/x
x*m*(1+m)/2
end
For example,
tot(3,9) #=> 18 (1*3 + 2*3 + 3*3)
tot(3,11) #=> 18
tot(3,12) #=> 30 (18 + 4*3)
tot(3,17) #=> 45 (30 + 5*3)
tot(5,9) #=> 5 (1*5)
tot(5,10) #=> 15 (5 + 2*5)
tot(5,14) #=> 15
tot(5,15) #=> 30 (15 + 3*5)
The sum of numbers no larger than n that are multiple of 3's and 5's is therefore given by the following:
def sum_of_multiples(n)
tot(3,n) + tot(5,n) - tot(15,n)
end
- tot(15,n) is needed because the first two terms double-count numbers that are multiples of 15.
sum_of_multiples(9) #=> 23 (3 + 6 + 9 + 5)
sum_of_multiples(10) #=> 33 (23 + 2*5)
sum_of_multiples(11) #=> 33
sum_of_multiples(12) #=> 45 (33 + 4*3)
sum_of_multiples(14) #=> 45
sum_of_multiples(15) #=> 60 (45 + 3*5)
sum_of_multiples(29) #=> 195
sum_of_multiples(30) #=> 225
sum_of_multiples(1_000) #=> 234168
sum_of_multiples(10_000) #=> 23341668
sum_of_multiples(100_000) #=> 2333416668
sum_of_multiples(1_000_000) #=> 233334166668

I keep getting an error that I don't understand

I am trying to create a function that takes a string in it's parameters. It's supposed to determine the highest and lowest numeric values in the string and return them unchanged.
Here's my code:
def high_and_low(numbers)
numbers.split
numbers.each {|x| x.to_i}
return numbers.max().to_s, numbers.min().to_s
end
Here's the error:
main.rb:5:in `high_and_low': undefined method `each' for "4 5 29 54 4 0 -214 542 -64 1 -3 6 -6":String (NoMethodError)
from main.rb:8:in `<main>'
You have not changed the value from string to array.
Replace numbers.split with numbers = numbers.split.
Also you will need to change from numbers.each { |x| x.to_i } to numbers.map!(&:to_i). Otherwise you don't save integers anywhere.
BTW you don't have to use () and return (if it's in the end) so you can write [numbers.max.to_s, numbers.min.to_s].
Something like this should work:
def high_and_low(numbers)
numbers = numbers.split.map(&:to_i)
[numbers.max, numbers.min].map(&:to_s)
end
high_and_low("4 5 29 54 4 0 -214 542 -64 1 -3 6 -6") #=> ["542", "-214"]
And bonus (one liner, not that you should write code this way):
def high_and_low(numbers)
numbers.split.map(&:to_i).sort.values_at(-1, 0).map(&:to_s)
end
high_and_low("4 5 29 54 4 0 -214 542 -64 1 -3 6 -6") #=> ["542", "-214"]
The other answer is a good approach too so I include it here:
numbers.split.minmax_by { |n| -n.to_i }
Ruby has some nice methods available to make this much more simple:
"2 1 0 -1 -2".split.map(&:to_i).minmax
# => [-2, 2]
Breaking it down:
"2 1 0 -1 -2".split # => ["2", "1", "0", "-1", "-2"]
.map(&:to_i) # => [2, 1, 0, -1, -2]
.minmax # => [-2, 2]
If you want string versions of the values back, compare two integers in a block. minmax will return the values at the corresponding positions in the source array:
"2 1 0 -1 -2".split.minmax{ |a, b| a.to_i <=> b.to_i }
# => ["-2", "2"]
or:
"2 1 0 -1 -2".split.minmax_by{ |a| a.to_i }
# => ["-2", "2"]
minmax and minmax_by do the heavy lifting. The first is faster when there isn't a costly lookup to find the values being compared such as this case where the values are in an array and only needed to_i to compare them.
The *_by version performs a "Schwartzian transform" which basically remembers the values in the block as they're compared so the costly lookup only occurs once. (Many of Enumerable's methods have *_by versions.) These versions of the methods can improve the speed when you want to compare two values that are nested, perhaps in arrays of hashes of hashes, or objects within objects within objects.
Note: When comparing string versions of numbers it's important to convert to a numeric value when comparing. ASCII and strings order differently than numbers, hence the use of to_i.

Ruby Array - highest integer

brand new to Ruby, and love it. Just playing around with the below code:
public
def highest
highest_number = 0
each do |number|
number = number.to_i
highest_number = number if number > highest_number
puts highest_number
end
end
array = %w{1 2 4 5 3 8 22 929 1000 2}
array.highest
So at the moment the response I get is:
1
2
4
5
5
8
22
929
1000
1000
So it puts the array first, then the highest number from the array as well. However all I want it to is put the highest number only...
I have played around with this and can't figure it out! Sorry for such a newbie question
The problem is that you have the puts statement inside the each loop, so during every iteration it prints out what the highest number currently is. Try moving it outside the each loop so that you have this:
public
def highest
highest_number = 0
each do |number|
number = number.to_i
highest_number = number if number > highest_number
end
puts highest_number
end
array = %w{1 2 4 5 3 8 22 929 1000 2}
array.highest
Which produces the desired output:
1000
You could also save yourself some trouble by using max_by:
>> a = %w{1 2 4 5 3 8 22 929 1000 2}
=> ["1", "2", "4", "5", "3", "8", "22", "929", "1000", "2"]
>> m = a.max_by { |e| e.to_i }
=> "1000"
You could also use another version of max_by:
m = a.max_by(&:to_i)
to avoid the extra noise of the "block that just calls a method".
But this is probably a Ruby blocks learning exercise for you so using existing parts of the standard libraries doesn't count. OTOH, it is good to know what's in the standard libraries so punting to max_by or max would also count as a learning exercise.
You can do this instead and avoid the highest_number variable.
array = %w{1 2 4 5 3 8 22 929 1000 2}
class Array
def highest
collect { |x| x.to_i }. \
sort. \
last.to_i
end
end
array.highest # 1000
The collect { |x| x.to_i } can also be written as collect(&:to_i) in this case.

Resources