String to list of list - python

I have a file in which I have some lines that looks like this:
[16, 1, 4, 15][0, 4, 5, 14][8, 9, 10, 3][2, 11, 12, 6][0, 1, 10, 11][1, 19, 12, 14][19, 3, 13, 15][9, 17, 14, 15][9, 2, 18, 17][8, 2, 13, 7][4, 2, 19, 12][16, 18, 3, 4][10, 3, 5, 15][16, 9, 18, 6][1, 19, 5, 7][0, 12, 6, 7][0, 17, 11, 13][16, 8, 18, 7][8, 17, 11, 13][10, 6, 5, 14]
and I want to read them, and make a list of lists with each line.
I've tried split() function but does not work.
What I've tried is:
file = open(filename, 'r')
string.split(',')
print(string[3])
But it returns ,, not [2, 11, 12, 6]
Any guesses? Thanks in advance!

You could use json and a list comprehension
import json
line = [16, 1, 4, 15][0, 4, 5, 14][8, 9, 10, 3][2, 11, 12, 6][0, 1, 10, 11][1, 19, 12, 14][19, 3, 13, 15][9, 17, 14, 15][9, 2, 18, 17][8, 2, 13, 7][4, 2, 19, 12][16, 18, 3, 4][10, 3, 5, 15][16, 9, 18, 6][1, 19, 5, 7][0, 12, 6, 7][0, 17, 11, 13][16, 8, 18, 7][8, 17, 11, 13][10, 6, 5, 14]
lst = [json.loads(sublist+']') for sublist in line.split(']') if sublist]
#[[16, 1, 4, 15],
# [0, 4, 5, 14],
# [8, 9, 10, 3],
# [2, 11, 12, 6],
# [0, 1, 10, 11],
# [1, 19, 12, 14],
# [19, 3, 13, 15],
# [9, 17, 14, 15],
# [9, 2, 18, 17],
# [8, 2, 13, 7],
# [4, 2, 19, 12],
# [16, 18, 3, 4],
# [10, 3, 5, 15],
# [16, 9, 18, 6],
# [1, 19, 5, 7],
# [0, 12, 6, 7],
# [0, 17, 11, 13],
# [16, 8, 18, 7],
# [8, 17, 11, 13],
# [10, 6, 5, 14]]
In this code, I split the line based on ']', this gives me a list of strings like '[16, 1, 4, 15', '[0, 4, 5, 14', ... Then for each of these strings, I add the ending bracket and use json to interpret it and transform it into a list.

In another website I get an answer which works (I don't know if it's a good way to do it, but it works for me).
A typical line in my file looks like this:
[16, 1, 4, 15][0, 4, 5, 14][8, 9, 10, 3][2, 11, 12, 6][0, 1, 10, 11][1, 19, 12, 14][19, 3, 13, 15][9, 17, 14, 15][9, 2, 18, 17][8, 2, 13, 7][4, 2, 19, 12][16, 18, 3, 4][10, 3, 5, 15][16, 9, 18, 6][1, 19, 5, 7][0, 12, 6, 7][0, 17, 11, 13][16, 8, 18, 7][8, 17, 11, 13][10, 6, 5, 14]
Is a string, not a list. And I want to make a list of lists from that str.
And my code now looks like this:
line=file.readline() # stores the str line from the file
line = '[' + line + ']'
line = line.replace('][', '],[')
line = ast.literal_eval(line)
Now I can access to each list within the (big) list, and each value in each list.

If you do not want to use an extra module, you can do it with list comprehensions and string split and strip methods:
[[int(s.strip()) for s in sublist.split(',')] for sublist in line[1:-1].split('][')]
#[[16, 1, 4, 15],
# [0, 4, 5, 14],
# [8, 9, 10, 3],
# [2, 11, 12, 6],
# [0, 1, 10, 11],
# [1, 19, 12, 14],
# [19, 3, 13, 15],
# [9, 17, 14, 15],
# [9, 2, 18, 17],
# [8, 2, 13, 7],
# [4, 2, 19, 12],
# [16, 18, 3, 4],
# [10, 3, 5, 15],
# [16, 9, 18, 6],
# [1, 19, 5, 7],
# [0, 12, 6, 7],
# [0, 17, 11, 13],
# [16, 8, 18, 7],
# [8, 17, 11, 13],
# [10, 6, 5, 14]]

s='[16, 1, 4, 15][0, 4, 5, 14][8, 9, 10, 3][2, 11, 12, 6][0, 1, 10, 11][1, 19, 12, 14][19, 3, 13, 15][9, 17, 14, 15][9, 2, 18, 17][8, 2, 13, 7][4, 2, 19, 12][16, 18, 3, 4][10, 3, 5, 15][16, 9, 18, 6][1, 19, 5, 7][0, 12, 6, 7][0, 17, 11, 13][16, 8, 18, 7][8, 17, 11, 13][10, 6, 5, 14]'
[l.split(',') for l in s[1:-1].split('][')]

If string is the line that you gave above, a 1-line solution using a list comprehension is:
[[int(s) for s in t.split(',')] for t in string.strip()[1:-1].split('][')]
Like thus:
>>> string = '[16, 1, 4, 15][0, 4, 5, 14][8, 9, 10, 3][2, 11, 12, 6][0, 1, 10, 11][1, 19, 12, 14][19, 3, 13, 15][9, 17, 14, 15][9, 2, 18, 17][8, 2, 13, 7][4, 2, 19, 12][16, 18, 3, 4][10, 3, 5, 15][16, 9, 18, 6][1, 19, 5, 7][0, 12, 6, 7][0, 17, 11, 13][16, 8, 18, 7][8, 17, 11, 13][10, 6, 5, 14]\n'
>>> [[int(s) for s in t.split(',')] for t in string.strip()[1:-1].split('][')]
[[16, 1, 4, 15], [0, 4, 5, 14], [8, 9, 10, 3], [2, 11, 12, 6], [0, 1, 10, 11], [1, 19, 12, 14], [19, 3, 13, 15], [9, 17, 14, 15], [9, 2, 18, 17], [8, 2, 13, 7], [4, 2, 19, 12], [16, 18, 3, 4], [10, 3, 5, 15], [16, 9, 18, 6], [1, 19, 5, 7], [0, 12, 6, 7], [0, 17, 11, 13], [16, 8, 18, 7], [8, 17, 11, 13], [10, 6, 5, 14]]
This last is clearly a list of lists of integers, and not a string, as the following output shows:
>>> [sum(nums) for nums in [[int(s) for s in t.split(',')] for t in string.strip()[1:-1].split('][')]]
[36, 23, 30, 31, 22, 46, 50, 55, 46, 30, 37, 41, 33, 49, 32, 25, 41, 49, 49, 35]

The string you are reading is almost ready:
it needs an opening "["
commas between each list
and a closing "]"
just modify your string, that you have in a variable string as I see from your question, and then parse it with json.loads, or ast.literal_eval
import json # or ast
parse = json.loads
# or
# parse = ast.literal_eval
new_string = parse("".join(["[", string.replace("][", "],["), "]"])

Related

How can i changes the values in a nested list to those specified in a dict? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have this code in which I have a list of lists and inside the sub-lists we got numbers. However, I also have a dict storing key-value pairs of name-number, in which the number is the index of the name stored in another list, but I want to replace all the numbers in the nested list with their respective names. Instead of having [1,9,13] I want to have ['The Beach Chimney', 'Parlay', 'The Private Exhibit'].
out = [(ind,ind2) for ind,i in enumerate(rows)
for ind2,y in enumerate(i) if y == '1']
list_of_restaurants_index = []
for empty_list in range(100):
empty_list = []
list_of_restaurants_index.append(empty_list)
for i in out:
for empty_list in list_of_restaurants_index:
if i[0] == list_of_restaurants_index.index(empty_list):
empty_list.append(i[1])
print(list_of_restaurants_index)
restaurants_dict = {}
for i in header:
restaurants_dict[i] = header.index(i)
Output:
[[1, 9, 13], [8, 14, 17], [6, 14], [4, 8, 9, 12], [1, 2, 5, 6, 12, 13, 18], [1, 4, 5, 8, 10, 11, 12], [1, 12, 14, 16], [3, 4, 5, 13, 14, 17, 18], [4, 9, 10, 12, 13, 14, 15, 18], [3, 16], [1, 3, 5, 10, 13], [1, 5, 10, 15, 17], [2, 4, 6, 7, 10, 13], [2, 4, 9, 12], [9, 11, 12, 13], [1, 3, 4, 7, 9, 17], [6, 8, 9, 10, 11, 13, 14, 15, 18], [2, 4, 6, 7, 8, 13], [4, 7, 10, 11, 13, 14, 16, 18], [7, 12, 16, 17, 18], [3, 7, 10, 13, 14], [1, 2, 3, 5, 8, 12, 14, 17, 18], [8, 10, 12, 13, 16, 17], [4, 5, 6, 7, 8, 11, 17], [1, 4, 7, 9, 13, 16], [4, 10, 12, 14, 15], [2, 3, 4, 11, 13, 14, 15, 17], [1, 2, 7, 8, 9, 16], [5, 6, 7], [4, 5, 6], [10, 16, 18], [6, 13, 14, 17], [1, 6, 16, 17], [1, 2, 4, 5, 10, 12, 15, 18], [3, 4, 10, 12, 14, 16, 18], [1, 2, 6, 8, 9, 11, 13, 14, 16, 17], [5, 6, 7], [1, 2, 5, 10, 13, 18], [4, 5, 13, 18], [5, 7, 9, 10, 11, 12, 15, 17], [2, 14], [4, 5, 9, 11, 12, 14], [1, 3, 5, 10, 11, 15], [3, 12, 13, 16], [1, 4, 5, 6, 7, 9, 11, 13, 14, 15], [4, 6, 9, 13, 15, 16, 18], [2, 3, 4, 6, 9, 12, 14, 15], [1, 7, 12, 14, 17], [5, 6, 8, 10, 11, 12, 15, 18], [2], [2], [4, 5, 7, 11, 12, 14], [1, 4, 9, 14, 18], [3, 6, 8, 15, 18], [1, 4, 7, 8, 14], [3, 4, 7, 11, 15], [1, 4, 5, 6, 10, 13, 14, 15, 16, 18], [2], [2], [5, 6, 8, 14, 15, 16, 18], [6], [8, 10, 12, 16], [1, 4, 5, 10, 14, 17, 18], [6], [5, 6, 9, 10, 13, 14], [1, 11, 12, 17], [1, 5, 10, 14, 15], [3, 4, 6, 9, 10, 15, 18], [4, 8, 10, 16, 17, 18], [4, 7, 14, 17], [1, 2, 3, 9, 16], [10, 12, 14, 16], [1, 2, 8, 10, 15], [1, 2, 4, 10, 13, 17], [3, 7, 17], [4, 5, 6], [4, 6, 11, 12, 17], [1, 2, 7, 8, 13, 16], [1, 2, 4, 8, 13], [8, 11], [1, 4, 5, 6, 7, 18], [1, 4, 5, 11, 12, 14, 17], [5, 8, 9, 14], [2], [4, 5, 7, 10, 14, 16], [6], [1, 2, 3, 4, 7, 11, 13, 14], [7, 12, 14], [3, 4, 7, 11, 13], [1, 2, 3, 4, 6, 7, 8, 9, 14, 15], [2], [6], [5, 12, 15, 16, 17, 18], [3, 4, 5, 11, 12, 13], [3, 5, 6, 14, 17, 18], [9, 12, 13, 15], [4, 14, 15, 16, 18], [4, 8], [3], [3]]
Also, here's what the dict is storing:
{'': 0, 'The Beach Chimney': 1, "The Pirate's Harvest": 2, 'The Square Dragon': 3, 'The Spicy Trumpet': 4, 'Vertigo': 5, 'Drifters': 6, 'The Tulip': 7, 'Seawise': 8, 'Parlay': 9, 'The Modern Salmon': 10, 'The Bitter Windmill': 11, 'The Minty Window': 12, 'The Private Exhibit': 13, 'Enigma': 14, 'The Lighthouse': 15, 'Harlequin': 16, 'Midnight': 17, 'Gastrognome': 18}
obs: header is a list containing the names.
Not sure the purpose of the dict.
empty_list.append(i[1]) seems to be appending a number
That number happens to align with the indicies of the strings you want.
Therefore, you could instead use
name = header[i[1]]
empty_list.append(name)
Having trouble making out where you are starting from, but starting from your output of the list of integers and the dict at the end of your question, you could do this:
inverted_dict = {restaurants_dict[k]:k for k in restaurants_dict}
rest_names = []
for i in range(len(list_of_restaurants_index)):
row = []
for j in range(len(list_of_restaurants_index[i])):
row.append(inverted_dict[list_of_restaurants_index[i][j]])
rest_names.append(row)
"rest_names" should be what you want, I think.
This creates a new list, rather than editing the members of your original list. Not sure if that matters to you.

Find all combinations of N length of every element of one list associated with every element of a second list, with conditions

I'm trying to write a splitting algorithm. I have a first list with 24 elements, [x for x in range(24)], and a second list with 3 elements, [a,b,c].
Every element in the second list can be represented as a "bucket".
The set of the combination of the three buckets, set([a] + [b] + [c]), need to be equal to the set of all the elements in the first list of 24 elements, set([x for x in range(24)]). Each element of the first list can only be in one bucket at a time.
What I need, is to find all combinations of the above problem, where every element in the first list is in a bucket. I tried to pass list(itertools.product(list_1, list_2)) into itertools.permutations with a specified length of 24, but even with my 48 cores processor and 128gb ram, it's taking forever, as I cannot specify that every element in the first list can only be associated with one element of the second list.
I'm pretty desperate here. Can someone help me?
You can use itertools.product in the following way:
assigned_buckets = it.product([a, b, c], repeat=len(list_1))
This produces one bucket assignment per element of list_1 and yields all such combinations.
The resulting list is too large for memory and would always take a long time to produce.
If you're only looking to generate solutions and iterate through them (presumably not all 282,429,536,481 of them), you could create a generator function using itertools.product:
from itertools import product
def makeBuckets(buckets,values):
for combo in product(range(len(buckets)),repeat=len(values)):
yield { b:[v for iv,v in zip(combo,values) if iv==ib]
for ib,b in enumerate(buckets) }
buckets = makeBuckets("abc",list(range(24)))
for _ in range(10): print(next(buckets))
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], 'b': [], 'c': []}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], 'b': [23], 'c': []}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], 'b': [], 'c': [23]}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], 'b': [22], 'c': []}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 'b': [22, 23], 'c': []}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 'b': [22], 'c': [23]}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], 'b': [], 'c': [22]}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 'b': [23], 'c': [22]}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 'b': [], 'c': [22, 23]}
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23], 'b': [21], 'c': []}

Reshaping a numpy array into desired shape

I am working in numpy and have a numpy array of the form;
[[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12],
[13, 14, 15],
[16, 17, 18],
[19, 20, 21],
[22, 23, 24]]
I want to use only the reshape and transpose functions and obtain the following array:
[[ 1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21],
[ 4, 5, 6, 10, 11, 12, 16, 17, 18, 22, 23, 24]]
Can this be done? I have spent hours trying and am starting to think it just can't be done - am I missing something obvious?
You can reshape into columns, then transpose, then reshape with something like:
a = np.array([[ 1,2,3],
[ 4,5,6],
[ 7,8,9],
[10, 11, 12],
[13, 14, 15],
[16, 17, 18],
[19, 20, 21],
[22, 23, 24]])
a.reshape(-1, 2, 3).transpose((1, 0, 2)).reshape(2, -1)
# array([[ 1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21],
# [ 4, 5, 6, 10, 11, 12, 16, 17, 18, 22, 23, 24]])
You may try to slice odd and even and pass them to np.reshape.
a_out = np.reshape([a[::2], a[1::2]], (2,-1))
Out[81]:
array([[ 1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21],
[ 4, 5, 6, 10, 11, 12, 16, 17, 18, 22, 23, 24]])

What should be the terminating condition for this implementation of the 15-puzzle problem?

I am trying to implement a solution for outputting the sequence of moves for a 15-puzzle problem in Python. This is part of an optional assignment for a MOOC. The problem statement is given at this link.
I have a version of the program (given below) which performs valid transitions.
I am first identifying the neighbors of the empty cell (represented by 0) and putting them in a list. Then, I am randomly choosing one of the neighbors from the list to perform swaps with the empty cell. All the swaps are accumulated in a different list to record the sequence of moves to solve the puzzle. This is then outputted at the end of the program.
However, the random selection of numbers to make the swap with the empty cell is just going on forever. To avoid "infinite" (very long run) of loops, I have limited the number of swaps to 30 for now.
from random import randint
def find_idx_of_empty_cell(p):
for i in range(len(p)):
if p[i] == 0:
return i
def pick_random_neighbour_idx(neighbours_idx_list):
rand_i = randint(0, len(neighbours_idx_list)-1)
return neighbours_idx_list[rand_i]
def perform__neighbour_transposition(p, tar_idx, src_idx):
temp = p[tar_idx]
p[tar_idx] = p[src_idx]
p[src_idx] = temp
def solve_15_puzzle(p):
standard_perm = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0]
neighbours_idx_list = []
moves_sequence = []
empty_cell_idx = find_idx_of_empty_cell(p)
previous_empty_cell_idx = empty_cell_idx
while (not(p == standard_perm) and len(moves_sequence) < 30):
if not (empty_cell_idx in [0,4,8,12]):
neighbours_idx_list.append(empty_cell_idx - 1)
if not (empty_cell_idx in [3,7,11,15]):
neighbours_idx_list.append(empty_cell_idx + 1)
if not (empty_cell_idx in [0,1,2,3]):
neighbours_idx_list.append(empty_cell_idx - 4)
if not (empty_cell_idx in [12,13,14,15]):
neighbours_idx_list.append(empty_cell_idx + 4)
if previous_empty_cell_idx in neighbours_idx_list:
neighbours_idx_list.remove(previous_empty_cell_idx)
chosen_neighbour_idx = pick_random_neighbour_idx(neighbours_idx_list)
moves_sequence.append(p[chosen_neighbour_idx])
perform__neighbour_transposition(p, empty_cell_idx, chosen_neighbour_idx)
previous_empty_cell_idx = empty_cell_idx
empty_cell_idx = chosen_neighbour_idx
neighbours_idx_list = []
if (p == standard_perm):
print("Solution: ", moves_sequence)
For the below invocation of the method, the expected output is [15, 14, 10, 13, 9, 10, 14, 15].
solve_15_puzzle([1, 2, 3, 4, 5, 6, 7, 8, 13, 9, 11, 12, 10, 14, 15, 0])
The 15-tiles problem is harder as it may seem at a first sight.
Computing the best (shortest) solution is a difficult problem and it has been proved than finding the optimal solution as N increases is NP-hard.
Finding a (non-optimal) solution is much easier. A very simple algorithm that can be made to work for example is:
Define a "distance" of the current position as the sum of the manhattan
distances of every tile from the position you want it to be
Start from the given position and make some random moves
If the distance after the moves improves or stays the same then keep the changes, otherwise undo them and return to the starting point.
This kind of algorithm could be described as a multi-step stochastic hill-climbing approach and is able to solve the 15 puzzle (just make sure to allow enough random moves to be able to escape a local minimum).
Python is probably not the best language to attack this problem, but if you use PyPy implementation you can get solutions in reasonable time.
My implementation finds a solution for a puzzle that has been mixed up with 1000 random moves in seconds, for example:
(1, 5, 43, [9, [4, 10, 14, 11, 15, 3, 8, 1, 13, None, 9, 7, 12, 2, 5, 6]])
(4, 17, 41, [9, [4, 10, 14, 11, 15, 3, 8, 1, 12, None, 6, 2, 5, 13, 9, 7]])
(7, 19, 39, [11, [4, 10, 14, 11, 15, 3, 1, 2, 12, 6, 8, None, 5, 13, 9, 7]])
(9, 54, 36, [5, [4, 14, 3, 11, 15, None, 10, 2, 12, 6, 1, 8, 5, 13, 9, 7]])
(11, 60, 34, [10, [4, 14, 3, 11, 15, 10, 1, 2, 12, 6, None, 8, 5, 13, 9, 7]])
(12, 93, 33, [14, [4, 14, 11, 2, 15, 10, 3, 8, 12, 6, 1, 7, 5, 13, None, 9]])
(38, 123, 31, [11, [4, 14, 11, 2, 6, 10, 3, 8, 15, 12, 1, None, 5, 13, 9, 7]])
(40, 126, 30, [13, [15, 6, 4, 2, 12, 10, 11, 3, 5, 14, 1, 8, 13, None, 9, 7]])
(44, 172, 28, [10, [15, 4, 2, 3, 12, 6, 11, 8, 5, 10, None, 14, 13, 9, 1, 7]])
(48, 199, 23, [11, [15, 6, 4, 3, 5, 12, 2, 8, 13, 10, 11, None, 9, 1, 7, 14]])
(61, 232, 22, [0, [None, 15, 4, 3, 5, 6, 2, 8, 1, 12, 10, 14, 13, 9, 11, 7]])
(80, 276, 20, [10, [5, 15, 4, 3, 1, 6, 2, 8, 13, 10, None, 7, 9, 12, 14, 11]])
(105, 291, 19, [4, [9, 1, 2, 4, None, 6, 8, 7, 5, 15, 3, 11, 13, 12, 14, 10]])
(112, 313, 17, [9, [1, 6, 2, 4, 9, 8, 3, 7, 5, None, 14, 11, 13, 15, 12, 10]])
(113, 328, 16, [15, [1, 6, 2, 4, 9, 8, 3, 7, 5, 15, 11, 10, 13, 12, 14, None]])
(136, 359, 15, [4, [1, 6, 2, 4, None, 8, 3, 7, 9, 5, 11, 10, 13, 15, 12, 14]])
(141, 374, 12, [15, [1, 2, 3, 4, 8, 6, 7, 10, 9, 5, 12, 11, 13, 15, 14, None]])
(1311, 385, 11, [14, [1, 2, 3, 4, 8, 5, 7, 10, 9, 6, 11, 12, 13, 15, None, 14]])
(1329, 400, 10, [13, [1, 2, 3, 4, 6, 8, 7, 10, 9, 5, 11, 12, 13, None, 15, 14]])
(1602, 431, 9, [4, [1, 2, 3, 4, None, 6, 8, 7, 9, 5, 11, 10, 13, 15, 14, 12]])
(1707, 446, 8, [5, [1, 2, 3, 4, 6, None, 7, 8, 9, 5, 15, 12, 13, 10, 14, 11]])
(1711, 475, 7, [12, [1, 2, 3, 4, 6, 5, 7, 8, 9, 10, 15, 12, None, 13, 14, 11]])
(1747, 502, 6, [8, [1, 2, 3, 4, 6, 5, 7, 8, None, 9, 10, 12, 13, 14, 15, 11]])
(1824, 519, 5, [14, [1, 2, 3, 4, 9, 6, 7, 8, 5, 10, 15, 12, 13, 14, None, 11]])
(1871, 540, 4, [10, [1, 2, 3, 4, 9, 6, 7, 8, 5, 10, None, 12, 13, 14, 15, 11]])
(28203, 555, 3, [9, [1, 2, 3, 4, 5, 6, 7, 8, 9, None, 10, 12, 13, 14, 11, 15]])
(28399, 560, 2, [10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, None, 12, 13, 14, 11, 15]])
(28425, 581, 1, [11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, None, 13, 14, 15, 12]])
(28483, 582, 0, [15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, None]])
The last line means that after 24,483 experiments it found the target position after 582 moves. Note that 582 is for sure very far from optimal as it's known that no position in the classic version of the 15 puzzle requires more than 80 moves.
The number after the number of moves is the "manhattan distance", for example the fourth-last row is the position:
where the sum of manhattan distances from the solution is 3.

Multi Dimensional Numpy Array Sorting

I have (5,5) np.array like below.
>>> a
array([[23, 15, 11, 0, 17],
[ 1, 2, 20, 4, 6],
[16, 22, 8, 10, 18],
[ 7, 12, 13, 14, 5],
[ 3, 9, 21, 19, 24]])
I want to multi dimensional sort the np.array to look like below.
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
To do that I did,
flatten() the array.
Sort the flatted array.
Reshape to (5,5)
In my method I feel like it is a bad programming practice.Are there any sophisticated way to do that task?
Thank you.
>>> a array([[23, 15, 11, 0, 17],
[ 1, 2, 20, 4, 6],
[16, 22, 8, 10, 18],
[ 7, 12, 13, 14, 5],
[ 3, 9, 21, 19, 24]])
>>> a_flat = a.flatten()
>>> a_flat
array([23, 15, 11, 0, 17, 1, 2, 20, 4, 6, 16, 22, 8, 10, 18, 7, 12,
13, 14, 5, 3, 9, 21, 19, 24])
>>> a_sort = np.sort(a_flat)
>>> a_sorted = a_sort.reshape(5,5)
>>> a_sorted
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
We could get a flattened view with np.ravel() and then sort in-place with ndarray.sort() -
a.ravel().sort()
Being everything in-place, it avoids creating any temporary array and also maintains the shape, which avoids any need of reshape.
Sample run -
In [18]: a
Out[18]:
array([[23, 15, 11, 0, 17],
[ 1, 2, 20, 4, 6],
[16, 22, 8, 10, 18],
[ 7, 12, 13, 14, 5],
[ 3, 9, 21, 19, 24]])
In [19]: a.ravel().sort()
In [20]: a
Out[20]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])

Categories

Resources