1

I'm trying to split a Integer into an "as symmetric array as possible" in python3 but just doesn't seem to get it right.

The desired input/output can be described by this Data Pattern Table.

# data pattern TABLE
# INPUT (int) => OUTPUT (len(array), array )
# 1 => 1 1
# 2 => 1 2
# 3 => 2 2,1
# 4 => 2 2,2
# 5 => 2 3,2
# 6 => 2 3,3
# 7 => 3 3,2,2
# 8 => 3 3,3,2
# 9 => 3 3,3,3
# 10 => 3 4,3,3
# 11 => 3 4,4,3
# 12 => 3 4,4,4
# 13 => 4 4,3,3,3
# 14 => 4 4,4,3,3
# 15 => 4 4,4,4,3
# 16 => 4 4,4,4,4
# 17 => 4 5,4,4,4
# 18 => 4 5,5,4,4
# 19 => 4 5,5,5,4
# 20 => 4 5,5,5,5

So far I got this code from looking around some on stackoverflow.

def splitnum(a, n):
    num, div = a, n
    return (num // div + (1 if x < num % div else 0)  for x in range (div))

x =20
print(list(splitnum(x, int(x/2))))

However it results in a two-splitted array. I'm really just trying to understand the pattern properly and if someone know some neat trick to solve this it would be very helpful!

Any help is appreciated!

Cheers!

Grebtsew
  • 192
  • 5
  • 13
  • 4
    How do you decide the length of the pattern? That seems to be the difficulty here - the same idiom you've displayed can be used to make a list, but currently you're making a 10-length list from the integer `20`, which of course is going to be 10 `2`s. How do you derive `4` from 13 through 20, `3` from 7 through 12, etc.? – Green Cloak Guy Feb 24 '20 at 16:43
  • 3
    Not clear to me how each of the patterns in your example demonstrate a "symmetric array" and what other unstated constraints you are working with. If "2" is the input, why output an array of `[2]` instead of `[1, 1]`? If "7" is the input, why output an array of `[3, 2, 2]` instead of `[3, 4]`? If "20" is the input, why output an array of `[5, 5, 5, 5]` instead of `[10, 10]`? It may help to read a bit about [integer partitions](https://en.wikipedia.org/wiki/Partition_(number_theory)). – benvc Feb 24 '20 at 16:57
  • @GreenCloakGuy the priority is to have a lesser amount of rows than columns. The difference between abs(len(row) ,len(column)) <= 1. My thought was to build trees and use highest divideable with modulus perhaps. Or I think this pattern can be recreated by counting up from 1 to the target while filling the array. – Grebtsew Feb 24 '20 at 17:12
  • @benvc the [5, 5, 5, 5] array would represent [[x,x,x,x,x][x,x,x,x,x][x,x,x,x,x][x,x,x,x,x]] and the alternative [4,4,4,4,4] wouldn't prioritise the number of rows. – Grebtsew Feb 24 '20 at 17:17
  • @Grebtsew what do you mean by `abs(len(row) ,len(column)) <= 1`? `abs` takes one argument. You're giving 2 here. It's still pretty unclear what exactly your rules are. – Axe319 Feb 24 '20 at 19:24
  • @Axe319 What I mean is that the resulting array, for instance [2,2] represents an [[x,x],[x,x]] matrix. When a matrix is uneven like for instance 7 = [3,2,2] != [3,4] the rules are that it is okey with a lower amount of rows than columns but it is not allowed to be a bigger difference than 1. So abs(rows-columns) <= 1. And yes i might have mixed column and row. Hope thats a little clearer. – Grebtsew Feb 24 '20 at 20:34
  • If anyone is intrested, I use this to split the monitor between X windows. – Grebtsew Feb 24 '20 at 20:38

2 Answers2

1

I think this is a neat proposal:

import math
def squarit(n: int):
  size = int(math.floor(math.sqrt(n)))
  ans = [n//size]*size
  for i in range(n-n//size*size):
    ans[i] += 1
  return size, ans

for i in range(4, 25):
  print(f'{i}: {squarit(i)}')

Result:

4: (2, [2, 2])
5: (2, [3, 2])
6: (2, [3, 3])
7: (2, [4, 3])
8: (2, [4, 4])
9: (3, [3, 3, 3])
10: (3, [4, 3, 3])
11: (3, [4, 4, 3])
12: (3, [4, 4, 4])
13: (3, [5, 4, 4])
14: (3, [5, 5, 4])
15: (3, [5, 5, 5])
16: (4, [4, 4, 4, 4])
17: (4, [5, 4, 4, 4])
18: (4, [5, 5, 4, 4])
19: (4, [5, 5, 5, 4])
20: (4, [5, 5, 5, 5])
21: (4, [6, 5, 5, 5])
22: (4, [6, 6, 5, 5])
23: (4, [6, 6, 6, 5])
24: (4, [6, 6, 6, 6])
Cedric Druck
  • 1,032
  • 7
  • 20
0

I solved the issue. Not a brilliant solution but works. Code:

def get_dim_arr(x):
    """ 
    Get even divided array of integer X 
    @Param X integer
    @Return [len(arr), arr], where arr contains number of columns per row
    """
    curr = 1
    res_arr = [1]
    while curr < x:
        val, idx = min((val, idx) for (idx, val) in enumerate(res_arr))
        print(res_arr)

        if(val > len(res_arr)): # if abs(row, col) >= 1
            # split
            temp = []
            for i in range(0,len(res_arr)):
                if i == 0:
                    temp.append(res_arr[i])
                else:
                    temp.append(res_arr[i]-1)
            temp.append(res_arr[i]-1)
            res_arr = temp
        else:
            val+=1
            res_arr[idx] = val
        curr+=1

    return [len(res_arr), res_arr]

x = 20
print(get_dim_arr(x))

Result:

[1]
[2]
[2, 1]
[2, 2]
[3, 2]
[3, 3]
[3, 2, 2]
[3, 3, 2]
[3, 3, 3]
[4, 3, 3]
[4, 4, 3]
[4, 4, 4]
[4, 3, 3, 3]
[4, 4, 3, 3]
[4, 4, 4, 3]
[4, 4, 4, 4]
[5, 4, 4, 4]
[5, 5, 4, 4]
[5, 5, 5, 4]
[4, [5, 5, 5, 5]]
Grebtsew
  • 192
  • 5
  • 13