ruby array iteration, counting only occupied indices - arrays

I'm trying to count the number of occupied spaces, then return that count from #turn_count. Right now I'm returning the orig array.
I'm also counting every iteration, instead of occupied indices.
board = [" ", " x", " ", " ", "O", "O", " ", " ", "X"]
def turn_count(board)
counter = 0
board.each do |index|
if index = "x" || index = "o"
counter += 1
puts "#{counter}"
end
end
end
turn_count(board)

You just need to return the value of counter at the end of your function and also change your = to ==.
= is for assignment. == is for comparison.
def turn_count(board)
counter = 0
board.each do |turn|
if turn.downcase == "x" || turn.downcase == "o"
counter += 1
puts "#{counter}"
end
end
counter
end
I've also added the downcase method so that you're comparison is consistent. Otherwise, if you're looking for x but the array contains an X, you won't get a match.
SIDENOTE:
I changed index to turn because what you're declaring for that each loop is not actually an index. It's the array element itself.
If you wanted to use the index in the loop, you'd need to do something like:
board.each_with_index do |turn, index|
SIDENOTE #2:
You could also do the each loop as a super clean one-liner:
board.each { |t| counter +=1 if ['x', 'o'].include?(t.downcase) }
Just another option. :-)

I'm trying to count the number of occupied spaces
board = [" ", " x", " ", " ", "O", "O", " ", " ", "X"]
board.count { |s| s != " " } #=> 4

[" ", " x", " ", " ", "O", "1O", " ", " ", "X"].count { |s| s =~ /\S/ }
#=> 4
You can do conditional counting for an array by passing a block to count that returns true for the elements you want to count.
In the above example the element is tested against a regex looking for anything other than whitespace in the field

If i understand your question correctly, i guess you want to return the count of occupied values.
To do this in ruby helpers are available. Like in your condition:
array = [" ", " x", " ", " ", "O", "O", " ", " ", "X"]
array.reject(&:blank?).count
It will return a count 4.
So here, reject will skip all the blank spaces and give a count of those elements are present.

Related

Beginner`s Kotlin question. Operating on the array size

I am following the numerous guides from this website: https://www.w3schools.com/kotlin/kotlin_arrays.php
I am experimenting along the way with my own ideas and such.
For the section detailing how to access elements in an array, I decided that I want to create an output that uses correct grammar in English. I want the list to be displayed as such:
"Volvo, BMW, Ford and Audi."
How can I achieve this? I`m of course an absolute beginner.
Thank you!
fun main()
{
val cars = arrayOf("Volvo", "BMW", "Ford", "Mazda")
println(cars[3]) // Prints "Mazda"
if ("Mazda" in cars)
{
println("It exists!")
}
else
{
println("It doesn`t exist!")
}
cars[3] = "Audi"
println(cars[3])
if ("Mazda" in cars)
{
println("It exists!")
}
else
{
println("It doesn`t exist!")
}
println("There are " + cars.size + " elements in this array:")
for (w in cars) // The dilemma begins from here
while (w < cars.size - 1)
{
print(w + ", ")
}
else
{
print(w + "and " + cars[3] + ".")
}
}
#Tenfour04
Thank you for your post.
Here is what I settled at before your last post
for ((i, w) in cars.withIndex())
{
if (i < cars.size - 1)
{
print(w + ", ")
}
else
{
for (i in 0..cars.size-4)
print("and " + cars[3])
}
}
which gave me the output of
Volvo, BMW, Ford, and Audi
After I`ve corrected it with your solution, thank you very much.
The output is still the same:
Volvo, BMW, Ford, and Audi
Now I am wondering how I can remove the third comma. The one after "Ford", so that the final output would be:
Volvo, BMW, Ford and Audi
while is a loop with a condition (in the parentheses after it). That's not what you want. And in your comment, you replaced for with println, which doesn't make sense.
And your else branch makes the mistake of using both w and cars[3] in you final output, two different ways of getting the name of the last car, so it appears twice in your output.
Since you are using both the elements of the array and their indices, you should iterate both at once using withIndex, like this.
Here's how you can iterate both the indices and the cars so you can do an if condition on the index (position) in the list of each item.
for ((i, w) in cars.withIndex()) {
if (i < cars.size - 1)
{
print(w + ", ")
}
else
{
print("and " + w + ".")
}
}
But it's cleaner to use string templates like:
for ((i, w) in cars.withIndex()) {
if (i < cars.size - 1)
{
print("$w, ")
}
else
{
print("and $w.")
}
}
When you have short single function calls in each branch of if/else, it sometimes is cleaner looking code to use when instead:
for ((i, w) in cars.withIndex()) {
when {
i < cars.size - 1 -> print("$w, ")
else -> print("and $w.")
}
}
Or for a completely different strategy, you could iterate all but the last item by dropping it, and then use just the last item:
for (car in cars.dropLast()) {
println("$car, ")
}
print("and ${cars.last()}")
For your comment in your own answer, you can use a when statement with three conditions:
for ((i, w) in cars.withIndex()) {
when {
i < cars.size - 2 -> print("$w, ")
i == cars.size - 2 -> print("$w ")
else -> print("and $w.")
}
}

How to make a parent thread output global variables defined in worker threads

The following is a multi-threaded program that does simple statistical computations on a user-defined array, I can't seem to figure out how to make the parent thread output the global variables defined in the worker threads, also how do I make a function that is invoked by using start() on a thread that points to that function to return a value?
import threading as th
# Function to give maximum in array
def maximum(arr):
global maxi
maxi = 0
for x in range(len(arr)):
if arr[x] > maxi:
maxi = arr[x]
#print ("%sMaximum value is: %s " % (" " , max) + "\n")
# Function to give minimum in array
def minimum(arr):
global mini
mini = 999999
for x in range(len(arr)):
if arr[x] < mini:
mini = arr[x]
#print ("%sMinimum value is: %s " % (" " , min) + "\n")
# Function to give average of an array
def average(arr):
count = len(arr)
global summ
summ = 0
for x in range(count):
summ = summ + arr[x]
avg = summ / count
#print ("%sAverage value is: %s " % (" " , avg) + "\n")
# Function to prompt user to input array of numbers
def defArray():
array = []
n = int(input("Please Enter the size of your Array of numbers: "))
for x in range(n):
s = input("Please Enter a number: ")
if check(s) == False:
print("Invalid User Input, Please make sure input is a number")
return
else:
array.append(float(s))
print("Your array is: ")
print(array)
return array
# Function to check if user input is correct
def check(item):
user_number = str(item)
if( user_number.isdigit()):
return True
else:
return False
# Section for calling the previous function to show execution
array = defArray()
t1 = th.Thread(target=maximum,args=[array])
t2 = th.Thread(target=minimum,args=[array])
t3 = th.Thread(target=average,args=[array])
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()

Scoping of variables in a for loop

The following program manipulates two arrays. The algorithm is of little importance except to note that the array tmp gradually gets smaller.
package main
import (
"strings"
"fmt"
)
func arrayToString(a []int, delim string) string {
return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim, -1), "[]")
}
func numSeries(arr []int) ([]int, []int) {
return arr[:2], arr[2:]
}
func main() {
highnum := []int{8,7}
tmp := []int{6,5,4,3,2,1}
curr := []int{}
// fRight := ""
for i, v := range highnum {
curr, tmp = numSeries(tmp)
fmt.Printf("v %d numSeries result curr %s tmp %s\n", v, arrayToString(curr, ", " ), arrayToString(tmp, ", " ) )
fmt.Printf("final (1) %s\n", arrayToString(tmp, ", " ) )
// fRight += "[" + arrayToString(append(curr, v), ", ") + "]"
if i == len(highnum)-1 {
fmt.Printf("final (2) %s\n", arrayToString(tmp, ", " ) )
}
// fmt.Printf("fRight |%s|\n", fRight)
}
}
The results are:
v 8 numSeries result curr 6, 5 tmp 4, 3, 2, 1
final (1) 4, 3, 2, 1
v 7 numSeries result curr 4, 3 tmp 2, 1
final (1) 2, 1
final (2) 2, 1
The program works - final (1) and final (2) comments in the output have the same value. However, if I uncomment the three commented-out statements above I get an incorrect result. Here is the incorrect program and the result.
package main
import (
"strings"
"fmt"
)
func arrayToString(a []int, delim string) string {
return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim, -1), "[]")
}
func numSeries(arr []int) ([]int, []int) {
return arr[:2], arr[2:]
}
func main() {
highnum := []int{8,7}
tmp := []int{6,5,4,3,2,1}
curr := []int{}
fRight := ""
for i, v := range highnum {
curr, tmp = numSeries(tmp)
fmt.Printf("v %d numSeries result curr %s tmp %s\n", v, arrayToString(curr, ", " ), arrayToString(tmp, ", " ) )
fmt.Printf("final (1) %s\n", arrayToString(tmp, ", " ) )
fRight += "[" + arrayToString(append(curr, v), ", ") + "]"
if i == len(highnum)-1 {
fmt.Printf("final (2) %s\n", arrayToString(tmp, ", " ) )
}
fmt.Printf("fRight |%s|\n", fRight)
}
}
Result:
v 8 numSeries result curr 6, 5 tmp 4, 3, 2, 1
final (1) 4, 3, 2, 1
fRight |[6, 5, 8]|
v 7 numSeries result curr 8, 3 tmp 2, 1
final (1) 2, 1
final (2) 7, 1
fRight |[6, 5, 8][8, 3, 7]|
Note that final (1) and final (2) comments have different values. This is wrong. I suspect this type of behaviour is entirely correct and I am falling for a beginner's 'gotcha'. I'd be grateful if somebody could point out an existing StackOverflow question that gives a solution, or describes what is going on. I'd be especially happy to see a reference to the official language definition covering this issue.
It is here:
fRight += "[" + arrayToString(append(curr, v), ", ") + "]"
In particular, append. The key here is that slices are views on arrays. The curr and tmp point to the same underlying array, curr being the beginning part of it and tmp being the end. The way append works is that if the slice has sufficient capacity, it will simply add the element to the end of the slice and increase the len. When you run that append, curr has sufficient capacity, so v is added to the end of curr, which happends to be the first element of tmp. So you overwrite that element.

JoshCheek's ruby-kickstart Challenge 1 Session 2

As part of an exercises, I should write a program that reads in two integers typed on the keyboard, and then outputs their sum, difference, and product.
Standard input is like "9 2\n" and expects me to print "11\n7\n18\n" to standard output.
Am I getting it completely wrong?
def sum_difference_product
input = gets.chomp
array = input.split(" ").map { |x| x.to_i }
sum = array[0] + array[1]
difference = array[0] - array[1]
product = array[0] * array[1]
result = ""
result << sum
result << difference
result << product
return result
end
sum_difference_product
You're currently appending integers to a string using << which (from the looks of it) treats the int as raw binary. 1 for example becoms \u0001.
Instead change result to an array and join it using " " like this.
def sum_difference_product
input = gets.chomp
array = input.split(" ").map { |x| x.to_i }
pp array
sum = array.fetch(0) + array.fetch(1)
difference = array[0] - array[1]
product = array[0] * array[1]
result = []
result << sum
result << difference
result << product
return result.join(" ")
end
puts sum_difference_product
Okay, I was overcomplicating things... Removed result, sum, difference, product and just puts the parts that were in sum, difference and product. It's ok now:
def sum_difference_product
input = gets.chomp
array = input.split(" ").map { |x| x.to_i }
puts array[0] + array[1]
puts array[0] - array[1]
puts array[0] * array[1]
end

display specific values form sorted array

this is my sorted array
$sortedArray = array($value_one_fin,$value_two_fin,$value_three_fin,$value_four_fin,$value_five_fin,$value_six_fin,$value_seven_fin,$value_eight_fin,$value_nine_fin,$value_ten_fin,$value_eleven_fin,$value_twelve_fin,$value_thirteen_fin,$value_fourteen_fin,$value_fifteen_fin,$value_sixteen_fin,$value_seventeen_fin,$value_eighteen_fin,$value_nineteen_fin,$value_twenty_fin,$value_twentyone_fin,$value_twentytwo_fin,$value_twentythree_fin,$value_twentyfour_fin);
$result=findClosest($sortedArray,$num1);
this is the variable where i store my entered number
$num1
what i want to do is to display values from sorted array in the manner Buy at / above: 102.51 Targets: 105,107.58,110.19,112.83
Stoploss : 100
in the above example i have entered 100 as $num1. as per calc the $result is also 100 so it has to display next greater closest number which is 102.51 and in stop loss it shuld display next smaller closest number
CONDITION
1>if entered number $num1 is greater than $result then display the next greater closest number from sorted array
2>if entered number $num1 is equal to $result then display the next greater closest number from sorted array
pls help me with this how can i do this im doing this
Buy At/Above ";if ($num1>$result) {echo "$result ";}if ($num1=$result) {echo "$result ";}if ($num1<$result) {echo "$result ";}echo "for Targets"; if ($result<$value_one_fin){echo " $value_one_fin,";}
if ($result<$value_two_fin){echo " $value_two_fin,";}
if ($result<$value_three_fin){echo " $value_three_fin,";}
if ($result<$value_four_fin){echo " $value_four_fin,";}
if ($result<$value_five_fin){echo " $value_five_fin,";}
if ($result<$value_six_fin){echo " $value_six_fin,";}
if ($result<$value_seven_fin){echo " $value_seven_fin,";}
if ($result<$value_eight_fin){echo " $value_eight_fin,";}
if ($result<$value_nine_fin){echo " $value_nine_fin,";}
if ($result<$value_ten_fin){echo " $value_ten_fin,";}
if ($result<$value_eleven_fin){echo " $value_eleven_fin,";}
if ($result<$value_twelve_fin){echo " $value_twelve_fin,";}
if ($result<$value_thirteen_fin){echo " $value_thirteen_fin,";}
if ($result<$value_fourteen_fin){echo " $value_fourteen_fin,";}
if ($result<$value_fifteen_fin){echo " $value_fifteen_fin,";}
if ($result<$value_sixteen_fin){echo " $value_sixteen_fin,";}
if ($result<$value_seventeen_fin){echo " $value_seventeen_fin,";}
if ($result<$value_eighteen_fin){echo " $value_eighteen_fin,";}
if ($result<$value_nineteen_fin){echo " $value_nineteen_fin,";}
if ($result<$value_twenty_fin){echo " $value_twenty_fin,";}
if ($result<$value_twentyone_fin){echo " $value_twentyone_fin,";}
if ($result<$value_twentytwo_fin){echo " $value_twentytwo_fin,";}
if ($result<$value_twentythree_fin){echo " $value_twentythree_fin,";}
if ($result<$value_twentyfour_fin){echo " $value_twentyfour_fin";}
but its not working and also how to display STOP LOSS
Apologies if I've misunderstood the question - I'm not 100% clear what you're trying to achieve, but I'll try to be helpful.
It looks as though your array is sorted smallest to largest. So to find the first value greater than or equal to $num1, simply loop through your array from beginning to end, and stop when you find a value >= $num1 e.g.
function findClosest($sortedArray, $num1) {
foreach ($sortedArray as $value) {
if ($value >= $num1) {
return $value;
}
}
}
To find the closest number less than or equal to $num1, loop through the array from the end to the beginning e.g.
function findClosestLessThanOrEqual($sortedArray, $num1) {
for ($i = sizeOf($sortedArray) - 1; $i >= 0; $i--) {
if ($sortedArray[$i] <= $num1) {
return $sortedArray[$i];
}
}
}
There are faster ways to search a large array, but if your array only contains 24 values I think that's the simplest way.
Just needs a slight tweak to get the first 5 items >= $num1:
function find5Closest($sortedArray, $num1) {
for ($i = 0; $i < sizeOf($sortedArray); $i++) {
if ($sortedArray[$i] >= $num1) {
return array_slice($sortedArray, $i, 5);
}
}
}
This should return an array up to 5 values. If there are only 3 values >= $num1, then it will only return 3 values; if no values are >= $num1 it will return an empty array.
Similarly:
function find5ClosestLessThanOrEqual($sortedArray, $num1) {
for ($i = sizeOf($sortedArray) - 1; $i >= 0; $i--) {
if ($sortedArray[$i] <= $num1) {
return array_slice($sortedArray, min(0, $i-4), 5);
}
}
}

Resources