Trying to check if two strings are permutations of each other - ruby

I am trying to implement this function that checks if two strings are permutations of each other. The code itself is straightforward.
def permutation(a, b)
if a.length != b.length
return False
end
a = a.chars.sort.join
b = b.chars.sort.join
return a == b
end
a = "abcedff"
b = "acbedf"
puts (permutation(a, b).to_s)
However, when I try to run this file on the terminal, I keep getting an error that says
permutation.rb:3:in permutation': uninitialized constant False (NameError)
from permutation.rb:13:in'
I don't understand the reason for this.

Ruby is not Python. You want true and false, not True and False.

Don't over-complicate it. All you need to do is compare two character arrays. For example:
def permutation a, b
a.chars.sort == b.chars.sort
end
Given your corpus as posted, this yields:
a = "abcedff"
b = "acbedf"
permutation a, b
#=> false
permutation a, a
#=> true

Related

Given an array of integers and target, return true if any two elements sum to target

As the title states, I'm looking to find two elements whose sum is equal to the target integer. I've already worked out the solution below, but this works only for unique integers. I'm having an issue when it comes to duplicate values. Of course, I can use multiple loops that keep track of two separate indices and, in this way, make sure those two indices are the same. However, I wanted to see if there was a way to solve this with one iteration.
two_sum([1,2,3,4,5,6], 8) = true
two_sum([4,4], 8) = false
def two_sum(array, target)
idx = 0
while idx < array.length
complement = target - array[idx]
if array.include?(complement) && complement != array[idx]
return true
end
idx+=1
end
return false
end
require 'set'
def two_sum(arr, tot)
st = Set.new
arr.each { |n| st.include?(tot-n) ? (return true) : st << n }
false
end
two_sum [1,2,3,4,5,6], 8 #=> true
two_sum [4,4], 8 #=> true
two_sum [1,2,3,4,5,6], 3421 #=> false
If you'd prefer to return the two values that sum to tot (when true), replace true with [n, tot-n] (or just return n, the other being tot - n).
I used a set rather than an array for faster lookups.
def two_sum(array, target)
array.combination(2).each { |pair| return true if pair.inject(:+) == target }
return false;
end

Check if two ranges overlap in ruby

I know that I can do:
(1..30).cover?(2)
=> true
But when I try to do the same with another range it always returns false:
(1..30).cover?(2..3)
=> false
So my question is - is there any elegant way to compare two ranges in ruby? In my case I want to check if two DateTime-ranges overlap. Thanks in advance.
Two ranges overlap for a given range A when:
range B starts within range A,
range B ends within range A or
range B starts before range A and ends after range A
Examples:
Range A |-----|
|-----| Case 1
|-----| Case 2
|-| Case 1 + 2
|---------| Case 3
Looking closer the rule is: Two ranges overlap when Range B starts before the range A ends and range B ends after the range A starts.
def ranges_overlap?(range_a, range_b)
range_b.begin <= range_a.end && range_a.begin <= range_b.end
end
def overlap?(r1,r2)
!(r1.first > r2.last || r1.last < r2.first)
end
overlap? 1..5, 4..10 #=> true
overlap? 1..5, 6..10 #=> false
overlap? 1..10, 4..8 #=> true
overlap? 1..4, 4..8 #=> true
The operative line is equivalent to:
r1.first <= r2.last && r1.last >= r2.first
I normally try to avoid negation, but in this case I think it reads better with it.
Another way:
def overlap?(r1,r2)
!(([r1.first, r2.first].min..[r1.last, r2.last].max).size >= r1.size + r2.size)
end
overlap? 1..5, 4..10 #=> true
overlap? 1..5, 6..10 #=> false
overlap? 1..10, 4..8 #=> true
overlap? 1..4, 4..8 #=> true
The operative line is equivalent to:
([r1.first, r2.first].min..[r1.last, r2.last].max).size < r1.size + r2.size
Again, I prefer the one with negation.
In rails You can use (1..3).overlaps?(2..4) # true
https://apidock.com/rails/Range/overlaps
If you want the rails implementation you can use
class Range
def overlaps?(other)
cover?(other.first) || other.cover?(first)
end
end
(1..5).overlaps?(4..6) # => true
(1..5).overlaps?(7..9) # => false
While the conversions may be wasteful, semantically comparing sets seems to make the most sense:
Set.new(1..30).superset?(Set.new(2..3))
#=> true
Set.new(1..30).superset?(Set.new(0..3))
#=> false
If you don't want to do that, you can do something like this (with r1 and r2 being ranges):
r1.cover?(r2.min) && r1.cover?(r2.max)
You can check Overlapping using
range1.first < range2.last && range2.first < range1.last
You can add it as an instance method of range or as a helper method somewhere in you data.
source: https://stackoverflow.com/a/325964/4091324

pythagorean triangle with any side equal to zero

So I have this spec I'm trying to solve for (I did not write the spec)...
it "returns false if any of the arguments are 0" do
# [0, 1, 1].permutation(3) returns all permutations of [0, 1, 1]
length = rand(0.01..100.0)
[0, length, length].permutation(3).all? { |(a,b,c)| valid_triangle?(a,b,c) }.should be_false
end
Here is my code
def valid_triangle?(a, b, c)
#A Pythagorean triple consists of three positive integers a, b, and c, such that a2 + b2 = c2.
if a > 0 && b > 0 && c > 0
one = a**2
two = b**2
three = c**2
if one+two=three
return "true"
else
return "false"
end
else
return "false"
end
end
How can I pass my spec? What am I missing?
The main problem is that when the test permutes the values of a, b and c, your method is not always checking that it is the square of the hypotenuse that equals the sum of the squares of the other two sides. For example, if a=3, b=4 and c=5, one of your tests will be 4*4 + 5*5 == 3*3. You need to sort a, b and c before checking the sum of squares, which is a good idea anyway, since the position of the hypotenuse among the parameters is not guaranteed. You could also simplify your code somewhat. Here's one way you could write it:
TOLERANCE = 0.01
def right_triangle?(a, b, c)
return false if a == 0 || b == 0 || c == 0
a, b, c = [a,b,c].sort
(a**2 + b**2 - c**2).abs < TOLERANCE
end
length = rand(0.01..100.0)
[0.0, length, length].permutation(3).all? { |(a,b,c)| right_triangle?(a,b,c)}
#=> false
[3,4,5].permutation(3).all? { |(a,b,c)| right_triangle?(a,b,c) }
#=> true
Since you are dealing with floats, you need to establish some level of tolerance when comparing values for equality. I've used an arbitrary fixed amount (0.01) for demonstration purposes.
You are returning "false" and "true" instead of false and true, also you check that one+two=three, when you should check one+two==three (an equals check, not an assignment)
def valid_triangle?(a, b, c)
#A Pythagorean triple consists of three positive integers a, b, and c, such that a2 + b2 = c2.
if a > 0 && b > 0 && c > 0
one = a**2
two = b**2
three = c**2
if one+two == three
return true
else
return false
end
else
return false
end
end

Define a method `sum_to_n?`

I have the code below. Method sum_to_n? takes an array arr of integers and an integer n as arguments and returns true if any two elements in arr sum to n. It should return true for empty arr with zero n, but keeps returning false.
def sum_to_n?(arr, n)
hash = Hash.new(0)
arr.each do |val|
if hash.key? val
return true
else
hash[n-val] = val
end
end
return false
end
What am I doing wrong?
shorter version:
def sum_to_n?(arr, n)
(arr.empty? && n.zero?) || arr.permutation(2).any? { |a, b| a + b == n }
end
Your code is (almost) correct, but your expectation is wrong. Your code returns true when there are two (or one) element that adds up to n. If you pass an empty array, then there will not be any element(s) that add up to n (because there is no element in the array in the first place). Hence, you get false.
If you want it to return true for an empty array, then that would be an exceptional behavior that does not follow logically. You will have to put a condition such as
return true if arr.empty?
in your code.

Ruby -If-Else Statement (Triangle Test)

The question is Create a function that takes three numbers as input and returns true or false depending on whether those three numbers can form a triangle. Three numbers can form a triangle if the sum of any two sides is greater than the third side.
my answer is:
def is_triangle(a,b,c)
if a+b > c
return true
elsif a+c>b
return true
elsif b+c>a
return true
else
return false
end
end
the thing is: my supposed false return keeps returning true. please help!
This logic should work for finding your triangle
def is_triangle?(a,b,c)
sorted = [a,b,c].sort
greatest_side = sorted.pop
greatest_side < sorted.sum
end
Yet another approach:
def is_triangle?(a,b,c)
[a,b,c].max < [a,b,c].sum/2.0
end
Or for Ruby outside of Rails:
def is_triangle?(a,b,c)
[a,b,c].max < [a,b,c].inject(:+)/2.0
end
Your problem is that unless all 3 numbers are 0 one of your ifs will always be true. What you want is something more like
def is_triangle(a,b,c)
a + b > c && a + c > b && b + c > a
end
is_triangle(3,6,8) #=> true
is_triangle(3,6,80) #=> false
Nothing you pass into this is going to return false. Your method is wrong.
You can tell if three sides make a triangle by finding the longest side and then adding the remaining two sides. If they are greater than the longest side, then the sides can make a traingle.
I suggest if you are sure your logic is correct change the method to
def is_triangle?(a, b, c)
a+b > c or b+c > a or c+a > b
end
But according to me it is not so the method should be
def is_triangle?(a, b, c)
a+b>c and b+c>a and c+a>b
end
Some points to note about ruby conventions:
Method which returns boolean ends with '?'
A ruby method returns the last evaluated expression, so writing return is redundant here.
puts " enter a, b and c values"
a=gets.to_i
b=gets.to_i
c=gets.to_i
if a+b > c
print true
elsif a+c>b
print true
elsif b+c>a
print true
else
print false
end
you can also use this code too.. this is much easy
This is also a solution to this problem :
if 2*[a,b,c].max < a + b + c
true
else
false
end
There are a variety of different inequalities theoretically possible:
http://en.wikipedia.org/wiki/Triangle_inequality

Resources