0

So I'm trying to find how to group similar numbers into different lists. I tried looking at some sources like (Grouping / clustering numbers in Python) but all of them requires the importation of itertools and use itertools.groupby, which I dont want because I dont want to use built in functions.

Here is my code so far.

def n_length_combo(lst, n):
    if n == 0:
        return [[]]

    l = []
    for i in range(0, len(lst)):

        m = lst[i]
        remLst = lst[i + 1:]

        for p in n_length_combo(remLst, n - 1):
            l.append([m] + p)

    return l

print(n_length_combo(lst=[1,1,76,45,45,4,5,99,105],n=3))

Edit: n: int represents the number of groups permitted from one single list, so if n is 3, the numbers will be grouped in (x,...), (x,....) (x,...) If n = 2, the numbers will be grouped in (x,..),(x,...)

However, my code prints out all possible combinations in a list of n elements. But it doesnt group the numbers together. So what I want is: for instance if the input is

[10,12,45,47,91,98,99]

and if n = 2, the output would be

[10,12,45,47] [91,98,99]

and if n = 3, the output would be

[10,12] [45,47] [91,98,99]

What changes to my code should I make?

Bruffff
  • 53
  • 7
  • 1
    What is the logic behind it? That is, what does `n` mean here? How is `n` related to your output? – j1-lee Nov 08 '21 at 03:15
  • To expand on @j1-lee's question, why is that when `n == 2`, you want two lists/groups, but when `n == 4` you want three lists/groups? – joseville Nov 08 '21 at 03:19
  • 1
    @j1-lee I have added what I want n to be – Bruffff Nov 08 '21 at 03:20
  • 1
    @joseville oh! apologies on my part, I wrote 4 by mistake. I have edited my question – Bruffff Nov 08 '21 at 03:21
  • "N represents the number of numbers in one single grouping" contradicts your examples where when `n == 2` one group has 4 numbers and the other group has 3 numbers. Same for `n == 3`, two of the groups have 2 numbers. Only one of the groups has 3 numbes. – joseville Nov 08 '21 at 03:23
  • 1
    Edited my question already, Sorry for the confusion and thank u for helping and pointing out my mistake :) – Bruffff Nov 08 '21 at 03:30
  • 1
    why dont you look at the source code for the itertools groupby function for inspiration? – Kinjal Dixit Nov 08 '21 at 03:32

2 Answers2

1

Assuming n is the number of groups/partitions you want:

import math

def partition(nums, n):
    partitions = [[] for _ in range(n)]
    min_, max_ = min(nums), max(nums)
    r = max_ - min_ # range of the numbers
    s = math.ceil(r / n) # size of each bucket/partition
    for num in nums:
        p = (num - min_) // s
        partitions[p].append(num)
    return partitions

nums = [10,12,45,47,91,98,99]

print(partition(nums, 2))
print(partition(nums, 3))

prints:

[[10, 12, 45, 47], [91, 98, 99]]
[[10, 12], [45, 47], [91, 98, 99]]
joseville
  • 685
  • 3
  • 16
  • 1
    Thank you for ur response! Btw, Is it possible to not use import?, like I wanna try to refrain from using built-in functions – Bruffff Nov 08 '21 at 03:33
  • Yes, it's possible. `math.ceil` can be implemented. What is the reason for avoiding `import`s? Btw, this code is flaky; it might fail due to `IndexError: list index out of range` on some inputs, e.g. if you include `100` in the `nums`, but the general idea/approach is there. – joseville Nov 08 '21 at 03:36
  • An easier way, though not as efficient, is to `sort` the input, then just partition it using slices. e.g. if `n == 2`, then do `nums.sort()` to sort `nums` in-place. Now, assuming `m` is the length of `nums`, the result would be `[nums[:m//2], nums[m//2:]]`. – joseville Nov 08 '21 at 03:58
0

You are trying to convert a 1d array into a 2d array. Forgive the badly named variables but the general idea is as follows. It is fairly easy to parse, but basically what we are doing is first finding out the size in rows of the 2d matrix given the length of the 1d matrix and desired number of cols. If this does not divide cleanly, we add one to rows. then we create one loop for counting the cols and inside that we create another loop for counting the rows. we map the current position (r,c) of the 2d array to an index into the 1d array. if there is an array index out of bounds, we put 0 (or None or -1 or just do nothing at all), otherwise we copy the value from the 1d array to the 2d array. Well, actually we create a 1d array inside the cols loop which we append to the lst2 array when the loop is finished.

def transform2d(lst, cols):
    size = len(lst)
    
    rows = int(size/cols)
    if cols * rows < size:
        rows+=1

    lst2 = []
    for c in range(cols):
        a2 = []
        for r in range(rows):
            i = c*cols + r
            if i < size:
                a2.append(lst[i])
            else:
                a2.append(0)  # default value
        lst2.append(a2)
    return lst2

i = [10,12,45,47,91,98,99]
r = transform2d(i, 2)
print(r)
r = transform2d(i, 3)
print(r)

the output is as you have specified except for printing 0 for the extra elements in the 2d array. this can be changed by just removing the else that does this.

Kinjal Dixit
  • 7,777
  • 2
  • 59
  • 68