war card game simulation in python - python

Hi you might remember this program if you are a regular here. I have solved many of the bugs but am stumped by one. The error is:
File "/Users/administrator/Desktop/war.py", line 62, in <module>
player1.extend(player1[range(warcardvalue1)])
TypeError: list indices must be integers, not list
the code is:
import random
cards = ['ace', 'ace', 'ace', 'ace', '1', '1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3', '4', '4', '4', '4', '5', '5', '5', '5', '6', '6', '6', '6', '7', '7', '7', '7', '8', '8', '8', '8', '9', '9', '9', '9', '10', '10', '10', '10', 'jack', 'jack', 'jack', 'jack', 'queen', 'queen', 'queen', 'queen', 'king', 'king', 'king', 'king']
order = ['ace', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jack', 'queen', 'king']
warcardvalue0 = 0
warcardvalue1 = 0
print "shuffling cards"
random.shuffle(cards)
print "lets play"
player0 = cards[1::2]
player1 = cards[::2]
while (len(player0) > 0 or len(player1) > 0):
nextcard0 = player0[0]
nextcard1 = player1[0]
cardplayed0 = order.index(nextcard0)
cardplayed1 = order.index(nextcard1)
if cardplayed0 > cardplayed1:
player0.append(nextcard0)
player0.append(nextcard1)
player0.remove(nextcard0)
player1.remove(nextcard1)
elif cardplayed0 < cardplayed1:
player1.append(nextcard1)
player1.append(nextcard0)
player1.remove(nextcard1)
player0.remove(nextcard0)
elif cardplayed0 == cardplayed1:
while warcardvalue0 == warcardvalue1:
if len(player0) >= 3:
warcard0 = player0[3]
elif len(player0) < 3:
warcard0 = player0[len(player0)-1]
if len(player1) >= 3:
warcard1 = player1[3]
elif len(player1) < 3:
warcard1 = player1[len(player1)-1]
warcardvalue0 = order.index(warcard0)
warcardvalue1 = order.index(warcard1)
if warcardvalue0 > warcardvalue1:
player0.extend(player0[range(warcardvalue0)])
player0.extend(player1[range(warcardvalue1)])
player0.extend(player0[range(warcardvalue0)])
player1.extend(player1[range(warcardvalue1)])
elif warcardvalue0 < warcardvalue1:
player1.extend(player1[range(warcardvalue1)])
player1.extend(player0[range(warcardvalue0)])
player1.extend(player1[range(warcardvalue1)])
player0.extend(player0[range(warcardvalue0)])
else:
print "another war!"
if len(player1) == 0:
print "player1 won!"
elif len(player0) == 0:
print "player0 won!"
I think the problem is that you cant use range in lists but I'm not sure.

I think the problem is that you cant use range in lists but I'm not sure.
The problem is that you can't index a list with a list.
Try this instead:
player1.extend(player1[:warcardvalue1])
Seems a bit odd to want to do it though....

Related

I don't understand why is this for loop so fast?

Today I was solving Project Euler's problem #43
Problem and I ran into a somewhat interesting problem. I don't understand why is my code so fast?
from itertools import permutations
def main():
numbers1_9 = [0,1,2,3,4,5,6,7,8,9]
list_of_all_permutations = list(permutations(numbers1_9, 10))
length_of_my_list = len(list_of_all_permutations)
number_of_times_it_ran=0
result = []
for n in list_of_all_permutations:
number_of_times_it_ran+=1
if n[0] == 0:
continue
elif n[3] % 2 == 0 and (n[2]+n[3]+n[4]) % 3 == 0 and n[5] % 5 ==0 and int(str(n[4])+str(n[5])+str(n[6])) % 7 == 0 and (n[5]+n[7]-n[6]) % 11 == 0 and int(str(n[6])+str(n[7])+str(n[8])) % 13 == 0 and int(str(n[7])+str(n[8])+str(n[9])) % 17 == 0:
temp_list = []
for digits_of_n in n:
temp_list.append(str(digits_of_n))
result.append(int("".join(temp_list)))
print(f"Added {temp_list}, Remaining: {length_of_my_list-number_of_times_it_ran}")
print(f"The code ran {number_of_times_it_ran} times and the result is {sum(result)}")
if __name__ == "__main__":
main()
I mean it went through the for loop 3,628,800 times, checked all those parameters, and only took a second.
Added ['1', '4', '0', '6', '3', '5', '7', '2', '8', '9'], Remaining: 3142649
Added ['1', '4', '3', '0', '9', '5', '2', '8', '6', '7'], Remaining: 3134251
Added ['1', '4', '6', '0', '3', '5', '7', '2', '8', '9'], Remaining: 3124649
Added ['4', '1', '0', '6', '3', '5', '7', '2', '8', '9'], Remaining: 2134649
Added ['4', '1', '3', '0', '9', '5', '2', '8', '6', '7'], Remaining: 2126251
Added ['4', '1', '6', '0', '3', '5', '7', '2', '8', '9'], Remaining: 2116649
The code ran 3628800 times, and the result is 16695334890
This is the output. The code finished in 1.3403266999521293 seconds.
It runs so quickly because of the short-circuiting feature of logical operators. The first three conditions in the if statement are easy to calculate, and they filter out the vast majority (around 97%) of all the permutations, so you hardly ever need to execute the more expensive operations like int(str(n[4])+str(n[5])+str(n[6])).
So when you have a bunch of conditions that you're connecting with and, and the order that they're tested doesn't matter for the logic, you should put the ones that are easiest to test or are most likely to fail first.

How to add specific elements from list of lists?

Let's say I have the following list that contains other lists:
episodes = [
['1', '2', '3', '4', '5', '6', '7'],
['1', '2', '3', '4', '5', '1', '2', '3', '4', '5', '6'],
['1', '2', '3', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '1', '2', '3']
]
Each list refer to episodes of TV-shows. For example, the first list has one season with 7 episodes, whereas the last list has five seasons with season one having 3 episodes, season 2 6 episodes and so on. I would like to save the total number of episodes for each TV-show by adding the total number of episodes for each season of the TV-show. In other words, first list is just taking the last element of that list, but the last list I have to add 3 & 6 & 6 & 4 & 3.
I hope you understand what I'm trying to do. I thought about using indexing and see where the element '1' lies in each list with more than one season so I can choose the element before (number of episodes of previous season) and so on. But it gets a bit tricky doing it for all other seasons as well.
if you just want the total number of episodes regardless of seasons just count the length of the each show list.
episodes = [
['1', '2', '3', '4', '5', '6', '7'],
['1', '2', '3', '4', '5', '1', '2', '3', '4', '5', '6'],
['1', '2', '3', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '1', '2', '3']
]
print(*[len(show) for show in episodes], sep="\n")
OUTPUT
7
11
22
If I understand you correctly you can just sum up the length of each list, i.e. sum(map(len, episodes))?
I came up with something like this to check for number of episodes in each season:
episodes = [
['1', '2', '3', '4', '5', '6', '7', "8", "9", "10", "11"],
['1', '2', '3', '4', '5',
'1', '2', '3', '4', '5', '6'],
['1', '2', '3',
'1', '2', '3', '4', '5', '6',
'1', '2', '3', '4', '5', '6',
'1', '2', '3', '4',
'1', '2', '3']
]
def count_episodes(list_of_episodes):
all_episodes = [e for l in list_of_episodes for e in l]
previous_episode = 0
season = 1
seasons = {}
tmp_list = []
for i in all_episodes:
if previous_episode > int(i):
seasons["season "+str(season)] = tmp_list
tmp_list = []
season += 1
previous_episode = int(i)
tmp_list.append(i)
if len(tmp_list) > 0:
seasons["season "+str(season)] = tmp_list
for i in seasons:
print(i + " has {} episodes".format(len(seasons[i])))
count_episodes(episodes)
OUTPUT
season 1 has 11 episodes
season 2 has 5 episodes
season 3 has 6 episodes
season 4 has 3 episodes
season 5 has 6 episodes
season 6 has 6 episodes
season 7 has 4 episodes
season 8 has 3 episodes
simpler solution
At the end, it is sth as simple as:
list(map(len, episodes))
## [7, 11, 22]
If all episodes are listed always, then you can just count the total number of episodes - it will be always the same as if you determined the maximum numbers and summed them up.
slighlty more elaborate solution
from functools import reduce
def list_to_max_seasons(lst, first_element='1'):
return reduce(lambda l, x: l + [x] if x == first_element else l[:-1] + [x], lst, [])
def sum_max_episodes(lol):
return [(lambda l: sum([int(x) for x in l]))(list_to_max_seasons(il)) for il in lol]
Test by:
sum_max_episodes(episodes)
## [7, 11, 22]
more elaborate (recursive) solution
These solutions are not very pythonic, I admit.
But they are quite universal.
def list_to_seasons(l, acc=[], by='1', tmp=[]):
if l == []:
return acc+[tmp]
elif l[0] == by:
if tmp == []:
return list_to_seasons(l[1:], acc=[], by=by, tmp=[l[0]])
else:
return list_to_seasons(l[1:], acc=acc+[tmp], by=by, tmp=[l[0]])
else:
return list_to_seasons(l[1:], acc=acc, by=by, tmp=tmp+[l[0]])
list_to_seasons(['1','2','3','1','2','1','2','3','1','1'])
## [['1', '2', '3'], ['1', '2'], ['1', '2', '3'], ['1'], ['1']]
Or:
def list_to_max_seasons(l, acc=[], by='1', last=None):
if l == []:
return acc+[last]
elif l[0] == by:
if last is None:
return list_to_max_seasons(l[1:], acc=[], by=by, last=l[0])
else:
return list_to_max_seasons(l[1:], acc=acc+[last], by=by, last=l[0])
else:
return list_to_max_seasons(l[1:], acc=acc, by=by, last=l[0])
list_to_max_seasons(['1','2','3','1','2','1','2','3','1','1'])
## ['3', '2', '3', '1', '1']
Then:
def sum_max_episodes(lol):
return [(lambda l: sum([int(x) for x in l]))(list_to_max_seasons(il)) for il in lol]
Test by:
sum_max_episodes(episodes)
## [7, 11, 22]

Deleting one position to another position elements from list in python

I have a list like the one below and I would like to delete all entries between any word (inclusive) and the next '0' (exclusive).
So for example this list:
array = ['1', '1', '0', '3', '0', '2', 'Continue', '1', '5', '1', '4', '0', '7', 'test', '3', '6', '0']
should become:
['1', '1', '0', '3', '0', '2', '0', '7', '0']
You can also do it by using exclusively list comprehension:
array = ['1', '1', '0', '3', '0', '2', 'Continue', '1', '5', '1', '4', '0', '7', 'test', '3', '6', '0']
# Find indices of strings in list
alphaIndex = [i for i in range(len(array)) if any(k.isalpha() for k in array[i])]
# Find indices of first zero following each string
zeroIndex = [array.index('0',i) for i in alphaIndex]
# Create a list with indices to be `blacklisted`
zippedIndex = [k for i,j in zip(alphaIndex, zeroIndex) for k in range(i,j)]
# Filter the original list
array = [i for j,i in enumerate(array) if j not in zippedIndex]
print(array)
Output:
['1', '1', '0', '3', '0', '2', '0', '7', '0']
array = ['1', '1', '0', '3', '0', '2', 'Continue', '1', '5', '1', '4', '0', '7', 'test', '3', '6', '0']
res = []
skip = False #Flag to skip elements after a word
for i in array:
if not skip:
if i.isalpha(): #Check if element is alpha
skip = True
continue
else:
res.append(i)
else:
if i.isdigit(): #Check if element is digit
if i == '0':
res.append(i)
skip = False
print res
Output:
['1', '1', '0', '3', '0', '2', '0', '7', '0']
Kicking it old school -
array = ['1', '1', '0', '3', '0', '2', 'Continue', '1', '5', '1', '4', '0', '7', 'test', '3', '6', '0']
print(array)
array_op = []
i=0
while i < len(array):
if not array[i].isdigit():
i = array[i:].index('0')+i
continue
array_op.append(array[i])
i += 1
print(array_op)

How to check columns and subgrids (Sudoku Checker in Python)?

I'm doing the traditional "Sudoku Puzzle Checker" activity, and I've only been able to figure out how to check the rows so far. As per instruction, I'm suppose to check (in 3 separate functions), the rows, columns, and subgrids (the 3x3 squares) of a solved sudoku puzzle (given in a .csv file). I understand how to do the columns (add 9 each time, 9 times starting numbers ranging from 0-8) and the subgrids (range of 3 numbers, add 6 to get to the next range of 3 numbers e.t.c) but I'm confused as how to implement these concepts into my code. Here's what I have right now:
def load_puzzle(filename):
file = open(filename, 'r')
puzzle = list(file)
#the puzzle currently looks like this:
['5,3,4,6,7,8,9,1,2\n', '6,7,2,1,9,5,3,4,8\n', '1,9,8,3,4,2,5,6,7\n', '8,5,9,7,6,1,4,2,3\n', '4,2,6,8,5,3,7,9,1\n', '7,1,3,9,2,4,8,5,6\n', '9,6,1,5,3,7,2,8,4\n', '2,8,7,4,1,9,6,3,5\n', '3,4,5,2,8,6,1,7,9\n']
print_puzzle(puzzle)
def print_puzzle(puzzle):
print(" ")
count = 0
while count <= 8:
line = list(puzzle[count])
line = [x for x in line if x != ',']
line.remove('\n')
line.insert(3, '|')
line.insert(7, '|')
if count == 3 or count == 6:
print("---------------------")
fresh = ' '.join(line)
count += 1
print('''
Checking puzzle...
''')
delimiter = ','
together = delimiter.join(puzzle)
new = list(together)
new[:] = [x for x in new if x != ',']
new[:] = [x for x in new if x != '\n']
check_rows(new)
#the puzzle now looks like this:
['5', '3', '4', '6', '7', '8', '9', '1', '2', '6', '7', '2', '1', '9', '5', '3', '4', '8', '1', '9', '8', '3', '4', '2', '5', '6', '7', '8', '5', '9', '7', '6', '1', '4', '2', '3', '4', '2', '6', '8', '5', '3', '7', '9', '1', '7', '1', '3', '9', '2', '4', '8', '5', '6', '9', '6', '1', '5', '3', '7', '2', '8', '4', '2', '8', '7', '4', '1', '9', '6', '3', '5', '3', '4', '5', '2', '8', '6', '1', '7', '9']
def check_numbers(numbers):
my_list = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
numbers.sort()
if numbers == my_list:
return True
else:
return False
def check_rows(n):
count = 0
start = 0
while count <= 8:
row = n[start:(start + 9)]
if check_numbers(row) is True:
count += 1
start += 9
elif check_numbers(row) is False:
break
if count == 9:
print("Rows okay...")
else:
print("Error in row", count)
check_columns(n)
def check_columns(n):
count = 0
start = 0
while count <= 8:
col = n[start::9]
if check_numbers(col) is True:
count += 1
start += 1
elif check_numbers(col) is False:
break
if count == 9:
print("Columns okay...")
else:
print("Error in row", count)
def check_subgrids(n):
filename = input("Enter file name of solved sudoku puzzle: ")
load_puzzle(filename)
I'm looking for a way to find the columns and subgrids similar to how I found the rows (i.e. row = n[start:(start + 9)]) if that's possible. I'm a beginner, so I'm also happy to learn about different tools/ways I could improve my code!
Edit: I've solved my problem with the check_columns function (code updated) but still would appreciate some guidance for the check_subgrid function!

Calculating element with most occurrences in list

I have
dict = {
0: ['9', '3', '3', '5', '1'],
1: ['9', '4', '1', '2'],
2: ['3', '4', '1', '5', '5'],
3: ['4', '4', '5', '5', '1'],
4: ['2', '8', '9', '5', '1']
}
take an example 0:['9', '3', '3', '5', '1'] here 3 has more number of occurance so iw ant to update enter list with only 3 so at index 0 becomes [3]
if every element has equal weight like 1: ['9', '4', '1', '2'] there will be no change
another ['4', '4', '5', '5', '1'] returns ['4','5']
i tried using collection.counter but donot know how to update the original dict with max repeated
for i,j in dictonary.items():
dictonary[i]=Counter(j)
expected output:
{0: ['3'], 1: ['9', '4', '1', '2'], 2: ['5'], 3: ['4'], 4: ['2', '8', '9', '5', '1']}
Edit: the list size may vary
[1,1,1,1,1,2,2,2,2,2,3,3,3]->[1,2]
[3,3,3,3,4,4,4,4,4,5,6,6,6,6,6]->[4,6]
from collections import *
d ={0: ['9', '3', '3', '5', '1'], 1: ['9', '4', '1', '2'], 2: ['3', '4', '1', '5', '5'], 3: ['4', '5', '0', '4', '3'], 4: ['2', '8', '9', '5', '1']}
for i,j in d.items():
c = Counter(j)
top = c.most_common(1)
if top[0][1] > 1:
d[i] = [ top[0][0] ]
print d
{0: ['3'], 1: ['9', '4', '1', '2'], 2: ['5'], 3: ['4'], 4: ['2', '8', '9', '5', '1']}
EDIT:
from collections import *
d = {
0: ['4', '4', '5', '5', '1'],
1: ['9', '4', '1', '2'],
2: ['3', '4', '1', '5', '5']
}
for i,j in d.items():
c = Counter(j)
result = []
for x in c:
if c[x] > 1:
result.append(x)
if result:
d[i] = result
print d
{0: ['5', '4'], 1: ['9', '4', '1', '2'], 2: ['5']}
EDIT:
from collections import *
d = {
0: ['4', '4', '5', '5', '1'],
1: [1,1,1,1,1,2,2,2,2,2,3,3,4],
2: ['3', '4', '1', '5', '5']
}
for i,j in d.items():
c = Counter(j)
longest = c.most_common(1)[0][1]
if longest > 1:
result = []
for x in c:
if c[x] == longest:
result.append(x)
d[i] = result
print d
{0: ['5', '4'], 1: [1, 2], 2: ['5']}
It appears you're looking for the mode of each element in your dictionary.
from collections import Counter
def mode(L):
result = []
for x in L:
if Counter(L)[x] == max(Counter(L).values()):
if x not in result: result.append(x)
return result
for item in dict:
dict[item] = mode(dict[item])

Categories