获取 100 个回文数

获取 100 个回文数

我是脚本编写新手,我的任务是找到 100回文使用以下算法的数字:

  1. 获取两位随机数(大于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

据我了解,首先您需要收到两位数的号码

  • 大于 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

相关内容