当前位置: 首页 > 知识库问答 >
问题:

Perl简单FIFO计算

周良弼
2023-03-14

我似乎无法得到这个先进先出的计算工作:

@base = (10,15,6,2);
@subtr = (2,4,6,2,2,5,7,2);

my $count = 0;
my $result;
my $prev;
foreach my $base1 (@base) {
    foreach my $subt (@subtr) {
        if ($count == 0) {
            $result = $base1 - $subt;
            print "$base1 - $subt = $result \n";
            if ($result > 0) {
                print "Still1 POS $result\n";
                $count = 1;
            } else {
                print "NEG1 now $result\n";
                $count = 1;
                next;
            }
        } else {
            $prev = $result;
            $result = $result - $subt;
            print "$prev - $subt = $result \n";
            if ($result > 0) {
                print "Still2 POS $result\n";
                next;
            } else {
                print "NEG2 now $result\n";
                $count = 1;
                next;
            }
        }
    }
    $count = 0;
}

我需要它从第一个数组@base中减去@subtr中的数字,一旦subt元素的总和超过@base数组的第一个元素,它就可以使用超出的数量,并从@base的第二个元素中减去,等等,直到完成为止。完成后,我需要它告诉我@base中的哪个数组结束了,该数组元素还剩多少(应该是1),然后还剩多少(应该是3)。提前谢谢!保罗

共有2个答案

司寇经亘
2023-03-14

我不确定在耗尽@subtr之前耗尽@base时的预期值应该是多少。不过,对于你提供的信息,这似乎是可行的:

#!/usr/bin/perl
use strict;
use warnings;
use feature qw{ say };

my @base = (10, 15, 6, 2);
my @subtr = (2, 4, 6, 2, 2, 5, 7, 2);

my ($base_index, $subtr_index) = (0, 0);
my $subtracted = 0;

while ($base_index <= $#base) {
    while ($base[$base_index] - $subtracted > 0 && $subtr_index <= $#subtr) {
        say "Subtract at $subtr_index: $subtr[$subtr_index]";
        $subtracted += $subtr[$subtr_index++];
        say "Remains: ", $base[$base_index] - $subtracted;
    }
    last if $subtr_index > $#subtr;

    say "$base[$base_index] <= $subtracted";
    $subtracted -= $base[$base_index++];
    if ($base_index > $#base) {
        --$base_index;
        last
    }
    say "Carrying $subtracted to index $base_index ($base[$base_index])";
}
say "Finished at base index $base_index ($base[$base_index])";
say "Remaining value: ", $base[$base_index] - $subtracted;
my $remaining = $base[$base_index] - $subtracted;
$remaining += $_ for @base[$base_index + 1 .. $#base];
say "Remaining total: $remaining";

但我发现使用阵列的副本并删除其元素更容易理解:

#!/usr/bin/perl
use strict;
use warnings;
use feature qw{ say };

my @base = (10, 15, 6, 2);
my @subtr = (2, 4, 6, 2, 2, 5, 7, 2);

my @copy_base = @base;
my @copy_subtr = @subtr;

while (@copy_base && @copy_subtr) {
    if ($copy_base[0] > $copy_subtr[0]) {
        $copy_base[0] -= shift @copy_subtr;
    } else {
        my $first = shift @copy_base;
        $copy_base[0] += $first;
        if (1 == @copy_base && $copy_base[0] <= $copy_subtr[0]) {
            $copy_subtr[0] -= $copy_base[0];
            @copy_base = ();
        }
    }
    # say "b:@copy_base";
    # say "s:@copy_subtr";
    # say "";
}

if (@copy_base) {
    say "Ended at base index ", @base - @copy_base;
    say "Value left: ", $copy_base[0];

    my $total = 0;
    $total += $_ for @copy_base;
    say "Total: ", $total;
} else {
    say "Base exhausted";
}
if (@copy_subtr) {
    say "Ended at subtr index ", @subtr - @copy_subtr;
    my $remain = 0;
    $remain += $_ for @copy_subtr;
    say "$remain wasn't subtracted" if $remain;
} else {
    say "Subtr exhausted";
}
党星鹏
2023-03-14
use warnings;
use strict;
use feature 'say';
use List::Util 1.33 qw(sum any);  # 'any' was in List::MoreUtils pre-1.33

my @base = (10,15,6,2);
my @subt = (2,4,6,2,2,5,7,2);  # SUBTract from @base in a particular way ("FIFO")

# For testing other cases:
#my @subt = (2,4,6,2,2,5,7,2,5,5);  # @base runs out
#my @subt = (2,4,36,20);            # large @subt values, @base runs out
#my @subt = (2,4,21,2);             # large @subt values, @base remains
#my @subt = (2,4,6,2,2,5,7,2,3);    # @base runs out, @subt runs out

say "base: @base (total: ", sum(@base), ")";
say "sub:  @subt (total: ", sum (@subt), ")\n" if @subt;

my ($base_idx, $carryover) = (0, 0);

BASE_ELEM:
for my $bi (0..$#base) {
    $base[$bi] -= $carryover;

    # If still negative move to next @base element, to use carry-over on it
    if ($base[$bi] <= 0) {
        $carryover = abs($base[$bi]);
        say "\t\@base element #", $bi+1, " value $base[$bi] (-> 0); ",
            "carry over $carryover.";
        $base[$bi] = 0;
        next BASE_ELEM;
    }

    # Subtract @subt elements until they're all gone or $base[$bi] < 0
    1 while @subt and ($base[$bi] -= shift @subt) > 0;

    # Either @base element got negative, or we ran out of @subt elements
    if ($base[$bi] <= 0) {
        $carryover = abs($base[$bi]);
        say "\@base element #", $bi+1, " emptied. carry-over: $carryover. ",
            "Stayed with \@sub: @subt";
        $base[$bi] = 0;
    }
    elsif (not @subt) {  # we're done
        $base_idx = $bi;
        say "\@base element #", $bi+1, " emptied. carry-over: $carryover. ",
            "Stayed with ", scalar @subt, " \@subt elements";
        last BASE_ELEM;
    }
}
my $total_base_value = sum @base;

say "\nStayed with base: @base";

if (any { $_ > 0 } @base) {  # some base elements remained
    say "Stopped at \@base element index $base_idx (element number ",
        $base_idx+1, "), with value $base[$base_idx]";
}
else {
    if ($carryover) {
        say "Last carry-over: $carryover. Put it back at front of \@subt";
        unshift @subt, $carryover;
    }
    if (@subt) { say "Remained with \@subt elements: @subt" }
    else       { say "Used all \@subt to deplete all \@base" }
}

say "Total remaining: $total_base_value";

印刷品

base: 10 15 6 2 (total: 33)
sub:  2 4 6 2 2 5 7 2 (total: 30)

@base element #1 emptied. carry-over: 2. Stayed with @sub: 2 2 5 7 2
@base element #2 emptied. carry-over: 3. Stayed with @sub: 2
@base element #3 emptied. carry-over: 3. Stayed with 0 @subt elements

Stayed with base: 0 0 1 2
Stopped at @base element index 2 (element number 3), with value 1
Total remaining: 3

(没有诊断打印的版本见末尾)

还有其他可能的情况,由注释掉的不同@subt输入指示

>

所有的@base都被驱动为零,@subt完全耗尽!这个阴谋可以通过输入来实现,使得@base@subt加起来是相同的(最后注释掉@subt输入)

一些@subt元素足够大,足以使@base元素负,以至于有足够的结转来耗尽下一个元素,等等。这在第一个if测试中处理,如果仍然有额外的负值(要结转),我们直接跳到下一个@base元素,以便它可以在上面使用,等等

一张便条。@subt元素总是先从前面移除(通过shift),然后从@base元素中减去。如果这使得@base元素为负值,则负值用于结转,并应用于下一个@base元素。

但是,如果这最终使最后一个@base元素变成负数,那么额外的(负数)金额将被视为留在该@subt元素中;它被放回@subt的前面(unshift-ed)。

示例:我们在@base的最后一个元素中剩下5(让我们想象一下,其中有一些钱),从中减去@subt的元素是7。然后,@base的元素变成零,@subt的元素保持在2

该代码也适用于空的@subt

循环中无需额外打印,便于查看

use warnings;
use strict;
use feature 'say';
use List::Util 1.33 qw(sum any);  # 'any' was in List::MoreUtils pre-1.33

my @base = (10,15,6,2);
my @subt = (2,4,6,2,2,5,7,2);
# For testing other cases:
#my @subt = (2,4,6,2,2,5,7,2,5,5);  # @base runs out
#my @subt = (2,4,36,20);            # large @subt values, @base runs out
#my @subt = (2,4,21,2);             # large @subt values, @base remains
#my @subt = (2,4,6,2,2,5,7,2,3);    # @base runs out, @subt runs out
say "base: @base (total: ", sum(@base), ")";
say "sub:  @subt (total: ", sum (@subt), ")\n" if @subt;

my ($base_idx, $carryover) = (0, 0);

for my $bi (0..$#base) {
    $base[$bi] -= $carryover;

    # If still negative move to next @base element, to use carry-over on it
    if ($base[$bi] <= 0) {
        $carryover = abs($base[$bi]);
        $base[$bi] = 0;
        next;
    }

    # Subtract @subt elements until they're all gone or $base[$bi] < 0
    1 while @subt and ($base[$bi] -= shift @subt) > 0;

    # Either @base element got negative, or we ran out of @subt elements
    if ($base[$bi] <= 0) {
        $carryover = abs($base[$bi]);
        $base[$bi] = 0;
    }
    elsif (not @subt) {  # we're done
        $base_idx = $bi;
        last;
    }
}
my $total_base_value = sum @base;

say "Stayed with base: @base";

if (any { $_ > 0 } @base) {  # some base elements remained
    say "Stopped at \@base element index $base_idx (element number ",
        $base_idx+1, "), with value $base[$base_idx]";
}
else {
    unshift @subt, $carryover  if $carryover;

    if (@subt) { say "Remained with \@subt elements: @subt" }
    else      { say "Used all \@subt to deplete all \@base" }
}

say "Total remaining: $total_base_value";
 类似资料:
  • 主要内容:FIFO 原理,FIFO 设计,实例,实例,实例,实例,实例FIFO(First In First Out)是异步数据传输时经常使用的存储器。该存储器的特点是数据先进先出(后进后出)。其实,多位宽数据的异步传输问题,无论是从快时钟到慢时钟域,还是从慢时钟到快时钟域,都可以使用 FIFO 处理。 FIFO 原理 工作流程 复位之后,在写时钟和状态信号的控制下,数据写入 FIFO 中。RAM 的写地址从 0 开始,每写一次数据写地址指针加一,指向下一个存储单元

  • 主要内容:什么是 Perl?,Perl 优点,Perl 缺点Perl,一种功能丰富的计算机程序语言,运行在超过100种计算机平台上,适用广泛,从大型机到便携设备,从快速原型创建到大规模可扩展开发。 Perl 语言的应用范围很广,除CGI以外,Perl被用于图形编程、系统管理、网络编程、金融、生物以及其他领域。由于其灵活性,Perl被称为脚本语言中的瑞士军刀。 什么是 Perl? Perl是由Larry Wall设计的,并由他不断更新和维护的编程语言。 Pe

  • Perl,一种功能丰富的计算机程序语言,运行在超过100种计算机平台上,适用广泛,从大型机到便携设备,从快速原型创建到大规模可扩展开发。 Perl 语言的应用范围很广,除CGI以外,Perl被用于图形编程、系统管理、网络编程、金融、生物以及其他领域。由于其灵活性,Perl被称为脚本语言中的瑞士军刀。 什么是 Perl? Perl是由Larry Wall设计的,并由他不断更新和维护的编程语言。 Pe

  • 问题内容: 首先,这不是一个作业问题。我正在练习有关Java的知识。我想一个很好的方法是编写一个没有帮助的简单程序。不幸的是,我的编译器告诉我我不知道如何解决的错误。在不更改大量逻辑和代码的情况下,有人可以指出我的一些错误在哪里吗?谢谢 问题答案: 这会工作

  • 本文向大家介绍JS简单计算器实例,包括了JS简单计算器实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JS简单计算器的实现方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的javascript程序设计有所帮助。

  • 本文向大家介绍js实现简单计算器,包括了js实现简单计算器的使用技巧和注意事项,需要的朋友参考一下 参考部分资料,编写一个简单的计算器案例,虽然完成了正常需求,但是也有不满之处,待后续实力提升后再来补充,先把不足之处列出:   1:本来打算只要打开页面,计算器的输入框会显示一个默认为0的状态,但是在输入框加入默认显示为0的时候,选择数据输入时,该0会显示输入数字的前面,例如”0123“,由于能力有