Larry Chen
Larry Chen

Reputation: 83

String to n*n matrix in python

I am an undergraduate student who loves programming. I encountered a problem today and I don't know how to solve this problem. I looked for "Python - string to matrix representation" (Python - string to matrix representation) for help, but I am still confused about this problem.

The problem is in the following:

Given a string of whitespace separated numbers, create an nxn matrix (a 2d list where with the same number of columns as rows)and return it. The string will contain a perfect square number of integers. The int() and split() functions may be useful.

Example:

Input: '1 2 3 4 5 6 7 8 9'

Output: [[1,2,3],[4,5,6],[7,8,9]]

Example 2:

Input: '1'

Output: [[1]]

My answer:

import numpy as np
def string_to_matrix(str_in):
    str_in_split = str_in.split()
    answer = []
    for element in str_in_split:
        newarray = []
    for number in element.split():
        newarray.append(int(number))
    answer.append(newarray)
    print (answer)

The test results are in the following:

Traceback (most recent call last):
  File "/grade/run/test.py", line 20, in test_whitespace
    self.assertEqual(string_to_matrix('1      2 3   4'), [[1,2],[3,4]])
AssertionError: None != [[1, 2], [3, 4]]

Stdout:
[[4]]

as well as

Traceback (most recent call last):
  File "/grade/run/test.py", line 15, in test_small
    self.assertEqual(string_to_matrix('1 2 3 4'), [[1,2],[3,4]])
AssertionError: None != [[1, 2], [3, 4]]

Stdout:
[[4]]

as well as

Traceback (most recent call last):
  File "/grade/run/test.py", line 10, in test_one
    self.assertEqual(string_to_matrix('1'), [[1]])
AssertionError: None != [[1]]

Stdout:
[[1]]

as well as

Traceback (most recent call last):
  File "/grade/run/test.py", line 25, in test_larger
    self.assertEqual(string_to_matrix('4 3 2 1 8 7 6 5 12 11 10 9 16 15 14 13'), [[4,3,2,1], [8,7,6,5], [12,11,10,9], [16,15,14,13]])
AssertionError: None != [[4, 3, 2, 1], [8, 7, 6, 5], [12, 11, 10, 9], [16, 15, 14, 13]]

Stdout:
[[13]]

I am still confused how to solve this problem. Thank you very much for your help!

Upvotes: 2

Views: 5236

Answers (6)

Nikolas Stevenson-Molnar
Nikolas Stevenson-Molnar

Reputation: 4700

Use split, create the 1D numpy array, then use reshape:

>>> s = '1 2 3 4 5 6 7 8 9'
>>> np.array([s.split(), dtype=int).reshape(3,3)
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

If you don't know the size of the array, but you know it's square (same width / height), then you can use math.sqrt to get the inputs for reshape:

>>> import math
>>> s = '1 2 3 4 5 6 7 8 9'
>>> arr = np.array(s.split(), dtype=int)
>>> size = int(math.sqrt(len(arr)))
>>> arr.reshape(size, size)
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

Upvotes: 1

user11065131
user11065131

Reputation: 1

import math
string = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16"
stringItems = string.split(" ")
numberOfItems = len(stringItems)
if math.sqrt(numberOfItems) - int(math.sqrt(numberOfItems)) == 0:
    width = int(math.sqrt(numberOfItems))
    array = []
    finalArray = []
    for i in range (0, width):
        for j in range (0, width):
            array.insert(j, stringItems[0])
            stringItems.pop(0)
        finalArray.insert(i, array)
        array = []
    print finalArray
else:
    print "I require a string with length equal to a square number please"

Upvotes: -1

Andres
Andres

Reputation: 4501

import numpy as np
def string_to_matrix(str_in):
   str_in_split = str_in.split()
   numbers = list(map(int, str_in_split))
   size = r_shape = int(np.sqrt(len(numbers)))
   return np.array(numbers).reshape(r_shape, r_shape)

This is why you always got: AssertionError: None != ...

assertEqual(A, string_to_matrix("...")) verifies if A is equals to the value returned by string_to_matrix. In your code you don't return anything so it is None

The other issue is how you splitted the string, the easier options is to split everything and convert to number, and then reshape to sqrt(number of elements). This assumes that input length can be splited to form a nxn matrix

Upvotes: 0

iz_
iz_

Reputation: 16593

Assuming you don't want numpy and want to use a list of lists:

def string_to_matrix(str_in):
    nums = str_in.split()
    n = int(len(nums) ** 0.5)
    return list(map(list, zip(*[map(int, nums)] * n)))

nums = str_in.split() splits by any whitespace, n is the side length of the result, map(int, nums) converts the numbers to integers (from strings), zip(*[map(int, nums)] * n) groups the numbers in groups of n, list(map(list, zip(*[map(int, nums)] * n))) converts the tuples produced by zip into lists.

Upvotes: 2

user2263572
user2263572

Reputation: 5606

Assuming you want to make this dynamic.

str_in = '1 2 3 4 5 6 7 8 9'
a = str_in.split(" ")
r_shape = int(math.sqrt(len(a)))
np.array([int(x) for x in a]).reshape(r_shape, r_shape)

Upvotes: 1

Chris
Chris

Reputation: 29742

Given that you will always get perfect square number of ints:

import numpy as np

input_strings = '1 2 3 4 5 6 7 8 9'
arr = np.array(input_strings.split(), dtype=int)
n = int(len(arr) ** 0.5)
arr.reshape(n, n)
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

Note: in your case, str.split is better off without explicit sep in order to work fine with multiple whitespaces in between the digits.

Upvotes: 0

Related Questions