Can this be refactored into boolean? board is an array and move is and index. position_taken?(board, move) should return false if board[move] is " ", "" or nil but return true if board[move] is "X" or "O".
def position_taken?(board, move)
if board[move] == " "
false
elsif board[move] == ""
false
elsif board[move] == nil
false
else
true
end
end
Since you have less and simpler positive cases I would test for the opposite:
def position_taken?(board, move)
%w[X O].include?(board[move])
end
It will handle invalid values differently than your original approach but it does directly what the method name suggests: check if the position is taken (instead of checking if the position is not not taken).
You can use none? and pass board[move] to be compared:
[' ', '', nil].none?(nil) # false
[' ', '', nil].none?('') # false
[' ', '', nil].none?(' ') # false
[' ', '', nil].none?('t') # true
It's hard to know what your method is doing without knowing what you will pass as board argument so the best I can demo is just a string:
str=''
!!(str && !str.strip.empty?)
#=> false
str='a'
!!(str && !str.strip.empty?)
#=> true
str=' '
!!(str && !str.strip.empty?)
#=> false
str=' '
!!(str && !str.strip.empty?)
#=> false
str=nil
!!(str && !str.strip.empty?)
#=> false
I think this is logically equivalent:
def position_taken?(board, move)
!(board[move] == " " || board[move] == "" || board[move] == nil)
end
If any of the conditions are true, it will be inverted and return false. If all of the conditions are false, it will be inverted to true.
You could also put the strings you want to match against in an array and use something like !include? or, if you're using ActiveSupport, you can use exclude?.
def position_taken?(board, move)
["", " ", nil].exclude?(board[move])
end
FWIW, this code should be refactored to:
def position_taken?(board, move)
not board[move].to_s.strip.empty?
end
If only X or O is allowed, Why don't you specify them in the condition like this:
boared[idx] == 'X' || board[idx] == 'O'
I think it is much better for readability and simple.
def position_taken?(board, move)
!case board[move]; when " ", "", nil; true end
end
Found the solution. It can be refactored to this:
def position_taken?(board, move)
board[move] != " " && board[move] != ""
end
Related
fairly new to programming and came across the following code which does gives the intended result, that is it stores the object in the instance variable if passed as an argumnet or defaults to generating a new object and storing that. but the syntax is using an or(||) operator which as i understood always returns a boolean. so is it behaving differently or there is more to or/and operators?
def initialize(args = {})`
#sms = args[:sms] || Messenger.new
end
The or operator in ruby does not "return" a boolean: it evalutes to the first expression if the first expression is truthy (a term which means everything but false and nil), otherwise it evalutes to the latter
5 || nil => 5
nil || 5 => 5
false || nil => nil
nil || false => false
in ruby, everything can be evaluated as an expression, and an expression will return a value
so || and even && do not return a boolean it will return a truthy or falsy value
in the case of || it will check if the first expression is truthy if not it will go to the next one, then the next one, if no truthy value is found it will return the last one which will be falsy as well
irb(main):004:0> nil || "true value" || 0
=> "true value"
irb(main):006:0> nil || false || "true value" || 0 || true
=> "true value"
in the case of && it will do the opposite, it will return the first falsy value it can find
irb(main):001:0> nil && false && "true value" && 0 && true
=> nil
and the if condition will understand truthy and falsy values which will be what these logical operators return
rb(main):007:0> if "true"
irb(main):008:1> puts "true"
irb(main):009:1> else
irb(main):010:1> puts "false"
irb(main):011:1> end
true
irb(main):017:0> if nil
irb(main):018:1> puts "true"
irb(main):019:1> else
irb(main):020:1> puts "false"
irb(main):021:1> end
false
I need help on Writing a method that takes a string in and returns true if the letter "z" appears within three letters after an "a". You may assume that the string contains only lowercase letters. here's what I have:
def nearby_az(string)
string.downcase!
i = 0
while i < string.length
if (string[i] == "a" && string[i] == "z")
true
else
false
end
end
end
puts('nearby_az("baz") == true: ' + (nearby_az('baz') == true).to_s)
puts('nearby_az("abz") == true: ' + (nearby_az('abz') == true).to_s)
puts('nearby_az("abcz") == true: ' + (nearby_az('abcz') == true).to_s)
puts('nearby_az("a") == false: ' + (nearby_az('a') == false).to_s)
puts('nearby_az("z") == false: ' + (nearby_az('z') == false).to_s)
puts('nearby_az("za") == false: ' + (nearby_az('za') == false).to_s)
A regular expression would be the best for this. Try
def nearby_az(string)
(string =~ /a.{0,2}z/) != nil
end
EDIT:
as per the "if statement required requirement" :)
def nearby_az(string)
if (string =~ /a.{0,2}z/) != nil
return true
end
return false
end
The way this code works is it searches the input string for an "a". After that, the period indicates that you can have any character. After that you have {0,2} which is a modifier of the period indicating you can have 0 to 2 of any character. After this you must have a "z", and this fulfills your must have a z within 3 characters of an "a".
I've saved this regex to regex101 here so you can try various inputs as well as change the regular expression around to understand it better.
To fix you code you need to:
increment i at the end of the loop.
search the z letter within the 3 next letters
return true when condition is met
return false when getting out of the loop
Here is what it should look like:
def nearby_az(string)
string.downcase!
i = 0
while i < string.length do
return true if string[i] == "a" && string[i+1,3].include?(?z)
i+=1
end
return false
end
def starts_with_consonant?(str)
str.empty? || str.class != String || /\A[^aeiou]/i=~str
end
p starts_with_consonant? "Apple" #=>nil
p starts_with_consonant? "microsoft"#=> 0
I expect it to return true or false, but it returns nil and 0.
Its because the Regex test in your last expression returns nil or 0, in the case of a match. You need to coerce the match into a boolean
def starts_with_consonant?(str)
str.empty? || str.class != String || (/\A[^aeiou]/i=~str != nil)
end
In Ruby every object is considered true(truthy), except for nil and false. This includes 0:
puts '0 is true' if 0
0 is true
For all intents and purposes, your code already returns false and true, it will work correctly with if or boolean operators like && and ||.
Only direct comparison will show the difference:
starts_with_consonant? "Apple" == false
=> false
But such comparison is not needed for anything in Ruby, and often is considered bad style. Just use if or unless
if starts_with_consonant? "Apple"
#...
end
unless starts_with_consonant? "Apple"
#...
end
This method is supposed to take a string and detect if the brackets '(' '{' '[' in the string are closing properly with the corresponding (opposite) brackets.
First, is there a more elegant, compact way to write this bit without using all the "or"s (||):
split_array.each do |i|
if (i == "{" || i == "(" || i == "[")
left.push(i)
else (i == "}" || i == ")" || i == "]")
right.push(i)
end
end
My second question is, is this code terrible (see below)? It seems I should be able to write this in way fewer lines, but logically, I haven't come up with another solution (yet.)
The code works for most tests, but it returns false for this test (see all driver tests at bottom): p valid_string?("[ ( text ) {} ]") == true
Any critique would be greatly appreciated!
(also, if there is a better section to post this, please let me know)
Thanks!
def valid_string?(string)
opposites = { "[" => "]", "{" => "}", "(" => ")", "]" => "[", "}" => "{", ")" => "(" }
left = Array.new
right = Array.new
return_val = true
split_array = string.split(//)
split_array.delete_if { |e| e.match(/\s/) }
split_array.each do |i|
if (i == "{" || i == "(" || i == "[")
left.push(i)
else (i == "}" || i == ")" || i == "]")
right.push(i)
end
end
# p left
# p right
left.each_index do |i|
if left[i] != opposites[right[i]]
return_val = false
end
end
return_val
end
p valid_string?("[ ] } ]") == false
p valid_string?("[ ]") == true
p valid_string?("[ ") == false
p valid_string?("[ ( text ) {} ]") == true
p valid_string?("[ ( text { ) } ]") == false
p valid_string?("[ (] {}") == false
p valid_string?("[ ( ) ") == false
-------Updated: After trying some different approaches, my refactor is this:-----------
def valid_string?(str)
mirrored = { "[" => "]", "{" => "}", "(" => ")" }
open_brackets = Array.new
split_str_array = str.split("")
split_str_array.each do |bracket|
if bracket.match(/[\[|\{|\(]/) then open_brackets.push(bracket)
elsif bracket.match(/[\]|\}|\)]/)
return false if mirrored[open_brackets.pop] != bracket
end
end
open_brackets.empty?
end
My approach is as below :
def valid_string?(string)
open_paren = ['[','{','(']
close_paren = [']','}',')']
open_close_hash = {"]"=>"[", "}"=>"{", ")"=>"("}
stack = []
regex = Regexp.union(close_paren+open_paren)
string.scan(regex).each do |char|
if open_paren.include? char
stack.push(char)
elsif close_paren.include? char
pop_val = stack.pop
return false if pop_val != open_close_hash[char]
end
end
open_paren.none? { |paren| stack.include? paren }
end
valid_string?("[ ] } ]") # => false
valid_string?("[ ]") # => true
valid_string?("[ ") # => false
valid_string?("[ (] {}") # => false
valid_string?("[ ( ) ") # => false
valid_string?("[ ( text { ) } ]") # => false
valid_string?("[ ( text ) {} ]") # => true
Algorithm :
Declare a character stack S.
Now traverse the expression string exp.
If the current character is a starting bracket (‘(‘ or ‘{‘ or ‘[') then push it to stack.
If the current character is a closing bracket (')' or '}' or ']') then pop from stack and if the popped character is the matching starting bracket then fine else parenthesis are not balanced.
After complete traversal, if there is some starting bracket left in
stack then “not balanced”
The shortest regex solution is probably:
def valid_string? orig
str = orig.dup
re = /\([^\[\](){}]*\)|\[[^\[\](){}]*\]|\{[^\[\](){}]*\}/
str[re] = '' while str[re]
!str[/[\[\](){}]/]
end
How about:
class Brackets
def self.paired?(s)
stack = []
brackets = { '{' => '}', '[' => ']', '(' => ')' }
s.each_char do |char|
if brackets.key?(char)
stack.push(char)
elsif brackets.values.include?(char)
return false if brackets.key(char) != stack.pop
end
end
stack.empty?
end
end
Brackets.paired?("[ ] } ]") # => false
Brackets.paired?("[ ]") # => true
Brackets.paired?("[ ") # => false
Brackets.paired?("[ (] {}") # => false
Brackets.paired?("[ ( ) ") # => false
Brackets.paired?("[ ( text { ) } ]") # => false
Brackets.paired?("[ ( text ) {} ]") # => true
You can try this approach:
def balanced_brackets?(string)
# your code here
stack = []
opening_bracket = ['{','[', '(']
closing_bracket = ['}', ']', ')']
string.chars.each do |char|
if opening_bracket.include?(char)
stack << char
elsif closing_bracket.include?(char)
value = stack.pop
return false if opening_bracket.index(value) != closing_bracket.index(char)
end
end
stack.empty?
end
if you want to understand pseudo code try this link from coursera (starts at 0:56).
Another way:
s = str.gsub(/[^\{\}\[\]\(\)]/, '')
while s.gsub!(/\{\}|\[\]|\(\)/, ''); end
s.empty?
Ex 1
str = "(a ()bb [cc{cb (vv) x} c ]ss) "
s = str.gsub(/[^\{\}\[\]\(\)]/, '') #=> "(()[{()}])"
while s.gsub!(/\{\}|\[\]|\(\)/, '') do; end
s => "([{}])" => "([])" => "()" => "" gsub!() => nil
s.empty? #=> true
Ex 2
str = "(a ()bb [cc{cb (vv) x] c }ss) "
s = str.gsub(/[^\{\}\[\]\(\)]/, '') #=> "(()[{()]})"
while s.gsub!(/\{\}|\[\]|\(\)/, '') do; end
s => "([{]})" gsub!() => nil
s.empty? #=> false
This should provide the same functionality
def valid_string?(string)
#assume validity
#valid = true
#empty array will be populated inside the loop
#open_characters = []
#set up a hash to translate the open character to a closing character
translate_open_closed = {"{" => "}","["=>"]","("=>")"}
#create an array from the string loop through each item
string.split('').each do |e|
#adding it to the open_characters array if it is an opening character
#open_characters << e if e=~ /[\[\{\(]/
#if it is a closing character then translate the last open_character to
#a closing character and compare them to make sure characters are closed in order
#the result of this comparison is applied to the valid variable
#valid &= e == translate_open_closed[#open_characters.pop] if e=~ /[\]\}\)]/
end
#return validity and make sure all open characters have been matched
#valid &= #open_characters.empty?
end
You could also do this with inject but it would be a bit less transparent.
I was given this as part of a simulated interview coding challenge. In my case, there was also a parens map passed in { "(" => ")", "[" => "]" }, meaning types of parentheses could vary.
def balanced_parens(string, parens_map)
# where we throw opening parens
opening_parens = []
i = 0
while i < string.length
# if current index is opening paren add to array
if parens_map.keys.include? string[i]
opening_parens << string[i]
# if current index is closing paren, remove last item from opening_array
elsif parens_map.values.include? string[i]
popped_paren = opening_parens.pop
# checking that closing parens at current index is a match for last open parens in opening_array
return false if string[i] != parens_map[popped_paren]
end
i += 1
end
# if opening_parens array is empty, all parens have been matched (&& value = true)
opening_parens.empty?
end
def valid_string?(exp)
return false if exp.size % 2 != 0
curly = "{}"
square = "[]"
parenthesis = "()"
emptystr = ""
loop do
old_exp = exp
exp = exp.sub(curly, emptystr)
break if exp == emptystr
exp = exp.sub(square, emptystr)
break if exp == emptystr
exp = exp.sub(parenthesis, emptystr)
break if exp == emptystr || exp == old_exp
end
exp == emptystr
end
Write a method 'valid_string?' that accepts a string. It returns true if the brackets, parentheses, and curly braces close correctly. It returns false otherwise.
valid_string?("[ ]") # returns true
valid_string?("[ ") # returns false
valid_string?("[ ( text ) {} ]") # returns true
valid_string?("[ ( text { ) } ]") # returns false
My code: Is returning false for everything. Even tried using explicit booleans for individual cases {} || () ||, etc. Did not work. Either returns true or false for everything. Is it my driver code?
def valid_string?(str)
if str == ("\[\s+]")
true
else
false
end
end
UPDATED SOLUTION:------------------------------------------------
Yes! #match definitely worked out better! Although my last line of test code is evaluating to true. When it should be false. . .
def valid_string?(str)
if str.match "(\\[.+\\])" || "|(\\(\\))" || "|({})"
return true
else
return false
end
end
puts valid_string?("[ ]") # returns true
puts valid_string?("[ ") # returns false
puts valid_string?("[ ( text ) {} ]") # returns true
puts valid_string?("[ ( text { ) } ]") # returns false
I think it might be complicated to use regex to solve this problem. Here is a potential solution: You may use a stack to record the left symbol like {, [, ( in the traverse. Each time you met the right symbol, just check whether the symbol on the stack top matches this right symbol. Simply return false if not match.
Below is my code:
def valid_string?(str)
stack = []
symbols = { '{' => '}', '[' => ']', '(' => ')' }
str.each_char do |c|
stack << c if symbols.key?(c)
return false if symbols.key(c) && symbols.key(c) != stack.pop
end
stack.empty?
end
puts valid_string?('[ ]') # returns true
puts valid_string?('[ ') # returns false
puts valid_string?('[ ( text ) {} ]') # returns true
puts valid_string?('[ ( text { ) } ]') # returns false
Just because it was fun, I went ahead and solved this The Ruby Way :)
class Brackets
class Bracket
def initialize(open, close)
#open = open
#close = close
#match_count = 0
end
attr_reader :match_count, :open, :close
def check(c)
#match_count += 1 if c == #open
#match_count -= 1 if c == #close
end
end
def initialize
#brackets = []
#stack = []
#valid = true
end
def add(open, close)
#brackets << Bracket.new(open,close)
end
def check(c)
#brackets.each do |b|
b.check(c)
#stack.push(c) if c == b.open
#valid = false if c == b.close and #stack.pop != b.open
end
end
def valid?
total = 0
#brackets.each { |b| total += b.match_count }
total == 0 && #valid == true
end
end
def valid_string?(str)
brackets = Brackets.new
brackets.add('[', ']')
brackets.add('{', '}')
brackets.add('(', ')')
str.each_char { |c| brackets.check(c) }
brackets.valid?
end
# Our tests
puts valid_string?("[ ]") ? 'true' : 'false' # returns true
puts valid_string?("[ ") ? 'true' : 'false' # returns false
puts valid_string?("[ ( text ) {} ]") ? 'true' : 'false' # returns true
puts valid_string?("[ ( text { ) } ]") ? 'true' : 'false' # returns false
puts valid_string?("[ ( text { } ) ]") ? 'true' : 'false' # returns true
Here's a way that doesn't use regex:
def valid_string?(str)
strim = str.gsub(/[^\[\]\(\)\{\}]/,'')
return true if strim.empty?
return false if strim.size.odd?
loop do
s = strim.gsub('()','').gsub('[]','').gsub('{}','')
return true if s.empty?
return false if s == strim
strim = s
end
end
p valid_string?("[ ]") # => true
p valid_string?("[ ") # => false
p valid_string?("[ ( text ) {} ]") # => true
p valid_string?("[ ( text { ) } ]") # => false
p valid_string?("[ ( text { more text { (more text) }} )]") # => true
First remove all characters other than those in "()[]{}".
If the remaining string is empty, return true
If the remaining string contains an odd number of characters, return false.
Continue removing adjacent pairs '()', '[]' and '[]' until either the string is empty, in which case return true, or no more adjacent pairs can be removed and the string is non-empty, in which case return false.
How about a simple counting routine?
def valid_string?(str)
match_count = 0
str.each_char do |c|
match_count += 1 if [ '[', '{', '(' ].include?(c)
match_count -= 1 if [ ']', '}', ')' ].include?(c)
end
return match_count == 0
end
I found recursion to work really well in this situation. Hope this helps!
def valid_string?(string)
bracket_string = string.gsub(/[^\[\]\(\)\{\}]/,'').gsub('()','').gsub('[]','').gsub('{}','')
return true if bracket_string.empty?
return false if bracket_string.length.odd?
return false if bracket_string.include?(string)
valid_string?(bracket_string)
end