我是脚本编写新手,我的任务是找到 100回文使用以下算法的数字:
- 获取两位随机数(大于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
据我了解,首先您需要收到两位数的号码
- 大于 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
是解析可能或可能不全部串在一起的短选项 - 因此它成为循环字符串中每个字节的便捷工具。
我不太喜欢shell$RAND
的函数bash
,但它可能比我的函数更保守,我的rand()
函数只是在后台运行一个无操作任务,并将其失效的 PID 分配给存储在其第一个参数中的任何 varname 。我承认,相当便宜。
该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
那里可能有一些骗子——显然,这种情况确实发生了。不多。我不知道这对您来说是否有问题,但这只是一个如何完成的示例。
最后一点 - 运行它dash
比在 中快得多bash
;尽管差异似乎只有一秒钟左右。任何状况之下,如果你这样做使用dash
你需要将rev()
set -- "$1"
行更改为set -- "${1#?}".
我刚刚意识到有一个两位数的要求 - 尽管我怀疑这个特定规则是为了防止作业变得太难。不管怎样,只获取字符串的子集是很容易做到的。事实上,这就是我r=
在以下情况下所做的:
r="${2#"${2%%[1-9]*}"}"
...它总是分配r
一个不以零开头的值。
rand()
这是始终为 分配两位数的版本$1
:
rand() { : & set -- "$1" "$!" "$(($!%100))"
: "$(($1=($3>10?$3:${#2}$3)))"
}
当然,您可以将相同的逻辑应用于bash
's 。$RAND
三元$((var=(value)?(assign if true):(assign if false)))"
运算符几乎适用于任何整数集。这里我要么给它分配 100 的模(基本上是一个百分位数)如果该值大于十,则我将其指定为两位数中的第二位,其中第一个是 中的数字计数$!
。
按照这种方式运行,其结果就不那么令人兴奋了:
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