选择适当的算法来分配值的问题

时间:2018-10-09 05:21:53

标签: php algorithm

我需要选择正确的算法来计算匹配的帮助。我有一个模块,可在其中将票证与发票匹配。可以将多张票证与多张发票匹配。

对于几个这样的基本演示,输入数据可能有所不同,对于所有这些基本演示,它们都应该以相同的方式进行匹配。这是我应该获得的一些输入数据和结果的示例:

左侧大于右侧:

$tickets = [
    [
        'issue_id' => 'ZAKUPY-1070',
        'amount' => '150'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'amount' => '100'
    ]
];

$invoices = [
    [
        'document_id' => '12998638134790357761.1',
        'amount' => '100'
    ],
    [
        'document_id' => '12998638134790357761.2',
        'amount' => '100'
    ]
];

$result = [
    [
        'issue_id' => 'ZAKUPY-1070',
        'document_id' => '12998638134790357761.1',
        'issue_amount' => '100.0000',
        'document_amount' => '100.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'document_id' => '12998638134790357761.1',
        'issue_amount' => '0.0000',
        'document_amount' => '0.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1070',
        'document_id' => '12998638134790357761.2',
        'issue_amount' => '50.0000',
        'document_amount' => '50.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'document_id' => '12998638134790357761.2',
        'issue_amount' => '50.0000',
        'document_amount' => '50.0000'
    ]
];

右侧大于左侧:

$tickets = [
    [
        'issue_id' => 'ZAKUPY-1070',
        'amount' => '100'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'amount' => '100'
    ]
];

$invoices = [
    [
        'document_id' => '12998638134790357761.1',
        'amount' => '150'
    ],
    [
        'document_id' => '12998638134790357761.2',
        'amount' => '100'
    ]
];

$result = [
    [
        'issue_id' => 'ZAKUPY-1070',
        'document_id' => '12998638134790357761.1',
        'issue_amount' => '100.0000',
        'document_amount' => '100.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'document_id' => '12998638134790357761.1',
        'issue_amount' => '50.0000',
        'document_amount' => '50.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1070',
        'document_id' => '12998638134790357761.2',
        'issue_amount' => '0.0000',
        'document_amount' => '0.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'document_id' => '12998638134790357761.2',
        'issue_amount' => '50.0000',
        'document_amount' => '50.0000'
    ]
];

双方相等:

$tickets = [
    [
        'issue_id' => 'ZAKUPY-1070',
        'amount' => '120'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'amount' => '80'
    ]
];

$invoices = [
    [
        'document_id' => '12998638134790357761.1',
        'amount' => '80'
    ],
    [
        'document_id' => '12998638134790357761.2',
        'amount' => '120'
    ]
];

$result = [
    [
        'issue_id' => 'ZAKUPY-1070',
        'document_id' => '12998638134790357761.1',
        'issue_amount' => '80.0000',
        'document_amount' => '80.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'document_id' => '12998638134790357761.1',
        'issue_amount' => '0.0000',
        'document_amount' => '0.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1070',
        'document_id' => '12998638134790357761.2',
        'issue_amount' => '40.0000',
        'document_amount' => '40.0000'
    ],
    [
        'issue_id' => 'ZAKUPY-1043',
        'document_id' => '12998638134790357761.2',
        'issue_amount' => '80.0000',
        'document_amount' => '80.0000'
    ]
];

我尝试过这种方式:

$ticketsSummary = 0;

foreach ($tickets as $ticket) {
    $baseTickets[$ticket['issue_id']] = $ticket;
    $ticketsSummary += $ticket['amount'];
}

$invoicesSummary = 0;

foreach ($invoices as $invoice) {
    $baseInvoices[$invoice['document_id']] = $invoice;
    $invoicesSummary += $invoice['amount'];
}

foreach ($invoices as $invoice) {
    foreach ($tickets as $ticket) {
        if (!isset($invoiceAmountCounter[$invoice['document_id']])) {
            $invoiceAmountCounter[$invoice['document_id']] = 0;
        }

        $invoiceAmountCounter[$invoice['document_id']] =
            $invoiceAmountCounter[$invoice['document_id']] + $ticket['amount'];

        if ($invoiceAmountCounter[$invoice['document_id']] >= $baseInvoices[$invoice['document_id']]['amount']) {
            $ticket['amount'] = $ticket['amount'] - ($invoiceAmountCounter[$invoice['document_id']] -
                    $baseInvoices[$invoice['document_id']]['amount']);
            $ticket['amount'] = $ticket['amount'] < 0 ? 0 : $ticket['amount'];
        }

        $result[] = [
            'issue_id' => $ticket['issue_id'],
            'document_id' => $invoice['document_id'],
            'document_amount' => $ticket['amount'],
            'issue_amount' => $ticket['amount'],
        ];
    }
}

但不幸的是,结果有所不同:(在这件事上,我热烈地请求您的帮助。

1 个答案:

答案 0 :(得分:1)

经过长时间的尝试,我得到了想要的帮助:

$right = $invoices;
$rightColIndex = 0;
$results = [];

foreach ($tickets as $leftPos) {

    $ticketSum = 0;

    while (isset($right[$rightColIndex]) && $leftPos['amount'] > $ticketSum) {

        $rightPos = $right[$rightColIndex];

        $ticketSum += $rightPos['amount'];

        $results[] = [
            'document_id' => $rightPos['document_id'],
            'issue_id' => $leftPos['issue_id'],
            'issue_amount' => $rightPos['amount'],
            'document_amount' => $rightPos['amount'],
        ];

        $rightColIndex++;
    }

    if ($ticketSum > $leftPos['amount']) {


        $rightColIndex--;

        $diffAmount = $ticketSum - $leftPos['amount'];


        $results[count($results) - 1]['document_amount'] = $right[$rightColIndex]['amount'] - $diffAmount;
        $results[count($results) - 1]['issue_amount'] = $right[$rightColIndex]['amount'] - $diffAmount;

        $right[$rightColIndex]['amount'] = $diffAmount;

    }
}