当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 解决另一个 PowerShell 数学挑战

作者:精品下载站 日期:2024-12-14 08:02:17 浏览:13 分类:玩电脑

解决另一个 PowerShell 数学挑战


上个月,Iron Scripter 主席发布了一个“有趣的”PowerShell 脚本挑战。实际上,有一些与数学相关的挑战。与所有这些挑战一样,您用来解决挑战的技术和概念比结果本身更重要。以下是我解决这些问题的方法。

问题#1

第一个挑战是取一个数字,例如 2568,并获得各个整数的总和。

2+5+6+8

答案是 21。您可能可以想出几种方法将字符串拆分为单独的元素。我决定使用正则表达式。

[int]$i = 12931

#define a regex pattern to match a single digit
[regex]$rx="\d{1}"

每个正则表达式匹配对象值将是单独的数字。我可以轻松地将值通过管道传递给 Measure-Object 以获得总和。

#get all matches and add them up
$measure = $rx.Matches($i) | Measure-Object -Property Value -Sum

#write the sum to the pipeline
$measure.sum

这很容易变成一个函数。

Function Get-NumberSum {

    [cmdletbinding()]
    [OutputType([Int])]
    Param(
        [Parameter(Position = 0, Mandatory, HelpMessage = "Enter an integer value like 1234")]
        [Alias("i")]
        [int]$Value
    )

    #define a regex pattern to match a single digit
    [regex]$rx = "\d{1}"

    #get all matches and add them up
    $measure = $rx.Matches($Value) | Measure-Object -Property Value -Sum

    #write the sum to the pipeline
    $measure.sum
}

该函数需要一个整数。但正则表达式模式适用于任何包含数字的内容。

($rx.matches("A12B9C31D") | measure value -sum).sum

这给了我相同的答案 16。挑战有一些奖励元素,所以这里是该函数的稍微更高级的版本。

Function Get-NumberSum {
    [cmdletbinding()]
    [OutputType([Int])]
    [OutputType("NumberSum")]
    [Alias("gns")]
    Param(
         [ValidateScript({
            if ($_.ToString().Length -le 10) {
                $True
            }
            else {
                Throw "Specify a value of 10 digits or less."
                $False
            }
        })]
        [int64]$Value,
        [switch]$Quiet
    )

    Write-Verbose "Processing $Value"
    #define a regex pattern to match a single digit
    [regex]$rx = "\d{1}"

    $values = $rx.Matches($Value).Value
    Write-Verbose ($values -join "+")

    $measure =  $Values | Measure-Object -Sum
    Write-Verbose "Equals $($measure.sum)"

    if ($Quiet) {
        $measure.sum
    }
    else {
        [pscustomobject]@{
            PSTypeName = "NumberSum"
            Value = $Value
            Elements = $values
            Sum = $measure.sum
        }
    }
}

此版本将默认创建自定义对象。 -Quiet 参数仅显示结果。可以通过多种方式处理参数验证。如果我将 $Value 的类型保留为 [int],那么数字无论如何都不能超过 10 位。但我想尝试一些不同的东西。因此,我使用 ValidateScript 属性来显示自定义错误消息。这是使用函数别名的样子。

[玩转系统] 解决另一个 PowerShell 数学挑战

好吧,我承认使用正则表达式对于这个挑战来说有点大材小用,但它很有趣。这是一个更简单的方法。

($i -split "" | measure-object -sum).sum

问题#2

第二个问题更具挑战性。给定一个数字数组,所有可能的唯一和是多少。

$a = 2,5,6

2
5
6
2+5 = 7
2+5+6 = 13
2+6 = 8
5+6 = 11

此问题需要从数组中获取数字之和,并考虑所有可能的组合。诀窍是递归调用该函数,减少组合测试的数量。

function Get-ReductiveSum {
    param([array]$Numbers,[int]$Index=0,[int]$Sum=0)

    if ($numbers.count -eq $index) {
        $sum
    }
    else {
        Get-ReductiveSum $numbers -index ($index+1) -sum ($sum+$numbers[$index])
        Get-ReductiveSum $numbers ($index+1) $sum
    }
}

我可以像这样使用这个功能。

[玩转系统] 解决另一个 PowerShell 数学挑战

为了满足挑战目标并使其易于使用,我创建了这个“父”功能。

Function Get-PossibleSum {
    [cmdletbinding()]
    Param(
        [Parameter(Position = 0, Mandatory)]
        [ValidateRange(1,9)]
        [int[]]$Values
    )

    #nested function
    function Get-ReductiveSum {
        param([array]$Numbers,[int]$Index=0,[int]$Sum=0)

        Write-Verbose "Get-ReductiveSum -Numbers $($numbers -join ',') -index $index -sum $sum"
        if ($numbers.count -eq $index) {
            Write-Verbose "Found sum $sum"
            $sum
        }
        else {
            Write-Verbose "Reducing numbers to $($numbers -join ',')"
            Write-Verbose "Setting index to $($index+1)"
            Write-Verbose "Get-ReductiveSum $($sum+$numbers[$index])"
            Get-ReductiveSum $numbers -index ($index+1) -sum ($sum+$numbers[$index])
            Write-Verbose "Get-ReductiveSum $sum"
            Get-ReductiveSum $numbers ($index+1) $sum
        }
    }

    Write-Verbose "Using values $($values -join ',')"
    Write-Verbose "Verifying unique values"
    $values = $values | Get-Unique
    if ($values.count -gt 9) {
        #this should probably never happen
        Write-Warning "You specified $($values.count) values. Only using the first 9"
        $Values = $Values[0..8]
    }
    Write-Verbose "Calculating possible unique sums for $($values -join ',')"
    $result  =  Get-ReductiveSum $Values | Where-Object {$_ -gt 0}
    Write-Verbose "Found $($result.count) non-zero sums"
    $result | Sort-Object
}

[玩转系统] 解决另一个 PowerShell 数学挑战

我将让您尝试代码以查看详细输出。

让你的大脑以 PowerShell 的方式思考可能很困难。这就是为什么这些挑战如此有帮助。您越能在头脑中遵循 PowerShell 管道,它就越容易使用。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯