【问题标题】:Recursive calls in bash (catalan-numbers)bash 中的递归调用(加泰罗尼亚语数字)
【发布时间】:2017-02-10 06:43:55
【问题描述】:

我正在尝试创建一个程序,列出低于或等于 bash 脚本中的参数的所有加泰罗尼亚语数字。这是我目前拥有的,但它给了我一个stackoverflow错误(我相信错误必须在for循环中,但我不知道为什么)。我用java制作了这个程序,它可以工作,所以我认为它一定是一些语法错误?

#!/usr/bin/env bash
pcat=0

Cat() {

res=0

    if [ $1 -le 1 ]
    then
        echo 1
        return 1
    fi

    for ((i=0; i<$1; i++))
    do
        var1=$(($1-($i+1)))
        call1=$(Cat $i)
        call2=$(Cat $var1)

        res=$(( res+call1+call2 ))
    done

echo ${res}
return res

}


while [ $pcat -lt $1 ]
do
    Cat $pcat

    pcat=$((pcat+1))
done

【问题讨论】:

  • Bash 变量是全局的,除非你明确地将它们设为本地。编写递归函数时必须注意这一点。此外,shell 中的 return 不返回值;它指示调用是否应该被视为成功(return 0)或失败(任何小的正整数)。

标签: bash shell unix recursion arguments


【解决方案1】:

return res所在行不正确,return一般只能处理数字和小于128的数字。

假设您的意思是return $res,脚本将运行。

我设法让程序使用与您的代码类似的代码:

#!/bin/bash
catalan() {
    local n=$1
    #echo "called with $n" >&2

    if (( n <= 1 )); then
        res=1
    else
        res=0
        for ((i=0; i<n; i++))
        do
            var1=$(( n-i-1 ))
            call1=$(catalan $i)
            call2=$(catalan $var1)
            res=$(( res+call1*call2 ));
            #echo ":$i:$var1: result Call1:$call1: and Call2:$call2: $res" >&2
        done
    fi
    #echo "result is ${res}" >&2
    echo "$res"
}

n=$1
until  (( pcat > n ))
do     catalan "$((pcat++))"
done


echo "all was done"

还有第二个问题,Call1 和 Call2 的值需要相乘,而不是相加。将res+call1+call2 更改为:

res=$(( res+call1*call2 ))

但是生成的代码非常慢。仅计算第十 (10) 个加泰罗尼亚数字,代码就需要 16 秒。


一个将值保存在单个数组中的全新程序:catarray

这样:

#!/bin/bash

# some initial values to jump start the code:
catarray=( 1 1 2 5 )

#############################################################################
catalan(){
    #echo "making call for $1" >&2
    local n=$1
    # ${#catarray[@]} is the count of values in catarray (last index + 1).
    # if the number n to be found is not yet in the array of values of
    # catarray then we need to calculate it. Else, we just print the value.
    if (( n >= ${#catarray[@]} )); then
        #echo "$n is bigger than ${#catarray[@]}" >&2
        # this is a new number, lets loop up till we
        # fill the array just up to this value
        for (( i=${#catarray[@]};i<=n;i++)); do
        #echo "fill index $i in array" >&2
        # calculate the sum of all terms for catalan of $n.
            for(( j=0;j<i;j++ )); do
                (( catarray[i] += catarray[j] * catarray[i-j-1] ))
                #echo "done math in $i for $j with ${catarray[j]} *
                #echo "* ${catarray[i-j-1]} = ${catarray[i]}"
            done
        done
    fi
    # After making the math or else we just print the known value.
    #printf 'result of catalan number is %s\n' "${catarray[n]}"
}
#############################################################################
catalan "$1"

printf '%s, ' "${catarray[@]}"; echo

Wich 将在 4 毫秒内执行第十 (10) 个加泰罗尼亚语数字。

包含很多回声以“了解”程序的工作原理。您可以取消引用它们。

虽然有一个限制,bash 中的数字应该适合 64 位(对于 64 位计算机)或小于 (2^63-1)。这使得最大的加泰罗尼亚数字可能成为第 35 个。

$ catalan 35
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900,  
2674440, 9694845, 35357670, 129644790, 477638700, 1767263190,  
6564120420, 24466267020, 91482563640, 343059613650, 1289904147324,  
4861946401452, 18367353072152, 69533550916004, 263747951750360,  
1002242216651368, 3814986502092304, 14544636039226909,  
55534064877048198, 212336130412243110, 812944042149730764,  
3116285494907301262

但只需约 20 毫秒即可完成。

【讨论】:

  • 哦,谢谢,我知道这是一些愚蠢的语法错误,我花了几个小时编辑它,因为我只习惯了 java 和 c++...它现在给了我正确的输出,但正如你所说,它不是出于某种原因,正确的数字。
  • @RasmusMichelsen 我已经编辑了我的答案以构建一个计算加泰罗尼亚数字的解决方案。请检查它。
  • @Sorantar 非常感谢第一个代码可以正常工作(尽管你说的很慢)。我不太确定如何继续,尽管作为问题的一部分是创建一个程序,其中参数是加泰罗尼亚数字的“最大允许”大小,但如果我把它放在直到语句中,我认为它会更慢因为它必须一直检查它?第二个例子也很棒,但是我忘了提到显然我们只能在我们的程序中存储最多一个加泰罗尼亚语数字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多