How to swapcase a string without using builtin functions - ruby

I am trying to swapcase a string without using builtin functions like swapcase.
I came up with with the following code:
a = gets.split
b = ""
for i in a
if /[[:upper:]]/.match(i)
b += i.downcase
end
if /[[:lower:]]/.match(i)
b += i.upcase
end
end
puts b
But it's producing a wrong output. How can I do it in Ruby?

One approach to mimic swapcase with no argument.
p 'Hello'.chars.map { |c| c.upcase == c ? c.downcase : c.upcase }.join
#=> "hELLO"

"Hello World!".tr("a-zA-Z", "A-Za-z")
# => "hELLO wORLD!"

Similar to #sagarpandya82's answer but doesn't convert the string to an array and back.
"ComMMent maintEnaNt, vaChe tacHetée?".gsub(/./) do |c|
c == c.upcase ? c.downcase : c.upcase
end
#=> "cOMmmENT MAINTeNAnT, VAcHE TAChETÉE?"

def fnswapcase(a):
r = ' '
for i in a:
if ord(i) in range(97,123):
r+=chr(ord(i)-32)
elif ord(i) in range(65,91):
r+=chr(ord(i)+32)
else:
r+=i
return r
a=input("Enter a string:")
print(fnswapcase(a))

Related

Manipulating symbols in ruby

I am trying to take an array of symbols,
a = [:apple, :banana ,:grape, :black]
and add a string at the end of each symbol depending on the last letter. If the symbol ends with e, add "hello", otherwise "hi". I want to get:
[:applehello, :bananahi]
I did:
n = []
a.each do |b|
if (b[-1] == "e")
n.push b.to_s + "hello"
else
n.push b.to_s + "hi"
end
end
p n
I have to convert it into strings. How can I get the final output in symbols?
Did it using sub aswell-
a.each do |q|
if (q[-1]=="e")
then n.push q.to_s.sub(/e/,"ehello")
else
n.push q.to_s.sub(/\z/,"ahi")
end
end
p n
Use to_sym to have a symbol back
a = [:apple, :banana , :grape, :black]
a.map do |s|
(s.to_s + (s[-1] == 'e' ? 'hello' : 'hi')).to_sym
end
An alternative
a = [:apple, :banana , :grape, :black]
a.map do |s|
"#{s}#{s[-1] == 'e' ? 'hello' : 'hi'}".to_sym
end
Tried with following,
a.map { |x| "#{x}#{x.to_s.last == 'e' ? 'hello' : 'hi'}".to_sym }
# => [:applehello, :bananahi, :grapehello, :blackhi]
a.map{|sym| sym.to_s.sub(/.\z/) do
|c| case c; when "e" then "hello"; else "hi" end.to_sym
end}
# => [:applhello, :bananhi, :graphello, :blachi]

Ruby: No Block Given error

I keep getting a 'no block given' error when trying to pass the string to the is_tut? method. I am new to Ruby and have no idea what I'm doing wrong. Any and all help would be appreciated.
class Tut
##consonants = ["b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"]
def is_tut? string
if string =~ /^(([b-df-hj-np-z]ut)|([aeiou\s])|[[:punct:]])+$/i
yield
else
false
end
end
def self.to_tut string
string.each_char do |c|
c += "ut" if ##consonants.find { |i| i == c.downcase }
yield c
end
end
def self.to_english string
array = string.split //
array.each do |c|
if ##consonants.find { |i| i == c.downcase }
array.shift
array.shift
end
yield c
end
end
end
#Tut.to_tut( "Wow! Look at this get converted to Tut!" ) { |c| print c }
# should output : Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!
puts
puts
tut = Tut.to_tut( "Wow! Look at this get converted to Tut!" )
puts "from return: #{tut}"
puts
#Tut.to_tut( "Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!" ) { |c| print c }
# should outout : Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!
puts
puts
#tut = Tut.to_tut( "Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!" )
#puts "from return: #{tut}"
puts
#tut_string = ""
#Tut.to_tut( "I'm in tut but I want to be in english." ) { |c| tut_string += c }
#puts tut_string
# should output : I'mut inut tututut bututut I wutanuttut tuto bute inut enutgutlutisuthut.
puts
#Tut.to_english( tut_string ) { |c| print c }
# should output : I'm in tut but I want to be in english.
If you have yield within your method definition, that means you have to obligatorily pass a block when you use it (unless the part including it is not executed according to conditioning etc.). (You might already know, but in case you don't: a block is something that is described as {...} or do ... end) And yield will refer to the block.
If you want to make a block optional, then one way to do it is to put the & symbol before the variable name.
def method(argument, &block_argument)
if block_argument # block is given
block_argument.call(argument_for_block) # use call to execute the block
else # the value of block_argument becomes nil if you didn't give a block
# block was not given
end
end
This will allow optional block. Or, as suggested by Squeegy,
def method(argument)
if block_given? # block is given
yield(argument_for_block) # no need to use call to execute the block
else
# block was not given
end
end
will also work.
Because you're calling yield in your to_tut() method, this line will fail:
tut = Tut.to_tut( "Wow! Look at this get converted to Tut!" )
You either need to give a block (as you did in the first commented-out call to Tut.to_tut()), or you need to modify your to_tut() function to make the code block optional:
def self.to_tut string
string.each_char do |c|
c += "ut" if ##consonants.find { |i| i == c.downcase }
yield c if block_given?
end
end
yield requires a block to be passed to to_tut.
When you do:
Tut.to_tut( "Wow! Look at this get converted to Tut!" ) { |c| print c }
It works because it has the block { |c| print c }.
Without a block it will raise the error.

All possible permutations of a given String?

How would I do this in Ruby?
p "abc".all_possible_permutations
Would return:
[
"abc",
"acb",
"bca",
"bac",
"cba",
"cab",
]
Edit
Thanks to Jakub Hampl:
class String
def all_possible_permutations
self.chars.to_a.permutation.map(&:join)
end
end
%w[a b c].permutation.map &:join
If someone doesnt want to use inbuilt function :
def permute(result,input)
if(input.length == 0)
return
end
if(input.length == 1)
puts result + input[0]
return
end
if(input.length == 2)
puts result + input[0] + input[1]
puts result + input[1] + input[0]
return
end
(0...input.length).step(1).each do |i|
firstpart = result+input[i]
secondpart = (i > 0 ? input[0..(i-1)] : '') + (input[(i+1)..-1] || '')
permute(firstpart,secondpart)
end
end
permute('',gets.chomp)
One line:
p "abc".chars.permutation.map &:join
Sample output:
["abc", "acb", "bac", "bca", "cab", "cba"]
p is optional
string could be a variable instead
chars is pretty quick, it separates the string into an array of single characters
map has tons of cool applications,it takes a object, and returns it after the block is done, in this case the operation join
&:join could be replaced with { |i| i.join } like this:
p "abc".chars.permutation.map{ |i| i.join }
If anyone wants to have the code for this using basic algorithms, here is how you do it-
$count = 0
def permute(permuted_string, original_string, done_array)
if permuted_string.length == original_string.length
$count = $count+1
puts "#{$count} #{permuted_string}"
else
(0..original_string.length-1).each do |i|
if !done_array[i]
done_array[i] = true
permute(permuted_string+original_string[i], original_string, done_array)
done_array[i] = false
end
end
end
end
puts "Please enter the string for permutations"
input = gets.chomp
done_array = Array.new(input.length, false)
permute("", input, done_array)

assigning mapped array directly

Trying to map stuff I read from a file into a
list of arrays that have an integer and a string
It doesn't seem to to work quite right, because I see
two strings per array, as opposed to an integer
and a string.
list_of_elems = []
File.foreach("line_counts.txt") do |line|
list_of_elems << arr = line.split(/\s+/).map! { |e, i| i == 0 ? e.to_i : e }
end
list_of_elems.each_with_index do |e, i|
if i > 10
break
end
p e
end
If I understand well, you want to take a file like this:
test 20 foo
7 1 bar 6
And get this:
[["test", 20, "foo"],
[7, 1, "bar", 6]]
Right?
Then you can use:
list_of_elems = []
File.foreach("line_counts.txt") do |line|
list_of_elems << line.split(/\s+/).map {|e| e =~ /^(?:+|-)?\d+$/ ? e.to_i : e }
end
Or:
list_of_elems = File.read("line_counts.txt").split("\n").map do |line|
line.split(/\s+/).map {|e| e =~ /^(?:+|-)?\d+$/ ? e.to_i : e }
end
This may not be too relevant, but
list_of_elems.each_with_index do |e, i|
if i > 10
break
end
p e
end
can be replaced with
list_of_elems[0..10].each {|e| p e}
Your problem is that map! only passes one argument to the block; hence i is always nil, i == 0 always fails, and to_i is never called. I think you want something more like this:
list_of_items = File.open('line_counts.txt').collect do |line|
line.split(/\s+/).inject([ ]) { |a, e| a.push(a.length == 0 ? e.to_i : e) }
end
The a.length == 0 essentially replaces your faulty i == 0 check and converts the first component of the line to an integer.
If linecounts.txt looks like this:
1 one
2 two
Then list_of_items ends up looking like this:
[[1, "one"], [2, "two"]]
and that seems to be what you're after.
This should work too:
list_of_elems = File.foreach("line_counts.txt").map |line|
line.split.map.with_index { |e, i| i == 0 ? e.to_i : e }
end
I use map instead of each for the output because you can hit tab twice in textmate and it builds the block for you.
list_of_elems.map { |e| puts e.to_s }

comparing multiple strings character by character and outputting the overlap?

ruby
i have the following
p = 0
[s1.size,s2.size].max.times { |c| if s1[c] == s2[c]; p = c; else break; end };
matched_part = s1[0..p]
but i dont know how i can this for multiple strings (more than 2) at the same time.
Alright, how's this?
class String
def self.overlap(s1,s2,*strings)
strings += [s2]
strings.min { |s| s.size }.size.times do |n|
return s1[0,n] unless strings.all? { |string| s1[n]==string[n] }
end
s1
end
end
class String
def self.overlap(first,second,*others)
s1 = first
others = [second] + others
others.each do |s2|
p = 0
s1.length.times { |c| if s1[c] == s2[c] then p = c else break end }
s1 = s1[0..p]
end
s1
end
end
puts String.overlap "marry had a little lamb", "marry had a bug dog", "marry had a cat", "marry had a bird OUT:", "marry had something" #=> marry had
In one line:
strings[0].slice(0,(0...strings[0].size).find {|i| strings.map {|s| s[i..i]}.uniq.size > 1})

Resources