how to traverse through a for loop - loops

I have a list of items, I want to be able to go through the list. start at index [0] if the item is in the board, add 1 to the index and keep going, if its not assign that value of x to computermove and break outside the loop . with the way I have it, the computermove is "b2" even though its in the list, shouldn't it add 1 to the index and loop back around, I don't understand that
list=["b2", "a1", "c3", "a3", "c1", "a2", "b3", "b1", "c2"]
board = {0:'b2', 1:' ', 2:' ',
3:' ', 4:'a1', 5:' ',
6:' ', 7:' ', 8:'c3',
}
for x in list:
if x in board:
x = x+1
else:
computermove= x
break

You seem to not understand how a for loop works.
You should not be increasing indexes manually(and x is not an index anyway), but let the for loop do that for you.
Your other problem is that x in board checks if x is in the keys of board, not its values.
Here's one possible way to make (that part of) your code work:
for x in list:
if x not in board.values():
computermove = x
break
That's really all the help I can give you with the amount of code/information you've shown.

Related

Logical Error - 2D array using ArrayList in Kotlin

I am making a simpel tic tac toe game while learning Kotlin, following a tutorial.
When I input and combination as my turn in the game, let's say 1, 3 : The X appears in all places of that column. I have spent almost 3 hours finding the erorr but I think it's somthing to do with Arraylist making. Kinldy help me. Code is shown below.
var board = arrayListOf<ArrayList<String>>()
fun main(args: Array<String>) {
for (i in 0..2){
val row = arrayListOf<String>()
for (j in 0..2){
row.add("")
board.add(row)
}
}
printBoard()
var continueGame = true
do{
println("Please enter a position. (e.g: 1, 3)")
val input = readLine()?:""
var x = 0
var y = 0
try {
val positions = input.split(",")
x = positions[0].trim().toInt()
y = positions[1].trim().toInt()
println("x is $x")
println("x is $y")
if(board[x-1][y-1] != "") {
println("position already taken")
}else{
board[x-1][y-1] ="X"
printBoard()
}
}catch (e: Exception){
println("Invalid input, please try again")
}
}while(continueGame)
}
fun printBoard(){
println("----------------")
for (i in 0..2){
for (j in 0..2){
when (board[i][j]){
"X" -> print("| X ")
"O" -> print("| O ")
else -> print("| ")
}
}
println("|")
println("----------------")
}
}
Move board.add(row) outside your inner for loop (the for (j... loop). You are adding each row to the outer ArrayList three times, so when you start using the 2D list later and assume it only has three rows, all three of those rows are the same first row repeated, and you're ignoring the last six rows.
But actually, when you know that your collections will not ever change size, Arrays are a cleaner solution than Lists. You can create your 3x3 2D Array in one line like this:
val board = Array(3) { Array(3) { "" } }
Here's how I looked at the problem.
Debug printBoard()
I first looked at the printBoard() function. I put a breakpoint in, and saw that board already had 3 Xs in it.
So the problem is happening further up the chain.
Debugging the X assignment
There's only once place in your code where X's are added to the board, so let's take a look there.
board[x - 1][y - 1] = "X"
I put a breakpoint on that line, and ran the program in debug mode.
When I inspect the board object, I see it's an ArrayList with 9 elements. Each element is also an ArrayList, each with 3 elements.
In total that's 27 squares, and a tic-tac-toe board only has 9! board only needs 3 ArrayLists.
Debugging board creation
If we take a look at where board is created...
for (i in 0..2) {
val row = arrayListOf<String>()
for (j in 0..2) {
row.add("")
board.add(row) // hmmmm
}
}
board.add(row) is nested inside both for loops. That means it will be called 9 times in total.
The Fix
So, quick fix, move add to the outer loop.
for (i in 0..2) {
val row = arrayListOf<String>()
for (j in 0..2) {
row.add("")
}
board.add(row) // better!
}
The program now works!
Why were there 3 X's?
I think it's interesting to understand why the X was appearing on the board three times.
If we look at the two for loops, the row list is being created in the outer loop - which means only 3 rows will be created. But because board.add(row) was in the inner loop, it will add the same row 3 times!
We can actually see that in the debug inspection. ArrayList#1073 is a unique ID for a specific row object, and it appears 3 times. So do ArrayList#1074 and ArrayList#1075
board[0], board[1], and board[2] all fetch the same row object, so in the printBoard() function, it loops over the first 3 elements of board... which are all exactly the same object!
Preventing the problem
The next step is to think about how to stop this problem from happening in the first place. I think that the for loops were confusing - they're easy to get wrong, and have 'magic numbers'. Fortunately Kotlin has lots of useful tools we can use to write clearer code.
Kotlin's Array class has a constructor that accepts an size: Int and an initialising lambda, that is used to fill each element of the array.
Here's a demo:
println(
Array(5) { i -> "I'm element $i" }.joinToString()
)
// output:
// I'm element 0, I'm element 1, I'm element 2, I'm element 3, I'm element 4
Each element of the Array has a value, based on i (the index of the array). For the tic-tac-toe board we don't care about the index, so we can ignore it.
// var board = arrayListOf<ArrayList<String>>() // old
var board = Array(3) { Array(3) { "" } } // new!
Output:
----------------
| | | |
----------------
| | | |
----------------
| | | |
----------------
Please enter a position. (e.g: 1, 3)
There we go, a 3x3 board - nice and clear!
I hope this helps!

how to coorelate multiple values in array with certain name in other array

I am trying to make an all text RPG game in python with cmd, but I need to find a way to place dungeons on certain X and Y.
I've tried creating two different arrays :
placesYX = [[50, 100]]
places = ['First Door']
and then making a function where it would check each time
if x == placesYX[0][0] and y == placesYX[0][1]:
print('you are at: ', places[0])
but I cannot repeat this for each place I add, I need a function that checks if x and y both match any values in placesXY and if it is true:
print('You are at: ', places[mathcingplace])
thank you to anyone who answers(I'm a beginner)
You could use python's enumerate functionality to keep track of both the index of your places, and the value:
placesXY = [[50, 100], [75, 150]]
places = ['First Door', 'Second Door']
def check_place(x, y):
for index, coordinates in enumerate(placesXY):
if coordinates[0] == x and coordinates[0] == y:
return f"You are at: {places[index]}"
enumerate lets you keep track of both index in the list, as well as value in the list.
f"some string {variable}" lets you (f)ormat a string with variables, and you can print f strings.
Just a suggestion: You might step back and reconsider the way you are modeling the data. If you need to frequently look things up given a tuple of (x,y) values, you could consider making a dictionary keyed to coordinates instead of separate lists.
For example:
from collections import defaultdict
# defaultdict will allow you to set global default when there's nothing at a coord
placesYX = [(50, 100), (90, 200)]
place_names = ['First Door', 'some creature']
places = dict(zip(placesYX, place_names))
# places looks like
# {(50, 100): 'First Door', (90, 200): 'some creature'}
# now you can lookup directly:
places[(50, 100)] # first door
places[(90, 200)] # some creature
If it's possible you will look up coordinates that aren't in the dictionary, you can use:
places.get((0,0), "some default value")
to avoid a key error.

How to convert two associated arrays so that elements are evenly distributed?

There are two arrays, an array of images and an array of the corresponding labels. (e.g pictures of figures and it's values)
The occurrences in the labels are unevenly distributed.
What I want is to cut both arrays in such a way, that the labels are evenly distributed. E.g. every label occurs 2 times.
To test I've just created two 1D arrays and it was working:
labels = np.array([1, 2, 3, 3, 1, 2, 1, 3, 1, 3, 1,])
images = np.array(['A','B','C','C','A','B','A','C','A','C','A',])
x, y = zip(*sorted(zip(images, labels)))
label = list(set(y))
new_images = []
new_labels = []
amount = 2
for i in label:
start = y.index(i)
stop = start + amount
new_images = np.append(new_images, x[start: stop])
new_labels = np.append(new_labels, y[start: stop])
What I get/want is this:
new_labels: [ 1. 1. 2. 2. 3. 3.]
new_images: ['A' 'A' 'B' 'B' 'C' 'C']
(It is not necessary, that the arrays are sorted)
But when I tried it with the right data (images.shape = (35000, 32, 32, 3), labels.shape = (35000)) I've got an error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
This does not help me a lot:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I think that my solution is quite dirty anyhow. Is there a way to do it right?
Thank you very much in advance!
When your labels are equal, the sort function tries to sort on the second value of the tuples it has as input, since this is an array in the case of your real data, (instead of the 1D data), it cannot compare them and raises this error.
Let me explain it a bit more detailed:
x, y = zip(*sorted(zip(images, labels)))
First, you zip your images and labels. What this means, is that you create tuples with the corresponding elements of images and lables. The first element from images by the first element of labels, etc.
In case of your real data, each label is paired with an array with shape (32, 32, 3).
Second you sort all those tuples. This function tries first to sort on the first element of the tuple. However, when they are equal, it will try to sort on the second element of the tuples. Since they are arrays it cannot compare them en throws an error.
You can solve this by explicitly telling the sorted function to only sort on the first tuple element.
x, y = zip(*sorted(zip(images, labels), key=lambda x: x[0]))
If performance is required, using itemgetter will be faster.
from operator import itemgetter
x, y = zip(*sorted(zip(images, labels), key=itemgetter(0)))

How to understand Ruby's .each and .map

I am having trouble understanding the differences between map and each, and where and when to use them.
I read "What does map do?" and "Ruby Iterators" but wanted some clarification.
If I have:
z = [1,2,3].map {|x| x + 1}
map takes each element in the array z and adds one to each element, however it does not mutate the original array unless I add !.
On the other hand:
y = [1,2,3].each {|x| x + 1}
returns [1,2,3]. This is confusing to me since:
names = ['danil', 'edmund']
names.each { |name| puts name + ' is a programmer' }
returns:
Danil is a programmer
Edmund is a programmer
What is exactly going on in my second example that isn't allowing each array element to be increased by 1, while in the last example a string is being attached to everything in the array?
All credits go to Speransky Danil, whom I took these examples off of.
The map method takes an enum given some block, and iterates through it doing some logic. In your case the logic is x+1. As you say it will not mutate anything unless you use !.
each is simply returning the array that is being called.
Let's take an example of:
names = ["bob"]
If we do:
names.each{|names| names + "somestring"}
the output is still ["bob"]. The reason your second example is different is due to the puts.
As an exercise try doing:
y = [1,2,3].each {|x| puts x + 1}
You will get:
2
3
4
[1,2,3]
tl;dr: I use map if I want to change my collection, apply a transformation on it, end up with something different. I use each if I just need to visit every element in a collection.
Key point is: you should use map if you want to apply a transformation on an array (an enumerable in reality, but let's keep it simple at the beginning). Otherwise, if you don't need to change your array, you can simply use each.
Note that in the code below you are not mutating the array but you are simply take advantage of the local string to print each string with a suffix.
names = ['danil', 'edmund']
names.each { |name| puts name + ' is a programmer' }
Obviously, you could do the same with map but in this case you don't need it and you have to use an each too to print every element. The code would be
names = ['danil', 'edmund']
names.map! { |name| name + ' is a programmer' }
# or names = names.map { |name| name + ' is a programmer' }
name.each { |name| puts name }
This is covered in Ruby's documentation in multiple places but the easiest to understand for your use is in the Array documentation for each:
each { |item| block } → ary
each → Enumerator
Calls the given block once for each element in self, passing that element as a parameter. Returns the array itself.
If no block is given, an Enumerator is returned.
a = [ "a", "b", "c" ]
a.each {|x| print x, " -- " }
produces:
a -- b -- c --
Note that it says "Returns the array itself."
Compare that to map:
map { |item| block } → new_ary
map → Enumerator
Invokes the given block once for each element of self.
Creates a new array containing the values returned by the block.
See also Enumerable#collect.
If no block is given, an Enumerator is returned instead.
a = [ "a", "b", "c", "d" ]
a.collect { |x| x + "!" } #=> ["a!", "b!", "c!", "d!"]
a.map.with_index { |x, i| x * i } #=> ["", "b", "cc", "ddd"]
a #=> ["a", "b", "c", "d"]
Note that it says "Creates a new array containing the values returned by the block."
This example should help knowing the above:
foo = [1,2,3]
foo.each { |i| puts i + 1 } # => [1, 2, 3]
foo.map { |i| i + 1 } # => [2, 3, 4]
# >> 2
# >> 3
# >> 4
where # => is the return value of the block and # >> is the captured STDOUT from puts.
And, knowing all that, use each when you want to display elements in the array or extract and reuse those elements as parameters or to build things. Use map when you want to change the elements of the array into something else.
The difference is that each is performing an action on each element in the array, returning the original array. The action performed possibly mutated the element.
Whereas map is performing an action on each element in the array and returning its result as an array.
In the first case, map:
z = [1,2,3].map {|x| x + 1}
will take each element in the given array and perform the operation in the block and return a new array, so here it returns [2,3,4].
.each executes the block for each of the elements in the array, and it will not change anything in the array, so here it performs x + 1, but it doesn't store it anywhere, hence in the second case it just returns the array.
Now in the third example you posted, you are printing output in the block itself. Again, there is no change in the array itself.

Matlab, Random Cell Array

I have a cell array Q, wich contains questions. And a Logical vector containing 1/0 as true / false and in same order as Q like this:
Q = {'A ball is squared: ' 'My computer is slow: ' 'A triangle has 3 corners: '};
A = {0 1 1};
I would then make a Q_random, containing the questions from Q but in randomly order and a A_random contaning the logical numbers which respond to the Q_random. I've come up with this code, but i not sure that this is the best way to do it.
Could I use another method, which is more simple and effective ?
Q = {'A ball is squared: ' 'My computer is slow: ' 'A triangle has 3 corners: '};
A = {0 1 1};
Q_random = cell(1,numel(Q));
A_random = cell(1,numel(Q));
i = 1;
while (i <= numel(Q));
random_number = randi(numel(Q));
if isempty(Q_random{random_number});
Q_random(random_number) = Q(i);
A_random(random_number) = A(i);
i = i + 1;
else
end
I would use randperm to generate randomly ordered indexes
rand_ind=randperm(length(Q));
and then use the random indexes to generate the randomly permuted cell arrays
Q_random=Q(rand_ind);
A_random=A(rand_ind);
This answer to a previous related question may also be worth looking at.

Resources