Ruby loop and array - arrays

I've been trying to teach myself Ruby. I've found a few code problems to try solving, but I'm stuck. Here is what I have and the problems I'm trying to solve.
My algorithm is as follows:
Prompt the user to enter a number between 1 and 10 (inclusive).
Read that number into an appropriately named variable.
Test that the number lies in the appropriate range.
Input new number if it is out of bounds as per the condition.
Use the number entered by the user to create an array with that
number of elements.
Write a loop which will run through a number of iterations equal to
the size of the array.
Each time through, prompt the user to enter a text string - a name
(names of cars, that sort of thing).
Once the array is entered, display the contents of the array three
items to a line.
You will want a for loop for this, and within the for loop you should include a decision which will insert a line break at the appropriate places.
Also,
Separate the array elements with dashes - but do not put a dash
before the first element on a line, and do not put a dash after the
last element on a line.
Use a Ruby function to sort the array alphabetically, then display it
again, the same way as before.
Reverse the order of the array
Display its contents a third time, again putting three elements on each line of output and placing dashes the way you did with the first display effort.
loop do
print "Enter an integer between 1 and 10: "
s = gets.chomp.to_i
if s >0 && s <= 10
break
else
puts "Interger entered is outside specified range."
end
end
array=[]
array.size
loop do
print "Enter name of a car model: "
car=gets.chomp
array<<car
for i in array
array.slice(1..9) {|car|
puts car.join(", ")
}
end
end

Is that solution you looking for?
loop do
print "Enter an integer between 1 and 10: "
s = gets.chomp.to_i
if (1..10).include?(s)
arr = [""] * s
i = 0
while i < arr.length
print "Enter name of a car model: "
car = gets.chomp
arr[i] = car
i += 1
end
puts arr.join(", ")
break
else
puts "Interger entered is outside specified range."
break
end
end
Result is:
[retgoat#iMac-Roman ~/temp]$ ruby loop.rb
Enter an integer between 1 and 10: 2
Enter name of a car model: car_a
Enter name of a car model: car_b
car_a, car_b
UPDATE
Below solution to print an array by 3 elements per line with natural sorting
loop do
print "Enter an integer between 1 and 10: "
s = gets.chomp.to_i
if (1..10).include?(s)
arr = [""] * s
i = 0
while i < arr.length
print "Enter name of a car model: "
car = gets.chomp
arr[i] = car
i += 1
end
puts arr.sort.each_slice(3){ |e| puts "#{e.join(", ")}\n"}
break
else
puts "Interger entered is outside specified range."
break
end
end
Result is:
[retgoat#iMac-Roman ~/temp]$ ruby loop.rb
Enter an integer between 1 and 10: 4
Enter name of a car model: z
Enter name of a car model: a
Enter name of a car model: x
Enter name of a car model: b
a, b, x
z
And reverse sorting:
loop do
print "Enter an integer between 1 and 10: "
s = gets.chomp.to_i
if (1..10).include?(s)
arr = [""] * s
i = 0
while i < arr.length
print "Enter name of a car model: "
car = gets.chomp
arr[i] = car
i += 1
end
puts arr.sort{ |x, y| y <=> x }.each_slice(3){ |e| puts "#{e.join(", ")}\n"}
break
else
puts "Interger entered is outside specified range."
break
end
end
Result is:
[retgoat#iMac-Roman ~/temp]$ ruby loop.rb
Enter an integer between 1 and 10: 4
Enter name of a car model: z
Enter name of a car model: a
Enter name of a car model: x
Enter name of a car model: b
z, x, b
a

It's better to split you program into small pieces. Also, try not to use loop without necessity.
# Specify Exception class for your context
class ValidationException < RuntimeError
end
def number_of_cars_from_input
# Get user input
print 'Enter an integer between 1 and 10: '
number = gets.chomp.to_i
# Validate input for your requirements
unless (1..10).cover?(number)
raise ValidationException, 'Interger entered is outside specified range.'
end
number
rescue ValidationException => err
# Print exception and retry current method
puts err
retry
end
# Get car name from user input
def car_from_input
print 'Enter name of a car model: '
gets.chomp
end
# Create array with size equal to number from imput and fill it with cars
array_of_cars = Array.new(number_of_cars_from_input) { car_from_input }
# Separate cars in groups by 3 and join groups
puts array_of_cars.each_slice(3).map { |a| a.join(', ') }

Related

How to compare letters in two strings Ruby

I am new to ruby and creating a hangman game. Soo far I have my code comparing the words to the correct word. But I want it to compare letters. So basically, if the secrect word is glue, the user enters G it would come inncorrect, but if the user enters glue it would be correct. I need it to compare letter by letter just like hangman.
Having a bit of trouble with that. I have attached my code below.
secret_word = []
puts "enter a word to be guessed"
secret_word = gets.chomp
guess_letters = []
guess = ""
guess_limit = 3
guess_count = 0
out_of_guesses = false
while guess != secret_word and !out_of_guesses
if guess_count < guess_limit
puts "enter your guess: "
guess = gets.chomp()
guess_letters << guess
guess_count +=1
puts "you have used these letters thus far #{guess_letters.join(", ")}"
else
out_of_guesses = true
end
end
if out_of_guesses
puts "you Lose, the word was #{secret_word}"
else
puts "you win"
end
I'm not sure which hangman rules you are using but here's a rough draft that allows three failed attempts and works with lowercase characters
def guess_word(word, tries)
if tries < 1
puts "You are hanged!"
elsif word.empty?
puts "You guessed it! You are saved from the gallows!"
else
print "Enter character: "
c = STDIN.getc.downcase
STDIN.getc # get rid of newline
if word.index(c).nil?
puts "Ooops, #{c} was wrong!"
guess_word(word, tries - 1)
else
puts "#{c} was correct!"
guess_word(word.sub(/["#{c}"]/, ''), tries)
end
end
end
if __FILE__ == $0
TRIES = 3
print "Enter word to guess: "
word = gets.chomp
guess_word(word.downcase, 3)
end
This is untested..
The rules of the game hangman are given at its Wiki. I've assumed the player trying to guess the word loses when all seven parts of the man on the gallows have been drawn (head, neck, left arm, body, right arm, left leg, right leg).
Helper methods
Draw the man being hanged
First create a hash that can be used to draw the partial or full hangman:
MAN = [" O\n", " |\n", "\\", "|", "/\n", " |\n/", " \\"].
map.each_with_object([""]) { |s,arr| arr << (arr.last + s) }.
each.with_index.with_object({}) { |(s,i),h| h[i] = s }
The keys are the number of incorrect guesses. For example:
puts MAN[2]
O
|
puts MAN[6]
O
|
\|/
|
/
Keep track of the positions of the letters of the word
Next create a hash whose keys are unique letters of the secret word and whose values are arrays of indices of the keys location(s) in the word.
def construct_unknown(word)
word.each_char.with_index.with_object({}) { |(c,i),h| (h[c] ||= []) << i }
end
For example,
unknown = construct_unknown("beetle")
#=> {"b"=>[0], "e"=>[1, 2, 5], "t"=>[3], "l"=>[4]}
We will also create an empty hash for letters whose positions are known:
known = {}
Move guessed letters from the hash unknown to the hash known
If a letter that is guessed is a key of unknown that key and value are moved to known.
def move_unknown_to_known(letter, unknown, known)
known.update(letter=>unknown[letter])
unknown.delete(letter)
end
For example (for unknown and known above),
move_unknown_to_known("e", unknown, known)
unknown #=> {"b"=>[0], "t"=>[3], "l"=>[4]}
known #=> {"e"=>[1, 2, 5]}
See if the guesser has won or lost
We to determine when, after guessing a letter, the player has won or lost, or is to continue:
def win?(word_size, known)
known.values.flatten.sum == word_size
end
def lose?(wrong_guess_count)
wrong_guess_count == HANGMAN.size
end
For example,
win?(word.size, known)
#=> false
lose?(6) #=> false
lose?(7) #=> true
Display the known letters
def display_known(word_size, known)
known.each_with_object('_' * word_size) { |(k,a),s| a.each { |i| s[i] = k } }
end
For example (recall word #=> "beetle"),
puts display_known(word.size, known)
_ee__e
Main method
We are now ready to write the main method.
def hangman
puts "Player 2, please avert your eyes for a moment."
print "Player 1: enter a secret word with at least two letters: "
word = gets.chomp.downcase
unknown = construct_unknown(word)
known = {}
wrong_guess_count = 0
loop do
puts display_known(word.size, known)
puts MAN[wrong_guess_count] if wrong_guess_count > 0
if win?(word.size, known)
puts "You win! You win! Congratulations!"
break
end
if lose?(wrong_guess_count)
puts "Sorry, but you've run out of guesses"
break
end
print "Player 2: enter a letter or your guess of the word: "
guess = gets.chomp.downcase
if guess.size > 1
if guess == word
puts word
puts "You win! You win! Congratulations!"
break
else
puts "Sorry, that's not the word"
wrong_guess_count += 1
end
elsif unknown.key?(guess)
nbr = unknown[guess].size
puts nbr == 1 ? "There is 1 #{guess}" : "There are #{nbr} #{guess}'s"
move_unknown_to_known(guess, unknown, known)
else
puts "Sorry, the word contains no #{guess}'s"
wrong_guess_count += 1
end
end
end
Example
After explaining the rules to the two players and to the audience, the guest host ends by saying, "And don't forget, when guessing a letter or the word it must be expressed as a question...one moment...hold that...I've been told it is not necessary to frame that as a question".
Suppose the word is beetle and the letter guesses are 't', 'i', 'a', 'l', 'r', 's', 't', 'u', 'e', 'beetle'.
hangman
Player 2, please avert your eyes for a moment.
Player 1: enter a secret word with at least two letters: beetle
______
Player 2: enter a letter or your guess of the word: t
There is 1 t
___t__
Player 2: enter a letter or your guess of the word: i
Sorry, the word contains no i's
___t__
O
Player 2: enter a letter or your guess of the word: a
Sorry, the word contains no a's
___t__
O
|
Player 2: enter a letter or your guess of the word: l
There is 1 l
___tl_
O
|
Player 2: enter a letter or your guess of the word: r
Sorry, the word contains no r's
___tl_
O
|
\
Player 2: enter a letter or your guess of the word: s
Sorry, the word contains no s's
___tl_
O
|
\|
Player 2: enter a letter or your guess of the word: t
Sorry, the word contains no t's
___tl_
O
|
\|/
Player 2: enter a letter or your guess of the word: u
Sorry, the word contains no u's
___tl_
O
|
\|/
|
/
Player 2: enter a letter or your guess of the word: e
There are 3 e's
_eetle
O
|
\|/
|
/
Player 2: enter a letter or your guess of the word: beetle
beetle
You win! You win! Congratulations!

Print array elements in reverse order

The first line contains an integer N, (the size of our array).
The second line contains N space-separated integers describing array's(A's) elements.
I have tried the following, however I looked at the solution page. However I do not understand how this code works. Can someone please explain it to me. I am pretty new in this coding world.
import math
import os
import random
import re
import sys
if __name__ == '__main__':
n = int(input())
arr = [int(arr_one) for arr_one in input().strip().split(' ')]
for i in range(len(arr)):
print(str(arr[-i-1]), end = " ")
input 1234
output 4 3 2 1
In Python3:
if __name__ == '__main__':
n = int(input())
arr = list(map(int, input().rstrip().split()))
print(" ".join(str(x) for x in arr[::-1]))
Input:
1 4 3 2
Output:
2 3 4 1
You are creating a list of integer values, by removing spaces and splitting the values at ' '. After obtaining the list of integers, you are iterating over the list and converting the ith element from the back (a negative value of index denotes element with ith index from right and it is 1 based) of arr back to string and printing the number.
Example:
arr = [1,2,3,4]
print(arr[1]) #prints 2 on the console, i.e 2nd element from the left.
print(arr[-1]) #prints 4 on the console, i.e 1st element from the right.
Let's take this code snippet
n = int(input())
arr = [int(arr_one) for arr_one in input().strip().split(' ')]
for i in range(len(arr)):
print(str(arr[-i-1]), end = " ")
The method input() will take the user input from key board. int(input()) will convert the input into int, if the input is in string format. like "4" instead of 4. The input value stored into variable n.
The Array input will be like this "1 2 3 4". So, we need to separate the string with space delimiter.
The strip() method returns a copy of the string with both leading and trailing characters removed.
The split() method returns a list of strings after breaking the given string by the specified separator.Here the separator is space. So, split(' ')
input().strip().split(' ') will take "1 2 3 4" as input and the output is "1" "2" "3" "4".
Now we need to take each element after separated. And then covert into int and store into array.
arr = [int(arr_one) for arr_one in input().strip().split(' ')]
arr_one is a variable, this variable stores each element after split. For each element, we converted it into int and then storing into a array arr.
In python, array index start from 0. If we want to access from last index in the array, the index will start from -1, -2, -3, and so on.
for i in range(len(arr)): The for loop will iterate from index 0 to length of the array. in this example, size is 4.
printing array elements from index -1. and the end argument is used to end the print statement with given character, here the end character is " ". So the output will be 4 3 2 1.
The above code can be rewritten as below with more readability.
if __name__ == '__main__':
n = int(input())
inp = input("Enter the numbers seperated by spaces:::")
inp = inp.strip() # To remove the leading and trailing spaces
array = []
for item in inp.split(' '): # Splitting the input with space and iterating over each element
array.append(int(item)) # converting the element into integer and appending it to the list
print(array[::-1]) # here -1 says to display the items in the reverse order. Look into list comprehension for more details
For more details on list slicing, look in the python documentation.
Try this!
if __name__ == '__main__':
n = int(input()) # input as int from stream
arr = [int(arr_one) for arr_one in input().strip().split(' ')]
"""
1. asking for input from user
2. strip() function removes leading and trailing characters.
3. split(' ') function split your input on space into list of characters
4. arr_one variable contains yours splited character and your iterating over it using for loop
5. int(arr_one) converts it into integer and [] is nothing just storing everything into another list.
6. In last you are assigning new list to arr variable
"""
for i in reversed(arr): # loop over list in reverse order with built in fucntion
print(i, end = " ") # printing whatever comes in i
It should work like this:
3 # your n
1 2 3 # your input
3 2 1 # output

Issues with the output format of hash

So I was trying to create a program that resembles a grocery list where the user puts the item and its associated cost and it would display it as a form of a list. So I created this:
arr = []
arr2 = []
entry = " "
while entry != "q"
print "Enter your item: "
item = gets.chomp
print "Enter the associated cost: "
cost = gets.chomp.to_f
print "Press any key to continue or 'q' to quit: "
entry = gets.chomp
arr << item
arr2 << cost
end
h = { arr => arr2 }
for k,v in h
puts "#{k} costs #{v}"
end
(Code is probably very inefficient, but with my limited starter knowledge it's the best I can do)
So my problem is when I try more than two items the results would display like this (Let's say I used Banana and Kiwi for item and put a random number for their costs):
["Banana", "Kiwi"] costs [2.0, 3,0]
I, however, would like it to display like this:
Banana costs $2.00
Kiwi costs $3.00
I know it probably has to do something with this line:
h = { arr => arr2 }
But I just don't know what I can change about it. I already spend hours trying to figure out how it works so if anyone can give me a hint or help me out I would appreciate it! (Also my apologies for the vague title, didn't know better on how to describe it...)
yes, you are correct. Problem is with this line h = { arr => arr2 }. This line will create a hash like h = {["Banana", "Kiwi"] => [2.0, 3,0]}.
1) You can modify your code as below if you want to use two arrays.
(0...arr.length).each do |ind|
puts "#{arr[ind]} costs $#{arr2[ind]}"
end
2) Better, you can use a hash to store the item and it's cost and then iterate over it to show the results
hash = {}
entry = " "
while entry != "q"
print "Enter your item: "
item = gets.chomp
print "Enter the associated cost: "
cost = gets.chomp.to_f
print "Press any key to continue or 'q' to quit: "
entry = gets.chomp
hash[item] = cost
end
hash.each do |k,v|
puts "#{k} costs $#{v}"
end
You are storing the item names and their costs in 2 different arrays. So, if want to keep your storage structure like that only, you will need to modify the display of result as below:
arr.each_with_index do |item, i|
puts "#{item} costs #{arr2[i]}"
end
But a better approach would be to store all the data in 1 hash instead of 2 arrays.
items = {}
entry = " "
while entry != "q"
print "Enter your item: "
item = gets.chomp
print "Enter the associated cost: "
cost = gets.chomp.to_f
print "Press any key to continue or 'q' to quit: "
entry = gets.chomp
items[item] = cost
end
items.each do |item, cost|
puts "#{item} costs #{cost}"
end
Let me know if it helps.

Counting amount of times element appears in array

I am new to post on Stackoverflow but I am having lots of trouble figuring something out. I am new to the ruby language.
I would like to count the amount of times an element in the array is greater than a specific constant. The array length is between 10 and 25, this is chosen by the user. I then have the array sorted from largest to smallest. I would like to count the amount of times a value in the array is larger or equal to 35. This will be defined as the constant "Quota"
puts "Enter a number between 10 and 25 to represent the number of users: "
num = gets.to_i
if num > 25 or num < 10
puts "I said between 10 and 25. Try again"
num = gets.to_i
end
homeDir = Array.new(num) { rand(20..50)}
homeDir.sort!{|x,y| y<=>x}
puts homeDir
quota = 35
you can use method count
homeDir.count{|el| el >= 35 }
This is my question solved.
print "Enter a number between 10 and 25 to represent the number of users: "
num = gets.chomp.to_i
while num > 25 or num < 10
print "I said between 10 and 25. Try again: "
num = gets.to_i
end
homeDir = Array.new(num) { rand(20..50)}
homeDir.sort!{|x,y| y<=>x}
quota = 35
counter = 0
puts"\n"
puts "Directory Sizes (in MB)"
puts "======================"
homeDir.each{|x| puts x}
homeDir.each do |y|
if y > quota
counter = counter + 1
end
end
puts "\n"
puts "There are #{counter} users whos directories are over 35MB"
Since homeDir is sorted largest to smallest, it would generally be more efficient to use Array#take_while (and then Array#size) than Array#count, as count must traverse the entire array.
def count_biggest(arr, num)
arr.take_while { |n| n >= num }.size
end
arr = [5,4,3,2,1]
count_biggest(arr, 3) #=> 3
count_biggest(arr, 6) #=> 0
count_biggest(arr, 0) #=> 5

Python: Comparing values in one array and replacing that value in another array at the same index from the first array

I’m trying to take user input and compare that input to the values in array B. Should the user input match one of those values in array B, I capture the index it is at and replace array A with the user input at the same index it found it in array B.
In the code example if I enter 11 it finds 11 in array B and inserts it into the same index point in array A. But if I choose 22, 33, or 44 it does not replace anything.
What do you see wrong with the code below? Why does it recognize number 11 in array B and replaces it with 1 in array A, but not the others?
a = [1,2,3,4]
b = [11,22,33,44]
c = input("Enter a Number: ")
for i in b:
if c == i:
x = b.index(i)
a.pop(x)
a.insert(x,c)
break
else:
print "Not in list b"
break
print a
Try this:
a = [1,2,3,4]
b = [11,22,33,44]
c = input("Enter a Number: ")
for i in b:
if c == i:
x = b.index(i)
print x
a.pop(x)
a.insert(x,c)
break
else:
print "Not in list b"
print a
Putting the else statement outside of the for loop should make it work as expected. As it was, the loop would, 100% of the time, break after 1 iteration.

Resources