By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.
3
7 4
2 4 6
8 5 9 3
That is, 3 + 7 + 4 + 9 = 23.
Find the maximum total from top to bottom of the triangle below:
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23
NOTE: As there are only 16384 routes, it is possible to solve this problem by trying every route. However, Problem 67, is the same challenge with a triangle containing one-hundred rows; it cannot be solved by brute force, and requires a clever method! ;o)
My code is a bit haywire
a="75, 95 64, 17 47 82, 18 35 87 10, 20 04 82 47 65, 19 01 23 75 03 34, 88 02 77 73 07 63 67, 99 65 04 28 06 16 70 92, 41 41 26 56 83 40 80 70 33, 41 48 72 33 47 32 37 16 94 29, 53 71 44 65 25 43 91 52 97 51 14, 70 11 33 28 77 73 17 78 39 68 17 57, 91 71 52 38 17 14 91 43 58 50 27 29 48, 63 66 04 68 89 53 67 30 73 16 69 87 40 31, 04 62 98 27 23 09 70 98 73 93 38 53 60 04 23"
b=a.split(", ")
d=[]
ans=0
for x in range(len(b)):
b[x]= b[x].split(" ")
c= [int(i) for i in b[x]]
d.append(c)
index= d[0].index(max(d[0]))
print index
for y in range(len(d)):
ans+= d[y][index]
if y+1==len(d):
break
else:
index= d[y+1].index(max(d[y+1][index], d[y+1][index+1]))
print ans
So I'm getting 1063 as the answer whereas the actual answer is 1074. I guess my approach is right but there's some bug I'm still not able to figure out.
Your approach is incorrect. You can't just do a greedy algorithm. Consider the example:
3
7 4
2 4 6
8 5 9 500
Clearly:
3 + 7 + 4 + 9 = 23 < 500 + (other terms here)
Yet you follow this algorithm.
However if the triangle were just:
3
7 4
The greedy approach works, in other words, we need to reduce the problem to a kind of "3 number" triangle. So, assume the path you follow gets to 6, what choice should be made? Go to 500. (What happens if the apath goes to 4? What about 2?)
How can we use these results to make a smaller triangle?
It looks like you always choose the larger number (of left and right) in the next line (This is called a greedy algorithm.) But maybe choosing the smaller number first, you could choose larger numbers in the subsequent lines. (And indeed, by doing so, 1074 can be achieved.)
The hints in the comments are useful:
A backtrack approach would give the correct result.
A dynamic programming approach would give the correct result, and it's faster than the backtrack, thus it can work for problem 67 as well.
Small remark on your code.
The maximum sum in this triangle is indeed 1074. Your numbers are correct, just change your for-loop code from
for i,cell in enumerate(line):
newline.append(int(cell)+max(map(int,topline[max([0,i-1]):min([len(line),i+2])])))
to
for i,cell in enumerate(line):
newline.append(int(cell)+max(map(int,topline[max([0,i-1]):min([len(line),i+1])])))
(The "1" instead of "2")
Kindly
You can reach each cell only from the adjacent (at most) three cells on the top line, and the most favorable will be the one with the highest number among these, you don't need to keep track of the others.
I put an example of the code. This works for the pyramid aligned to the left as in your question (the original problem is with a centered pyramid, but at least I don't completely spoil the problem). Max total for my case is 1116:
d="""
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23
"""
ll=[line.split() for line in d.split('\n')][1:-1]
topline=ll[0]
for line in ll[1:]:
newline=[]
for i,cell in enumerate(line):
newline.append(int(cell)+max(map(int,topline[max([0,i-1]):min([len(line),i+2])])))
topline=newline
print newline
print "final results is %i"%max(newline)
I thought about this problem all day and night. Here is my solution:
# Maximum path sum I
import time
def e18():
start = time.time()
f=open("num_triangle.txt")
summ=[75]
for s in f:
slst=s.split()
lst=[int(item) for item in slst]
for i in range(len(lst)):
if i==0:
lst[i]+=summ[i]
elif i==len(lst)-1:
lst[i]+=summ[i-1]
elif (lst[i]+summ[i-1])>(lst[i]+summ[i]):
lst[i]+=summ[i-1]
else:
lst[i]+=summ[i]
summ=lst
end = time.time() - start
print("Runtime =", end)
f.close()
return max(summ)
print(e18()) #1074
P.S. num_triangle.txt is without first string '75'
Related
I have started to play around with Project Euler, however i hit a roadblock at problem 11
What is the greatest product of four adjacent numbers in the same
direction (up, down, left, right, or diagonally) in the 20×20 grid?`
There probably is a bug in my logic somewhere but even after multiple breaks and new approaches, i still have had no success.
The correct output should be 70600674 but i get 51267216.
This is more of an educational question, I would like to at least know where i messed up.
input.txt:
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
Main.py:
in_file = 'input.txt'
m = list(map(lambda line_str: list(map(int, line_str.split(' '))), open(in_file, 'r').read().split('\n')))
for line in m:
print(' '.join(map(lambda num: str(num).rjust(2), line)))
print()
vertical_max = horizontal_max = main_diag_max = second_diag_max = 0
for line in range(17):
for col in range(20):
vertical_max = max(vertical_max, m[line][col] * m[line+1][col] * m[line+2][col] * m[line+3][col])
for line in range(20):
for col in range(17):
horizontal_max = max(horizontal_max, m[line][col] * m[line][col+1] * m[line][col+2] * m[line][col+3])
for line in range(17):
for col in range(17):
main_diag_max = max(main_diag_max, m[line][col] * m[line+1][col+1] * m[line+2][col+2] * m[line+3][col+3])
for line in range(3, 20):
for col in range(3, 20):
second_diag_max = max(second_diag_max, m[line][col] * m[line-1][col-1] * m[line-2][col-2] * m[line-3][col-3])
print('max vertical: ', vertical_max)
print('max horizontal: ', horizontal_max)
print('max main diagonal: ', main_diag_max)
print('max secondary diagonal:', second_diag_max)
print('max result: ', max(vertical_max, horizontal_max, main_diag_max, second_diag_max))
For the second diagonal, your code should be:
for line in range(3, 20):
for col in range(17):
second_diag_max = max(second_diag_max, m[line ][col ] *
m[line-1][col+1] *
m[line-2][col+2] *
m[line-3][col+3])
The problem was that instead of increasing col while decreasing line you were decreasing both. That was essentially checking main diagonal again, but from the opposite direction.
So basically we are given a text that looks like this:
20
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
It's a 20x20 dimensional square, and you have to figure out the greatest product of four adjacent numbers in the same direction (horizontal, vertical, or diagonal) in a grid of positive integers. This is what I have:
def main():
# open file for reading
in_file = open ("./Grid.txt", "r")
dimension = in_file.readline()
dimensions = int(dimension)
greatest = 0
grid = ''
largest = [0, 0, 0, 0]
for i in range (0, dimensions):
grid = grid + in_file.readline()
grid = grid.strip()
grid = grid.replace(" ","")
i = 0
j = 0
print(int(grid[i]))
for i in range (0, dimensions * 2 + (dimensions - 1)):
for j in range (0, dimensions * 2 + (dimensions - 1) - 3):
if (int(grid[i])*10 + int(grid[i+1]))*(int(grid[i+2])*10 + int(grid[i+3]))*(int(grid[i+4])*10 + int(grid[i+5]))*(int(grid[i+6])*10 + int(grid[i+7])) > largest[0]:
largest[0] = (int(grid[i])*10 + int(grid[i+1]))*(int(grid[i+2])*10 + int(grid[i+3]))*(int(grid[i+4])*10 + int(grid[i+5]))*(int(grid[i+6])*10 + int(grid[i+7]))
print(max(largest))
main()
I know it's super complicated but basically, I'm not sure how to make this set of numbers look like a list of numbers (an array)... So I essentially end up having to make the numbers. For example the first number is 02, so I multiple 0 by 10, and add 2... Anyways, the problem is that I get ValueError: invalid literal for int() with base 10: '\n'. Any help is appreciated!
The problem is this line:
grid = grid + in_file.readline()
Change it to:
grid = grid + in_file.readline().strip() # you must strip each line
You need to strip each line as you read it, but currently, you're stripping only the final string, which leaves all the whitespace you have in each line present. Eventually, your code tries to convert non-numeric characters (e.g. spaces, newlines) into numbers and runs into the error.
After the fix, running it produces the following output:
➜ /tmp ./test.py
0
1614
Additional Recommendations
You definitely need to make your code more readable before posting. It was painful to look at and even more painful to debug... I almost left it there.
One possible start could be in the complicated for loop. Consider:
for i in range (0, dimensions * 2 + (dimensions - 1)):
for j in range (0, dimensions * 2 + (dimensions - 1) - 3):
tmp = int(grid[i]) * 10 \
+ int(grid[i+1]) * int(grid[i+2]) * 10 \
+ int(grid[i+3]) * int(grid[i+4]) * 10 \
+ int(grid[i+5]) * int(grid[i+6]) * 10 \
+ int(grid[i+7])
if tmp > largest[0]:
largest[0] = tmp
First, it allowed me to see that the culprit was int(grid[i+7]) instruction, whereas before it would show the entire line while complaining and was not informative.
Second, it does not calculate exactly the same thing twice. It uses a temporary variable instead.
Third, you should consider converting your grid variable into an actual grid (e.g. an array of arrays). Currently, it's merely a string, so the name is misleading.
Fourth, while you turn grid into an actual grid, you can use a list comprehension and convert the values into numbers directly, as in this short example:
>>> line = '12 34 5 6 78 08 1234'
>>> [int(v) for v in line.split()]
[12, 34, 5, 6, 78, 8, 1234] # array of integers, not strings
>>>
It will save you the conversions before getting to the other parts and validates the data for you in the process while the code is still simpler, instead of waiting to your complicated calculations to blow up.
By starting at the top of the triangle below and moving to adjacent numbers on the row below, find the maximum total from top to bottom of the triangle below.
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23
This is Project Euler, Problem 18.
I got an answer as 1064. But they say it is wrong. Help me...in python 2.7
This is my code:
s='''Here the sequence'''
s=s.split("\n")
value=0
total=0
for x in range(len(s)):
y=s[x].split()
if (value+1)>x:
total+=int(y[value])
print int(y[value])
else:
if int(y[value])>int(y[value+1]):
total+=int(y[value])
print int(y[value])
else:
total+=int(y[value+1])
print int(y[value+1])
value+=1
print "Total:::%d"%total
The problem with your algorithm is that you only explore a single path through the triangle: At each "junction", you always select the higher value and proceed down that path. But this "greedy" algorithm does not always work. Consider this example:
1 Yours: (1) Best: (1)
1 2 1 (2) (1) 2
9 1 1 9 (1) 1 (9) 1 1
When presented with the choice of 1 or 2, you select 2 and go down the right path, missing out the 9. Instead, you have to consider all the paths. You can do this in a "dynamic programming" kind of fashion, where you store the highest-possible value that can be reached in each cell and then just add them up. You can do this top-down or bottom-up, and then just select the highest value in the final row.
Example (bottom-up): In each step, add the maximum of the two adjacent lower cells to the cell above.
5 5 5 5 5 ==> 5+17
2 4 2 4 2 4 ==> 2+11 4+13 ==> 13 17
3 5 7 ==> 3+5 5+6 7+6 ==> 8 11 13
1 5 6 2
Implementing this idea in an algorithm is left as an excercise to the reader. ;-)
You have a greedy algorithm, which appends the largest adjacent number at every iteration. It produces a suboptimal solution. Simple explanation - consider just a triangle that consists of three top rows. Your solution will be 75 + 95 + 47 = 217. While the optimal solution in this case is 75 + 64 + 82 = 221. How to solve this? I would recommend designing a dynamic programming algorithm.
This is in reference to the problem posted in:
http://projecteuler.net/problem=11
I have encountered an oversimplified solution using python as follows:(mayoff)
grid = [[0]*23]*3 + [[int(x) for x in line.split()]+[0,0,0] for line in
'''08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48'''.split('\n')
] + [[0]*23]*3
import operator
print max([reduce(operator.mul, [grid[y+n*d[0]][x+n*d[1]] for n in (0,1,2,3)])
for x in xrange(0,20) for y in xrange(3,23)
for d in ((0,1),(1,0),(1,1),(-1,1))])
The grid is simply a 2-dimensioanl matrix equivalent to the 20x20 matrix given in the problem.
My understanding with the max() function is that it takes a list of integers as an input and then selects from it the maximum value and returns it.
The question is, how come the succeeding for-loops in the last expression are located outside the parameter list in max()? This sounds confusing to me since to create a list using a for-loop we can do it with the following:
>>> line = "12 12 12 12 12 12"
>>> [x for x in line.split()]
['12','12','12','12','12','12']
and doing something similar below would result into an error
>>> [x] for x in line.split()
After your clarification - actually, they are not, if you look better, you have this:
print max(
[
reduce(
operator.mul,
[grid[y+n*d[0]][x+n*d[1]] for n in (0,1,2,3)])
for x in xrange(0,20)
for y in xrange(3,23)
for d in ((0,1),(1,0),(1,1),(-1,1))
])
To reduce some clutter, what you have is this:
print max(
[
reduce(...)
for x in ...
for y in ...
for d in ...
])
i.e.:
print max([reduce(...) for x in ... for y in ... for d in ...])
which is a list comprehension such as the one you gave as an example ([x for x in line.split()] ).
See the documentation:
http://docs.python.org/library/functions.html#max
Excerpt:
max(iterable[, args...][key])
With a single argument iterable, return the largest item of a non-empty iterable (such as a string, tuple or list). With more than one argument, return the largest of the arguments.
You can do e.g. this:
>>> max(1, 2, 3)
3
i.e. run max with a number of parameters and it will give you the maximum of these, or e.g. you can do this:
>>> max([1,2,3])
3
and it will treat it as the iterable and give you the maximum in an iterable. Strings are iterables, so you can do this, too:
>>> max("aqrmn")
'r'
or this:
>>> max(dict(the=1,biggest=-1,word=2,maybe=4,this=0))
'word'
where it considers keys of a dictionary, maybe easier to grasp like this:
>>> max({1:"hey", 5:"man", -3:"how", 7:"are", 3: "you?"})
7
Hope this helps.
>> help(max)
max(...)
max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.
That max does return the maximum value. If you want the location do:
a = [reduce(operator.mul, [grid[y+n*d[0]][x+n*d[1]] for n in (0,1,2,3)])
for x in xrange(0,20) for y in xrange(3,23)
for d in ((0,1),(1,0),(1,1),(-1,1))
max_value = max(a)
max_value_position = a.index(max_value)
Not exactly sure what you want. But you did get the maximum value of the list created.
I've got a list of 400 numbers, and i want to but them in a 20x20 grid using Python.
I've made a "2d array" (not really because Python doesn't support them, I've had to use a list of lists.)
When i try to loop through and assign each subsequnt item to the next box in the grid, it fails. i end up assinging the last item in the list to every box.
Here's the code:
numbers = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48"
grid = [[0 for col in range(20)] for row in range(20)]
for x in range(0, 1200, 3):
y = x + 2
a = numbers[x:y]
for i in range(20):
for j in range(20):
grid[i][j] = a
print(grid)
I can see why it's going wrong: the two loops that generate the list coordinates are inside the loop that gets each items from the list, so each time they run the value they are assigning doesn't change.
Therefore I guess seeing as they don't work in the loop, they need to be out of it.
The problem is that I can't work out where exactly.
Anyone give me a hand?
This is the sort of thing that list comprehensions are good for.
nums = iter(numbers.split())
grid = [[next(nums) for col in range(20)] for row in range(20)]
Alternatively, as a for loop:
grid = [[0]*20 for row in range(20)]
nums = iter(numbers.split())
for i in xrange(20):
for j in xrange(20):
grid[i][j] = next(nums)
I'm not recommending that you do this, but the way to do it if you don't just want to split the list and then call next on its iterator is to write a generator to parse the list the way that you were and then call next on that. I point this out because there are situations where builtins wont do it for you so you should see the pattern (not Design Pattern, just pattern for the pedantic):
def items(numbers):
for x in range(0, len(numbers), 3):
yield numbers[x:x+2]
nums = items(numbers)
for i in xrange(20):
for j in xrange(20):
grid[i][j] = next(nums)
This lets you step through the two loops in parallel.
Another alternative is to use the grouper idiom:
nums = iter(numbers.split())
grid = zip(*[nums]*20)
Note that this makes a list of tuples, not a list of lists.
If you need a list of lists, then
grid = map(list,zip(*[nums]*20))
Your for loop confusion stems from having more loops than you need.
Instead, one approach is to start by looping over your grid squares and then figuring out the needed offset into your list of numbers:
for i in range(20):
for j in range(20):
offset = i*20*3 + j*3
grid[i][j] = numbers[offset:offset+2]
In this case, the offset has a few constants. i is the row, so for each row you need to skip over a row's worth of characters (60) in your list. j is the column index; each column is 3 characters wide.
You could, of course, do this operation in reverse. In that case, you would loop over your list of numbers and then figure out to which grid square it belongs. It works very similarly, except you'd be using division and modulo arithmetic instead of multiplication in the offset above.
Hopefully this provides some insight into how to use for loops to work with multiple objects and multiple dimensions.