uniform distribution of a set of characters

后端 未结 2 826
眼角桃花
眼角桃花 2021-01-29 13:22

There is a set of characters that needs to be uniformly distributed in an array. For example,

a - 1

b - 2

c - 3

d - 4

In this case there

相关标签:
2条回答
  • 2021-01-29 13:56

    You could use something similar to the bresenham algorithm to track the error between the ideal spacing and the last spacing for each component:

    vals = ['a','b','c','d']
    cts  = [1,2,3,4]
    
    sz = sum(cts)
    spacing = [float(sz)/(ct+1) for ct in cts]
    err = [s for s in spacing]
    a=[]
    for i in range(sz):
        err = [e-1 for e in err]
        m = min(err)
        i = err.index(m)
        a.append(vals[i])
        err[i]+=spacing[i]
    print a
    

    yeilds: ['d', 'c', 'b', 'd', 'a', 'c', 'd', 'b', 'c', 'd']

    0 讨论(0)
  • 2021-01-29 14:01

    First, try to guess where each letter instance would be, only considering one letter at a time. If there's 10 total, and 3as, try to place the As at index 0, 3, and 7. Calculate these estimated indecies for each letter, and put them in a ordered multiset.

    std::multimap<unsigned,char> set;
    const unsigned totalcount = ... //for your example this would be 10
    for (const auto& letterpair : letters) {
        unsigned lettercount = letterpair.second; //for c this would be 3
        for(unsigned i=0; i<lettercount; ++i) {
            unsigned targetIdx = (2*i*totalcount+1)/lettercount;
            set.insert(std::make_pair(targetIdx, letterpair.first));
        }
    }
    

    Then we can simply iterate over the set in order and place each thing in a single index.

    std::vector<char> result;
    for(const auto& p : set)
        result.push_back(p.second); //insert the letters in order
    

    It's not perfect, but it works pretty darn well considering the speed and simplicity.

    For your inputs, it results in bcdadcbdcd: http://coliru.stacked-crooked.com/a/1f83ae4518b7c6ca

    0 讨论(0)
提交回复
热议问题