Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在一次传递中将帐户(用整数表示)平衡到接近0的最佳方法_Php_Algorithm_Sorting_Logic - Fatal编程技术网

Php 在一次传递中将帐户(用整数表示)平衡到接近0的最佳方法

Php 在一次传递中将帐户(用整数表示)平衡到接近0的最佳方法,php,algorithm,sorting,logic,Php,Algorithm,Sorting,Logic,我有一系列的银行账户,每个月都有最低的付款要求,我正试图找出逻辑,以获得最佳的付款计划。以下是阵列结构: array(4) { ["account_one"]=> array(9) { ["account"]=> string(21) "Account One" ["balance"]=> int(2500) ["minimum_payment"]=> int(1000) } ["account_two"]=

我有一系列的银行账户,每个月都有最低的付款要求,我正试图找出逻辑,以获得最佳的付款计划。以下是阵列结构:

array(4) {
  ["account_one"]=>
  array(9) {
    ["account"]=>
    string(21) "Account One"
    ["balance"]=>
    int(2500)
    ["minimum_payment"]=>
    int(1000)
  }
  ["account_two"]=>
  array(9) {
    ["account"]=>
    string(16) "Account Two"
    ["balance"]=>
    int(1500)
    ["minimum_payment"]=>
    int(500)
  }
  ["account_three"]=>
  array(9) {
    ["account"]=>
    string(10) "Account Three"
    ["balance"]=>
    int(3000)
    ["minimum_payment"]=>
    int(750)
  }
  ["account_four"]=>
  array(9) {
    ["account"]=>
    string(14) "Account Four"
    ["balance"]=>
    int(3000)
    ["minimum_payment"]=>
    int(750)
  }
}
在本例中,帐户中的总金额为10000,需要在每个帐户之间移动,以满足最低付款要求。付款计划还需要尽可能高效,以最少的付款次数满足要求。这是一个简单的例子,但在生产中,我们可能有15个或更多的帐户,最低付款金额不同

到目前为止,我所得到的并不多,因为我正在努力掌握我需要的总体逻辑:

$accounts_by_amount (array of accounts sorted by balance high to low)
$accounts_reversed ($accounts_by_amount in reverse order)
$schedule = array()
foreach $accounts_by_amount as $account_a
    foreach $accounts_reversed as $account_b
        if $account_a['minimum_payment'] > $account_b['mininum_payment']
            // use higher minimum payment to reduce total payments needed
            $schedule_b[] = array(
              'from' => $account_a['account'],
              'to' => $account_b['account'],
              'amount' => $account_a['minimum_payment'],
            );
        else
            continue;

    if $schedule_b
        $schedule += $schedule_b
    else
        continue

显然,这不起作用,但我认为我可能使循环中的循环变得过于复杂。我不是在寻找一个真正为我编写代码的人,更多的是告诉我,我对这个逻辑有多么愚蠢,以及如何将这个计划与最低付款数量结合起来的粗略想法。

排除计划逻辑,我写了这样的东西来转移和平衡账户之间的金额。希望这有帮助。这是JavaScript/我将让您使用PHP来尝试

基本上,我们计算可用余额,从高到低对可用余额进行排序,并在平衡账户的同时从开始到结束进行迭代。这也不是您可以进行的最小转账次数,但如果您在每次迭代后重新计算最佳可用帐户,您就可以得到该数目

在最坏的情况下,它将在O(n)处执行,在真正最坏的情况下,您的最佳帐户中没有足够的资金,这将使它跳过while循环。但这意味着你会有真正的问题,而不是大O符号

let accounts = [
    { id: 2, balance: 6000, minpay: 4000 },
    { id: 1, balance: 5000, minpay: 2000 },
    { id: 3, balance: 4000, minpay: 4000 },
    { id: 4, balance: 4000, minpay: 5000 },
    { id: 6, balance: 3000, minpay: 6000 },
    { id: 5, balance: 3000, minpay: 5000 }
];

// create a map of workable balances.
let workableBalance = accounts.map(v => {
    return {
        id: v.id,
        value: v.balance - v.minpay
    }
}).sort((a,b) => {return b.value-a.value}); // sort descending;

let cursorFromBeginning = 0;
let cursorFromEnd = workableBalance.length - 1;

if (workableBalance[cursorFromEnd].value > 0) {
    console.log('All accounts have sufficient money in them.');
    return; // terminate.
}

if (workableBalance[cursorFromBeginning].value < 0) {
    console.log(`No way that we'll balance the accounts. The best account is in negatives.`);
    return; // terminate.
}

console.log('Present state of things: ', workableBalance);

while(cursorFromBeginning < cursorFromEnd) {
    // Get the balance from least available account.
    // Validate that the worst account actually needs money.
    let worstAccount = workableBalance[cursorFromEnd];
    if (worstAccount.value >= 0) {
        console.log(`All good! We're balanced`, workableBalance);
        return;
    }

    let bestAccount = workableBalance[cursorFromBeginning];
    if (bestAccount.value == 0) {
        cursorFromBeginning++;
        continue;
    }

    // Can this account single-handedly balance the next worst account?
    if (bestAccount.value >= Math.abs(worstAccount.value)) {
        // Balance the account.
        console.log(`Moving $${bestAccount.value} from account ${bestAccount.id} to ${worstAccount.id} - balancing the whole account.`);
        bestAccount.value += worstAccount.value;
        worstAccount.value = 0;
        cursorFromEnd--;
    }
    else {
        // Balance as much as we can.
        console.log(`Moving $${bestAccount.value} from account ${bestAccount.id} to ${worstAccount.id} - balancing the account partially.`);
        bestAccount.value = 0;
        worstAccount.value += bestAccount.value;
        cursorFromBeginning++;
    }
}


console.log('Things after some magic: ', workableBalance);
let账户=[
{id:2,余额:6000,minpay:4000},
{id:1,余额:5000,minpay:2000},
{id:3,余额:4000,minpay:4000},
{id:4,余额:4000,minpay:5000},
{id:6,余额:3000,minpay:6000},
{id:5,余额:3000,minpay:5000}
];
//创建一张可行平衡图。
让workableBalance=accounts.map(v=>{
返回{
id:v.id,
价值:v.balance-v.minpay
}
}).sort((a,b)=>{return b.value-a.value});//降序排序;
让CursorFromStart=0;
让cursorFromEnd=可工作平衡。长度-1;
if(可工作平衡[cursorFromEnd]。值>0){
console.log('所有帐户都有足够的钱');
return;//终止。
}
if(可工作平衡[CursorFromStart]。值<0){
log(`我们不可能平衡帐户。最好的帐户是负数。`);
return;//终止。
}
console.log('事物的当前状态:',可用平衡);
while(CursorFromStart=0){
log(`All good!We's balanced`,workableBalance);
回来
}
让bestAccount=可操作余额[游标从开始];
如果(bestAccount.value==0){
游标fromStart++;
持续
}
//这个账户能单独平衡下一个最差的账户吗?
if(bestAccount.value>=Math.abs(worstAccount.value)){
//结清帐目。
log(`Moving${bestAccount.value}从帐户${bestAccount.id}移动到${worstAccount.id}-平衡整个帐户。`);
bestAccount.value+=worstAccount.value;
worstAccount.value=0;
cursorFromEnd--;
}
否则{
//尽量保持平衡。
log(`Moving${bestAccount.value}从帐户${bestAccount.id}移动到${worstAccount.id}-部分平衡帐户。`);
bestAccount.value=0;
worstAccount.value+=bestAccount.value;
游标fromStart++;
}
}
log('Things after some magic:',workableBalance);

我多次阅读了您的问题,但仍然不清楚您想了解/完成什么。您示例中的所有帐户余额都足以支付每个帐户的最低付款。Dave,这可能是一个不好的示例,因为有时在资金从另一个帐户转入该帐户之前,余额中不会有足够的款项支付。账户之间总共有10万美元,我需要一个付款计划,在每个账户之间移动资金以达到最低付款。我会试着改写原来的问题。我也很困惑。你提到了一个不同付款的时间表,但我没有看到描述这些付款和变化的条款,也没有处理基于时间的流程。此外,如果没有基于时间的输入,则时间因素无关紧要:您需要涵盖每个帐户的所有付款总额。请为输入和输出提供清晰的示例和问题案例。我们将需要与数组项的时间关联,例如付款到期日。如果所有人的付款到期日都一样,那就更好了。我认为您要做的是在N个帐户之间进行最小数量的转账,以便满足他们的最小付款值。另外,知道我们的总收入是否总是大于需要支付的金额也将是一件好事。这正是我所寻找的。因为没有截止日期,所以这是有效的。我将尝试将类似的东西引入PHP。谢谢很高兴听到!我很感激绿色的勾号:)