编程语言
首页 > 编程语言> > python-从for循环返回false,否则在F#中继续

python-从for循环返回false,否则在F#中继续

作者:互联网

我正在出于专业目的学习F#.我知道Python / Django和C#/.NET Core.因此,我想将我用Python编写的一些代码转换为F#.我不确定要挂断电话或只是感到疲倦,以为我可以进行一些协作.我想继续做,但发现那不是一个选择.原始的python代码:

#!/Users/ryandines/.local/share/virtualenvs/netcoreapp2.0-5nmzfUwt/bin/python

NUMBER_OF_TESTS = input()

INT_MIN = -2**32

def can_represent_bst(pre):
    stack = []
    root = INT_MIN
    for value in pre:
        if value < root:
            return False
        while(stack and stack[-1] < value):
            root = stack.pop()

        stack.append(value)

    return True

for test in range(int(NUMBER_OF_TESTS)):
    node_count = int(input())
    nodes = list(map(int, input().split(' ')))
    print("NODES: " + str(nodes))
    if can_represent_bst(pre=nodes):
        print("YES")
    else:
        print("NO")

到目前为止,这就是我在F#中可以编译和运行的内容:

open System
let NumberOfTests = Console.ReadLine() |> int
let root = Int32.MinValue
let seq1 = seq { for i in 0 .. NumberOfTests-1 -> (i, i*i) }

let CanRepresentBST args =
    printfn "Passed args: %s" args
    let result = args.Split ' '
    let IntList = [for i in result -> i |> int32]
    for value in IntList do
        printfn "%d" value

[<EntryPoint>]
let main argv =
    printfn "Hello World from F#!"    
    printfn "Number of tests: %d" NumberOfTests   
    printfn "Int min value: %d" root

    for _ in seq1 do
        let NodeCount = Console.ReadLine()
        let Nodes = Console.ReadLine()
        printfn "NodeCount: %s" NodeCount      
        let _ = CanRepresentBST Nodes
        0 |> ignore

    0

未完成的部分是这样的:

    if value < root:
        return False
    while(stack and stack[-1] < value):
        root = stack.pop()

    stack.append(value)

可能要睡在上面,但是如果有人为我做些繁重的工作,我会很喜欢的,这样我醒来时就可以把它敲下来.

解决方法:

这是一个部分解决方案(因为它试图复制Python,而不是正确地使用F#):

open System
let NumberOfTests = Console.ReadLine() |> int

let rec getNewRoot value stack root =
    let mutable newRoot = root
    let mutable acc = stack
    while not (List.isEmpty acc) && (List.head acc) < value do
       newRoot <- List.head acc
       acc <- List.tail acc

    (newRoot, acc)

let CanRepresentBST args baseRoot =
    printfn "Passed args: %s" args
    let intList = args.Split ' ' |> Seq.map int |> Seq.toList
    let rec subfunc rem acc root =
        match rem with
        | [] -> true
        | r :: rs ->
            if r < root then
                false
            else
                let (newRoot, newAcc) = getNewRoot r acc root
                subfunc rs (r :: newAcc) newRoot

    subfunc intList [] baseRoot

printfn "Number of tests: %d" NumberOfTests
let root = Int32.MinValue
printfn "Int min value: %d" root

for _ in 1..NumberOfTests do
    let NodeCount = Console.ReadLine()
    let Nodes = Console.ReadLine()
    printfn "NodeCount: %s" NodeCount
    if CanRepresentBST Nodes root then
        printfn "YES"
    else
        printfn "NO"

我将其更改为fsx交互式脚本,以使其更易于测试(使用fsi filename.fsx运行),但我认为将其转换回编译程序应该很容易.

请注意,由于getNewRoot函数的作用,许多(如果不是大多数)F#爱好者都不喜欢该程序-那里的可变性太多了.

我将root的定义移至程序的末尾,并使CanRepresentBST将其作为参数,以使函数纯净-如果始终以MinValue作为root开头,则可以在CanRepresentBST的顶部声明它. CanRepresentBST现在使用一个辅助子功能(无用的子功能),该子功能获取输入列表其余部分的参数,累积的“堆栈”和当前根值.然后,它递归处理输入列表,像以前一样返回false,在列表末尾返回true,或者通过尾部递归调用正常处理它.

getNewRoot用于封装根值的更新和累积堆栈的调整.

请注意,这是Python的相当接近的翻译版本,这就是为什么它是如此膨胀的原因.最好是回到您尝试实现的本质,并使用F#中的功能编写新的东西.如果其他人想发布更好的版本,请这样做!

标签:f,python
来源: https://codeday.me/bug/20191108/2009181.html