100回の回文を入手してください

100回の回文を入手してください

私はスクリプトに初めて触れ、私の使命は100を見つけることです。回門次のアルゴリズムを使用する数値:

  1. 2つの乱数を取得します(10より大きい)。
  2. リバース番号
  3. 数字とその逆数を加える
  4. 合意結果が回文の場合は印刷してください。それ以外の場合は、ステップ2に戻ります。

たとえば、

  • 開始数量:75
  • 裏面は57
  • 合計は 75+57 = 132 です。

132は回文番号ではないため、ステップ2に戻ります。

  • その反対は321です。
  • 132+321=363
  • 363は回文数です。標準出力で印刷してください!

そして、そのような数字が100個まで印刷されるまで続きます。


これが私が今まで持っているものです:

#! /bin/bash

CONT=0
while [ $CONT -lt 100 ] 
do
    NUM= $RANDOM
    while [ $SUM -ne $SUMINV ] 
    do

        echo $NUM > file.txt
        INV= rev file.txt
        SUM= `expr[ $NUM + $INV ]`
        echo $SUM > file2.txt
        SUMINV= rev file2.txt
        NUM= $SUM
    done
    echo $NUM
    CONT=`expr $CONT + 1`
done

このスクリプトの解決策と助けを探しています!

答え1

私が知るには、まず2桁の数字を受け取る必要があります。

  • 10より大きい 100より小さい
  • 10で割らない(20、30などではない)
  • 回門ではない(22、33などではありません)

だからあなたはそれを通して到達することができます

while :
do
  a=$[$RANDOM%10]
  b=$[$RANDOM%10]
  if [ $a -ne $b -a $a -ne 0 -a $b -ne 0 ]
  then
    NUM="$a$b"
    RNUM="$b$a"
    break
  fi
done

次に、数字の合計と反転を確認してください。

while :
do
  NUM=$[$NUM+$RNUM]
  RNUM=$(printf "%d" $NUM | rev)
  if [ $NUM -eq $RNUM ]
  then
    echo $NUM
    break
  fi
done

答え2

ソーススクリプトにはさまざまな構文エラーがあります。たとえばfoo= bar、 Bash では空白が重要です。あなたはする必要がありますfoo=bar。また、コマンドの出力を取得するにはこれを行うことはできず、foo=commandコマンドをバックティックで囲む必要がありますfoo=$(command)。または、より良い方法は次のとおりです。作業バージョンは次のとおりです。

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

## This array will hold the numbers we've seen
## uncomment this line for unique numbers
#declare -a seen;
while [ "$CONT" -lt 100 ] 
do
    ## Get a random number
    NUM=$RANDOM
    ## Make sure it is < 100
    let "NUM %= 100"
    ## Make sure the number is more than 10
    while [ "$NUM" -le 10 ]
    do
        NUM=$((NUM+1))
    done
    ## In case the addition made it longer than two digits
    NUM="${NUM:0:2}"
    ## Make sure the number does not end in 0
    ## If it does, we will get an error when
    ## attempting to add it. Bash doesn't
    ## like leading 0s. 
    [[ $NUM =~ 0$ ]] && let NUM++
    ## Sum the number and its reverse
    SUM=$((NUM+$(rev <<<$NUM)));

    ## Is this a palindrome?
    if [ "$SUM" = "$(rev <<<$SUM)" ]
    then
        ## You did not say if you wanted 100 different
        ## numbers. If so, uncomment these lines
        #let seen[$SUM]++
        ## If this number has not been seen before
        #if [ "${seen[$SUM]}" -eq 1 ]
        #   then
        ## print it
        echo $SUM
        ## increment the counter
        let CONT++
        #fi
    fi
done

スクリプトは数字をそのまま繰り返します。一意の番号を取得するには、スクリプトのコメントで説明されているように、この行のコメントを削除します。

答え3

これは面白いです。私はこの質問が好きです。タスクを実行するために次の関数を作成し、タスクが完了しました。

palindromes() (
rev()   while getopts : o "-$1" ||
        ! r="${2#"${2%%[1-9]*}"}"
        do set -- "$1" "$OPTARG$2"
        done
rand()  { : & : "$(($1=$!))"; }

[ "$1" -gt 10 ] || exit
n=$1; set --
while OPTIND=1; rev "$n"
        case "$#.$n.$r"                              in
        (100.*) ! printf '%s\t%s\t%s\t%s\t%s\n' "$@" ;;
        (*.$r.$n) set -- "$@" "$n"; rand n           ;;
        (*)       n=$((${n#-}+${r%-}))               ;;
esac; do :; done
)

これに注目すべきいくつかの点があります。まず、getopts数字を反転させることです。の主な機能は、getoptsすべて一緒にリンクすることも、そうでない場合もある短いオプションを解析することです。したがって、文字列の各バイトを繰り返すのに便利なツールになります。

$RAND私はシェルの機能があまり好きではありませんが、バックグラウンドで何もしないで、最初の引数に格納されているvarnameに無効なPIDを割り当てるbash私の機能よりも保守的です。rand()認めます、かなり安いです。

このcase構造により、簡単なテストで課題のすべての側面を簡単に評価できます。私は以下が欲しい:

case "$#.$n.$r" in 
(100*) all done; printf %s\\n "$@";; 
(*$r.$n) palindrome; set -- "$@" "$n";;
(*) no luck; $n+$r; go again;;
esac

最初はこれのために多くの困難を経験しました。最初に私は次のようなことをしていました。

(*$r.$n) set -- ...; n=$((n+1))

それは悪いアイデア。ランアウェイ加算は、単に数字を数えるだけで、回文を見つける可能性を排除するのに十分な数字をすぐに増やします。めちゃくちゃになりましたが、date +%S別のプロセスを実行したい場合は、PIDを使用する方が良いと思いました。この場合、プロセスは何もしないかもしれません。それにもかかわらず、PID範囲はほぼ毎回暴走要因を制御するのに十分小さいです。

たとえば、今実行して結果を貼り付けます。

palindromes 76

出力

484     29292   49294   69296   89298
215512  50605   90609   446644  886688
123321  52625   92629   468864  663787366
134431  54645   94649   881585188       7667585634365857667
145541  23432   43434   63436   83438
147741  24442   44444   64446   84448
158851  25452   45454   65456   85458
169961  13231   46464   66466   86468
49985258994     27472   47474   67476   87478
14355341        28482   48484   68486   88488
395593  29492   49494   69496   89498
219912  121121  11244211        441144  881188
125521  165561  15522551        463364  7365409856589045637
136631  211112  17858768886785871       485584  893974888888479398
147741  23632   43634   63636   83638
149941  24642   44644   64646   84648
523325  25652   45654   65656   85658
567765  13331   46664   66666   86668
2358532 27672   47674   67676   87678
2236322 28682   48684   68686   88688

おそらく詐欺師がいるでしょう。明らかにそのようなことが起こります。あまり。これがあなたにとって問題になるかどうかはわかりませんが、これはそれがどのように達成できるかを示す例に過ぎません。

最後の注意 - 違いは1秒ほどであるように見えますが、それを実行することがdashで実行するよりもはるかに高速です。bashいずれにせよ、そうすれば使用するには、行を次に変更する必要がdashあります。rev() set -- "$1"set -- "${1#?}".

私はちょうど2桁の要件があることに気づきました。たとえ、この特定の規則は、課題が難しくなるのを防ぐためのものだと思います。とにかく、文字列のサブセットだけを取得するのは簡単です。実際、これはr=次の状況で私がしたことです。

r="${2#"${2%%[1-9]*}"}"

r...常に0で始まらない値を割り当てます。

rand()常に2桁の数字を割り当てるバージョンは次のとおりです$1

rand() { : & set -- "$1" "$!" "$(($!%100))"
         : "$(($1=($3>10?$3:${#2}$3)))"
}

もちろん、bash's'にも同じロジックを適用できます。$RAND$((var=(value)?(assign if true):(assign if false)))"項演算子は、ほぼすべての整数セットに対して機能します。ここではモジュロ100を割り当てます。(基本的に百分位数)値が10より大きい場合は、2桁の2桁目を指定します。ここで、最初の桁はcountの桁数です$!

このように実行すると、結果はあまり興味深くなりません。

333     66      484     1111    4884
77      88      99      121     121
363     484     77      4884    44044
88      99      121     121     363
484     1111    4884    88      8813200023188
99      121     121     363     484
1111    4884    44044   8813200023188   99
44      55      66      77      44
99      121     121     363     484
424     11      33      44      55
66      77      88      99      121
22      33      22      55      66
77      88      99      121     121
33      44      55      33      77
88      99      121     121     363
44      55      66      77      44
99      121     121     363     484
55      66      77      88      99
55      121     363     484     1111
66      77      88      99      121

関連情報