私はスクリプトに初めて触れ、私の使命は100を見つけることです。回門次のアルゴリズムを使用する数値:
- 2つの乱数を取得します(10より大きい)。
- リバース番号
- 数字とその逆数を加える
- 合意結果が回文の場合は印刷してください。それ以外の場合は、ステップ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