Completed
Pull Request — master (#2)
by Pol
04:12
created

GreedyAlt::fillPartitions()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 29
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 16
nc 6
nop 3
dl 0
loc 29
rs 9.4222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace drupol\phpartition;
6
7
use drupol\phpartition\Partition\Partition;
8
use drupol\phpartition\Partitions\Partitions;
9
10
/**
11
 * Class GreedyAlt.
12
 */
13
class GreedyAlt extends Partitioner
14
{
15
    /**
16
     * {@inheritdoc}
17
     */
18
    protected function fillPartitions(Partitions $partitions, Partition $dataset, int $chunks): void
19
    {
20
        // Greedy needs a dataset sorted DESC.
21
        $dataset->uasort(
22
            static function ($left, $right) {
23
                return $right->getWeight() <=> $left->getWeight();
24
            }
25
        );
26
27
        $partitionsArray = [];
28
29
        for ($p = $chunks; 1 < $p; --$p) {
30
            $partition = new Partition();
31
            $best = $dataset->getWeight() / $chunks;
32
33
            while ($partition->getWeight() < $best && 0 !== $dataset->count()) {
34
                $key = $this->findOptimalItemKey($partition, $dataset, $best);
35
                $partition->append($dataset[$key]);
36
                unset($dataset[$key]);
37
                $dataset->exchangeArray(\array_values($dataset->getArrayCopy()));
38
            }
39
40
            $partitionsArray[] = $partition;
41
        }
42
43
        $partitionsArray[] = $dataset;
44
45
        foreach ($partitionsArray as $key => $subset) {
46
            $partitions->partition($key)->exchangeArray($subset);
47
        }
48
    }
49
50
    /**
51
     * @param \drupol\phpartition\Partition\Partition $partition
52
     * @param \drupol\phpartition\Partition\Partition $dataset
53
     * @param float $best
54
     *
55
     * @return null|false|int|string
56
     */
57
    private function findOptimalItemKey(Partition $partition, Partition $dataset, $best)
58
    {
59
        if (0 === $partition->count()) {
60
            return \key($dataset);
0 ignored issues
show
Bug introduced by
$dataset of type drupol\phpartition\Partition\Partition is incompatible with the type array expected by parameter $array of key(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

60
            return \key(/** @scrutinizer ignore-type */ $dataset);
Loading history...
61
        }
62
63
        $solutions = [];
64
        $partitionWeightMinusBest = $partition->getWeight() - $best;
65
66
        foreach ($dataset as $key => $item) {
67
            $solutions[$key] = \abs($partitionWeightMinusBest + $item->getWeight());
68
        }
69
70
        \asort($solutions);
71
72
        return \key($solutions);
73
    }
74
}
75