2

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!

2
  • assertEqual is not going to compare your print result, it uses the value returned by string_to_matrix. string_to_matrix currently returns nothing so the value is None. Change print for return and you will start getting better resutls Commented Feb 15, 2019 at 2:00
  • Firstly, the function you created only print out the answer, rather than returning it, thus the assertion will always fail as None is what functions return by default. Replace print (answer) with simply return answer. Secondly, it doesn't seem like you taken into account of "The string will contain a perfect square number of integers". Commented Feb 15, 2019 at 2:01

6 Answers 6

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot! Your explanation of "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." is very helpful for me to understand why it could be written like this.
This use of zip is shown in the grouper recipe at docs.python.org/3/library/itertools.html#itertools-recipes. Unfortunately it doesn't explain how it works. It takes advantage of a couple of Python features that often trip up users.
1

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)

Comments

1

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]])

2 Comments

You don't need the int map or comprehension. Just ask np.array to produce an integer array: np.array(s.split(), dtype=int)
Ah neat! Thanks for the tip!
0

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.

Comments

0
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

Comments

-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"

1 Comment

Answers should consist of more than a mere code-dump. If you think the question is poorly asked, you can flag it or post a comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.