bash-shell 的一个排列脚本-递归 (permutation)

bash-shell 的一个排列脚本-递归 (permutation)

#!/bin/bash

intswitch()
{
#echo "********"
#echo $1
#echo $2
#echo "********"
local a=${p[$1]}
p[$1]=${p[$2]}
p[$2]=$a
}

[ $# -eq 0 ] && exit 0
declare -a p
p=($(echo "$*"))

count=0

echo "---------------------------"
echo -n "pai lie ( "
for (( i=0; i<${#p
  • }; i++ ))
    do
    echo -n "${p[$i]} "
    done
    echo ")"
    echo "---------------------------"

    pailie()
    {
        if [ ${#p
    • } -eq $(($1+1)) ] ; then
              local i=0 #very important to declare to local
              for (( i=0; i<${#p
    • }; i++ ))
              do
                  echo -n "${p} "
              done
              echo
      #      count=$(($count+1))
      #      let "count+=1"
              return
          fi
          local j=0 #very important to declare to local
          for ((j=$1; j<${#p
    • };j++ ))
          do
              intswitch $j $1
              pailie $(($1+1))
              intswitch $j $1
          done
      }

      pailie 0

      echo "---------------------------"
      echo "total count $count"
      echo "---------------------------"
      exit 1



      //效果如下
      [email="Administrator@smallheart"]Administrator@smallheart[/email] ~/shellprg
      $ ./pailie.txt a b c
      ---------------------------
      pai lie ( a b c )
      ---------------------------
      a b c
      a c b
      b a c
      b c a
      c b a
      c a b
      ---------------------------
      total count 0
      ---------------------------

      大家可以把数据结构的程序改写成shell脚本,一起来学shell编程      
  • 来个简单的:
    引用:
    -(guest@mac:tty1)-(bash)-
    [244 0] % cat permutation-1.sh
    #! /bin/bash

    function perm()
    {
        local n=$#
        if [ $n = 1 ]; then
            echo "$1"
            return
        fi

        local i first lines line
        for ((i = 0; i < n; i++)); do
            first=$1
            shift
            lines=$(perm "$@")
            while read line; do
                echo "$first $line"
            done <<< "$lines"
            set -- "$@" "$first"
        done
    }

    perm "$@"
    -(guest@mac:tty1)-(bash)-
    [244 0] % ./permutation-1.sh 1 2 3 4
    1 2 3 4
    1 2 4 3
    1 3 4 2
    1 3 2 4
    1 4 2 3
    1 4 3 2
    2 3 4 1
    2 3 1 4
    2 4 1 3
    2 4 3 1
    2 1 3 4
    2 1 4 3
    3 4 1 2
    3 4 2 1
    3 1 2 4
    3 1 4 2
    3 2 4 1
    3 2 1 4
    4 1 2 3
    4 1 3 2
    4 2 3 1
    4 2 1 3
    4 3 1 2
    4 3 2 1
    -(guest@mac:tty1)-(bash)-
    [244 0] %


          
    虽然简洁一些,效率却低了许多       
    看了dearvoid 的脚本之后,发现

    intswitch $j $1
    pailie $(($1+1))
    intswitch $j $1

    中第二行intswitch $j $1是多此一举啊,      
    约瑟夫环
    [CODE]

    #!/bin/bash
    function random()
    {
    local m
    declare -i m
    m=0
    until [ $m -gt 0 ]
    do
      let m="$RANDOM%100"
    done
    return $m  
    }
    echo -n "please input a number(<=20):"
    declare -i n
    read n
    if [ $n -gt 0 ] && [ $n -lt 21 ]
    then
    echo "nice input n="$n
    echo "begin generate radom cipher:"
    else
    echo "invalid value, bye"
    exit 1
    fi
    #create the array
    #varname[_[0-9]+]+ means an array
    i=1
    declare -i m
    echo "number,cipher"
    while [ $i -le $n ]
    do
    eval a_"$i"_1=$i
    random
    eval a_"$i"_2=$?
    m=$i+1
    eval a_"$i"_3=a_$m
    eval echo "\$a_"$i"_1,\$a_"$i"_2"
    let i+=1
    done
    eval a_"$n"_3="a_1"
    declare -i num
    num=$n # num for the total number in the a list
    m=1 # m for index of output list
    #n for the begin number
    echo -n "please enter the begin number(<=100):"
    read n
    if [ $n -gt 0 ] && [ $n -lt 101 ]
    then
    echo "nice input n="$n
    else
    echo "invalid value, bye"
    exit 2
    fi
    p=a_1
    q=a_$num
    #function get one out
    function johnsiph ()
    {
            declare -i k
            while [ $num -gt 0 ]
            do
    let k=$(((n-1)%num))
    # echo $k
    i=0
    while [ $i -lt $k ]
    do
      q=$p
      eval p=\$"$p"_3
    #  echo $p,$q
      let i+=1
    done
    eval "$q"_3=\$"$p"_3
    eval b_"$m"_1=\$"$p"_1
    eval b_"$m"_2=\$"$p"_2
    # eval echo \$b_"$m"_1,\$b_"$m"_2
    eval let n=\$"$p"_2
    let m+=1
    eval p=\$"$p"_3
    let num-=1
            done
    }
    johnsiph
    echo "the order to kick out is "
    i=1
    until [ $m -eq $i ]
    do
    eval "echo -n \$b_"$i"_1\"  \""
    let i+=1
    done
    echo ""
    [/CODE]      
    计算表达式
    [CODE]
    #!/bin/bash
    expr=""
    if [ $# -eq 0 ]
    then
    echo "enter an experation,blank line to end input"
    while [ true ]
    do
    read t
    if [ -z $t ] ; then
    break
    else
    expr="$expr$t"
    fi
    done
    else
    expr=$1
    fi
    echo "caculating $expr"
    declare -i top
    top=0 #top used as a point to top of the stack
    o=""
    o2=""
    function get_operator()
    {
    if [ $# -eq 0 ] ; then { echo "!error invoke"; return 1 }; fi
    declare -i oi
    oi=$1
    o2=$2
    [ $oi -eq 0 ] && oi=1
    until [ $oi -eq 0 ]
    do
    o=`echo $o2|sed -e '1!d;s/^[0-9]*\([*+-/()]\)\(.*\)/\1/g;t;d'`
    o2=`echo $o2|sed -e '1!d;s/^[0-9]*\([*+-/()]\)\(.*\)/\2/g;t;d'`
    let oi-=1
    done
    }
    function popup()
    {
    o=`echo $1|sed -e '1!d;s/\(.*\)\([*+-/()]\)$/\2/g;t;d'`
    o2=`echo $1|sed -e '1!d;s/\(.*\)\([*+-/()]\)$/\1/g;t;d'`
    [ -z "$o2" ] && {
    o=${1##*[*+-/()]}
    o2=`echo $1|sed -e '1!d;s/\(.*[*+-/()]\)\(.*\)/\1/g;t;d'`
    temp=`echo $o2|sed -e '1!d;s/\(.*\)\([*+-/()]\)$/\2/g;t;d'`
    [ "$temp" = "-" ] && {
    temp=`echo $o2|sed -e '1!d;s/\(.*\)\([*+-/(]\{2\}\)$/\1/g;t;d'`
    [ "$o2" = "-" ] || [ ! -z "$temp" ]&&{
    o=-$o
    o2=`echo $o2|sed -e '1!d;s/\(.*\)\([*+-/()]\)$/\1/g;t;d'`
    }
    }
    }
    }
    function get_top_num()
    {
    o=`echo $1|sed -e '1!d;s/\(^[0-9]*\)\(.*\)/\1/g;t;d'`
    o2=`echo $1|sed -e '1!d;s/\(^[0-9]*\)\(.*\)/\2/g;t;d'`
    }
    function compare_operator()
    {
    [ -z "$1" ] && return 1
    for a in '+*' '+/' '-*' '-/' '+(' '-(' '*(' '/(' '(-' '(+' '(*' '(/'
    do
    [ $a = "$1$2" ] && return 1
    done
    return 0
    }
    ERROR_INTERNAL=1
    ERROR_EXPERATION=2
    function print_error()
    {
    case $1 in
    $ERROR_INTERNAL) echo "undetermined internal error .";;
    $ERROR_EXPERATION) echo "error experation .";;
    esac
    }
    stackstr=""
    while [ true ]
    do
    while [ true ]
    do
    ch=`expr substr $expr 1 1`
    [ $ch = "(" ] && {
    stackstr="$stackstr"\(
    expr=${expr#(}
    } || break
    done #remove the available "("
    get_top_num $expr
    [ -z $o ] && {
    get_operator 1 $expr
    expr=$o2
    [ $o = '-' ] && {
    get_top_num $expr
    o=-$o
    } || {
    print_error ERROR_EXPERATION
    exit ERROR_EXPERATION
    }
    }
    num2=$o
    get_operator 1 $expr
    oper2=$o
    expr=$o2
    #check the stack to see if we can perform a operator
    popup $stackstr
    oper1=$o
    [ "$oper1" = "(" ] && [ "$oper2" = ")" ] && {
    stackstr=$o2
    expr=$num2$expr
    continue
    }
    compare_operator "$oper1" "$oper2"
    if [ $? -eq 1 ]
    then
    stackstr=$stackstr$num2$oper2
    else
    stackstr=$o2
    popup $stackstr
    num1=$o
    stackstr=$o2
    expr=$(($num1$oper1$num2))$oper2$expr
    [ -z $oper2 ] && [ -z $stackstr ] && break
    fi
    done
    echo "the result is "$expr


    [/CODE]

    初学shell,这里用sed做字符的截取,好象很慢,有更简单的方法吧?:confused:      
    BEAR UP!!!      
    if condition is

    list all permutation of a string in fixed length

    ex.

    list.sh [a-z] 5

    will list length=5's  all permutation list

    ??